1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/content/media/directshow/AudioSinkFilter.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,289 @@ 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 "SampleSink.h" 1.11 +#include "AudioSinkFilter.h" 1.12 +#include "AudioSinkInputPin.h" 1.13 +#include "VideoUtils.h" 1.14 +#include "prlog.h" 1.15 + 1.16 + 1.17 +#include <initguid.h> 1.18 +#include <wmsdkidl.h> 1.19 + 1.20 +#define DELETE_RESET(p) { delete (p) ; (p) = nullptr ;} 1.21 + 1.22 +DEFINE_GUID(CLSID_MozAudioSinkFilter, 0x1872d8c8, 0xea8d, 0x4c34, 0xae, 0x96, 0x69, 0xde, 1.23 + 0xf1, 0x33, 0x7b, 0x33); 1.24 + 1.25 +using namespace mozilla::media; 1.26 + 1.27 +namespace mozilla { 1.28 + 1.29 +#ifdef PR_LOGGING 1.30 +PRLogModuleInfo* GetDirectShowLog(); 1.31 +#define LOG(...) PR_LOG(GetDirectShowLog(), PR_LOG_DEBUG, (__VA_ARGS__)) 1.32 +#else 1.33 +#define LOG(...) 1.34 +#endif 1.35 + 1.36 +AudioSinkFilter::AudioSinkFilter(const wchar_t* aObjectName, HRESULT* aOutResult) 1.37 + : BaseFilter(aObjectName, CLSID_MozAudioSinkFilter), 1.38 + mFilterCritSec("AudioSinkFilter::mFilterCritSec") 1.39 +{ 1.40 + (*aOutResult) = S_OK; 1.41 + mInputPin = new AudioSinkInputPin(L"AudioSinkInputPin", 1.42 + this, 1.43 + &mFilterCritSec, 1.44 + aOutResult); 1.45 +} 1.46 + 1.47 +AudioSinkFilter::~AudioSinkFilter() 1.48 +{ 1.49 +} 1.50 + 1.51 +int 1.52 +AudioSinkFilter::GetPinCount() 1.53 +{ 1.54 + return 1; 1.55 +} 1.56 + 1.57 +BasePin* 1.58 +AudioSinkFilter::GetPin(int aIndex) 1.59 +{ 1.60 + CriticalSectionAutoEnter lockFilter(mFilterCritSec); 1.61 + return (aIndex == 0) ? static_cast<BasePin*>(mInputPin) : nullptr; 1.62 +} 1.63 + 1.64 +HRESULT 1.65 +AudioSinkFilter::Pause() 1.66 +{ 1.67 + CriticalSectionAutoEnter lockFilter(mFilterCritSec); 1.68 + if (mState == State_Stopped) { 1.69 + // Change the state, THEN activate the input pin. 1.70 + mState = State_Paused; 1.71 + if (mInputPin && mInputPin->IsConnected()) { 1.72 + mInputPin->Active(); 1.73 + } 1.74 + } else if (mState == State_Running) { 1.75 + mState = State_Paused; 1.76 + } 1.77 + return S_OK; 1.78 +} 1.79 + 1.80 +HRESULT 1.81 +AudioSinkFilter::Stop() 1.82 +{ 1.83 + CriticalSectionAutoEnter lockFilter(mFilterCritSec); 1.84 + mState = State_Stopped; 1.85 + if (mInputPin) { 1.86 + mInputPin->Inactive(); 1.87 + } 1.88 + 1.89 + GetSampleSink()->Flush(); 1.90 + 1.91 + return S_OK; 1.92 +} 1.93 + 1.94 +HRESULT 1.95 +AudioSinkFilter::Run(REFERENCE_TIME tStart) 1.96 +{ 1.97 + LOG("AudioSinkFilter::Run(%lld) [%4.2lf]", 1.98 + RefTimeToUsecs(tStart), 1.99 + double(RefTimeToUsecs(tStart)) / USECS_PER_S); 1.100 + return media::BaseFilter::Run(tStart); 1.101 +} 1.102 + 1.103 +HRESULT 1.104 +AudioSinkFilter::GetClassID( OUT CLSID * pCLSID ) 1.105 +{ 1.106 + (* pCLSID) = CLSID_MozAudioSinkFilter; 1.107 + return S_OK; 1.108 +} 1.109 + 1.110 +HRESULT 1.111 +AudioSinkFilter::QueryInterface(REFIID aIId, void **aInterface) 1.112 +{ 1.113 + if (aIId == IID_IMediaSeeking) { 1.114 + *aInterface = static_cast<IMediaSeeking*>(this); 1.115 + AddRef(); 1.116 + return S_OK; 1.117 + } 1.118 + return mozilla::media::BaseFilter::QueryInterface(aIId, aInterface); 1.119 +} 1.120 + 1.121 +ULONG 1.122 +AudioSinkFilter::AddRef() 1.123 +{ 1.124 + return ::InterlockedIncrement(&mRefCnt); 1.125 +} 1.126 + 1.127 +ULONG 1.128 +AudioSinkFilter::Release() 1.129 +{ 1.130 + unsigned long newRefCnt = ::InterlockedDecrement(&mRefCnt); 1.131 + if (!newRefCnt) { 1.132 + delete this; 1.133 + } 1.134 + return newRefCnt; 1.135 +} 1.136 + 1.137 +SampleSink* 1.138 +AudioSinkFilter::GetSampleSink() 1.139 +{ 1.140 + return mInputPin->GetSampleSink(); 1.141 +} 1.142 + 1.143 + 1.144 +// IMediaSeeking implementation. 1.145 +// 1.146 +// Calls to IMediaSeeking are forwarded to the output pin that the 1.147 +// AudioSinkInputPin is connected to, i.e. upstream towards the parser and 1.148 +// source filters, which actually implement seeking. 1.149 +#define ENSURE_CONNECTED_PIN_SEEKING \ 1.150 + if (!mInputPin) { \ 1.151 + return E_NOTIMPL; \ 1.152 + } \ 1.153 + RefPtr<IMediaSeeking> pinSeeking = mInputPin->GetConnectedPinSeeking(); \ 1.154 + if (!pinSeeking) { \ 1.155 + return E_NOTIMPL; \ 1.156 + } 1.157 + 1.158 +HRESULT 1.159 +AudioSinkFilter::GetCapabilities(DWORD* aCapabilities) 1.160 +{ 1.161 + ENSURE_CONNECTED_PIN_SEEKING 1.162 + return pinSeeking->GetCapabilities(aCapabilities); 1.163 +} 1.164 + 1.165 +HRESULT 1.166 +AudioSinkFilter::CheckCapabilities(DWORD* aCapabilities) 1.167 +{ 1.168 + ENSURE_CONNECTED_PIN_SEEKING 1.169 + return pinSeeking->CheckCapabilities(aCapabilities); 1.170 +} 1.171 + 1.172 +HRESULT 1.173 +AudioSinkFilter::IsFormatSupported(const GUID* aFormat) 1.174 +{ 1.175 + ENSURE_CONNECTED_PIN_SEEKING 1.176 + return pinSeeking->IsFormatSupported(aFormat); 1.177 +} 1.178 + 1.179 +HRESULT 1.180 +AudioSinkFilter::QueryPreferredFormat(GUID* aFormat) 1.181 +{ 1.182 + ENSURE_CONNECTED_PIN_SEEKING 1.183 + return pinSeeking->QueryPreferredFormat(aFormat); 1.184 +} 1.185 + 1.186 +HRESULT 1.187 +AudioSinkFilter::GetTimeFormat(GUID* aFormat) 1.188 +{ 1.189 + ENSURE_CONNECTED_PIN_SEEKING 1.190 + return pinSeeking->GetTimeFormat(aFormat); 1.191 +} 1.192 + 1.193 +HRESULT 1.194 +AudioSinkFilter::IsUsingTimeFormat(const GUID* aFormat) 1.195 +{ 1.196 + ENSURE_CONNECTED_PIN_SEEKING 1.197 + return pinSeeking->IsUsingTimeFormat(aFormat); 1.198 +} 1.199 + 1.200 +HRESULT 1.201 +AudioSinkFilter::SetTimeFormat(const GUID* aFormat) 1.202 +{ 1.203 + ENSURE_CONNECTED_PIN_SEEKING 1.204 + return pinSeeking->SetTimeFormat(aFormat); 1.205 +} 1.206 + 1.207 +HRESULT 1.208 +AudioSinkFilter::GetDuration(LONGLONG* aDuration) 1.209 +{ 1.210 + ENSURE_CONNECTED_PIN_SEEKING 1.211 + return pinSeeking->GetDuration(aDuration); 1.212 +} 1.213 + 1.214 +HRESULT 1.215 +AudioSinkFilter::GetStopPosition(LONGLONG* aStop) 1.216 +{ 1.217 + ENSURE_CONNECTED_PIN_SEEKING 1.218 + return pinSeeking->GetStopPosition(aStop); 1.219 +} 1.220 + 1.221 +HRESULT 1.222 +AudioSinkFilter::GetCurrentPosition(LONGLONG* aCurrent) 1.223 +{ 1.224 + ENSURE_CONNECTED_PIN_SEEKING 1.225 + return pinSeeking->GetCurrentPosition(aCurrent); 1.226 +} 1.227 + 1.228 +HRESULT 1.229 +AudioSinkFilter::ConvertTimeFormat(LONGLONG* aTarget, 1.230 + const GUID* aTargetFormat, 1.231 + LONGLONG aSource, 1.232 + const GUID* aSourceFormat) 1.233 +{ 1.234 + ENSURE_CONNECTED_PIN_SEEKING 1.235 + return pinSeeking->ConvertTimeFormat(aTarget, 1.236 + aTargetFormat, 1.237 + aSource, 1.238 + aSourceFormat); 1.239 +} 1.240 + 1.241 +HRESULT 1.242 +AudioSinkFilter::SetPositions(LONGLONG* aCurrent, 1.243 + DWORD aCurrentFlags, 1.244 + LONGLONG* aStop, 1.245 + DWORD aStopFlags) 1.246 +{ 1.247 + ENSURE_CONNECTED_PIN_SEEKING 1.248 + return pinSeeking->SetPositions(aCurrent, 1.249 + aCurrentFlags, 1.250 + aStop, 1.251 + aStopFlags); 1.252 +} 1.253 + 1.254 +HRESULT 1.255 +AudioSinkFilter::GetPositions(LONGLONG* aCurrent, 1.256 + LONGLONG* aStop) 1.257 +{ 1.258 + ENSURE_CONNECTED_PIN_SEEKING 1.259 + return pinSeeking->GetPositions(aCurrent, aStop); 1.260 +} 1.261 + 1.262 +HRESULT 1.263 +AudioSinkFilter::GetAvailable(LONGLONG* aEarliest, 1.264 + LONGLONG* aLatest) 1.265 +{ 1.266 + ENSURE_CONNECTED_PIN_SEEKING 1.267 + return pinSeeking->GetAvailable(aEarliest, aLatest); 1.268 +} 1.269 + 1.270 +HRESULT 1.271 +AudioSinkFilter::SetRate(double aRate) 1.272 +{ 1.273 + ENSURE_CONNECTED_PIN_SEEKING 1.274 + return pinSeeking->SetRate(aRate); 1.275 +} 1.276 + 1.277 +HRESULT 1.278 +AudioSinkFilter::GetRate(double* aRate) 1.279 +{ 1.280 + ENSURE_CONNECTED_PIN_SEEKING 1.281 + return pinSeeking->GetRate(aRate); 1.282 +} 1.283 + 1.284 +HRESULT 1.285 +AudioSinkFilter::GetPreroll(LONGLONG* aPreroll) 1.286 +{ 1.287 + ENSURE_CONNECTED_PIN_SEEKING 1.288 + return pinSeeking->GetPreroll(aPreroll); 1.289 +} 1.290 + 1.291 +} // namespace mozilla 1.292 +