зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1595994 - P2: Make RemoteDecoderManagerChild responsible for creation of remote decoders. r=kamidphish,mattwoodrow
Fly-by fix potential races when accessing the manager's thread. Depends on D52796 Differential Revision: https://phabricator.services.mozilla.com/D52797
This commit is contained in:
Родитель
5cc27aec49
Коммит
29f6310810
|
@ -48,32 +48,8 @@ already_AddRefed<MediaDataDecoder> GpuDecoderModule::CreateVideoDecoder(
|
|||
return mWrapped->CreateVideoDecoder(aParams);
|
||||
}
|
||||
|
||||
RefPtr<GpuRemoteVideoDecoderChild> child = new GpuRemoteVideoDecoderChild();
|
||||
MediaResult result(NS_OK);
|
||||
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) {
|
||||
*aParams.mError = result;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
RefPtr<RemoteMediaDataDecoder> object = new RemoteMediaDataDecoder(child);
|
||||
|
||||
return object.forget();
|
||||
return RemoteDecoderManagerChild::CreateVideoDecoder(
|
||||
aParams, RemoteDecodeIn::GpuProcess);
|
||||
}
|
||||
|
||||
} // namespace mozilla
|
||||
|
|
|
@ -39,7 +39,7 @@ MediaResult RemoteAudioDecoderChild::InitIPDL(
|
|||
const AudioInfo& aAudioInfo,
|
||||
const CreateDecoderParams::OptionSet& aOptions) {
|
||||
RefPtr<RemoteDecoderManagerChild> manager =
|
||||
RemoteDecoderManagerChild::GetRDDProcessSingleton();
|
||||
RemoteDecoderManagerChild::GetSingleton(RemoteDecodeIn::RddProcess);
|
||||
|
||||
// The manager isn't available because RemoteDecoderManagerChild has been
|
||||
// initialized with null end points and we don't want to decode video on RDD
|
||||
|
|
|
@ -5,7 +5,10 @@
|
|||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
#include "RemoteDecoderManagerChild.h"
|
||||
|
||||
#include "RemoteAudioDecoder.h"
|
||||
#include "RemoteDecoderChild.h"
|
||||
#include "RemoteMediaDataDecoder.h"
|
||||
#include "RemoteVideoDecoder.h"
|
||||
#include "VideoUtils.h"
|
||||
#include "mozilla/dom/ContentChild.h" // for launching RDD w/ ContentChild
|
||||
#include "mozilla/gfx/2D.h"
|
||||
|
@ -22,7 +25,9 @@ namespace mozilla {
|
|||
using namespace layers;
|
||||
using namespace gfx;
|
||||
|
||||
StaticMutex RemoteDecoderManagerChild::sLaunchMonitor;
|
||||
// Used so that we only ever attempt to check if the RDD process should be
|
||||
// launched serially.
|
||||
StaticMutex sLaunchMutex;
|
||||
|
||||
// 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
|
||||
|
@ -140,8 +145,8 @@ void RemoteDecoderManagerChild::RunWhenGPUProcessRecreated(
|
|||
MOZ_ASSERT(GetManagerThread() && GetManagerThread()->IsOnCurrentThread());
|
||||
|
||||
// If we've already been recreated, then run the task immediately.
|
||||
if (GetGPUProcessSingleton() && GetGPUProcessSingleton() != this &&
|
||||
GetGPUProcessSingleton()->CanSend()) {
|
||||
auto* manager = GetSingleton(RemoteDecodeIn::GpuProcess);
|
||||
if (manager && manager != this && manager->CanSend()) {
|
||||
RefPtr<Runnable> task = aTask;
|
||||
task->Run();
|
||||
} else {
|
||||
|
@ -150,15 +155,17 @@ void RemoteDecoderManagerChild::RunWhenGPUProcessRecreated(
|
|||
}
|
||||
|
||||
/* static */
|
||||
RemoteDecoderManagerChild* RemoteDecoderManagerChild::GetRDDProcessSingleton() {
|
||||
RemoteDecoderManagerChild* RemoteDecoderManagerChild::GetSingleton(
|
||||
RemoteDecodeIn aLocation) {
|
||||
MOZ_ASSERT(GetManagerThread() && GetManagerThread()->IsOnCurrentThread());
|
||||
return sRemoteDecoderManagerChildForRDDProcess;
|
||||
}
|
||||
|
||||
/* static */
|
||||
RemoteDecoderManagerChild* RemoteDecoderManagerChild::GetGPUProcessSingleton() {
|
||||
MOZ_ASSERT(GetManagerThread() && GetManagerThread()->IsOnCurrentThread());
|
||||
return sRemoteDecoderManagerChildForGPUProcess;
|
||||
switch (aLocation) {
|
||||
case RemoteDecodeIn::GpuProcess:
|
||||
return sRemoteDecoderManagerChildForGPUProcess;
|
||||
case RemoteDecodeIn::RddProcess:
|
||||
return sRemoteDecoderManagerChildForRDDProcess;
|
||||
default:
|
||||
MOZ_CRASH("Unexpected RemoteDecode variant");
|
||||
}
|
||||
}
|
||||
|
||||
/* static */
|
||||
|
@ -167,13 +174,100 @@ nsISerialEventTarget* RemoteDecoderManagerChild::GetManagerThread() {
|
|||
return *remoteDecoderManagerThread;
|
||||
}
|
||||
|
||||
/* static */
|
||||
already_AddRefed<MediaDataDecoder>
|
||||
RemoteDecoderManagerChild::CreateAudioDecoder(
|
||||
const CreateDecoderParams& aParams) {
|
||||
nsCOMPtr<nsISerialEventTarget> managerThread = GetManagerThread();
|
||||
if (!managerThread) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
auto child = MakeRefPtr<RemoteAudioDecoderChild>();
|
||||
MediaResult result(NS_OK);
|
||||
// We can use child as a ref here because this is a sync dispatch. In
|
||||
// the error case for InitIPDL, we can't just let the RefPtr go out of
|
||||
// scope at the end of the method because it will release the
|
||||
// RemoteAudioDecoderChild on the wrong thread. This will assert in
|
||||
// RemoteDecoderChild's destructor. Passing the RefPtr by reference
|
||||
// allows us to release the RemoteAudioDecoderChild on the manager
|
||||
// thread during this single dispatch.
|
||||
RefPtr<Runnable> task =
|
||||
NS_NewRunnableFunction("RemoteDecoderModule::CreateAudioDecoder", [&]() {
|
||||
result = child->InitIPDL(aParams.AudioConfig(), aParams.mOptions);
|
||||
if (NS_FAILED(result)) {
|
||||
// Release RemoteAudioDecoderChild here, while we're on
|
||||
// manager thread. Don't just let the RefPtr go out of scope.
|
||||
child = nullptr;
|
||||
}
|
||||
});
|
||||
SyncRunnable::DispatchToThread(managerThread, task);
|
||||
|
||||
if (NS_FAILED(result)) {
|
||||
if (aParams.mError) {
|
||||
*aParams.mError = result;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
RefPtr<RemoteMediaDataDecoder> object = new RemoteMediaDataDecoder(child);
|
||||
|
||||
return object.forget();
|
||||
}
|
||||
|
||||
/* static */
|
||||
already_AddRefed<MediaDataDecoder>
|
||||
RemoteDecoderManagerChild::CreateVideoDecoder(
|
||||
const CreateDecoderParams& aParams, RemoteDecodeIn aLocation) {
|
||||
nsCOMPtr<nsISerialEventTarget> managerThread = GetManagerThread();
|
||||
if (!managerThread) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
MOZ_ASSERT(aLocation != RemoteDecodeIn::Unspecified);
|
||||
auto child = MakeRefPtr<RemoteVideoDecoderChild>(aLocation);
|
||||
MediaResult result(NS_OK);
|
||||
// We can use child as a ref here because this is a sync dispatch. In
|
||||
// the error case for InitIPDL, we can't just let the RefPtr go out of
|
||||
// scope at the end of the method because it will release the
|
||||
// RemoteVideoDecoderChild on the wrong thread. This will assert in
|
||||
// RemoteDecoderChild's destructor. Passing the RefPtr by reference
|
||||
// allows us to release the RemoteVideoDecoderChild on the manager
|
||||
// thread during this single dispatch.
|
||||
RefPtr<Runnable> task = NS_NewRunnableFunction(
|
||||
"RemoteDecoderManagerChild::CreateVideoDecoder", [&]() {
|
||||
result = child->InitIPDL(
|
||||
aParams.VideoConfig(), aParams.mRate.mValue, aParams.mOptions,
|
||||
aParams.mKnowsCompositor
|
||||
? &aParams.mKnowsCompositor->GetTextureFactoryIdentifier()
|
||||
: nullptr);
|
||||
if (NS_FAILED(result)) {
|
||||
// Release RemoteVideoDecoderChild here, while we're on
|
||||
// manager thread. Don't just let the RefPtr go out of scope.
|
||||
child = nullptr;
|
||||
}
|
||||
});
|
||||
SyncRunnable::DispatchToThread(managerThread, task);
|
||||
|
||||
if (NS_FAILED(result)) {
|
||||
if (aParams.mError) {
|
||||
*aParams.mError = result;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
RefPtr<RemoteMediaDataDecoder> object = new RemoteMediaDataDecoder(child);
|
||||
|
||||
return object.forget();
|
||||
}
|
||||
|
||||
/* static */
|
||||
void RemoteDecoderManagerChild::LaunchRDDProcessIfNeeded() {
|
||||
if (!XRE_IsContentProcess()) {
|
||||
return;
|
||||
}
|
||||
|
||||
StaticMutexAutoLock mon(sLaunchMonitor);
|
||||
StaticMutexAutoLock lock(sLaunchMutex);
|
||||
|
||||
// We have a couple possible states here. We are in a content process
|
||||
// and:
|
||||
|
@ -193,7 +287,7 @@ void RemoteDecoderManagerChild::LaunchRDDProcessIfNeeded() {
|
|||
if (managerThread) {
|
||||
RefPtr<Runnable> task = NS_NewRunnableFunction(
|
||||
"RemoteDecoderManagerChild::LaunchRDDProcessIfNeeded-CheckSend", [&]() {
|
||||
auto* rps = GetRDDProcessSingleton();
|
||||
auto* rps = GetSingleton(RemoteDecodeIn::RddProcess);
|
||||
needsLaunch = rps ? !rps->CanSend() : true;
|
||||
});
|
||||
SyncRunnable::DispatchToThread(managerThread, task);
|
||||
|
@ -224,9 +318,8 @@ bool RemoteDecoderManagerChild::DeallocPRemoteDecoderChild(
|
|||
return true;
|
||||
}
|
||||
|
||||
RemoteDecoderManagerChild::RemoteDecoderManagerChild(
|
||||
layers::VideoBridgeSource aSource)
|
||||
: mSource(aSource) {}
|
||||
RemoteDecoderManagerChild::RemoteDecoderManagerChild(RemoteDecodeIn aLocation)
|
||||
: mLocation(aLocation) {}
|
||||
|
||||
void RemoteDecoderManagerChild::OpenForRDDProcess(
|
||||
Endpoint<PRemoteDecoderManagerChild>&& aEndpoint) {
|
||||
|
@ -244,7 +337,7 @@ void RemoteDecoderManagerChild::OpenForRDDProcess(
|
|||
sRemoteDecoderManagerChildForRDDProcess = nullptr;
|
||||
if (aEndpoint.IsValid()) {
|
||||
RefPtr<RemoteDecoderManagerChild> manager =
|
||||
new RemoteDecoderManagerChild(VideoBridgeSource::RddProcess);
|
||||
new RemoteDecoderManagerChild(RemoteDecodeIn::RddProcess);
|
||||
if (aEndpoint.Bind(manager)) {
|
||||
sRemoteDecoderManagerChildForRDDProcess = manager;
|
||||
manager->InitIPDL();
|
||||
|
@ -259,7 +352,7 @@ void RemoteDecoderManagerChild::OpenForGPUProcess(
|
|||
sRemoteDecoderManagerChildForGPUProcess = nullptr;
|
||||
if (aEndpoint.IsValid()) {
|
||||
RefPtr<RemoteDecoderManagerChild> manager =
|
||||
new RemoteDecoderManagerChild(VideoBridgeSource::GpuProcess);
|
||||
new RemoteDecoderManagerChild(RemoteDecodeIn::GpuProcess);
|
||||
if (aEndpoint.Bind(manager)) {
|
||||
sRemoteDecoderManagerChildForGPUProcess = manager;
|
||||
manager->InitIPDL();
|
||||
|
@ -275,6 +368,17 @@ void RemoteDecoderManagerChild::InitIPDL() { mIPDLSelfRef = this; }
|
|||
|
||||
void RemoteDecoderManagerChild::ActorDealloc() { mIPDLSelfRef = nullptr; }
|
||||
|
||||
VideoBridgeSource RemoteDecoderManagerChild::GetSource() const {
|
||||
switch (mLocation) {
|
||||
case RemoteDecodeIn::RddProcess:
|
||||
return VideoBridgeSource::RddProcess;
|
||||
case RemoteDecodeIn::GpuProcess:
|
||||
return VideoBridgeSource::GpuProcess;
|
||||
default:
|
||||
MOZ_CRASH("Unexpected RemoteDecode variant");
|
||||
}
|
||||
}
|
||||
|
||||
bool RemoteDecoderManagerChild::DeallocShmem(mozilla::ipc::Shmem& aShmem) {
|
||||
nsCOMPtr<nsISerialEventTarget> managerThread = GetManagerThread();
|
||||
if (!managerThread) {
|
||||
|
|
|
@ -11,6 +11,12 @@
|
|||
|
||||
namespace mozilla {
|
||||
|
||||
enum class RemoteDecodeIn {
|
||||
Unspecified,
|
||||
RddProcess,
|
||||
GpuProcess,
|
||||
};
|
||||
|
||||
class RemoteDecoderManagerChild final
|
||||
: public PRemoteDecoderManagerChild,
|
||||
public mozilla::ipc::IShmemAllocator,
|
||||
|
@ -21,8 +27,13 @@ class RemoteDecoderManagerChild final
|
|||
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(RemoteDecoderManagerChild, override)
|
||||
|
||||
// Can only be called from the manager thread
|
||||
static RemoteDecoderManagerChild* GetRDDProcessSingleton();
|
||||
static RemoteDecoderManagerChild* GetGPUProcessSingleton();
|
||||
static RemoteDecoderManagerChild* GetSingleton(RemoteDecodeIn aLocation);
|
||||
|
||||
// Can be called from any thread.
|
||||
static already_AddRefed<MediaDataDecoder> CreateAudioDecoder(
|
||||
const CreateDecoderParams& aParams);
|
||||
static already_AddRefed<MediaDataDecoder> CreateVideoDecoder(
|
||||
const CreateDecoderParams& aParams, RemoteDecodeIn aLocation);
|
||||
|
||||
// Can be called from any thread.
|
||||
static nsISerialEventTarget* GetManagerThread();
|
||||
|
@ -65,7 +76,7 @@ class RemoteDecoderManagerChild final
|
|||
// called from the manager thread.
|
||||
void RunWhenGPUProcessRecreated(already_AddRefed<Runnable> aTask);
|
||||
|
||||
layers::VideoBridgeSource GetSource() const { return mSource; }
|
||||
layers::VideoBridgeSource GetSource() const;
|
||||
|
||||
protected:
|
||||
void InitIPDL();
|
||||
|
@ -82,7 +93,7 @@ class RemoteDecoderManagerChild final
|
|||
bool DeallocPRemoteDecoderChild(PRemoteDecoderChild* actor);
|
||||
|
||||
private:
|
||||
explicit RemoteDecoderManagerChild(layers::VideoBridgeSource aSource);
|
||||
explicit RemoteDecoderManagerChild(RemoteDecodeIn aLocation);
|
||||
~RemoteDecoderManagerChild() = default;
|
||||
|
||||
static void OpenForRDDProcess(
|
||||
|
@ -90,12 +101,10 @@ class RemoteDecoderManagerChild final
|
|||
static void OpenForGPUProcess(
|
||||
Endpoint<PRemoteDecoderManagerChild>&& aEndpoint);
|
||||
|
||||
static StaticMutex sLaunchMonitor;
|
||||
|
||||
RefPtr<RemoteDecoderManagerChild> mIPDLSelfRef;
|
||||
|
||||
// The associated source of this decoder manager
|
||||
layers::VideoBridgeSource mSource;
|
||||
// The location for decoding, Rdd or Gpu process.
|
||||
const RemoteDecodeIn mLocation;
|
||||
};
|
||||
|
||||
} // namespace mozilla
|
||||
|
|
|
@ -29,11 +29,6 @@ using dom::ContentChild;
|
|||
using namespace ipc;
|
||||
using namespace layers;
|
||||
|
||||
RemoteDecoderModule::RemoteDecoderModule()
|
||||
: mManagerThread(RemoteDecoderManagerChild::GetManagerThread()) {
|
||||
MOZ_DIAGNOSTIC_ASSERT(mManagerThread);
|
||||
}
|
||||
|
||||
/* static */
|
||||
void RemoteDecoderModule::Init() {
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
@ -85,82 +80,21 @@ already_AddRefed<MediaDataDecoder> RemoteDecoderModule::CreateAudioDecoder(
|
|||
// that IsDefaultPlaybackDeviceMono provides. We want to avoid calls
|
||||
// to IsDefaultPlaybackDeviceMono on RDD because initializing audio
|
||||
// backends on RDD will be blocked by the sandbox.
|
||||
CreateDecoderParams::OptionSet options(aParams.mOptions);
|
||||
if (OpusDataDecoder::IsOpus(aParams.mConfig.mMimeType) &&
|
||||
IsDefaultPlaybackDeviceMono()) {
|
||||
options += CreateDecoderParams::Option::DefaultPlaybackDeviceMono;
|
||||
CreateDecoderParams params = aParams;
|
||||
params.mOptions += CreateDecoderParams::Option::DefaultPlaybackDeviceMono;
|
||||
return RemoteDecoderManagerChild::CreateAudioDecoder(params);
|
||||
}
|
||||
|
||||
RefPtr<RemoteAudioDecoderChild> child = new RemoteAudioDecoderChild();
|
||||
MediaResult result(NS_OK);
|
||||
// We can use child as a ref here because this is a sync dispatch. In
|
||||
// the error case for InitIPDL, we can't just let the RefPtr go out of
|
||||
// scope at the end of the method because it will release the
|
||||
// RemoteAudioDecoderChild on the wrong thread. This will assert in
|
||||
// RemoteDecoderChild's destructor. Passing the RefPtr by reference
|
||||
// allows us to release the RemoteAudioDecoderChild on the manager
|
||||
// thread during this single dispatch.
|
||||
RefPtr<Runnable> task =
|
||||
NS_NewRunnableFunction("RemoteDecoderModule::CreateAudioDecoder", [&]() {
|
||||
result = child->InitIPDL(aParams.AudioConfig(), options);
|
||||
if (NS_FAILED(result)) {
|
||||
// Release RemoteAudioDecoderChild here, while we're on
|
||||
// manager thread. Don't just let the RefPtr go out of scope.
|
||||
child = nullptr;
|
||||
}
|
||||
});
|
||||
SyncRunnable::DispatchToThread(mManagerThread, task);
|
||||
|
||||
if (NS_FAILED(result)) {
|
||||
if (aParams.mError) {
|
||||
*aParams.mError = result;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
RefPtr<RemoteMediaDataDecoder> object = new RemoteMediaDataDecoder(child);
|
||||
|
||||
return object.forget();
|
||||
return RemoteDecoderManagerChild::CreateAudioDecoder(aParams);
|
||||
}
|
||||
|
||||
already_AddRefed<MediaDataDecoder> RemoteDecoderModule::CreateVideoDecoder(
|
||||
const CreateDecoderParams& aParams) {
|
||||
RemoteDecoderManagerChild::LaunchRDDProcessIfNeeded();
|
||||
|
||||
RefPtr<RemoteVideoDecoderChild> child = new RemoteVideoDecoderChild();
|
||||
MediaResult result(NS_OK);
|
||||
// We can use child as a ref here because this is a sync dispatch. In
|
||||
// the error case for InitIPDL, we can't just let the RefPtr go out of
|
||||
// scope at the end of the method because it will release the
|
||||
// RemoteVideoDecoderChild on the wrong thread. This will assert in
|
||||
// RemoteDecoderChild's destructor. Passing the RefPtr by reference
|
||||
// allows us to release the RemoteVideoDecoderChild on the manager
|
||||
// thread during this single dispatch.
|
||||
RefPtr<Runnable> task =
|
||||
NS_NewRunnableFunction("RemoteDecoderModule::CreateVideoDecoder", [&]() {
|
||||
result = child->InitIPDL(
|
||||
aParams.VideoConfig(), aParams.mRate.mValue, aParams.mOptions,
|
||||
aParams.mKnowsCompositor
|
||||
? &aParams.mKnowsCompositor->GetTextureFactoryIdentifier()
|
||||
: nullptr);
|
||||
if (NS_FAILED(result)) {
|
||||
// Release RemoteVideoDecoderChild here, while we're on
|
||||
// manager thread. Don't just let the RefPtr go out of scope.
|
||||
child = nullptr;
|
||||
}
|
||||
});
|
||||
SyncRunnable::DispatchToThread(mManagerThread, task);
|
||||
|
||||
if (NS_FAILED(result)) {
|
||||
if (aParams.mError) {
|
||||
*aParams.mError = result;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
RefPtr<RemoteMediaDataDecoder> object = new RemoteMediaDataDecoder(child);
|
||||
|
||||
return object.forget();
|
||||
return RemoteDecoderManagerChild::CreateVideoDecoder(
|
||||
aParams, RemoteDecodeIn::RddProcess);
|
||||
}
|
||||
|
||||
} // namespace mozilla
|
||||
|
|
|
@ -6,7 +6,6 @@
|
|||
#ifndef include_dom_media_ipc_RemoteDecoderModule_h
|
||||
#define include_dom_media_ipc_RemoteDecoderModule_h
|
||||
#include "PlatformDecoderModule.h"
|
||||
#include "mozilla/StaticMutex.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
|
@ -18,8 +17,6 @@ class RemoteDecoderModule : public PlatformDecoderModule {
|
|||
public:
|
||||
static void Init();
|
||||
|
||||
RemoteDecoderModule();
|
||||
|
||||
bool SupportsMimeType(const nsACString& aMimeType,
|
||||
DecoderDoctorDiagnostics* aDiagnostics) const override;
|
||||
|
||||
|
@ -28,9 +25,6 @@ class RemoteDecoderModule : public PlatformDecoderModule {
|
|||
|
||||
already_AddRefed<MediaDataDecoder> CreateAudioDecoder(
|
||||
const CreateDecoderParams& aParams) override;
|
||||
|
||||
private:
|
||||
const nsCOMPtr<nsISerialEventTarget> mManagerThread;
|
||||
};
|
||||
|
||||
} // namespace mozilla
|
||||
|
|
|
@ -160,10 +160,10 @@ RemoteImageHolder::~RemoteImageHolder() {
|
|||
return false;
|
||||
}
|
||||
if (!aResult->mEmpty) {
|
||||
aResult->mManager =
|
||||
aResult->mManager = RemoteDecoderManagerChild::GetSingleton(
|
||||
aResult->mSource == VideoBridgeSource::GpuProcess
|
||||
? RemoteDecoderManagerChild::GetGPUProcessSingleton()
|
||||
: RemoteDecoderManagerChild::GetRDDProcessSingleton();
|
||||
? RemoteDecodeIn::GpuProcess
|
||||
: RemoteDecodeIn::RddProcess);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -13,7 +13,7 @@ namespace mozilla {
|
|||
|
||||
class GpuDecoderModule;
|
||||
class IRemoteDecoderChild;
|
||||
class RemoteDecoderModule;
|
||||
class RemoteDecoderManagerChild;
|
||||
class RemoteMediaDataDecoder;
|
||||
|
||||
DDLoggedTypeCustomNameAndBase(RemoteMediaDataDecoder, RemoteMediaDataDecoder,
|
||||
|
@ -28,7 +28,7 @@ class RemoteMediaDataDecoder
|
|||
public DecoderDoctorLifeLogger<RemoteMediaDataDecoder> {
|
||||
public:
|
||||
friend class GpuDecoderModule;
|
||||
friend class RemoteDecoderModule;
|
||||
friend class RemoteDecoderManagerChild;
|
||||
|
||||
// MediaDataDecoder
|
||||
RefPtr<InitPromise> Init() override;
|
||||
|
|
|
@ -19,7 +19,6 @@
|
|||
#include "MediaDataDecoderProxy.h"
|
||||
#include "MediaInfo.h"
|
||||
#include "PDMFactory.h"
|
||||
#include "RemoteDecoderManagerChild.h"
|
||||
#include "RemoteDecoderManagerParent.h"
|
||||
#include "RemoteImageHolder.h"
|
||||
#include "mozilla/StaticPrefs_media.h"
|
||||
|
@ -70,9 +69,10 @@ class KnowsCompositorVideo : public layers::KnowsCompositor {
|
|||
virtual ~KnowsCompositorVideo() = default;
|
||||
};
|
||||
|
||||
RemoteVideoDecoderChild::RemoteVideoDecoderChild(bool aRecreatedOnCrash)
|
||||
: RemoteDecoderChild(aRecreatedOnCrash),
|
||||
mBufferRecycleBin(new BufferRecycleBin) {}
|
||||
RemoteVideoDecoderChild::RemoteVideoDecoderChild(RemoteDecodeIn aLocation)
|
||||
: RemoteDecoderChild(aLocation == RemoteDecodeIn::GpuProcess),
|
||||
mBufferRecycleBin(new BufferRecycleBin),
|
||||
mLocation(aLocation) {}
|
||||
|
||||
MediaResult RemoteVideoDecoderChild::ProcessOutput(
|
||||
DecodedOutputIPDL&& aDecodedData) {
|
||||
|
@ -102,8 +102,10 @@ MediaResult RemoteVideoDecoderChild::InitIPDL(
|
|||
const VideoInfo& aVideoInfo, float aFramerate,
|
||||
const CreateDecoderParams::OptionSet& aOptions,
|
||||
const layers::TextureFactoryIdentifier* aIdentifier) {
|
||||
MOZ_ASSERT_IF(mLocation == RemoteDecodeIn::GpuProcess, aIdentifier);
|
||||
|
||||
RefPtr<RemoteDecoderManagerChild> manager =
|
||||
RemoteDecoderManagerChild::GetRDDProcessSingleton();
|
||||
RemoteDecoderManagerChild::GetSingleton(mLocation);
|
||||
|
||||
// The manager isn't available because RemoteDecoderManagerChild has been
|
||||
// initialized with null end points and we don't want to decode video on RDD
|
||||
|
@ -114,6 +116,16 @@ MediaResult RemoteVideoDecoderChild::InitIPDL(
|
|||
}
|
||||
|
||||
if (!manager->CanSend()) {
|
||||
if (mLocation == RemoteDecodeIn::GpuProcess) {
|
||||
// The manager doesn't support sending messages because we've just crashed
|
||||
// and are working on reinitialization. Don't initialize mIPDLSelfRef and
|
||||
// leave us in an error state. We'll then immediately reject the promise
|
||||
// when Init() is called and the caller can try again. Hopefully by then
|
||||
// the new manager is ready, or we've notified the caller of it being no
|
||||
// longer available. If not, then the cycle repeats until we're ready.
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
return MediaResult(NS_ERROR_DOM_MEDIA_FATAL_ERR,
|
||||
RESULT_DETAIL("RemoteDecoderManager unable to send."));
|
||||
}
|
||||
|
@ -130,46 +142,6 @@ MediaResult RemoteVideoDecoderChild::InitIPDL(
|
|||
: MediaResult(NS_ERROR_DOM_MEDIA_FATAL_ERR, errorDescription);
|
||||
}
|
||||
|
||||
GpuRemoteVideoDecoderChild::GpuRemoteVideoDecoderChild()
|
||||
: RemoteVideoDecoderChild(true) {}
|
||||
|
||||
MediaResult GpuRemoteVideoDecoderChild::InitIPDL(
|
||||
const VideoInfo& aVideoInfo, float aFramerate,
|
||||
const CreateDecoderParams::OptionSet& aOptions,
|
||||
const layers::TextureFactoryIdentifier& aIdentifier) {
|
||||
RefPtr<RemoteDecoderManagerChild> manager =
|
||||
RemoteDecoderManagerChild::GetGPUProcessSingleton();
|
||||
|
||||
// The manager isn't available because RemoteDecoderManagerChild has been
|
||||
// initialized with null end points and we don't want to decode video on GPU
|
||||
// process anymore. Return false here so that we can fallback to other PDMs.
|
||||
if (!manager) {
|
||||
return MediaResult(NS_ERROR_DOM_MEDIA_FATAL_ERR,
|
||||
RESULT_DETAIL("RemoteDecoderManager is not available."));
|
||||
}
|
||||
|
||||
// The manager doesn't support sending messages because we've just crashed
|
||||
// and are working on reinitialization. Don't initialize mIPDLSelfRef and
|
||||
// leave us in an error state. We'll then immediately reject the promise when
|
||||
// Init() is called and the caller can try again. Hopefully by then the new
|
||||
// manager is ready, or we've notified the caller of it being no longer
|
||||
// available. If not, then the cycle repeats until we're ready.
|
||||
if (!manager->CanSend()) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
mIPDLSelfRef = this;
|
||||
bool success = false;
|
||||
nsCString errorDescription;
|
||||
VideoDecoderInfoIPDL decoderInfo(aVideoInfo, aFramerate);
|
||||
Unused << manager->SendPRemoteDecoderConstructor(this, decoderInfo, aOptions,
|
||||
Some(aIdentifier), &success,
|
||||
&errorDescription);
|
||||
|
||||
return success ? MediaResult(NS_OK)
|
||||
: MediaResult(NS_ERROR_DOM_MEDIA_FATAL_ERR, errorDescription);
|
||||
}
|
||||
|
||||
RemoteVideoDecoderParent::RemoteVideoDecoderParent(
|
||||
RemoteDecoderManagerParent* aParent, const VideoInfo& aVideoInfo,
|
||||
float aFramerate, const CreateDecoderParams::OptionSet& aOptions,
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
#ifndef include_dom_media_ipc_RemoteVideoDecoderChild_h
|
||||
#define include_dom_media_ipc_RemoteVideoDecoderChild_h
|
||||
#include "RemoteDecoderChild.h"
|
||||
#include "RemoteDecoderManagerChild.h"
|
||||
#include "RemoteDecoderParent.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
@ -17,31 +18,25 @@ class BufferRecycleBin;
|
|||
namespace mozilla {
|
||||
|
||||
class KnowsCompositorVideo;
|
||||
|
||||
using mozilla::ipc::IPCResult;
|
||||
|
||||
class RemoteVideoDecoderChild : public RemoteDecoderChild {
|
||||
public:
|
||||
explicit RemoteVideoDecoderChild(bool aRecreatedOnCrash = false);
|
||||
explicit RemoteVideoDecoderChild(RemoteDecodeIn aLocation);
|
||||
|
||||
MOZ_IS_CLASS_INIT
|
||||
MediaResult InitIPDL(const VideoInfo& aVideoInfo, float aFramerate,
|
||||
const CreateDecoderParams::OptionSet& aOptions,
|
||||
const layers::TextureFactoryIdentifier* aIdentifier);
|
||||
MOZ_IS_CLASS_INIT MediaResult
|
||||
InitIPDL(const VideoInfo& aVideoInfo, float aFramerate,
|
||||
const CreateDecoderParams::OptionSet& aOptions,
|
||||
const layers::TextureFactoryIdentifier* aIdentifier);
|
||||
|
||||
MediaResult ProcessOutput(DecodedOutputIPDL&& aDecodedData) override;
|
||||
|
||||
private:
|
||||
RefPtr<mozilla::layers::BufferRecycleBin> mBufferRecycleBin;
|
||||
};
|
||||
|
||||
class GpuRemoteVideoDecoderChild final : public RemoteVideoDecoderChild {
|
||||
public:
|
||||
GpuRemoteVideoDecoderChild();
|
||||
|
||||
MOZ_IS_CLASS_INIT
|
||||
MediaResult InitIPDL(const VideoInfo& aVideoInfo, float aFramerate,
|
||||
const CreateDecoderParams::OptionSet& aOptions,
|
||||
const layers::TextureFactoryIdentifier& aIdentifier);
|
||||
// The location of the RemoteVideoDecoderParent - Gpu or Rdd process.
|
||||
const RemoteDecodeIn mLocation;
|
||||
};
|
||||
|
||||
class RemoteVideoDecoderParent final : public RemoteDecoderParent {
|
||||
|
|
|
@ -86,6 +86,12 @@ struct MOZ_STACK_CLASS CreateDecoderParams final {
|
|||
Set(std::forward<T1>(a1), std::forward<Ts>(args)...);
|
||||
}
|
||||
|
||||
template <typename T1, typename... Ts>
|
||||
CreateDecoderParams(const CreateDecoderParams& aParams, T1&& a1, Ts&&... args)
|
||||
: CreateDecoderParams(aParams) {
|
||||
Set(std::forward<T1>(a1), std::forward<Ts>(args)...);
|
||||
}
|
||||
|
||||
const VideoInfo& VideoConfig() const {
|
||||
MOZ_ASSERT(mConfig.IsVideo());
|
||||
return *mConfig.GetAsVideoInfo();
|
||||
|
|
Загрузка…
Ссылка в новой задаче