diff options
Diffstat (limited to 'dom/media/directshow/AudioSinkFilter.cpp')
-rw-r--r-- | dom/media/directshow/AudioSinkFilter.cpp | 285 |
1 files changed, 285 insertions, 0 deletions
diff --git a/dom/media/directshow/AudioSinkFilter.cpp b/dom/media/directshow/AudioSinkFilter.cpp new file mode 100644 index 000000000..9f23c0e00 --- /dev/null +++ b/dom/media/directshow/AudioSinkFilter.cpp @@ -0,0 +1,285 @@ +/* -*- 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 <initguid.h> +#include <wmsdkidl.h> + +#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<BasePin*>(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<IMediaSeeking*>(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<IMediaSeeking> 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 + |