1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=2 sts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 #include "UtilityAudioDecoderChild.h"
9 #include "base/basictypes.h"
10 #include "mozilla/AppShutdown.h"
11 #include "mozilla/dom/ContentParent.h"
13 #ifdef MOZ_WMF_MEDIA_ENGINE
14 # include "mozilla/StaticPrefs_media.h"
15 # include "mozilla/gfx/GPUProcessManager.h"
16 # include "mozilla/gfx/gfxVars.h"
17 # include "mozilla/ipc/UtilityProcessManager.h"
18 # include "mozilla/layers/PVideoBridge.h"
19 # include "mozilla/layers/VideoBridgeUtils.h"
22 namespace mozilla::ipc
{
24 NS_IMETHODIMP
UtilityAudioDecoderChildShutdownObserver::Observe(
25 nsISupports
* aSubject
, const char* aTopic
, const char16_t
* aData
) {
26 MOZ_ASSERT(strcmp(aTopic
, "ipc:utility-shutdown") == 0);
28 nsCOMPtr
<nsIObserverService
> observerService
= services::GetObserverService();
29 if (observerService
) {
30 observerService
->RemoveObserver(this, "ipc:utility-shutdown");
33 UtilityAudioDecoderChild::Shutdown(mSandbox
);
37 NS_IMPL_ISUPPORTS(UtilityAudioDecoderChildShutdownObserver
, nsIObserver
);
39 static EnumeratedArray
<SandboxingKind
, SandboxingKind::COUNT
,
40 StaticRefPtr
<UtilityAudioDecoderChild
>>
43 UtilityAudioDecoderChild::UtilityAudioDecoderChild(SandboxingKind aKind
)
44 : mSandbox(aKind
), mAudioDecoderChildStart(TimeStamp::Now()) {
45 MOZ_ASSERT(NS_IsMainThread());
46 nsCOMPtr
<nsIObserverService
> observerService
= services::GetObserverService();
47 if (observerService
) {
48 auto* obs
= new UtilityAudioDecoderChildShutdownObserver(aKind
);
49 observerService
->AddObserver(obs
, "ipc:utility-shutdown", false);
53 void UtilityAudioDecoderChild::ActorDestroy(ActorDestroyReason aReason
) {
54 MOZ_ASSERT(NS_IsMainThread());
55 #ifdef MOZ_WMF_MEDIA_ENGINE
56 if (mSandbox
== SandboxingKind::MF_MEDIA_ENGINE_CDM
) {
57 gfx::gfxVars::RemoveReceiver(this);
63 void UtilityAudioDecoderChild::Bind(
64 Endpoint
<PUtilityAudioDecoderChild
>&& aEndpoint
) {
65 MOZ_ASSERT(NS_IsMainThread());
66 if (NS_WARN_IF(!aEndpoint
.Bind(this))) {
67 MOZ_ASSERT_UNREACHABLE("Failed to bind UtilityAudioDecoderChild!");
70 #ifdef MOZ_WMF_MEDIA_ENGINE
71 if (mSandbox
== SandboxingKind::MF_MEDIA_ENGINE_CDM
) {
72 gfx::gfxVars::AddReceiver(this);
78 void UtilityAudioDecoderChild::Shutdown(SandboxingKind aKind
) {
79 sAudioDecoderChilds
[aKind
] = nullptr;
83 RefPtr
<UtilityAudioDecoderChild
> UtilityAudioDecoderChild::GetSingleton(
84 SandboxingKind aKind
) {
85 MOZ_ASSERT(NS_IsMainThread());
86 bool shutdown
= AppShutdown::IsInOrBeyond(ShutdownPhase::XPCOMWillShutdown
);
87 if (!sAudioDecoderChilds
[aKind
] && !shutdown
) {
88 sAudioDecoderChilds
[aKind
] = new UtilityAudioDecoderChild(aKind
);
90 return sAudioDecoderChilds
[aKind
];
93 mozilla::ipc::IPCResult
94 UtilityAudioDecoderChild::RecvUpdateMediaCodecsSupported(
95 const RemoteDecodeIn
& aLocation
,
96 const media::MediaCodecsSupported
& aSupported
) {
97 dom::ContentParent::BroadcastMediaCodecsSupportedUpdate(aLocation
,
102 #ifdef MOZ_WMF_MEDIA_ENGINE
103 mozilla::ipc::IPCResult
104 UtilityAudioDecoderChild::RecvCompleteCreatedVideoBridge() {
105 MOZ_ASSERT(NS_IsMainThread());
106 MOZ_ASSERT(mSandbox
== SandboxingKind::MF_MEDIA_ENGINE_CDM
);
107 mHasCreatedVideoBridge
= true;
111 bool UtilityAudioDecoderChild::HasCreatedVideoBridge() const {
112 MOZ_ASSERT(NS_IsMainThread());
113 return mHasCreatedVideoBridge
;
116 void UtilityAudioDecoderChild::OnVarChanged(const gfx::GfxVarUpdate
& aVar
) {
117 MOZ_ASSERT(mSandbox
== SandboxingKind::MF_MEDIA_ENGINE_CDM
);
121 void UtilityAudioDecoderChild::OnCompositorUnexpectedShutdown() {
122 MOZ_ASSERT(NS_IsMainThread());
123 MOZ_ASSERT(mSandbox
== SandboxingKind::MF_MEDIA_ENGINE_CDM
);
124 mHasCreatedVideoBridge
= false;
128 bool UtilityAudioDecoderChild::CreateVideoBridge() {
129 MOZ_ASSERT(NS_IsMainThread());
130 MOZ_ASSERT(mSandbox
== SandboxingKind::MF_MEDIA_ENGINE_CDM
);
132 if (HasCreatedVideoBridge()) {
136 // Build content device data first; this ensure that the GPU process is fully
138 gfx::ContentDeviceData contentDeviceData
;
139 gfxPlatform::GetPlatform()->BuildContentDeviceData(&contentDeviceData
);
141 gfx::GPUProcessManager
* gpuManager
= gfx::GPUProcessManager::Get();
143 NS_WARNING("Failed to get a gpu mananger!");
147 // The child end is the producer of video frames; the parent end is the
149 base::ProcessId childPid
= UtilityProcessManager::GetSingleton()
150 ->GetProcessParent(mSandbox
)
152 base::ProcessId parentPid
= gpuManager
->GPUProcessPid();
153 if (parentPid
== base::kInvalidProcessId
) {
154 NS_WARNING("GPU process Id is invald!");
158 ipc::Endpoint
<layers::PVideoBridgeParent
> parentPipe
;
159 ipc::Endpoint
<layers::PVideoBridgeChild
> childPipe
;
160 nsresult rv
= layers::PVideoBridge::CreateEndpoints(parentPid
, childPid
,
161 &parentPipe
, &childPipe
);
163 NS_WARNING("Failed to create endpoints for video bridge!");
167 nsTArray
<gfx::GfxVarUpdate
> updates
= gfx::gfxVars::FetchNonDefaultVars();
168 gpuManager
->InitVideoBridge(
169 std::move(parentPipe
),
170 layers::VideoBridgeSource::MFMediaEngineCDMProcess
);
171 SendInitVideoBridge(std::move(childPipe
), updates
, contentDeviceData
);
176 } // namespace mozilla::ipc