Bug 1471535 - pt7 - Add remote decoding in dom/media/ipc alongside gpu decoding. r=jya,mattwoodrow,jld

Depends on D8488

Differential Revision: https://phabricator.services.mozilla.com/D8489

--HG--
extra : moz-landing-system : lando
This commit is contained in:
Michael Froman 2018-11-09 00:12:46 +00:00
Родитель e1e4d7186c
Коммит 95000decd4
17 изменённых файлов: 1538 добавлений и 0 удалений

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

@ -44,6 +44,49 @@ namespace IPC {
return false;
}
};
template<>
struct ParamTraits<mozilla::AudioInfo>
{
typedef mozilla::AudioInfo paramType;
static void Write(Message* aMsg, const paramType& aParam)
{
// TrackInfo
WriteParam(aMsg, aParam.mMimeType);
// AudioInfo
WriteParam(aMsg, aParam.mRate);
WriteParam(aMsg, aParam.mChannels);
WriteParam(aMsg, aParam.mChannelMap);
WriteParam(aMsg, aParam.mBitDepth);
WriteParam(aMsg, aParam.mProfile);
WriteParam(aMsg, aParam.mExtendedProfile);
}
static bool Read(const Message* aMsg, PickleIterator* aIter, paramType* aResult)
{
if (ReadParam(aMsg, aIter, &aResult->mMimeType) &&
ReadParam(aMsg, aIter, &aResult->mRate) &&
ReadParam(aMsg, aIter, &aResult->mChannels) &&
ReadParam(aMsg, aIter, &aResult->mChannelMap) &&
ReadParam(aMsg, aIter, &aResult->mBitDepth) &&
ReadParam(aMsg, aIter, &aResult->mProfile) &&
ReadParam(aMsg, aIter, &aResult->mExtendedProfile)) {
return true;
}
return false;
}
};
template<>
struct ParamTraits<mozilla::MediaDataDecoder::ConversionRequired>
: public ContiguousEnumSerializerInclusive<
mozilla::MediaDataDecoder::ConversionRequired,
mozilla::MediaDataDecoder::ConversionRequired(0),
mozilla::MediaDataDecoder::ConversionRequired(
mozilla::MediaDataDecoder::ConversionRequired::kNeedAnnexB)> {};
} // namespace IPC
#endif // mozilla_dom_media_MediaIPCUtils_h

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

@ -0,0 +1,27 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
include protocol PRemoteVideoDecoder;
include "mozilla/dom/MediaIPCUtils.h";
using VideoInfo from "MediaInfo.h";
using AudioInfo from "MediaInfo.h";
using mozilla::CreateDecoderParams::OptionSet from "PlatformDecoderModule.h";
namespace mozilla {
sync protocol PRemoteDecoderManager
{
manages PRemoteVideoDecoder;
parent:
sync PRemoteVideoDecoder(VideoInfo info,
float framerate,
OptionSet options)
returns (bool success,
nsCString aErrorDescription);
};
} // namespace mozilla

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

@ -0,0 +1,60 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
include "mozilla/dom/MediaIPCUtils.h";
include protocol PRemoteDecoderManager;
include PMediaDecoderParams;
include LayersSurfaces;
using mozilla::MediaDataDecoder::ConversionRequired from "PlatformDecoderModule.h";
namespace mozilla {
struct RemoteVideoDataIPDL
{
MediaDataIPDL base;
IntSize display;
IntSize frameSize;
SurfaceDescriptorBuffer sdBuffer;
int32_t frameID;
};
// This protocol provides a way to use MediaDataDecoder across processes.
// The parent side currently is only implemented to work with
// RemoteDecoderModule.
// The child side runs in the content process, and the parent side runs
// in the RDD process. We run a separate IPDL thread for both sides.
async protocol PRemoteVideoDecoder
{
manager PRemoteDecoderManager;
parent:
async Init();
async Input(MediaRawDataIPDL data);
async Flush();
async Drain();
async Shutdown();
async SetSeekThreshold(int64_t time);
async __delete__();
child:
async InitComplete(nsCString decoderDescription,
ConversionRequired conversion);
async InitFailed(nsresult reason);
async FlushComplete();
// Each output includes a SurfaceDescriptorBuffer that represents the decoded
// frame.
async VideoOutput(RemoteVideoDataIPDL data);
async InputExhausted();
async DrainComplete();
async Error(nsresult error);
};
} // namespace mozilla

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

