void MediaDecoder::OnDecoderDoctorEvent(DecoderDoctorEvent aEvent) { MOZ_ASSERT(NS_IsMainThread()); // OnDecoderDoctorEvent is disconnected at shutdown time. MOZ_DIAGNOSTIC_ASSERT(!IsShutdown()); nsIDocument* doc = GetOwner()->GetDocument(); if (!doc) { return; } DecoderDoctorDiagnostics diags; diags.StoreEvent(doc, aEvent, __func__); }
/* static */ bool MediaSource::IsTypeSupported(const GlobalObject& aOwner, const nsAString& aType) { MOZ_ASSERT(NS_IsMainThread()); DecoderDoctorDiagnostics diagnostics; nsresult rv = IsTypeSupported(aType, &diagnostics); nsCOMPtr<nsPIDOMWindowInner> window = do_QueryInterface(aOwner.GetAsSupports()); diagnostics.StoreFormatDiagnostics(window ? window->GetExtantDoc() : nullptr, aType, NS_SUCCEEDED(rv), __func__); #define this nullptr MSE_API("IsTypeSupported(aType=%s)%s ", NS_ConvertUTF16toUTF8(aType).get(), rv == NS_OK ? "OK" : "[not supported]"); #undef this // don't ever remove this line ! return NS_SUCCEEDED(rv); }
/* static */ bool MediaSource::IsTypeSupported(const GlobalObject& aOwner, const nsAString& aType) { MOZ_ASSERT(NS_IsMainThread()); DecoderDoctorDiagnostics diagnostics; nsresult rv = IsTypeSupported(aType, &diagnostics); nsCOMPtr<nsPIDOMWindowInner> window = do_QueryInterface(aOwner.GetAsSupports()); diagnostics.StoreFormatDiagnostics(window ? window->GetExtantDoc() : nullptr, aType, NS_SUCCEEDED(rv), __func__); MOZ_LOG(GetMediaSourceAPILog(), mozilla::LogLevel::Debug, ("MediaSource::%s: IsTypeSupported(aType=%s) %s", __func__, NS_ConvertUTF16toUTF8(aType).get(), rv == NS_OK ? "OK" : "[not supported]")); return NS_SUCCEEDED(rv); }
already_AddRefed<MediaDataDecoder> PDMFactory::CreateDecoder(const CreateDecoderParams& aParams) { if (aParams.mUseBlankDecoder) { MOZ_ASSERT(mBlankPDM); return CreateDecoderWithPDM(mBlankPDM, aParams); } const TrackInfo& config = aParams.mConfig; bool isEncrypted = mEMEPDM && config.mCrypto.mValid; if (isEncrypted) { return CreateDecoderWithPDM(mEMEPDM, aParams); } DecoderDoctorDiagnostics* diagnostics = aParams.mDiagnostics; if (diagnostics) { // If libraries failed to load, the following loop over mCurrentPDMs // will not even try to use them. So we record failures now. if (mWMFFailedToLoad) { diagnostics->SetWMFFailedToLoad(); } if (mFFmpegFailedToLoad) { diagnostics->SetFFmpegFailedToLoad(); } if (mGMPPDMFailedToStartup) { diagnostics->SetGMPPDMFailedToStartup(); } } for (auto& current : mCurrentPDMs) { if (!current->SupportsMimeType(config.mMimeType, diagnostics)) { continue; } RefPtr<MediaDataDecoder> m = CreateDecoderWithPDM(current, aParams); if (m) { return m.forget(); } } NS_WARNING("Unable to create a decoder, no platform found."); return nullptr; }
already_AddRefed<SourceBuffer> MediaSource::AddSourceBuffer(const nsAString& aType, ErrorResult& aRv) { MOZ_ASSERT(NS_IsMainThread()); DecoderDoctorDiagnostics diagnostics; nsresult rv = IsTypeSupported(aType, &diagnostics); diagnostics.StoreFormatDiagnostics(GetOwner() ? GetOwner()->GetExtantDoc() : nullptr, aType, NS_SUCCEEDED(rv), __func__); MSE_API("AddSourceBuffer(aType=%s)%s", NS_ConvertUTF16toUTF8(aType).get(), rv == NS_OK ? "" : " [not supported]"); if (NS_FAILED(rv)) { aRv.Throw(rv); return nullptr; } if (mSourceBuffers->Length() >= MAX_SOURCE_BUFFERS) { aRv.Throw(NS_ERROR_DOM_QUOTA_EXCEEDED_ERR); return nullptr; } if (mReadyState != MediaSourceReadyState::Open) { aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR); return nullptr; } Maybe<MediaContainerType> containerType = MakeMediaContainerType(aType); if (!containerType) { aRv.Throw(NS_ERROR_DOM_NOT_SUPPORTED_ERR); return nullptr; } RefPtr<SourceBuffer> sourceBuffer = new SourceBuffer(this, *containerType); if (!sourceBuffer) { aRv.Throw(NS_ERROR_FAILURE); // XXX need a better error here return nullptr; } mSourceBuffers->Append(sourceBuffer); DDLINKCHILD("sourcebuffer[]", sourceBuffer.get()); MSE_DEBUG("sourceBuffer=%p", sourceBuffer.get()); return sourceBuffer.forget(); }
already_AddRefed<MediaDataDecoder> PDMFactory::CreateDecoderWithPDM(PlatformDecoderModule* aPDM, const CreateDecoderParams& aParams) { MOZ_ASSERT(aPDM); RefPtr<MediaDataDecoder> m; SupportChecker supportChecker; const TrackInfo& config = aParams.mConfig; supportChecker.AddMediaFormatChecker(config); auto reason = supportChecker.Check(); if (reason != SupportChecker::Result::kSupported) { DecoderDoctorDiagnostics* diagnostics = aParams.mDiagnostics; if (diagnostics) { if (reason == SupportChecker::Result::kVideoFormatNotSupported) { diagnostics->SetVideoFormatNotSupport(); } else if (reason == SupportChecker::Result::kAudioFormatNotSupported) { diagnostics->SetAudioFormatNotSupport(); } } return nullptr; } if (config.IsAudio()) { m = aPDM->CreateAudioDecoder(aParams); return m.forget(); } if (!config.IsVideo()) { return nullptr; } MediaDataDecoderCallback* callback = aParams.mCallback; RefPtr<DecoderCallbackFuzzingWrapper> callbackWrapper; if (MediaPrefs::PDMFuzzingEnabled()) { callbackWrapper = new DecoderCallbackFuzzingWrapper(callback); callbackWrapper->SetVideoOutputMinimumInterval( TimeDuration::FromMilliseconds(MediaPrefs::PDMFuzzingInterval())); callbackWrapper->SetDontDelayInputExhausted(!MediaPrefs::PDMFuzzingDelayInputExhausted()); callback = callbackWrapper.get(); } CreateDecoderParams params = aParams; params.mCallback = callback; if (MP4Decoder::IsH264(config.mMimeType) && !aParams.mUseBlankDecoder) { RefPtr<H264Converter> h = new H264Converter(aPDM, params); 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 = aPDM->CreateVideoDecoder(params); } if (callbackWrapper && m) { m = new DecoderFuzzingWrapper(m.forget(), callbackWrapper.forget()); } return m.forget(); }
already_AddRefed<MediaDataDecoder> PDMFactory::CreateDecoderWithPDM(PlatformDecoderModule* aPDM, const CreateDecoderParams& aParams) { MOZ_ASSERT(aPDM); RefPtr<MediaDataDecoder> m; MediaResult* result = aParams.mError; SupportChecker supportChecker; const TrackInfo& config = aParams.mConfig; supportChecker.AddMediaFormatChecker(config); auto checkResult = supportChecker.Check(); if (checkResult.mReason != SupportChecker::Reason::kSupported) { DecoderDoctorDiagnostics* diagnostics = aParams.mDiagnostics; if (checkResult.mReason == SupportChecker::Reason::kVideoFormatNotSupported) { if (diagnostics) { diagnostics->SetVideoNotSupported(); } if (result) { *result = checkResult.mMediaResult; } } else if (checkResult.mReason == SupportChecker::Reason::kAudioFormatNotSupported) { if (diagnostics) { diagnostics->SetAudioNotSupported(); } if (result) { *result = checkResult.mMediaResult; } } return nullptr; } if (config.IsAudio()) { m = aPDM->CreateAudioDecoder(aParams); return m.forget(); } if (!config.IsVideo()) { *result = MediaResult( NS_ERROR_DOM_MEDIA_FATAL_ERR, RESULT_DETAIL("Decoder configuration error, expected audio or video.")); return nullptr; } if (MP4Decoder::IsH264(config.mMimeType) && !aParams.mUseNullDecoder) { RefPtr<H264Converter> h = new H264Converter(aPDM, aParams); 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 = aPDM->CreateVideoDecoder(aParams); } return m.forget(); }