diff --git a/README.md b/README.md index bce6376429..c9e0e61bc7 100644 --- a/README.md +++ b/README.md @@ -14,7 +14,7 @@ Some advantages over upstream, roytam1's Serpent, Eclipse Hydra and Firefox are: - Support for extensions in the Chrome and Edge Web Store (soon) - Support for extensions released for both Pale Moon, Basilisk and Firefox - WebExtensions support comparable to Firefox ESR 78 -- Literally being the fastest XUL browser (33.7 in Speedometer 2.1 compared to 22.4 in Pale Moon 34.2 AVX2) +- Literally being the fastest XUL browser (48.7 in Speedometer 2.1 compared to 22.4 in Pale Moon 34.2 AVX2) - Re-add support for iOS, Android, Windows 2000 and later, NetBSD (soon OpenBSD) ## Interested in running Dactyloidae in Win9x? diff --git a/build/moz.configure/windows.configure b/build/moz.configure/windows.configure index 4a28470d34..e2cb128265 100644 --- a/build/moz.configure/windows.configure +++ b/build/moz.configure/windows.configure @@ -84,7 +84,14 @@ def get_sdk_dirs(sdk, subdir): include_dirs['winv6.3'] = include_dirs['include'] del include_dirs['include'] - valid_versions = sorted(set(include_dirs) & set(lib_dirs), reverse=True) + def build_num(v): + parts = v.split('.') + try: + return int(parts[2]) if len(parts) >= 3 else 0 + except ValueError: + return 0 + valid_versions = sorted((v for v in set(include_dirs) & set(lib_dirs) + if build_num(v) <= 19041), reverse=True) if valid_versions: return namespace( path=sdk, @@ -136,6 +143,13 @@ def valid_windows_sdk_dir(compiler, windows_sdk_dir, target_version, 'WINDOWSSDKDIR (%s). Please verify it contains a valid and ' 'complete SDK installation.' % windows_sdk_dir_env) + def sdk_build(path): + parts = os.path.basename(path).split('.') + try: + return int(parts[2]) if len(parts) >= 3 else 0 + except ValueError: + return 0 + sdks = {k: v for k, v in sdks.items() if sdk_build(k) <= 19041} valid_sdks = sorted(sdks, key=lambda x: sdks[x][0], reverse=True) if valid_sdks: biggest_version, sdk = sdks[valid_sdks[0]] @@ -226,6 +240,7 @@ def valid_ucrt_sdk_dir(windows_sdk_dir, windows_sdk_dir_env): 'The SDK in WINDOWSSDKDIR (%s) does not contain the Universal ' 'CRT.' % windows_sdk_dir_env) + sdks = {k: v for k, v in sdks.items() if int(str(v[0]).split('.')[2]) <= 19041} valid_sdks = sorted(sdks, key=lambda x: sdks[x][0], reverse=True) if not valid_sdks: raise FatalCheckError('Cannot find the Universal CRT SDK. ' diff --git a/dom/media/DecoderTraits.cpp b/dom/media/DecoderTraits.cpp index 0795830528..891da0e488 100644 --- a/dom/media/DecoderTraits.cpp +++ b/dom/media/DecoderTraits.cpp @@ -34,11 +34,6 @@ #include "FlacDecoder.h" #include "FlacDemuxer.h" -#ifdef MOZ_DIRECTSHOW -#include "DirectShowDecoder.h" -#include "DirectShowReader.h" -#endif - #include "nsPluginHost.h" #include "MediaPrefs.h" @@ -143,14 +138,6 @@ IsFlacSupportedType(const nsACString& aType, return FlacDecoder::CanHandleMediaType(aType, aCodecs); } -#ifdef MOZ_DIRECTSHOW -static bool -IsDirectShowSupportedType(const nsACString& aType) -{ - return DirectShowDecoder::GetSupportedCodecs(aType, nullptr); -} -#endif - static CanPlayStatus CanHandleCodecsType(const MediaContentType& aType, @@ -210,11 +197,6 @@ CanHandleCodecsType(const MediaContentType& aType, if (IsFlacSupportedType(aType.GetMIMEType(), aType.GetCodecs())) { return CANPLAY_YES; } -#ifdef MOZ_DIRECTSHOW - if (IsDirectShowSupportedType(aType.GetMIMEType())) { - return CANPLAY_YES; - } -#endif if (!codecList) { return CANPLAY_MAYBE; } @@ -276,11 +258,6 @@ CanHandleMediaType(const MediaContentType& aType, if (IsFlacSupportedType(aType.GetMIMEType())) { return CANPLAY_MAYBE; } -#ifdef MOZ_DIRECTSHOW - if (IsDirectShowSupportedType(aType.GetMIMEType())) { - return CANPLAY_MAYBE; - } -#endif return CANPLAY_NO; } @@ -370,13 +347,6 @@ InstantiateDecoder(const nsACString& aType, return decoder.forget(); } -#ifdef MOZ_DIRECTSHOW - if (IsDirectShowSupportedType(aType)) { - decoder = new DirectShowDecoder(aOwner); - return decoder.forget(); - } -#endif - return nullptr; } @@ -423,11 +393,6 @@ MediaDecoderReader* DecoderTraits::CreateReader(const nsACString& aType, Abstrac decoderReader = new MediaFormatReader(aDecoder, new WebMDemuxer(aDecoder->GetResource())); } -#ifdef MOZ_DIRECTSHOW - else if (IsDirectShowSupportedType(aType)) { - decoderReader = new DirectShowReader(aDecoder); - } -#endif return decoderReader; } @@ -453,9 +418,6 @@ bool DecoderTraits::IsSupportedInVideoDocument(const nsACString& aType) IsAACSupportedType(aType) || IsWaveSupportedType(aType) || IsFlacSupportedType(aType) || -#ifdef MOZ_DIRECTSHOW - IsDirectShowSupportedType(aType) || -#endif false; } diff --git a/dom/media/directshow/AudioSinkFilter.cpp b/dom/media/directshow/AudioSinkFilter.cpp deleted file mode 100644 index 58a329338f..0000000000 --- a/dom/media/directshow/AudioSinkFilter.cpp +++ /dev/null @@ -1,290 +0,0 @@ -/* -*- 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(); -} - -const ::VIDEOINFOHEADER* -AudioSinkFilter::GetVideoInfo() const -{ - return mInputPin->GetVideoInfo(); -} - - -// 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 diff --git a/dom/media/directshow/AudioSinkFilter.h b/dom/media/directshow/AudioSinkFilter.h deleted file mode 100644 index 2170d45f00..0000000000 --- a/dom/media/directshow/AudioSinkFilter.h +++ /dev/null @@ -1,96 +0,0 @@ -/* -*- 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/. */ - -#if !defined(AudioSinkFilter_h_) -#define AudioSinkFilter_h_ - -#include "BaseFilter.h" -#include "DirectShowUtils.h" -#include "nsAutoPtr.h" -#include "mozilla/RefPtr.h" - -namespace mozilla { - -class AudioSinkInputPin; -class SampleSink; - -// Filter that acts as the end of the graph. Audio samples input into -// this filter block the calling thread, and the calling thread is -// unblocked when the decode thread extracts the sample. The samples -// input into this filter are stored in the SampleSink, where the blocking -// is implemented. The input pin owns the SampleSink. -class AudioSinkFilter: public mozilla::media::BaseFilter, - public IMediaSeeking -{ - -public: - AudioSinkFilter(const wchar_t* aObjectName, HRESULT* aOutResult); - virtual ~AudioSinkFilter(); - - // Gets the input pin's sample sink. - SampleSink* GetSampleSink(); - const ::VIDEOINFOHEADER* GetVideoInfo() const; - - // IUnknown implementation. - STDMETHODIMP QueryInterface(REFIID aIId, void **aInterface); - STDMETHODIMP_(ULONG) AddRef(); - STDMETHODIMP_(ULONG) Release(); - - // -------------------------------------------------------------------- - // CBaseFilter methods - int GetPinCount (); - mozilla::media::BasePin* GetPin ( IN int Index); - STDMETHODIMP Pause (); - STDMETHODIMP Stop (); - STDMETHODIMP GetClassID ( OUT CLSID * pCLSID); - STDMETHODIMP Run(REFERENCE_TIME tStart); - // IMediaSeeking Methods... - - // We defer to SourceFilter, but we must expose the interface on - // the output pins. Seeking commands come upstream from the renderers, - // but they must be actioned at the source filters. - STDMETHODIMP GetCapabilities(DWORD* aCapabilities); - STDMETHODIMP CheckCapabilities(DWORD* aCapabilities); - STDMETHODIMP IsFormatSupported(const GUID* aFormat); - STDMETHODIMP QueryPreferredFormat(GUID* aFormat); - STDMETHODIMP GetTimeFormat(GUID* aFormat); - STDMETHODIMP IsUsingTimeFormat(const GUID* aFormat); - STDMETHODIMP SetTimeFormat(const GUID* aFormat); - STDMETHODIMP GetDuration(LONGLONG* pDuration); - STDMETHODIMP GetStopPosition(LONGLONG* pStop); - STDMETHODIMP GetCurrentPosition(LONGLONG* aCurrent); - STDMETHODIMP ConvertTimeFormat(LONGLONG* aTarget, - const GUID* aTargetFormat, - LONGLONG aSource, - const GUID* aSourceFormat); - STDMETHODIMP SetPositions(LONGLONG* aCurrent, - DWORD aCurrentFlags, - LONGLONG* aStop, - DWORD aStopFlags); - STDMETHODIMP GetPositions(LONGLONG* aCurrent, - LONGLONG* aStop); - STDMETHODIMP GetAvailable(LONGLONG* aEarliest, - LONGLONG* aLatest); - STDMETHODIMP SetRate(double aRate); - STDMETHODIMP GetRate(double* aRate); - STDMETHODIMP GetPreroll(LONGLONG* aPreroll); - - // -------------------------------------------------------------------- - // class factory calls this - static IUnknown * CreateInstance (IN LPUNKNOWN punk, OUT HRESULT * phr); - -private: - CriticalSection mFilterCritSec; - - // Note: The input pin defers its refcounting to the sink filter, so when - // the input pin is addrefed, what actually happens is the sink filter is - // addrefed. - nsAutoPtr mInputPin; -}; - -} // namespace mozilla - -#endif // AudioSinkFilter_h_ diff --git a/dom/media/directshow/AudioSinkInputPin.cpp b/dom/media/directshow/AudioSinkInputPin.cpp deleted file mode 100644 index c1ff9d55ea..0000000000 --- a/dom/media/directshow/AudioSinkInputPin.cpp +++ /dev/null @@ -1,210 +0,0 @@ -/* -*- 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 "AudioSinkInputPin.h" -#include "AudioSinkFilter.h" -#include "SampleSink.h" -#include "mozilla/Logging.h" - -#include - -using namespace mozilla::media; - -namespace mozilla { - -static LazyLogModule gDirectShowLog("DirectShowDecoder"); -#define LOG(...) MOZ_LOG(gDirectShowLog, mozilla::LogLevel::Debug, (__VA_ARGS__)) - -AudioSinkInputPin::AudioSinkInputPin(wchar_t* aObjectName, - AudioSinkFilter* aFilter, - mozilla::CriticalSection* aLock, - HRESULT* aOutResult) - : BaseInputPin(aObjectName, aFilter, aLock, aOutResult, aObjectName), - mSegmentStartTime(0) -{ - MOZ_COUNT_CTOR(AudioSinkInputPin); - mSampleSink = new SampleSink(); - memset(&mVideoInfo, 0, sizeof(mVideoInfo)); -} - -AudioSinkInputPin::~AudioSinkInputPin() -{ - MOZ_COUNT_DTOR(AudioSinkInputPin); -} - -HRESULT -AudioSinkInputPin::GetMediaType(int aPosition, MediaType* aOutMediaType) -{ - NS_ENSURE_TRUE(aPosition >= 0, E_INVALIDARG); - NS_ENSURE_TRUE(aOutMediaType, E_POINTER); - - // Note: We set output as PCM, as IEEE_FLOAT only works when using the - // MP3 decoder as an MFT, and we can't do that while using DirectShow. - aOutMediaType->SetType(&MEDIATYPE_Audio); - aOutMediaType->SetSubtype(&MEDIASUBTYPE_PCM); - aOutMediaType->SetFormatType(&FORMAT_WaveFormatEx); - aOutMediaType->SetTemporalCompression(FALSE); - - if (aPosition == 0) { - return S_OK; - } - if (aPosition == 1) { - aOutMediaType->SetType(&MEDIATYPE_Video); - aOutMediaType->SetSubtype(&MEDIASUBTYPE_YUY2); - aOutMediaType->SetFormatType(&FORMAT_VideoInfo); - aOutMediaType->SetTemporalCompression(FALSE); - return S_OK; - } - return S_FALSE; -} - -HRESULT -AudioSinkInputPin::CheckMediaType(const MediaType* aMediaType) -{ - if (!aMediaType) { - return E_INVALIDARG; - } - - GUID majorType = *aMediaType->Type(); - if (majorType == MEDIATYPE_Video && - *aMediaType->Subtype() == MEDIASUBTYPE_YUY2 && - *aMediaType->FormatType() == FORMAT_VideoInfo) { - if (aMediaType->cbFormat >= sizeof(VIDEOINFOHEADER)) { - memcpy(&mVideoInfo, aMediaType->pbFormat, sizeof(VIDEOINFOHEADER)); - } - return S_OK; - } - - if (majorType != MEDIATYPE_Audio && majorType != WMMEDIATYPE_Audio) { - return E_INVALIDARG; - } - - if (*aMediaType->Subtype() != MEDIASUBTYPE_PCM) { - return E_INVALIDARG; - } - - if (*aMediaType->FormatType() != FORMAT_WaveFormatEx) { - return E_INVALIDARG; - } - - // We accept the media type, stash its layout format! - WAVEFORMATEX* wfx = (WAVEFORMATEX*)(aMediaType->pbFormat); - GetSampleSink()->SetAudioFormat(wfx); - - return S_OK; -} - -AudioSinkFilter* -AudioSinkInputPin::GetAudioSinkFilter() -{ - return reinterpret_cast(mFilter); -} - -SampleSink* -AudioSinkInputPin::GetSampleSink() -{ - return mSampleSink; -} - -HRESULT -AudioSinkInputPin::SetAbsoluteMediaTime(IMediaSample* aSample) -{ - HRESULT hr; - REFERENCE_TIME start = 0, end = 0; - hr = aSample->GetTime(&start, &end); - NS_ENSURE_TRUE(SUCCEEDED(hr), E_FAIL); - { - CriticalSectionAutoEnter lock(*mLock); - start += mSegmentStartTime; - end += mSegmentStartTime; - } - hr = aSample->SetMediaTime(&start, &end); - NS_ENSURE_TRUE(SUCCEEDED(hr), E_FAIL); - return S_OK; -} - -HRESULT -AudioSinkInputPin::Receive(IMediaSample* aSample ) -{ - HRESULT hr; - NS_ENSURE_TRUE(aSample, E_POINTER); - - hr = BaseInputPin::Receive(aSample); - if (SUCCEEDED(hr) && hr != S_FALSE) { // S_FALSE == flushing - // Set the timestamp of the sample after being adjusted for - // seeking/segments in the "media time" attribute. When we seek, - // DirectShow starts a new "segment", and starts labeling samples - // from time=0 again, so we need to correct for this to get the - // actual timestamps after seeking. - hr = SetAbsoluteMediaTime(aSample); - NS_ENSURE_TRUE(SUCCEEDED(hr), hr); - hr = GetSampleSink()->Receive(aSample); - NS_ENSURE_TRUE(SUCCEEDED(hr), hr); - } - return S_OK; -} - -already_AddRefed -AudioSinkInputPin::GetConnectedPinSeeking() -{ - RefPtr peer = GetConnected(); - if (!peer) - return nullptr; - RefPtr seeking; - peer->QueryInterface(static_cast(getter_AddRefs(seeking))); - return seeking.forget(); -} - -HRESULT -AudioSinkInputPin::BeginFlush() -{ - HRESULT hr = media::BaseInputPin::BeginFlush(); - NS_ENSURE_TRUE(SUCCEEDED(hr), hr); - - GetSampleSink()->Flush(); - - return S_OK; -} - -HRESULT -AudioSinkInputPin::EndFlush() -{ - HRESULT hr = media::BaseInputPin::EndFlush(); - NS_ENSURE_TRUE(SUCCEEDED(hr), hr); - - // Reset the EOS flag, so that if we're called after a seek we still work. - GetSampleSink()->Reset(); - - return S_OK; -} - -HRESULT -AudioSinkInputPin::EndOfStream(void) -{ - HRESULT hr = media::BaseInputPin::EndOfStream(); - if (FAILED(hr) || hr == S_FALSE) { - // Pin is stil flushing. - return hr; - } - GetSampleSink()->SetEOS(); - - return S_OK; -} - - -HRESULT -AudioSinkInputPin::NewSegment(REFERENCE_TIME tStart, - REFERENCE_TIME tStop, - double dRate) -{ - CriticalSectionAutoEnter lock(*mLock); - // Record the start time of the new segment, so that we can store the - // correct absolute timestamp in the "media time" each incoming sample. - mSegmentStartTime = tStart; - return S_OK; -} - -} // namespace mozilla diff --git a/dom/media/directshow/AudioSinkInputPin.h b/dom/media/directshow/AudioSinkInputPin.h deleted file mode 100644 index 17650774f0..0000000000 --- a/dom/media/directshow/AudioSinkInputPin.h +++ /dev/null @@ -1,78 +0,0 @@ -/* -*- 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/. */ - -#if !defined(AudioSinkInputPin_h_) -#define AudioSinkInputPin_h_ - -#include "BaseInputPin.h" -#include "DirectShowUtils.h" -#include "mozilla/RefPtr.h" -#include "nsAutoPtr.h" - -namespace mozilla { - -namespace media { - class MediaType; -} - -class AudioSinkFilter; -class SampleSink; - - -// Input pin for capturing audio output of a DirectShow filter graph. -// This is the input pin for the AudioSinkFilter. -class AudioSinkInputPin: public mozilla::media::BaseInputPin -{ -public: - AudioSinkInputPin(wchar_t* aObjectName, - AudioSinkFilter* aFilter, - mozilla::CriticalSection* aLock, - HRESULT* aOutResult); - virtual ~AudioSinkInputPin(); - - HRESULT GetMediaType (IN int iPos, OUT mozilla::media::MediaType * pmt); - HRESULT CheckMediaType (IN const mozilla::media::MediaType * pmt); - STDMETHODIMP Receive (IN IMediaSample *); - STDMETHODIMP BeginFlush() override; - STDMETHODIMP EndFlush() override; - - // Called when we start decoding a new segment, that happens directly after - // a seek. This captures the segment's start time. Samples decoded by the - // MP3 decoder have their timestamps offset from the segment start time. - // Storing the segment start time enables us to set each sample's MediaTime - // as an offset in the stream relative to the start of the stream, rather - // than the start of the segment, i.e. its absolute time in the stream. - STDMETHODIMP NewSegment(REFERENCE_TIME tStart, - REFERENCE_TIME tStop, - double dRate) override; - - STDMETHODIMP EndOfStream() override; - - // Returns the IMediaSeeking interface of the connected output pin. - // We forward seeking requests upstream from the sink to the source - // filters. - already_AddRefed GetConnectedPinSeeking(); - - SampleSink* GetSampleSink(); - const VIDEOINFOHEADER* GetVideoInfo() const { return &mVideoInfo; } - -private: - AudioSinkFilter* GetAudioSinkFilter(); - - // Sets the media time on the media sample, relative to the segment - // start time. - HRESULT SetAbsoluteMediaTime(IMediaSample* aSample); - - nsAutoPtr mSampleSink; - - // Synchronized by the filter lock; BaseInputPin::mLock. - REFERENCE_TIME mSegmentStartTime; - VIDEOINFOHEADER mVideoInfo; -}; - -} // namespace mozilla - -#endif // AudioSinkInputPin_h_ diff --git a/dom/media/directshow/DirectShowDecoder.cpp b/dom/media/directshow/DirectShowDecoder.cpp deleted file mode 100644 index d10c850e2f..0000000000 --- a/dom/media/directshow/DirectShowDecoder.cpp +++ /dev/null @@ -1,78 +0,0 @@ -/* -*- 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 "DirectShowDecoder.h" -#include "DirectShowReader.h" -#include "DirectShowUtils.h" -#include "MediaDecoderStateMachine.h" -#include "mozilla/Preferences.h" -#include "mozilla/WindowsVersion.h" - -namespace mozilla { - -MediaDecoderStateMachine* DirectShowDecoder::CreateStateMachine() -{ - return new MediaDecoderStateMachine(this, new DirectShowReader(this)); -} - -/* static */ -bool -DirectShowDecoder::GetSupportedCodecs(const nsACString& aType, - char const *const ** aCodecList) -{ - if (!IsEnabled()) { - return false; - } - - static char const *const mp3AudioCodecs[] = { - "mp3", - nullptr - }; - if (aType.EqualsASCII("audio/mpeg") || - aType.EqualsASCII("audio/mp3")) { - if (aCodecList) { - *aCodecList = mp3AudioCodecs; - } - return true; - } - - static char const *const h264VideoCodecs[] = { - "avc1", - "h264", - nullptr - }; - if ((aType.EqualsASCII("video/h264") || - aType.EqualsASCII("video/avc")) && - CanDecodeH264UsingDirectShow()) { - if (aCodecList) { - *aCodecList = h264VideoCodecs; - } - return true; - } - - return false; -} - -/* static */ -bool -DirectShowDecoder::IsEnabled() -{ - return Preferences::GetBool("media.directshow.enabled") && - (CanDecodeMP3UsingDirectShow() || CanDecodeH264UsingDirectShow()); -} - -DirectShowDecoder::DirectShowDecoder(MediaDecoderOwner* aOwner) - : MediaDecoder(aOwner) -{ - MOZ_COUNT_CTOR(DirectShowDecoder); -} - -DirectShowDecoder::~DirectShowDecoder() -{ - MOZ_COUNT_DTOR(DirectShowDecoder); -} - -} // namespace mozilla diff --git a/dom/media/directshow/DirectShowDecoder.h b/dom/media/directshow/DirectShowDecoder.h deleted file mode 100644 index 90b72aef1e..0000000000 --- a/dom/media/directshow/DirectShowDecoder.h +++ /dev/null @@ -1,45 +0,0 @@ -/* -*- 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/. */ - -#if !defined(DirectShowDecoder_h_) -#define DirectShowDecoder_h_ - -#include "MediaDecoder.h" - -namespace mozilla { - -// Decoder that uses the legacy DirectShow graph on systems without WMF. -class DirectShowDecoder : public MediaDecoder -{ -public: - - explicit DirectShowDecoder(MediaDecoderOwner* aOwner); - virtual ~DirectShowDecoder(); - - MediaDecoder* Clone(MediaDecoderOwner* aOwner) override { - if (!IsEnabled()) { - return nullptr; - } - return new DirectShowDecoder(aOwner); - } - - MediaDecoderStateMachine* CreateStateMachine() override; - - // Returns true if aType is a MIME type that we render with the - // DirectShow backend. If aCodecList is non null, - // it is filled with a (static const) null-terminated list of strings - // denoting the codecs we'll playback. Note that playback is strictly - // limited to MP3 only. - static bool GetSupportedCodecs(const nsACString& aType, - char const *const ** aCodecList); - - // Returns true if the DirectShow backend is preffed on. - static bool IsEnabled(); -}; - -} // namespace mozilla - -#endif diff --git a/dom/media/directshow/DirectShowReader.cpp b/dom/media/directshow/DirectShowReader.cpp deleted file mode 100644 index cc7278146e..0000000000 --- a/dom/media/directshow/DirectShowReader.cpp +++ /dev/null @@ -1,417 +0,0 @@ -/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* vim: set ts=8 sts=2 et sw=2 tw=80: */ -/* 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 "DirectShowReader.h" -#include "MediaDecoderReader.h" -#include "mozilla/RefPtr.h" -#include "DirectShowUtils.h" -#include "AudioSinkFilter.h" -#include "SourceFilter.h" -#include "SampleSink.h" -#include "VideoUtils.h" -#include "mozilla/Preferences.h" - -using namespace mozilla::media; - -namespace mozilla { - -// Windows XP's MP3 decoder filter. This is available on XP only, on Vista -// and later we can use the DMO Wrapper filter and MP3 decoder DMO. -const GUID DirectShowReader::CLSID_MPEG_LAYER_3_DECODER_FILTER = -{ 0x38BE3000, 0xDBF4, 0x11D0, {0x86, 0x0E, 0x00, 0xA0, 0x24, 0xCF, 0xEF, 0x6D} }; - - -static LazyLogModule gDirectShowLog("DirectShowDecoder"); -#define LOG(...) MOZ_LOG(gDirectShowLog, mozilla::LogLevel::Debug, (__VA_ARGS__)) - -DirectShowReader::DirectShowReader(AbstractMediaDecoder* aDecoder) - : MediaDecoderReader(aDecoder), -#ifdef DIRECTSHOW_REGISTER_GRAPH - mRotRegister(0), -#endif - mNumChannels(0), - mAudioRate(0), - mBytesPerSample(0), - mIsH264(aDecoder->GetResource()->GetContentType().EqualsLiteral("video/h264") || - aDecoder->GetResource()->GetContentType().EqualsLiteral("video/avc")) -{ - MOZ_ASSERT(NS_IsMainThread(), "Must be on main thread."); - MOZ_COUNT_CTOR(DirectShowReader); - if (mIsH264) { - Preferences::SetBool("media.directshow.h264.active", true); - } -} - -DirectShowReader::~DirectShowReader() -{ - MOZ_ASSERT(NS_IsMainThread(), "Must be on main thread."); - MOZ_COUNT_DTOR(DirectShowReader); - if (mIsH264) { - Preferences::SetBool("media.directshow.h264.active", false); - } -#ifdef DIRECTSHOW_REGISTER_GRAPH - if (mRotRegister) { - RemoveGraphFromRunningObjectTable(mRotRegister); - } -#endif -} - -nsresult -DirectShowReader::ReadMetadata(MediaInfo* aInfo, - MetadataTags** aTags) -{ - MOZ_ASSERT(OnTaskQueue()); - HRESULT hr; - nsresult rv; - - // Create the filter graph, reference it by the GraphBuilder interface, - // to make graph building more convenient. - hr = CoCreateInstance(CLSID_FilterGraph, - nullptr, - CLSCTX_INPROC_SERVER, - IID_IGraphBuilder, - reinterpret_cast(static_cast(getter_AddRefs(mGraph)))); - NS_ENSURE_TRUE(SUCCEEDED(hr) && mGraph, NS_ERROR_FAILURE); - -#ifdef DIRECTSHOW_REGISTER_GRAPH - hr = AddGraphToRunningObjectTable(mGraph, &mRotRegister); - NS_ENSURE_TRUE(SUCCEEDED(hr), NS_ERROR_FAILURE); - #endif - - // Extract the interface pointers we'll need from the filter graph. - hr = mGraph->QueryInterface(static_cast(getter_AddRefs(mControl))); - NS_ENSURE_TRUE(SUCCEEDED(hr) && mControl, NS_ERROR_FAILURE); - - hr = mGraph->QueryInterface(static_cast(getter_AddRefs(mMediaSeeking))); - NS_ENSURE_TRUE(SUCCEEDED(hr) && mMediaSeeking, NS_ERROR_FAILURE); - - if (mIsH264) { - return ReadH264Metadata(aInfo, aTags); - } - - // Build the graph. Create the filters we need, and connect them. We - // build the entire graph ourselves to prevent other decoders installed - // on the system being created and used. - - // Our source filters, wraps the MediaResource. - mSourceFilter = new SourceFilter(MEDIATYPE_Stream, MEDIASUBTYPE_MPEG1Audio); - NS_ENSURE_TRUE(mSourceFilter, NS_ERROR_FAILURE); - - rv = mSourceFilter->Init(mDecoder->GetResource(), 0); - NS_ENSURE_SUCCESS(rv, rv); - - hr = mGraph->AddFilter(mSourceFilter, L"MozillaDirectShowSource"); - NS_ENSURE_TRUE(SUCCEEDED(hr), NS_ERROR_FAILURE); - - // The MPEG demuxer. - RefPtr demuxer; - hr = CreateAndAddFilter(mGraph, - CLSID_MPEG1Splitter, - L"MPEG1Splitter", - getter_AddRefs(demuxer)); - NS_ENSURE_TRUE(SUCCEEDED(hr), NS_ERROR_FAILURE); - - // Platform MP3 decoder. - RefPtr decoder; - // Firstly try to create the MP3 decoder filter that ships with WinXP - // directly. This filter doesn't normally exist on later versions of - // Windows. - hr = CreateAndAddFilter(mGraph, - CLSID_MPEG_LAYER_3_DECODER_FILTER, - L"MPEG Layer 3 Decoder", - getter_AddRefs(decoder)); - if (FAILED(hr)) { - // Failed to create MP3 decoder filter. Try to instantiate - // the MP3 decoder DMO. - hr = AddMP3DMOWrapperFilter(mGraph, getter_AddRefs(decoder)); - NS_ENSURE_TRUE(SUCCEEDED(hr), NS_ERROR_FAILURE); - } - - // Sink, captures audio samples and inserts them into our pipeline. - static const wchar_t* AudioSinkFilterName = L"MozAudioSinkFilter"; - mAudioSinkFilter = new AudioSinkFilter(AudioSinkFilterName, &hr); - NS_ENSURE_TRUE(mAudioSinkFilter && SUCCEEDED(hr), NS_ERROR_FAILURE); - hr = mGraph->AddFilter(mAudioSinkFilter, AudioSinkFilterName); - NS_ENSURE_TRUE(SUCCEEDED(hr), NS_ERROR_FAILURE); - - // Join the filters. - hr = ConnectFilters(mGraph, mSourceFilter, demuxer); - NS_ENSURE_TRUE(SUCCEEDED(hr), NS_ERROR_FAILURE); - - hr = ConnectFilters(mGraph, demuxer, decoder); - NS_ENSURE_TRUE(SUCCEEDED(hr), NS_ERROR_FAILURE); - - hr = ConnectFilters(mGraph, decoder, mAudioSinkFilter); - NS_ENSURE_TRUE(SUCCEEDED(hr), NS_ERROR_FAILURE); - - WAVEFORMATEX format; - mAudioSinkFilter->GetSampleSink()->GetAudioFormat(&format); - NS_ENSURE_TRUE(format.wFormatTag == WAVE_FORMAT_PCM, NS_ERROR_FAILURE); - - mInfo.mAudio.mChannels = mNumChannels = format.nChannels; - mInfo.mAudio.mRate = mAudioRate = format.nSamplesPerSec; - mInfo.mAudio.mBitDepth = format.wBitsPerSample; - mBytesPerSample = format.wBitsPerSample / 8; - - // Begin decoding! - hr = mControl->Run(); - NS_ENSURE_TRUE(SUCCEEDED(hr), NS_ERROR_FAILURE); - - DWORD seekCaps = 0; - hr = mMediaSeeking->GetCapabilities(&seekCaps); - mInfo.mMediaSeekable = SUCCEEDED(hr) && (AM_SEEKING_CanSeekAbsolute & seekCaps); - - LOG("Successfully initialized DirectShow MP3 decoder."); - LOG("Channels=%u Hz=%u duration=%lld bytesPerSample=%d", - mInfo.mAudio.mChannels, - mInfo.mAudio.mRate, - 0LL, - mBytesPerSample); - - *aInfo = mInfo; - // Note: The SourceFilter strips ID3v2 tags out of the stream. - *aTags = nullptr; - - return NS_OK; -} - -nsresult -DirectShowReader::ReadH264Metadata(MediaInfo* aInfo, MetadataTags** aTags) -{ - HRESULT hr; - mSourceFilter = new SourceFilter(MEDIATYPE_Stream, MEDIASUBTYPE_H264); - NS_ENSURE_TRUE(mSourceFilter, NS_ERROR_OUT_OF_MEMORY); - nsresult rv = mSourceFilter->Init(mDecoder->GetResource(), 0); - NS_ENSURE_SUCCESS(rv, rv); - hr = mGraph->AddFilter(mSourceFilter, L"Mozilla H.264 source"); - NS_ENSURE_TRUE(SUCCEEDED(hr), NS_ERROR_FAILURE); - - RefPtr decoder; - hr = AddH264DecoderFilter(mGraph, getter_AddRefs(decoder)); - NS_ENSURE_TRUE(SUCCEEDED(hr), NS_ERROR_FAILURE); - mAudioSinkFilter = new AudioSinkFilter(L"Mozilla H.264 video sink", &hr); - NS_ENSURE_TRUE(mAudioSinkFilter && SUCCEEDED(hr), NS_ERROR_FAILURE); - hr = mGraph->AddFilter(mAudioSinkFilter, L"Mozilla H.264 video sink"); - NS_ENSURE_TRUE(SUCCEEDED(hr), NS_ERROR_FAILURE); - hr = ConnectFilters(mGraph, mSourceFilter, decoder); - NS_ENSURE_TRUE(SUCCEEDED(hr), NS_ERROR_FAILURE); - hr = ConnectFilters(mGraph, decoder, mAudioSinkFilter); - NS_ENSURE_TRUE(SUCCEEDED(hr), NS_ERROR_FAILURE); - - const VIDEOINFOHEADER* vih = mAudioSinkFilter->GetVideoInfo(); - int32_t width = abs(vih->bmiHeader.biWidth); - int32_t height = abs(vih->bmiHeader.biHeight); - NS_ENSURE_TRUE(width > 0 && height > 0, NS_ERROR_FAILURE); - mInfo.mVideo = VideoInfo(width, height); - mInfo.mVideo.mMimeType = "video/h264"; - hr = mControl->Run(); - NS_ENSURE_TRUE(SUCCEEDED(hr), NS_ERROR_FAILURE); - *aInfo = mInfo; - *aTags = nullptr; - return NS_OK; -} - -inline float -UnsignedByteToAudioSample(uint8_t aValue) -{ - return aValue * (2.0f / UINT8_MAX) - 1.0f; -} - -bool -DirectShowReader::Finish(HRESULT aStatus) -{ - MOZ_ASSERT(OnTaskQueue()); - - LOG("DirectShowReader::Finish(0x%x)", aStatus); - // Notify the filter graph of end of stream. - RefPtr eventSink; - HRESULT hr = mGraph->QueryInterface(static_cast(getter_AddRefs(eventSink))); - if (SUCCEEDED(hr) && eventSink) { - eventSink->Notify(EC_COMPLETE, aStatus, 0); - } - return false; -} - -class DirectShowCopy -{ -public: - DirectShowCopy(uint8_t *aSource, uint32_t aBytesPerSample, - uint32_t aSamples, uint32_t aChannels) - : mSource(aSource) - , mBytesPerSample(aBytesPerSample) - , mSamples(aSamples) - , mChannels(aChannels) - , mNextSample(0) - { } - - uint32_t operator()(AudioDataValue *aBuffer, uint32_t aSamples) - { - uint32_t maxSamples = std::min(aSamples, mSamples - mNextSample); - uint32_t frames = maxSamples / mChannels; - size_t byteOffset = mNextSample * mBytesPerSample; - if (mBytesPerSample == 1) { - for (uint32_t i = 0; i < maxSamples; ++i) { - uint8_t *sample = mSource + byteOffset; - aBuffer[i] = UnsignedByteToAudioSample(*sample); - byteOffset += mBytesPerSample; - } - } else if (mBytesPerSample == 2) { - for (uint32_t i = 0; i < maxSamples; ++i) { - int16_t *sample = reinterpret_cast(mSource + byteOffset); - aBuffer[i] = AudioSampleToFloat(*sample); - byteOffset += mBytesPerSample; - } - } - mNextSample += maxSamples; - return frames; - } - -private: - uint8_t * const mSource; - const uint32_t mBytesPerSample; - const uint32_t mSamples; - const uint32_t mChannels; - uint32_t mNextSample; -}; - -bool -DirectShowReader::DecodeAudioData() -{ - MOZ_ASSERT(OnTaskQueue()); - HRESULT hr; - - SampleSink* sink = mAudioSinkFilter->GetSampleSink(); - if (sink->AtEOS()) { - // End of stream. - return Finish(S_OK); - } - - // Get the next chunk of audio samples. This blocks until the sample - // arrives, or an error occurs (like the stream is shutdown). - RefPtr sample; - hr = sink->Extract(sample); - if (FAILED(hr) || hr == S_FALSE) { - return Finish(hr); - } - - int64_t start = 0, end = 0; - sample->GetMediaTime(&start, &end); - LOG("DirectShowReader::DecodeAudioData [%4.2lf-%4.2lf]", - RefTimeToSeconds(start), - RefTimeToSeconds(end)); - - LONG length = sample->GetActualDataLength(); - LONG numSamples = length / mBytesPerSample; - LONG numFrames = length / mBytesPerSample / mNumChannels; - - BYTE* data = nullptr; - hr = sample->GetPointer(&data); - NS_ENSURE_TRUE(SUCCEEDED(hr), Finish(hr)); - - mAudioCompactor.Push(mDecoder->GetResource()->Tell(), - RefTimeToUsecs(start), - mInfo.mAudio.mRate, - numFrames, - mNumChannels, - DirectShowCopy(reinterpret_cast(data), - mBytesPerSample, - numSamples, - mNumChannels)); - return true; -} - -bool -DirectShowReader::DecodeVideoFrame(bool &aKeyframeSkip, - int64_t aTimeThreshold) -{ - MOZ_ASSERT(OnTaskQueue()); - if (!mIsH264) { - return false; - } - RefPtr sample; - HRESULT hr = mAudioSinkFilter->GetSampleSink()->Extract(sample); - if (FAILED(hr) || hr == S_FALSE) { - return Finish(hr); - } - REFERENCE_TIME start = 0, end = 0; - sample->GetMediaTime(&start, &end); - BYTE* data = nullptr; - NS_ENSURE_TRUE(SUCCEEDED(sample->GetPointer(&data)), Finish(E_FAIL)); - LONG length = sample->GetActualDataLength(); - int32_t width = mInfo.mVideo.mImage.width; - int32_t height = mInfo.mVideo.mImage.height; - int32_t stride = width * 2; - NS_ENSURE_TRUE(length >= stride * height, Finish(E_FAIL)); - nsTArray y; - nsTArray u; - nsTArray v; - y.SetLength(width * height); - u.SetLength((width / 2) * (height / 2)); - v.SetLength((width / 2) * (height / 2)); - for (int32_t row = 0; row < height; ++row) { - const uint8_t* src = data + row * stride; - for (int32_t x = 0; x < width; x += 2) { - int32_t p = row * width + x; - y[p] = src[0]; y[p + 1] = src[2]; - if (!(row & 1)) { - u[(row / 2) * (width / 2) + x / 2] = src[1]; - v[(row / 2) * (width / 2) + x / 2] = src[3]; - } - src += 4; - } - } - VideoData::YCbCrBuffer buffer; - buffer.mPlanes[0] = { y.Elements(), uint32_t(width), uint32_t(height), uint32_t(width), 0, 1 }; - buffer.mPlanes[1] = { u.Elements(), uint32_t(width / 2), uint32_t(height / 2), uint32_t(width / 2), 0, 1 }; - buffer.mPlanes[2] = { v.Elements(), uint32_t(width / 2), uint32_t(height / 2), uint32_t(width / 2), 0, 1 }; - RefPtr video = VideoData::CreateAndCopyData( - mInfo.mVideo, mDecoder->GetImageContainer(), 0, RefTimeToUsecs(start), - RefTimeToUsecs(end - start), buffer, true, -1, - gfx::IntRect(0, 0, width, height)); - NS_ENSURE_TRUE(video, Finish(E_OUTOFMEMORY)); - VideoQueue().Push(video); - return true; -} - -RefPtr -DirectShowReader::Seek(SeekTarget aTarget, int64_t aEndTime) -{ - nsresult res = SeekInternal(aTarget.GetTime().ToMicroseconds()); - if (NS_FAILED(res)) { - return SeekPromise::CreateAndReject(res, __func__); - } else { - return SeekPromise::CreateAndResolve(aTarget.GetTime(), __func__); - } -} - -nsresult -DirectShowReader::SeekInternal(int64_t aTargetUs) -{ - HRESULT hr; - MOZ_ASSERT(OnTaskQueue()); - - LOG("DirectShowReader::Seek() target=%lld", aTargetUs); - - hr = mControl->Pause(); - NS_ENSURE_TRUE(SUCCEEDED(hr), NS_ERROR_FAILURE); - - nsresult rv = ResetDecode(); - NS_ENSURE_SUCCESS(rv, rv); - - LONGLONG seekPosition = UsecsToRefTime(aTargetUs); - hr = mMediaSeeking->SetPositions(&seekPosition, - AM_SEEKING_AbsolutePositioning, - nullptr, - AM_SEEKING_NoPositioning); - NS_ENSURE_TRUE(SUCCEEDED(hr), NS_ERROR_FAILURE); - - hr = mControl->Run(); - NS_ENSURE_TRUE(SUCCEEDED(hr), NS_ERROR_FAILURE); - - return NS_OK; -} - -} // namespace mozilla diff --git a/dom/media/directshow/DirectShowReader.h b/dom/media/directshow/DirectShowReader.h deleted file mode 100644 index 32972517a2..0000000000 --- a/dom/media/directshow/DirectShowReader.h +++ /dev/null @@ -1,106 +0,0 @@ -/* -*- 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/. */ - -#if !defined(DirectShowReader_h_) -#define DirectShowReader_h_ - -#include "windows.h" // HRESULT, DWORD -#include "MediaDecoderReader.h" -#include "MediaResource.h" -#include "mozilla/RefPtr.h" - -// Add the graph to the Running Object Table so that we can connect -// to this graph with GraphEdit/GraphStudio. Note: you must -// also regsvr32 proppage.dll from the Windows SDK. -// See: http://msdn.microsoft.com/en-us/library/ms787252(VS.85).aspx -// #define DIRECTSHOW_REGISTER_GRAPH - -struct IGraphBuilder; -struct IMediaControl; -struct IMediaSeeking; - -namespace mozilla { - -class AudioSinkFilter; -class SourceFilter; - -// Decoder backend for decoding legacy media using DirectShow. DirectShow operates as -// a filter graph. The basic design of the DirectShowReader is that we have -// a SourceFilter that wraps the MediaResource that connects to the -// MP3 decoder filter. The MP3 decoder filter "pulls" data as it requires it -// downstream on its own thread. When the MP3 decoder has produced a block of -// decoded samples, its thread calls downstream into our AudioSinkFilter, -// passing the decoded buffer in. The AudioSinkFilter inserts the samples into -// a SampleSink object. The SampleSink blocks the MP3 decoder's thread until -// the decode thread calls DecodeAudioData(), whereupon the SampleSink -// releases the decoded samples to the decode thread, and unblocks the MP3 -// decoder's thread. The MP3 decoder can then request more data from the -// SourceFilter, and decode more data. If the decode thread calls -// DecodeAudioData() and there's no decoded samples waiting to be extracted -// in the SampleSink, the SampleSink blocks the decode thread until the MP3 -// decoder produces a decoded sample. -class DirectShowReader : public MediaDecoderReader -{ -public: - DirectShowReader(AbstractMediaDecoder* aDecoder); - - virtual ~DirectShowReader(); - - bool DecodeAudioData() override; - bool DecodeVideoFrame(bool &aKeyframeSkip, - int64_t aTimeThreshold) override; - - nsresult ReadMetadata(MediaInfo* aInfo, - MetadataTags** aTags) override; - - RefPtr - Seek(SeekTarget aTarget, int64_t aEndTime) override; - - static const GUID CLSID_MPEG_LAYER_3_DECODER_FILTER; - -private: - // Notifies the filter graph that playback is complete. aStatus is - // the code to send to the filter graph. Always returns false, so - // that we can just "return Finish()" from DecodeAudioData(). - bool Finish(HRESULT aStatus); - - nsresult SeekInternal(int64_t aTime); - nsresult ReadH264Metadata(MediaInfo* aInfo, MetadataTags** aTags); - - // DirectShow filter graph, and associated playback and seeking - // control interfaces. - RefPtr mGraph; - RefPtr mControl; - RefPtr mMediaSeeking; - - // Wraps the MediaResource, and feeds undecoded data into the filter graph. - RefPtr mSourceFilter; - - // Sits at the end of the graph, removing decoded samples from the graph. - // The graph will block while this is blocked, i.e. it will pause decoding. - RefPtr mAudioSinkFilter; - bool mIsH264; - -#ifdef DIRECTSHOW_REGISTER_GRAPH - // Used to add/remove the filter graph to the Running Object Table. You can - // connect GraphEdit/GraphStudio to the graph to observe and/or debug its - // topology and state. - DWORD mRotRegister; -#endif - - // Number of channels in the audio stream. - uint32_t mNumChannels; - - // Samples per second in the audio stream. - uint32_t mAudioRate; - - // Number of bytes per sample. Can be either 1 or 2. - uint32_t mBytesPerSample; -}; - -} // namespace mozilla - -#endif diff --git a/dom/media/directshow/DirectShowUtils.cpp b/dom/media/directshow/DirectShowUtils.cpp deleted file mode 100644 index e76b1b2b24..0000000000 --- a/dom/media/directshow/DirectShowUtils.cpp +++ /dev/null @@ -1,457 +0,0 @@ -/* 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 "DirectShowUtils.h" -#include "DirectShowReader.h" -#include "dmodshow.h" -#include "wmcodecdsp.h" -#include "dmoreg.h" -#include "mozilla/ArrayUtils.h" -#include "mozilla/RefPtr.h" -#include "nsPrintfCString.h" -#include - -#define WARN(...) NS_WARNING(nsPrintfCString(__VA_ARGS__).get()) - -namespace mozilla { - -// Create a table which maps GUIDs to a string representation of the GUID. -// This is useful for debugging purposes, for logging the GUIDs of media types. -// This is only available when logging is enabled, i.e. not in release builds. -struct GuidToName { - const char* name; - const GUID guid; -}; - -#pragma push_macro("OUR_GUID_ENTRY") -#undef OUR_GUID_ENTRY -#define OUR_GUID_ENTRY(name, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8) \ - { #name, {l, w1, w2, {b1, b2, b3, b4, b5, b6, b7, b8}} }, - -static const GuidToName GuidToNameTable[] = { -#include -}; - -#pragma pop_macro("OUR_GUID_ENTRY") - -const char* -GetDirectShowGuidName(const GUID& aGuid) -{ - const size_t len = ArrayLength(GuidToNameTable); - for (unsigned i = 0; i < len; i++) { - if (IsEqualGUID(aGuid, GuidToNameTable[i].guid)) { - return GuidToNameTable[i].name; - } - } - return "Unknown"; -} - -void -RemoveGraphFromRunningObjectTable(DWORD aRotRegister) -{ - RefPtr runningObjectTable; - if (SUCCEEDED(GetRunningObjectTable(0, getter_AddRefs(runningObjectTable)))) { - runningObjectTable->Revoke(aRotRegister); - } -} - -HRESULT -AddGraphToRunningObjectTable(IUnknown *aUnkGraph, DWORD *aOutRotRegister) -{ - HRESULT hr; - - RefPtr moniker; - RefPtr runningObjectTable; - - hr = GetRunningObjectTable(0, getter_AddRefs(runningObjectTable)); - NS_ENSURE_TRUE(SUCCEEDED(hr), hr); - - const size_t STRING_LENGTH = 256; - WCHAR wsz[STRING_LENGTH]; - - StringCchPrintfW(wsz, - STRING_LENGTH, - L"FilterGraph %08x pid %08x", - (DWORD_PTR)aUnkGraph, - GetCurrentProcessId()); - - hr = CreateItemMoniker(L"!", wsz, getter_AddRefs(moniker)); - NS_ENSURE_TRUE(SUCCEEDED(hr), hr); - - hr = runningObjectTable->Register(ROTFLAGS_REGISTRATIONKEEPSALIVE, - aUnkGraph, - moniker, - aOutRotRegister); - NS_ENSURE_TRUE(SUCCEEDED(hr), hr); - - return S_OK; -} - -const char* -GetGraphNotifyString(long evCode) -{ -#define CASE(x) case x: return #x - switch(evCode) { - CASE(EC_ACTIVATE); // A video window is being activated or deactivated. - CASE(EC_BANDWIDTHCHANGE); // Not supported. - CASE(EC_BUFFERING_DATA); // The graph is buffering data, or has stopped buffering data. - CASE(EC_BUILT); // Send by the Video Control when a graph has been built. Not forwarded to applications. - CASE(EC_CLOCK_CHANGED); // The reference clock has changed. - CASE(EC_CLOCK_UNSET); // The clock provider was disconnected. - CASE(EC_CODECAPI_EVENT); // Sent by an encoder to signal an encoding event. - CASE(EC_COMPLETE); // All data from a particular stream has been rendered. - CASE(EC_CONTENTPROPERTY_CHANGED); // Not supported. - CASE(EC_DEVICE_LOST); // A Plug and Play device was removed or has become available again. - CASE(EC_DISPLAY_CHANGED); // The display mode has changed. - CASE(EC_END_OF_SEGMENT); // The end of a segment has been reached. - CASE(EC_EOS_SOON); // Not supported. - CASE(EC_ERROR_STILLPLAYING); // An asynchronous command to run the graph has failed. - CASE(EC_ERRORABORT); // An operation was aborted because of an error. - CASE(EC_ERRORABORTEX); // An operation was aborted because of an error. - CASE(EC_EXTDEVICE_MODE_CHANGE); // Not supported. - CASE(EC_FILE_CLOSED); // The source file was closed because of an unexpected event. - CASE(EC_FULLSCREEN_LOST); // The video renderer is switching out of full-screen mode. - CASE(EC_GRAPH_CHANGED); // The filter graph has changed. - CASE(EC_LENGTH_CHANGED); // The length of a source has changed. - CASE(EC_LOADSTATUS); // Notifies the application of progress when opening a network file. - CASE(EC_MARKER_HIT); // Not supported. - CASE(EC_NEED_RESTART); // A filter is requesting that the graph be restarted. - CASE(EC_NEW_PIN); // Not supported. - CASE(EC_NOTIFY_WINDOW); // Notifies a filter of the video renderer's window. - CASE(EC_OLE_EVENT); // A filter is passing a text string to the application. - CASE(EC_OPENING_FILE); // The graph is opening a file, or has finished opening a file. - CASE(EC_PALETTE_CHANGED); // The video palette has changed. - CASE(EC_PAUSED); // A pause request has completed. - CASE(EC_PLEASE_REOPEN); // The source file has changed. - CASE(EC_PREPROCESS_COMPLETE); // Sent by the WM ASF Writer filter when it completes the pre-processing for multipass encoding. - CASE(EC_PROCESSING_LATENCY); // Indicates the amount of time that a component is taking to process each sample. - CASE(EC_QUALITY_CHANGE); // The graph is dropping samples, for quality control. - //CASE(EC_RENDER_FINISHED); // Not supported. - CASE(EC_REPAINT); // A video renderer requires a repaint. - CASE(EC_SAMPLE_LATENCY); // Specifies how far behind schedule a component is for processing samples. - //CASE(EC_SAMPLE_NEEDED); // Requests a new input sample from the Enhanced Video Renderer (EVR) filter. - CASE(EC_SCRUB_TIME); // Specifies the time stamp for the most recent frame step. - CASE(EC_SEGMENT_STARTED); // A new segment has started. - CASE(EC_SHUTTING_DOWN); // The filter graph is shutting down, prior to being destroyed. - CASE(EC_SNDDEV_IN_ERROR); // A device error has occurred in an audio capture filter. - CASE(EC_SNDDEV_OUT_ERROR); // A device error has occurred in an audio renderer filter. - CASE(EC_STARVATION); // A filter is not receiving enough data. - CASE(EC_STATE_CHANGE); // The filter graph has changed state. - CASE(EC_STATUS); // Contains two arbitrary status strings. - CASE(EC_STEP_COMPLETE); // A filter performing frame stepping has stepped the specified number of frames. - CASE(EC_STREAM_CONTROL_STARTED); // A stream-control start command has taken effect. - CASE(EC_STREAM_CONTROL_STOPPED); // A stream-control stop command has taken effect. - CASE(EC_STREAM_ERROR_STILLPLAYING); // An error has occurred in a stream. The stream is still playing. - CASE(EC_STREAM_ERROR_STOPPED); // A stream has stopped because of an error. - CASE(EC_TIMECODE_AVAILABLE); // Not supported. - CASE(EC_UNBUILT); // Send by the Video Control when a graph has been torn down. Not forwarded to applications. - CASE(EC_USERABORT); // The user has terminated playback. - CASE(EC_VIDEO_SIZE_CHANGED); // The native video size has changed. - CASE(EC_VIDEOFRAMEREADY); // A video frame is ready for display. - CASE(EC_VMR_RECONNECTION_FAILED); // Sent by the VMR-7 and the VMR-9 when it was unable to accept a dynamic format change request from the upstream decoder. - CASE(EC_VMR_RENDERDEVICE_SET); // Sent when the VMR has selected its rendering mechanism. - CASE(EC_VMR_SURFACE_FLIPPED); // Sent when the VMR-7's allocator presenter has called the DirectDraw Flip method on the surface being presented. - CASE(EC_WINDOW_DESTROYED); // The video renderer was destroyed or removed from the graph. - CASE(EC_WMT_EVENT); // Sent by the WM ASF Reader filter when it reads ASF files protected by digital rights management (DRM). - CASE(EC_WMT_INDEX_EVENT); // Sent when an application uses the WM ASF Writer to index Windows Media Video files. - CASE(S_OK); // Success. - CASE(VFW_S_AUDIO_NOT_RENDERED); // Partial success; the audio was not rendered. - CASE(VFW_S_DUPLICATE_NAME); // Success; the Filter Graph Manager modified a filter name to avoid duplication. - CASE(VFW_S_PARTIAL_RENDER); // Partial success; some of the streams in this movie are in an unsupported format. - CASE(VFW_S_VIDEO_NOT_RENDERED); // Partial success; the video was not rendered. - CASE(E_ABORT); // Operation aborted. - CASE(E_OUTOFMEMORY); // Insufficient memory. - CASE(E_POINTER); // Null pointer argument. - CASE(VFW_E_CANNOT_CONNECT); // No combination of intermediate filters could be found to make the connection. - CASE(VFW_E_CANNOT_RENDER); // No combination of filters could be found to render the stream. - CASE(VFW_E_NO_ACCEPTABLE_TYPES); // There is no common media type between these pins. - CASE(VFW_E_NOT_IN_GRAPH); - - default: - return "Unknown Code"; - }; -#undef CASE -} - -HRESULT -CreateAndAddFilter(IGraphBuilder* aGraph, - REFGUID aFilterClsId, - LPCWSTR aFilterName, - IBaseFilter **aOutFilter) -{ - NS_ENSURE_TRUE(aGraph, E_POINTER); - NS_ENSURE_TRUE(aOutFilter, E_POINTER); - HRESULT hr; - - RefPtr filter; - hr = CoCreateInstance(aFilterClsId, - nullptr, - CLSCTX_INPROC_SERVER, - IID_IBaseFilter, - getter_AddRefs(filter)); - if (FAILED(hr)) { - // Object probably not available on this system. - WARN("CoCreateInstance failed, hr=%x", hr); - return hr; - } - - hr = aGraph->AddFilter(filter, aFilterName); - if (FAILED(hr)) { - WARN("AddFilter failed, hr=%x", hr); - return hr; - } - - filter.forget(aOutFilter); - - return S_OK; -} - -HRESULT -CreateMP3DMOWrapperFilter(IBaseFilter **aOutFilter) -{ - NS_ENSURE_TRUE(aOutFilter, E_POINTER); - HRESULT hr; - - // Create the wrapper filter. - RefPtr filter; - hr = CoCreateInstance(CLSID_DMOWrapperFilter, - nullptr, - CLSCTX_INPROC_SERVER, - IID_IBaseFilter, - getter_AddRefs(filter)); - if (FAILED(hr)) { - WARN("CoCreateInstance failed, hr=%x", hr); - return hr; - } - - // Query for IDMOWrapperFilter. - RefPtr dmoWrapper; - hr = filter->QueryInterface(IID_IDMOWrapperFilter, - getter_AddRefs(dmoWrapper)); - if (FAILED(hr)) { - WARN("QueryInterface failed, hr=%x", hr); - return hr; - } - - hr = dmoWrapper->Init(CLSID_CMP3DecMediaObject, DMOCATEGORY_AUDIO_DECODER); - if (FAILED(hr)) { - // Can't instantiate MP3 DMO. It doesn't exist on Windows XP, we're - // probably hitting that. Don't log warning to console, this is an - // expected error. - WARN("dmoWrapper Init failed, hr=%x", hr); - return hr; - } - - filter.forget(aOutFilter); - - return S_OK; -} - -HRESULT -AddMP3DMOWrapperFilter(IGraphBuilder* aGraph, - IBaseFilter **aOutFilter) -{ - NS_ENSURE_TRUE(aGraph, E_POINTER); - NS_ENSURE_TRUE(aOutFilter, E_POINTER); - HRESULT hr; - - // Create the wrapper filter. - RefPtr filter; - hr = CreateMP3DMOWrapperFilter(getter_AddRefs(filter)); - NS_ENSURE_TRUE(SUCCEEDED(hr), hr); - - // Add the wrapper filter to graph. - hr = aGraph->AddFilter(filter, L"MP3 Decoder DMO"); - if (FAILED(hr)) { - WARN("AddFilter failed, hr=%x", hr); - return hr; - } - - filter.forget(aOutFilter); - - return S_OK; -} - -bool -CanDecodeMP3UsingDirectShow() -{ - RefPtr filter; - - // Can we create the MP3 demuxer filter? - if (FAILED(CoCreateInstance(CLSID_MPEG1Splitter, - nullptr, - CLSCTX_INPROC_SERVER, - IID_IBaseFilter, - getter_AddRefs(filter)))) { - return false; - } - - // Can we create either the WinXP MP3 decoder filter or the MP3 DMO decoder? - if (FAILED(CoCreateInstance(DirectShowReader::CLSID_MPEG_LAYER_3_DECODER_FILTER, - nullptr, - CLSCTX_INPROC_SERVER, - IID_IBaseFilter, - getter_AddRefs(filter))) && - FAILED(CreateMP3DMOWrapperFilter(getter_AddRefs(filter)))) { - return false; - } - - // Else, we can create all of the components we need. Assume - // DirectShow is going to work... - return true; -} - -bool -CanDecodeH264UsingDirectShow() -{ - RefPtr devEnum; - HRESULT hr = CoCreateInstance(CLSID_SystemDeviceEnum, nullptr, - CLSCTX_INPROC_SERVER, - IID_ICreateDevEnum, getter_AddRefs(devEnum)); - if (FAILED(hr)) { - return false; - } - - RefPtr filters; - hr = devEnum->CreateClassEnumerator(CLSID_LegacyAmFilterCategory, - getter_AddRefs(filters), 0); - if (hr != S_OK) { - return false; - } - - RefPtr moniker; - ULONG fetched = 0; - while (filters->Next(1, getter_AddRefs(moniker), &fetched) == S_OK) { - RefPtr bag; - if (SUCCEEDED(moniker->BindToStorage(nullptr, nullptr, - IID_IPropertyBag, - getter_AddRefs(bag)))) { - VARIANT value; - VariantInit(&value); - if (SUCCEEDED(bag->Read(L"FriendlyName", &value, nullptr)) && - value.vt == VT_BSTR && value.bstrVal && - (wcsstr(value.bstrVal, L"H264") || - wcsstr(value.bstrVal, L"H.264") || - wcsstr(value.bstrVal, L"AVC"))) { - VariantClear(&value); - return true; - } - VariantClear(&value); - } - moniker = nullptr; - } - return false; -} - -HRESULT -AddH264DecoderFilter(IGraphBuilder* aGraph, IBaseFilter** aOutFilter) -{ - NS_ENSURE_TRUE(aGraph && aOutFilter, E_POINTER); - *aOutFilter = nullptr; - RefPtr devEnum; - HRESULT hr = CoCreateInstance(CLSID_SystemDeviceEnum, nullptr, - CLSCTX_INPROC_SERVER, IID_ICreateDevEnum, - getter_AddRefs(devEnum)); - NS_ENSURE_TRUE(SUCCEEDED(hr), hr); - RefPtr filters; - hr = devEnum->CreateClassEnumerator(CLSID_LegacyAmFilterCategory, - getter_AddRefs(filters), 0); - NS_ENSURE_TRUE(hr == S_OK, VFW_E_NOT_FOUND); - RefPtr moniker; - ULONG fetched = 0; - while (filters->Next(1, getter_AddRefs(moniker), &fetched) == S_OK) { - RefPtr bag; - VARIANT value; - VariantInit(&value); - bool h264 = false; - if (SUCCEEDED(moniker->BindToStorage(nullptr, nullptr, IID_IPropertyBag, - getter_AddRefs(bag))) && - SUCCEEDED(bag->Read(L"FriendlyName", &value, nullptr)) && - value.vt == VT_BSTR && value.bstrVal) { - h264 = wcsstr(value.bstrVal, L"H264") || - wcsstr(value.bstrVal, L"H.264") || - wcsstr(value.bstrVal, L"AVC"); - } - VariantClear(&value); - if (h264 && SUCCEEDED(moniker->BindToObject(nullptr, nullptr, IID_IBaseFilter, - reinterpret_cast(aOutFilter)))) { - hr = aGraph->AddFilter(*aOutFilter, L"DirectShow H.264 decoder"); - if (SUCCEEDED(hr)) { - return hr; - } - (*aOutFilter)->Release(); - *aOutFilter = nullptr; - } - moniker = nullptr; - } - return VFW_E_NOT_FOUND; -} - -// Match a pin by pin direction and connection state. -HRESULT -MatchUnconnectedPin(IPin* aPin, - PIN_DIRECTION aPinDir, - bool *aOutMatches) -{ - NS_ENSURE_TRUE(aPin, E_POINTER); - NS_ENSURE_TRUE(aOutMatches, E_POINTER); - - // Ensure the pin is unconnected. - RefPtr peer; - HRESULT hr = aPin->ConnectedTo(getter_AddRefs(peer)); - if (hr != VFW_E_NOT_CONNECTED) { - *aOutMatches = false; - return hr; - } - - // Ensure the pin is of the specified direction. - PIN_DIRECTION pinDir; - hr = aPin->QueryDirection(&pinDir); - NS_ENSURE_TRUE(SUCCEEDED(hr), hr); - - *aOutMatches = (pinDir == aPinDir); - return S_OK; -} - -// Return the first unconnected input pin or output pin. -already_AddRefed -GetUnconnectedPin(IBaseFilter* aFilter, PIN_DIRECTION aPinDir) -{ - RefPtr enumPins; - - HRESULT hr = aFilter->EnumPins(getter_AddRefs(enumPins)); - NS_ENSURE_TRUE(SUCCEEDED(hr), nullptr); - - // Test each pin to see if it matches the direction we're looking for. - RefPtr pin; - while (S_OK == enumPins->Next(1, getter_AddRefs(pin), nullptr)) { - bool matches = FALSE; - if (SUCCEEDED(MatchUnconnectedPin(pin, aPinDir, &matches)) && - matches) { - return pin.forget(); - } - } - - return nullptr; -} - -HRESULT -ConnectFilters(IGraphBuilder* aGraph, - IBaseFilter* aOutputFilter, - IBaseFilter* aInputFilter) -{ - RefPtr output = GetUnconnectedPin(aOutputFilter, PINDIR_OUTPUT); - NS_ENSURE_TRUE(output, E_FAIL); - - RefPtr input = GetUnconnectedPin(aInputFilter, PINDIR_INPUT); - NS_ENSURE_TRUE(output, E_FAIL); - - return aGraph->Connect(output, input); -} - -} // namespace mozilla - -// avoid redefined macro in unified build -#undef WARN diff --git a/dom/media/directshow/DirectShowUtils.h b/dom/media/directshow/DirectShowUtils.h deleted file mode 100644 index 8043c8b30e..0000000000 --- a/dom/media/directshow/DirectShowUtils.h +++ /dev/null @@ -1,134 +0,0 @@ -/* 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/. */ - -#ifndef _DirectShowUtils_h_ -#define _DirectShowUtils_h_ - -#include -#include "dshow.h" - -// XXXbz windowsx.h defines GetFirstChild, GetNextSibling, -// GetPrevSibling are macros, apparently... Eeevil. We have functions -// called that on some classes, so undef them. -#undef GetFirstChild -#undef GetNextSibling -#undef GetPrevSibling - -#include "DShowTools.h" -#include "mozilla/Logging.h" - -namespace mozilla { - -// Win32 "Event" wrapper. Must be paired with a CriticalSection to create a -// Java-style "monitor". -class Signal { -public: - - Signal(CriticalSection* aLock) - : mLock(aLock) - { - CriticalSectionAutoEnter lock(*mLock); - mEvent = CreateEvent(nullptr, FALSE, FALSE, nullptr); - } - - ~Signal() { - CriticalSectionAutoEnter lock(*mLock); - CloseHandle(mEvent); - } - - // Lock must be held. - void Notify() { - SetEvent(mEvent); - } - - // Lock must be held. Check the wait condition before waiting! - HRESULT Wait() { - mLock->Leave(); - DWORD result = WaitForSingleObject(mEvent, INFINITE); - mLock->Enter(); - return result == WAIT_OBJECT_0 ? S_OK : E_FAIL; - } - -private: - CriticalSection* mLock; - HANDLE mEvent; -}; - -HRESULT -AddGraphToRunningObjectTable(IUnknown *aUnkGraph, DWORD *aOutRotRegister); - -void -RemoveGraphFromRunningObjectTable(DWORD aRotRegister); - -const char* -GetGraphNotifyString(long evCode); - -// Creates a filter and adds it to a graph. -HRESULT -CreateAndAddFilter(IGraphBuilder* aGraph, - REFGUID aFilterClsId, - LPCWSTR aFilterName, - IBaseFilter **aOutFilter); - -HRESULT -AddMP3DMOWrapperFilter(IGraphBuilder* aGraph, - IBaseFilter **aOutFilter); - -// Connects the output pin on aOutputFilter to an input pin on -// aInputFilter, in aGraph. -HRESULT -ConnectFilters(IGraphBuilder* aGraph, - IBaseFilter* aOutputFilter, - IBaseFilter* aInputFilter); - -HRESULT -MatchUnconnectedPin(IPin* aPin, - PIN_DIRECTION aPinDir, - bool *aOutMatches); - -// Converts from microseconds to DirectShow "Reference Time" -// (hundreds of nanoseconds). -inline int64_t -UsecsToRefTime(const int64_t aUsecs) -{ - return aUsecs * 10; -} - -// Converts from DirectShow "Reference Time" (hundreds of nanoseconds) -// to microseconds. -inline int64_t -RefTimeToUsecs(const int64_t hRefTime) -{ - return hRefTime / 10; -} - -// Converts from DirectShow "Reference Time" (hundreds of nanoseconds) -// to seconds. -inline double -RefTimeToSeconds(const REFERENCE_TIME aRefTime) -{ - return double(aRefTime) / 10000000; -} - -const char* -GetDirectShowGuidName(const GUID& aGuid); - -// Returns true if we can instantiate an MP3 demuxer and decoder filters. -// Use this to detect whether MP3 support is installed. -bool -CanDecodeMP3UsingDirectShow(); - -// Returns true when a registered DirectShow filter advertises H.264/AVC -// decoding. This works on Windows 2000 because it uses the legacy filter -// enumerator instead of Media Foundation. -bool -CanDecodeH264UsingDirectShow(); - -HRESULT -AddH264DecoderFilter(IGraphBuilder* aGraph, IBaseFilter** aOutFilter); - -} // namespace mozilla - -#endif diff --git a/dom/media/directshow/SampleSink.cpp b/dom/media/directshow/SampleSink.cpp deleted file mode 100644 index fa5dc8d19c..0000000000 --- a/dom/media/directshow/SampleSink.cpp +++ /dev/null @@ -1,159 +0,0 @@ -/* -*- 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" - -using namespace mozilla::media; - -namespace mozilla { - -static LazyLogModule gDirectShowLog("DirectShowDecoder"); -#define LOG(...) MOZ_LOG(gDirectShowLog, mozilla::LogLevel::Debug, (__VA_ARGS__)) - -SampleSink::SampleSink() - : mMonitor("SampleSink"), - mIsFlushing(false), - mAtEOS(false) -{ - MOZ_COUNT_CTOR(SampleSink); -} - -SampleSink::~SampleSink() -{ - MOZ_COUNT_DTOR(SampleSink); -} - -void -SampleSink::SetAudioFormat(const WAVEFORMATEX* aInFormat) -{ - NS_ENSURE_TRUE(aInFormat, ); - ReentrantMonitorAutoEnter mon(mMonitor); - memcpy(&mAudioFormat, aInFormat, sizeof(WAVEFORMATEX)); -} - -void -SampleSink::GetAudioFormat(WAVEFORMATEX* aOutFormat) -{ - MOZ_ASSERT(aOutFormat); - ReentrantMonitorAutoEnter mon(mMonitor); - memcpy(aOutFormat, &mAudioFormat, sizeof(WAVEFORMATEX)); -} - -HRESULT -SampleSink::Receive(IMediaSample* aSample) -{ - ReentrantMonitorAutoEnter mon(mMonitor); - - while (true) { - if (mIsFlushing) { - return S_FALSE; - } - if (!mSample) { - break; - } - if (mAtEOS) { - return E_UNEXPECTED; - } - // Wait until the consumer thread consumes the sample. - mon.Wait(); - } - - if (MOZ_LOG_TEST(gDirectShowLog, LogLevel::Debug)) { - REFERENCE_TIME start = 0, end = 0; - HRESULT hr = aSample->GetMediaTime(&start, &end); - LOG("SampleSink::Receive() [%4.2lf-%4.2lf]", - (double)RefTimeToUsecs(start) / USECS_PER_S, - (double)RefTimeToUsecs(end) / USECS_PER_S); - } - - mSample = aSample; - // Notify the signal, to awaken the consumer thread in WaitForSample() - // if necessary. - mon.NotifyAll(); - return S_OK; -} - -HRESULT -SampleSink::Extract(RefPtr& aOutSample) -{ - ReentrantMonitorAutoEnter mon(mMonitor); - // Loop until we have a sample, or we should abort. - while (true) { - if (mIsFlushing) { - return S_FALSE; - } - if (mSample) { - break; - } - if (mAtEOS) { - // Order is important here, if we have a sample, we should return it - // before reporting EOS. - return E_UNEXPECTED; - } - // Wait until the producer thread gives us a sample. - mon.Wait(); - } - aOutSample = mSample; - - if (MOZ_LOG_TEST(gDirectShowLog, LogLevel::Debug)) { - int64_t start = 0, end = 0; - mSample->GetMediaTime(&start, &end); - LOG("SampleSink::Extract() [%4.2lf-%4.2lf]", - (double)RefTimeToUsecs(start) / USECS_PER_S, - (double)RefTimeToUsecs(end) / USECS_PER_S); - } - - mSample = nullptr; - // Notify the signal, to awaken the producer thread in Receive() - // if necessary. - mon.NotifyAll(); - return S_OK; -} - -void -SampleSink::Flush() -{ - LOG("SampleSink::Flush()"); - ReentrantMonitorAutoEnter mon(mMonitor); - mIsFlushing = true; - mSample = nullptr; - mon.NotifyAll(); -} - -void -SampleSink::Reset() -{ - LOG("SampleSink::Reset()"); - ReentrantMonitorAutoEnter mon(mMonitor); - mIsFlushing = false; - mAtEOS = false; -} - -void -SampleSink::SetEOS() -{ - LOG("SampleSink::SetEOS()"); - ReentrantMonitorAutoEnter mon(mMonitor); - mAtEOS = true; - // Notify to unblock any threads waiting for samples in - // Extract() or Receive(). Now that we're at EOS, no more samples - // will come! - mon.NotifyAll(); -} - -bool -SampleSink::AtEOS() -{ - ReentrantMonitorAutoEnter mon(mMonitor); - return mAtEOS && !mSample; -} - -} // namespace mozilla - diff --git a/dom/media/directshow/SampleSink.h b/dom/media/directshow/SampleSink.h deleted file mode 100644 index 6a1af9fee4..0000000000 --- a/dom/media/directshow/SampleSink.h +++ /dev/null @@ -1,67 +0,0 @@ -/* -*- 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/. */ - -#if !defined(SampleSink_h_) -#define SampleSink_h_ - -#include "BaseFilter.h" -#include "DirectShowUtils.h" -#include "mozilla/RefPtr.h" -#include "mozilla/ReentrantMonitor.h" - -namespace mozilla { - -class SampleSink { -public: - SampleSink(); - virtual ~SampleSink(); - - // Sets the audio format of the incoming samples. The upstream filter - // calls this. This makes a copy. - void SetAudioFormat(const WAVEFORMATEX* aInFormat); - - // Copies the format of incoming audio samples into into *aOutFormat. - void GetAudioFormat(WAVEFORMATEX* aOutFormat); - - // Called when a sample is delivered by the DirectShow graph to the sink. - // The decode thread retrieves the sample by calling WaitForSample(). - // Blocks if there's already a sample waiting to be consumed by the decode - // thread. - HRESULT Receive(IMediaSample* aSample); - - // Retrieves a sample from the sample queue, blocking until one becomes - // available, or until an error occurs. Returns S_FALSE on EOS. - HRESULT Extract(RefPtr& aOutSample); - - // Unblocks any threads waiting in GetSample(). - // Clears mSample, which unblocks upstream stream. - void Flush(); - - // Opens up the sink to receive more samples in PutSample(). - // Clears EOS flag. - void Reset(); - - // Marks that we've reacehd the end of stream. - void SetEOS(); - - // Returns whether we're at end of stream. - bool AtEOS(); - -private: - // All data in this class is syncronized by mMonitor. - ReentrantMonitor mMonitor; - RefPtr mSample; - - // Format of the audio stream we're receiving. - WAVEFORMATEX mAudioFormat; - - bool mIsFlushing; - bool mAtEOS; -}; - -} // namespace mozilla - -#endif // SampleSink_h_ diff --git a/dom/media/directshow/SourceFilter.cpp b/dom/media/directshow/SourceFilter.cpp deleted file mode 100644 index f5ef11ec78..0000000000 --- a/dom/media/directshow/SourceFilter.cpp +++ /dev/null @@ -1,682 +0,0 @@ -/* -*- 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 "SourceFilter.h" -#include "MediaResource.h" -#include "mozilla/RefPtr.h" -#include "DirectShowUtils.h" -#include "mozilla/Logging.h" -#include - -using namespace mozilla::media; - -namespace mozilla { - -// Define to trace what's on... -//#define DEBUG_SOURCE_TRACE 1 - -#if defined (DEBUG_SOURCE_TRACE) -static LazyLogModule gDirectShowLog("DirectShowDecoder"); -#define DIRECTSHOW_LOG(...) MOZ_LOG(gDirectShowLog, mozilla::LogLevel::Debug, (__VA_ARGS__)) -#else -#define DIRECTSHOW_LOG(...) -#endif - -static HRESULT -DoGetInterface(IUnknown* aUnknown, void** aInterface) -{ - if (!aInterface) - return E_POINTER; - *aInterface = aUnknown; - aUnknown->AddRef(); - return S_OK; -} - -// Stores details of IAsyncReader::Request(). -class ReadRequest { -public: - - ReadRequest(IMediaSample* aSample, - DWORD_PTR aDwUser, - uint32_t aOffset, - uint32_t aCount) - : mSample(aSample), - mDwUser(aDwUser), - mOffset(aOffset), - mCount(aCount) - { - MOZ_COUNT_CTOR(ReadRequest); - } - - ~ReadRequest() { - MOZ_COUNT_DTOR(ReadRequest); - } - - RefPtr mSample; - DWORD_PTR mDwUser; - uint32_t mOffset; - uint32_t mCount; -}; - -// A wrapper around media resource that presents only a partition of the -// underlying resource to the caller to use. The partition returned is from -// an offset to the end of stream, and this object deals with ensuring -// the offsets and lengths etc are translated from the reduced partition -// exposed to the caller, to the absolute offsets of the underlying stream. -class MediaResourcePartition { -public: - MediaResourcePartition(MediaResource* aResource, - int64_t aDataStart) - : mResource(aResource), - mDataOffset(aDataStart) - {} - - int64_t GetLength() { - int64_t len = mResource.GetLength(); - if (len == -1) { - return len; - } - return std::max(0, len - mDataOffset); - } - nsresult ReadAt(int64_t aOffset, char* aBuffer, - uint32_t aCount, uint32_t* aBytes) - { - return mResource.ReadAt(aOffset + mDataOffset, - aBuffer, - aCount, - aBytes); - } - int64_t GetCachedDataEnd() { - int64_t tell = mResource.GetResource()->Tell(); - int64_t dataEnd = - mResource.GetResource()->GetCachedDataEnd(tell) - mDataOffset; - return dataEnd; - } -private: - // MediaResource from which we read data. - MediaResourceIndex mResource; - int64_t mDataOffset; -}; - - -// Output pin for SourceFilter, which implements IAsyncReader, to -// allow downstream filters to pull/read data from it. Downstream pins -// register to read data using Request(), and asynchronously wait for the -// reads to complete using WaitForNext(). They may also synchronously read -// using SyncRead(). This class is a delegate (tear off) of -// SourceFilter. -// -// We can expose only a segment of the MediaResource to the filter graph. -// This is used to strip off the ID3v2 tags from the stream, as DirectShow -// has trouble parsing some headers. -// -// Implements: -// * IAsyncReader -// * IPin -// * IQualityControl -// * IUnknown -// -class DECLSPEC_UUID("18e5cfb2-1015-440c-a65c-e63853235894") -OutputPin : public IAsyncReader, - public BasePin -{ -public: - - OutputPin(MediaResource* aMediaResource, - SourceFilter* aParent, - CriticalSection& aFilterLock, - int64_t aMP3DataStart); - virtual ~OutputPin(); - - // IUnknown - // Defer to ref counting to BasePin, which defers to owning nsBaseFilter. - STDMETHODIMP_(ULONG) AddRef() override { return BasePin::AddRef(); } - STDMETHODIMP_(ULONG) Release() override { return BasePin::Release(); } - STDMETHODIMP QueryInterface(REFIID iid, void** ppv) override; - - // BasePin Overrides. - // Determines if the pin accepts a specific media type. - HRESULT CheckMediaType(const MediaType* aMediaType) override; - - // Retrieves a preferred media type, by index value. - HRESULT GetMediaType(int aPosition, MediaType* aMediaType) override; - - // Releases the pin from a connection. - HRESULT BreakConnect(void) override; - - // Determines whether a pin connection is suitable. - HRESULT CheckConnect(IPin* aPin) override; - - - // IAsyncReader overrides - - // The RequestAllocator method requests an allocator during the - // pin connection. - STDMETHODIMP RequestAllocator(IMemAllocator* aPreferred, - ALLOCATOR_PROPERTIES* aProps, - IMemAllocator** aActual) override; - - // The Request method queues an asynchronous request for data. Downstream - // will call WaitForNext() when they want to retrieve the result. - STDMETHODIMP Request(IMediaSample* aSample, DWORD_PTR aUserData) override; - - // The WaitForNext method waits for the next pending read request - // to complete. This method fails if the graph is flushing. - // Defers to SyncRead/5. - STDMETHODIMP WaitForNext(DWORD aTimeout, - IMediaSample** aSamples, - DWORD_PTR* aUserData) override; - - // The SyncReadAligned method performs a synchronous read. The method - // blocks until the request is completed. Defers to SyncRead/5. This - // method does not fail if the graph is flushing. - STDMETHODIMP SyncReadAligned(IMediaSample* aSample) override; - - // The SyncRead method performs a synchronous read. The method blocks - // until the request is completed. Defers to SyncRead/5. This - // method does not fail if the graph is flushing. - STDMETHODIMP SyncRead(LONGLONG aPosition, LONG aLength, BYTE* aBuffer) override; - - // The Length method retrieves the total length of the stream. - STDMETHODIMP Length(LONGLONG* aTotal, LONGLONG* aAvailable) override; - - // IPin Overrides - STDMETHODIMP BeginFlush(void) override; - STDMETHODIMP EndFlush(void) override; - - uint32_t GetAndResetBytesConsumedCount(); - -private: - - // Protects thread-shared data/structures (mFlushCount, mPendingReads). - // WaitForNext() also waits on this monitor - CriticalSection& mPinLock; - - // Signal used with mPinLock to implement WaitForNext(). - Signal mSignal; - - // The filter that owns us. Weak reference, as we're a delegate (tear off). - SourceFilter* mParentSource; - - MediaResourcePartition mResource; - - // Counter, inc'd in BeginFlush(), dec'd in EndFlush(). Calls to this can - // come from multiple threads and can interleave, hence the counter. - int32_t mFlushCount; - - // Number of bytes that have been read from the output pin since the last - // time GetAndResetBytesConsumedCount() was called. - uint32_t mBytesConsumed; - - // Deque of ReadRequest* for reads that are yet to be serviced. - // nsReadRequest's are stored on the heap, popper must delete them. - nsDeque mPendingReads; - - // Flags if the downstream pin has QI'd for IAsyncReader. We refuse - // connection if they don't query, as it means they're assuming that we're - // a push filter, and we're not. - bool mQueriedForAsyncReader; - -}; - -// For mingw __uuidof support -#ifdef __CRT_UUID_DECL -} -__CRT_UUID_DECL(mozilla::OutputPin, 0x18e5cfb2,0x1015,0x440c,0xa6,0x5c,0xe6,0x38,0x53,0x23,0x58,0x94); -namespace mozilla { -#endif - -OutputPin::OutputPin(MediaResource* aResource, - SourceFilter* aParent, - CriticalSection& aFilterLock, - int64_t aMP3DataStart) - : BasePin(static_cast(aParent), - &aFilterLock, - L"MozillaOutputPin", - PINDIR_OUTPUT), - mPinLock(aFilterLock), - mSignal(&mPinLock), - mParentSource(aParent), - mResource(aResource, aMP3DataStart), - mFlushCount(0), - mBytesConsumed(0), - mQueriedForAsyncReader(false) -{ - MOZ_COUNT_CTOR(OutputPin); - DIRECTSHOW_LOG("OutputPin::OutputPin()"); -} - -OutputPin::~OutputPin() -{ - MOZ_COUNT_DTOR(OutputPin); - DIRECTSHOW_LOG("OutputPin::~OutputPin()"); -} - -HRESULT -OutputPin::BreakConnect() -{ - mQueriedForAsyncReader = false; - return BasePin::BreakConnect(); -} - -STDMETHODIMP -OutputPin::QueryInterface(REFIID aIId, void** aInterface) -{ - if (aIId == IID_IAsyncReader) { - mQueriedForAsyncReader = true; - return DoGetInterface(static_cast(this), aInterface); - } - - if (aIId == __uuidof(OutputPin)) { - AddRef(); - *aInterface = this; - return S_OK; - } - - return BasePin::QueryInterface(aIId, aInterface); -} - -HRESULT -OutputPin::CheckConnect(IPin* aPin) -{ - // Our connection is only suitable if the downstream pin knows - // that we're asynchronous (i.e. it queried for IAsyncReader). - return mQueriedForAsyncReader ? S_OK : S_FALSE; -} - -HRESULT -OutputPin::CheckMediaType(const MediaType* aMediaType) -{ - const MediaType *myMediaType = mParentSource->GetMediaType(); - - if (IsEqualGUID(aMediaType->majortype, myMediaType->majortype) && - IsEqualGUID(aMediaType->subtype, myMediaType->subtype) && - IsEqualGUID(aMediaType->formattype, myMediaType->formattype)) - { - DIRECTSHOW_LOG("OutputPin::CheckMediaType() Match: major=%s minor=%s TC=%d FSS=%d SS=%u", - GetDirectShowGuidName(aMediaType->majortype), - GetDirectShowGuidName(aMediaType->subtype), - aMediaType->TemporalCompression(), - aMediaType->bFixedSizeSamples, - aMediaType->SampleSize()); - return S_OK; - } - - DIRECTSHOW_LOG("OutputPin::CheckMediaType() Failed to match: major=%s minor=%s TC=%d FSS=%d SS=%u", - GetDirectShowGuidName(aMediaType->majortype), - GetDirectShowGuidName(aMediaType->subtype), - aMediaType->TemporalCompression(), - aMediaType->bFixedSizeSamples, - aMediaType->SampleSize()); - return S_FALSE; -} - -HRESULT -OutputPin::GetMediaType(int aPosition, MediaType* aMediaType) -{ - if (!aMediaType) - return E_POINTER; - - if (aPosition == 0) { - aMediaType->Assign(mParentSource->GetMediaType()); - return S_OK; - } - return VFW_S_NO_MORE_ITEMS; -} - -static inline bool -IsPowerOf2(int32_t x) { - return ((-x & x) != x); -} - -STDMETHODIMP -OutputPin::RequestAllocator(IMemAllocator* aPreferred, - ALLOCATOR_PROPERTIES* aProps, - IMemAllocator** aActual) -{ - // Require the downstream pin to suggest what they want... - if (!aPreferred) return E_POINTER; - if (!aProps) return E_POINTER; - if (!aActual) return E_POINTER; - - // We only care about alignment - our allocator will reject anything - // which isn't power-of-2 aligned, so so try a 4-byte aligned allocator. - ALLOCATOR_PROPERTIES props; - memcpy(&props, aProps, sizeof(ALLOCATOR_PROPERTIES)); - if (aProps->cbAlign == 0 || IsPowerOf2(aProps->cbAlign)) { - props.cbAlign = 4; - } - - // Limit allocator's number of buffers. We know that the media will most - // likely be bound by network speed, not by decoding speed. We also - // store the incoming data in a Gecko stream, if we don't limit buffers - // here we'll end up duplicating a lot of storage. We must have enough - // space for audio key frames to fit in the first batch of buffers however, - // else pausing may fail for some downstream decoders. - if (props.cBuffers > BaseFilter::sMaxNumBuffers) { - props.cBuffers = BaseFilter::sMaxNumBuffers; - } - - // The allocator properties that are actually used. We don't store - // this, we need it for SetProperties() below to succeed. - ALLOCATOR_PROPERTIES actualProps; - HRESULT hr; - - if (aPreferred) { - // Play nice and prefer the downstream pin's preferred allocator. - hr = aPreferred->SetProperties(&props, &actualProps); - if (SUCCEEDED(hr)) { - aPreferred->AddRef(); - *aActual = aPreferred; - return S_OK; - } - } - - // Else downstream hasn't requested a specific allocator, so create one... - - // Just create a default allocator. It's highly unlikely that we'll use - // this anyway, as most parsers insist on using their own allocators. - RefPtr allocator; - hr = CoCreateInstance(CLSID_MemoryAllocator, - 0, - CLSCTX_INPROC_SERVER, - IID_IMemAllocator, - getter_AddRefs(allocator)); - if(FAILED(hr) || (allocator == nullptr)) { - NS_WARNING("Can't create our own DirectShow allocator."); - return hr; - } - - // See if we can make it suitable - hr = allocator->SetProperties(&props, &actualProps); - if (SUCCEEDED(hr)) { - // We need to release our refcount on pAlloc, and addref - // it to pass a refcount to the caller - this is a net nothing. - allocator.forget(aActual); - return S_OK; - } - - NS_WARNING("Failed to pick an allocator"); - return hr; -} - -STDMETHODIMP -OutputPin::Request(IMediaSample* aSample, DWORD_PTR aDwUser) -{ - if (!aSample) return E_FAIL; - - CriticalSectionAutoEnter lock(*mLock); - NS_ASSERTION(!mFlushCount, "Request() while flushing"); - - if (mFlushCount) - return VFW_E_WRONG_STATE; - - REFERENCE_TIME refStart = 0, refEnd = 0; - if (FAILED(aSample->GetTime(&refStart, &refEnd))) { - NS_WARNING("Sample incorrectly timestamped"); - return VFW_E_SAMPLE_TIME_NOT_SET; - } - - // Convert reference time to bytes. - uint32_t start = (uint32_t)(refStart / 10000000); - uint32_t end = (uint32_t)(refEnd / 10000000); - - uint32_t numBytes = end - start; - - ReadRequest* request = new ReadRequest(aSample, - aDwUser, - start, - numBytes); - // Memory for |request| is free when it's popped from the completed - // reads list. - - // Push this onto the queue of reads to be serviced. - mPendingReads.Push(request); - - // Notify any threads blocked in WaitForNext() which are waiting for mPendingReads - // to become non-empty. - mSignal.Notify(); - - return S_OK; -} - -STDMETHODIMP -OutputPin::WaitForNext(DWORD aTimeout, - IMediaSample** aOutSample, - DWORD_PTR* aOutDwUser) -{ - NS_ASSERTION(aTimeout == 0 || aTimeout == INFINITE, - "Oops, we don't handle this!"); - - *aOutSample = nullptr; - *aOutDwUser = 0; - - LONGLONG offset = 0; - LONG count = 0; - BYTE* buf = nullptr; - - { - CriticalSectionAutoEnter lock(*mLock); - - // Wait until there's a pending read to service. - while (aTimeout && mPendingReads.GetSize() == 0 && !mFlushCount) { - // Note: No need to guard against shutdown-during-wait here, as - // typically the thread doing the pull will have already called - // Request(), so we won't Wait() here anyway. SyncRead() will fail - // on shutdown. - mSignal.Wait(); - } - - nsAutoPtr request(reinterpret_cast(mPendingReads.PopFront())); - if (!request) - return VFW_E_WRONG_STATE; - - *aOutSample = request->mSample; - *aOutDwUser = request->mDwUser; - - offset = request->mOffset; - count = request->mCount; - buf = nullptr; - request->mSample->GetPointer(&buf); - NS_ASSERTION(buf != nullptr, "Invalid buffer!"); - - if (mFlushCount) { - return VFW_E_TIMEOUT; - } - } - - return SyncRead(offset, count, buf); -} - -STDMETHODIMP -OutputPin::SyncReadAligned(IMediaSample* aSample) -{ - { - // Ignore reads while flushing. - CriticalSectionAutoEnter lock(*mLock); - if (mFlushCount) { - return S_FALSE; - } - } - - if (!aSample) - return E_FAIL; - - REFERENCE_TIME lStart = 0, lEnd = 0; - if (FAILED(aSample->GetTime(&lStart, &lEnd))) { - NS_WARNING("Sample incorrectly timestamped"); - return VFW_E_SAMPLE_TIME_NOT_SET; - } - - // Convert reference time to bytes. - int32_t start = (int32_t)(lStart / 10000000); - int32_t end = (int32_t)(lEnd / 10000000); - - int32_t numBytes = end - start; - - // If the range extends off the end of stream, truncate to the end of stream - // as per IAsyncReader specificiation. - int64_t streamLength = mResource.GetLength(); - if (streamLength != -1) { - // We know the exact length of the stream, fail if the requested offset - // is beyond it. - if (start > streamLength) { - return VFW_E_BADALIGN; - } - - // If the end of the chunk to read is off the end of the stream, - // truncate it to the end of the stream. - if ((start + numBytes) > streamLength) { - numBytes = (uint32_t)(streamLength - start); - } - } - - BYTE* buf=0; - aSample->GetPointer(&buf); - - return SyncRead(start, numBytes, buf); -} - -STDMETHODIMP -OutputPin::SyncRead(LONGLONG aPosition, - LONG aLength, - BYTE* aBuffer) -{ - MOZ_ASSERT(!NS_IsMainThread()); - NS_ENSURE_TRUE(aPosition >= 0, E_FAIL); - NS_ENSURE_TRUE(aLength > 0, E_FAIL); - NS_ENSURE_TRUE(aBuffer, E_POINTER); - - DIRECTSHOW_LOG("OutputPin::SyncRead(%lld, %d)", aPosition, aLength); - { - // Ignore reads while flushing. - CriticalSectionAutoEnter lock(*mLock); - if (mFlushCount) { - return S_FALSE; - } - } - - uint32_t totalBytesRead = 0; - nsresult rv = mResource.ReadAt(aPosition, - reinterpret_cast(aBuffer), - aLength, - &totalBytesRead); - if (NS_FAILED(rv)) { - return E_FAIL; - } - if (totalBytesRead > 0) { - CriticalSectionAutoEnter lock(*mLock); - mBytesConsumed += totalBytesRead; - } - return (totalBytesRead == aLength) ? S_OK : S_FALSE; -} - -STDMETHODIMP -OutputPin::Length(LONGLONG* aTotal, LONGLONG* aAvailable) -{ - HRESULT hr = S_OK; - int64_t length = mResource.GetLength(); - if (length == -1) { - hr = VFW_S_ESTIMATED; - // Don't have a length. Just lie, it seems to work... - *aTotal = INT32_MAX; - } else { - *aTotal = length; - } - if (aAvailable) { - *aAvailable = mResource.GetCachedDataEnd(); - } - - DIRECTSHOW_LOG("OutputPin::Length() len=%lld avail=%lld", *aTotal, *aAvailable); - - return hr; -} - -STDMETHODIMP -OutputPin::BeginFlush() -{ - CriticalSectionAutoEnter lock(*mLock); - mFlushCount++; - mSignal.Notify(); - return S_OK; -} - -STDMETHODIMP -OutputPin::EndFlush(void) -{ - CriticalSectionAutoEnter lock(*mLock); - mFlushCount--; - return S_OK; -} - -uint32_t -OutputPin::GetAndResetBytesConsumedCount() -{ - CriticalSectionAutoEnter lock(*mLock); - uint32_t bytesConsumed = mBytesConsumed; - mBytesConsumed = 0; - return bytesConsumed; -} - -SourceFilter::SourceFilter(const GUID& aMajorType, - const GUID& aSubType) - : BaseFilter(L"MozillaDirectShowSource", __uuidof(SourceFilter)) -{ - MOZ_COUNT_CTOR(SourceFilter); - mMediaType.majortype = aMajorType; - mMediaType.subtype = aSubType; - - DIRECTSHOW_LOG("SourceFilter Constructor(%s, %s)", - GetDirectShowGuidName(aMajorType), - GetDirectShowGuidName(aSubType)); -} - -SourceFilter::~SourceFilter() -{ - MOZ_COUNT_DTOR(SourceFilter); - DIRECTSHOW_LOG("SourceFilter Destructor()"); -} - -BasePin* -SourceFilter::GetPin(int n) -{ - if (n == 0) { - NS_ASSERTION(mOutputPin != 0, "GetPin with no pin!"); - return static_cast(mOutputPin); - } else { - return nullptr; - } -} - -// Get's the media type we're supplying. -const MediaType* -SourceFilter::GetMediaType() const -{ - return &mMediaType; -} - -nsresult -SourceFilter::Init(MediaResource* aResource, int64_t aMP3Offset) -{ - DIRECTSHOW_LOG("SourceFilter::Init()"); - - mOutputPin = new OutputPin(aResource, - this, - mLock, - aMP3Offset); - NS_ENSURE_TRUE(mOutputPin != nullptr, NS_ERROR_FAILURE); - - return NS_OK; -} - -uint32_t -SourceFilter::GetAndResetBytesConsumedCount() -{ - return mOutputPin->GetAndResetBytesConsumedCount(); -} - - -} // namespace mozilla diff --git a/dom/media/directshow/SourceFilter.h b/dom/media/directshow/SourceFilter.h deleted file mode 100644 index d5ce2770e9..0000000000 --- a/dom/media/directshow/SourceFilter.h +++ /dev/null @@ -1,75 +0,0 @@ -/* -*- 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/. */ - -#if !defined(nsDirectShowSource_h___) -#define nsDirectShowSource_h___ - -#include "BaseFilter.h" -#include "BasePin.h" -#include "MediaType.h" - -#include "nsDeque.h" -#include "nsAutoPtr.h" -#include "DirectShowUtils.h" -#include "mozilla/RefPtr.h" - -namespace mozilla { - -class MediaResource; -class OutputPin; - - -// SourceFilter is an asynchronous DirectShow source filter which -// reads from an MediaResource, and supplies data via a pull model downstream -// using OutputPin. It us used to supply a generic byte stream into -// DirectShow. -// -// Implements: -// * IBaseFilter -// * IMediaFilter -// * IPersist -// * IUnknown -// -class DECLSPEC_UUID("5c2a7ad0-ba82-4659-9178-c4719a2765d6") -SourceFilter : public media::BaseFilter -{ -public: - - // Constructs source filter to deliver given media type. - SourceFilter(const GUID& aMajorType, const GUID& aSubType); - ~SourceFilter(); - - nsresult Init(MediaResource *aResource, int64_t aMP3Offset); - - // BaseFilter overrides. - // Only one output - the byte stream. - int GetPinCount() override { return 1; } - - media::BasePin* GetPin(int n) override; - - // Get's the media type we're supplying. - const media::MediaType* GetMediaType() const; - - uint32_t GetAndResetBytesConsumedCount(); - -protected: - - // Our async pull output pin. - nsAutoPtr mOutputPin; - - // Type of byte stream we output. - media::MediaType mMediaType; - -}; - -} // namespace mozilla - -// For mingw __uuidof support -#ifdef __CRT_UUID_DECL -__CRT_UUID_DECL(mozilla::SourceFilter, 0x5c2a7ad0,0xba82,0x4659,0x91,0x78,0xc4,0x71,0x9a,0x27,0x65,0xd6); -#endif - -#endif diff --git a/dom/media/directshow/moz.build b/dom/media/directshow/moz.build deleted file mode 100644 index 06cae45fff..0000000000 --- a/dom/media/directshow/moz.build +++ /dev/null @@ -1,42 +0,0 @@ -# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*- -# vim: set filetype=python: -# 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/. - -EXPORTS += [ - 'AudioSinkFilter.h', - 'AudioSinkInputPin.h', - 'DirectShowDecoder.h', - 'DirectShowReader.h', - 'DirectShowUtils.h', -] - -UNIFIED_SOURCES += [ - 'DirectShowDecoder.cpp', - 'DirectShowUtils.cpp', - 'SourceFilter.cpp', -] - -SOURCES += [ - 'AudioSinkFilter.cpp', - 'AudioSinkInputPin.cpp', - 'DirectShowReader.cpp', - 'SampleSink.cpp', -] - -# If WebRTC isn't being built, we need to compile the DirectShow base classes so that -# they're available at link time. -if not CONFIG['MOZ_WEBRTC']: - SOURCES += [ - '/media/webrtc/trunk/webrtc/modules/video_capture/windows/BaseFilter.cpp', - '/media/webrtc/trunk/webrtc/modules/video_capture/windows/BaseInputPin.cpp', - '/media/webrtc/trunk/webrtc/modules/video_capture/windows/BasePin.cpp', - '/media/webrtc/trunk/webrtc/modules/video_capture/windows/MediaType.cpp', - ] - -FINAL_LIBRARY = 'xul' -LOCAL_INCLUDES += [ - '/dom/media', - '/media/webrtc/trunk/webrtc/modules/video_capture/windows', -] diff --git a/dom/media/moz.build b/dom/media/moz.build index bd20936d7a..300c6ae347 100644 --- a/dom/media/moz.build +++ b/dom/media/moz.build @@ -42,12 +42,6 @@ DIRS += [ 'standalone', ] -if CONFIG['MOZ_DIRECTSHOW']: - DIRS += ['directshow'] - LOCAL_INCLUDES += [ - '/media/webrtc/trunk/webrtc/modules/video_capture/windows', - ] - if CONFIG['MOZ_FMP4']: DIRS += ['fmp4'] diff --git a/memory/mozalloc/mozalloc.h b/memory/mozalloc/mozalloc.h index de8c549b31..9c5b693288 100644 --- a/memory/mozalloc/mozalloc.h +++ b/memory/mozalloc/mozalloc.h @@ -33,6 +33,12 @@ #define MOZALLOC_HAVE_XMALLOC +/* Workaround build problems with v142+ MSVC*/ +#if defined(_MSC_VER) +#pragma warning(push) +#pragma warning(disable: 5043) +#endif + /* Workaround build problem with Sun Studio 12 */ #if defined(__SUNPRO_C) || defined(__SUNPRO_CC) # undef MOZ_MUST_USE diff --git a/modules/libpref/init/all.js b/modules/libpref/init/all.js index 1df142b5e5..9fbcbcab9c 100644 --- a/modules/libpref/init/all.js +++ b/modules/libpref/init/all.js @@ -392,11 +392,6 @@ pref("media.wave.play-stand-alone", false); pref("media.hardware-video-decoding.enabled", true); pref("media.hardware-video-decoding.force-enabled", false); -#ifdef MOZ_DIRECTSHOW -pref("media.directshow.enabled", true); -pref("media.directshow.h264.active", false); -#endif - #ifdef MOZ_FMP4 pref("media.mp4.enabled", true); // Specifies whether the PDMFactory can create a test decoder that diff --git a/moz.configure b/moz.configure index ec5b027219..f4cbbed1c8 100644 --- a/moz.configure +++ b/moz.configure @@ -5,16 +5,6 @@ include('build/moz.configure/init.configure') -# DirectShow is the legacy Windows media backend. Keep this independent of -# the old configure scripts so the backend is actually compiled on Windows. -@depends(target) -def directshow_enabled(target): - if target.kernel == 'WINNT': - return True - -set_config('MOZ_DIRECTSHOW', directshow_enabled) -set_define('MOZ_DIRECTSHOW', directshow_enabled) - # Note: # - Gecko-specific options and rules should go in toolkit/moz.configure. # - Firefox-specific options and rules should go in browser/moz.configure. diff --git a/toolkit/content/aboutSupport.js b/toolkit/content/aboutSupport.js index a1825c7cad..9684e80ba7 100644 --- a/toolkit/content/aboutSupport.js +++ b/toolkit/content/aboutSupport.js @@ -337,16 +337,6 @@ var snapshotFormatters = { addRowFromKey("features", "webgl2Extensions"); addRowFromKey("features", "supportsHardwareH264", "hardwareH264"); addRowFromKey("features", "currentAudioBackend", "audioBackend"); - if ("directShowEnabled" in data) { - addRow("features", "directShowEnabled", - strings.GetStringFromName(data.directShowEnabled ? "yes" : "no")); - delete data.directShowEnabled; - } - if ("directShowH264Active" in data) { - addRow("features", "directShowH264Active", - strings.GetStringFromName(data.directShowH264Active ? "yes" : "no")); - delete data.directShowH264Active; - } addRowFromKey("features", "direct2DEnabled", "#Direct2D"); if ("directWriteEnabled" in data) { diff --git a/toolkit/library/moz.build b/toolkit/library/moz.build index 470f10124b..49ff260b47 100644 --- a/toolkit/library/moz.build +++ b/toolkit/library/moz.build @@ -173,9 +173,6 @@ if CONFIG['OS_ARCH'] == 'WINNT': 'crypt32', 'shell32', 'ole32', - 'strmiids', - 'dmoguids', - 'msdmo', 'version', 'winspool', ] diff --git a/toolkit/locales/en-US/chrome/global/aboutSupport.properties b/toolkit/locales/en-US/chrome/global/aboutSupport.properties index 629651d81f..b452514158 100644 --- a/toolkit/locales/en-US/chrome/global/aboutSupport.properties +++ b/toolkit/locales/en-US/chrome/global/aboutSupport.properties @@ -60,8 +60,6 @@ clearTypeParameters = ClearType Parameters compositing = Compositing hardwareH264 = Hardware H264 Decoding audioBackend = Audio Backend -directShowEnabled = DirectShow H264 Backend Enabled -directShowH264Active = DirectShow H264 Decoding Active mainThreadNoOMTC = main thread, no OMTC yes = Yes no = No diff --git a/toolkit/modules/Troubleshoot.jsm b/toolkit/modules/Troubleshoot.jsm index 1cf7333ed5..c25cbce433 100644 --- a/toolkit/modules/Troubleshoot.jsm +++ b/toolkit/modules/Troubleshoot.jsm @@ -358,8 +358,6 @@ var dataProviders = { } catch (e) {} data.currentAudioBackend = winUtils.currentAudioBackend; - data.directShowEnabled = Services.prefs.getBoolPref("media.directshow.enabled", false); - data.directShowH264Active = Services.prefs.getBoolPref("media.directshow.h264.active", false); if (!data.numAcceleratedWindows && gfxInfo) { #ifdef XP_WIN @@ -553,3 +551,4 @@ var dataProviders = { }); } }; +