@ -0,0 +1,151 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=99: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "RemoteDecoderManagerChild.h"
#include "base/task.h"
#include "RemoteVideoDecoderChild.h"
namespace mozilla {
// Only modified on the main-thread
StaticRefPtr<nsIThread> sRemoteDecoderManagerChildThread;
StaticRefPtr<AbstractThread> sRemoteDecoderManagerChildAbstractThread;
// Only accessed from sRemoteDecoderManagerChildThread
static StaticRefPtr<RemoteDecoderManagerChild> sRemoteDecoderManagerChild;
/* static */ 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;
sRemoteDecoderManagerChildAbstractThread =
AbstractThread::CreateXPCOMThreadWrapper(childThread, false);
}
}
/* static */ void
RemoteDecoderManagerChild::InitForContent(
Endpoint<PRemoteDecoderManagerChild>&& aVideoManager)
{
InitializeThread();
sRemoteDecoderManagerChildThread->Dispatch(
NewRunnableFunction("InitForContentRunnable",
&Open,
std::move(aVideoManager)),
NS_DISPATCH_NORMAL);
}
/* static */ void
RemoteDecoderManagerChild::Shutdown()
{
MOZ_ASSERT(NS_IsMainThread());
if (sRemoteDecoderManagerChildThread) {
sRemoteDecoderManagerChildThread->Dispatch(
NS_NewRunnableFunction("dom::RemoteDecoderManagerChild::Shutdown",
[]() {
if (sRemoteDecoderManagerChild &&
sRemoteDecoderManagerChild->CanSend()) {
sRemoteDecoderManagerChild->Close();
sRemoteDecoderManagerChild = nullptr;
}
}),
NS_DISPATCH_NORMAL);
sRemoteDecoderManagerChildAbstractThread = nullptr;
sRemoteDecoderManagerChildThread->Shutdown();
sRemoteDecoderManagerChildThread = nullptr;
}
}
/* static */ RemoteDecoderManagerChild*
RemoteDecoderManagerChild::GetSingleton()
{
MOZ_ASSERT(NS_GetCurrentThread() == GetManagerThread());
return sRemoteDecoderManagerChild;
}
/* static */ nsIThread*
RemoteDecoderManagerChild::GetManagerThread()
{
return sRemoteDecoderManagerChildThread;
}
/* static */ AbstractThread*
RemoteDecoderManagerChild::GetManagerAbstractThread()
{
return sRemoteDecoderManagerChildAbstractThread;
}
PRemoteVideoDecoderChild*
RemoteDecoderManagerChild::AllocPRemoteVideoDecoderChild(
const VideoInfo& /* not used */,
const float& /* not used */,
const CreateDecoderParams::OptionSet& /* not used */,
bool* /* not used */,
nsCString* /* not used */)
{
return new RemoteVideoDecoderChild();
}
bool
RemoteDecoderManagerChild::DeallocPRemoteVideoDecoderChild(
PRemoteVideoDecoderChild* actor)
{
RemoteVideoDecoderChild* child = static_cast<RemoteVideoDecoderChild*>(actor);
child->IPDLActorDestroyed();
return true;
}
void
RemoteDecoderManagerChild::Open(
Endpoint<PRemoteDecoderManagerChild>&& aEndpoint)
{
sRemoteDecoderManagerChild = nullptr;
if (aEndpoint.IsValid()) {
RefPtr<RemoteDecoderManagerChild> manager = new RemoteDecoderManagerChild();
if (aEndpoint.Bind(manager)) {
sRemoteDecoderManagerChild = manager;
manager->InitIPDL();
}
}
}
void
RemoteDecoderManagerChild::InitIPDL()
{
mCanSend = true;
mIPDLSelfRef = this;
}
void
RemoteDecoderManagerChild::ActorDestroy(ActorDestroyReason aWhy)
{
mCanSend = false;
}
void
RemoteDecoderManagerChild::DeallocPRemoteDecoderManagerChild()
{
mIPDLSelfRef = nullptr;
}
bool
RemoteDecoderManagerChild::CanSend()
{
MOZ_ASSERT(NS_GetCurrentThread() == GetManagerThread());
return mCanSend;
}
} // namespace mozilla

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

@ -0,0 +1,63 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=99: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef include_dom_media_ipc_RemoteDecoderManagerChild_h
#define include_dom_media_ipc_RemoteDecoderManagerChild_h
#include "mozilla/PRemoteDecoderManagerChild.h"
namespace mozilla {
class RemoteDecoderManagerChild final : public PRemoteDecoderManagerChild
{
public:
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(RemoteDecoderManagerChild)
// Can only be called from the manager thread
static RemoteDecoderManagerChild* GetSingleton();
// Can be called from any thread.
static nsIThread* GetManagerThread();
static AbstractThread* GetManagerAbstractThread();
// Main thread only
static void InitForContent(
Endpoint<PRemoteDecoderManagerChild>&& aVideoManager);
static void Shutdown();
bool CanSend();
protected:
void InitIPDL();
void ActorDestroy(ActorDestroyReason aWhy) override;
void DeallocPRemoteDecoderManagerChild() override;
PRemoteVideoDecoderChild* AllocPRemoteVideoDecoderChild(
const VideoInfo& aVideoInfo,
const float& aFramerate,
const CreateDecoderParams::OptionSet& aOptions,
bool* aSuccess,
nsCString* aErrorDescription) override;
bool DeallocPRemoteVideoDecoderChild(
PRemoteVideoDecoderChild* actor) override;
private:
// Main thread only
static void InitializeThread();
RemoteDecoderManagerChild() = default;
~RemoteDecoderManagerChild() = default;
static void Open(Endpoint<PRemoteDecoderManagerChild>&& aEndpoint);
RefPtr<RemoteDecoderManagerChild> mIPDLSelfRef;
// Should only ever be accessed on the manager thread.
bool mCanSend = false;
};
} // namespace mozilla
#endif // include_dom_media_ipc_RemoteDecoderManagerChild_h

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

