Wed, 31 Dec 2014 06:55:46 +0100
Added tag TORBROWSER_REPLICA for changeset 6474c204b198
michael@0 | 1 | /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ |
michael@0 | 2 | /* vim:set ts=2 sw=2 sts=2 et cindent: */ |
michael@0 | 3 | /* This Source Code Form is subject to the terms of the Mozilla Public |
michael@0 | 4 | * License, v. 2.0. If a copy of the MPL was not distributed with this |
michael@0 | 5 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
michael@0 | 6 | |
michael@0 | 7 | #include "SampleSink.h" |
michael@0 | 8 | #include "AudioSinkFilter.h" |
michael@0 | 9 | #include "AudioSinkInputPin.h" |
michael@0 | 10 | #include "VideoUtils.h" |
michael@0 | 11 | #include "prlog.h" |
michael@0 | 12 | |
michael@0 | 13 | |
michael@0 | 14 | #include <initguid.h> |
michael@0 | 15 | #include <wmsdkidl.h> |
michael@0 | 16 | |
michael@0 | 17 | #define DELETE_RESET(p) { delete (p) ; (p) = nullptr ;} |
michael@0 | 18 | |
michael@0 | 19 | DEFINE_GUID(CLSID_MozAudioSinkFilter, 0x1872d8c8, 0xea8d, 0x4c34, 0xae, 0x96, 0x69, 0xde, |
michael@0 | 20 | 0xf1, 0x33, 0x7b, 0x33); |
michael@0 | 21 | |
michael@0 | 22 | using namespace mozilla::media; |
michael@0 | 23 | |
michael@0 | 24 | namespace mozilla { |
michael@0 | 25 | |
michael@0 | 26 | #ifdef PR_LOGGING |
michael@0 | 27 | PRLogModuleInfo* GetDirectShowLog(); |
michael@0 | 28 | #define LOG(...) PR_LOG(GetDirectShowLog(), PR_LOG_DEBUG, (__VA_ARGS__)) |
michael@0 | 29 | #else |
michael@0 | 30 | #define LOG(...) |
michael@0 | 31 | #endif |
michael@0 | 32 | |
michael@0 | 33 | AudioSinkFilter::AudioSinkFilter(const wchar_t* aObjectName, HRESULT* aOutResult) |
michael@0 | 34 | : BaseFilter(aObjectName, CLSID_MozAudioSinkFilter), |
michael@0 | 35 | mFilterCritSec("AudioSinkFilter::mFilterCritSec") |
michael@0 | 36 | { |
michael@0 | 37 | (*aOutResult) = S_OK; |
michael@0 | 38 | mInputPin = new AudioSinkInputPin(L"AudioSinkInputPin", |
michael@0 | 39 | this, |
michael@0 | 40 | &mFilterCritSec, |
michael@0 | 41 | aOutResult); |
michael@0 | 42 | } |
michael@0 | 43 | |
michael@0 | 44 | AudioSinkFilter::~AudioSinkFilter() |
michael@0 | 45 | { |
michael@0 | 46 | } |
michael@0 | 47 | |
michael@0 | 48 | int |
michael@0 | 49 | AudioSinkFilter::GetPinCount() |
michael@0 | 50 | { |
michael@0 | 51 | return 1; |
michael@0 | 52 | } |
michael@0 | 53 | |
michael@0 | 54 | BasePin* |
michael@0 | 55 | AudioSinkFilter::GetPin(int aIndex) |
michael@0 | 56 | { |
michael@0 | 57 | CriticalSectionAutoEnter lockFilter(mFilterCritSec); |
michael@0 | 58 | return (aIndex == 0) ? static_cast<BasePin*>(mInputPin) : nullptr; |
michael@0 | 59 | } |
michael@0 | 60 | |
michael@0 | 61 | HRESULT |
michael@0 | 62 | AudioSinkFilter::Pause() |
michael@0 | 63 | { |
michael@0 | 64 | CriticalSectionAutoEnter lockFilter(mFilterCritSec); |
michael@0 | 65 | if (mState == State_Stopped) { |
michael@0 | 66 | // Change the state, THEN activate the input pin. |
michael@0 | 67 | mState = State_Paused; |
michael@0 | 68 | if (mInputPin && mInputPin->IsConnected()) { |
michael@0 | 69 | mInputPin->Active(); |
michael@0 | 70 | } |
michael@0 | 71 | } else if (mState == State_Running) { |
michael@0 | 72 | mState = State_Paused; |
michael@0 | 73 | } |
michael@0 | 74 | return S_OK; |
michael@0 | 75 | } |
michael@0 | 76 | |
michael@0 | 77 | HRESULT |
michael@0 | 78 | AudioSinkFilter::Stop() |
michael@0 | 79 | { |
michael@0 | 80 | CriticalSectionAutoEnter lockFilter(mFilterCritSec); |
michael@0 | 81 | mState = State_Stopped; |
michael@0 | 82 | if (mInputPin) { |
michael@0 | 83 | mInputPin->Inactive(); |
michael@0 | 84 | } |
michael@0 | 85 | |
michael@0 | 86 | GetSampleSink()->Flush(); |
michael@0 | 87 | |
michael@0 | 88 | return S_OK; |
michael@0 | 89 | } |
michael@0 | 90 | |
michael@0 | 91 | HRESULT |
michael@0 | 92 | AudioSinkFilter::Run(REFERENCE_TIME tStart) |
michael@0 | 93 | { |
michael@0 | 94 | LOG("AudioSinkFilter::Run(%lld) [%4.2lf]", |
michael@0 | 95 | RefTimeToUsecs(tStart), |
michael@0 | 96 | double(RefTimeToUsecs(tStart)) / USECS_PER_S); |
michael@0 | 97 | return media::BaseFilter::Run(tStart); |
michael@0 | 98 | } |
michael@0 | 99 | |
michael@0 | 100 | HRESULT |
michael@0 | 101 | AudioSinkFilter::GetClassID( OUT CLSID * pCLSID ) |
michael@0 | 102 | { |
michael@0 | 103 | (* pCLSID) = CLSID_MozAudioSinkFilter; |
michael@0 | 104 | return S_OK; |
michael@0 | 105 | } |
michael@0 | 106 | |
michael@0 | 107 | HRESULT |
michael@0 | 108 | AudioSinkFilter::QueryInterface(REFIID aIId, void **aInterface) |
michael@0 | 109 | { |
michael@0 | 110 | if (aIId == IID_IMediaSeeking) { |
michael@0 | 111 | *aInterface = static_cast<IMediaSeeking*>(this); |
michael@0 | 112 | AddRef(); |
michael@0 | 113 | return S_OK; |
michael@0 | 114 | } |
michael@0 | 115 | return mozilla::media::BaseFilter::QueryInterface(aIId, aInterface); |
michael@0 | 116 | } |
michael@0 | 117 | |
michael@0 | 118 | ULONG |
michael@0 | 119 | AudioSinkFilter::AddRef() |
michael@0 | 120 | { |
michael@0 | 121 | return ::InterlockedIncrement(&mRefCnt); |
michael@0 | 122 | } |
michael@0 | 123 | |
michael@0 | 124 | ULONG |
michael@0 | 125 | AudioSinkFilter::Release() |
michael@0 | 126 | { |
michael@0 | 127 | unsigned long newRefCnt = ::InterlockedDecrement(&mRefCnt); |
michael@0 | 128 | if (!newRefCnt) { |
michael@0 | 129 | delete this; |
michael@0 | 130 | } |
michael@0 | 131 | return newRefCnt; |
michael@0 | 132 | } |
michael@0 | 133 | |
michael@0 | 134 | SampleSink* |
michael@0 | 135 | AudioSinkFilter::GetSampleSink() |
michael@0 | 136 | { |
michael@0 | 137 | return mInputPin->GetSampleSink(); |
michael@0 | 138 | } |
michael@0 | 139 | |
michael@0 | 140 | |
michael@0 | 141 | // IMediaSeeking implementation. |
michael@0 | 142 | // |
michael@0 | 143 | // Calls to IMediaSeeking are forwarded to the output pin that the |
michael@0 | 144 | // AudioSinkInputPin is connected to, i.e. upstream towards the parser and |
michael@0 | 145 | // source filters, which actually implement seeking. |
michael@0 | 146 | #define ENSURE_CONNECTED_PIN_SEEKING \ |
michael@0 | 147 | if (!mInputPin) { \ |
michael@0 | 148 | return E_NOTIMPL; \ |
michael@0 | 149 | } \ |
michael@0 | 150 | RefPtr<IMediaSeeking> pinSeeking = mInputPin->GetConnectedPinSeeking(); \ |
michael@0 | 151 | if (!pinSeeking) { \ |
michael@0 | 152 | return E_NOTIMPL; \ |
michael@0 | 153 | } |
michael@0 | 154 | |
michael@0 | 155 | HRESULT |
michael@0 | 156 | AudioSinkFilter::GetCapabilities(DWORD* aCapabilities) |
michael@0 | 157 | { |
michael@0 | 158 | ENSURE_CONNECTED_PIN_SEEKING |
michael@0 | 159 | return pinSeeking->GetCapabilities(aCapabilities); |
michael@0 | 160 | } |
michael@0 | 161 | |
michael@0 | 162 | HRESULT |
michael@0 | 163 | AudioSinkFilter::CheckCapabilities(DWORD* aCapabilities) |
michael@0 | 164 | { |
michael@0 | 165 | ENSURE_CONNECTED_PIN_SEEKING |
michael@0 | 166 | return pinSeeking->CheckCapabilities(aCapabilities); |
michael@0 | 167 | } |
michael@0 | 168 | |
michael@0 | 169 | HRESULT |
michael@0 | 170 | AudioSinkFilter::IsFormatSupported(const GUID* aFormat) |
michael@0 | 171 | { |
michael@0 | 172 | ENSURE_CONNECTED_PIN_SEEKING |
michael@0 | 173 | return pinSeeking->IsFormatSupported(aFormat); |
michael@0 | 174 | } |
michael@0 | 175 | |
michael@0 | 176 | HRESULT |
michael@0 | 177 | AudioSinkFilter::QueryPreferredFormat(GUID* aFormat) |
michael@0 | 178 | { |
michael@0 | 179 | ENSURE_CONNECTED_PIN_SEEKING |
michael@0 | 180 | return pinSeeking->QueryPreferredFormat(aFormat); |
michael@0 | 181 | } |
michael@0 | 182 | |
michael@0 | 183 | HRESULT |
michael@0 | 184 | AudioSinkFilter::GetTimeFormat(GUID* aFormat) |
michael@0 | 185 | { |
michael@0 | 186 | ENSURE_CONNECTED_PIN_SEEKING |
michael@0 | 187 | return pinSeeking->GetTimeFormat(aFormat); |
michael@0 | 188 | } |
michael@0 | 189 | |
michael@0 | 190 | HRESULT |
michael@0 | 191 | AudioSinkFilter::IsUsingTimeFormat(const GUID* aFormat) |
michael@0 | 192 | { |
michael@0 | 193 | ENSURE_CONNECTED_PIN_SEEKING |
michael@0 | 194 | return pinSeeking->IsUsingTimeFormat(aFormat); |
michael@0 | 195 | } |
michael@0 | 196 | |
michael@0 | 197 | HRESULT |
michael@0 | 198 | AudioSinkFilter::SetTimeFormat(const GUID* aFormat) |
michael@0 | 199 | { |
michael@0 | 200 | ENSURE_CONNECTED_PIN_SEEKING |
michael@0 | 201 | return pinSeeking->SetTimeFormat(aFormat); |
michael@0 | 202 | } |
michael@0 | 203 | |
michael@0 | 204 | HRESULT |
michael@0 | 205 | AudioSinkFilter::GetDuration(LONGLONG* aDuration) |
michael@0 | 206 | { |
michael@0 | 207 | ENSURE_CONNECTED_PIN_SEEKING |
michael@0 | 208 | return pinSeeking->GetDuration(aDuration); |
michael@0 | 209 | } |
michael@0 | 210 | |
michael@0 | 211 | HRESULT |
michael@0 | 212 | AudioSinkFilter::GetStopPosition(LONGLONG* aStop) |
michael@0 | 213 | { |
michael@0 | 214 | ENSURE_CONNECTED_PIN_SEEKING |
michael@0 | 215 | return pinSeeking->GetStopPosition(aStop); |
michael@0 | 216 | } |
michael@0 | 217 | |
michael@0 | 218 | HRESULT |
michael@0 | 219 | AudioSinkFilter::GetCurrentPosition(LONGLONG* aCurrent) |
michael@0 | 220 | { |
michael@0 | 221 | ENSURE_CONNECTED_PIN_SEEKING |
michael@0 | 222 | return pinSeeking->GetCurrentPosition(aCurrent); |
michael@0 | 223 | } |
michael@0 | 224 | |
michael@0 | 225 | HRESULT |
michael@0 | 226 | AudioSinkFilter::ConvertTimeFormat(LONGLONG* aTarget, |
michael@0 | 227 | const GUID* aTargetFormat, |
michael@0 | 228 | LONGLONG aSource, |
michael@0 | 229 | const GUID* aSourceFormat) |
michael@0 | 230 | { |
michael@0 | 231 | ENSURE_CONNECTED_PIN_SEEKING |
michael@0 | 232 | return pinSeeking->ConvertTimeFormat(aTarget, |
michael@0 | 233 | aTargetFormat, |
michael@0 | 234 | aSource, |
michael@0 | 235 | aSourceFormat); |
michael@0 | 236 | } |
michael@0 | 237 | |
michael@0 | 238 | HRESULT |
michael@0 | 239 | AudioSinkFilter::SetPositions(LONGLONG* aCurrent, |
michael@0 | 240 | DWORD aCurrentFlags, |
michael@0 | 241 | LONGLONG* aStop, |
michael@0 | 242 | DWORD aStopFlags) |
michael@0 | 243 | { |
michael@0 | 244 | ENSURE_CONNECTED_PIN_SEEKING |
michael@0 | 245 | return pinSeeking->SetPositions(aCurrent, |
michael@0 | 246 | aCurrentFlags, |
michael@0 | 247 | aStop, |
michael@0 | 248 | aStopFlags); |
michael@0 | 249 | } |
michael@0 | 250 | |
michael@0 | 251 | HRESULT |
michael@0 | 252 | AudioSinkFilter::GetPositions(LONGLONG* aCurrent, |
michael@0 | 253 | LONGLONG* aStop) |
michael@0 | 254 | { |
michael@0 | 255 | ENSURE_CONNECTED_PIN_SEEKING |
michael@0 | 256 | return pinSeeking->GetPositions(aCurrent, aStop); |
michael@0 | 257 | } |
michael@0 | 258 | |
michael@0 | 259 | HRESULT |
michael@0 | 260 | AudioSinkFilter::GetAvailable(LONGLONG* aEarliest, |
michael@0 | 261 | LONGLONG* aLatest) |
michael@0 | 262 | { |
michael@0 | 263 | ENSURE_CONNECTED_PIN_SEEKING |
michael@0 | 264 | return pinSeeking->GetAvailable(aEarliest, aLatest); |
michael@0 | 265 | } |
michael@0 | 266 | |
michael@0 | 267 | HRESULT |
michael@0 | 268 | AudioSinkFilter::SetRate(double aRate) |
michael@0 | 269 | { |
michael@0 | 270 | ENSURE_CONNECTED_PIN_SEEKING |
michael@0 | 271 | return pinSeeking->SetRate(aRate); |
michael@0 | 272 | } |
michael@0 | 273 | |
michael@0 | 274 | HRESULT |
michael@0 | 275 | AudioSinkFilter::GetRate(double* aRate) |
michael@0 | 276 | { |
michael@0 | 277 | ENSURE_CONNECTED_PIN_SEEKING |
michael@0 | 278 | return pinSeeking->GetRate(aRate); |
michael@0 | 279 | } |
michael@0 | 280 | |
michael@0 | 281 | HRESULT |
michael@0 | 282 | AudioSinkFilter::GetPreroll(LONGLONG* aPreroll) |
michael@0 | 283 | { |
michael@0 | 284 | ENSURE_CONNECTED_PIN_SEEKING |
michael@0 | 285 | return pinSeeking->GetPreroll(aPreroll); |
michael@0 | 286 | } |
michael@0 | 287 | |
michael@0 | 288 | } // namespace mozilla |
michael@0 | 289 |