Skip to content

Commit

Permalink
Bug 1650996 - P3. Have RemoteDecoderManagerChild use a TaskQueue over…
Browse files Browse the repository at this point in the history
… a media threadpool. r=mjf

Differential Revision: https://phabricator.services.mozilla.com/D82503
  • Loading branch information
Jean-Yves Avenard committed Jul 9, 2020
1 parent e2dc020 commit 71dbeca
Show file tree
Hide file tree
Showing 7 changed files with 67 additions and 76 deletions.
1 change: 0 additions & 1 deletion build/clang-plugin/ThreadAllows.txt
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,6 @@ ProxyResolution
RemoteLzyStream
RWLockTester
RacingServMan
RemVidChild
Sandbox Testing
SaveScripts
Socket Thread
Expand Down
33 changes: 16 additions & 17 deletions dom/media/ipc/GpuDecoderModule.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,11 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "GpuDecoderModule.h"

#include "base/thread.h"
#include "mozilla/layers/SynchronousTask.h"
#include "mozilla/StaticPrefs_media.h"
#include "RemoteVideoDecoder.h"
#include "RemoteDecoderManagerChild.h"

#include "RemoteMediaDataDecoder.h"
#include "RemoteVideoDecoder.h"
#include "mozilla/StaticPrefs_media.h"
#include "mozilla/SyncRunnable.h"

