--- a/dom/media/ipc/PVideoDecoder.ipdl
+++ b/dom/media/ipc/PVideoDecoder.ipdl
@@ -53,18 +53,17 @@ parent:
async Drain();
async Shutdown();
async SetSeekThreshold(int64_t time);
async __delete__();
child:
-
- async InitComplete(bool hardware, nsCString hardwareReason);
+ async InitComplete(bool hardware, nsCString hardwareReason, uint32_t conversion);
async InitFailed(nsresult reason);
async FlushComplete();
// Each output includes a SurfaceDescriptorGPUVideo that represents the decoded
// frame. This SurfaceDescriptor can be used on the Layers IPDL protocol, but
// must be released explicitly using DeallocateSurfaceDescriptorGPUVideo
// on the manager protocol.
--- a/dom/media/ipc/RemoteVideoDecoder.cpp
+++ b/dom/media/ipc/RemoteVideoDecoder.cpp
@@ -104,16 +104,22 @@ RemoteVideoDecoder::SetSeekThreshold(con
RefPtr<RemoteVideoDecoder> self = this;
media::TimeUnit time = aTime;
VideoDecoderManagerChild::GetManagerThread()->Dispatch(NS_NewRunnableFunction([=]() {
MOZ_ASSERT(self->mActor);
self->mActor->SetSeekThreshold(time);
}), NS_DISPATCH_NORMAL);
}
+MediaDataDecoder::ConversionRequired
+RemoteVideoDecoder::NeedsConversion() const
+{
+ return mActor->NeedsConversion();
+}
+
nsresult
RemoteDecoderModule::Startup()
{
if (!VideoDecoderManagerChild::GetManagerThread()) {
return NS_ERROR_FAILURE;
}
return mWrapped->Startup();
}
@@ -127,22 +133,16 @@ RemoteDecoderModule::SupportsMimeType(co
bool
RemoteDecoderModule::Supports(const TrackInfo& aTrackInfo,
DecoderDoctorDiagnostics* aDiagnostics) const
{
return mWrapped->Supports(aTrackInfo, aDiagnostics);
}
-PlatformDecoderModule::ConversionRequired
-RemoteDecoderModule::DecoderNeedsConversion(const TrackInfo& aConfig) const
-{
- return mWrapped->DecoderNeedsConversion(aConfig);
-}
-
already_AddRefed<MediaDataDecoder>
RemoteDecoderModule::CreateVideoDecoder(const CreateDecoderParams& aParams)
{
if (!MediaPrefs::PDMUseGPUDecoder() ||
!aParams.mKnowsCompositor ||
aParams.mKnowsCompositor->GetTextureFactoryIdentifier().mParentProcessType != GeckoProcessType_GPU) {
return mWrapped->CreateVideoDecoder(aParams);
}
--- a/dom/media/ipc/RemoteVideoDecoder.h
+++ b/dom/media/ipc/RemoteVideoDecoder.h
@@ -31,16 +31,17 @@ public:
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;
const char* GetDescriptionName() const override { return "RemoteVideoDecoder"; }
+ 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.
@@ -60,19 +61,16 @@ public:
nsresult Startup() override;
bool SupportsMimeType(const nsACString& aMimeType,
DecoderDoctorDiagnostics* aDiagnostics) const override;
bool Supports(const TrackInfo& aTrackInfo,
DecoderDoctorDiagnostics* aDiagnostics) const override;
- ConversionRequired DecoderNeedsConversion(
- const TrackInfo& aConfig) const override;
-
already_AddRefed<MediaDataDecoder> CreateVideoDecoder(
const CreateDecoderParams& aParams) override;
already_AddRefed<MediaDataDecoder> CreateAudioDecoder(
const CreateDecoderParams& aParams) override
{
return nullptr;
}
--- a/dom/media/ipc/VideoDecoderChild.cpp
+++ b/dom/media/ipc/VideoDecoderChild.cpp
@@ -19,16 +19,17 @@ using namespace ipc;
using namespace layers;
using namespace gfx;
VideoDecoderChild::VideoDecoderChild()
: mThread(VideoDecoderManagerChild::GetManagerThread())
, mCanSend(false)
, mInitialized(false)
, mIsHardwareAccelerated(false)
+ , mConversion(MediaDataDecoder::ConversionRequired::kNeedNone)
, mNeedNewDecoder(false)
{
}
VideoDecoderChild::~VideoDecoderChild()
{
AssertOnManagerThread();
mInitPromise.RejectIfExists(NS_ERROR_DOM_MEDIA_CANCELED, __func__);
@@ -83,23 +84,25 @@ VideoDecoderChild::RecvError(const nsres
mDecodePromise.RejectIfExists(aError, __func__);
mDrainPromise.RejectIfExists(aError, __func__);
mFlushPromise.RejectIfExists(aError, __func__);
return IPC_OK();
}
mozilla::ipc::IPCResult
VideoDecoderChild::RecvInitComplete(const bool& aHardware,
- const nsCString& aHardwareReason)
+ const nsCString& aHardwareReason,
+ const uint32_t& aConversion)
{
AssertOnManagerThread();
mInitPromise.ResolveIfExists(TrackInfo::kVideoTrack, __func__);
mInitialized = true;
mIsHardwareAccelerated = aHardware;
mHardwareAcceleratedReason = aHardwareReason;
+ mConversion = static_cast<MediaDataDecoder::ConversionRequired>(aConversion);
return IPC_OK();
}
mozilla::ipc::IPCResult
VideoDecoderChild::RecvInitFailed(const nsresult& aReason)
{
AssertOnManagerThread();
mInitPromise.RejectIfExists(aReason, __func__);
@@ -289,18 +292,24 @@ void
VideoDecoderChild::SetSeekThreshold(const media::TimeUnit& aTime)
{
AssertOnManagerThread();
if (mCanSend) {
SendSetSeekThreshold(aTime.ToMicroseconds());
}
}
+MediaDataDecoder::ConversionRequired
+VideoDecoderChild::NeedsConversion() const
+{
+ return mConversion;
+}
+
void
-VideoDecoderChild::AssertOnManagerThread()
+VideoDecoderChild::AssertOnManagerThread() const
{
MOZ_ASSERT(NS_GetCurrentThread() == mThread);
}
VideoDecoderManagerChild*
VideoDecoderChild::GetManager()
{
if (!mCanSend) {
--- a/dom/media/ipc/VideoDecoderChild.h
+++ b/dom/media/ipc/VideoDecoderChild.h
@@ -2,16 +2,17 @@
/* 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_VideoDecoderChild_h
#define include_dom_ipc_VideoDecoderChild_h
#include "PlatformDecoderModule.h"
+#include "mozilla/Atomics.h"
#include "mozilla/dom/PVideoDecoderChild.h"
namespace mozilla {
namespace dom {
class RemoteVideoDecoder;
class RemoteDecoderModule;
class VideoDecoderManagerChild;
@@ -23,57 +24,62 @@ public:
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(VideoDecoderChild)
// PVideoDecoderChild
mozilla::ipc::IPCResult RecvOutput(const VideoDataIPDL& aData) override;
mozilla::ipc::IPCResult RecvInputExhausted() override;
mozilla::ipc::IPCResult RecvDrainComplete() override;
mozilla::ipc::IPCResult RecvError(const nsresult& aError) override;
- mozilla::ipc::IPCResult RecvInitComplete(const bool& aHardware, const nsCString& aHardwareReason) override;
+ mozilla::ipc::IPCResult RecvInitComplete(const bool& aHardware,
+ const nsCString& aHardwareReason,
+ const uint32_t& aConversion) override;
mozilla::ipc::IPCResult RecvInitFailed(const nsresult& aReason) override;
mozilla::ipc::IPCResult RecvFlushComplete() override;
void ActorDestroy(ActorDestroyReason aWhy) override;
RefPtr<MediaDataDecoder::InitPromise> Init();
RefPtr<MediaDataDecoder::DecodePromise> Decode(MediaRawData* aSample);
RefPtr<MediaDataDecoder::DecodePromise> Drain();
RefPtr<MediaDataDecoder::FlushPromise> Flush();
void Shutdown();
bool IsHardwareAccelerated(nsACString& aFailureReason) const;
void SetSeekThreshold(const media::TimeUnit& aTime);
+ MediaDataDecoder::ConversionRequired NeedsConversion() const;
MOZ_IS_CLASS_INIT
bool InitIPDL(const VideoInfo& aVideoInfo,
const layers::TextureFactoryIdentifier& aIdentifier);
void DestroyIPDL();
// Called from IPDL when our actor has been destroyed
void IPDLActorDestroyed();
VideoDecoderManagerChild* GetManager();
private:
~VideoDecoderChild();
- void AssertOnManagerThread();
+ void AssertOnManagerThread() const;
RefPtr<VideoDecoderChild> mIPDLSelfRef;
RefPtr<nsIThread> mThread;
MozPromiseHolder<MediaDataDecoder::InitPromise> mInitPromise;
MozPromiseHolder<MediaDataDecoder::DecodePromise> mDecodePromise;
MozPromiseHolder<MediaDataDecoder::DecodePromise> mDrainPromise;
MozPromiseHolder<MediaDataDecoder::FlushPromise> mFlushPromise;
nsCString mHardwareAcceleratedReason;
bool mCanSend;
bool mInitialized;
- bool mIsHardwareAccelerated;
+ Atomic<bool> mIsHardwareAccelerated;
+ Atomic<MediaDataDecoder::ConversionRequired> mConversion;
+
// Set to true if the actor got destroyed and we haven't yet notified the
// caller.
bool mNeedNewDecoder;
MediaDataDecoder::DecodedData mDecodedData;
};
} // namespace dom
} // namespace mozilla
--- a/dom/media/ipc/VideoDecoderParent.cpp
+++ b/dom/media/ipc/VideoDecoderParent.cpp
@@ -104,17 +104,20 @@ VideoDecoderParent::RecvInit()
MOZ_ASSERT(OnManagerThread());
RefPtr<VideoDecoderParent> self = this;
mDecoder->Init()->Then(mManagerTaskQueue, __func__,
[self] (TrackInfo::TrackType aTrack) {
if (self->mDecoder) {
nsCString hardwareReason;
bool hardwareAccelerated =
self->mDecoder->IsHardwareAccelerated(hardwareReason);
- Unused << self->SendInitComplete(hardwareAccelerated, hardwareReason);
+ uint32_t conversion =
+ static_cast<uint32_t>(self->mDecoder->NeedsConversion());
+ Unused << self->SendInitComplete(
+ hardwareAccelerated, hardwareReason, conversion);
}
},
[self] (MediaResult aReason) {
if (!self->mDestroyed) {
Unused << self->SendInitFailed(aReason);
}
});
return IPC_OK();
--- a/dom/media/platforms/PlatformDecoderModule.h
+++ b/dom/media/platforms/PlatformDecoderModule.h
@@ -147,29 +147,16 @@ public:
virtual bool Supports(const TrackInfo& aTrackInfo,
DecoderDoctorDiagnostics* aDiagnostics) const
{
// By default, fall back to SupportsMimeType with just the MIME string.
// (So PDMs do not need to override this method -- yet.)
return SupportsMimeType(aTrackInfo.mMimeType, aDiagnostics);
}
- enum class ConversionRequired : uint8_t
- {
- kNeedNone,
- kNeedAVCC,
- kNeedAnnexB,
- };
-
- // Indicates that the decoder requires a specific format.
- // The PlatformDecoderModule will convert the demuxed data accordingly before
- // feeding it to MediaDataDecoder::Input.
- virtual ConversionRequired DecoderNeedsConversion(
- const TrackInfo& aConfig) const = 0;
-
protected:
PlatformDecoderModule() { }
virtual ~PlatformDecoderModule() { }
friend class H264Converter;
friend class PDMFactory;
friend class dom::RemoteDecoderModule;
friend class EMEDecoderModule;
@@ -311,13 +298,27 @@ public:
// Care should be taken as ConfigurationChanged is called on the reader's
// taskqueue.
virtual void ConfigurationChanged(const TrackInfo& aConfig)
{
MOZ_ASSERT(SupportDecoderRecycling(),
"Can only work with a decoder supporting recycling.");
}
+ enum class ConversionRequired
+ {
+ kNeedNone = 0,
+ kNeedAVCC = 1,
+ kNeedAnnexB = 2,
+ };
+
+ // Indicates that the decoder requires a specific format.
+ // The demuxed data will be converted accordingly before feeding it to
+ // Decode().
+ virtual ConversionRequired NeedsConversion() const
+ {
+ return ConversionRequired::kNeedNone;
+ }
};
} // namespace mozilla
#endif
--- a/dom/media/platforms/agnostic/AgnosticDecoderModule.h
+++ b/dom/media/platforms/agnostic/AgnosticDecoderModule.h
@@ -8,22 +8,16 @@ namespace mozilla {
class AgnosticDecoderModule : public PlatformDecoderModule
{
public:
AgnosticDecoderModule() = default;
bool SupportsMimeType(const nsACString& aMimeType,
DecoderDoctorDiagnostics* aDiagnostics) const override;
- ConversionRequired
- DecoderNeedsConversion(const TrackInfo& aConfig) const override
- {
- return ConversionRequired::kNeedNone;
- }
-
protected:
virtual ~AgnosticDecoderModule() = default;
// Decode thread.
already_AddRefed<MediaDataDecoder>
CreateVideoDecoder(const CreateDecoderParams& aParams) override;
// Decode thread.
already_AddRefed<MediaDataDecoder>
--- a/dom/media/platforms/agnostic/BlankDecoderModule.cpp
+++ b/dom/media/platforms/agnostic/BlankDecoderModule.cpp
@@ -27,24 +27,24 @@ namespace mozilla {
// MediaData objects.
template<class BlankMediaDataCreator>
class BlankMediaDataDecoder : public MediaDataDecoder
{
public:
BlankMediaDataDecoder(BlankMediaDataCreator* aCreator,
const CreateDecoderParams& aParams)
: mCreator(aCreator)
+ , mIsH264(MP4Decoder::IsH264(aParams.mConfig.mMimeType))
, mMaxRefFrames(
- aParams.mConfig.GetType() == TrackInfo::kVideoTrack
- && MP4Decoder::IsH264(aParams.mConfig.mMimeType)
- ? mp4_demuxer::AnnexB::HasSPS(aParams.VideoConfig().mExtraData)
- ? mp4_demuxer::H264::ComputeMaxRefFrames(
- aParams.VideoConfig().mExtraData)
- : 16
- : 0)
+ mIsH264
+ ? mp4_demuxer::AnnexB::HasSPS(aParams.VideoConfig().mExtraData)
+ ? mp4_demuxer::H264::ComputeMaxRefFrames(
+ aParams.VideoConfig().mExtraData)
+ : 16
+ : 0)
, mType(aParams.mConfig.GetType())
{
}
RefPtr<InitPromise> Init() override
{
return InitPromise::CreateAndResolve(mType, __func__);
}
@@ -90,18 +90,26 @@ public:
return FlushPromise::CreateAndResolve(true, __func__);
}
const char* GetDescriptionName() const override
{
return "blank media data decoder";
}
+ ConversionRequired NeedsConversion() const override
+ {
+ return mIsH264
+ ? ConversionRequired::kNeedAVCC
+ : ConversionRequired::kNeedNone;
+ }
+
private:
nsAutoPtr<BlankMediaDataCreator> mCreator;
+ const bool mIsH264;
const uint32_t mMaxRefFrames;
ReorderQueue mReorderQueue;
TrackInfo::TrackType mType;
};
class BlankVideoDataCreator
{
public:
@@ -255,27 +263,16 @@ public:
return decoder.forget();
}
bool SupportsMimeType(const nsACString& aMimeType,
DecoderDoctorDiagnostics* aDiagnostics) const override
{
return true;
}
-
- ConversionRequired
- DecoderNeedsConversion(const TrackInfo& aConfig) const override
- {
- if (aConfig.IsVideo() && MP4Decoder::IsH264(aConfig.mMimeType)) {
- return ConversionRequired::kNeedAVCC;
- } else {
- return ConversionRequired::kNeedNone;
- }
- }
-
};
already_AddRefed<PlatformDecoderModule> CreateBlankDecoderModule()
{
RefPtr<PlatformDecoderModule> pdm = new BlankDecoderModule();
return pdm.forget();
}
--- a/dom/media/platforms/agnostic/eme/EMEDecoderModule.cpp
+++ b/dom/media/platforms/agnostic/eme/EMEDecoderModule.cpp
@@ -184,16 +184,21 @@ public:
return decoder->Shutdown();
}
const char* GetDescriptionName() const override
{
return mDecoder->GetDescriptionName();
}
+ ConversionRequired NeedsConversion() const override
+ {
+ return mDecoder->NeedsConversion();
+ }
+
private:
RefPtr<MediaDataDecoder> mDecoder;
RefPtr<TaskQueue> mTaskQueue;
RefPtr<CDMProxy> mProxy;
nsClassHashtable<nsRefPtrHashKey<MediaRawData>, DecryptPromiseRequestHolder>
mDecrypts;
RefPtr<SamplesWaitingForKey> mSamplesWaitingForKey;
MozPromiseRequestHolder<SamplesWaitingForKey::WaitForKeyPromise> mKeyRequest;
@@ -365,26 +370,16 @@ EMEDecoderModule::CreateAudioDecoder(con
}
RefPtr<MediaDataDecoder> emeDecoder(new EMEDecryptor(
decoder, mProxy, AbstractThread::GetCurrent()->AsTaskQueue(),
aParams.mType, aParams.mOnWaitingForKeyEvent));
return emeDecoder.forget();
}
-PlatformDecoderModule::ConversionRequired
-EMEDecoderModule::DecoderNeedsConversion(const TrackInfo& aConfig) const
-{
- if (aConfig.IsVideo() && MP4Decoder::IsH264(aConfig.mMimeType)) {
- return ConversionRequired::kNeedAVCC;
- } else {
- return ConversionRequired::kNeedNone;
- }
-}
-
bool
EMEDecoderModule::SupportsMimeType(const nsACString& aMimeType,
DecoderDoctorDiagnostics* aDiagnostics) const
{
Maybe<nsCString> gmp;
gmp.emplace(NS_ConvertUTF16toUTF8(mProxy->KeySystem()));
return GMPDecoderModule::SupportsMimeType(aMimeType, gmp);
}
--- a/dom/media/platforms/agnostic/eme/EMEDecoderModule.h
+++ b/dom/media/platforms/agnostic/eme/EMEDecoderModule.h
@@ -26,19 +26,16 @@ protected:
// Decode thread.
already_AddRefed<MediaDataDecoder>
CreateVideoDecoder(const CreateDecoderParams& aParams) override;
// Decode thread.
already_AddRefed<MediaDataDecoder>
CreateAudioDecoder(const CreateDecoderParams& aParams) override;
- ConversionRequired
- DecoderNeedsConversion(const TrackInfo& aConfig) const override;
-
bool
SupportsMimeType(const nsACString &aMimeType,
DecoderDoctorDiagnostics *aDiagnostics) const override;
private:
virtual ~EMEDecoderModule();
RefPtr<CDMProxy> mProxy;
// Will be null if CDM has decoding capability.
--- a/dom/media/platforms/agnostic/gmp/GMPDecoderModule.cpp
+++ b/dom/media/platforms/agnostic/gmp/GMPDecoderModule.cpp
@@ -65,28 +65,16 @@ GMPDecoderModule::CreateVideoDecoder(con
}
already_AddRefed<MediaDataDecoder>
GMPDecoderModule::CreateAudioDecoder(const CreateDecoderParams& aParams)
{
return nullptr;
}
-PlatformDecoderModule::ConversionRequired
-GMPDecoderModule::DecoderNeedsConversion(const TrackInfo& aConfig) const
-{
- // GMPVideoCodecType::kGMPVideoCodecH264 specifies that encoded frames must be
- // in AVCC format.
- if (aConfig.IsVideo() && MP4Decoder::IsH264(aConfig.mMimeType)) {
- return ConversionRequired::kNeedAVCC;
- } else {
- return ConversionRequired::kNeedNone;
- }
-}
-
/* static */
bool
GMPDecoderModule::SupportsMimeType(const nsACString& aMimeType,
const Maybe<nsCString>& aGMP)
{
if (aGMP.isNothing()) {
return false;
}
--- a/dom/media/platforms/agnostic/gmp/GMPDecoderModule.h
+++ b/dom/media/platforms/agnostic/gmp/GMPDecoderModule.h
@@ -33,19 +33,16 @@ public:
// Decode thread.
already_AddRefed<MediaDataDecoder>
CreateVideoDecoder(const CreateDecoderParams& aParams) override;
// Decode thread.
already_AddRefed<MediaDataDecoder>
CreateAudioDecoder(const CreateDecoderParams& aParams) override;
- ConversionRequired
- DecoderNeedsConversion(const TrackInfo& aConfig) const override;
-
bool
SupportsMimeType(const nsACString& aMimeType,
DecoderDoctorDiagnostics* aDiagnostics) const override;
static bool SupportsMimeType(const nsACString& aMimeType,
const Maybe<nsCString>& aGMP);
private:
--- a/dom/media/platforms/agnostic/gmp/GMPVideoDecoder.h
+++ b/dom/media/platforms/agnostic/gmp/GMPVideoDecoder.h
@@ -37,16 +37,20 @@ public:
RefPtr<DecodePromise> Decode(MediaRawData* aSample) override;
RefPtr<DecodePromise> Drain() override;
RefPtr<FlushPromise> Flush() override;
RefPtr<ShutdownPromise> Shutdown() override;
const char* GetDescriptionName() const override
{
return "GMP video decoder";
}
+ ConversionRequired NeedsConversion() const override
+ {
+ return ConversionRequired::kNeedAVCC;
+ }
// GMPVideoDecoderCallbackProxy
// All those methods are called on the GMP thread.
void Decoded(GMPVideoi420Frame* aDecodedFrame) override;
void ReceivedDecodedReferenceFrame(const uint64_t aPictureId) override;
void ReceivedDecodedFrame(const uint64_t aPictureId) override;
void InputDataExhausted() override;
void DrainComplete() override;
--- a/dom/media/platforms/android/AndroidDecoderModule.cpp
+++ b/dom/media/platforms/android/AndroidDecoderModule.cpp
@@ -205,18 +205,9 @@ AndroidDecoderModule::CreateAudioDecoder
if (mProxy) {
drmStubId = mProxy->GetMediaDrmStubId();
}
RefPtr<MediaDataDecoder> decoder =
RemoteDataDecoder::CreateAudioDecoder(aParams, drmStubId, mProxy);
return decoder.forget();
}
-PlatformDecoderModule::ConversionRequired
-AndroidDecoderModule::DecoderNeedsConversion(const TrackInfo& aConfig) const
-{
- if (aConfig.IsVideo()) {
- return ConversionRequired::kNeedAnnexB;
- }
- return ConversionRequired::kNeedNone;
-}
-
} // mozilla
--- a/dom/media/platforms/android/AndroidDecoderModule.h
+++ b/dom/media/platforms/android/AndroidDecoderModule.h
@@ -19,19 +19,16 @@ public:
already_AddRefed<MediaDataDecoder>
CreateAudioDecoder(const CreateDecoderParams& aParams) override;
AndroidDecoderModule(CDMProxy* aProxy = nullptr);
bool SupportsMimeType(const nsACString& aMimeType,
DecoderDoctorDiagnostics* aDiagnostics) const override;
- ConversionRequired
- DecoderNeedsConversion(const TrackInfo& aConfig) const override;
-
private:
virtual ~AndroidDecoderModule() { }
RefPtr<MediaDrmCDMProxy> mProxy;
};
extern LazyLogModule sAndroidDecoderModuleLog;
} // namespace mozilla
--- a/dom/media/platforms/android/RemoteDataDecoder.cpp
+++ b/dom/media/platforms/android/RemoteDataDecoder.cpp
@@ -332,16 +332,21 @@ public:
if (mJavaDecoder == nullptr) {
return InitPromise::CreateAndReject(NS_ERROR_DOM_MEDIA_FATAL_ERR,
__func__);
}
return InitPromise::CreateAndResolve(TrackInfo::kAudioTrack, __func__);
}
+ ConversionRequired NeedsConversion() const override
+ {
+ return ConversionRequired::kNeedAnnexB;
+ }
+
private:
class CallbacksSupport final : public JavaCallbacksSupport
{
public:
CallbacksSupport(RemoteAudioDecoder* aDecoder) : mDecoder(aDecoder) { }
void HandleInputExhausted() override
{
--- a/dom/media/platforms/apple/AppleDecoderModule.cpp
+++ b/dom/media/platforms/apple/AppleDecoderModule.cpp
@@ -18,23 +18,19 @@
namespace mozilla {
bool AppleDecoderModule::sInitialized = false;
bool AppleDecoderModule::sIsCoreMediaAvailable = false;
bool AppleDecoderModule::sIsVTAvailable = false;
bool AppleDecoderModule::sIsVTHWAvailable = false;
bool AppleDecoderModule::sCanUseHardwareVideoDecoder = true;
-AppleDecoderModule::AppleDecoderModule()
-{
-}
+AppleDecoderModule::AppleDecoderModule() { }
-AppleDecoderModule::~AppleDecoderModule()
-{
-}
+AppleDecoderModule::~AppleDecoderModule() { }
/* static */
void
AppleDecoderModule::Init()
{
if (sInitialized) {
return;
}
@@ -92,19 +88,9 @@ AppleDecoderModule::SupportsMimeType(con
{
return (sIsCoreMediaAvailable &&
(aMimeType.EqualsLiteral("audio/mpeg") ||
aMimeType.EqualsLiteral("audio/mp4a-latm"))) ||
(sIsVTAvailable && (aMimeType.EqualsLiteral("video/mp4") ||
aMimeType.EqualsLiteral("video/avc")));
}
-PlatformDecoderModule::ConversionRequired
-AppleDecoderModule::DecoderNeedsConversion(const TrackInfo& aConfig) const
-{
- if (aConfig.IsVideo()) {
- return ConversionRequired::kNeedAVCC;
- } else {
- return ConversionRequired::kNeedNone;
- }
-}
-
} // namespace mozilla
--- a/dom/media/platforms/apple/AppleDecoderModule.h
+++ b/dom/media/platforms/apple/AppleDecoderModule.h
@@ -24,19 +24,16 @@ public:
// Decode thread.
already_AddRefed<MediaDataDecoder>
CreateAudioDecoder(const CreateDecoderParams& aParams) override;
bool SupportsMimeType(const nsACString& aMimeType,
DecoderDoctorDiagnostics* aDiagnostics) const override;
- ConversionRequired
- DecoderNeedsConversion(const TrackInfo& aConfig) const override;
-
static void Init();
static bool sCanUseHardwareVideoDecoder;
private:
static bool sInitialized;
static bool sIsCoreMediaAvailable;
static bool sIsVTAvailable;
--- a/dom/media/platforms/apple/AppleVTDecoder.h
+++ b/dom/media/platforms/apple/AppleVTDecoder.h
@@ -55,16 +55,21 @@ public:
const char* GetDescriptionName() const override
{
return mIsHardwareAccelerated
? "apple hardware VT decoder"
: "apple software VT decoder";
}
+ ConversionRequired NeedsConversion() const override
+ {
+ return ConversionRequired::kNeedAVCC;
+ }
+
// Access from the taskqueue and the decoder's thread.
// OutputFrame is thread-safe.
void OutputFrame(CVPixelBufferRef aImage, AppleFrameRef aFrameRef);
private:
virtual ~AppleVTDecoder();
RefPtr<FlushPromise> ProcessFlush();
RefPtr<DecodePromise> ProcessDrain();
--- a/dom/media/platforms/ffmpeg/FFmpegDecoderModule.h
+++ b/dom/media/platforms/ffmpeg/FFmpegDecoderModule.h
@@ -64,27 +64,15 @@ public:
AVCodecID audioCodec = FFmpegAudioDecoder<V>::GetCodecId(aMimeType);
if (audioCodec == AV_CODEC_ID_NONE && videoCodec == AV_CODEC_ID_NONE) {
return false;
}
AVCodecID codec = audioCodec != AV_CODEC_ID_NONE ? audioCodec : videoCodec;
return !!FFmpegDataDecoder<V>::FindAVCodec(mLib, codec);
}
- ConversionRequired
- DecoderNeedsConversion(const TrackInfo& aConfig) const override
- {
- if (aConfig.IsVideo()
- && (aConfig.mMimeType.EqualsLiteral("video/avc")
- || aConfig.mMimeType.EqualsLiteral("video/mp4"))) {
- return ConversionRequired::kNeedAVCC;
- } else {
- return ConversionRequired::kNeedNone;
- }
- }
-
private:
FFmpegLibWrapper* mLib;
};
} // namespace mozilla
#endif // __FFmpegDecoderModule_h__
--- a/dom/media/platforms/ffmpeg/FFmpegVideoDecoder.h
+++ b/dom/media/platforms/ffmpeg/FFmpegVideoDecoder.h
@@ -36,16 +36,21 @@ public:
const char* GetDescriptionName() const override
{
#ifdef USING_MOZFFVPX
return "ffvpx video decoder";
#else
return "ffmpeg video decoder";
#endif
}
+ ConversionRequired NeedsConversion() const override
+ {
+ return ConversionRequired::kNeedAVCC;
+ }
+
static AVCodecID GetCodecId(const nsACString& aMimeType);
private:
RefPtr<DecodePromise> ProcessDecode(MediaRawData* aSample) override;
RefPtr<DecodePromise> ProcessDrain() override;
RefPtr<FlushPromise> ProcessFlush() override;
MediaResult DoDecode(MediaRawData* aSample, bool* aGotFrame,
DecodedData& aResults);
--- a/dom/media/platforms/omx/OmxDataDecoder.h
+++ b/dom/media/platforms/omx/OmxDataDecoder.h
@@ -69,16 +69,21 @@ public:
RefPtr<FlushPromise> Flush() override;
RefPtr<ShutdownPromise> Shutdown() override;
const char* GetDescriptionName() const override
{
return "omx decoder";
}
+ ConversionRequired NeedsConversion() const override
+ {
+ return ConversionRequired::kNeedAnnexB;
+ }
+
// Return true if event is handled.
bool Event(OMX_EVENTTYPE aEvent, OMX_U32 aData1, OMX_U32 aData2);
protected:
void InitializationTask();
void ResolveInitPromise(const char* aMethodName);
--- a/dom/media/platforms/omx/OmxDecoderModule.cpp
+++ b/dom/media/platforms/omx/OmxDecoderModule.cpp
@@ -22,22 +22,16 @@ OmxDecoderModule::CreateVideoDecoder(con
already_AddRefed<MediaDataDecoder>
OmxDecoderModule::CreateAudioDecoder(const CreateDecoderParams& aParams)
{
RefPtr<OmxDataDecoder> decoder = new OmxDataDecoder(aParams.mConfig,
nullptr);
return decoder.forget();
}
-PlatformDecoderModule::ConversionRequired
-OmxDecoderModule::DecoderNeedsConversion(const TrackInfo& aConfig) const
-{
- return ConversionRequired::kNeedNone;
-}
-
bool
OmxDecoderModule::SupportsMimeType(const nsACString& aMimeType,
DecoderDoctorDiagnostics* aDiagnostics) const
{
return OmxPlatformLayer::SupportsMimeType(aMimeType);
}
}
--- a/dom/media/platforms/omx/OmxDecoderModule.h
+++ b/dom/media/platforms/omx/OmxDecoderModule.h
@@ -16,15 +16,13 @@ public:
already_AddRefed<MediaDataDecoder>
CreateVideoDecoder(const CreateDecoderParams& aParams) override;
already_AddRefed<MediaDataDecoder>
CreateAudioDecoder(const CreateDecoderParams& aParams) override;
bool SupportsMimeType(const nsACString& aMimeType,
DecoderDoctorDiagnostics* aDiagnostics) const override;
-
- ConversionRequired DecoderNeedsConversion(const TrackInfo& aConfig) const override;
};
} // namespace mozilla
#endif // OmxDecoderModule_h_
--- a/dom/media/platforms/wmf/WMFDecoderModule.cpp
+++ b/dom/media/platforms/wmf/WMFDecoderModule.cpp
@@ -241,18 +241,9 @@ WMFDecoderModule::Supports(const TrackIn
return true;
}
}
// Some unsupported codec.
return false;
}
-PlatformDecoderModule::ConversionRequired
-WMFDecoderModule::DecoderNeedsConversion(const TrackInfo& aConfig) const
-{
- if (aConfig.IsVideo() && MP4Decoder::IsH264(aConfig.mMimeType)) {
- return ConversionRequired::kNeedAnnexB;
- }
- return ConversionRequired::kNeedNone;
-}
-
} // namespace mozilla
--- a/dom/media/platforms/wmf/WMFDecoderModule.h
+++ b/dom/media/platforms/wmf/WMFDecoderModule.h
@@ -23,19 +23,16 @@ public:
already_AddRefed<MediaDataDecoder>
CreateAudioDecoder(const CreateDecoderParams& aParams) override;
bool SupportsMimeType(const nsACString& aMimeType,
DecoderDoctorDiagnostics* aDiagnostics) const override;
bool Supports(const TrackInfo& aTrackInfo,
DecoderDoctorDiagnostics* aDiagnostics) const override;
- ConversionRequired
- DecoderNeedsConversion(const TrackInfo& aConfig) const override;
-
// Called on main thread.
static void Init();
// Called from any thread, must call init first
static int GetNumDecoderThreads();
// Accessors that report whether we have the required MFTs available
// on the system to play various codecs. Windows Vista doesn't have the
--- a/dom/media/platforms/wmf/WMFMediaDataDecoder.h
+++ b/dom/media/platforms/wmf/WMFMediaDataDecoder.h
@@ -62,16 +62,21 @@ public:
virtual const char* GetDescriptionName() const = 0;
virtual void SetSeekThreshold(const media::TimeUnit& aTime)
{
mSeekTargetThreshold = Some(aTime);
}
+ virtual MediaDataDecoder::ConversionRequired NeedsConversion() const
+ {
+ return MediaDataDecoder::ConversionRequired::kNeedNone;
+ }
+
protected:
// IMFTransform wrapper that performs the decoding.
RefPtr<MFTDecoder> mDecoder;
Maybe<media::TimeUnit> mSeekTargetThreshold;
};
// Decodes audio and video using Windows Media Foundation. Samples are decoded
@@ -97,16 +102,22 @@ public:
bool IsHardwareAccelerated(nsACString& aFailureReason) const override;
const char* GetDescriptionName() const override
{
return mMFTManager ? mMFTManager->GetDescriptionName() : "";
}
+ ConversionRequired NeedsConversion() const override
+ {
+ MOZ_ASSERT(mMFTManager);
+ return mMFTManager->NeedsConversion();
+ }
+
virtual void SetSeekThreshold(const media::TimeUnit& aTime) override;
private:
// Called on the task queue. Inserts the sample into the decoder, and
// extracts output if available.
RefPtr<DecodePromise> ProcessDecode(MediaRawData* aSample);
--- a/dom/media/platforms/wmf/WMFVideoMFTManager.h
+++ b/dom/media/platforms/wmf/WMFVideoMFTManager.h
@@ -54,16 +54,23 @@ public:
}
void Drain() override
{
MFTManager::Drain();
mDraining = true;
}
+ MediaDataDecoder::ConversionRequired NeedsConversion() const override
+ {
+ return mStreamType == H264
+ ? MediaDataDecoder::ConversionRequired::kNeedAnnexB
+ : MediaDataDecoder::ConversionRequired::kNeedNone;
+ }
+
private:
bool ValidateVideoInfo();
bool InitializeDXVA(bool aForceD3D9);
bool InitInternal(bool aForceD3D9);
HRESULT ConfigureVideoFrameGeometry();
--- a/dom/media/platforms/wrappers/H264Converter.cpp
+++ b/dom/media/platforms/wrappers/H264Converter.cpp
@@ -21,18 +21,16 @@ H264Converter::H264Converter(PlatformDec
: mPDM(aPDM)
, mOriginalConfig(aParams.VideoConfig())
, mCurrentConfig(aParams.VideoConfig())
, mKnowsCompositor(aParams.mKnowsCompositor)
, mImageContainer(aParams.mImageContainer)
, mTaskQueue(aParams.mTaskQueue)
, mDecoder(nullptr)
, mGMPCrashHelper(aParams.mCrashHelper)
- , mNeedAVCC(aPDM->DecoderNeedsConversion(aParams.mConfig)
- == PlatformDecoderModule::ConversionRequired::kNeedAVCC)
, mLastError(NS_OK)
, mType(aParams.mType)
, mOnWaitingForKeyEvent(aParams.mOnWaitingForKeyEvent)
{
CreateDecoder(aParams.mDiagnostics);
}
H264Converter::~H264Converter()
@@ -93,17 +91,22 @@ H264Converter::Decode(MediaRawData* aSam
RESULT_DETAIL("Unable to create H264 decoder")),
__func__);
}
if (mNeedKeyframe && !aSample->mKeyframe) {
return DecodePromise::CreateAndResolve(DecodedData(), __func__);
}
- if (!mNeedAVCC
+ if (!mNeedAVCC) {
+ mNeedAVCC =
+ Some(mDecoder->NeedsConversion() == ConversionRequired::kNeedAVCC);
+ }
+
+ if (!*mNeedAVCC
&& !mp4_demuxer::AnnexB::ConvertSampleToAnnexB(aSample, mNeedKeyframe)) {
return DecodePromise::CreateAndReject(
MediaResult(NS_ERROR_OUT_OF_MEMORY,
RESULT_DETAIL("ConvertSampleToAnnexB")),
__func__);
}
mNeedKeyframe = false;
@@ -268,17 +271,21 @@ H264Converter::OnDecoderInitFailed(const
void
H264Converter::DecodeFirstSample(MediaRawData* aSample)
{
if (mNeedKeyframe && !aSample->mKeyframe) {
mDecodePromise.Resolve(DecodedData(), __func__);
return;
}
mNeedKeyframe = false;
- if (!mNeedAVCC
+
+ mNeedAVCC =
+ Some(mDecoder->NeedsConversion() == ConversionRequired::kNeedAVCC);
+
+ if (!*mNeedAVCC
&& !mp4_demuxer::AnnexB::ConvertSampleToAnnexB(aSample, mNeedKeyframe)) {
mDecodePromise.Reject(
MediaResult(NS_ERROR_OUT_OF_MEMORY,
RESULT_DETAIL("ConvertSampleToAnnexB")),
__func__);
return;
}
if (CanRecycleDecoder()) {
@@ -350,16 +357,17 @@ H264Converter::CheckForSPSChange(MediaRa
mFlushRequest.Complete();
mShutdownPromise = Shutdown();
mShutdownPromise
->Then(AbstractThread::GetCurrent()->AsTaskQueue(),
__func__,
[self, this]() {
mShutdownRequest.Complete();
mShutdownPromise = nullptr;
+ mNeedAVCC.reset();
RefPtr<MediaRawData> sample = mPendingSample.forget();
nsresult rv = CreateDecoderAndInit(sample);
if (rv == NS_ERROR_DOM_MEDIA_INITIALIZING_DECODER) {
// All good so far, will continue later.
return;
}
MOZ_ASSERT(NS_FAILED(rv));
mDecodePromise.Reject(rv, __func__);
--- a/dom/media/platforms/wrappers/H264Converter.h
+++ b/dom/media/platforms/wrappers/H264Converter.h
@@ -3,16 +3,17 @@
/* 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 mozilla_H264Converter_h
#define mozilla_H264Converter_h
#include "PlatformDecoderModule.h"
+#include "mozilla/Maybe.h"
namespace mozilla {
// H264Converter is a MediaDataDecoder wrapper used to ensure that
// only AVCC or AnnexB is fed to the underlying MediaDataDecoder.
// The H264Converter allows playback of content where the SPS NAL may not be
// provided in the init segment (e.g. AVC3 or Annex B)
// H264Converter will monitor the input data, and will delay creation of the
@@ -48,16 +49,24 @@ public:
return false;
}
void ConfigurationChanged(const TrackInfo& aConfig) override
{
if (mDecoder && mDecoder->SupportDecoderRecycling()) {
mDecoder->ConfigurationChanged(aConfig);
}
}
+ ConversionRequired NeedsConversion() const override
+ {
+ if (mDecoder) {
+ return mDecoder->NeedsConversion();
+ }
+ // Default so no conversion is performed.
+ return ConversionRequired::kNeedAVCC;
+ }
nsresult GetLastError() const { return mLastError; }
private:
// Will create the required MediaDataDecoder if need AVCC and we have a SPS NAL.
// Returns NS_ERROR_FAILURE if error is permanent and can't be recovered and
// will set mError accordingly.
nsresult CreateDecoder(DecoderDoctorDiagnostics* aDiagnostics);
nsresult CreateDecoderAndInit(MediaRawData* aSample);
@@ -87,17 +96,17 @@ private:
MozPromiseRequestHolder<InitPromise> mInitPromiseRequest;
MozPromiseRequestHolder<DecodePromise> mDecodePromiseRequest;
MozPromiseHolder<DecodePromise> mDecodePromise;
MozPromiseRequestHolder<FlushPromise> mFlushRequest;
MozPromiseRequestHolder<ShutdownPromise> mShutdownRequest;
RefPtr<ShutdownPromise> mShutdownPromise;
RefPtr<GMPCrashHelper> mGMPCrashHelper;
- bool mNeedAVCC;
+ Maybe<bool> mNeedAVCC;
nsresult mLastError;
bool mNeedKeyframe = true;
// Set to true once a decoder has been created.
bool mUseOriginalConfig = true;
const TrackInfo::TrackType mType;
MediaEventProducer<TrackInfo::TrackType>* const mOnWaitingForKeyEvent;
};
--- a/dom/media/platforms/wrappers/MediaDataDecoderProxy.cpp
+++ b/dom/media/platforms/wrappers/MediaDataDecoderProxy.cpp
@@ -129,9 +129,17 @@ MediaDataDecoderProxy::ConfigurationChan
RefPtr<MediaDataDecoderProxy> self = this;
RefPtr<TrackInfoSharedPtr> config = new TrackInfoSharedPtr(aConfig, 0);
mProxyThread->Dispatch(NS_NewRunnableFunction([self, config] {
const TrackInfo* trackInfo = *config;
self->mProxyDecoder->ConfigurationChanged(*trackInfo);
}));
}
+MediaDataDecoder::ConversionRequired
+MediaDataDecoderProxy::NeedsConversion() const
+{
+ MOZ_ASSERT(!mIsShutdown);
+
+ return mProxyDecoder->NeedsConversion();
+}
+
} // namespace mozilla
--- a/dom/media/platforms/wrappers/MediaDataDecoderProxy.h
+++ b/dom/media/platforms/wrappers/MediaDataDecoderProxy.h
@@ -46,16 +46,17 @@ public:
RefPtr<DecodePromise> Drain() override;
RefPtr<FlushPromise> Flush() override;
RefPtr<ShutdownPromise> Shutdown() override;
const char* GetDescriptionName() const override;
bool IsHardwareAccelerated(nsACString& aFailureReason) const override;
void SetSeekThreshold(const media::TimeUnit& aTime) override;
bool SupportDecoderRecycling() const override;
void ConfigurationChanged(const TrackInfo& aConfig) override;
+ ConversionRequired NeedsConversion() const override;
private:
RefPtr<MediaDataDecoder> mProxyDecoder;
RefPtr<AbstractThread> mProxyThread;
#if defined(DEBUG)
Atomic<bool> mIsShutdown;
#endif