@ -0,0 +1,216 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=99: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "RemoteDecoderManagerParent.h"
#if XP_WIN
#include <objbase.h>
#endif
#include "RemoteVideoDecoderParent.h"
#include "VideoUtils.h" // for MediaThreadType
namespace mozilla {
StaticRefPtr<nsIThread> sRemoteDecoderManagerParentThread;
StaticRefPtr<TaskQueue> sRemoteDecoderManagerTaskQueue;
class RemoteDecoderManagerThreadHolder
{
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(RemoteDecoderManagerThreadHolder)
public:
RemoteDecoderManagerThreadHolder() { }
private:
~RemoteDecoderManagerThreadHolder()
{
NS_DispatchToMainThread(NS_NewRunnableFunction(
"dom::RemoteDecoderManagerThreadHolder::~RemoteDecoderManagerThreadHolder",
[]() {
sRemoteDecoderManagerParentThread->Shutdown();
sRemoteDecoderManagerParentThread = nullptr;
}));
}
};
StaticRefPtr<RemoteDecoderManagerThreadHolder>
sRemoteDecoderManagerParentThreadHolder;
class RemoteDecoderManagerThreadShutdownObserver : public nsIObserver
{
virtual ~RemoteDecoderManagerThreadShutdownObserver() = default;
public:
RemoteDecoderManagerThreadShutdownObserver() = default;
NS_DECL_ISUPPORTS
NS_IMETHOD Observe(nsISupports* aSubject, const char* aTopic,
const char16_t* aData) override
{
MOZ_ASSERT(strcmp(aTopic, NS_XPCOM_SHUTDOWN_OBSERVER_ID) == 0);
RemoteDecoderManagerParent::ShutdownThreads();
return NS_OK;
}
};
NS_IMPL_ISUPPORTS(RemoteDecoderManagerThreadShutdownObserver, nsIObserver);
bool
RemoteDecoderManagerParent::StartupThreads()
{
MOZ_ASSERT(NS_IsMainThread());
if (sRemoteDecoderManagerParentThread) {
return true;
}
nsCOMPtr<nsIObserverService> observerService = services::GetObserverService();
if (!observerService) {
return false;
}
RefPtr<nsIThread> managerThread;
nsresult rv =
NS_NewNamedThread("RemVidParent", getter_AddRefs(managerThread));
if (NS_FAILED(rv)) {
return false;
}
sRemoteDecoderManagerParentThread = managerThread;
sRemoteDecoderManagerParentThreadHolder =
new RemoteDecoderManagerThreadHolder();
#if XP_WIN
sRemoteDecoderManagerParentThread->Dispatch(
NS_NewRunnableFunction(
"RemoteDecoderManagerParent::StartupThreads",
[]() {
DebugOnly<HRESULT> hr = CoInitializeEx(0, COINIT_MULTITHREADED);
MOZ_ASSERT(SUCCEEDED(hr));
}),
NS_DISPATCH_NORMAL);
#endif
sRemoteDecoderManagerTaskQueue = new TaskQueue(
managerThread.forget(),
"RemoteDecoderManagerParent::sRemoteDecoderManagerTaskQueue");
auto* obs = new RemoteDecoderManagerThreadShutdownObserver();
observerService->AddObserver(obs, NS_XPCOM_SHUTDOWN_OBSERVER_ID, false);
return true;
}
void
RemoteDecoderManagerParent::ShutdownThreads()
{
sRemoteDecoderManagerTaskQueue = nullptr;
sRemoteDecoderManagerParentThreadHolder = nullptr;
while (sRemoteDecoderManagerParentThread) {
NS_ProcessNextEvent(nullptr, true);
}
}
bool
RemoteDecoderManagerParent::OnManagerThread()
{
return NS_GetCurrentThread() == sRemoteDecoderManagerParentThread;
}
bool
RemoteDecoderManagerParent::CreateForContent(
Endpoint<PRemoteDecoderManagerParent>&& aEndpoint)
{
MOZ_ASSERT(XRE_GetProcessType() == GeckoProcessType_RDD);
MOZ_ASSERT(NS_IsMainThread());
if (!StartupThreads()) {
return false;
}
RefPtr<RemoteDecoderManagerParent> parent =
new RemoteDecoderManagerParent(sRemoteDecoderManagerParentThreadHolder);
RefPtr<Runnable> task =
NewRunnableMethod<Endpoint<PRemoteDecoderManagerParent>&&>(
"dom::RemoteDecoderManagerParent::Open",
parent,
&RemoteDecoderManagerParent::Open,
std::move(aEndpoint));
sRemoteDecoderManagerParentThread->Dispatch(task.forget(),
NS_DISPATCH_NORMAL);
return true;
}
RemoteDecoderManagerParent::RemoteDecoderManagerParent(
RemoteDecoderManagerThreadHolder* aHolder)
: mThreadHolder(aHolder)
{
MOZ_COUNT_CTOR(RemoteDecoderManagerParent);
}
RemoteDecoderManagerParent::~RemoteDecoderManagerParent()
{
MOZ_COUNT_DTOR(RemoteDecoderManagerParent);
}
void
RemoteDecoderManagerParent::ActorDestroy(
mozilla::ipc::IProtocol::ActorDestroyReason)
{
mThreadHolder = nullptr;
}
PRemoteVideoDecoderParent*
RemoteDecoderManagerParent::AllocPRemoteVideoDecoderParent(
const VideoInfo& aVideoInfo,
const float& aFramerate,
const CreateDecoderParams::OptionSet& aOptions,
bool* aSuccess,
nsCString* aErrorDescription)
{
RefPtr<TaskQueue> decodeTaskQueue = new TaskQueue(
GetMediaThreadPool(MediaThreadType::PLATFORM_DECODER),
"RemoteVideoDecoderParent::mDecodeTaskQueue");
auto* parent = new RemoteVideoDecoderParent(this,
aVideoInfo,
aFramerate,
aOptions,
sRemoteDecoderManagerTaskQueue,
decodeTaskQueue,
aSuccess,
aErrorDescription);
return parent;
}
bool
RemoteDecoderManagerParent::DeallocPRemoteVideoDecoderParent(
PRemoteVideoDecoderParent* actor)
{
RemoteVideoDecoderParent* parent =
static_cast<RemoteVideoDecoderParent*>(actor);
parent->Destroy();
return true;
}
void
RemoteDecoderManagerParent::Open(
Endpoint<PRemoteDecoderManagerParent>&& aEndpoint)
{
if (!aEndpoint.Bind(this)) {
// We can't recover from this.
MOZ_CRASH("Failed to bind RemoteDecoderManagerParent to endpoint");
}
AddRef();
}
void
RemoteDecoderManagerParent::DeallocPRemoteDecoderManagerParent()
{
Release();
}
} // namespace mozilla

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

@ -0,0 +1,53 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=99: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef include_dom_media_ipc_RemoteDecoderManagerParent_h
#define include_dom_media_ipc_RemoteDecoderManagerParent_h
#include "mozilla/PRemoteDecoderManagerParent.h"
namespace mozilla {
class RemoteDecoderManagerThreadHolder;
class RemoteDecoderManagerParent final : public PRemoteDecoderManagerParent
{
public:
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(RemoteDecoderManagerParent)
static bool CreateForContent(
Endpoint<PRemoteDecoderManagerParent>&& aEndpoint);
static bool StartupThreads();
static void ShutdownThreads();
bool OnManagerThread();
protected:
PRemoteVideoDecoderParent* AllocPRemoteVideoDecoderParent(
const VideoInfo& aVideoInfo,
const float& aFramerate,
const CreateDecoderParams::OptionSet& aOptions,
bool* aSuccess,
nsCString* aErrorDescription) override;
bool DeallocPRemoteVideoDecoderParent(
PRemoteVideoDecoderParent* actor) override;
void ActorDestroy(mozilla::ipc::IProtocol::ActorDestroyReason) override;
void DeallocPRemoteDecoderManagerParent() override;
private:
explicit RemoteDecoderManagerParent(
RemoteDecoderManagerThreadHolder* aThreadHolder);
~RemoteDecoderManagerParent();
void Open(Endpoint<PRemoteDecoderManagerParent>&& aEndpoint);
RefPtr<RemoteDecoderManagerThreadHolder> mThreadHolder;
};
} // namespace mozilla
#endif // include_dom_media_ipc_RemoteDecoderManagerParent_h

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

