diff --git a/dom/media/platforms/PDMFactory.cpp b/dom/media/platforms/PDMFactory.cpp index a2e5f23d64e2..f14b8a0bd5d4 100644 --- a/dom/media/platforms/PDMFactory.cpp +++ b/dom/media/platforms/PDMFactory.cpp @@ -96,11 +96,8 @@ PDMFactory::Init() } PDMFactory::PDMFactory() - : mCurrentPDM(CreatePDM()) { - if (!mCurrentPDM || NS_FAILED(mCurrentPDM->Startup())) { - mCurrentPDM = CreateAgnosticDecoderModule(); - } + CreatePDMs(); } PDMFactory::~PDMFactory() @@ -114,25 +111,22 @@ PDMFactory::CreateDecoder(const TrackInfo& aConfig, layers::LayersBackend aLayersBackend, layers::ImageContainer* aImageContainer) { - MOZ_ASSERT(mCurrentPDM); - + nsRefPtr current = GetDecoder(aConfig.mMimeType); nsRefPtr m; - bool hasPlatformDecoder = mCurrentPDM->SupportsMimeType(aConfig.mMimeType); - if (aConfig.GetAsAudioInfo()) { - if (!hasPlatformDecoder && VorbisDataDecoder::IsVorbis(aConfig.mMimeType)) { + if (!current && VorbisDataDecoder::IsVorbis(aConfig.mMimeType)) { m = new VorbisDataDecoder(*aConfig.GetAsAudioInfo(), aTaskQueue, aCallback); - } else if (!hasPlatformDecoder && OpusDataDecoder::IsOpus(aConfig.mMimeType)) { + } else if (!current && OpusDataDecoder::IsOpus(aConfig.mMimeType)) { m = new OpusDataDecoder(*aConfig.GetAsAudioInfo(), aTaskQueue, aCallback); - } else { - m = mCurrentPDM->CreateAudioDecoder(*aConfig.GetAsAudioInfo(), - aTaskQueue, - aCallback); + } else if (current) { + m = current->CreateAudioDecoder(*aConfig.GetAsAudioInfo(), + aTaskQueue, + aCallback); } return m.forget(); } @@ -151,32 +145,34 @@ PDMFactory::CreateDecoder(const TrackInfo& aConfig, callback = callbackWrapper.get(); } - if (H264Converter::IsH264(aConfig)) { - nsRefPtr h - = new H264Converter(mCurrentPDM, - *aConfig.GetAsVideoInfo(), - aLayersBackend, - aImageContainer, - aTaskQueue, - callback); - const nsresult rv = h->GetLastError(); - if (NS_SUCCEEDED(rv) || rv == NS_ERROR_NOT_INITIALIZED) { - // The H264Converter either successfully created the wrapped decoder, - // or there wasn't enough AVCC data to do so. Otherwise, there was some - // problem, for example WMF DLLs were missing. - m = h.forget(); - } - } else if (!hasPlatformDecoder && VPXDecoder::IsVPX(aConfig.mMimeType)) { + if (!current && VPXDecoder::IsVPX(aConfig.mMimeType)) { m = new VPXDecoder(*aConfig.GetAsVideoInfo(), aImageContainer, aTaskQueue, callback); - } else { - m = mCurrentPDM->CreateVideoDecoder(*aConfig.GetAsVideoInfo(), - aLayersBackend, - aImageContainer, - aTaskQueue, - callback); + } else if (current) { + if (H264Converter::IsH264(aConfig)) { + nsRefPtr h + = new H264Converter(current, + *aConfig.GetAsVideoInfo(), + aLayersBackend, + aImageContainer, + aTaskQueue, + callback); + const nsresult rv = h->GetLastError(); + if (NS_SUCCEEDED(rv) || rv == NS_ERROR_NOT_INITIALIZED) { + // The H264Converter either successfully created the wrapped decoder, + // or there wasn't enough AVCC data to do so. Otherwise, there was some + // problem, for example WMF DLLs were missing. + m = h.forget(); + } + } else { + m = current->CreateVideoDecoder(*aConfig.GetAsVideoInfo(), + aLayersBackend, + aImageContainer, + aTaskQueue, + callback); + } } if (callbackWrapper && m) { @@ -189,56 +185,79 @@ PDMFactory::CreateDecoder(const TrackInfo& aConfig, bool PDMFactory::SupportsMimeType(const nsACString& aMimeType) { - MOZ_ASSERT(mCurrentPDM); - return mCurrentPDM->SupportsMimeType(aMimeType) || + nsRefPtr current = GetDecoder(aMimeType); + return current || VPXDecoder::IsVPX(aMimeType) || OpusDataDecoder::IsOpus(aMimeType) || VorbisDataDecoder::IsVorbis(aMimeType); } -already_AddRefed -PDMFactory::CreatePDM() +void +PDMFactory::CreatePDMs() { + nsRefPtr m; + if (sGMPDecoderEnabled) { - nsRefPtr m(new GMPDecoderModule()); - return m.forget(); + m = new GMPDecoderModule(); + StartupPDM(m); } #ifdef MOZ_WIDGET_ANDROID - if(sAndroidMCDecoderPreferred && sAndroidMCDecoderEnabled){ - nsRefPtr m(new AndroidDecoderModule()); - return m.forget(); + if(sAndroidMCDecoderPreferred && sAndroidMCDecoderEnabled) { + m = new AndroidDecoderModule(); + StartupPDM(m); } #endif - if (sUseBlankDecoder) { - return CreateBlankDecoderModule(); - } #ifdef XP_WIN - nsRefPtr m(new WMFDecoderModule()); - return m.forget(); + m = new WMFDecoderModule(); + StartupPDM(m); #endif #ifdef MOZ_FFMPEG - nsRefPtr mffmpeg = FFmpegRuntimeLinker::CreateDecoderModule(); - if (mffmpeg) { - return mffmpeg.forget(); - } + m = FFmpegRuntimeLinker::CreateDecoderModule(); + StartupPDM(m); #endif #ifdef MOZ_APPLEMEDIA - nsRefPtr m(new AppleDecoderModule()); - return m.forget(); + m = new AppleDecoderModule(); + StartupPDM(m); #endif #ifdef MOZ_GONK_MEDIACODEC if (sGonkDecoderEnabled) { - nsRefPtr m(new GonkDecoderModule()); - return m.forget(); + m = new GonkDecoderModule(); + StartupPDM(m); } #endif #ifdef MOZ_WIDGET_ANDROID if(sAndroidMCDecoderEnabled){ - nsRefPtr m(new AndroidDecoderModule()); - return m.forget(); + m = new AndroidDecoderModule(); + StartupPDM(m); } #endif - return nullptr; + if (sUseBlankDecoder) { + m = CreateBlankDecoderModule(); + StartupPDM(m); + } +} + +bool +PDMFactory::StartupPDM(PlatformDecoderModule* aPDM) +{ + if (aPDM && NS_SUCCEEDED(aPDM->Startup())) { + mCurrentPDMs.AppendElement(aPDM); + return true; + } + return false; +} + +already_AddRefed +PDMFactory::GetDecoder(const nsACString& aMimeType) +{ + nsRefPtr pdm; + for (auto& current : mCurrentPDMs) { + if (current->SupportsMimeType(aMimeType)) { + pdm = current; + break; + } + } + return pdm.forget(); } } // namespace mozilla diff --git a/dom/media/platforms/PDMFactory.h b/dom/media/platforms/PDMFactory.h index 2cd70a83bfcc..4f88f215ea4f 100644 --- a/dom/media/platforms/PDMFactory.h +++ b/dom/media/platforms/PDMFactory.h @@ -60,7 +60,11 @@ protected: } private: - already_AddRefed CreatePDM(); + void CreatePDMs(); + // Startup the provided PDM and add it to our list if successful. + bool StartupPDM(PlatformDecoderModule* aPDM); + // Returns the first PDM in our list supporting the mimetype. + already_AddRefed GetDecoder(const nsACString& aMimeType); // Caches pref media.fragmented-mp4.use-blank-decoder static bool sUseBlankDecoder; @@ -72,7 +76,7 @@ private: static uint32_t sVideoOutputMinimumInterval_ms; static bool sDontDelayInputExhausted; - nsRefPtr mCurrentPDM; + nsTArray> mCurrentPDMs; }; } // namespace mozilla