diff --git a/dom/media/MediaFormatReader.cpp b/dom/media/MediaFormatReader.cpp index a4578f7c6fbf..62b671c76fac 100644 --- a/dom/media/MediaFormatReader.cpp +++ b/dom/media/MediaFormatReader.cpp @@ -380,10 +380,13 @@ MediaFormatReader::EnsureDecoderCreated(TrackType aTrack) MOZ_ASSERT(OnTaskQueue()); MOZ_DIAGNOSTIC_ASSERT(!IsSuspended()); + auto decoderCreatingError = "error creating decoder"; + MediaResult result = MediaResult(NS_ERROR_DOM_MEDIA_FATAL_ERR, decoderCreatingError); auto& decoder = GetDecoderData(aTrack); if (decoder.mDecoder) { - return NS_OK; + result = NS_OK; + return result; } if (!mPlatform) { @@ -405,7 +408,8 @@ MediaFormatReader::EnsureDecoderCreated(TrackType aTrack) decoder.mTaskQueue, decoder.mCallback.get(), mCrashHelper, - decoder.mIsBlankDecode + decoder.mIsBlankDecode, + &result }); break; } @@ -420,19 +424,22 @@ MediaFormatReader::EnsureDecoderCreated(TrackType aTrack) mLayersBackendType, GetImageContainer(), mCrashHelper, - decoder.mIsBlankDecode + decoder.mIsBlankDecode, + &result }); break; } default: break; } - if (decoder.mDecoder ) { + if (decoder.mDecoder) { decoder.mDescription = decoder.mDecoder->GetDescriptionName(); - return NS_OK; + result = MediaResult(NS_OK); + return result; } - decoder.mDescription = "error creating decoder"; - return MediaResult(NS_ERROR_DOM_MEDIA_FATAL_ERR, "error creating decoder"); + + decoder.mDescription = decoderCreatingError; + return result; } bool diff --git a/dom/media/platforms/PDMFactory.cpp b/dom/media/platforms/PDMFactory.cpp index ee11eab2edfb..922ab4ae6756 100644 --- a/dom/media/platforms/PDMFactory.cpp +++ b/dom/media/platforms/PDMFactory.cpp @@ -83,7 +83,7 @@ StaticMutex PDMFactory::sMonitor; class SupportChecker { public: - enum class Result : uint8_t + enum class Reason : uint8_t { kSupported, kVideoFormatNotSupported, @@ -91,6 +91,22 @@ public: kUnknown, }; + struct CheckResult + { + explicit CheckResult(Reason aReason, + MediaResult aResult = MediaResult(NS_OK)) + : mReason(aReason), + mMediaResult(mozilla::Move(aResult)) + {} + CheckResult(const CheckResult& aOther) = default; + CheckResult(CheckResult&& aOther) = default; + CheckResult& operator=(const CheckResult& aOther) = default; + CheckResult& operator=(CheckResult&& aOther) = default; + + Reason mReason; + MediaResult mMediaResult; + }; + template void AddToCheckList(Func&& aChecker) @@ -113,30 +129,34 @@ public: // For consistency, all decoders should be checked. if (mp4_demuxer::H264::DecodeSPSFromExtraData(extraData, spsdata) && spsdata.chroma_format_idc == PDMFactory::kYUV444) { - return SupportChecker::Result::kVideoFormatNotSupported; + return CheckResult(SupportChecker::Reason::kVideoFormatNotSupported, + MediaResult(NS_ERROR_DOM_MEDIA_FATAL_ERR, + RESULT_DETAIL("Decoder may not have the capability to handle" + " the requested video format" + " with YUV444 chroma subsampling."))); } } - return SupportChecker::Result::kSupported; + return CheckResult(SupportChecker::Reason::kSupported); }); } } - SupportChecker::Result + SupportChecker::CheckResult Check() { for (auto& checker : mCheckerList) { auto result = checker(); - if (result != SupportChecker::Result::kSupported) { + if (result.mReason != SupportChecker::Reason::kSupported) { return result; } } - return SupportChecker::Result::kSupported; + return CheckResult(SupportChecker::Reason::kSupported); } void Clear() { mCheckerList.Clear(); } private: - nsTArray> mCheckerList; + nsTArray> mCheckerList; }; // SupportChecker PDMFactory::PDMFactory() @@ -229,20 +249,29 @@ PDMFactory::CreateDecoderWithPDM(PlatformDecoderModule* aPDM, { MOZ_ASSERT(aPDM); RefPtr m; + MediaResult* result = aParams.mError; SupportChecker supportChecker; const TrackInfo& config = aParams.mConfig; supportChecker.AddMediaFormatChecker(config); - auto reason = supportChecker.Check(); - if (reason != SupportChecker::Result::kSupported) { + auto checkResult = supportChecker.Check(); + if (checkResult.mReason != SupportChecker::Reason::kSupported) { DecoderDoctorDiagnostics* diagnostics = aParams.mDiagnostics; - if (diagnostics) { - if (reason == SupportChecker::Result::kVideoFormatNotSupported) { + if (checkResult.mReason == SupportChecker::Reason::kVideoFormatNotSupported) { + if (diagnostics) { diagnostics->SetVideoNotSupported(); - } else if (reason == SupportChecker::Result::kAudioFormatNotSupported) { + } + if (result) { + *result = checkResult.mMediaResult; + } + } else if (checkResult.mReason == SupportChecker::Reason::kAudioFormatNotSupported) { + if (diagnostics) { diagnostics->SetAudioNotSupported(); } + if (result) { + *result = checkResult.mMediaResult; + } } return nullptr; } @@ -253,6 +282,8 @@ PDMFactory::CreateDecoderWithPDM(PlatformDecoderModule* aPDM, } if (!config.IsVideo()) { + *result = MediaResult(NS_ERROR_DOM_MEDIA_FATAL_ERR, + RESULT_DETAIL("Decoder configuration error, expected audio or video.")); return nullptr; } diff --git a/dom/media/platforms/PlatformDecoderModule.h b/dom/media/platforms/PlatformDecoderModule.h index 0f3877204c3c..a3f48b62c883 100644 --- a/dom/media/platforms/PlatformDecoderModule.h +++ b/dom/media/platforms/PlatformDecoderModule.h @@ -34,7 +34,7 @@ class CDMProxy; static LazyLogModule sPDMLog("PlatformDecoderModule"); -struct CreateDecoderParams { +struct MOZ_STACK_CLASS CreateDecoderParams final { explicit CreateDecoderParams(const TrackInfo& aConfig) : mConfig(aConfig) {} @@ -63,6 +63,7 @@ struct CreateDecoderParams { MediaDataDecoderCallback* mCallback = nullptr; DecoderDoctorDiagnostics* mDiagnostics = nullptr; layers::ImageContainer* mImageContainer = nullptr; + MediaResult* mError = nullptr; layers::LayersBackend mLayersBackend = layers::LayersBackend::LAYERS_NONE; RefPtr mCrashHelper; bool mUseBlankDecoder = false; @@ -72,6 +73,7 @@ private: void Set(MediaDataDecoderCallback* aCallback) { mCallback = aCallback; } void Set(DecoderDoctorDiagnostics* aDiagnostics) { mDiagnostics = aDiagnostics; } void Set(layers::ImageContainer* aImageContainer) { mImageContainer = aImageContainer; } + void Set(MediaResult* aError) { mError = aError; } void Set(layers::LayersBackend aLayersBackend) { mLayersBackend = aLayersBackend; } void Set(GMPCrashHelper* aCrashHelper) { mCrashHelper = aCrashHelper; } void Set(bool aUseBlankDecoder) { mUseBlankDecoder = aUseBlankDecoder; }