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:
Dan Glastonbury 2020-10-20 23:23:58 +00:00
Родитель 5cc27aec49
Коммит 29f6310810
11 изменённых файлов: 185 добавлений и 195 удалений

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

@ -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();