зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1288618 - Part 15: Add media code interface RemoteVideoDecoder. r=cpearce,dvander
This commit is contained in:
Родитель
637309d62d
Коммит
8d050a3f83
|
@ -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;
|
using namespace gfx;
|
||||||
|
|
||||||
StaticRefPtr<nsIThread> sVideoDecoderChildThread;
|
StaticRefPtr<nsIThread> sVideoDecoderChildThread;
|
||||||
|
StaticRefPtr<AbstractThread> sVideoDecoderChildAbstractThread;
|
||||||
static StaticRefPtr<VideoDecoderManagerChild> sDecoderManager;
|
static StaticRefPtr<VideoDecoderManagerChild> sDecoderManager;
|
||||||
|
|
||||||
/* static */ void
|
/* static */ void
|
||||||
|
@ -41,6 +42,9 @@ VideoDecoderManagerChild::Initialize()
|
||||||
nsresult rv = NS_NewNamedThread("VideoChild", getter_AddRefs(childThread));
|
nsresult rv = NS_NewNamedThread("VideoChild", getter_AddRefs(childThread));
|
||||||
NS_ENSURE_SUCCESS_VOID(rv);
|
NS_ENSURE_SUCCESS_VOID(rv);
|
||||||
sVideoDecoderChildThread = childThread;
|
sVideoDecoderChildThread = childThread;
|
||||||
|
|
||||||
|
sVideoDecoderChildAbstractThread =
|
||||||
|
AbstractThread::CreateXPCOMThreadWrapper(childThread, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
Endpoint<PVideoDecoderManagerChild> endpoint;
|
Endpoint<PVideoDecoderManagerChild> endpoint;
|
||||||
|
@ -77,6 +81,7 @@ VideoDecoderManagerChild::Shutdown()
|
||||||
|
|
||||||
sDecoderManager = nullptr;
|
sDecoderManager = nullptr;
|
||||||
|
|
||||||
|
sVideoDecoderChildAbstractThread = nullptr;
|
||||||
sVideoDecoderChildThread->Shutdown();
|
sVideoDecoderChildThread->Shutdown();
|
||||||
sVideoDecoderChildThread = nullptr;
|
sVideoDecoderChildThread = nullptr;
|
||||||
}
|
}
|
||||||
|
@ -94,6 +99,12 @@ VideoDecoderManagerChild::GetManagerThread()
|
||||||
return sVideoDecoderChildThread;
|
return sVideoDecoderChildThread;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* static */ AbstractThread*
|
||||||
|
VideoDecoderManagerChild::GetManagerAbstractThread()
|
||||||
|
{
|
||||||
|
return sVideoDecoderChildAbstractThread;
|
||||||
|
}
|
||||||
|
|
||||||
PVideoDecoderChild*
|
PVideoDecoderChild*
|
||||||
VideoDecoderManagerChild::AllocPVideoDecoderChild()
|
VideoDecoderManagerChild::AllocPVideoDecoderChild()
|
||||||
{
|
{
|
||||||
|
|
|
@ -19,6 +19,7 @@ public:
|
||||||
|
|
||||||
static VideoDecoderManagerChild* GetSingleton();
|
static VideoDecoderManagerChild* GetSingleton();
|
||||||
static nsIThread* GetManagerThread();
|
static nsIThread* GetManagerThread();
|
||||||
|
static AbstractThread* GetManagerAbstractThread();
|
||||||
|
|
||||||
// Can be called from any thread, dispatches the request to the IPDL thread internally.
|
// Can be called from any thread, dispatches the request to the IPDL thread internally.
|
||||||
void DeallocateSurfaceDescriptorGPUVideo(const SurfaceDescriptorGPUVideo& aSD);
|
void DeallocateSurfaceDescriptorGPUVideo(const SurfaceDescriptorGPUVideo& aSD);
|
||||||
|
|
|
@ -12,11 +12,13 @@ IPDL_SOURCES += [
|
||||||
|
|
||||||
EXPORTS.mozilla.dom += [
|
EXPORTS.mozilla.dom += [
|
||||||
'MediaIPCUtils.h',
|
'MediaIPCUtils.h',
|
||||||
|
'RemoteVideoDecoder.h',
|
||||||
'VideoDecoderManagerChild.h',
|
'VideoDecoderManagerChild.h',
|
||||||
'VideoDecoderManagerParent.h',
|
'VideoDecoderManagerParent.h',
|
||||||
]
|
]
|
||||||
|
|
||||||
SOURCES += [
|
SOURCES += [
|
||||||
|
'RemoteVideoDecoder.cpp',
|
||||||
'VideoDecoderChild.cpp',
|
'VideoDecoderChild.cpp',
|
||||||
'VideoDecoderManagerChild.cpp',
|
'VideoDecoderManagerChild.cpp',
|
||||||
'VideoDecoderManagerParent.cpp',
|
'VideoDecoderManagerParent.cpp',
|
||||||
|
|
|
@ -47,6 +47,7 @@
|
||||||
#include "DecoderDoctorDiagnostics.h"
|
#include "DecoderDoctorDiagnostics.h"
|
||||||
|
|
||||||
#include "MP4Decoder.h"
|
#include "MP4Decoder.h"
|
||||||
|
#include "mozilla/dom/RemoteVideoDecoder.h"
|
||||||
|
|
||||||
#include "mp4_demuxer/H264.h"
|
#include "mp4_demuxer/H264.h"
|
||||||
|
|
||||||
|
@ -322,7 +323,11 @@ PDMFactory::CreatePDMs()
|
||||||
#ifdef XP_WIN
|
#ifdef XP_WIN
|
||||||
if (MediaPrefs::PDMWMFEnabled()) {
|
if (MediaPrefs::PDMWMFEnabled()) {
|
||||||
m = new WMFDecoderModule();
|
m = new WMFDecoderModule();
|
||||||
mWMFFailedToLoad = !StartupPDM(m);
|
RefPtr<PlatformDecoderModule> remote = new dom::RemoteDecoderModule(m);
|
||||||
|
mWMFFailedToLoad = !StartupPDM(remote);
|
||||||
|
if (mWMFFailedToLoad) {
|
||||||
|
mWMFFailedToLoad = !StartupPDM(m);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
mWMFFailedToLoad = MediaPrefs::DecoderDoctorWMFDisabledIsFailure();
|
mWMFFailedToLoad = MediaPrefs::DecoderDoctorWMFDisabledIsFailure();
|
||||||
}
|
}
|
||||||
|
|
Загрузка…
Ссылка в новой задаче