mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-20 00:35:44 +00:00
Bug 1471535 - pt1 - Split RemoteVideoDecoder into GpuDecoderModule and RemoteMediaDataDecoder preparing for new RDD decoder work. r=jya
- also makes RemoteMediaDecoder generic so it can work with the remote decoders on the RDD process - changes VideoDecoderChild to subclass IRemoteDecoderChild Differential Revision: https://phabricator.services.mozilla.com/D8482 --HG-- rename : dom/media/ipc/RemoteVideoDecoder.cpp => dom/media/ipc/GpuDecoderModule.cpp rename : dom/media/ipc/RemoteVideoDecoder.h => dom/media/ipc/GpuDecoderModule.h extra : moz-landing-system : lando
This commit is contained in:
parent
9e02794565
commit
25ac4aee06
98
dom/media/ipc/GpuDecoderModule.cpp
Normal file
98
dom/media/ipc/GpuDecoderModule.cpp
Normal file
@ -0,0 +1,98 @@
|
|||||||
|
/* -*- 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 "GpuDecoderModule.h"
|
||||||
|
|
||||||
|
#include "base/thread.h"
|
||||||
|
#include "mozilla/layers/SynchronousTask.h"
|
||||||
|
#include "mozilla/StaticPrefs.h"
|
||||||
|
|
||||||
|
#include "RemoteMediaDataDecoder.h"
|
||||||
|
#include "VideoDecoderChild.h"
|
||||||
|
#include "VideoDecoderManagerChild.h"
|
||||||
|
|
||||||
|
namespace mozilla {
|
||||||
|
|
||||||
|
using base::Thread;
|
||||||
|
using dom::VideoDecoderChild;
|
||||||
|
using dom::VideoDecoderManagerChild;
|
||||||
|
using namespace ipc;
|
||||||
|
using namespace layers;
|
||||||
|
using namespace gfx;
|
||||||
|
|
||||||
|
nsresult
|
||||||
|
GpuDecoderModule::Startup()
|
||||||
|
{
|
||||||
|
if (!VideoDecoderManagerChild::GetManagerThread()) {
|
||||||
|
return NS_ERROR_FAILURE;
|
||||||
|
}
|
||||||
|
return mWrapped->Startup();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
GpuDecoderModule::SupportsMimeType(const nsACString& aMimeType,
|
||||||
|
DecoderDoctorDiagnostics* aDiagnostics) const
|
||||||
|
{
|
||||||
|
return mWrapped->SupportsMimeType(aMimeType, aDiagnostics);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
GpuDecoderModule::Supports(const TrackInfo& aTrackInfo,
|
||||||
|
DecoderDoctorDiagnostics* aDiagnostics) const
|
||||||
|
{
|
||||||
|
return mWrapped->Supports(aTrackInfo, aDiagnostics);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline bool
|
||||||
|
IsRemoteAcceleratedCompositor(KnowsCompositor* aKnows)
|
||||||
|
{
|
||||||
|
TextureFactoryIdentifier ident = aKnows->GetTextureFactoryIdentifier();
|
||||||
|
return ident.mParentBackend != LayersBackend::LAYERS_BASIC &&
|
||||||
|
ident.mParentProcessType == GeckoProcessType_GPU;
|
||||||
|
}
|
||||||
|
|
||||||
|
already_AddRefed<MediaDataDecoder>
|
||||||
|
GpuDecoderModule::CreateVideoDecoder(const CreateDecoderParams& aParams)
|
||||||
|
{
|
||||||
|
if (!StaticPrefs::MediaGpuProcessDecoder() ||
|
||||||
|
!aParams.mKnowsCompositor ||
|
||||||
|
!IsRemoteAcceleratedCompositor(aParams.mKnowsCompositor))
|
||||||
|
{
|
||||||
|
return mWrapped->CreateVideoDecoder(aParams);
|
||||||
|
}
|
||||||
|
|
||||||
|
RefPtr<VideoDecoderChild> child = new VideoDecoderChild();
|
||||||
|
RefPtr<RemoteMediaDataDecoder> object = new RemoteMediaDataDecoder(
|
||||||
|
child,
|
||||||
|
VideoDecoderManagerChild::GetManagerThread(),
|
||||||
|
VideoDecoderManagerChild::GetManagerAbstractThread());
|
||||||
|
|
||||||
|
SynchronousTask task("InitIPDL");
|
||||||
|
MediaResult result(NS_OK);
|
||||||
|
VideoDecoderManagerChild::GetManagerThread()->Dispatch(
|
||||||
|
NS_NewRunnableFunction(
|
||||||
|
"dom::GpuDecoderModule::CreateVideoDecoder",
|
||||||
|
[&]() {
|
||||||
|
AutoCompleteTask complete(&task);
|
||||||
|
result = child->InitIPDL(
|
||||||
|
aParams.VideoConfig(),
|
||||||
|
aParams.mRate.mValue,
|
||||||
|
aParams.mOptions,
|
||||||
|
aParams.mKnowsCompositor->GetTextureFactoryIdentifier());
|
||||||
|
}),
|
||||||
|
NS_DISPATCH_NORMAL);
|
||||||
|
task.Wait();
|
||||||
|
|
||||||
|
if (NS_FAILED(result)) {
|
||||||
|
if (aParams.mError) {
|
||||||
|
*aParams.mError = result;
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
return object.forget();
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace mozilla
|
50
dom/media/ipc/GpuDecoderModule.h
Normal file
50
dom/media/ipc/GpuDecoderModule.h
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
/* -*- 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_GpuDecoderModule_h
|
||||||
|
#define include_dom_media_ipc_GpuDecoderModule_h
|
||||||
|
#include "PlatformDecoderModule.h"
|
||||||
|
|
||||||
|
#include "MediaData.h"
|
||||||
|
|
||||||
|
namespace mozilla {
|
||||||
|
|
||||||
|
// A PDM implementation that creates a RemoteMediaDataDecoder (a
|
||||||
|
// MediaDataDecoder) that proxies to a VideoDecoderChild. The
|
||||||
|
// VideoDecoderChild will talk to a VideoDecoderParent running on the
|
||||||
|
// GPU process.
|
||||||
|
// 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 GpuDecoderModule : public PlatformDecoderModule
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
explicit GpuDecoderModule(PlatformDecoderModule* aWrapped)
|
||||||
|
: mWrapped(aWrapped)
|
||||||
|
{}
|
||||||
|
|
||||||
|
nsresult Startup() override;
|
||||||
|
|
||||||
|
bool SupportsMimeType(const nsACString& aMimeType,
|
||||||
|
DecoderDoctorDiagnostics* aDiagnostics) const override;
|
||||||
|
bool Supports(const TrackInfo& aTrackInfo,
|
||||||
|
DecoderDoctorDiagnostics* aDiagnostics) const override;
|
||||||
|
|
||||||
|
already_AddRefed<MediaDataDecoder> CreateVideoDecoder(
|
||||||
|
const CreateDecoderParams& aParams) override;
|
||||||
|
|
||||||
|
already_AddRefed<MediaDataDecoder> CreateAudioDecoder(
|
||||||
|
const CreateDecoderParams& aParams) override
|
||||||
|
{
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
RefPtr<PlatformDecoderModule> mWrapped;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace mozilla
|
||||||
|
|
||||||
|
#endif // include_dom_media_ipc_GpuDecoderModule_h
|
47
dom/media/ipc/IRemoteDecoderChild.h
Normal file
47
dom/media/ipc/IRemoteDecoderChild.h
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
/* -*- 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_IRemoteDecoderChild_h
|
||||||
|
#define include_dom_media_ipc_IRemoteDecoderChild_h
|
||||||
|
|
||||||
|
#include "PlatformDecoderModule.h"
|
||||||
|
|
||||||
|
namespace mozilla {
|
||||||
|
|
||||||
|
// This interface mirrors the MediaDataDecoder plus a bit (DestroyIPDL)
|
||||||
|
// to allow proxying to a remote decoder in RemoteDecoderModule or
|
||||||
|
// GpuDecoderModule. RemoteAudioDecoderChild, RemoteVideoDecoderChild,
|
||||||
|
// and VideoDecoderChild (for GPU) implement this interface.
|
||||||
|
class IRemoteDecoderChild
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(IRemoteDecoderChild);
|
||||||
|
|
||||||
|
virtual RefPtr<MediaDataDecoder::InitPromise> Init() = 0;
|
||||||
|
virtual RefPtr<MediaDataDecoder::DecodePromise> Decode(
|
||||||
|
MediaRawData* aSample) = 0;
|
||||||
|
virtual RefPtr<MediaDataDecoder::DecodePromise> Drain() = 0;
|
||||||
|
virtual RefPtr<MediaDataDecoder::FlushPromise> Flush() = 0;
|
||||||
|
virtual void Shutdown() = 0;
|
||||||
|
virtual bool IsHardwareAccelerated(nsACString& aFailureReason) const
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
virtual nsCString GetDescriptionName() const = 0;
|
||||||
|
virtual void SetSeekThreshold(const media::TimeUnit& aTime) {}
|
||||||
|
virtual MediaDataDecoder::ConversionRequired NeedsConversion() const
|
||||||
|
{
|
||||||
|
return MediaDataDecoder::ConversionRequired::kNeedNone;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void DestroyIPDL() = 0;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
virtual ~IRemoteDecoderChild() {}
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace mozilla
|
||||||
|
|
||||||
|
#endif // include_dom_media_ipc_IRemoteDecoderChild_h
|
140
dom/media/ipc/RemoteMediaDataDecoder.cpp
Normal file
140
dom/media/ipc/RemoteMediaDataDecoder.cpp
Normal file
@ -0,0 +1,140 @@
|
|||||||
|
/* -*- 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 "RemoteMediaDataDecoder.h"
|
||||||
|
|
||||||
|
#include "base/thread.h"
|
||||||
|
|
||||||
|
#include "IRemoteDecoderChild.h"
|
||||||
|
|
||||||
|
namespace mozilla {
|
||||||
|
|
||||||
|
using base::Thread;
|
||||||
|
|
||||||
|
RemoteMediaDataDecoder::RemoteMediaDataDecoder(
|
||||||
|
IRemoteDecoderChild* aChild,
|
||||||
|
nsIThread* aManagerThread,
|
||||||
|
AbstractThread* aAbstractManagerThread)
|
||||||
|
: mChild(aChild)
|
||||||
|
, mManagerThread(aManagerThread)
|
||||||
|
, mAbstractManagerThread(aAbstractManagerThread)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
RemoteMediaDataDecoder::~RemoteMediaDataDecoder()
|
||||||
|
{
|
||||||
|
// We're about to be destroyed and drop our ref to
|
||||||
|
// *DecoderChild. Make sure we put a ref into the
|
||||||
|
// task queue for the *DecoderChild thread to keep
|
||||||
|
// it alive until we send the delete message.
|
||||||
|
RefPtr<IRemoteDecoderChild> child = mChild.forget();
|
||||||
|
|
||||||
|
RefPtr<Runnable> task = NS_NewRunnableFunction(
|
||||||
|
"dom::RemoteMediaDataDecoder::~RemoteMediaDataDecoder", [child]() {
|
||||||
|
MOZ_ASSERT(child);
|
||||||
|
child->DestroyIPDL();
|
||||||
|
});
|
||||||
|
|
||||||
|
// Drop our references to the child so that the last ref
|
||||||
|
// always gets released on the manager thread.
|
||||||
|
child = nullptr;
|
||||||
|
|
||||||
|
mManagerThread->Dispatch(task.forget(), NS_DISPATCH_NORMAL);
|
||||||
|
}
|
||||||
|
|
||||||
|
RefPtr<MediaDataDecoder::InitPromise>
|
||||||
|
RemoteMediaDataDecoder::Init()
|
||||||
|
{
|
||||||
|
RefPtr<RemoteMediaDataDecoder> self = this;
|
||||||
|
return InvokeAsync(mAbstractManagerThread,
|
||||||
|
__func__,
|
||||||
|
[self]() { return self->mChild->Init(); })
|
||||||
|
->Then(mAbstractManagerThread,
|
||||||
|
__func__,
|
||||||
|
[self, this](TrackType aTrack) {
|
||||||
|
mDescription =
|
||||||
|
mChild->GetDescriptionName() + NS_LITERAL_CSTRING(" (remote)");
|
||||||
|
mIsHardwareAccelerated =
|
||||||
|
mChild->IsHardwareAccelerated(mHardwareAcceleratedReason);
|
||||||
|
mConversion = mChild->NeedsConversion();
|
||||||
|
return InitPromise::CreateAndResolve(aTrack, __func__);
|
||||||
|
},
|
||||||
|
[self](const MediaResult& aError) {
|
||||||
|
return InitPromise::CreateAndReject(aError, __func__);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
RefPtr<MediaDataDecoder::DecodePromise>
|
||||||
|
RemoteMediaDataDecoder::Decode(MediaRawData* aSample)
|
||||||
|
{
|
||||||
|
RefPtr<RemoteMediaDataDecoder> self = this;
|
||||||
|
RefPtr<MediaRawData> sample = aSample;
|
||||||
|
return InvokeAsync(mAbstractManagerThread, __func__, [self, sample]() {
|
||||||
|
return self->mChild->Decode(sample);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
RefPtr<MediaDataDecoder::FlushPromise>
|
||||||
|
RemoteMediaDataDecoder::Flush()
|
||||||
|
{
|
||||||
|
RefPtr<RemoteMediaDataDecoder> self = this;
|
||||||
|
return InvokeAsync(mAbstractManagerThread, __func__, [self]() {
|
||||||
|
return self->mChild->Flush();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
RefPtr<MediaDataDecoder::DecodePromise>
|
||||||
|
RemoteMediaDataDecoder::Drain()
|
||||||
|
{
|
||||||
|
RefPtr<RemoteMediaDataDecoder> self = this;
|
||||||
|
return InvokeAsync(mAbstractManagerThread, __func__, [self]() {
|
||||||
|
return self->mChild->Drain();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
RefPtr<ShutdownPromise>
|
||||||
|
RemoteMediaDataDecoder::Shutdown()
|
||||||
|
{
|
||||||
|
RefPtr<RemoteMediaDataDecoder> self = this;
|
||||||
|
return InvokeAsync(mAbstractManagerThread, __func__, [self]() {
|
||||||
|
self->mChild->Shutdown();
|
||||||
|
return ShutdownPromise::CreateAndResolve(true, __func__);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
RemoteMediaDataDecoder::IsHardwareAccelerated(nsACString& aFailureReason) const
|
||||||
|
{
|
||||||
|
aFailureReason = mHardwareAcceleratedReason;
|
||||||
|
return mIsHardwareAccelerated;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
RemoteMediaDataDecoder::SetSeekThreshold(const media::TimeUnit& aTime)
|
||||||
|
{
|
||||||
|
RefPtr<RemoteMediaDataDecoder> self = this;
|
||||||
|
media::TimeUnit time = aTime;
|
||||||
|
mManagerThread->Dispatch(
|
||||||
|
NS_NewRunnableFunction("dom::RemoteMediaDataDecoder::SetSeekThreshold",
|
||||||
|
[=]() {
|
||||||
|
MOZ_ASSERT(self->mChild);
|
||||||
|
self->mChild->SetSeekThreshold(time);
|
||||||
|
}),
|
||||||
|
NS_DISPATCH_NORMAL);
|
||||||
|
}
|
||||||
|
|
||||||
|
MediaDataDecoder::ConversionRequired
|
||||||
|
RemoteMediaDataDecoder::NeedsConversion() const
|
||||||
|
{
|
||||||
|
return mConversion;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsCString
|
||||||
|
RemoteMediaDataDecoder::GetDescriptionName() const
|
||||||
|
{
|
||||||
|
return mDescription;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace mozilla
|
66
dom/media/ipc/RemoteMediaDataDecoder.h
Normal file
66
dom/media/ipc/RemoteMediaDataDecoder.h
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
/* -*- 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_RemoteMediaDataDecoder_h
|
||||||
|
#define include_dom_media_ipc_RemoteMediaDataDecoder_h
|
||||||
|
#include "PlatformDecoderModule.h"
|
||||||
|
|
||||||
|
#include "MediaData.h"
|
||||||
|
|
||||||
|
namespace mozilla {
|
||||||
|
|
||||||
|
class GpuDecoderModule;
|
||||||
|
class IRemoteDecoderChild;
|
||||||
|
class RemoteMediaDataDecoder;
|
||||||
|
|
||||||
|
DDLoggedTypeCustomNameAndBase(RemoteMediaDataDecoder,
|
||||||
|
RemoteMediaDataDecoder,
|
||||||
|
MediaDataDecoder);
|
||||||
|
|
||||||
|
// A MediaDataDecoder implementation that proxies through IPDL
|
||||||
|
// to a 'real' decoder in the GPU or RDD process.
|
||||||
|
// All requests get forwarded to a *DecoderChild instance that
|
||||||
|
// operates solely on the provided manager and abstract manager threads.
|
||||||
|
class RemoteMediaDataDecoder
|
||||||
|
: public MediaDataDecoder
|
||||||
|
, public DecoderDoctorLifeLogger<RemoteMediaDataDecoder>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
friend class GpuDecoderModule;
|
||||||
|
|
||||||
|
// MediaDataDecoder
|
||||||
|
RefPtr<InitPromise> Init() override;
|
||||||
|
RefPtr<DecodePromise> Decode(MediaRawData* aSample) override;
|
||||||
|
RefPtr<DecodePromise> Drain() override;
|
||||||
|
RefPtr<FlushPromise> Flush() override;
|
||||||
|
RefPtr<ShutdownPromise> Shutdown() override;
|
||||||
|
bool IsHardwareAccelerated(nsACString& aFailureReason) const override;
|
||||||
|
void SetSeekThreshold(const media::TimeUnit& aTime) override;
|
||||||
|
nsCString GetDescriptionName() const override;
|
||||||
|
ConversionRequired NeedsConversion() const override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
RemoteMediaDataDecoder(IRemoteDecoderChild* aChild,
|
||||||
|
nsIThread* aManagerThread,
|
||||||
|
AbstractThread* aAbstractManagerThread);
|
||||||
|
~RemoteMediaDataDecoder();
|
||||||
|
|
||||||
|
// 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<IRemoteDecoderChild> mChild;
|
||||||
|
nsIThread* mManagerThread;
|
||||||
|
AbstractThread* mAbstractManagerThread;
|
||||||
|
// Only ever written/modified during decoder initialisation.
|
||||||
|
// As such can be accessed from any threads after that.
|
||||||
|
nsCString mDescription = NS_LITERAL_CSTRING("RemoteMediaDataDecoder");
|
||||||
|
bool mIsHardwareAccelerated = false;
|
||||||
|
nsCString mHardwareAcceleratedReason;
|
||||||
|
ConversionRequired mConversion = ConversionRequired::kNeedNone;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace mozilla
|
||||||
|
|
||||||
|
#endif // include_dom_media_ipc_RemoteMediaDataDecoder_h
|
@ -1,218 +0,0 @@
|
|||||||
/* -*- 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 "mozilla/StaticPrefs.h"
|
|
||||||
#include "base/thread.h"
|
|
||||||
#include "MediaInfo.h"
|
|
||||||
#include "ImageContainer.h"
|
|
||||||
#include "mozilla/layers/SynchronousTask.h"
|
|
||||||
|
|
||||||
namespace mozilla {
|
|
||||||
namespace dom {
|
|
||||||
|
|
||||||
using base::Thread;
|
|
||||||
using namespace ipc;
|
|
||||||
using namespace layers;
|
|
||||||
using namespace gfx;
|
|
||||||
|
|
||||||
RemoteVideoDecoder::RemoteVideoDecoder()
|
|
||||||
: mActor(new VideoDecoderChild())
|
|
||||||
, mDescription("RemoteVideoDecoder")
|
|
||||||
, mIsHardwareAccelerated(false)
|
|
||||||
, mConversion(MediaDataDecoder::ConversionRequired::kNeedNone)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
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;
|
|
||||||
|
|
||||||
RefPtr<Runnable> task = NS_NewRunnableFunction(
|
|
||||||
"dom::RemoteVideoDecoder::~RemoteVideoDecoder", [actor]() {
|
|
||||||
MOZ_ASSERT(actor);
|
|
||||||
actor->DestroyIPDL();
|
|
||||||
});
|
|
||||||
|
|
||||||
// Drop out references to the actor so that the last ref
|
|
||||||
// always gets released on the manager thread.
|
|
||||||
actor = nullptr;
|
|
||||||
mActor = nullptr;
|
|
||||||
|
|
||||||
VideoDecoderManagerChild::GetManagerThread()->Dispatch(task.forget(),
|
|
||||||
NS_DISPATCH_NORMAL);
|
|
||||||
}
|
|
||||||
|
|
||||||
RefPtr<MediaDataDecoder::InitPromise>
|
|
||||||
RemoteVideoDecoder::Init()
|
|
||||||
{
|
|
||||||
RefPtr<RemoteVideoDecoder> self = this;
|
|
||||||
return InvokeAsync(VideoDecoderManagerChild::GetManagerAbstractThread(),
|
|
||||||
__func__,
|
|
||||||
[self]() { return self->mActor->Init(); })
|
|
||||||
->Then(VideoDecoderManagerChild::GetManagerAbstractThread(),
|
|
||||||
__func__,
|
|
||||||
[self, this](TrackType aTrack) {
|
|
||||||
mDescription =
|
|
||||||
mActor->GetDescriptionName() + NS_LITERAL_CSTRING(" (remote)");
|
|
||||||
mIsHardwareAccelerated =
|
|
||||||
mActor->IsHardwareAccelerated(mHardwareAcceleratedReason);
|
|
||||||
mConversion = mActor->NeedsConversion();
|
|
||||||
return InitPromise::CreateAndResolve(aTrack, __func__);
|
|
||||||
},
|
|
||||||
[self](const MediaResult& aError) {
|
|
||||||
return InitPromise::CreateAndReject(aError, __func__);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
RefPtr<MediaDataDecoder::DecodePromise>
|
|
||||||
RemoteVideoDecoder::Decode(MediaRawData* aSample)
|
|
||||||
{
|
|
||||||
RefPtr<RemoteVideoDecoder> self = this;
|
|
||||||
RefPtr<MediaRawData> sample = aSample;
|
|
||||||
return InvokeAsync(VideoDecoderManagerChild::GetManagerAbstractThread(),
|
|
||||||
__func__,
|
|
||||||
[self, sample]() { return self->mActor->Decode(sample); });
|
|
||||||
}
|
|
||||||
|
|
||||||
RefPtr<MediaDataDecoder::FlushPromise>
|
|
||||||
RemoteVideoDecoder::Flush()
|
|
||||||
{
|
|
||||||
RefPtr<RemoteVideoDecoder> self = this;
|
|
||||||
return InvokeAsync(VideoDecoderManagerChild::GetManagerAbstractThread(),
|
|
||||||
__func__, [self]() { return self->mActor->Flush(); });
|
|
||||||
}
|
|
||||||
|
|
||||||
RefPtr<MediaDataDecoder::DecodePromise>
|
|
||||||
RemoteVideoDecoder::Drain()
|
|
||||||
{
|
|
||||||
RefPtr<RemoteVideoDecoder> self = this;
|
|
||||||
return InvokeAsync(VideoDecoderManagerChild::GetManagerAbstractThread(),
|
|
||||||
__func__, [self]() { return self->mActor->Drain(); });
|
|
||||||
}
|
|
||||||
|
|
||||||
RefPtr<ShutdownPromise>
|
|
||||||
RemoteVideoDecoder::Shutdown()
|
|
||||||
{
|
|
||||||
RefPtr<RemoteVideoDecoder> self = this;
|
|
||||||
return InvokeAsync(VideoDecoderManagerChild::GetManagerAbstractThread(),
|
|
||||||
__func__, [self]() {
|
|
||||||
self->mActor->Shutdown();
|
|
||||||
return ShutdownPromise::CreateAndResolve(true, __func__);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
|
||||||
RemoteVideoDecoder::IsHardwareAccelerated(nsACString& aFailureReason) const
|
|
||||||
{
|
|
||||||
aFailureReason = mHardwareAcceleratedReason;
|
|
||||||
return mIsHardwareAccelerated;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
RemoteVideoDecoder::SetSeekThreshold(const media::TimeUnit& aTime)
|
|
||||||
{
|
|
||||||
RefPtr<RemoteVideoDecoder> self = this;
|
|
||||||
media::TimeUnit time = aTime;
|
|
||||||
VideoDecoderManagerChild::GetManagerThread()->Dispatch(
|
|
||||||
NS_NewRunnableFunction("dom::RemoteVideoDecoder::SetSeekThreshold",
|
|
||||||
[=]() {
|
|
||||||
MOZ_ASSERT(self->mActor);
|
|
||||||
self->mActor->SetSeekThreshold(time);
|
|
||||||
}),
|
|
||||||
NS_DISPATCH_NORMAL);
|
|
||||||
}
|
|
||||||
|
|
||||||
MediaDataDecoder::ConversionRequired
|
|
||||||
RemoteVideoDecoder::NeedsConversion() const
|
|
||||||
{
|
|
||||||
return mConversion;
|
|
||||||
}
|
|
||||||
|
|
||||||
nsresult
|
|
||||||
RemoteDecoderModule::Startup()
|
|
||||||
{
|
|
||||||
if (!VideoDecoderManagerChild::GetManagerThread()) {
|
|
||||||
return NS_ERROR_FAILURE;
|
|
||||||
}
|
|
||||||
return mWrapped->Startup();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
|
||||||
RemoteDecoderModule::SupportsMimeType(const nsACString& aMimeType,
|
|
||||||
DecoderDoctorDiagnostics* aDiagnostics) const
|
|
||||||
{
|
|
||||||
return mWrapped->SupportsMimeType(aMimeType, aDiagnostics);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
|
||||||
RemoteDecoderModule::Supports(const TrackInfo& aTrackInfo,
|
|
||||||
DecoderDoctorDiagnostics* aDiagnostics) const
|
|
||||||
{
|
|
||||||
return mWrapped->Supports(aTrackInfo, aDiagnostics);
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline bool
|
|
||||||
IsRemoteAcceleratedCompositor(KnowsCompositor* aKnows)
|
|
||||||
{
|
|
||||||
TextureFactoryIdentifier ident = aKnows->GetTextureFactoryIdentifier();
|
|
||||||
return ident.mParentBackend != LayersBackend::LAYERS_BASIC &&
|
|
||||||
ident.mParentProcessType == GeckoProcessType_GPU;
|
|
||||||
}
|
|
||||||
|
|
||||||
already_AddRefed<MediaDataDecoder>
|
|
||||||
RemoteDecoderModule::CreateVideoDecoder(const CreateDecoderParams& aParams)
|
|
||||||
{
|
|
||||||
if (!StaticPrefs::MediaGpuProcessDecoder() ||
|
|
||||||
!aParams.mKnowsCompositor ||
|
|
||||||
!IsRemoteAcceleratedCompositor(aParams.mKnowsCompositor))
|
|
||||||
{
|
|
||||||
return mWrapped->CreateVideoDecoder(aParams);
|
|
||||||
}
|
|
||||||
|
|
||||||
RefPtr<RemoteVideoDecoder> object = new RemoteVideoDecoder();
|
|
||||||
|
|
||||||
SynchronousTask task("InitIPDL");
|
|
||||||
MediaResult result(NS_OK);
|
|
||||||
VideoDecoderManagerChild::GetManagerThread()->Dispatch(
|
|
||||||
NS_NewRunnableFunction(
|
|
||||||
"dom::RemoteDecoderModule::CreateVideoDecoder",
|
|
||||||
[&]() {
|
|
||||||
AutoCompleteTask complete(&task);
|
|
||||||
result = object->mActor->InitIPDL(
|
|
||||||
aParams.VideoConfig(),
|
|
||||||
aParams.mRate.mValue,
|
|
||||||
aParams.mOptions,
|
|
||||||
aParams.mKnowsCompositor->GetTextureFactoryIdentifier());
|
|
||||||
}),
|
|
||||||
NS_DISPATCH_NORMAL);
|
|
||||||
task.Wait();
|
|
||||||
|
|
||||||
if (NS_FAILED(result)) {
|
|
||||||
if (aParams.mError) {
|
|
||||||
*aParams.mError = result;
|
|
||||||
}
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
return object.forget();
|
|
||||||
}
|
|
||||||
|
|
||||||
nsCString
|
|
||||||
RemoteVideoDecoder::GetDescriptionName() const
|
|
||||||
{
|
|
||||||
return mDescription;
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace dom
|
|
||||||
} // namespace mozilla
|
|
@ -1,100 +0,0 @@
|
|||||||
/* -*- 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 RemoteVideoDecoder;
|
|
||||||
}
|
|
||||||
DDLoggedTypeCustomNameAndBase(dom::RemoteVideoDecoder,
|
|
||||||
RemoteVideoDecoder,
|
|
||||||
MediaDataDecoder);
|
|
||||||
|
|
||||||
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 DecoderDoctorLifeLogger<RemoteVideoDecoder>
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
friend class RemoteDecoderModule;
|
|
||||||
|
|
||||||
// MediaDataDecoder
|
|
||||||
RefPtr<InitPromise> Init() override;
|
|
||||||
RefPtr<DecodePromise> Decode(MediaRawData* aSample) override;
|
|
||||||
RefPtr<DecodePromise> Drain() override;
|
|
||||||
RefPtr<FlushPromise> Flush() override;
|
|
||||||
RefPtr<ShutdownPromise> Shutdown() override;
|
|
||||||
bool IsHardwareAccelerated(nsACString& aFailureReason) const override;
|
|
||||||
void SetSeekThreshold(const media::TimeUnit& aTime) override;
|
|
||||||
nsCString GetDescriptionName() const override;
|
|
||||||
ConversionRequired NeedsConversion() const override;
|
|
||||||
|
|
||||||
private:
|
|
||||||
RemoteVideoDecoder();
|
|
||||||
~RemoteVideoDecoder();
|
|
||||||
|
|
||||||
// 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;
|
|
||||||
// Only ever written/modified during decoder initialisation.
|
|
||||||
// As such can be accessed from any threads after that.
|
|
||||||
nsCString mDescription;
|
|
||||||
bool mIsHardwareAccelerated;
|
|
||||||
nsCString mHardwareAcceleratedReason;
|
|
||||||
MediaDataDecoder::ConversionRequired mConversion;
|
|
||||||
};
|
|
||||||
|
|
||||||
// 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)
|
|
||||||
{}
|
|
||||||
|
|
||||||
nsresult Startup() override;
|
|
||||||
|
|
||||||
bool SupportsMimeType(const nsACString& aMimeType,
|
|
||||||
DecoderDoctorDiagnostics* aDiagnostics) const override;
|
|
||||||
bool Supports(const TrackInfo& aTrackInfo,
|
|
||||||
DecoderDoctorDiagnostics* aDiagnostics) const override;
|
|
||||||
|
|
||||||
already_AddRefed<MediaDataDecoder> CreateVideoDecoder(
|
|
||||||
const CreateDecoderParams& aParams) override;
|
|
||||||
|
|
||||||
already_AddRefed<MediaDataDecoder> CreateAudioDecoder(
|
|
||||||
const CreateDecoderParams& aParams) override
|
|
||||||
{
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
RefPtr<PlatformDecoderModule> mWrapped;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace dom
|
|
||||||
} // namespace mozilla
|
|
||||||
|
|
||||||
#endif // include_dom_ipc_RemoteVideoDecoder_h
|
|
@ -9,6 +9,7 @@
|
|||||||
#include "MediaResult.h"
|
#include "MediaResult.h"
|
||||||
#include "PlatformDecoderModule.h"
|
#include "PlatformDecoderModule.h"
|
||||||
#include "mozilla/dom/PVideoDecoderChild.h"
|
#include "mozilla/dom/PVideoDecoderChild.h"
|
||||||
|
#include "IRemoteDecoderChild.h"
|
||||||
|
|
||||||
namespace mozilla {
|
namespace mozilla {
|
||||||
namespace dom {
|
namespace dom {
|
||||||
@ -18,12 +19,11 @@ class RemoteDecoderModule;
|
|||||||
class VideoDecoderManagerChild;
|
class VideoDecoderManagerChild;
|
||||||
|
|
||||||
class VideoDecoderChild final : public PVideoDecoderChild
|
class VideoDecoderChild final : public PVideoDecoderChild
|
||||||
|
, public IRemoteDecoderChild
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
explicit VideoDecoderChild();
|
explicit VideoDecoderChild();
|
||||||
|
|
||||||
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(VideoDecoderChild)
|
|
||||||
|
|
||||||
// PVideoDecoderChild
|
// PVideoDecoderChild
|
||||||
mozilla::ipc::IPCResult RecvOutput(const VideoDataIPDL& aData) override;
|
mozilla::ipc::IPCResult RecvOutput(const VideoDataIPDL& aData) override;
|
||||||
mozilla::ipc::IPCResult RecvInputExhausted() override;
|
mozilla::ipc::IPCResult RecvInputExhausted() override;
|
||||||
@ -38,22 +38,22 @@ public:
|
|||||||
|
|
||||||
void ActorDestroy(ActorDestroyReason aWhy) override;
|
void ActorDestroy(ActorDestroyReason aWhy) override;
|
||||||
|
|
||||||
RefPtr<MediaDataDecoder::InitPromise> Init();
|
RefPtr<MediaDataDecoder::InitPromise> Init() override;
|
||||||
RefPtr<MediaDataDecoder::DecodePromise> Decode(MediaRawData* aSample);
|
RefPtr<MediaDataDecoder::DecodePromise> Decode(MediaRawData* aSample) override;
|
||||||
RefPtr<MediaDataDecoder::DecodePromise> Drain();
|
RefPtr<MediaDataDecoder::DecodePromise> Drain() override;
|
||||||
RefPtr<MediaDataDecoder::FlushPromise> Flush();
|
RefPtr<MediaDataDecoder::FlushPromise> Flush() override;
|
||||||
void Shutdown();
|
void Shutdown() override;
|
||||||
bool IsHardwareAccelerated(nsACString& aFailureReason) const;
|
bool IsHardwareAccelerated(nsACString& aFailureReason) const override;
|
||||||
nsCString GetDescriptionName() const;
|
nsCString GetDescriptionName() const override;
|
||||||
void SetSeekThreshold(const media::TimeUnit& aTime);
|
void SetSeekThreshold(const media::TimeUnit& aTime) override;
|
||||||
MediaDataDecoder::ConversionRequired NeedsConversion() const;
|
MediaDataDecoder::ConversionRequired NeedsConversion() const override;
|
||||||
|
void DestroyIPDL() override;
|
||||||
|
|
||||||
MOZ_IS_CLASS_INIT
|
MOZ_IS_CLASS_INIT
|
||||||
MediaResult InitIPDL(const VideoInfo& aVideoInfo,
|
MediaResult InitIPDL(const VideoInfo& aVideoInfo,
|
||||||
float aFramerate,
|
float aFramerate,
|
||||||
const CreateDecoderParams::OptionSet& aOptions,
|
const CreateDecoderParams::OptionSet& aOptions,
|
||||||
const layers::TextureFactoryIdentifier& aIdentifier);
|
const layers::TextureFactoryIdentifier& aIdentifier);
|
||||||
void DestroyIPDL();
|
|
||||||
|
|
||||||
// Called from IPDL when our actor has been destroyed
|
// Called from IPDL when our actor has been destroyed
|
||||||
void IPDLActorDestroyed();
|
void IPDLActorDestroyed();
|
||||||
|
@ -10,15 +10,20 @@ IPDL_SOURCES += [
|
|||||||
'PVideoDecoderManager.ipdl',
|
'PVideoDecoderManager.ipdl',
|
||||||
]
|
]
|
||||||
|
|
||||||
|
EXPORTS.mozilla += [
|
||||||
|
'GpuDecoderModule.h',
|
||||||
|
'RemoteMediaDataDecoder.h',
|
||||||
|
]
|
||||||
|
|
||||||
EXPORTS.mozilla.dom += [
|
EXPORTS.mozilla.dom += [
|
||||||
'MediaIPCUtils.h',
|
'MediaIPCUtils.h',
|
||||||
'RemoteVideoDecoder.h',
|
|
||||||
'VideoDecoderManagerChild.h',
|
'VideoDecoderManagerChild.h',
|
||||||
'VideoDecoderManagerParent.h',
|
'VideoDecoderManagerParent.h',
|
||||||
]
|
]
|
||||||
|
|
||||||
SOURCES += [
|
SOURCES += [
|
||||||
'RemoteVideoDecoder.cpp',
|
'GpuDecoderModule.cpp',
|
||||||
|
'RemoteMediaDataDecoder.cpp',
|
||||||
'VideoDecoderChild.cpp',
|
'VideoDecoderChild.cpp',
|
||||||
'VideoDecoderManagerChild.cpp',
|
'VideoDecoderManagerChild.cpp',
|
||||||
'VideoDecoderManagerParent.cpp',
|
'VideoDecoderManagerParent.cpp',
|
||||||
|
@ -45,7 +45,7 @@
|
|||||||
|
|
||||||
#include "MP4Decoder.h"
|
#include "MP4Decoder.h"
|
||||||
#include "VPXDecoder.h"
|
#include "VPXDecoder.h"
|
||||||
#include "mozilla/dom/RemoteVideoDecoder.h"
|
#include "mozilla/GpuDecoderModule.h"
|
||||||
|
|
||||||
#include "H264.h"
|
#include "H264.h"
|
||||||
|
|
||||||
@ -355,7 +355,7 @@ PDMFactory::CreatePDMs()
|
|||||||
#ifdef XP_WIN
|
#ifdef XP_WIN
|
||||||
if (StaticPrefs::MediaWmfEnabled() && !IsWin7AndPre2000Compatible()) {
|
if (StaticPrefs::MediaWmfEnabled() && !IsWin7AndPre2000Compatible()) {
|
||||||
m = new WMFDecoderModule();
|
m = new WMFDecoderModule();
|
||||||
RefPtr<PlatformDecoderModule> remote = new dom::RemoteDecoderModule(m);
|
RefPtr<PlatformDecoderModule> remote = new GpuDecoderModule(m);
|
||||||
StartupPDM(remote);
|
StartupPDM(remote);
|
||||||
mWMFFailedToLoad = !StartupPDM(m);
|
mWMFFailedToLoad = !StartupPDM(m);
|
||||||
} else {
|
} else {
|
||||||
|
@ -33,10 +33,7 @@ namespace layers {
|
|||||||
class ImageContainer;
|
class ImageContainer;
|
||||||
} // namespace layers
|
} // namespace layers
|
||||||
|
|
||||||
namespace dom {
|
class GpuDecoderModule;
|
||||||
class RemoteDecoderModule;
|
|
||||||
}
|
|
||||||
|
|
||||||
class MediaDataDecoder;
|
class MediaDataDecoder;
|
||||||
class TaskQueue;
|
class TaskQueue;
|
||||||
class CDMProxy;
|
class CDMProxy;
|
||||||
@ -214,7 +211,7 @@ protected:
|
|||||||
|
|
||||||
friend class MediaChangeMonitor;
|
friend class MediaChangeMonitor;
|
||||||
friend class PDMFactory;
|
friend class PDMFactory;
|
||||||
friend class dom::RemoteDecoderModule;
|
friend class GpuDecoderModule;
|
||||||
friend class EMEDecoderModule;
|
friend class EMEDecoderModule;
|
||||||
|
|
||||||
// Indicates if the PlatformDecoderModule supports decoding of aColorDepth.
|
// Indicates if the PlatformDecoderModule supports decoding of aColorDepth.
|
||||||
|
Loading…
Reference in New Issue
Block a user