@ -0,0 +1,89 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=99: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "RemoteDecoderModule.h"
#include "base/thread.h"
#include "mozilla/layers/SynchronousTask.h"
#include "mozilla/StaticPrefs.h"
#ifdef MOZ_AV1
#include "AOMDecoder.h"
#endif
#include "RemoteDecoderManagerChild.h"
#include "RemoteMediaDataDecoder.h"
#include "RemoteVideoDecoderChild.h"
namespace mozilla {
using base::Thread;
using namespace ipc;
using namespace layers;
using namespace gfx;
nsresult
RemoteDecoderModule::Startup()
{
if (!RemoteDecoderManagerChild::GetManagerThread()) {
return NS_ERROR_FAILURE;
}
return NS_OK;
}
bool
RemoteDecoderModule::SupportsMimeType(
const nsACString& aMimeType,
DecoderDoctorDiagnostics* aDiagnostics) const
{
bool supports = false;
#ifdef MOZ_AV1
if (StaticPrefs::MediaAv1Enabled()) {
supports |= AOMDecoder::IsAV1(aMimeType);
}
#endif
MOZ_LOG(sPDMLog, LogLevel::Debug, ("Sandbox decoder %s requested type",
supports ? "supports" : "rejects"));
return supports;
}
already_AddRefed<MediaDataDecoder>
RemoteDecoderModule::CreateVideoDecoder(const CreateDecoderParams& aParams)
{
RemoteVideoDecoderChild* child = new RemoteVideoDecoderChild();
RefPtr<RemoteMediaDataDecoder> object =
new RemoteMediaDataDecoder(
child,
RemoteDecoderManagerChild::GetManagerThread(),
RemoteDecoderManagerChild::GetManagerAbstractThread());
// (per Matt Woodrow) We can't use NS_DISPATCH_SYNC here since that
// can spin the event loop while it waits.
SynchronousTask task("InitIPDL");
MediaResult result(NS_OK);
RemoteDecoderManagerChild::GetManagerThread()->Dispatch(
NS_NewRunnableFunction(
"dom::RemoteDecoderModule::CreateVideoDecoder",
[&]() {
AutoCompleteTask complete(&task);
result = child->InitIPDL(
aParams.VideoConfig(),
aParams.mRate.mValue,
aParams.mOptions);
}),
NS_DISPATCH_NORMAL);
task.Wait();
if (NS_FAILED(result)) {
if (aParams.mError) {
*aParams.mError = result;
}
return nullptr;
}
return object.forget();
}
} // namespace mozilla

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

@ -0,0 +1,38 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=99: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef include_dom_media_ipc_RemoteDecoderModule_h
#define include_dom_media_ipc_RemoteDecoderModule_h
#include "PlatformDecoderModule.h"
namespace mozilla {
// A PDM implementation that creates a RemoteMediaDataDecoder (a
// MediaDataDecoder) that proxies to a RemoteVideoDecoderChild.
// A decoder child will talk to its respective decoder parent
// (RemoteVideoDecoderParent) on the RDD process.
class RemoteDecoderModule : public PlatformDecoderModule
{
public:
RemoteDecoderModule() = default;
nsresult Startup() override;
bool SupportsMimeType(const nsACString& aMimeType,
DecoderDoctorDiagnostics* aDiagnostics) const override;
already_AddRefed<MediaDataDecoder> CreateVideoDecoder(
const CreateDecoderParams& aParams) override;
already_AddRefed<MediaDataDecoder> CreateAudioDecoder(
const CreateDecoderParams& aParams) override
{
return nullptr;
}
};
} // namespace mozilla
#endif // include_dom_media_ipc_RemoteDecoderModule_h

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

