Bug 1288618 - Part 15: Add media code interface RemoteVideoDecoder. r=cpearce,dvander

This commit is contained in:
Matt Woodrow 2016-09-21 21:25:41 +12:00
Родитель a64365e7ad
Коммит d57dae2c04
6 изменённых файлов: 250 добавлений и 1 удалений

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

@ -0,0 +1,145 @@
/* -*- 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 "RemoteVideoDecoder.h"
#include "VideoDecoderChild.h"
#include "VideoDecoderManagerChild.h"
#include "mozilla/layers/TextureClient.h"
#include "base/thread.h"
#include "MediaInfo.h"
#include "ImageContainer.h"
namespace mozilla {
namespace dom {
using base::Thread;
using namespace ipc;
using namespace layers;
using namespace gfx;
RemoteVideoDecoder::RemoteVideoDecoder(MediaDataDecoderCallback* aCallback)
: mActor(new VideoDecoderChild())
{
#ifdef DEBUG
mCallback = aCallback;
#endif
MOZ_ASSERT(mCallback->OnReaderTaskQueue());
}
RemoteVideoDecoder::~RemoteVideoDecoder()
{
// We're about to be destroyed and drop our ref to
// VideoDecoderChild. Make sure we put a ref into the
// task queue for the VideoDecoderChild thread to keep
// it alive until we send the delete message.
RefPtr<VideoDecoderChild> actor = mActor;
VideoDecoderManagerChild::GetManagerThread()->Dispatch(NS_NewRunnableFunction([actor]() {
MOZ_ASSERT(actor);
actor->DestroyIPDL();
}), NS_DISPATCH_NORMAL);
}
RefPtr<MediaDataDecoder::InitPromise>
RemoteVideoDecoder::Init()
{
MOZ_ASSERT(mCallback->OnReaderTaskQueue());
return InvokeAsync(VideoDecoderManagerChild::GetManagerAbstractThread(),
this, __func__, &RemoteVideoDecoder::InitInternal);
}
RefPtr<MediaDataDecoder::InitPromise>
RemoteVideoDecoder::InitInternal()
{
MOZ_ASSERT(mActor);
MOZ_ASSERT(NS_GetCurrentThread() == VideoDecoderManagerChild::GetManagerThread());
return mActor->Init();
}
void
RemoteVideoDecoder::Input(MediaRawData* aSample)
{
MOZ_ASSERT(mCallback->OnReaderTaskQueue());
RefPtr<RemoteVideoDecoder> self = this;
RefPtr<MediaRawData> sample = aSample;
VideoDecoderManagerChild::GetManagerThread()->Dispatch(NS_NewRunnableFunction([self, sample]() {
MOZ_ASSERT(self->mActor);
self->mActor->Input(sample);
}), NS_DISPATCH_NORMAL);
}
void
RemoteVideoDecoder::Flush()
{
MOZ_ASSERT(mCallback->OnReaderTaskQueue());
RefPtr<RemoteVideoDecoder> self = this;
VideoDecoderManagerChild::GetManagerThread()->Dispatch(NS_NewRunnableFunction([self]() {
MOZ_ASSERT(self->mActor);
self->mActor->Flush();
}), NS_DISPATCH_NORMAL);
}
void
RemoteVideoDecoder::Drain()
{
MOZ_ASSERT(mCallback->OnReaderTaskQueue());
RefPtr<RemoteVideoDecoder> self = this;
VideoDecoderManagerChild::GetManagerThread()->Dispatch(NS_NewRunnableFunction([self]() {
MOZ_ASSERT(self->mActor);
self->mActor->Drain();
}), NS_DISPATCH_NORMAL);
}
void
RemoteVideoDecoder::Shutdown()
{
MOZ_ASSERT(mCallback->OnReaderTaskQueue());
RefPtr<RemoteVideoDecoder> self = this;
VideoDecoderManagerChild::GetManagerThread()->Dispatch(NS_NewRunnableFunction([self]() {
MOZ_ASSERT(self->mActor);
self->mActor->Shutdown();
}), NS_DISPATCH_NORMAL);
}
nsresult
RemoteDecoderModule::Startup()
{
if (!VideoDecoderManagerChild::GetSingleton()) {
return NS_ERROR_FAILURE;
}
return mWrapped->Startup();
}
bool
RemoteDecoderModule::SupportsMimeType(const nsACString& aMimeType,
DecoderDoctorDiagnostics* aDiagnostics) const
{
return mWrapped->SupportsMimeType(aMimeType, aDiagnostics);
}
PlatformDecoderModule::ConversionRequired
RemoteDecoderModule::DecoderNeedsConversion(const TrackInfo& aConfig) const
{
return mWrapped->DecoderNeedsConversion(aConfig);
}
already_AddRefed<MediaDataDecoder>
RemoteDecoderModule::CreateVideoDecoder(const CreateDecoderParams& aParams)
{
MediaDataDecoderCallback* callback = aParams.mCallback;
MOZ_ASSERT(callback->OnReaderTaskQueue());
RefPtr<RemoteVideoDecoder> object = new RemoteVideoDecoder(callback);
VideoInfo info = aParams.VideoConfig();
layers::LayersBackend backend = aParams.mLayersBackend;
VideoDecoderManagerChild::GetManagerThread()->Dispatch(NS_NewRunnableFunction([object, callback, info, backend]() {
object->mActor->InitIPDL(callback, info, backend);
}), NS_DISPATCH_NORMAL);
return object.forget();
}
} // namespace dom
} // namespace mozilla

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

@ -0,0 +1,85 @@
/* -*- 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_ipc_RemoteVideoDecoder_h
#define include_dom_ipc_RemoteVideoDecoder_h
#include "mozilla/RefPtr.h"
#include "mozilla/DebugOnly.h"
#include "MediaData.h"
#include "PlatformDecoderModule.h"
namespace mozilla {
namespace dom {
class VideoDecoderChild;
class RemoteDecoderModule;
// A MediaDataDecoder implementation that proxies through IPDL
// to a 'real' decoder in the GPU process.
// All requests get forwarded to a VideoDecoderChild instance that
// operates solely on the VideoDecoderManagerChild thread.
class RemoteVideoDecoder : public MediaDataDecoder
{
public:
friend class RemoteDecoderModule;
// MediaDataDecoder
RefPtr<InitPromise> Init() override;
void Input(MediaRawData* aSample) override;
void Flush() override;
void Drain() override;
void Shutdown() override;
void ConfigurationChanged(const TrackInfo& aConfig) override { MOZ_ASSERT(false); }
const char* GetDescriptionName() const override { return "RemoteVideoDecoder"; }
private:
explicit RemoteVideoDecoder(MediaDataDecoderCallback* aCallback);
~RemoteVideoDecoder();
RefPtr<InitPromise> InitInternal();
// Only ever written to from the reader task queue (during the constructor and destructor
// when we can guarantee no other threads are accessing it). Only read from the manager
// thread.
RefPtr<VideoDecoderChild> mActor;
#ifdef DEBUG
MediaDataDecoderCallback* mCallback;
#endif
};
// A PDM implementation that creates RemoteVideoDecoders.
// We currently require a 'wrapped' PDM in order to be able to answer SupportsMimeType
// and DecoderNeedsConversion. Ideally we'd check these over IPDL using the manager
// protocol
class RemoteDecoderModule : public PlatformDecoderModule
{
public:
explicit RemoteDecoderModule(PlatformDecoderModule* aWrapped)
: mWrapped(aWrapped)
{}
virtual nsresult Startup() override;
virtual bool SupportsMimeType(const nsACString& aMimeType,
DecoderDoctorDiagnostics* aDiagnostics) const override;
virtual ConversionRequired DecoderNeedsConversion(const TrackInfo& aConfig) const override;
virtual already_AddRefed<MediaDataDecoder>
CreateVideoDecoder(const CreateDecoderParams& aParams) override;
virtual already_AddRefed<MediaDataDecoder>
CreateAudioDecoder(const CreateDecoderParams& aParams) override { return nullptr; }
private:
RefPtr<PlatformDecoderModule> mWrapped;
};
} // namespace dom
} // namespace mozilla
#endif // include_dom_ipc_RemoteVideoDecoder_h

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

@ -17,6 +17,7 @@ using namespace layers;
using namespace gfx;
StaticRefPtr<nsIThread> sVideoDecoderChildThread;
StaticRefPtr<AbstractThread> sVideoDecoderChildAbstractThread;
static StaticRefPtr<VideoDecoderManagerChild> sDecoderManager;
/* static */ void
@ -41,6 +42,9 @@ VideoDecoderManagerChild::Initialize()
nsresult rv = NS_NewNamedThread("VideoChild", getter_AddRefs(childThread));
NS_ENSURE_SUCCESS_VOID(rv);
sVideoDecoderChildThread = childThread;
sVideoDecoderChildAbstractThread =
AbstractThread::CreateXPCOMThreadWrapper(childThread, false);
}
Endpoint<PVideoDecoderManagerChild> endpoint;
@ -77,6 +81,7 @@ VideoDecoderManagerChild::Shutdown()
sDecoderManager = nullptr;
sVideoDecoderChildAbstractThread = nullptr;
sVideoDecoderChildThread->Shutdown();
sVideoDecoderChildThread = nullptr;
}
@ -94,6 +99,12 @@ VideoDecoderManagerChild::GetManagerThread()
return sVideoDecoderChildThread;
}
/* static */ AbstractThread*
VideoDecoderManagerChild::GetManagerAbstractThread()
{
return sVideoDecoderChildAbstractThread;
}
PVideoDecoderChild*
VideoDecoderManagerChild::AllocPVideoDecoderChild()
{

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

@ -19,6 +19,7 @@ public:
static VideoDecoderManagerChild* GetSingleton();
static nsIThread* GetManagerThread();
static AbstractThread* GetManagerAbstractThread();
// Can be called from any thread, dispatches the request to the IPDL thread internally.
void DeallocateSurfaceDescriptorGPUVideo(const SurfaceDescriptorGPUVideo& aSD);

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

@ -12,11 +12,13 @@ IPDL_SOURCES += [
EXPORTS.mozilla.dom += [
'MediaIPCUtils.h',
'RemoteVideoDecoder.h',
'VideoDecoderManagerChild.h',
'VideoDecoderManagerParent.h',
]
SOURCES += [
'RemoteVideoDecoder.cpp',
'VideoDecoderChild.cpp',
'VideoDecoderManagerChild.cpp',
'VideoDecoderManagerParent.cpp',

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

@ -47,6 +47,7 @@
#include "DecoderDoctorDiagnostics.h"
#include "MP4Decoder.h"
#include "mozilla/dom/RemoteVideoDecoder.h"
#include "mp4_demuxer/H264.h"
@ -322,7 +323,11 @@ PDMFactory::CreatePDMs()
#ifdef XP_WIN
if (MediaPrefs::PDMWMFEnabled()) {
m = new WMFDecoderModule();
mWMFFailedToLoad = !StartupPDM(m);
RefPtr<PlatformDecoderModule> remote = new dom::RemoteDecoderModule(m);
mWMFFailedToLoad = !StartupPDM(remote);
if (mWMFFailedToLoad) {
mWMFFailedToLoad = !StartupPDM(m);
}
} else {
mWMFFailedToLoad = MediaPrefs::DecoderDoctorWMFDisabledIsFailure();
}