1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/content/media/directshow/AudioSinkInputPin.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,199 @@ 1.4 +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 1.5 +/* vim:set ts=2 sw=2 sts=2 et cindent: */ 1.6 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.7 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.8 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.9 + 1.10 +#include "AudioSinkInputPin.h" 1.11 +#include "AudioSinkFilter.h" 1.12 +#include "SampleSink.h" 1.13 +#include "prlog.h" 1.14 + 1.15 +#include <wmsdkidl.h> 1.16 + 1.17 +using namespace mozilla::media; 1.18 + 1.19 +namespace mozilla { 1.20 + 1.21 +#ifdef PR_LOGGING 1.22 +PRLogModuleInfo* GetDirectShowLog(); 1.23 +#define LOG(...) PR_LOG(GetDirectShowLog(), PR_LOG_DEBUG, (__VA_ARGS__)) 1.24 +#else 1.25 +#define LOG(...) 1.26 +#endif 1.27 + 1.28 +AudioSinkInputPin::AudioSinkInputPin(wchar_t* aObjectName, 1.29 + AudioSinkFilter* aFilter, 1.30 + mozilla::CriticalSection* aLock, 1.31 + HRESULT* aOutResult) 1.32 + : BaseInputPin(aObjectName, aFilter, aLock, aOutResult, aObjectName), 1.33 + mSegmentStartTime(0) 1.34 +{ 1.35 + MOZ_COUNT_CTOR(AudioSinkInputPin); 1.36 + mSampleSink = new SampleSink(); 1.37 +} 1.38 + 1.39 +AudioSinkInputPin::~AudioSinkInputPin() 1.40 +{ 1.41 + MOZ_COUNT_DTOR(AudioSinkInputPin); 1.42 +} 1.43 + 1.44 +HRESULT 1.45 +AudioSinkInputPin::GetMediaType(int aPosition, MediaType* aOutMediaType) 1.46 +{ 1.47 + NS_ENSURE_TRUE(aPosition >= 0, E_INVALIDARG); 1.48 + NS_ENSURE_TRUE(aOutMediaType, E_POINTER); 1.49 + 1.50 + if (aPosition > 0) { 1.51 + return S_FALSE; 1.52 + } 1.53 + 1.54 + // Note: We set output as PCM, as IEEE_FLOAT only works when using the 1.55 + // MP3 decoder as an MFT, and we can't do that while using DirectShow. 1.56 + aOutMediaType->SetType(&MEDIATYPE_Audio); 1.57 + aOutMediaType->SetSubtype(&MEDIASUBTYPE_PCM); 1.58 + aOutMediaType->SetType(&FORMAT_WaveFormatEx); 1.59 + aOutMediaType->SetTemporalCompression(FALSE); 1.60 + 1.61 + return S_OK; 1.62 +} 1.63 + 1.64 +HRESULT 1.65 +AudioSinkInputPin::CheckMediaType(const MediaType* aMediaType) 1.66 +{ 1.67 + if (!aMediaType) { 1.68 + return E_INVALIDARG; 1.69 + } 1.70 + 1.71 + GUID majorType = *aMediaType->Type(); 1.72 + if (majorType != MEDIATYPE_Audio && majorType != WMMEDIATYPE_Audio) { 1.73 + return E_INVALIDARG; 1.74 + } 1.75 + 1.76 + if (*aMediaType->Subtype() != MEDIASUBTYPE_PCM) { 1.77 + return E_INVALIDARG; 1.78 + } 1.79 + 1.80 + if (*aMediaType->FormatType() != FORMAT_WaveFormatEx) { 1.81 + return E_INVALIDARG; 1.82 + } 1.83 + 1.84 + // We accept the media type, stash its layout format! 1.85 + WAVEFORMATEX* wfx = (WAVEFORMATEX*)(aMediaType->pbFormat); 1.86 + GetSampleSink()->SetAudioFormat(wfx); 1.87 + 1.88 + return S_OK; 1.89 +} 1.90 + 1.91 +AudioSinkFilter* 1.92 +AudioSinkInputPin::GetAudioSinkFilter() 1.93 +{ 1.94 + return reinterpret_cast<AudioSinkFilter*>(mFilter); 1.95 +} 1.96 + 1.97 +SampleSink* 1.98 +AudioSinkInputPin::GetSampleSink() 1.99 +{ 1.100 + return mSampleSink; 1.101 +} 1.102 + 1.103 +HRESULT 1.104 +AudioSinkInputPin::SetAbsoluteMediaTime(IMediaSample* aSample) 1.105 +{ 1.106 + HRESULT hr; 1.107 + REFERENCE_TIME start = 0, end = 0; 1.108 + hr = aSample->GetTime(&start, &end); 1.109 + NS_ENSURE_TRUE(SUCCEEDED(hr), E_FAIL); 1.110 + { 1.111 + CriticalSectionAutoEnter lock(*mLock); 1.112 + start += mSegmentStartTime; 1.113 + end += mSegmentStartTime; 1.114 + } 1.115 + hr = aSample->SetMediaTime(&start, &end); 1.116 + NS_ENSURE_TRUE(SUCCEEDED(hr), E_FAIL); 1.117 + return S_OK; 1.118 +} 1.119 + 1.120 +HRESULT 1.121 +AudioSinkInputPin::Receive(IMediaSample* aSample ) 1.122 +{ 1.123 + HRESULT hr; 1.124 + NS_ENSURE_TRUE(aSample, E_POINTER); 1.125 + 1.126 + hr = BaseInputPin::Receive(aSample); 1.127 + if (SUCCEEDED(hr) && hr != S_FALSE) { // S_FALSE == flushing 1.128 + // Set the timestamp of the sample after being adjusted for 1.129 + // seeking/segments in the "media time" attribute. When we seek, 1.130 + // DirectShow starts a new "segment", and starts labeling samples 1.131 + // from time=0 again, so we need to correct for this to get the 1.132 + // actual timestamps after seeking. 1.133 + hr = SetAbsoluteMediaTime(aSample); 1.134 + NS_ENSURE_TRUE(SUCCEEDED(hr), hr); 1.135 + hr = GetSampleSink()->Receive(aSample); 1.136 + NS_ENSURE_TRUE(SUCCEEDED(hr), hr); 1.137 + } 1.138 + return S_OK; 1.139 +} 1.140 + 1.141 +TemporaryRef<IMediaSeeking> 1.142 +AudioSinkInputPin::GetConnectedPinSeeking() 1.143 +{ 1.144 + RefPtr<IPin> peer = GetConnected(); 1.145 + if (!peer) 1.146 + return nullptr; 1.147 + RefPtr<IMediaSeeking> seeking; 1.148 + peer->QueryInterface(static_cast<IMediaSeeking**>(byRef(seeking))); 1.149 + return seeking; 1.150 +} 1.151 + 1.152 +HRESULT 1.153 +AudioSinkInputPin::BeginFlush() 1.154 +{ 1.155 + HRESULT hr = media::BaseInputPin::BeginFlush(); 1.156 + NS_ENSURE_TRUE(SUCCEEDED(hr), hr); 1.157 + 1.158 + GetSampleSink()->Flush(); 1.159 + 1.160 + return S_OK; 1.161 +} 1.162 + 1.163 +HRESULT 1.164 +AudioSinkInputPin::EndFlush() 1.165 +{ 1.166 + HRESULT hr = media::BaseInputPin::EndFlush(); 1.167 + NS_ENSURE_TRUE(SUCCEEDED(hr), hr); 1.168 + 1.169 + // Reset the EOS flag, so that if we're called after a seek we still work. 1.170 + GetSampleSink()->Reset(); 1.171 + 1.172 + return S_OK; 1.173 +} 1.174 + 1.175 +HRESULT 1.176 +AudioSinkInputPin::EndOfStream(void) 1.177 +{ 1.178 + HRESULT hr = media::BaseInputPin::EndOfStream(); 1.179 + if (FAILED(hr) || hr == S_FALSE) { 1.180 + // Pin is stil flushing. 1.181 + return hr; 1.182 + } 1.183 + GetSampleSink()->SetEOS(); 1.184 + 1.185 + return S_OK; 1.186 +} 1.187 + 1.188 + 1.189 +HRESULT 1.190 +AudioSinkInputPin::NewSegment(REFERENCE_TIME tStart, 1.191 + REFERENCE_TIME tStop, 1.192 + double dRate) 1.193 +{ 1.194 + CriticalSectionAutoEnter lock(*mLock); 1.195 + // Record the start time of the new segment, so that we can store the 1.196 + // correct absolute timestamp in the "media time" each incoming sample. 1.197 + mSegmentStartTime = tStart; 1.198 + return S_OK; 1.199 +} 1.200 + 1.201 +} // namespace mozilla 1.202 +