namespace mozilla {

Expand Down Expand Up @@ -50,19 +48,20 @@ already_AddRefed<MediaDataDecoder> GpuDecoderModule::CreateVideoDecoder(
}

RefPtr<GpuRemoteVideoDecoderChild> child = new GpuRemoteVideoDecoderChild();
SynchronousTask task("InitIPDL");
MediaResult result(NS_OK);
RemoteDecoderManagerChild::GetManagerThread()->Dispatch(
NS_NewRunnableFunction(
"dom::GpuDecoderModule::CreateVideoDecoder",
[&, child]() {
AutoCompleteTask complete(&task);
result = child->InitIPDL(
aParams.VideoConfig(), aParams.mRate.mValue, aParams.mOptions,
aParams.mKnowsCompositor->GetTextureFactoryIdentifier());
}),
NS_DISPATCH_NORMAL);
task.Wait();
RefPtr<Runnable> task = NS_NewRunnableFunction(
"dom::GpuDecoderModule::CreateVideoDecoder", [&]() {
result = child->InitIPDL(
aParams.VideoConfig(), aParams.mRate.mValue, aParams.mOptions,
aParams.mKnowsCompositor->GetTextureFactoryIdentifier());
if (NS_FAILED(result)) {
// Release GpuRemoteVideoDecoderChild here, while we're on
// manager thread. Don't just let the RefPtr go out of scope.
child = nullptr;
}
});
SyncRunnable::DispatchToThread(RemoteDecoderManagerChild::GetManagerThread(),
task);

if (NS_FAILED(result)) {
if (aParams.mError) {
Expand Down
2 changes: 1 addition & 1 deletion dom/media/ipc/RemoteDecoderChild.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -254,7 +254,7 @@ MediaDataDecoder::ConversionRequired RemoteDecoderChild::NeedsConversion()
}

void RemoteDecoderChild::AssertOnManagerThread() const {
MOZ_ASSERT(NS_GetCurrentThread() == mThread);
MOZ_ASSERT(mThread->IsOnCurrentThread());
}

RemoteDecoderManagerChild* RemoteDecoderChild::GetManager() {
Expand Down
2 changes: 1 addition & 1 deletion dom/media/ipc/RemoteDecoderChild.h
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ class RemoteDecoderChild : public PRemoteDecoderChild,
MediaDataDecoder::DecodedData mDecodedData;

private:
const RefPtr<nsIThread> mThread;
const nsCOMPtr<nsISerialEventTarget> mThread;

MozPromiseHolder<MediaDataDecoder::InitPromise> mInitPromise;
MozPromiseRequestHolder<PRemoteDecoderChild::InitPromise> mInitPromiseRequest;
Expand Down
96 changes: 45 additions & 51 deletions dom/media/ipc/RemoteDecoderManagerChild.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,23 +5,22 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "RemoteDecoderManagerChild.h"

#include "base/task.h"

#include "RemoteDecoderChild.h"
#include "VideoUtils.h"
#include "mozilla/dom/ContentChild.h"
#include "mozilla/gfx/2D.h"
#include "mozilla/ipc/ProtocolUtils.h"
#include "mozilla/layers/SynchronousTask.h"
#include "mozilla/gfx/DataSurfaceHelpers.h"
#include "mozilla/ipc/ProtocolUtils.h"
#include "mozilla/layers/ISurfaceAllocator.h"
#include "mozilla/layers/SynchronousTask.h"

namespace mozilla {

using namespace layers;
using namespace gfx;

// Only modified on the main-thread
StaticRefPtr<nsIThread> sRemoteDecoderManagerChildThread;
StaticRefPtr<TaskQueue> sRemoteDecoderManagerChildThread;

// Only accessed from sRemoteDecoderManagerChildThread
static StaticRefPtr<RemoteDecoderManagerChild>
Expand All @@ -36,10 +35,12 @@ void RemoteDecoderManagerChild::InitializeThread() {
MOZ_ASSERT(NS_IsMainThread());

if (!sRemoteDecoderManagerChildThread) {
RefPtr<nsIThread> childThread;
nsresult rv = NS_NewNamedThread("RemVidChild", getter_AddRefs(childThread));
NS_ENSURE_SUCCESS_VOID(rv);
sRemoteDecoderManagerChildThread = childThread;
// We can't use a MediaThreadType::PLAYBACK as the GpuDecoderModule and
// RemoteDecoderModule runs on it and dispatch synchronous tasks to the
// manager thread, should more than 4 concurrent videos being instantiated
// at the same time, we could end up in a deadlock.
sRemoteDecoderManagerChildThread = new TaskQueue(
GetMediaThreadPool(MediaThreadType::PLATFORM_DECODER), "RemVidChild");

sRecreateTasks = MakeUnique<nsTArray<RefPtr<Runnable>>>();
}
Expand All @@ -49,45 +50,42 @@ void RemoteDecoderManagerChild::InitializeThread() {
void RemoteDecoderManagerChild::InitForRDDProcess(
Endpoint<PRemoteDecoderManagerChild>&& aVideoManager) {
InitializeThread();
sRemoteDecoderManagerChildThread->Dispatch(
MOZ_ALWAYS_SUCCEEDS(sRemoteDecoderManagerChildThread->Dispatch(
NewRunnableFunction("InitForContentRunnable", &OpenForRDDProcess,
std::move(aVideoManager)),
NS_DISPATCH_NORMAL);
std::move(aVideoManager))));
}

/* static */
void RemoteDecoderManagerChild::InitForGPUProcess(
Endpoint<PRemoteDecoderManagerChild>&& aVideoManager) {
InitializeThread();
sRemoteDecoderManagerChildThread->Dispatch(
MOZ_ALWAYS_SUCCEEDS(sRemoteDecoderManagerChildThread->Dispatch(
NewRunnableFunction("InitForContentRunnable", &OpenForGPUProcess,
std::move(aVideoManager)),
NS_DISPATCH_NORMAL);
std::move(aVideoManager))));
}

/* static */
void RemoteDecoderManagerChild::Shutdown() {
MOZ_ASSERT(NS_IsMainThread());

if (sRemoteDecoderManagerChildThread) {
sRemoteDecoderManagerChildThread->Dispatch(
NS_NewRunnableFunction(
"dom::RemoteDecoderManagerChild::Shutdown",
[]() {
MOZ_ALWAYS_SUCCEEDS(
sRemoteDecoderManagerChildThread->Dispatch(NS_NewRunnableFunction(
"dom::RemoteDecoderManagerChild::Shutdown", []() {
if (sRemoteDecoderManagerChildForRDDProcess &&
sRemoteDecoderManagerChildForRDDProcess->CanSend()) {
sRemoteDecoderManagerChildForRDDProcess->Close();
sRemoteDecoderManagerChildForRDDProcess = nullptr;
}
sRemoteDecoderManagerChildForRDDProcess = nullptr;
if (sRemoteDecoderManagerChildForGPUProcess &&
sRemoteDecoderManagerChildForGPUProcess->CanSend()) {
sRemoteDecoderManagerChildForGPUProcess->Close();
sRemoteDecoderManagerChildForGPUProcess = nullptr;
}
}),
NS_DISPATCH_NORMAL);
sRemoteDecoderManagerChildForGPUProcess = nullptr;
})));

sRemoteDecoderManagerChildThread->Shutdown();
sRemoteDecoderManagerChildThread->BeginShutdown();
sRemoteDecoderManagerChildThread->AwaitShutdownAndIdle();
sRemoteDecoderManagerChildThread = nullptr;

sRecreateTasks = nullptr;
Expand All @@ -96,7 +94,7 @@ void RemoteDecoderManagerChild::Shutdown() {

void RemoteDecoderManagerChild::RunWhenGPUProcessRecreated(
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 (GetGPUProcessSingleton() && GetGPUProcessSingleton() != this &&
Expand All @@ -110,18 +108,18 @@ void RemoteDecoderManagerChild::RunWhenGPUProcessRecreated(

/* static */
RemoteDecoderManagerChild* RemoteDecoderManagerChild::GetRDDProcessSingleton() {
MOZ_ASSERT(NS_GetCurrentThread() == GetManagerThread());
MOZ_ASSERT(GetManagerThread() && GetManagerThread()->IsOnCurrentThread());
return sRemoteDecoderManagerChildForRDDProcess;
}

/* static */
RemoteDecoderManagerChild* RemoteDecoderManagerChild::GetGPUProcessSingleton() {
MOZ_ASSERT(NS_GetCurrentThread() == GetManagerThread());
MOZ_ASSERT(GetManagerThread() && GetManagerThread()->IsOnCurrentThread());
return sRemoteDecoderManagerChildForGPUProcess;
}

/* static */
nsIThread* RemoteDecoderManagerChild::GetManagerThread() {
nsISerialEventTarget* RemoteDecoderManagerChild::GetManagerThread() {
return sRemoteDecoderManagerChildThread;
}

Expand Down Expand Up @@ -151,7 +149,7 @@ RemoteDecoderManagerChild::RemoteDecoderManagerChild(

void RemoteDecoderManagerChild::OpenForRDDProcess(
Endpoint<PRemoteDecoderManagerChild>&& aEndpoint) {
MOZ_ASSERT(NS_GetCurrentThread() == GetManagerThread());
MOZ_ASSERT(GetManagerThread() && GetManagerThread()->IsOnCurrentThread());
// Only create RemoteDecoderManagerChild, bind new endpoint and init
// ipdl if:
// 1) haven't init'd sRemoteDecoderManagerChild
Expand Down Expand Up @@ -199,18 +197,17 @@ void RemoteDecoderManagerChild::InitIPDL() {
void RemoteDecoderManagerChild::ActorDealloc() { mIPDLSelfRef = nullptr; }

bool RemoteDecoderManagerChild::DeallocShmem(mozilla::ipc::Shmem& aShmem) {
if (NS_GetCurrentThread() != sRemoteDecoderManagerChildThread) {
if (!sRemoteDecoderManagerChildThread->IsOnCurrentThread()) {
RefPtr<RemoteDecoderManagerChild> self = this;
mozilla::ipc::Shmem shmem = aShmem;
sRemoteDecoderManagerChildThread->Dispatch(
NS_NewRunnableFunction("RemoteDecoderManagerChild::DeallocShmem",
[self, shmem]() {
if (self->CanSend()) {
mozilla::ipc::Shmem shmemCopy = shmem;
self->DeallocShmem(shmemCopy);
}
}),
NS_DISPATCH_NORMAL);
MOZ_ALWAYS_SUCCEEDS(
sRemoteDecoderManagerChildThread->Dispatch(NS_NewRunnableFunction(
"RemoteDecoderManagerChild::DeallocShmem", [self, shmem]() {
if (self->CanSend()) {
mozilla::ipc::Shmem shmemCopy = shmem;
self->DeallocShmem(shmemCopy);
}
})));
return true;
}
return PRemoteDecoderManagerChild::DeallocShmem(aShmem);
Expand Down Expand Up @@ -242,14 +239,12 @@ already_AddRefed<SourceSurface> RemoteDecoderManagerChild::Readback(
RefPtr<RemoteDecoderManagerChild> ref = this;
SurfaceDescriptor sd;
if (NS_FAILED(sRemoteDecoderManagerChildThread->Dispatch(
NS_NewRunnableFunction("RemoteDecoderManagerChild::Readback",
[&]() {
AutoCompleteTask complete(&task);
if (ref->CanSend()) {
ref->SendReadback(aSD, &sd);
}
}),
NS_DISPATCH_NORMAL))) {
NS_NewRunnableFunction("RemoteDecoderManagerChild::Readback", [&]() {
AutoCompleteTask complete(&task);
if (ref->CanSend()) {
ref->SendReadback(aSD, &sd);
}
})))) {
return nullptr;
}

Expand Down Expand Up @@ -278,15 +273,14 @@ void RemoteDecoderManagerChild::DeallocateSurfaceDescriptor(
const SurfaceDescriptorGPUVideo& aSD) {
RefPtr<RemoteDecoderManagerChild> ref = this;
SurfaceDescriptorGPUVideo sd = std::move(aSD);
sRemoteDecoderManagerChildThread->Dispatch(
NS_NewRunnableFunction(
MOZ_ALWAYS_SUCCEEDS(
sRemoteDecoderManagerChildThread->Dispatch(NS_NewRunnableFunction(
"RemoteDecoderManagerChild::DeallocateSurfaceDescriptor",
[ref, sd]() {
if (ref->CanSend()) {
ref->SendDeallocateSurfaceDescriptorGPUVideo(sd);
}
}),
NS_DISPATCH_NORMAL);
})));
}

void RemoteDecoderManagerChild::HandleFatalError(const char* aMsg) const {
Expand Down
2 changes: 1 addition & 1 deletion dom/media/ipc/RemoteDecoderManagerChild.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ class RemoteDecoderManagerChild final
static RemoteDecoderManagerChild* GetGPUProcessSingleton();

// 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
// internally and will be ignored if the IPDL actor has been destroyed.
Expand Down
7 changes: 3 additions & 4 deletions dom/media/ipc/RemoteDecoderModule.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,20 +5,19 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#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/SyncRunnable.h"
#include "mozilla/dom/ContentChild.h" // for launching RDD w/ ContentChild
#include "mozilla/layers/SynchronousTask.h"

#ifdef MOZ_AV1
# include "AOMDecoder.h"
#endif
#include "OpusDecoder.h"
#include "RemoteAudioDecoder.h"
#include "RemoteDecoderManagerChild.h"
#include "RemoteMediaDataDecoder.h"
#include "RemoteVideoDecoder.h"
#include "OpusDecoder.h"
#include "VideoUtils.h"
#include "VorbisDecoder.h"
#include "WAVDecoder.h"
Expand Down

0 comments on commit 71dbeca

Please sign in to comment.