summaryrefslogtreecommitdiffstats
path: root/ipc/glue/UtilityAudioDecoderChild.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'ipc/glue/UtilityAudioDecoderChild.cpp')
-rw-r--r--ipc/glue/UtilityAudioDecoderChild.cpp173
1 files changed, 173 insertions, 0 deletions
diff --git a/ipc/glue/UtilityAudioDecoderChild.cpp b/ipc/glue/UtilityAudioDecoderChild.cpp
new file mode 100644
index 0000000000..ecd4727a18
--- /dev/null
+++ b/ipc/glue/UtilityAudioDecoderChild.cpp
@@ -0,0 +1,173 @@
+/* -*- 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
+
+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) {
+ MOZ_ASSERT(NS_IsMainThread());
+#ifdef MOZ_WMF_MEDIA_ENGINE
+ if (mSandbox == SandboxingKind::MF_MEDIA_ENGINE_CDM) {
+ gfx::gfxVars::AddReceiver(this);
+ }
+#endif
+ 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) {
+ DebugOnly<bool> ok = aEndpoint.Bind(this);
+ MOZ_ASSERT(ok);
+}
+
+/* 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
+
+} // namespace mozilla::ipc