summaryrefslogtreecommitdiffstats
path: root/ipc/glue/UtilityAudioDecoderChild.cpp
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-19 00:47:55 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-19 00:47:55 +0000
commit26a029d407be480d791972afb5975cf62c9360a6 (patch)
treef435a8308119effd964b339f76abb83a57c29483 /ipc/glue/UtilityAudioDecoderChild.cpp
parentInitial commit. (diff)
downloadfirefox-26a029d407be480d791972afb5975cf62c9360a6.tar.xz
firefox-26a029d407be480d791972afb5975cf62c9360a6.zip
Adding upstream version 124.0.1.upstream/124.0.1
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'ipc/glue/UtilityAudioDecoderChild.cpp')
-rw-r--r--ipc/glue/UtilityAudioDecoderChild.cpp232
1 files changed, 232 insertions, 0 deletions
diff --git a/ipc/glue/UtilityAudioDecoderChild.cpp b/ipc/glue/UtilityAudioDecoderChild.cpp
new file mode 100644
index 0000000000..88124a1f8b
--- /dev/null
+++ b/ipc/glue/UtilityAudioDecoderChild.cpp
@@ -0,0 +1,232 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=2 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 "UtilityAudioDecoderChild.h"
+
+#include "base/basictypes.h"
+#include "mozilla/AppShutdown.h"
+#include "mozilla/dom/ContentParent.h"
+
+#ifdef MOZ_WMF_MEDIA_ENGINE
+# include "mozilla/StaticPrefs_media.h"
+# include "mozilla/gfx/GPUProcessManager.h"
+# include "mozilla/gfx/gfxVars.h"
+# include "mozilla/ipc/UtilityProcessManager.h"
+# include "mozilla/layers/PVideoBridge.h"
+# include "mozilla/layers/VideoBridgeUtils.h"
+#endif
+
+#ifdef MOZ_WMF_CDM
+# include "mozilla/dom/Promise.h"
+# include "mozilla/EMEUtils.h"
+# include "mozilla/PMFCDM.h"
+#endif
+
+namespace mozilla::ipc {
+
+NS_IMETHODIMP UtilityAudioDecoderChildShutdownObserver::Observe(
+ nsISupports* aSubject, const char* aTopic, const char16_t* aData) {
+ MOZ_ASSERT(strcmp(aTopic, "ipc:utility-shutdown") == 0);
+
+ nsCOMPtr<nsIObserverService> observerService = services::GetObserverService();
+ if (observerService) {
+ observerService->RemoveObserver(this, "ipc:utility-shutdown");
+ }
+
+ UtilityAudioDecoderChild::Shutdown(mSandbox);
+ return NS_OK;
+}
+
+NS_IMPL_ISUPPORTS(UtilityAudioDecoderChildShutdownObserver, nsIObserver);
+
+static EnumeratedArray<SandboxingKind, SandboxingKind::COUNT,
+ StaticRefPtr<UtilityAudioDecoderChild>>
+ sAudioDecoderChilds;
+
+UtilityAudioDecoderChild::UtilityAudioDecoderChild(SandboxingKind aKind)
+ : mSandbox(aKind), mAudioDecoderChildStart(TimeStamp::Now()) {
+ MOZ_ASSERT(NS_IsMainThread());
+ nsCOMPtr<nsIObserverService> observerService = services::GetObserverService();
+ if (observerService) {
+ auto* obs = new UtilityAudioDecoderChildShutdownObserver(aKind);
+ observerService->AddObserver(obs, "ipc:utility-shutdown", false);
+ }
+}
+
+void UtilityAudioDecoderChild::ActorDestroy(ActorDestroyReason aReason) {
+ MOZ_ASSERT(NS_IsMainThread());
+#ifdef MOZ_WMF_MEDIA_ENGINE
+ if (mSandbox == SandboxingKind::MF_MEDIA_ENGINE_CDM) {
+ gfx::gfxVars::RemoveReceiver(this);
+ }
+#endif
+ Shutdown(mSandbox);
+}
+
+void UtilityAudioDecoderChild::Bind(
+ Endpoint<PUtilityAudioDecoderChild>&& aEndpoint) {
+ MOZ_ASSERT(NS_IsMainThread());
+ if (NS_WARN_IF(!aEndpoint.Bind(this))) {
+ MOZ_ASSERT_UNREACHABLE("Failed to bind UtilityAudioDecoderChild!");
+ return;
+ }
+#ifdef MOZ_WMF_MEDIA_ENGINE
+ if (mSandbox == SandboxingKind::MF_MEDIA_ENGINE_CDM) {
+ gfx::gfxVars::AddReceiver(this);
+ }
+#endif
+}
+
+/* static */
+void UtilityAudioDecoderChild::Shutdown(SandboxingKind aKind) {
+ sAudioDecoderChilds[aKind] = nullptr;
+}
+
+/* static */
+RefPtr<UtilityAudioDecoderChild> UtilityAudioDecoderChild::GetSingleton(
+ SandboxingKind aKind) {
+ MOZ_ASSERT(NS_IsMainThread());
+ bool shutdown = AppShutdown::IsInOrBeyond(ShutdownPhase::XPCOMWillShutdown);
+ if (!sAudioDecoderChilds[aKind] && !shutdown) {
+ sAudioDecoderChilds[aKind] = new UtilityAudioDecoderChild(aKind);
+ }
+ return sAudioDecoderChilds[aKind];
+}
+
+mozilla::ipc::IPCResult
+UtilityAudioDecoderChild::RecvUpdateMediaCodecsSupported(
+ const RemoteDecodeIn& aLocation,
+ const media::MediaCodecsSupported& aSupported) {
+ dom::ContentParent::BroadcastMediaCodecsSupportedUpdate(aLocation,
+ aSupported);
+ return IPC_OK();
+}
+
+#ifdef MOZ_WMF_MEDIA_ENGINE
+mozilla::ipc::IPCResult
+UtilityAudioDecoderChild::RecvCompleteCreatedVideoBridge() {
+ MOZ_ASSERT(NS_IsMainThread());
+ MOZ_ASSERT(mSandbox == SandboxingKind::MF_MEDIA_ENGINE_CDM);
+ mHasCreatedVideoBridge = true;
+ return IPC_OK();
+}
+
+bool UtilityAudioDecoderChild::HasCreatedVideoBridge() const {
+ MOZ_ASSERT(NS_IsMainThread());
+ return mHasCreatedVideoBridge;
+}
+
+void UtilityAudioDecoderChild::OnVarChanged(const gfx::GfxVarUpdate& aVar) {
+ MOZ_ASSERT(mSandbox == SandboxingKind::MF_MEDIA_ENGINE_CDM);
+ SendUpdateVar(aVar);
+}
+
+void UtilityAudioDecoderChild::OnCompositorUnexpectedShutdown() {
+ MOZ_ASSERT(NS_IsMainThread());
+ MOZ_ASSERT(mSandbox == SandboxingKind::MF_MEDIA_ENGINE_CDM);
+ mHasCreatedVideoBridge = false;
+ CreateVideoBridge();
+}
+
+bool UtilityAudioDecoderChild::CreateVideoBridge() {
+ MOZ_ASSERT(NS_IsMainThread());
+ MOZ_ASSERT(mSandbox == SandboxingKind::MF_MEDIA_ENGINE_CDM);
+
+ if (HasCreatedVideoBridge()) {
+ return true;
+ }
+
+ // Build content device data first; this ensure that the GPU process is fully
+ // ready.
+ gfx::ContentDeviceData contentDeviceData;
+ gfxPlatform::GetPlatform()->BuildContentDeviceData(&contentDeviceData);
+
+ gfx::GPUProcessManager* gpuManager = gfx::GPUProcessManager::Get();
+ if (!gpuManager) {
+ NS_WARNING("Failed to get a gpu mananger!");
+ return false;
+ }
+
+ // The child end is the producer of video frames; the parent end is the
+ // consumer.
+ base::ProcessId childPid = UtilityProcessManager::GetSingleton()
+ ->GetProcessParent(mSandbox)
+ ->OtherPid();
+ base::ProcessId parentPid = gpuManager->GPUProcessPid();
+ if (parentPid == base::kInvalidProcessId) {
+ NS_WARNING("GPU process Id is invald!");
+ return false;
+ }
+
+ ipc::Endpoint<layers::PVideoBridgeParent> parentPipe;
+ ipc::Endpoint<layers::PVideoBridgeChild> childPipe;
+ nsresult rv = layers::PVideoBridge::CreateEndpoints(parentPid, childPid,
+ &parentPipe, &childPipe);
+ if (NS_FAILED(rv)) {
+ NS_WARNING("Failed to create endpoints for video bridge!");
+ return false;
+ }
+
+ nsTArray<gfx::GfxVarUpdate> updates = gfx::gfxVars::FetchNonDefaultVars();
+ gpuManager->InitVideoBridge(
+ std::move(parentPipe),
+ layers::VideoBridgeSource::MFMediaEngineCDMProcess);
+ SendInitVideoBridge(std::move(childPipe), updates, contentDeviceData);
+ return true;
+}
+#endif
+
+#ifdef MOZ_WMF_CDM
+void UtilityAudioDecoderChild::GetKeySystemCapabilities(
+ dom::Promise* aPromise) {
+ EME_LOG("Ask capabilities for all supported CDMs");
+ SendGetKeySystemCapabilities()->Then(
+ NS_GetCurrentThread(), __func__,
+ [promise = RefPtr<dom::Promise>(aPromise)](
+ CopyableTArray<MFCDMCapabilitiesIPDL>&& result) {
+ FallibleTArray<dom::CDMInformation> cdmInfo;
+ for (const auto& capabilities : result) {
+ EME_LOG("Received capabilities for %s",
+ NS_ConvertUTF16toUTF8(capabilities.keySystem()).get());
+ for (const auto& v : capabilities.videoCapabilities()) {
+ EME_LOG(" capabilities: video=%s",
+ NS_ConvertUTF16toUTF8(v.contentType()).get());
+ }
+ for (const auto& a : capabilities.audioCapabilities()) {
+ EME_LOG(" capabilities: audio=%s",
+ NS_ConvertUTF16toUTF8(a.contentType()).get());
+ }
+ for (const auto& e : capabilities.encryptionSchemes()) {
+ EME_LOG(" capabilities: encryptionScheme=%s",
+ EncryptionSchemeStr(e));
+ }
+ auto* info = cdmInfo.AppendElement(fallible);
+ if (!info) {
+ promise->MaybeReject(NS_ERROR_OUT_OF_MEMORY);
+ return;
+ }
+ info->mKeySystemName = capabilities.keySystem();
+
+ KeySystemConfig config;
+ MFCDMCapabilitiesIPDLToKeySystemConfig(capabilities, config);
+ info->mCapabilities = config.GetDebugInfo();
+ info->mClearlead =
+ DoesKeySystemSupportClearLead(info->mKeySystemName);
+ if (capabilities.isHDCP22Compatible()) {
+ info->mIsHDCP22Compatible = true;
+ }
+ }
+ promise->MaybeResolve(cdmInfo);
+ },
+ [promise = RefPtr<dom::Promise>(aPromise)](
+ const mozilla::ipc::ResponseRejectReason& aReason) {
+ EME_LOG("IPC failure for GetKeySystemCapabilities!");
+ promise->MaybeReject(NS_ERROR_DOM_MEDIA_CDM_ERR);
+ });
+}
+#endif
+
+} // namespace mozilla::ipc