Bug 1672072 - P9. Make EnsureRDDProcessAndCreateBridge an async API. r=mattwoodrow,bryce,mjf,padenot,ipc-reviewers,mccr8

We can now chaincreation of the decoder to the launch of the RDD process as needed and setting up the PRemoteDecoderManager

Differential Revision: https://phabricator.services.mozilla.com/D96365
This commit is contained in:
Jean-Yves Avenard 2020-11-12 22:53:49 +00:00
Родитель 7a6315ba80
Коммит 8ffdd4eaef
7 изменённых файлов: 83 добавлений и 58 удалений

Просмотреть файл

@ -26,8 +26,9 @@ using namespace layers;
using namespace gfx;
// Used so that we only ever attempt to check if the RDD process should be
// launched serially.
// 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
@ -202,9 +203,9 @@ RemoteDecoderManagerChild::CreateAudioDecoder(
return PlatformDecoderModule::CreateDecoderPromise::CreateAndReject(
NS_ERROR_DOM_MEDIA_CANCELED, __func__);
}
return InvokeAsync(
return LaunchRDDProcessIfNeeded()->Then(
managerThread, __func__,
[params = CreateDecoderParamsForAsync(aParams)]() {
[params = CreateDecoderParamsForAsync(aParams)](bool) {
auto child = MakeRefPtr<RemoteAudioDecoderChild>();
MediaResult result =
child->InitIPDL(params.AudioConfig(), params.mOptions);
@ -213,6 +214,10 @@ RemoteDecoderManagerChild::CreateAudioDecoder(
result, __func__);
}
return Construct(std::move(child));
},
[](nsresult aResult) {
return PlatformDecoderModule::CreateDecoderPromise::CreateAndReject(
MediaResult(aResult, "Couldn't start RDD process"), __func__);
});
}
@ -235,10 +240,15 @@ RemoteDecoderManagerChild::CreateVideoDecoder(
}
MOZ_ASSERT(aLocation != RemoteDecodeIn::Unspecified);
return InvokeAsync(
RefPtr<GenericNonExclusivePromise> p =
aLocation == RemoteDecodeIn::GpuProcess
? GenericNonExclusivePromise::CreateAndResolve(true, __func__)
: LaunchRDDProcessIfNeeded();
return p->Then(
managerThread, __func__,
[aLocation, params = CreateDecoderParamsForAsync(aParams)]()
-> RefPtr<PlatformDecoderModule::CreateDecoderPromise> {
[aLocation, params = CreateDecoderParamsForAsync(aParams)](bool) {
auto child = MakeRefPtr<RemoteVideoDecoderChild>(aLocation);
MediaResult result = child->InitIPDL(
params.VideoConfig(), params.mRate.mValue, params.mOptions,
@ -250,6 +260,10 @@ RemoteDecoderManagerChild::CreateVideoDecoder(
result, __func__);
}
return Construct(std::move(child));
},
[](nsresult aResult) {
return PlatformDecoderModule::CreateDecoderPromise::CreateAndReject(
MediaResult(aResult, "Couldn't start RDD process"), __func__);
});
}
@ -287,24 +301,24 @@ RemoteDecoderManagerChild::Construct(RefPtr<RemoteDecoderChild>&& aChild) {
}
/* static */
void RemoteDecoderManagerChild::LaunchRDDProcessIfNeeded(
RemoteDecodeIn aLocation) {
RefPtr<GenericNonExclusivePromise>
RemoteDecoderManagerChild::LaunchRDDProcessIfNeeded() {
MOZ_DIAGNOSTIC_ASSERT(XRE_IsContentProcess(),
"Only supported from a content process.");
if (aLocation != RemoteDecodeIn::RddProcess) {
// Not targeting RDD process? No need to launch RDD.
return;
}
nsCOMPtr<nsISerialEventTarget> managerThread = GetManagerThread();
if (!managerThread) {
// We got shutdown.
return;
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
@ -319,33 +333,51 @@ void RemoteDecoderManagerChild::LaunchRDDProcessIfNeeded(
// LaunchRDDProcess which will launch RDD if necessary, and setup the
// IPC connections between *this* content process and the RDD process.
bool needsLaunch = true;
RefPtr<Runnable> task = NS_NewRunnableFunction(
"RemoteDecoderManagerChild::LaunchRDDProcessIfNeeded-CheckSend", [&]() {
RefPtr<GenericNonExclusivePromise> p = InvokeAsync(
managerThread, __func__, []() -> RefPtr<GenericNonExclusivePromise> {
auto* rps = GetSingleton(RemoteDecodeIn::RddProcess);
needsLaunch = rps ? !rps->CanSend() : true;
});
if (NS_FAILED(SyncRunnable::DispatchToThread(managerThread, task))) {
return;
};
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__);
}
if (needsLaunch) {
managerThread->Dispatch(NS_NewRunnableFunction(
"RemoteDecoderManagerChild::EnsureRDDProcessAndCreateBridge", [&]() {
ipc::PBackgroundChild* bgActor =
ipc::BackgroundChild::GetForCurrentThread();
if (NS_WARN_IF(!bgActor)) {
return;
}
nsresult rv;
Endpoint<PRemoteDecoderManagerChild> endpoint;
Unused << bgActor->SendEnsureRDDProcessAndCreateBridge(&rv,
&endpoint);
if (NS_SUCCEEDED(rv)) {
OpenForRDDProcess(std::move(endpoint));
}
}));
}
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(

Просмотреть файл

@ -44,7 +44,6 @@ class RemoteDecoderManagerChild final
// Can be called from any thread.
static nsISerialEventTarget* GetManagerThread();
static void LaunchRDDProcessIfNeeded(RemoteDecodeIn aLocation);
// Can be called from any thread, dispatches the request to the IPDL thread
// internally and will be ignored if the IPDL actor has been destroyed.
@ -106,6 +105,7 @@ class RemoteDecoderManagerChild final
Endpoint<PRemoteDecoderManagerChild>&& aEndpoint);
static void OpenForGPUProcess(
Endpoint<PRemoteDecoderManagerChild>&& aEndpoint);
static RefPtr<GenericNonExclusivePromise> LaunchRDDProcessIfNeeded();
RefPtr<RemoteDecoderManagerChild> mIPDLSelfRef;
// The location for decoding, Rdd or Gpu process.

Просмотреть файл

@ -5,11 +5,6 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "RemoteDecoderModule.h"
#include "mozilla/StaticPrefs_media.h"
#include "mozilla/SyncRunnable.h"
#include "mozilla/dom/ContentChild.h" // for launching RDD w/ ContentChild
#include "mozilla/layers/SynchronousTask.h"
#ifdef MOZ_AV1
# include "AOMDecoder.h"
#endif
@ -63,8 +58,6 @@ bool RemoteDecoderModule::Supports(
RefPtr<RemoteDecoderModule::CreateDecoderPromise>
RemoteDecoderModule::AsyncCreateDecoder(const CreateDecoderParams& aParams) {
RemoteDecoderManagerChild::LaunchRDDProcessIfNeeded(mLocation);
if (aParams.mConfig.IsAudio()) {
// OpusDataDecoder will check this option to provide the same info
// that IsDefaultPlaybackDeviceMono provides. We want to avoid calls

Просмотреть файл

@ -1314,13 +1314,16 @@ mozilla::ipc::IPCResult BackgroundParentImpl::RecvPEndpointForReportConstructor(
mozilla::ipc::IPCResult
BackgroundParentImpl::RecvEnsureRDDProcessAndCreateBridge(
nsresult* aRv, Endpoint<PRemoteDecoderManagerChild>* aEndpoint) {
EnsureRDDProcessAndCreateBridgeResolver&& aResolver) {
RDDProcessManager* rdd = RDDProcessManager::Get();
if (rdd && rdd->EnsureRDDProcessAndCreateBridge(OtherPid(), aEndpoint)) {
*aRv = NS_OK;
} else {
*aRv = NS_ERROR_NOT_AVAILABLE;
}
Endpoint<PRemoteDecoderManagerChild> endpoint;
nsresult rv =
rdd && rdd->EnsureRDDProcessAndCreateBridge(OtherPid(), &endpoint)
? NS_OK
: NS_ERROR_NOT_AVAILABLE;
aResolver(
Tuple<const nsresult&, Endpoint<mozilla::PRemoteDecoderManagerChild>&&>(
rv, std::move(endpoint)));
return IPC_OK();
}

Просмотреть файл

@ -392,7 +392,7 @@ class BackgroundParentImpl : public PBackgroundParent,
const PrincipalInfo& aPrincipalInfo) override;
mozilla::ipc::IPCResult RecvEnsureRDDProcessAndCreateBridge(
nsresult* aRv, Endpoint<PRemoteDecoderManagerChild>* aEndpoint) override;
EnsureRDDProcessAndCreateBridgeResolver&& aResolver) override;
bool DeallocPEndpointForReportParent(
PEndpointForReportParent* aActor) override;

Просмотреть файл

@ -263,8 +263,7 @@ parent:
uint32_t aProviderFlags,
uint32_t aCertVerifierFlags);
// See Bug 1518344 - Investigate using async for PBackground::EnsureRDDProcessAndCreateBridge
sync EnsureRDDProcessAndCreateBridge()
async EnsureRDDProcessAndCreateBridge()
returns (nsresult rv, Endpoint<PRemoteDecoderManagerChild> aEndpoint);
child:

Просмотреть файл

@ -884,8 +884,6 @@ description = legacy sync IPC - please add detailed description
description = legacy sync IPC - please add detailed description
[PRemoteDecoderManager::Readback]
description = legacy sync IPC - please add detailed description
[PBackground::EnsureRDDProcessAndCreateBridge]
description = See Bug 1518344 - investigate using async for PBackground::EnsureRDDProcessAndCreateBridge
[PBackgroundStorage::Preload]
description = legacy sync IPC - please add detailed description
[PBackgroundLSDatabase::PBackgroundLSSnapshot]