Bug 1288618 - Part 16: Add media code facing RemoteVideoDecoder. r?cpearce,dvander
MozReview-Commit-ID: buEP5MvIS0
new file mode 100644
--- /dev/null
+++ b/dom/media/ipc/RemoteVideoDecoder.cpp
@@ -0,0 +1,146 @@
+/* -*- 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(nullptr)
+ , mCallback(aCallback)
+{
+ MOZ_ASSERT(mCallback->OnReaderTaskQueue());
+}
+
+RemoteVideoDecoder::~RemoteVideoDecoder()
+{
+ VideoDecoderChild* actor = mActor;
+ VideoDecoderManagerChild::GetMessageLoop()->PostTask(NS_NewRunnableFunction([actor]() {
+ MOZ_ASSERT(actor);
+ PVideoDecoderChild::Send__delete__(actor);
+ }));
+}
+
+RefPtr<MediaDataDecoder::InitPromise>
+RemoteVideoDecoder::Init()
+{
+ MOZ_ASSERT(mCallback->OnReaderTaskQueue());
+ MozPromiseHolder<InitPromise> promise;
+ RefPtr<MediaDataDecoder::InitPromise> p = promise.Ensure(__func__);
+ RefPtr<MediaDataDecoder::InitPromise::Private> val = promise.Steal();
+ RefPtr<RemoteVideoDecoder> self = this;
+ VideoDecoderManagerChild::GetMessageLoop()->PostTask(NS_NewRunnableFunction([self, val]() mutable {
+ MOZ_ASSERT(self->mActor);
+ self->mActor->Init(val);
+ }));
+ return p;
+}
+
+nsresult
+RemoteVideoDecoder::Input(MediaRawData* aSample)
+{
+ MOZ_ASSERT(mCallback->OnReaderTaskQueue());
+ RefPtr<RemoteVideoDecoder> self = this;
+ RefPtr<MediaRawData> sample = aSample;
+ VideoDecoderManagerChild::GetMessageLoop()->PostTask(NS_NewRunnableFunction([self, sample]() {
+ MOZ_ASSERT(self->mActor);
+ self->mActor->Input(sample);
+ }));
+ return NS_OK;
+}
+
+nsresult
+RemoteVideoDecoder::Flush()
+{
+ MOZ_ASSERT(mCallback->OnReaderTaskQueue());
+ RefPtr<RemoteVideoDecoder> self = this;
+ VideoDecoderManagerChild::GetMessageLoop()->PostTask(NS_NewRunnableFunction([self]() {
+ MOZ_ASSERT(self->mActor);
+ self->mActor->Flush();
+ }));
+ return NS_OK;
+}
+
+nsresult
+RemoteVideoDecoder::Drain()
+{
+ MOZ_ASSERT(mCallback->OnReaderTaskQueue());
+ RefPtr<RemoteVideoDecoder> self = this;
+ VideoDecoderManagerChild::GetMessageLoop()->PostTask(NS_NewRunnableFunction([self]() {
+ MOZ_ASSERT(self->mActor);
+ self->mActor->Drain();
+ }));
+ return NS_OK;
+}
+
+nsresult
+RemoteVideoDecoder::Shutdown()
+{
+ MOZ_ASSERT(mCallback->OnReaderTaskQueue());
+ RefPtr<RemoteVideoDecoder> self = this;
+ VideoDecoderManagerChild::GetMessageLoop()->PostTask(NS_NewRunnableFunction([self]() {
+ MOZ_ASSERT(self->mActor);
+ self->mActor->Shutdown();
+ }));
+ return NS_OK;
+}
+
+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::GetMessageLoop()->PostTask(NS_NewRunnableFunction([object, callback, info, backend]() {
+ VideoDecoderChild* child = static_cast<VideoDecoderChild*>(VideoDecoderManagerChild::GetSingleton()->SendPVideoDecoderConstructor());
+ object->mActor = child;
+ object->mActor->mCallback = callback;
+ object->mActor->mVideoInfo = info;
+ object->mActor->mLayersBackend = backend;
+ }));
+
+ return object.forget();
+}
+
+} // namespace dom
+} // namespace mozilla
new file mode 100644
--- /dev/null
+++ b/dom/media/ipc/RemoteVideoDecoder.h
@@ -0,0 +1,78 @@
+/* -*- 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 "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;
+ nsresult Input(MediaRawData* aSample) override;
+ nsresult Flush() override;
+ nsresult Drain() override;
+ nsresult Shutdown() override;
+ nsresult ConfigurationChanged(const TrackInfo& aConfig) { MOZ_ASSERT(false); }
+
+ virtual const char* GetDescriptionName() const override { return "RemoteVideoDecoder"; }
+
+private:
+ RemoteVideoDecoder(MediaDataDecoderCallback* aCallback);
+ ~RemoteVideoDecoder();
+
+ // Only ever accessed or written to from the manager thread (excluding the destructor)
+ VideoDecoderChild* mActor;
+ MediaDataDecoderCallback* mCallback;
+};
+
+// 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:
+ 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
--- a/dom/media/ipc/moz.build
+++ b/dom/media/ipc/moz.build
@@ -7,21 +7,23 @@
IPDL_SOURCES += [
'PVideoDecoder.ipdl',
'PVideoDecoderManager.ipdl',
]
EXPORTS.mozilla.dom += [
'MediaIPCUtils.h',
+ 'RemoteVideoDecoder.h',
'VideoDecoderManagerChild.h',
'VideoDecoderManagerParent.h',
]
SOURCES += [
+ 'RemoteVideoDecoder.cpp',
'VideoDecoderChild.cpp',
'VideoDecoderManagerChild.cpp',
'VideoDecoderManagerParent.cpp',
'VideoDecoderParent.cpp',
]
include('/ipc/chromium/chromium-config.mozbuild')
--- a/dom/media/platforms/PDMFactory.cpp
+++ b/dom/media/platforms/PDMFactory.cpp
@@ -42,16 +42,17 @@
#ifdef MOZ_EME
#include "EMEDecoderModule.h"
#include "mozilla/CDMProxy.h"
#endif
#include "DecoderDoctorDiagnostics.h"
#include "MP4Decoder.h"
+#include "mozilla/dom/RemoteVideoDecoder.h"
#include "mp4_demuxer/H264.h"
namespace mozilla {
extern already_AddRefed<PlatformDecoderModule> CreateAgnosticDecoderModule();
extern already_AddRefed<PlatformDecoderModule> CreateBlankDecoderModule();
@@ -317,17 +318,21 @@ PDMFactory::CreatePDMs()
MediaPrefs::PDMAndroidMediaCodecEnabled()) {
m = new AndroidDecoderModule();
StartupPDM(m);
}
#endif
#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();
}
#endif
#ifdef MOZ_FFVPX
if (MediaPrefs::PDMFFVPXEnabled()) {
m = FFVPXRuntimeLinker::CreateDecoderModule();
StartupPDM(m);
--- a/gfx/thebes/gfxPrefs.h
+++ b/gfx/thebes/gfxPrefs.h
@@ -471,17 +471,17 @@ private:
// decrease it until we hit mid gray at -1 contrast, after that it gets weird.
DECL_GFX_PREF(Live, "layers.effect.contrast", LayersEffectContrast, float, 0.0f);
DECL_GFX_PREF(Live, "layers.effect.grayscale", LayersEffectGrayscale, bool, false);
DECL_GFX_PREF(Live, "layers.effect.invert", LayersEffectInvert, bool, false);
DECL_GFX_PREF(Once, "layers.enable-tiles", LayersTilesEnabled, bool, false);
DECL_GFX_PREF(Live, "layers.flash-borders", FlashLayerBorders, bool, false);
DECL_GFX_PREF(Once, "layers.force-shmem-tiles", ForceShmemTiles, bool, false);
DECL_GFX_PREF(Live, "layers.frame-counter", DrawFrameCounter, bool, false);
- DECL_GFX_PREF(Once, "layers.gpu-process.dev.enabled", GPUProcessDevEnabled, bool, false);
+ DECL_GFX_PREF(Once, "layers.gpu-process.dev.enabled", GPUProcessDevEnabled, bool, true);
DECL_GFX_PREF(Once, "layers.gpu-process.dev.timeout_ms", GPUProcessDevTimeoutMs, int32_t, 5000);
DECL_GFX_PREF(Once, "layers.gralloc.disable", DisableGralloc, bool, false);
DECL_GFX_PREF(Live, "layers.low-precision-buffer", UseLowPrecisionBuffer, bool, false);
DECL_GFX_PREF(Live, "layers.low-precision-opacity", LowPrecisionOpacity, float, 1.0f);
DECL_GFX_PREF(Live, "layers.low-precision-resolution", LowPrecisionResolution, float, 0.25f);
DECL_GFX_PREF(Live, "layers.max-active", MaxActiveLayers, int32_t, -1);
DECL_GFX_PREF(Once, "layers.offmainthreadcomposition.force-disabled", LayersOffMainThreadCompositionForceDisabled, bool, false);
DECL_GFX_PREF(Live, "layers.offmainthreadcomposition.frame-rate", LayersCompositionFrameRate, int32_t,-1);