@ -13,6 +13,7 @@ namespace mozilla {
class GpuDecoderModule;
class IRemoteDecoderChild;
class RemoteDecoderModule;
class RemoteMediaDataDecoder;
DDLoggedTypeCustomNameAndBase(RemoteMediaDataDecoder,
@ -29,6 +30,7 @@ class RemoteMediaDataDecoder
{
public:
friend class GpuDecoderModule;
friend class RemoteDecoderModule;
// MediaDataDecoder
RefPtr<InitPromise> Init() override;

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

@ -0,0 +1,365 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=99: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "RemoteVideoDecoderChild.h"
#include "base/thread.h"
#include "mozilla/layers/ImageDataSerializer.h"
#include "ImageContainer.h" // for PlanarYCbCrData and BufferRecycleBin
#include "RemoteDecoderManagerChild.h"
namespace mozilla {
using base::Thread;
using namespace layers; // for PlanarYCbCrData and BufferRecycleBin
RemoteVideoDecoderChild::RemoteVideoDecoderChild()
: mThread(RemoteDecoderManagerChild::GetManagerThread())
, mCanSend(false)
, mInitialized(false)
, mIsHardwareAccelerated(false)
, mConversion(MediaDataDecoder::ConversionRequired::kNeedNone)
, mBufferRecycleBin(new BufferRecycleBin)
{
}
RemoteVideoDecoderChild::~RemoteVideoDecoderChild()
{
AssertOnManagerThread();
mInitPromise.RejectIfExists(NS_ERROR_DOM_MEDIA_CANCELED, __func__);
}
RefPtr<mozilla::layers::Image>
RemoteVideoDecoderChild::DeserializeImage(
const SurfaceDescriptorBuffer& aSdBuffer,
const IntSize& aPicSize)
{
MOZ_ASSERT(aSdBuffer.desc().type() == BufferDescriptor::TYCbCrDescriptor);
if (aSdBuffer.desc().type() != BufferDescriptor::TYCbCrDescriptor) {
return nullptr;
}
const YCbCrDescriptor& descriptor = aSdBuffer.desc().get_YCbCrDescriptor();
uint8_t* buffer = nullptr;
const MemoryOrShmem& memOrShmem = aSdBuffer.data();
switch (memOrShmem.type()) {
case MemoryOrShmem::Tuintptr_t:
buffer = reinterpret_cast<uint8_t*>(memOrShmem.get_uintptr_t());
break;
case MemoryOrShmem::TShmem:
buffer = memOrShmem.get_Shmem().get<uint8_t>();
break;
default:
MOZ_ASSERT(false, "Unknown MemoryOrShmem type");
}
if (!buffer) {
return nullptr;
}
PlanarYCbCrData pData;
pData.mYSize = descriptor.ySize();
pData.mYStride = descriptor.yStride();
pData.mCbCrSize = descriptor.cbCrSize();
pData.mCbCrStride = descriptor.cbCrStride();
// default mYSkip, mCbSkip, mCrSkip because not held in YCbCrDescriptor
pData.mYSkip = pData.mCbSkip = pData.mCrSkip = 0;
// default mPicX, mPicY because not held in YCbCrDescriptor
pData.mPicX = pData.mPicY = 0;
pData.mPicSize = aPicSize;
pData.mStereoMode = descriptor.stereoMode();
pData.mColorDepth = descriptor.colorDepth();
pData.mYUVColorSpace = descriptor.yUVColorSpace();
pData.mYChannel = ImageDataSerializer::GetYChannel(buffer, descriptor);
pData.mCbChannel = ImageDataSerializer::GetCbChannel(buffer, descriptor);
pData.mCrChannel = ImageDataSerializer::GetCrChannel(buffer, descriptor);
// images coming from AOMDecoder are RecyclingPlanarYCbCrImages.
RefPtr<RecyclingPlanarYCbCrImage> image =
new RecyclingPlanarYCbCrImage(mBufferRecycleBin);
image->CopyData(pData);
switch (memOrShmem.type()) {
case MemoryOrShmem::Tuintptr_t:
delete [] reinterpret_cast<uint8_t*>(memOrShmem.get_uintptr_t());
break;
case MemoryOrShmem::TShmem:
DeallocShmem(memOrShmem.get_Shmem());
break;
default:
MOZ_ASSERT(false, "Unknown MemoryOrShmem type");
}
return image;
}
mozilla::ipc::IPCResult
RemoteVideoDecoderChild::RecvVideoOutput(const RemoteVideoDataIPDL& aData)
{
AssertOnManagerThread();
RefPtr<Image> image = DeserializeImage(aData.sdBuffer(), aData.frameSize());
RefPtr<VideoData> video = VideoData::CreateFromImage(
aData.display(),
aData.base().offset(),
media::TimeUnit::FromMicroseconds(aData.base().time()),
media::TimeUnit::FromMicroseconds(aData.base().duration()),
image,
aData.base().keyframe(),
media::TimeUnit::FromMicroseconds(aData.base().timecode()));
mDecodedData.AppendElement(std::move(video));
return IPC_OK();
}
mozilla::ipc::IPCResult
RemoteVideoDecoderChild::RecvInputExhausted()
{
AssertOnManagerThread();
mDecodePromise.ResolveIfExists(mDecodedData, __func__);
mDecodedData.Clear();
return IPC_OK();
}
mozilla::ipc::IPCResult
RemoteVideoDecoderChild::RecvDrainComplete()
{
AssertOnManagerThread();
mDrainPromise.ResolveIfExists(mDecodedData, __func__);
mDecodedData.Clear();
return IPC_OK();
}
mozilla::ipc::IPCResult
RemoteVideoDecoderChild::RecvError(const nsresult& aError)
{
AssertOnManagerThread();
mDecodedData.Clear();
mDecodePromise.RejectIfExists(aError, __func__);
mDrainPromise.RejectIfExists(aError, __func__);
mFlushPromise.RejectIfExists(aError, __func__);
return IPC_OK();
}
mozilla::ipc::IPCResult
RemoteVideoDecoderChild::RecvInitComplete(const nsCString& aDecoderDescription,
const ConversionRequired& aConversion)
{
AssertOnManagerThread();
mInitPromise.ResolveIfExists(TrackInfo::kVideoTrack, __func__);
mInitialized = true;
mDescription = aDecoderDescription;
mConversion = aConversion;
return IPC_OK();
}
mozilla::ipc::IPCResult
RemoteVideoDecoderChild::RecvInitFailed(const nsresult& aReason)
{
AssertOnManagerThread();
mInitPromise.RejectIfExists(aReason, __func__);
return IPC_OK();
}
mozilla::ipc::IPCResult
RemoteVideoDecoderChild::RecvFlushComplete()
{
AssertOnManagerThread();
mFlushPromise.ResolveIfExists(true, __func__);
return IPC_OK();
}
void
RemoteVideoDecoderChild::ActorDestroy(ActorDestroyReason aWhy)
{
mCanSend = false;
}
MediaResult
RemoteVideoDecoderChild::InitIPDL(
const VideoInfo& aVideoInfo,
float aFramerate,
const CreateDecoderParams::OptionSet& aOptions)
{
RefPtr<RemoteDecoderManagerChild> manager =
RemoteDecoderManagerChild::GetSingleton();
// The manager isn't available because RemoteDecoderManagerChild has been
// initialized with null end points and we don't want to decode video on RDD
// 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."));
}
if (!manager->CanSend()) {
return MediaResult(NS_ERROR_DOM_MEDIA_FATAL_ERR,
RESULT_DETAIL("RemoteDecoderManager unable to send."));
}
mIPDLSelfRef = this;
bool success = false;
nsCString errorDescription;
if (manager->SendPRemoteVideoDecoderConstructor(this,
aVideoInfo,
aFramerate,
aOptions,
&success,
&errorDescription)) {
mCanSend = true;
}
return success ? MediaResult(NS_OK) :
MediaResult(NS_ERROR_DOM_MEDIA_FATAL_ERR, errorDescription);
}
void
RemoteVideoDecoderChild::DestroyIPDL()
{
if (mCanSend) {
PRemoteVideoDecoderChild::Send__delete__(this);
}
}
void
RemoteVideoDecoderChild::IPDLActorDestroyed()
{
mIPDLSelfRef = nullptr;
}
// MediaDataDecoder methods
RefPtr<MediaDataDecoder::InitPromise>
RemoteVideoDecoderChild::Init()
{
AssertOnManagerThread();
if (!mIPDLSelfRef || !mCanSend) {
return MediaDataDecoder::InitPromise::CreateAndReject(
NS_ERROR_DOM_MEDIA_DECODE_ERR, __func__);
}
SendInit();
return mInitPromise.Ensure(__func__);
}
RefPtr<MediaDataDecoder::DecodePromise>
RemoteVideoDecoderChild::Decode(MediaRawData* aSample)
{
AssertOnManagerThread();
if (!mCanSend) {
return MediaDataDecoder::DecodePromise::CreateAndReject(
NS_ERROR_DOM_MEDIA_DECODE_ERR, __func__);
}
// TODO: It would be nice to add an allocator method to
// MediaDataDecoder so that the demuxer could write directly
// into shmem rather than requiring a copy here.
Shmem buffer;
if (!AllocShmem(aSample->Size(), Shmem::SharedMemory::TYPE_BASIC, &buffer)) {
return MediaDataDecoder::DecodePromise::CreateAndReject(
NS_ERROR_DOM_MEDIA_DECODE_ERR, __func__);
}
memcpy(buffer.get<uint8_t>(), aSample->Data(), aSample->Size());
MediaRawDataIPDL sample(MediaDataIPDL(aSample->mOffset,
aSample->mTime.ToMicroseconds(),
aSample->mTimecode.ToMicroseconds(),
aSample->mDuration.ToMicroseconds(),
aSample->mFrames,
aSample->mKeyframe),
buffer);
SendInput(sample);
return mDecodePromise.Ensure(__func__);
}
RefPtr<MediaDataDecoder::FlushPromise>
RemoteVideoDecoderChild::Flush()
{
AssertOnManagerThread();
mDecodePromise.RejectIfExists(NS_ERROR_DOM_MEDIA_CANCELED, __func__);
mDrainPromise.RejectIfExists(NS_ERROR_DOM_MEDIA_CANCELED, __func__);
if (!mCanSend) {
return MediaDataDecoder::FlushPromise::CreateAndReject(
NS_ERROR_DOM_MEDIA_DECODE_ERR, __func__);
}
SendFlush();
return mFlushPromise.Ensure(__func__);
}
RefPtr<MediaDataDecoder::DecodePromise>
RemoteVideoDecoderChild::Drain()
{
AssertOnManagerThread();
if (!mCanSend) {
return MediaDataDecoder::DecodePromise::CreateAndReject(
NS_ERROR_DOM_MEDIA_DECODE_ERR, __func__);
}
SendDrain();
return mDrainPromise.Ensure(__func__);
}
void
RemoteVideoDecoderChild::Shutdown()
{
AssertOnManagerThread();
mInitPromise.RejectIfExists(NS_ERROR_DOM_MEDIA_CANCELED, __func__);
if (mCanSend) {
SendShutdown();
}
mInitialized = false;
}
bool
RemoteVideoDecoderChild::IsHardwareAccelerated(nsACString& aFailureReason) const
{
AssertOnManagerThread();
aFailureReason = mHardwareAcceleratedReason;
return mIsHardwareAccelerated;
}
nsCString
RemoteVideoDecoderChild::GetDescriptionName() const
{
AssertOnManagerThread();
return mDescription;
}
void
RemoteVideoDecoderChild::SetSeekThreshold(const media::TimeUnit& aTime)
{
AssertOnManagerThread();
if (mCanSend) {
SendSetSeekThreshold(aTime.ToMicroseconds());
}
}
MediaDataDecoder::ConversionRequired
RemoteVideoDecoderChild::NeedsConversion() const
{
AssertOnManagerThread();
return mConversion;
}
void
RemoteVideoDecoderChild::AssertOnManagerThread() const
{
MOZ_ASSERT(NS_GetCurrentThread() == mThread);
}
RemoteDecoderManagerChild*
RemoteVideoDecoderChild::GetManager()
{
if (!mCanSend) {
return nullptr;
}
return static_cast<RemoteDecoderManagerChild*>(Manager());
}
} // namespace mozilla

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

@ -0,0 +1,94 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=99: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef include_dom_media_ipc_RemoteVideoDecoderChild_h
#define include_dom_media_ipc_RemoteVideoDecoderChild_h
#include "mozilla/PRemoteVideoDecoderChild.h"
#include "IRemoteDecoderChild.h"
#include "MediaResult.h"
namespace mozilla {
namespace layers {
class BufferRecycleBin;
}
}
namespace mozilla {
class RemoteDecoderManagerChild;
using mozilla::MediaDataDecoder;
class RemoteVideoDecoderChild final : public PRemoteVideoDecoderChild
, public IRemoteDecoderChild
{
public:
explicit RemoteVideoDecoderChild();
// PRemoteVideoDecoderChild
mozilla::ipc::IPCResult RecvVideoOutput(
const RemoteVideoDataIPDL& aData) override;
mozilla::ipc::IPCResult RecvInputExhausted() override;
mozilla::ipc::IPCResult RecvDrainComplete() override;
mozilla::ipc::IPCResult RecvError(const nsresult& aError) override;
mozilla::ipc::IPCResult RecvInitComplete(
const nsCString& aDecoderDescription,
const ConversionRequired& aConversion) override;
mozilla::ipc::IPCResult RecvInitFailed(const nsresult& aReason) override;
mozilla::ipc::IPCResult RecvFlushComplete() override;
void ActorDestroy(ActorDestroyReason aWhy) override;
// IRemoteDecoderChild
RefPtr<MediaDataDecoder::InitPromise> Init() override;
RefPtr<MediaDataDecoder::DecodePromise> Decode(MediaRawData* aSample) override;
RefPtr<MediaDataDecoder::DecodePromise> Drain() override;
RefPtr<MediaDataDecoder::FlushPromise> Flush() override;
void Shutdown() override;
bool IsHardwareAccelerated(nsACString& aFailureReason) const override;
nsCString GetDescriptionName() const override;
void SetSeekThreshold(const media::TimeUnit& aTime) override;
MediaDataDecoder::ConversionRequired NeedsConversion() const override;
void DestroyIPDL() override;
MOZ_IS_CLASS_INIT
MediaResult InitIPDL(const VideoInfo& aVideoInfo,
float aFramerate,
const CreateDecoderParams::OptionSet& aOptions);
// Called from IPDL when our actor has been destroyed
void IPDLActorDestroyed();
RemoteDecoderManagerChild* GetManager();
private:
~RemoteVideoDecoderChild();
void AssertOnManagerThread() const;
RefPtr<mozilla::layers::Image> DeserializeImage(
const SurfaceDescriptorBuffer& sdBuffer,
const IntSize& aPicSize);
RefPtr<RemoteVideoDecoderChild> mIPDLSelfRef;
RefPtr<nsIThread> mThread;
MozPromiseHolder<MediaDataDecoder::InitPromise> mInitPromise;
MozPromiseHolder<MediaDataDecoder::DecodePromise> mDecodePromise;
MozPromiseHolder<MediaDataDecoder::DecodePromise> mDrainPromise;
MozPromiseHolder<MediaDataDecoder::FlushPromise> mFlushPromise;
nsCString mHardwareAcceleratedReason;
nsCString mDescription;
bool mCanSend;
bool mInitialized;
bool mIsHardwareAccelerated;
MediaDataDecoder::ConversionRequired mConversion;
MediaDataDecoder::DecodedData mDecodedData;
RefPtr<mozilla::layers::BufferRecycleBin> mBufferRecycleBin;
};
} // namespace mozilla
#endif // include_dom_media_ipc_RemoteVideoDecoderChild_h

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

@ -0,0 +1,261 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=99: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "RemoteVideoDecoderParent.h"
#include "mozilla/Unused.h"
#ifdef MOZ_AV1
#include "AOMDecoder.h"
#endif
#include "ImageContainer.h"
#include "RemoteDecoderManagerParent.h"
#include "RemoteDecoderModule.h"
namespace mozilla {
using media::TimeUnit;
using namespace layers; // for PlanarYCbCrImage and BufferRecycleBin
RemoteVideoDecoderParent::RemoteVideoDecoderParent(
RemoteDecoderManagerParent* aParent,
const VideoInfo& aVideoInfo,
float aFramerate,
const CreateDecoderParams::OptionSet& aOptions,
TaskQueue* aManagerTaskQueue,
TaskQueue* aDecodeTaskQueue,
bool* aSuccess,
nsCString* aErrorDescription)
: mParent(aParent)
, mManagerTaskQueue(aManagerTaskQueue)
, mDecodeTaskQueue(aDecodeTaskQueue)
, mDestroyed(false)
, mVideoInfo(aVideoInfo)
{
MOZ_COUNT_CTOR(RemoteVideoDecoderParent);
MOZ_ASSERT(OnManagerThread());
// We hold a reference to ourselves to keep us alive until IPDL
// explictly destroys us. There may still be refs held by
// tasks, but no new ones should be added after we're
// destroyed.
mIPDLSelfRef = this;
CreateDecoderParams params(mVideoInfo);
params.mTaskQueue = mDecodeTaskQueue;
params.mImageContainer = new layers::ImageContainer();
params.mRate = CreateDecoderParams::VideoFrameRate(aFramerate);
params.mOptions = aOptions;
MediaResult error(NS_OK);
params.mError = &error;
#ifdef MOZ_AV1
if (AOMDecoder::IsAV1(params.mConfig.mMimeType)) {
mDecoder = new AOMDecoder(params);
}
#endif
if (NS_FAILED(error)) {
MOZ_ASSERT(aErrorDescription);
*aErrorDescription = error.Description();
}
*aSuccess = !!mDecoder;
}
RemoteVideoDecoderParent::~RemoteVideoDecoderParent()
{
MOZ_COUNT_DTOR(RemoteVideoDecoderParent);
}
void
RemoteVideoDecoderParent::Destroy()
{
MOZ_ASSERT(OnManagerThread());
mDestroyed = true;
mIPDLSelfRef = nullptr;
}
mozilla::ipc::IPCResult
RemoteVideoDecoderParent::RecvInit()
{
MOZ_ASSERT(OnManagerThread());
RefPtr<RemoteVideoDecoderParent> self = this;
mDecoder->Init()->Then(mManagerTaskQueue, __func__,
[self] (TrackInfo::TrackType aTrack) {
MOZ_ASSERT(aTrack == TrackInfo::kVideoTrack);
if (self->mDecoder) {
Unused << self->SendInitComplete(self->mDecoder->GetDescriptionName(),
self->mDecoder->NeedsConversion());
}
},
[self] (MediaResult aReason) {
if (!self->mDestroyed) {
Unused << self->SendInitFailed(aReason);
}
});
return IPC_OK();
}
mozilla::ipc::IPCResult
RemoteVideoDecoderParent::RecvInput(const MediaRawDataIPDL& aData)
{
MOZ_ASSERT(OnManagerThread());
// XXX: This copies the data into a buffer owned by the MediaRawData. Ideally
// we'd just take ownership of the shmem.
RefPtr<MediaRawData> data = new MediaRawData(aData.buffer().get<uint8_t>(),
aData.buffer().Size<uint8_t>());
if (aData.buffer().Size<uint8_t>() && !data->Data()) {
// OOM
Error(NS_ERROR_OUT_OF_MEMORY);
return IPC_OK();
}
data->mOffset = aData.base().offset();
data->mTime = TimeUnit::FromMicroseconds(aData.base().time());
data->mTimecode = TimeUnit::FromMicroseconds(aData.base().timecode());
data->mDuration = TimeUnit::FromMicroseconds(aData.base().duration());
data->mKeyframe = aData.base().keyframe();
DeallocShmem(aData.buffer());
RefPtr<RemoteVideoDecoderParent> self = this;
mDecoder->Decode(data)->Then(
mManagerTaskQueue, __func__,
[self, this](const MediaDataDecoder::DecodedData& aResults) {
if (mDestroyed) {
return;
}
ProcessDecodedData(aResults);
Unused << SendInputExhausted();
},
[self](const MediaResult& aError) { self->Error(aError); });
return IPC_OK();
}
void
RemoteVideoDecoderParent::ProcessDecodedData(
const MediaDataDecoder::DecodedData& aData)
{
MOZ_ASSERT(OnManagerThread());
for (const auto& data : aData) {
MOZ_ASSERT(data->mType == MediaData::VIDEO_DATA,
"Can only decode videos using RemoteVideoDecoderParent!");
VideoData* video = static_cast<VideoData*>(data.get());
MOZ_ASSERT(video->mImage, "Decoded video must output a layer::Image to "
"be used with RemoteVideoDecoderParent");
PlanarYCbCrImage* image =
static_cast<PlanarYCbCrImage*>(video->mImage.get());
SurfaceDescriptorBuffer sdBuffer;
Shmem buffer;
if (AllocShmem(image->GetDataSize(),
Shmem::SharedMemory::TYPE_BASIC, &buffer) &&
image->GetDataSize() == buffer.Size<uint8_t>()) {
sdBuffer.data() = buffer;
image->BuildSurfaceDescriptorBuffer(sdBuffer);
}
RemoteVideoDataIPDL output(
MediaDataIPDL(data->mOffset, data->mTime.ToMicroseconds(),
data->mTimecode.ToMicroseconds(),
data->mDuration.ToMicroseconds(),
data->mFrames, data->mKeyframe),
video->mDisplay,
image->GetSize(),
sdBuffer,
video->mFrameID);
Unused << SendVideoOutput(output);
}
}
mozilla::ipc::IPCResult
RemoteVideoDecoderParent::RecvFlush()
{
MOZ_ASSERT(!mDestroyed);
MOZ_ASSERT(OnManagerThread());
RefPtr<RemoteVideoDecoderParent> self = this;
mDecoder->Flush()->Then(
mManagerTaskQueue, __func__,
[self]() {
if (!self->mDestroyed) {
Unused << self->SendFlushComplete();
}
},
[self](const MediaResult& aError) { self->Error(aError); });
return IPC_OK();
}
mozilla::ipc::IPCResult
RemoteVideoDecoderParent::RecvDrain()
{
MOZ_ASSERT(!mDestroyed);
MOZ_ASSERT(OnManagerThread());
RefPtr<RemoteVideoDecoderParent> self = this;
mDecoder->Drain()->Then(
mManagerTaskQueue, __func__,
[self, this](const MediaDataDecoder::DecodedData& aResults) {
if (!mDestroyed) {
ProcessDecodedData(aResults);
Unused << SendDrainComplete();
}
},
[self](const MediaResult& aError) { self->Error(aError); });
return IPC_OK();
}
mozilla::ipc::IPCResult
RemoteVideoDecoderParent::RecvShutdown()
{
MOZ_ASSERT(!mDestroyed);
MOZ_ASSERT(OnManagerThread());
if (mDecoder) {
mDecoder->Shutdown();
}
mDecoder = nullptr;
return IPC_OK();
}
mozilla::ipc::IPCResult
RemoteVideoDecoderParent::RecvSetSeekThreshold(const int64_t& aTime)
{
MOZ_ASSERT(!mDestroyed);
MOZ_ASSERT(OnManagerThread());
mDecoder->SetSeekThreshold(TimeUnit::FromMicroseconds(aTime));
return IPC_OK();
}
void
RemoteVideoDecoderParent::ActorDestroy(ActorDestroyReason aWhy)
{
MOZ_ASSERT(!mDestroyed);
MOZ_ASSERT(OnManagerThread());
if (mDecoder) {
mDecoder->Shutdown();
mDecoder = nullptr;
}
if (mDecodeTaskQueue) {
mDecodeTaskQueue->BeginShutdown();
}
}
void
RemoteVideoDecoderParent::Error(const MediaResult& aError)
{
MOZ_ASSERT(OnManagerThread());
if (!mDestroyed) {
Unused << SendError(aError);
}
}
bool
RemoteVideoDecoderParent::OnManagerThread()
{
return mParent->OnManagerThread();
}
} // namespace mozilla

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

@ -0,0 +1,62 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=99: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef include_dom_media_ipc_RemoteVideoDecoderParent_h
#define include_dom_media_ipc_RemoteVideoDecoderParent_h
#include "mozilla/PRemoteVideoDecoderParent.h"
namespace mozilla {
class RemoteDecoderManagerParent;
class RemoteVideoDecoderParent final : public PRemoteVideoDecoderParent
{
public:
// We refcount this class since the task queue can have runnables
// that reference us.
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(RemoteVideoDecoderParent)
RemoteVideoDecoderParent(RemoteDecoderManagerParent* aParent,
const VideoInfo& aVideoInfo,
float aFramerate,
const CreateDecoderParams::OptionSet& aOptions,
TaskQueue* aManagerTaskQueue,
TaskQueue* aDecodeTaskQueue,
bool* aSuccess,
nsCString* aErrorDescription);
void Destroy();
// PRemoteVideoDecoderParent
mozilla::ipc::IPCResult RecvInit() override;
mozilla::ipc::IPCResult RecvInput(const MediaRawDataIPDL& aData) override;
mozilla::ipc::IPCResult RecvFlush() override;
mozilla::ipc::IPCResult RecvDrain() override;
mozilla::ipc::IPCResult RecvShutdown() override;
mozilla::ipc::IPCResult RecvSetSeekThreshold(const int64_t& aTime) override;
void ActorDestroy(ActorDestroyReason aWhy) override;
private:
bool OnManagerThread();
void Error(const MediaResult& aError);
~RemoteVideoDecoderParent();
void ProcessDecodedData(const MediaDataDecoder::DecodedData& aData);
RefPtr<RemoteDecoderManagerParent> mParent;
RefPtr<RemoteVideoDecoderParent> mIPDLSelfRef;
RefPtr<TaskQueue> mManagerTaskQueue;
RefPtr<TaskQueue> mDecodeTaskQueue;
RefPtr<MediaDataDecoder> mDecoder;
// Can only be accessed from the manager thread
bool mDestroyed;
VideoInfo mVideoInfo;
};
} // namespace mozilla
#endif // include_dom_media_ipc_RemoteVideoDecoderParent_h

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

@ -7,12 +7,17 @@
IPDL_SOURCES += [
'PMediaDecoderParams.ipdlh',
'PRemoteDecoderManager.ipdl',
'PRemoteVideoDecoder.ipdl',
'PVideoDecoder.ipdl',
'PVideoDecoderManager.ipdl',
]
EXPORTS.mozilla += [
'GpuDecoderModule.h',
'RemoteDecoderManagerChild.h',
'RemoteDecoderManagerParent.h',
'RemoteDecoderModule.h',
'RemoteMediaDataDecoder.h',
]
@ -24,7 +29,12 @@ EXPORTS.mozilla.dom += [
SOURCES += [
'GpuDecoderModule.cpp',
'RemoteDecoderManagerChild.cpp',
'RemoteDecoderManagerParent.cpp',
'RemoteDecoderModule.cpp',
'RemoteMediaDataDecoder.cpp',
'RemoteVideoDecoderChild.cpp',
'RemoteVideoDecoderParent.cpp',
'VideoDecoderChild.cpp',
'VideoDecoderManagerChild.cpp',
'VideoDecoderManagerParent.cpp',

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

@ -35,6 +35,7 @@ class ImageContainer;
class GpuDecoderModule;
class MediaDataDecoder;
class RemoteDecoderModule;
class TaskQueue;
class CDMProxy;
@ -213,6 +214,7 @@ protected:
friend class PDMFactory;
friend class GpuDecoderModule;
friend class EMEDecoderModule;
friend class RemoteDecoderModule;
// Indicates if the PlatformDecoderModule supports decoding of aColorDepth.
// Should override this method when the platform can support color depth != 8.

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

@ -914,6 +914,8 @@ description =
description =
[PGMPVideoEncoder::NeedShmem]
description =
[PRemoteDecoderManager::PRemoteVideoDecoder]
description = See Bug 1505976 - investigate changing to async instead of matching GPU pattern
[PVideoDecoderManager::PVideoDecoder]
description =
[PVideoDecoderManager::Readback]