зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1288618 - Part 15: Add media code interface RemoteVideoDecoder. r=cpearce,dvander
This commit is contained in:
Родитель
a64365e7ad
Коммит
d57dae2c04
|
@ -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();
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче