/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* vim:set ts=2 sw=2 sts=2 et cindent: */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "SampleSink.h" #include "AudioSinkFilter.h" #include "AudioSinkInputPin.h" #include "VideoUtils.h" #include "mozilla/Logging.h" #include #include #define DELETE_RESET(p) { delete (p) ; (p) = nullptr ;} DEFINE_GUID(CLSID_MozAudioSinkFilter, 0x1872d8c8, 0xea8d, 0x4c34, 0xae, 0x96, 0x69, 0xde, 0xf1, 0x33, 0x7b, 0x33); using namespace mozilla::media; namespace mozilla { static LazyLogModule gDirectShowLog("DirectShowDecoder"); #define LOG(...) MOZ_LOG(gDirectShowLog, mozilla::LogLevel::Debug, (__VA_ARGS__)) AudioSinkFilter::AudioSinkFilter(const wchar_t* aObjectName, HRESULT* aOutResult) : BaseFilter(aObjectName, CLSID_MozAudioSinkFilter), mFilterCritSec("AudioSinkFilter::mFilterCritSec") { (*aOutResult) = S_OK; mInputPin = new AudioSinkInputPin(L"AudioSinkInputPin", this, &mFilterCritSec, aOutResult); } AudioSinkFilter::~AudioSinkFilter() { } int AudioSinkFilter::GetPinCount() { return 1; } BasePin* AudioSinkFilter::GetPin(int aIndex) { CriticalSectionAutoEnter lockFilter(mFilterCritSec); return (aIndex == 0) ? static_cast(mInputPin) : nullptr; } HRESULT AudioSinkFilter::Pause() { CriticalSectionAutoEnter lockFilter(mFilterCritSec); if (mState == State_Stopped) { // Change the state, THEN activate the input pin. mState = State_Paused; if (mInputPin && mInputPin->IsConnected()) { mInputPin->Active(); } } else if (mState == State_Running) { mState = State_Paused; } return S_OK; } HRESULT AudioSinkFilter::Stop() { CriticalSectionAutoEnter lockFilter(mFilterCritSec); mState = State_Stopped; if (mInputPin) { mInputPin->Inactive(); } GetSampleSink()->Flush(); return S_OK; } HRESULT AudioSinkFilter::Run(REFERENCE_TIME tStart) { LOG("AudioSinkFilter::Run(%lld) [%4.2lf]", RefTimeToUsecs(tStart), double(RefTimeToUsecs(tStart)) / USECS_PER_S); return media::BaseFilter::Run(tStart); } HRESULT AudioSinkFilter::GetClassID( OUT CLSID * pCLSID ) { (* pCLSID) = CLSID_MozAudioSinkFilter; return S_OK; } HRESULT AudioSinkFilter::QueryInterface(REFIID aIId, void **aInterface) { if (aIId == IID_IMediaSeeking) { *aInterface = static_cast(this); AddRef(); return S_OK; } return mozilla::media::BaseFilter::QueryInterface(aIId, aInterface); } ULONG AudioSinkFilter::AddRef() { return ::InterlockedIncrement(&mRefCnt); } ULONG AudioSinkFilter::Release() { unsigned long newRefCnt = ::InterlockedDecrement(&mRefCnt); if (!newRefCnt) { delete this; } return newRefCnt; } SampleSink* AudioSinkFilter::GetSampleSink() { return mInputPin->GetSampleSink(); } // IMediaSeeking implementation. // // Calls to IMediaSeeking are forwarded to the output pin that the // AudioSinkInputPin is connected to, i.e. upstream towards the parser and // source filters, which actually implement seeking. #define ENSURE_CONNECTED_PIN_SEEKING \ if (!mInputPin) { \ return E_NOTIMPL; \ } \ RefPtr pinSeeking = mInputPin->GetConnectedPinSeeking(); \ if (!pinSeeking) { \ return E_NOTIMPL; \ } HRESULT AudioSinkFilter::GetCapabilities(DWORD* aCapabilities) { ENSURE_CONNECTED_PIN_SEEKING return pinSeeking->GetCapabilities(aCapabilities); } HRESULT AudioSinkFilter::CheckCapabilities(DWORD* aCapabilities) { ENSURE_CONNECTED_PIN_SEEKING return pinSeeking->CheckCapabilities(aCapabilities); } HRESULT AudioSinkFilter::IsFormatSupported(const GUID* aFormat) { ENSURE_CONNECTED_PIN_SEEKING return pinSeeking->IsFormatSupported(aFormat); } HRESULT AudioSinkFilter::QueryPreferredFormat(GUID* aFormat) { ENSURE_CONNECTED_PIN_SEEKING return pinSeeking->QueryPreferredFormat(aFormat); } HRESULT AudioSinkFilter::GetTimeFormat(GUID* aFormat) { ENSURE_CONNECTED_PIN_SEEKING return pinSeeking->GetTimeFormat(aFormat); } HRESULT AudioSinkFilter::IsUsingTimeFormat(const GUID* aFormat) { ENSURE_CONNECTED_PIN_SEEKING return pinSeeking->IsUsingTimeFormat(aFormat); } HRESULT AudioSinkFilter::SetTimeFormat(const GUID* aFormat) { ENSURE_CONNECTED_PIN_SEEKING return pinSeeking->SetTimeFormat(aFormat); } HRESULT AudioSinkFilter::GetDuration(LONGLONG* aDuration) { ENSURE_CONNECTED_PIN_SEEKING return pinSeeking->GetDuration(aDuration); } HRESULT AudioSinkFilter::GetStopPosition(LONGLONG* aStop) { ENSURE_CONNECTED_PIN_SEEKING return pinSeeking->GetStopPosition(aStop); } HRESULT AudioSinkFilter::GetCurrentPosition(LONGLONG* aCurrent) { ENSURE_CONNECTED_PIN_SEEKING return pinSeeking->GetCurrentPosition(aCurrent); } HRESULT AudioSinkFilter::ConvertTimeFormat(LONGLONG* aTarget, const GUID* aTargetFormat, LONGLONG aSource, const GUID* aSourceFormat) { ENSURE_CONNECTED_PIN_SEEKING return pinSeeking->ConvertTimeFormat(aTarget, aTargetFormat, aSource, aSourceFormat); } HRESULT AudioSinkFilter::SetPositions(LONGLONG* aCurrent, DWORD aCurrentFlags, LONGLONG* aStop, DWORD aStopFlags) { ENSURE_CONNECTED_PIN_SEEKING return pinSeeking->SetPositions(aCurrent, aCurrentFlags, aStop, aStopFlags); } HRESULT AudioSinkFilter::GetPositions(LONGLONG* aCurrent, LONGLONG* aStop) { ENSURE_CONNECTED_PIN_SEEKING return pinSeeking->GetPositions(aCurrent, aStop); } HRESULT AudioSinkFilter::GetAvailable(LONGLONG* aEarliest, LONGLONG* aLatest) { ENSURE_CONNECTED_PIN_SEEKING return pinSeeking->GetAvailable(aEarliest, aLatest); } HRESULT AudioSinkFilter::SetRate(double aRate) { ENSURE_CONNECTED_PIN_SEEKING return pinSeeking->SetRate(aRate); } HRESULT AudioSinkFilter::GetRate(double* aRate) { ENSURE_CONNECTED_PIN_SEEKING return pinSeeking->GetRate(aRate); } HRESULT AudioSinkFilter::GetPreroll(LONGLONG* aPreroll) { ENSURE_CONNECTED_PIN_SEEKING return pinSeeking->GetPreroll(aPreroll); } } // namespace mozilla