Bug 1650996 - P3. Have RemoteDecoderManagerChild use a TaskQueue over a media threadpool. r=mjf

Differential Revision: https://phabricator.services.mozilla.com/D82503
This commit is contained in:
Jean-Yves Avenard 2020-07-08 06:35:55 +00:00
Родитель a7619dfaf8
Коммит ae45d4a7e0
7 изменённых файлов: 69 добавлений и 80 удалений

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

@ -65,7 +65,6 @@ ProxyResolution
RemoteLzyStream RemoteLzyStream
RWLockTester RWLockTester
RacingServMan RacingServMan
RemVidChild
Sandbox Testing Sandbox Testing
SaveScripts SaveScripts
Socket Thread Socket Thread

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

@ -5,13 +5,11 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "GpuDecoderModule.h" #include "GpuDecoderModule.h"
#include "base/thread.h"
#include "mozilla/layers/SynchronousTask.h"
#include "mozilla/StaticPrefs_media.h"
#include "RemoteVideoDecoder.h"
#include "RemoteDecoderManagerChild.h" #include "RemoteDecoderManagerChild.h"
#include "RemoteMediaDataDecoder.h" #include "RemoteMediaDataDecoder.h"
#include "RemoteVideoDecoder.h"
#include "mozilla/StaticPrefs_media.h"
#include "mozilla/SyncRunnable.h"
namespace mozilla { namespace mozilla {
@ -50,19 +48,20 @@ already_AddRefed<MediaDataDecoder> GpuDecoderModule::CreateVideoDecoder(
} }
RefPtr<GpuRemoteVideoDecoderChild> child = new GpuRemoteVideoDecoderChild(); RefPtr<GpuRemoteVideoDecoderChild> child = new GpuRemoteVideoDecoderChild();
SynchronousTask task("InitIPDL");
MediaResult result(NS_OK); MediaResult result(NS_OK);
RemoteDecoderManagerChild::GetManagerThread()->Dispatch( RefPtr<Runnable> task = NS_NewRunnableFunction(
NS_NewRunnableFunction( "dom::GpuDecoderModule::CreateVideoDecoder", [&]() {
"dom::GpuDecoderModule::CreateVideoDecoder", result = child->InitIPDL(
[&, child]() { aParams.VideoConfig(), aParams.mRate.mValue, aParams.mOptions,
AutoCompleteTask complete(&task); aParams.mKnowsCompositor->GetTextureFactoryIdentifier());
result = child->InitIPDL( if (NS_FAILED(result)) {
aParams.VideoConfig(), aParams.mRate.mValue, aParams.mOptions, // Release GpuRemoteVideoDecoderChild here, while we're on
aParams.mKnowsCompositor->GetTextureFactoryIdentifier()); // manager thread. Don't just let the RefPtr go out of scope.
}), child = nullptr;
NS_DISPATCH_NORMAL); }
task.Wait(); });
SyncRunnable::DispatchToThread(RemoteDecoderManagerChild::GetManagerThread(),
task);
if (NS_FAILED(result)) { if (NS_FAILED(result)) {
if (aParams.mError) { if (aParams.mError) {

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

@ -254,7 +254,7 @@ MediaDataDecoder::ConversionRequired RemoteDecoderChild::NeedsConversion()
} }
void RemoteDecoderChild::AssertOnManagerThread() const { void RemoteDecoderChild::AssertOnManagerThread() const {
MOZ_ASSERT(NS_GetCurrentThread() == mThread); MOZ_ASSERT(mThread->IsOnCurrentThread());
} }
RemoteDecoderManagerChild* RemoteDecoderChild::GetManager() { RemoteDecoderManagerChild* RemoteDecoderChild::GetManager() {

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

@ -55,7 +55,7 @@ class RemoteDecoderChild : public PRemoteDecoderChild,
MediaDataDecoder::DecodedData mDecodedData; MediaDataDecoder::DecodedData mDecodedData;
private: private:
RefPtr<nsIThread> mThread; const nsCOMPtr<nsISerialEventTarget> mThread;
MozPromiseHolder<MediaDataDecoder::InitPromise> mInitPromise; MozPromiseHolder<MediaDataDecoder::InitPromise> mInitPromise;
MozPromiseRequestHolder<PRemoteDecoderChild::InitPromise> mInitPromiseRequest; MozPromiseRequestHolder<PRemoteDecoderChild::InitPromise> mInitPromiseRequest;

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

@ -5,15 +5,14 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "RemoteDecoderManagerChild.h" #include "RemoteDecoderManagerChild.h"
#include "base/task.h"
#include "RemoteDecoderChild.h" #include "RemoteDecoderChild.h"
#include "VideoUtils.h"
#include "mozilla/dom/ContentChild.h" #include "mozilla/dom/ContentChild.h"
#include "mozilla/gfx/2D.h" #include "mozilla/gfx/2D.h"
#include "mozilla/ipc/ProtocolUtils.h"
#include "mozilla/layers/SynchronousTask.h"
#include "mozilla/gfx/DataSurfaceHelpers.h" #include "mozilla/gfx/DataSurfaceHelpers.h"
#include "mozilla/ipc/ProtocolUtils.h"
#include "mozilla/layers/ISurfaceAllocator.h" #include "mozilla/layers/ISurfaceAllocator.h"
#include "mozilla/layers/SynchronousTask.h"
namespace mozilla { namespace mozilla {
@ -21,7 +20,7 @@ using namespace layers;
using namespace gfx; using namespace gfx;
// Only modified on the main-thread // Only modified on the main-thread
StaticRefPtr<nsIThread> sRemoteDecoderManagerChildThread; StaticRefPtr<TaskQueue> sRemoteDecoderManagerChildThread;
// Only accessed from sRemoteDecoderManagerChildThread // Only accessed from sRemoteDecoderManagerChildThread
static StaticRefPtr<RemoteDecoderManagerChild> static StaticRefPtr<RemoteDecoderManagerChild>
@ -36,10 +35,12 @@ void RemoteDecoderManagerChild::InitializeThread() {
MOZ_ASSERT(NS_IsMainThread()); MOZ_ASSERT(NS_IsMainThread());
if (!sRemoteDecoderManagerChildThread) { if (!sRemoteDecoderManagerChildThread) {
RefPtr<nsIThread> childThread; // We can't use a MediaThreadType::PLAYBACK as the GpuDecoderModule and
nsresult rv = NS_NewNamedThread("RemVidChild", getter_AddRefs(childThread)); // RemoteDecoderModule runs on it and dispatch synchronous tasks to the
NS_ENSURE_SUCCESS_VOID(rv); // manager thread, should more than 4 concurrent videos being instantiated
sRemoteDecoderManagerChildThread = childThread; // at the same time, we could end up in a deadlock.
sRemoteDecoderManagerChildThread = new TaskQueue(
GetMediaThreadPool(MediaThreadType::PLATFORM_DECODER), "RemVidChild");
sRecreateTasks = MakeUnique<nsTArray<RefPtr<Runnable>>>(); sRecreateTasks = MakeUnique<nsTArray<RefPtr<Runnable>>>();
} }
@ -49,20 +50,18 @@ void RemoteDecoderManagerChild::InitializeThread() {
void RemoteDecoderManagerChild::InitForRDDProcess( void RemoteDecoderManagerChild::InitForRDDProcess(
Endpoint<PRemoteDecoderManagerChild>&& aVideoManager) { Endpoint<PRemoteDecoderManagerChild>&& aVideoManager) {
InitializeThread(); InitializeThread();
sRemoteDecoderManagerChildThread->Dispatch( MOZ_ALWAYS_SUCCEEDS(sRemoteDecoderManagerChildThread->Dispatch(
NewRunnableFunction("InitForContentRunnable", &OpenForRDDProcess, NewRunnableFunction("InitForContentRunnable", &OpenForRDDProcess,
std::move(aVideoManager)), std::move(aVideoManager))));
NS_DISPATCH_NORMAL);
} }
/* static */ /* static */
void RemoteDecoderManagerChild::InitForGPUProcess( void RemoteDecoderManagerChild::InitForGPUProcess(
Endpoint<PRemoteDecoderManagerChild>&& aVideoManager) { Endpoint<PRemoteDecoderManagerChild>&& aVideoManager) {
InitializeThread(); InitializeThread();
sRemoteDecoderManagerChildThread->Dispatch( MOZ_ALWAYS_SUCCEEDS(sRemoteDecoderManagerChildThread->Dispatch(
NewRunnableFunction("InitForContentRunnable", &OpenForGPUProcess, NewRunnableFunction("InitForContentRunnable", &OpenForGPUProcess,
std::move(aVideoManager)), std::move(aVideoManager))));
NS_DISPATCH_NORMAL);
} }
/* static */ /* static */
@ -70,24 +69,23 @@ void RemoteDecoderManagerChild::Shutdown() {
MOZ_ASSERT(NS_IsMainThread()); MOZ_ASSERT(NS_IsMainThread());
if (sRemoteDecoderManagerChildThread) { if (sRemoteDecoderManagerChildThread) {
sRemoteDecoderManagerChildThread->Dispatch( MOZ_ALWAYS_SUCCEEDS(
NS_NewRunnableFunction( sRemoteDecoderManagerChildThread->Dispatch(NS_NewRunnableFunction(
"dom::RemoteDecoderManagerChild::Shutdown", "dom::RemoteDecoderManagerChild::Shutdown", []() {
[]() {
if (sRemoteDecoderManagerChildForRDDProcess && if (sRemoteDecoderManagerChildForRDDProcess &&
sRemoteDecoderManagerChildForRDDProcess->CanSend()) { sRemoteDecoderManagerChildForRDDProcess->CanSend()) {
sRemoteDecoderManagerChildForRDDProcess->Close(); sRemoteDecoderManagerChildForRDDProcess->Close();
sRemoteDecoderManagerChildForRDDProcess = nullptr;
} }
sRemoteDecoderManagerChildForRDDProcess = nullptr;
if (sRemoteDecoderManagerChildForGPUProcess && if (sRemoteDecoderManagerChildForGPUProcess &&
sRemoteDecoderManagerChildForGPUProcess->CanSend()) { sRemoteDecoderManagerChildForGPUProcess->CanSend()) {
sRemoteDecoderManagerChildForGPUProcess->Close(); sRemoteDecoderManagerChildForGPUProcess->Close();
sRemoteDecoderManagerChildForGPUProcess = nullptr;
} }
}), sRemoteDecoderManagerChildForGPUProcess = nullptr;
NS_DISPATCH_NORMAL); })));
sRemoteDecoderManagerChildThread->Shutdown(); sRemoteDecoderManagerChildThread->BeginShutdown();
sRemoteDecoderManagerChildThread->AwaitShutdownAndIdle();
sRemoteDecoderManagerChildThread = nullptr; sRemoteDecoderManagerChildThread = nullptr;
sRecreateTasks = nullptr; sRecreateTasks = nullptr;
@ -96,7 +94,7 @@ void RemoteDecoderManagerChild::Shutdown() {
void RemoteDecoderManagerChild::RunWhenGPUProcessRecreated( void RemoteDecoderManagerChild::RunWhenGPUProcessRecreated(
already_AddRefed<Runnable> aTask) { already_AddRefed<Runnable> aTask) {
MOZ_ASSERT(NS_GetCurrentThread() == GetManagerThread()); MOZ_ASSERT(GetManagerThread() && GetManagerThread()->IsOnCurrentThread());
// If we've already been recreated, then run the task immediately. // If we've already been recreated, then run the task immediately.
if (GetGPUProcessSingleton() && GetGPUProcessSingleton() != this && if (GetGPUProcessSingleton() && GetGPUProcessSingleton() != this &&
@ -110,18 +108,18 @@ void RemoteDecoderManagerChild::RunWhenGPUProcessRecreated(
/* static */ /* static */
RemoteDecoderManagerChild* RemoteDecoderManagerChild::GetRDDProcessSingleton() { RemoteDecoderManagerChild* RemoteDecoderManagerChild::GetRDDProcessSingleton() {
MOZ_ASSERT(NS_GetCurrentThread() == GetManagerThread()); MOZ_ASSERT(GetManagerThread() && GetManagerThread()->IsOnCurrentThread());
return sRemoteDecoderManagerChildForRDDProcess; return sRemoteDecoderManagerChildForRDDProcess;
} }
/* static */ /* static */
RemoteDecoderManagerChild* RemoteDecoderManagerChild::GetGPUProcessSingleton() { RemoteDecoderManagerChild* RemoteDecoderManagerChild::GetGPUProcessSingleton() {
MOZ_ASSERT(NS_GetCurrentThread() == GetManagerThread()); MOZ_ASSERT(GetManagerThread() && GetManagerThread()->IsOnCurrentThread());
return sRemoteDecoderManagerChildForGPUProcess; return sRemoteDecoderManagerChildForGPUProcess;
} }
/* static */ /* static */
nsIThread* RemoteDecoderManagerChild::GetManagerThread() { nsISerialEventTarget* RemoteDecoderManagerChild::GetManagerThread() {
return sRemoteDecoderManagerChildThread; return sRemoteDecoderManagerChildThread;
} }
@ -151,7 +149,7 @@ RemoteDecoderManagerChild::RemoteDecoderManagerChild(
void RemoteDecoderManagerChild::OpenForRDDProcess( void RemoteDecoderManagerChild::OpenForRDDProcess(
Endpoint<PRemoteDecoderManagerChild>&& aEndpoint) { Endpoint<PRemoteDecoderManagerChild>&& aEndpoint) {
MOZ_ASSERT(NS_GetCurrentThread() == GetManagerThread()); MOZ_ASSERT(GetManagerThread() && GetManagerThread()->IsOnCurrentThread());
// Only create RemoteDecoderManagerChild, bind new endpoint and init // Only create RemoteDecoderManagerChild, bind new endpoint and init
// ipdl if: // ipdl if:
// 1) haven't init'd sRemoteDecoderManagerChild // 1) haven't init'd sRemoteDecoderManagerChild
@ -199,18 +197,17 @@ void RemoteDecoderManagerChild::InitIPDL() {
void RemoteDecoderManagerChild::ActorDealloc() { mIPDLSelfRef = nullptr; } void RemoteDecoderManagerChild::ActorDealloc() { mIPDLSelfRef = nullptr; }
bool RemoteDecoderManagerChild::DeallocShmem(mozilla::ipc::Shmem& aShmem) { bool RemoteDecoderManagerChild::DeallocShmem(mozilla::ipc::Shmem& aShmem) {
if (NS_GetCurrentThread() != sRemoteDecoderManagerChildThread) { if (!sRemoteDecoderManagerChildThread->IsOnCurrentThread()) {
RefPtr<RemoteDecoderManagerChild> self = this; RefPtr<RemoteDecoderManagerChild> self = this;
mozilla::ipc::Shmem shmem = aShmem; mozilla::ipc::Shmem shmem = aShmem;
sRemoteDecoderManagerChildThread->Dispatch( MOZ_ALWAYS_SUCCEEDS(
NS_NewRunnableFunction("RemoteDecoderManagerChild::DeallocShmem", sRemoteDecoderManagerChildThread->Dispatch(NS_NewRunnableFunction(
[self, shmem]() { "RemoteDecoderManagerChild::DeallocShmem", [self, shmem]() {
if (self->CanSend()) { if (self->CanSend()) {
mozilla::ipc::Shmem shmemCopy = shmem; mozilla::ipc::Shmem shmemCopy = shmem;
self->DeallocShmem(shmemCopy); self->DeallocShmem(shmemCopy);
} }
}), })));
NS_DISPATCH_NORMAL);
return true; return true;
} }
return PRemoteDecoderManagerChild::DeallocShmem(aShmem); return PRemoteDecoderManagerChild::DeallocShmem(aShmem);
@ -242,14 +239,12 @@ already_AddRefed<SourceSurface> RemoteDecoderManagerChild::Readback(
RefPtr<RemoteDecoderManagerChild> ref = this; RefPtr<RemoteDecoderManagerChild> ref = this;
SurfaceDescriptor sd; SurfaceDescriptor sd;
if (NS_FAILED(sRemoteDecoderManagerChildThread->Dispatch( if (NS_FAILED(sRemoteDecoderManagerChildThread->Dispatch(
NS_NewRunnableFunction("RemoteDecoderManagerChild::Readback", NS_NewRunnableFunction("RemoteDecoderManagerChild::Readback", [&]() {
[&]() { AutoCompleteTask complete(&task);
AutoCompleteTask complete(&task); if (ref->CanSend()) {
if (ref->CanSend()) { ref->SendReadback(aSD, &sd);
ref->SendReadback(aSD, &sd); }
} })))) {
}),
NS_DISPATCH_NORMAL))) {
return nullptr; return nullptr;
} }
@ -278,15 +273,14 @@ void RemoteDecoderManagerChild::DeallocateSurfaceDescriptor(
const SurfaceDescriptorGPUVideo& aSD) { const SurfaceDescriptorGPUVideo& aSD) {
RefPtr<RemoteDecoderManagerChild> ref = this; RefPtr<RemoteDecoderManagerChild> ref = this;
SurfaceDescriptorGPUVideo sd = std::move(aSD); SurfaceDescriptorGPUVideo sd = std::move(aSD);
sRemoteDecoderManagerChildThread->Dispatch( MOZ_ALWAYS_SUCCEEDS(
NS_NewRunnableFunction( sRemoteDecoderManagerChildThread->Dispatch(NS_NewRunnableFunction(
"RemoteDecoderManagerChild::DeallocateSurfaceDescriptor", "RemoteDecoderManagerChild::DeallocateSurfaceDescriptor",
[ref, sd]() { [ref, sd]() {
if (ref->CanSend()) { if (ref->CanSend()) {
ref->SendDeallocateSurfaceDescriptorGPUVideo(sd); ref->SendDeallocateSurfaceDescriptorGPUVideo(sd);
} }
}), })));
NS_DISPATCH_NORMAL);
} }
void RemoteDecoderManagerChild::HandleFatalError(const char* aMsg) const { void RemoteDecoderManagerChild::HandleFatalError(const char* aMsg) const {

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

@ -5,9 +5,9 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef include_dom_media_ipc_RemoteDecoderManagerChild_h #ifndef include_dom_media_ipc_RemoteDecoderManagerChild_h
#define include_dom_media_ipc_RemoteDecoderManagerChild_h #define include_dom_media_ipc_RemoteDecoderManagerChild_h
#include "GPUVideoImage.h"
#include "mozilla/PRemoteDecoderManagerChild.h" #include "mozilla/PRemoteDecoderManagerChild.h"
#include "mozilla/layers/VideoBridgeUtils.h" #include "mozilla/layers/VideoBridgeUtils.h"
#include "GPUVideoImage.h"
namespace mozilla { namespace mozilla {
@ -25,7 +25,7 @@ class RemoteDecoderManagerChild final
static RemoteDecoderManagerChild* GetGPUProcessSingleton(); static RemoteDecoderManagerChild* GetGPUProcessSingleton();
// Can be called from any thread. // Can be called from any thread.
static nsIThread* GetManagerThread(); static nsISerialEventTarget* GetManagerThread();
// Can be called from any thread, dispatches the request to the IPDL thread // 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. // internally and will be ignored if the IPDL actor has been destroyed.
@ -51,6 +51,7 @@ class RemoteDecoderManagerChild final
bool DeallocShmem(mozilla::ipc::Shmem& aShmem) override; bool DeallocShmem(mozilla::ipc::Shmem& aShmem) override;
// Main thread only // Main thread only
static void InitializeThread();
static void InitForRDDProcess( static void InitForRDDProcess(
Endpoint<PRemoteDecoderManagerChild>&& aVideoManager); Endpoint<PRemoteDecoderManagerChild>&& aVideoManager);
static void InitForGPUProcess( static void InitForGPUProcess(
@ -80,9 +81,6 @@ class RemoteDecoderManagerChild final
bool DeallocPRemoteDecoderChild(PRemoteDecoderChild* actor); bool DeallocPRemoteDecoderChild(PRemoteDecoderChild* actor);
private: private:
// Main thread only
static void InitializeThread();
explicit RemoteDecoderManagerChild(layers::VideoBridgeSource aSource); explicit RemoteDecoderManagerChild(layers::VideoBridgeSource aSource);
~RemoteDecoderManagerChild() = default; ~RemoteDecoderManagerChild() = default;

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

@ -5,20 +5,19 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "RemoteDecoderModule.h" #include "RemoteDecoderModule.h"
#include "base/thread.h"
#include "mozilla/dom/ContentChild.h" // for launching RDD w/ ContentChild
#include "mozilla/layers/SynchronousTask.h"
#include "mozilla/StaticPrefs_media.h" #include "mozilla/StaticPrefs_media.h"
#include "mozilla/SyncRunnable.h" #include "mozilla/SyncRunnable.h"
#include "mozilla/dom/ContentChild.h" // for launching RDD w/ ContentChild
#include "mozilla/layers/SynchronousTask.h"
#ifdef MOZ_AV1 #ifdef MOZ_AV1
# include "AOMDecoder.h" # include "AOMDecoder.h"
#endif #endif
#include "OpusDecoder.h"
#include "RemoteAudioDecoder.h" #include "RemoteAudioDecoder.h"
#include "RemoteDecoderManagerChild.h" #include "RemoteDecoderManagerChild.h"
#include "RemoteMediaDataDecoder.h" #include "RemoteMediaDataDecoder.h"
#include "RemoteVideoDecoder.h" #include "RemoteVideoDecoder.h"
#include "OpusDecoder.h"
#include "VideoUtils.h" #include "VideoUtils.h"
#include "VorbisDecoder.h" #include "VorbisDecoder.h"
#include "WAVDecoder.h" #include "WAVDecoder.h"