diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-28 14:29:10 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-28 14:29:10 +0000 |
commit | 2aa4a82499d4becd2284cdb482213d541b8804dd (patch) | |
tree | b80bf8bf13c3766139fbacc530efd0dd9d54394c /dom/media/ipc/RemoteDecoderManagerChild.cpp | |
parent | Initial commit. (diff) | |
download | firefox-2aa4a82499d4becd2284cdb482213d541b8804dd.tar.xz firefox-2aa4a82499d4becd2284cdb482213d541b8804dd.zip |
Adding upstream version 86.0.1.upstream/86.0.1upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'dom/media/ipc/RemoteDecoderManagerChild.cpp')
-rw-r--r-- | dom/media/ipc/RemoteDecoderManagerChild.cpp | 619 |
1 files changed, 619 insertions, 0 deletions
diff --git a/dom/media/ipc/RemoteDecoderManagerChild.cpp b/dom/media/ipc/RemoteDecoderManagerChild.cpp new file mode 100644 index 0000000000..50e80e7a33 --- /dev/null +++ b/dom/media/ipc/RemoteDecoderManagerChild.cpp @@ -0,0 +1,619 @@ +/* -*- 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 "RemoteDecoderManagerChild.h" + +#include "PDMFactory.h" +#include "RemoteAudioDecoder.h" +#include "RemoteMediaDataDecoder.h" +#include "RemoteVideoDecoder.h" +#include "VideoUtils.h" +#include "mozilla/DataMutex.h" +#include "mozilla/SyncRunnable.h" +#include "mozilla/dom/ContentChild.h" // for launching RDD w/ ContentChild +#include "mozilla/gfx/2D.h" +#include "mozilla/gfx/DataSurfaceHelpers.h" +#include "mozilla/ipc/BackgroundChild.h" +#include "mozilla/ipc/PBackgroundChild.h" +#include "mozilla/ipc/Endpoint.h" +#include "mozilla/layers/ISurfaceAllocator.h" +#include "nsContentUtils.h" +#include "nsIObserver.h" + +namespace mozilla { + +using namespace layers; +using namespace gfx; + +// Used so that we only ever attempt to check if the RDD process should be +// launched serially. Protects sLaunchPromise +StaticMutex sLaunchMutex; +static StaticRefPtr<GenericNonExclusivePromise> sLaunchRDDPromise; + +// Only modified on the main-thread, read on any thread. While it could be read +// on the main thread directly, for clarity we force access via the DataMutex +// wrapper. +static StaticDataMutex<StaticRefPtr<nsIThread>> + sRemoteDecoderManagerChildThread("sRemoteDecoderManagerChildThread"); + +// Only accessed from sRemoteDecoderManagerChildThread +static StaticRefPtr<RemoteDecoderManagerChild> + sRemoteDecoderManagerChildForRDDProcess; + +static StaticRefPtr<RemoteDecoderManagerChild> + sRemoteDecoderManagerChildForGPUProcess; +static UniquePtr<nsTArray<RefPtr<Runnable>>> sRecreateTasks; + +static StaticDataMutex<Maybe<PDMFactory::MediaCodecsSupported>> sGPUSupported( + "RDMC::sGPUSupported"); +static StaticDataMutex<Maybe<PDMFactory::MediaCodecsSupported>> sRDDSupported( + "RDMC::sRDDSupported"); + +class ShutdownObserver final : public nsIObserver { + public: + NS_DECL_ISUPPORTS + NS_DECL_NSIOBSERVER + + protected: + ~ShutdownObserver() = default; +}; +NS_IMPL_ISUPPORTS(ShutdownObserver, nsIObserver); + +NS_IMETHODIMP +ShutdownObserver::Observe(nsISupports* aSubject, const char* aTopic, + const char16_t* aData) { + MOZ_ASSERT(!strcmp(aTopic, NS_XPCOM_SHUTDOWN_OBSERVER_ID)); + RemoteDecoderManagerChild::Shutdown(); + return NS_OK; +} + +StaticRefPtr<ShutdownObserver> sObserver; + +/* static */ +void RemoteDecoderManagerChild::Init() { + MOZ_ASSERT(NS_IsMainThread()); + + auto remoteDecoderManagerThread = sRemoteDecoderManagerChildThread.Lock(); + if (!*remoteDecoderManagerThread) { + // We can't use a MediaThreadType::SUPERVISOR as the RemoteDecoderModule + // runs on it and dispatch synchronous tasks to the manager thread, should + // more than 4 concurrent videos being instantiated at the same time, we + // could end up in a deadlock. + RefPtr<nsIThread> childThread; + nsresult rv = NS_NewNamedThread( + "RemVidChild", getter_AddRefs(childThread), + NS_NewRunnableFunction( + "RemoteDecoderManagerChild::InitPBackground", []() { + ipc::PBackgroundChild* bgActor = + ipc::BackgroundChild::GetOrCreateForCurrentThread(); + NS_ASSERTION(bgActor, "Failed to start Background channel"); + Unused << bgActor; + })); + + NS_ENSURE_SUCCESS_VOID(rv); + *remoteDecoderManagerThread = childThread; + sRecreateTasks = MakeUnique<nsTArray<RefPtr<Runnable>>>(); + sObserver = new ShutdownObserver(); + nsContentUtils::RegisterShutdownObserver(sObserver); + } +} + +/* static */ +void RemoteDecoderManagerChild::InitForGPUProcess( + Endpoint<PRemoteDecoderManagerChild>&& aVideoManager) { + MOZ_ASSERT(NS_IsMainThread()); + + Init(); + + auto remoteDecoderManagerThread = sRemoteDecoderManagerChildThread.Lock(); + MOZ_ALWAYS_SUCCEEDS((*remoteDecoderManagerThread) + ->Dispatch(NewRunnableFunction( + "InitForContentRunnable", &OpenForGPUProcess, + std::move(aVideoManager)))); +} + +/* static */ +void RemoteDecoderManagerChild::Shutdown() { + MOZ_ASSERT(NS_IsMainThread()); + + if (sObserver) { + nsContentUtils::UnregisterShutdownObserver(sObserver); + sObserver = nullptr; + } + + nsCOMPtr<nsIThread> childThread; + { + auto remoteDecoderManagerThread = sRemoteDecoderManagerChildThread.Lock(); + childThread = remoteDecoderManagerThread->forget(); + } + if (childThread) { + MOZ_ALWAYS_SUCCEEDS(childThread->Dispatch(NS_NewRunnableFunction( + "dom::RemoteDecoderManagerChild::Shutdown", []() { + if (sRemoteDecoderManagerChildForRDDProcess && + sRemoteDecoderManagerChildForRDDProcess->CanSend()) { + sRemoteDecoderManagerChildForRDDProcess->Close(); + } + sRemoteDecoderManagerChildForRDDProcess = nullptr; + if (sRemoteDecoderManagerChildForGPUProcess && + sRemoteDecoderManagerChildForGPUProcess->CanSend()) { + sRemoteDecoderManagerChildForGPUProcess->Close(); + } + sRemoteDecoderManagerChildForGPUProcess = nullptr; + ipc::BackgroundChild::CloseForCurrentThread(); + }))); + childThread->Shutdown(); + sRecreateTasks = nullptr; + } +} + +void RemoteDecoderManagerChild::RunWhenGPUProcessRecreated( + already_AddRefed<Runnable> aTask) { + nsCOMPtr<nsISerialEventTarget> managerThread = GetManagerThread(); + if (!managerThread) { + // We've been shutdown, bail. + return; + } + MOZ_ASSERT(managerThread->IsOnCurrentThread()); + + // If we've already been recreated, then run the task immediately. + auto* manager = GetSingleton(RemoteDecodeIn::GpuProcess); + if (manager && manager != this && manager->CanSend()) { + RefPtr<Runnable> task = aTask; + task->Run(); + } else { + sRecreateTasks->AppendElement(aTask); + } +} + +/* static */ +RemoteDecoderManagerChild* RemoteDecoderManagerChild::GetSingleton( + RemoteDecodeIn aLocation) { + nsCOMPtr<nsISerialEventTarget> managerThread = GetManagerThread(); + if (!managerThread) { + // We've been shutdown, bail. + return nullptr; + } + MOZ_ASSERT(managerThread->IsOnCurrentThread()); + switch (aLocation) { + case RemoteDecodeIn::GpuProcess: + return sRemoteDecoderManagerChildForGPUProcess; + case RemoteDecodeIn::RddProcess: + return sRemoteDecoderManagerChildForRDDProcess; + default: + MOZ_CRASH("Unexpected RemoteDecode variant"); + } +} + +/* static */ +nsISerialEventTarget* RemoteDecoderManagerChild::GetManagerThread() { + auto remoteDecoderManagerThread = sRemoteDecoderManagerChildThread.Lock(); + return *remoteDecoderManagerThread; +} + +/* static */ +bool RemoteDecoderManagerChild::Supports( + RemoteDecodeIn aLocation, const SupportDecoderParams& aParams, + DecoderDoctorDiagnostics* aDiagnostics) { + Maybe<PDMFactory::MediaCodecsSupported> supported; + switch (aLocation) { + case RemoteDecodeIn::RddProcess: { + auto supportedRDD = sRDDSupported.Lock(); + supported = *supportedRDD; + break; + } + case RemoteDecodeIn::GpuProcess: { + auto supportedGPU = sGPUSupported.Lock(); + supported = *supportedGPU; + break; + } + default: + return false; + } + if (!supported) { + // We haven't received the correct information yet from either the GPU or + // the RDD process; assume it is supported to prevent false negative. + if (aLocation == RemoteDecodeIn::RddProcess) { + // Ensure the RDD process got started. + // TODO: This can be removed once bug 1684991 is fixed. + LaunchRDDProcessIfNeeded(); + } + return true; + } + + // We can ignore the SupportDecoderParams argument for now as creation of the + // decoder will actually fail later and fallback PDMs will be tested on later. + return PDMFactory::SupportsMimeType(aParams.MimeType(), *supported); +} + +/* static */ +RefPtr<PlatformDecoderModule::CreateDecoderPromise> +RemoteDecoderManagerChild::CreateAudioDecoder( + const CreateDecoderParams& aParams) { + nsCOMPtr<nsISerialEventTarget> managerThread = GetManagerThread(); + if (!managerThread) { + // We got shutdown. + return PlatformDecoderModule::CreateDecoderPromise::CreateAndReject( + NS_ERROR_DOM_MEDIA_CANCELED, __func__); + } + return LaunchRDDProcessIfNeeded()->Then( + managerThread, __func__, + [params = CreateDecoderParamsForAsync(aParams)](bool) { + auto child = MakeRefPtr<RemoteAudioDecoderChild>(); + MediaResult result = + child->InitIPDL(params.AudioConfig(), params.mOptions); + if (NS_FAILED(result)) { + return PlatformDecoderModule::CreateDecoderPromise::CreateAndReject( + result, __func__); + } + return Construct(std::move(child)); + }, + [](nsresult aResult) { + return PlatformDecoderModule::CreateDecoderPromise::CreateAndReject( + MediaResult(aResult, "Couldn't start RDD process"), __func__); + }); +} + +/* static */ +RefPtr<PlatformDecoderModule::CreateDecoderPromise> +RemoteDecoderManagerChild::CreateVideoDecoder( + const CreateDecoderParams& aParams, RemoteDecodeIn aLocation) { + nsCOMPtr<nsISerialEventTarget> managerThread = GetManagerThread(); + if (!managerThread) { + // We got shutdown. + return PlatformDecoderModule::CreateDecoderPromise::CreateAndReject( + NS_ERROR_DOM_MEDIA_CANCELED, __func__); + } + + if (!aParams.mKnowsCompositor && aLocation == RemoteDecodeIn::GpuProcess) { + // We don't have an image bridge; don't attempt to decode in the GPU + // process. + return PlatformDecoderModule::CreateDecoderPromise::CreateAndReject( + NS_ERROR_DOM_MEDIA_NOT_SUPPORTED_ERR, __func__); + } + + MOZ_ASSERT(aLocation != RemoteDecodeIn::Unspecified); + + RefPtr<GenericNonExclusivePromise> p = + aLocation == RemoteDecodeIn::GpuProcess + ? GenericNonExclusivePromise::CreateAndResolve(true, __func__) + : LaunchRDDProcessIfNeeded(); + + return p->Then( + managerThread, __func__, + [aLocation, params = CreateDecoderParamsForAsync(aParams)](bool) { + auto child = MakeRefPtr<RemoteVideoDecoderChild>(aLocation); + MediaResult result = child->InitIPDL( + params.VideoConfig(), params.mRate.mValue, params.mOptions, + params.mKnowsCompositor + ? Some(params.mKnowsCompositor->GetTextureFactoryIdentifier()) + : Nothing()); + if (NS_FAILED(result)) { + return PlatformDecoderModule::CreateDecoderPromise::CreateAndReject( + result, __func__); + } + return Construct(std::move(child)); + }, + [](nsresult aResult) { + return PlatformDecoderModule::CreateDecoderPromise::CreateAndReject( + MediaResult(aResult, "Couldn't start RDD process"), __func__); + }); +} + +/* static */ +RefPtr<PlatformDecoderModule::CreateDecoderPromise> +RemoteDecoderManagerChild::Construct(RefPtr<RemoteDecoderChild>&& aChild) { + nsCOMPtr<nsISerialEventTarget> managerThread = GetManagerThread(); + if (!managerThread) { + // We got shutdown. + return PlatformDecoderModule::CreateDecoderPromise::CreateAndReject( + NS_ERROR_DOM_MEDIA_CANCELED, __func__); + } + MOZ_ASSERT(managerThread->IsOnCurrentThread()); + + RefPtr<PlatformDecoderModule::CreateDecoderPromise> p = + aChild->SendConstruct()->Then( + managerThread, __func__, + [child = std::move(aChild)](MediaResult aResult) { + if (NS_FAILED(aResult)) { + // We will never get to use this remote decoder, tear it down. + child->DestroyIPDL(); + return PlatformDecoderModule::CreateDecoderPromise:: + CreateAndReject(aResult, __func__); + } + return PlatformDecoderModule::CreateDecoderPromise:: + CreateAndResolve(MakeRefPtr<RemoteMediaDataDecoder>(child), + __func__); + }, + [](const mozilla::ipc::ResponseRejectReason& aReason) { + // The parent has died. + return PlatformDecoderModule::CreateDecoderPromise::CreateAndReject( + NS_ERROR_DOM_MEDIA_NEED_NEW_DECODER, __func__); + }); + return p; +} + +/* static */ +RefPtr<GenericNonExclusivePromise> +RemoteDecoderManagerChild::LaunchRDDProcessIfNeeded() { + MOZ_DIAGNOSTIC_ASSERT(XRE_IsContentProcess(), + "Only supported from a content process."); + + nsCOMPtr<nsISerialEventTarget> managerThread = GetManagerThread(); + if (!managerThread) { + // We got shutdown. + return GenericNonExclusivePromise::CreateAndReject(NS_ERROR_FAILURE, + __func__); + } + + StaticMutexAutoLock lock(sLaunchMutex); + + if (sLaunchRDDPromise) { + return sLaunchRDDPromise; + } + + // We have a couple possible states here. We are in a content process + // and: + // 1) the RDD process has never been launched. RDD should be launched + // and the IPC connections setup. + // 2) the RDD process has been launched, but this particular content + // process has not setup (or has lost) its IPC connection. + // In the code below, we assume we need to launch the RDD process and + // setup the IPC connections. However, if the manager thread for + // RemoteDecoderManagerChild is available we do a quick check to see + // if we can send (meaning the IPC channel is open). If we can send, + // then no work is necessary. If we can't send, then we call + // LaunchRDDProcess which will launch RDD if necessary, and setup the + // IPC connections between *this* content process and the RDD process. + + RefPtr<GenericNonExclusivePromise> p = InvokeAsync( + managerThread, __func__, []() -> RefPtr<GenericNonExclusivePromise> { + auto* rps = GetSingleton(RemoteDecodeIn::RddProcess); + if (rps && rps->CanSend()) { + return GenericNonExclusivePromise::CreateAndResolve(true, __func__); + } + nsCOMPtr<nsISerialEventTarget> managerThread = GetManagerThread(); + ipc::PBackgroundChild* bgActor = + ipc::BackgroundChild::GetForCurrentThread(); + if (!managerThread || NS_WARN_IF(!bgActor)) { + return GenericNonExclusivePromise::CreateAndReject(NS_ERROR_FAILURE, + __func__); + } + + return bgActor->SendEnsureRDDProcessAndCreateBridge()->Then( + managerThread, __func__, + [](ipc::PBackgroundChild::EnsureRDDProcessAndCreateBridgePromise:: + ResolveOrRejectValue&& aResult) { + nsCOMPtr<nsISerialEventTarget> managerThread = GetManagerThread(); + if (!managerThread || aResult.IsReject()) { + // The parent process died or we got shutdown + return GenericNonExclusivePromise::CreateAndReject( + NS_ERROR_FAILURE, __func__); + } + nsresult rv = Get<0>(aResult.ResolveValue()); + if (NS_FAILED(rv)) { + return GenericNonExclusivePromise::CreateAndReject(rv, + __func__); + } + OpenForRDDProcess(Get<1>(std::move(aResult.ResolveValue()))); + return GenericNonExclusivePromise::CreateAndResolve(true, + __func__); + }); + }); + + p = p->Then( + GetCurrentSerialEventTarget(), __func__, + [](const GenericNonExclusivePromise::ResolveOrRejectValue& aResult) { + StaticMutexAutoLock lock(sLaunchMutex); + sLaunchRDDPromise = nullptr; + return GenericNonExclusivePromise::CreateAndResolveOrReject(aResult, + __func__); + }); + sLaunchRDDPromise = p; + return sLaunchRDDPromise; +} + +PRemoteDecoderChild* RemoteDecoderManagerChild::AllocPRemoteDecoderChild( + const RemoteDecoderInfoIPDL& /* not used */, + const CreateDecoderParams::OptionSet& aOptions, + const Maybe<layers::TextureFactoryIdentifier>& aIdentifier) { + // RemoteDecoderModule is responsible for creating RemoteDecoderChild + // classes. + MOZ_ASSERT(false, + "RemoteDecoderManagerChild cannot create " + "RemoteDecoderChild classes"); + return nullptr; +} + +bool RemoteDecoderManagerChild::DeallocPRemoteDecoderChild( + PRemoteDecoderChild* actor) { + RemoteDecoderChild* child = static_cast<RemoteDecoderChild*>(actor); + child->IPDLActorDestroyed(); + return true; +} + +RemoteDecoderManagerChild::RemoteDecoderManagerChild(RemoteDecodeIn aLocation) + : mLocation(aLocation) {} + +void RemoteDecoderManagerChild::OpenForRDDProcess( + Endpoint<PRemoteDecoderManagerChild>&& aEndpoint) { + nsCOMPtr<nsISerialEventTarget> managerThread = GetManagerThread(); + if (!managerThread) { + // We've been shutdown, bail. + return; + } + MOZ_ASSERT(managerThread->IsOnCurrentThread()); + + // Only create RemoteDecoderManagerChild, bind new endpoint and init + // ipdl if: + // 1) haven't init'd sRemoteDecoderManagerChild + // or + // 2) if ActorDestroy was called meaning the other end of the ipc channel was + // torn down + if (sRemoteDecoderManagerChildForRDDProcess && + sRemoteDecoderManagerChildForRDDProcess->CanSend()) { + return; + } + sRemoteDecoderManagerChildForRDDProcess = nullptr; + if (aEndpoint.IsValid()) { + RefPtr<RemoteDecoderManagerChild> manager = + new RemoteDecoderManagerChild(RemoteDecodeIn::RddProcess); + if (aEndpoint.Bind(manager)) { + sRemoteDecoderManagerChildForRDDProcess = manager; + manager->InitIPDL(); + } + } +} + +void RemoteDecoderManagerChild::OpenForGPUProcess( + Endpoint<PRemoteDecoderManagerChild>&& aEndpoint) { + nsCOMPtr<nsISerialEventTarget> managerThread = GetManagerThread(); + if (!managerThread) { + // We've been shutdown, bail. + return; + } + MOZ_ASSERT(managerThread->IsOnCurrentThread()); + // Make sure we always dispatch everything in sRecreateTasks, even if we + // fail since this is as close to being recreated as we will ever be. + sRemoteDecoderManagerChildForGPUProcess = nullptr; + if (aEndpoint.IsValid()) { + RefPtr<RemoteDecoderManagerChild> manager = + new RemoteDecoderManagerChild(RemoteDecodeIn::GpuProcess); + if (aEndpoint.Bind(manager)) { + sRemoteDecoderManagerChildForGPUProcess = manager; + manager->InitIPDL(); + } + } + for (Runnable* task : *sRecreateTasks) { + task->Run(); + } + sRecreateTasks->Clear(); +} + +void RemoteDecoderManagerChild::InitIPDL() { mIPDLSelfRef = this; } + +void RemoteDecoderManagerChild::ActorDealloc() { mIPDLSelfRef = nullptr; } + +VideoBridgeSource RemoteDecoderManagerChild::GetSource() const { + switch (mLocation) { + case RemoteDecodeIn::RddProcess: + return VideoBridgeSource::RddProcess; + case RemoteDecodeIn::GpuProcess: + return VideoBridgeSource::GpuProcess; + default: + MOZ_CRASH("Unexpected RemoteDecode variant"); + } +} + +bool RemoteDecoderManagerChild::DeallocShmem(mozilla::ipc::Shmem& aShmem) { + nsCOMPtr<nsISerialEventTarget> managerThread = GetManagerThread(); + if (!managerThread) { + return false; + } + if (!managerThread->IsOnCurrentThread()) { + MOZ_ALWAYS_SUCCEEDS(managerThread->Dispatch(NS_NewRunnableFunction( + "RemoteDecoderManagerChild::DeallocShmem", + [self = RefPtr{this}, shmem = aShmem]() mutable { + if (self->CanSend()) { + self->PRemoteDecoderManagerChild::DeallocShmem(shmem); + } + }))); + return true; + } + return PRemoteDecoderManagerChild::DeallocShmem(aShmem); +} + +struct SurfaceDescriptorUserData { + SurfaceDescriptorUserData(RemoteDecoderManagerChild* aAllocator, + SurfaceDescriptor& aSD) + : mAllocator(aAllocator), mSD(aSD) {} + ~SurfaceDescriptorUserData() { DestroySurfaceDescriptor(mAllocator, &mSD); } + + RefPtr<RemoteDecoderManagerChild> mAllocator; + SurfaceDescriptor mSD; +}; + +void DeleteSurfaceDescriptorUserData(void* aClosure) { + SurfaceDescriptorUserData* sd = + reinterpret_cast<SurfaceDescriptorUserData*>(aClosure); + delete sd; +} + +already_AddRefed<SourceSurface> RemoteDecoderManagerChild::Readback( + const SurfaceDescriptorGPUVideo& aSD) { + // We can't use NS_DISPATCH_SYNC here since that can spin the event + // loop while it waits. This function can be called from JS and we + // don't want that to happen. + nsCOMPtr<nsISerialEventTarget> managerThread = GetManagerThread(); + if (!managerThread) { + return nullptr; + } + + SurfaceDescriptor sd; + RefPtr<Runnable> task = + NS_NewRunnableFunction("RemoteDecoderManagerChild::Readback", [&]() { + if (CanSend()) { + SendReadback(aSD, &sd); + } + }); + SyncRunnable::DispatchToThread(managerThread, task); + + if (!IsSurfaceDescriptorValid(sd)) { + return nullptr; + } + + RefPtr<DataSourceSurface> source = GetSurfaceForDescriptor(sd); + if (!source) { + DestroySurfaceDescriptor(this, &sd); + NS_WARNING("Failed to map SurfaceDescriptor in Readback"); + return nullptr; + } + + static UserDataKey sSurfaceDescriptor; + source->AddUserData(&sSurfaceDescriptor, + new SurfaceDescriptorUserData(this, sd), + DeleteSurfaceDescriptorUserData); + + return source.forget(); +} + +void RemoteDecoderManagerChild::DeallocateSurfaceDescriptor( + const SurfaceDescriptorGPUVideo& aSD) { + nsCOMPtr<nsISerialEventTarget> managerThread = GetManagerThread(); + if (!managerThread) { + return; + } + MOZ_ALWAYS_SUCCEEDS(managerThread->Dispatch(NS_NewRunnableFunction( + "RemoteDecoderManagerChild::DeallocateSurfaceDescriptor", + [ref = RefPtr{this}, sd = aSD]() { + if (ref->CanSend()) { + ref->SendDeallocateSurfaceDescriptorGPUVideo(sd); + } + }))); +} + +void RemoteDecoderManagerChild::HandleFatalError(const char* aMsg) const { + dom::ContentChild::FatalErrorIfNotUsingGPUProcess(aMsg, OtherPid()); +} + +void RemoteDecoderManagerChild::SetSupported( + RemoteDecodeIn aLocation, + const PDMFactory::MediaCodecsSupported& aSupported) { + switch (aLocation) { + case RemoteDecodeIn::GpuProcess: { + auto supported = sGPUSupported.Lock(); + *supported = Some(aSupported); + break; + } + case RemoteDecodeIn::RddProcess: { + auto supported = sRDDSupported.Lock(); + *supported = Some(aSupported); + break; + } + default: + MOZ_CRASH("Not to be used for any other process"); + } +} + +} // namespace mozilla |