Backed out 13 changesets (bug 1672072) for short.mp4.firstframe.html failures CLOSED TREE

Backed out changeset f093b7969e8b (bug 1672072)
Backed out changeset 28db8276ec2b (bug 1672072)
Backed out changeset ff8fe1b856b3 (bug 1672072)
Backed out changeset 091b9449c786 (bug 1672072)
Backed out changeset 89d9a12c0737 (bug 1672072)
Backed out changeset 9cb71fd4b43b (bug 1672072)
Backed out changeset 09adad7416e1 (bug 1672072)
Backed out changeset 9905650335ef (bug 1672072)
Backed out changeset 6f1d99e9c3a1 (bug 1672072)
Backed out changeset b59655b7a595 (bug 1672072)
Backed out changeset 1ef9d6d10508 (bug 1672072)
Backed out changeset fbf0b5117655 (bug 1672072)
Backed out changeset 65cd3b9de5c6 (bug 1672072)
This commit is contained in:
Bogdan Tara 2020-11-13 06:13:22 +02:00
Родитель ca56bb2db5
Коммит 266d9ad46c
67 изменённых файлов: 863 добавлений и 1099 удалений

Просмотреть файл

@ -247,20 +247,19 @@ void BenchmarkPlayback::InitDecoder(UniquePtr<TrackInfo>&& aInfo) {
RefPtr<PDMFactory> platform = new PDMFactory();
mInfo = std::move(aInfo);
RefPtr<MediaDataDecoder> decoder =
platform->CreateDecoder(CreateDecoderParams{*mInfo});
if (!decoder) {
Error(MediaResult(NS_ERROR_FAILURE, "Failed to create decoder"));
return;
}
mDecoder = new MediaDataDecoderProxy(decoder.forget(),
do_AddRef(mDecoderTaskQueue.get()));
RefPtr<Benchmark> ref(mGlobalState);
platform->CreateDecoder(CreateDecoderParams{*mInfo})
->Then(
Thread(), __func__,
[this, ref](RefPtr<MediaDataDecoder>&& aDecoder) {
mDecoder = new MediaDataDecoderProxy(
aDecoder.forget(), do_AddRef(mDecoderTaskQueue.get()));
mDecoder->Init()->Then(
Thread(), __func__,
[this, ref](TrackInfo::TrackType aTrackType) {
InputExhausted();
},
[this, ref](const MediaResult& aError) { Error(aError); });
},
[this, ref](TrackInfo::TrackType aTrackType) { InputExhausted(); },
[this, ref](const MediaResult& aError) { Error(aError); });
}

Просмотреть файл

@ -209,7 +209,6 @@ class MediaFormatReader::DecoderFactory {
using InitPromise = MediaDataDecoder::InitPromise;
using TokenPromise = AllocPolicy::Promise;
using Token = AllocPolicy::Token;
using CreateDecoderPromise = PlatformDecoderModule::CreateDecoderPromise;
public:
explicit DecoderFactory(MediaFormatReader* aOwner)
@ -237,23 +236,6 @@ class MediaFormatReader::DecoderFactory {
auto& data = aTrack == TrackInfo::kAudioTrack ? mAudio : mVideo;
data.mPolicy->Cancel();
data.mTokenRequest.DisconnectIfExists();
if (data.mLiveToken) {
// We haven't completed creation of the decoder, and it hasn't been
// initialised yet.
data.mLiveToken = nullptr;
// The decoder will be shutdown as soon as it's available and tracked by
// the ShutdownPromisePool.
mOwner->mShutdownPromisePool->Track(data.mCreateDecoderPromise->Then(
mOwner->mTaskQueue, __func__,
[](CreateDecoderPromise::ResolveOrRejectValue&& aResult) {
if (aResult.IsReject()) {
return ShutdownPromise::CreateAndResolve(true, __func__);
}
return aResult.ResolveValue()->Shutdown();
}));
// Free the token to leave room for a new decoder.
data.mToken = nullptr;
}
data.mInitRequest.DisconnectIfExists();
if (data.mDecoder) {
mOwner->mShutdownPromisePool->ShutdownDecoder(data.mDecoder.forget());
@ -277,21 +259,11 @@ class MediaFormatReader::DecoderFactory {
RefPtr<Token> mToken;
RefPtr<MediaDataDecoder> mDecoder;
MozPromiseRequestHolder<TokenPromise> mTokenRequest;
struct DecoderCancelled : public SupportsWeakPtr {
NS_INLINE_DECL_REFCOUNTING_ONEVENTTARGET(DecoderCancelled)
private:
~DecoderCancelled() = default;
};
// Set when decoder is about to be created. If cleared before the decoder
// creation promise is resolved; it indicates that Shutdown() was called and
// further processing such as initialization should stop.
RefPtr<DecoderCancelled> mLiveToken;
RefPtr<CreateDecoderPromise> mCreateDecoderPromise;
MozPromiseRequestHolder<InitPromise> mInitRequest;
} mAudio, mVideo;
void RunStage(Data& aData);
void DoCreateDecoder(Data& aData);
MediaResult DoCreateDecoder(Data& aData);
void DoInitDecoder(Data& aData);
// guaranteed to be valid by the owner.
@ -337,20 +309,38 @@ void MediaFormatReader::DecoderFactory::RunStage(Data& aData) {
MOZ_ASSERT(!aData.mDecoder);
MOZ_ASSERT(!aData.mInitRequest.Exists());
DoCreateDecoder(aData);
MediaResult rv = DoCreateDecoder(aData);
if (NS_FAILED(rv)) {
NS_WARNING("Error constructing decoders");
aData.mToken = nullptr;
aData.mStage = Stage::None;
aData.mOwnerData.mDescription = rv.Description();
DDLOGEX2("MediaFormatReader::DecoderFactory", this, DDLogCategory::Log,
"create_decoder_error", rv);
mOwner->NotifyError(aData.mTrack, rv);
return;
}
aData.mDecoder =
new AllocationWrapper(aData.mDecoder.forget(), aData.mToken.forget());
DecoderDoctorLogger::LinkParentAndChild(
aData.mDecoder.get(), "decoder", "MediaFormatReader::DecoderFactory",
this);
DoInitDecoder(aData);
aData.mStage = Stage::WaitForInit;
break;
}
case Stage::WaitForInit: {
MOZ_ASSERT((aData.mDecoder && aData.mInitRequest.Exists()) ||
aData.mLiveToken);
MOZ_ASSERT(aData.mDecoder);
MOZ_ASSERT(aData.mInitRequest.Exists());
break;
}
}
}
void MediaFormatReader::DecoderFactory::DoCreateDecoder(Data& aData) {
MediaResult MediaFormatReader::DecoderFactory::DoCreateDecoder(Data& aData) {
AUTO_PROFILER_LABEL("DecoderFactory::DoCreateDecoder", MEDIA_PLAYBACK);
auto& ownerData = aData.mOwnerData;
auto& decoder = mOwner->GetDecoderData(aData.mTrack);
@ -365,21 +355,26 @@ void MediaFormatReader::DecoderFactory::DoCreateDecoder(Data& aData) {
}
}
RefPtr<PlatformDecoderModule::CreateDecoderPromise> p;
MediaFormatReader* owner = mOwner;
auto onWaitingForKeyEvent =
[owner = ThreadSafeWeakPtr<MediaFormatReader>(owner)]() {
RefPtr<MediaFormatReader> mfr(owner);
MOZ_DIAGNOSTIC_ASSERT(mfr, "The MediaFormatReader didn't wait for us");
return mfr ? &mfr->OnTrackWaitingForKeyProducer() : nullptr;
};
// result may not be updated by PDMFactory::CreateDecoder, as such it must be
// initialized to a fatal error by default.
MediaResult result =
MediaResult(NS_ERROR_DOM_MEDIA_FATAL_ERR,
nsPrintfCString("error creating %s decoder",
TrackTypeToStr(aData.mTrack)));
switch (aData.mTrack) {
case TrackInfo::kAudioTrack: {
p = platform->CreateDecoder(
RefPtr<MediaDataDecoder> decoder = platform->CreateDecoder(
{*ownerData.GetCurrentInfo()->GetAsAudioInfo(), mOwner->mCrashHelper,
CreateDecoderParams::UseNullDecoder(ownerData.mIsNullDecode),
TrackInfo::kAudioTrack, std::move(onWaitingForKeyEvent)});
&result, TrackInfo::kAudioTrack,
&mOwner->OnTrackWaitingForKeyProducer()});
if (!decoder) {
aData.mDecoder = nullptr;
break;
}
aData.mDecoder = new MediaDataDecoderProxy(
decoder.forget(), do_AddRef(ownerData.mTaskQueue.get()));
break;
}
@ -389,64 +384,37 @@ void MediaFormatReader::DecoderFactory::DoCreateDecoder(Data& aData) {
using Option = CreateDecoderParams::Option;
using OptionSet = CreateDecoderParams::OptionSet;
p = platform->CreateDecoder(
RefPtr<MediaDataDecoder> decoder = platform->CreateDecoder(
{*ownerData.GetCurrentInfo()->GetAsVideoInfo(),
mOwner->mKnowsCompositor, mOwner->GetImageContainer(),
mOwner->mCrashHelper,
CreateDecoderParams::UseNullDecoder(ownerData.mIsNullDecode),
TrackType::kVideoTrack, std::move(onWaitingForKeyEvent),
&result, TrackType::kVideoTrack,
&mOwner->OnTrackWaitingForKeyProducer(),
CreateDecoderParams::VideoFrameRate(ownerData.mMeanRate.Mean()),
OptionSet(ownerData.mHardwareDecodingDisabled
? Option::HardwareDecoderNotAllowed
: Option::Default)});
if (!decoder) {
aData.mDecoder = nullptr;
break;
}
aData.mDecoder = new MediaDataDecoderProxy(
decoder.forget(), do_AddRef(ownerData.mTaskQueue.get()));
break;
}
default:
p = PlatformDecoderModule::CreateDecoderPromise::CreateAndReject(
NS_ERROR_DOM_MEDIA_FATAL_ERR, __func__);
break;
}
aData.mLiveToken = MakeRefPtr<Data::DecoderCancelled>();
aData.mCreateDecoderPromise = p->Then(
mOwner->OwnerThread(), __func__,
[this, &aData, &ownerData, live = WeakPtr{aData.mLiveToken},
owner = ThreadSafeWeakPtr<MediaFormatReader>(owner)](
RefPtr<MediaDataDecoder>&& aDecoder) {
if (!live) {
return CreateDecoderPromise::CreateAndResolve(std::move(aDecoder),
__func__);
if (aData.mDecoder) {
return NS_OK;
}
aData.mLiveToken = nullptr;
aData.mDecoder = new MediaDataDecoderProxy(
aDecoder.forget(), do_AddRef(ownerData.mTaskQueue.get()));
aData.mDecoder = new AllocationWrapper(aData.mDecoder.forget(),
aData.mToken.forget());
DecoderDoctorLogger::LinkParentAndChild(
aData.mDecoder.get(), "decoder",
"MediaFormatReader::DecoderFactory", this);
DoInitDecoder(aData);
MOZ_RELEASE_ASSERT(NS_FAILED(result), "PDM returned an invalid error code");
return CreateDecoderPromise::CreateAndResolve(aData.mDecoder, __func__);
},
[this, &aData,
live = WeakPtr{aData.mLiveToken}](const MediaResult& aError) {
NS_WARNING("Error constructing decoders");
if (!live) {
return CreateDecoderPromise::CreateAndReject(aError, __func__);
}
aData.mLiveToken = nullptr;
aData.mToken = nullptr;
aData.mStage = Stage::None;
aData.mOwnerData.mDescription = aError.Description();
DDLOGEX2("MediaFormatReader::DecoderFactory", this, DDLogCategory::Log,
"create_decoder_error", aError);
mOwner->NotifyError(aData.mTrack, aError);
return CreateDecoderPromise::CreateAndReject(aError, __func__);
});
return result;
}
void MediaFormatReader::DecoderFactory::DoInitDecoder(Data& aData) {

Просмотреть файл

@ -7,22 +7,22 @@
#if !defined(MediaFormatReader_h_)
# define MediaFormatReader_h_
# include "FrameStatistics.h"
# include "MediaDataDemuxer.h"
# include "MediaEventSource.h"
# include "MediaMetadataManager.h"
# include "MediaPromiseDefs.h"
# include "PDMFactory.h"
# include "SeekTarget.h"
# include "mozilla/Atomics.h"
# include "mozilla/Maybe.h"
# include "mozilla/Mutex.h"
# include "mozilla/StateMirroring.h"
# include "mozilla/StaticPrefs_media.h"
# include "mozilla/TaskQueue.h"
# include "mozilla/ThreadSafeWeakPtr.h"
# include "mozilla/dom/MediaDebugInfoBinding.h"
# include "FrameStatistics.h"
# include "MediaEventSource.h"
# include "MediaDataDemuxer.h"
# include "MediaMetadataManager.h"
# include "MediaPromiseDefs.h"
# include "PDMFactory.h"
# include "SeekTarget.h"
namespace mozilla {
class CDMProxy;
@ -70,16 +70,13 @@ struct MOZ_STACK_CLASS MediaFormatReaderInit {
DDLoggedTypeDeclName(MediaFormatReader);
class MediaFormatReader final
: public SupportsThreadSafeWeakPtr<MediaFormatReader>,
public DecoderDoctorLifeLogger<MediaFormatReader> {
: public DecoderDoctorLifeLogger<MediaFormatReader> {
static const bool IsExclusive = true;
typedef TrackInfo::TrackType TrackType;
typedef MozPromise<bool, MediaResult, IsExclusive> NotifyDataArrivedPromise;
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(MediaFormatReader)
public:
MOZ_DECLARE_THREADSAFEWEAKREFERENCE_TYPENAME(MediaFormatReader)
MOZ_DECLARE_REFCOUNTED_TYPENAME(MediaFormatReader)
using TrackSet = EnumSet<TrackInfo::TrackType>;
using MetadataPromise = MozPromise<MetadataHolder, MediaResult, IsExclusive>;
@ -98,7 +95,6 @@ class MediaFormatReader final
MozPromise<MediaData::Type, WaitForDataRejectValue, IsExclusive>;
MediaFormatReader(MediaFormatReaderInit& aInit, MediaDataDemuxer* aDemuxer);
virtual ~MediaFormatReader();
// Initializes the reader, returns NS_OK on success, or NS_ERROR_FAILURE
// on failure.
@ -240,6 +236,8 @@ class MediaFormatReader final
}
private:
~MediaFormatReader();
bool HasVideo() const { return mVideo.mTrackDemuxer; }
bool HasAudio() const { return mAudio.mTrackDemuxer; }

Просмотреть файл

@ -0,0 +1,45 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* 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"
#include "mozilla/TaskQueue.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(
const nsTArray<RefPtr<MediaRawData>>& aSamples) = 0;
virtual RefPtr<MediaDataDecoder::DecodePromise> Drain() = 0;
virtual RefPtr<MediaDataDecoder::FlushPromise> Flush() = 0;
virtual RefPtr<ShutdownPromise> 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() = default;
};
} // namespace mozilla
#endif // include_dom_media_ipc_IRemoteDecoderChild_h

Просмотреть файл

@ -56,8 +56,6 @@ async protocol PRemoteDecoder
{
manager PRemoteDecoderManager;
parent:
async Construct() returns (MediaResult result);
async Init() returns (InitResultIPDL result);
// Each output may include a SurfaceDescriptorGPUVideo that represents the decoded

Просмотреть файл

@ -33,9 +33,11 @@ sync protocol PRemoteDecoderManager
manages PRemoteDecoder;
parent:
async PRemoteDecoder(RemoteDecoderInfoIPDL info,
sync PRemoteDecoder(RemoteDecoderInfoIPDL info,
OptionSet options,
TextureFactoryIdentifier? identifier);
TextureFactoryIdentifier? identifier)
returns (bool success,
nsCString aErrorDescription);
sync Readback(SurfaceDescriptorGPUVideo sd) returns (SurfaceDescriptor aResult);

Просмотреть файл

@ -99,23 +99,18 @@ void RDDProcessManager::OnPreferenceChange(const char16_t* aData) {
}
}
auto RDDProcessManager::EnsureRDDProcessAndCreateBridge(
base::ProcessId aOtherProcess) -> RefPtr<EnsureRDDPromise> {
return InvokeAsync(GetMainThreadSerialEventTarget(), __func__,
[aOtherProcess, this]() -> RefPtr<EnsureRDDPromise> {
if (!Get()) {
// Shutdown?
return EnsureRDDPromise::CreateAndReject(
NS_ERROR_NOT_AVAILABLE, __func__);
}
bool RDDProcessManager::EnsureRDDProcessAndCreateBridge(
base::ProcessId aOtherProcess,
mozilla::ipc::Endpoint<PRemoteDecoderManagerChild>*
aOutRemoteDecoderManager) {
bool success = false;
RefPtr<Runnable> task =
NS_NewRunnableFunction("RDDProcessManager::RDDProcessManager", [&]() {
if (mProcess) {
ipc::Endpoint<PRemoteDecoderManagerChild> endpoint;
if (!CreateContentBridge(aOtherProcess, &endpoint)) {
return EnsureRDDPromise::CreateAndReject(
NS_ERROR_NOT_AVAILABLE, __func__);
}
return EnsureRDDPromise::CreateAndResolve(
std::move(endpoint), __func__);
success =
CreateContentBridge(aOtherProcess, aOutRemoteDecoderManager);
return;
}
mNumProcessAttempts++;
@ -125,23 +120,23 @@ auto RDDProcessManager::EnsureRDDProcessAndCreateBridge(
extraArgs.push_back("-parentBuildID");
extraArgs.push_back(parentBuildID.get());
// The subprocess is launched asynchronously, so we wait
// for a callback to acquire the IPDL actor.
// The subprocess is launched asynchronously, so we wait for a callback
// to acquire the IPDL actor.
mProcess = new RDDProcessHost(this);
if (!mProcess->Launch(extraArgs)) {
DestroyProcess();
return EnsureRDDPromise::CreateAndReject(
NS_ERROR_NOT_AVAILABLE, __func__);
return;
}
ipc::Endpoint<PRemoteDecoderManagerChild> endpoint;
if (!EnsureRDDReady() || !CreateVideoBridge() ||
!CreateContentBridge(aOtherProcess, &endpoint)) {
return EnsureRDDPromise::CreateAndReject(
NS_ERROR_NOT_AVAILABLE, __func__);
if (!EnsureRDDReady()) {
return;
}
return EnsureRDDPromise::CreateAndResolve(
std::move(endpoint), __func__);
success = CreateVideoBridge() &&
CreateContentBridge(aOtherProcess, aOutRemoteDecoderManager);
});
SyncRunnable::DispatchToThread(GetMainThreadSerialEventTarget(), task);
return success;
}
bool RDDProcessManager::IsRDDProcessLaunching() {
@ -242,8 +237,9 @@ void RDDProcessManager::DestroyProcess() {
bool RDDProcessManager::CreateContentBridge(
base::ProcessId aOtherProcess,
ipc::Endpoint<PRemoteDecoderManagerChild>* aOutRemoteDecoderManager) {
MOZ_ASSERT(NS_IsMainThread());
bool success = false;
RefPtr<Runnable> task =
NS_NewRunnableFunction("RDDProcessManager::RDDProcessManager", [&]() {
ipc::Endpoint<PRemoteDecoderManagerParent> parentPipe;
ipc::Endpoint<PRemoteDecoderManagerChild> childPipe;
@ -252,13 +248,16 @@ bool RDDProcessManager::CreateContentBridge(
if (NS_FAILED(rv)) {
MOZ_LOG(sPDMLog, LogLevel::Debug,
("Could not create content remote decoder: %d", int(rv)));
return false;
return;
}
mRDDChild->SendNewContentRemoteDecoderManager(std::move(parentPipe));
*aOutRemoteDecoderManager = std::move(childPipe);
return true;
success = true;
});
SyncRunnable::DispatchToThread(GetMainThreadSerialEventTarget(), task);
return success;
}
bool RDDProcessManager::CreateVideoBridge() {

Просмотреть файл

@ -5,14 +5,13 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef _include_dom_media_ipc_RDDProcessManager_h_
#define _include_dom_media_ipc_RDDProcessManager_h_
#include "mozilla/MozPromise.h"
#include "mozilla/PRemoteDecoderManagerChild.h"
#include "mozilla/RDDProcessHost.h"
#include "mozilla/ipc/TaskFactory.h"
namespace mozilla {
class MemoryReportingProcess;
class PRemoteDecoderManagerChild;
class RDDChild;
// The RDDProcessManager is a singleton responsible for creating RDD-bound
@ -28,12 +27,18 @@ class RDDProcessManager final : public RDDProcessHost::Listener {
~RDDProcessManager();
using EnsureRDDPromise =
MozPromise<ipc::Endpoint<PRemoteDecoderManagerChild>, nsresult, true>;
// If not using a RDD process, launch a new RDD process asynchronously and
// create a RemoteDecoderManager bridge
RefPtr<EnsureRDDPromise> EnsureRDDProcessAndCreateBridge(
base::ProcessId aOtherProcess);
bool EnsureRDDProcessAndCreateBridge(
base::ProcessId aOtherProcess,
mozilla::ipc::Endpoint<PRemoteDecoderManagerChild>*
aOutRemoteDecoderManager);
bool IsRDDProcessLaunching();
// Ensure that RDD-bound methods can be used. If no RDD process is being
// used, or one is launched and ready, this function returns immediately.
// Otherwise it blocks until the RDD process has finished launching.
bool EnsureRDDReady();
void OnProcessLaunchComplete(RDDProcessHost* aHost) override;
void OnProcessUnexpectedShutdown(RDDProcessHost* aHost) override;
@ -62,11 +67,6 @@ class RDDProcessManager final : public RDDProcessHost::Listener {
RDDProcessHost* Process() { return mProcess; }
private:
bool IsRDDProcessLaunching();
// Ensure that RDD-bound methods can be used. If no RDD process is being
// used, or one is launched and ready, this function returns immediately.
// Otherwise it blocks until the RDD process has finished launching.
bool EnsureRDDReady();
bool CreateVideoBridge();
// Called from our xpcom-shutdown observer.
@ -94,12 +94,13 @@ class RDDProcessManager final : public RDDProcessHost::Listener {
};
friend class Observer;
bool CreateContentBridge(
base::ProcessId aOtherProcess,
ipc::Endpoint<PRemoteDecoderManagerChild>* aOutRemoteDecoderManager);
private:
bool CreateContentBridge(base::ProcessId aOtherProcess,
mozilla::ipc::Endpoint<PRemoteDecoderManagerChild>*
aOutRemoteDecoderManager);
const RefPtr<Observer> mObserver;
ipc::TaskFactory<RDDProcessManager> mTaskFactory;
mozilla::ipc::TaskFactory<RDDProcessManager> mTaskFactory;
uint32_t mNumProcessAttempts = 0;
// Fields that are associated with the current RDD process.
@ -109,7 +110,7 @@ class RDDProcessManager final : public RDDProcessHost::Listener {
// Collects any pref changes that occur during process launch (after
// the initial map is passed in command-line arguments) to be sent
// when the process can receive IPC messages.
nsTArray<dom::Pref> mQueuedPrefs;
nsTArray<mozilla::dom::Pref> mQueuedPrefs;
};
} // namespace mozilla

Просмотреть файл

@ -54,40 +54,39 @@ MediaResult RemoteAudioDecoderChild::InitIPDL(
}
mIPDLSelfRef = this;
Unused << manager->SendPRemoteDecoderConstructor(this, aAudioInfo, aOptions,
Nothing());
return NS_OK;
bool success = false;
nsCString errorDescription;
Unused << manager->SendPRemoteDecoderConstructor(
this, aAudioInfo, aOptions, Nothing(), &success, &errorDescription);
return success ? MediaResult(NS_OK)
: MediaResult(NS_ERROR_DOM_MEDIA_FATAL_ERR, errorDescription);
}
RemoteAudioDecoderParent::RemoteAudioDecoderParent(
RemoteDecoderManagerParent* aParent, const AudioInfo& aAudioInfo,
const CreateDecoderParams::OptionSet& aOptions,
nsISerialEventTarget* aManagerThread, TaskQueue* aDecodeTaskQueue)
: RemoteDecoderParent(aParent, aOptions, aManagerThread, aDecodeTaskQueue),
mAudioInfo(aAudioInfo) {}
nsISerialEventTarget* aManagerThread, TaskQueue* aDecodeTaskQueue,
bool* aSuccess, nsCString* aErrorDescription)
: RemoteDecoderParent(aParent, aManagerThread, aDecodeTaskQueue),
mAudioInfo(aAudioInfo) {
MediaResult error(NS_OK);
auto params = CreateDecoderParams{
mAudioInfo, aOptions, CreateDecoderParams::NoWrapper(true), &error};
IPCResult RemoteAudioDecoderParent::RecvConstruct(
ConstructResolver&& aResolver) {
auto params = CreateDecoderParams{mAudioInfo, mOptions,
CreateDecoderParams::NoWrapper(true)};
auto& factory = aParent->EnsurePDMFactory();
RefPtr<MediaDataDecoder> decoder = factory.CreateDecoder(params);
mParent->EnsurePDMFactory().CreateDecoder(params)->Then(
GetCurrentSerialEventTarget(), __func__,
[resolver = std::move(aResolver), self = RefPtr{this}](
PlatformDecoderModule::CreateDecoderPromise::ResolveOrRejectValue&&
aValue) {
if (aValue.IsReject()) {
resolver(aValue.RejectValue());
return;
if (NS_FAILED(error)) {
MOZ_ASSERT(aErrorDescription);
*aErrorDescription = error.Description();
}
MOZ_ASSERT(aValue.ResolveValue());
self->mDecoder =
new MediaDataDecoderProxy(aValue.ResolveValue().forget(),
do_AddRef(self->mDecodeTaskQueue.get()));
resolver(NS_OK);
});
return IPC_OK();
if (decoder) {
mDecoder = new MediaDataDecoderProxy(decoder.forget(),
do_AddRef(mDecodeTaskQueue.get()));
}
*aSuccess = !!mDecoder;
}
MediaResult RemoteAudioDecoderParent::ProcessDecodedData(

Просмотреть файл

@ -29,10 +29,10 @@ class RemoteAudioDecoderParent final : public RemoteDecoderParent {
const AudioInfo& aAudioInfo,
const CreateDecoderParams::OptionSet& aOptions,
nsISerialEventTarget* aManagerThread,
TaskQueue* aDecodeTaskQueue);
TaskQueue* aDecodeTaskQueue, bool* aSuccess,
nsCString* aErrorDescription);
protected:
IPCResult RecvConstruct(ConstructResolver&& aResolver) override;
MediaResult ProcessDecodedData(MediaDataDecoder::DecodedData&& aData,
DecodedOutputIPDL& aDecodedData) override;
@ -43,7 +43,6 @@ class RemoteAudioDecoderParent final : public RemoteDecoderParent {
// passed a deserialized AudioInfo from RecvPRemoteDecoderConstructor
// which is destroyed when RecvPRemoteDecoderConstructor returns.
const AudioInfo mAudioInfo;
const CreateDecoderParams::OptionSet mOptions;
};
} // namespace mozilla

Просмотреть файл

@ -19,8 +19,6 @@ RemoteDecoderChild::RemoteDecoderChild(bool aRecreatedOnCrash)
"Must be created on the manager thread");
}
RemoteDecoderChild::~RemoteDecoderChild() = default;
void RemoteDecoderChild::HandleRejectionError(
const ipc::ResponseRejectReason& aReason,
std::function<void(const MediaResult&)>&& aCallback) {

Просмотреть файл

@ -8,6 +8,7 @@
#include <functional>
#include "IRemoteDecoderChild.h"
#include "mozilla/PRemoteDecoderChild.h"
#include "mozilla/ShmemRecycleAllocator.h"
@ -18,29 +19,27 @@ using mozilla::MediaDataDecoder;
using mozilla::ipc::IPCResult;
class RemoteDecoderChild : public ShmemRecycleAllocator<RemoteDecoderChild>,
public PRemoteDecoderChild {
public PRemoteDecoderChild,
public IRemoteDecoderChild {
friend class PRemoteDecoderChild;
public:
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(RemoteDecoderChild);
explicit RemoteDecoderChild(bool aRecreatedOnCrash = false);
void ActorDestroy(ActorDestroyReason aWhy) override;
// This interface closely mirrors the MediaDataDecoder plus a bit
// (DestroyIPDL) to allow proxying to a remote decoder in RemoteDecoderModule.
RefPtr<MediaDataDecoder::InitPromise> Init();
// IRemoteDecoderChild
RefPtr<MediaDataDecoder::InitPromise> Init() override;
RefPtr<MediaDataDecoder::DecodePromise> Decode(
const nsTArray<RefPtr<MediaRawData>>& aSamples);
RefPtr<MediaDataDecoder::DecodePromise> Drain();
RefPtr<MediaDataDecoder::FlushPromise> Flush();
RefPtr<mozilla::ShutdownPromise> Shutdown();
bool IsHardwareAccelerated(nsACString& aFailureReason) const;
nsCString GetDescriptionName() const;
void SetSeekThreshold(const media::TimeUnit& aTime);
MediaDataDecoder::ConversionRequired NeedsConversion() const;
void DestroyIPDL();
const nsTArray<RefPtr<MediaRawData>>& aSamples) override;
RefPtr<MediaDataDecoder::DecodePromise> Drain() override;
RefPtr<MediaDataDecoder::FlushPromise> Flush() override;
RefPtr<mozilla::ShutdownPromise> Shutdown() override;
bool IsHardwareAccelerated(nsACString& aFailureReason) const override;
nsCString GetDescriptionName() const override;
void SetSeekThreshold(const media::TimeUnit& aTime) override;
MediaDataDecoder::ConversionRequired NeedsConversion() const override;
void DestroyIPDL() override;
// Called from IPDL when our actor has been destroyed
void IPDLActorDestroyed();
@ -48,7 +47,7 @@ class RemoteDecoderChild : public ShmemRecycleAllocator<RemoteDecoderChild>,
RemoteDecoderManagerChild* GetManager();
protected:
virtual ~RemoteDecoderChild();
virtual ~RemoteDecoderChild() = default;
void AssertOnManagerThread() const;
virtual MediaResult ProcessOutput(DecodedOutputIPDL&& aDecodedData) = 0;

Просмотреть файл

@ -6,6 +6,7 @@
#include "RemoteDecoderManagerChild.h"
#include "RemoteAudioDecoder.h"
#include "RemoteDecoderChild.h"
#include "RemoteMediaDataDecoder.h"
#include "RemoteVideoDecoder.h"
#include "VideoUtils.h"
@ -26,9 +27,8 @@ using namespace layers;
using namespace gfx;
// Used so that we only ever attempt to check if the RDD process should be
// launched serially. Protects sLaunchPromise
// launched serially.
StaticMutex sLaunchMutex;
static StaticRefPtr<GenericNonExclusivePromise> sLaunchRDDPromise;
// Only modified on the main-thread, read on any thread. While it could be read
// on the main thread directly, for clarity we force access via the DataMutex
@ -70,10 +70,10 @@ void RemoteDecoderManagerChild::Init() {
auto remoteDecoderManagerThread = sRemoteDecoderManagerChildThread.Lock();
if (!*remoteDecoderManagerThread) {
// We can't use a MediaThreadType::SUPERVISOR as the RemoteDecoderModule
// runs on it and dispatch synchronous tasks to the manager thread, should
// more than 4 concurrent videos being instantiated at the same time, we
// could end up in a deadlock.
// We can't use a MediaThreadType::CONTROLLER as the GpuDecoderModule and
// RemoteDecoderModule runs on it and dispatch synchronous tasks to the
// manager thread, should more than 4 concurrent videos being instantiated
// at the same time, we could end up in a deadlock.
RefPtr<nsIThread> childThread;
nsresult rv = NS_NewNamedThread(
"RemVidChild", getter_AddRefs(childThread),
@ -194,131 +194,117 @@ bool RemoteDecoderManagerChild::Supports(
}
/* static */
RefPtr<PlatformDecoderModule::CreateDecoderPromise>
already_AddRefed<MediaDataDecoder>
RemoteDecoderManagerChild::CreateAudioDecoder(
const CreateDecoderParams& aParams) {
nsCOMPtr<nsISerialEventTarget> managerThread = GetManagerThread();
if (!managerThread) {
// We got shutdown.
return PlatformDecoderModule::CreateDecoderPromise::CreateAndReject(
NS_ERROR_DOM_MEDIA_CANCELED, __func__);
return nullptr;
}
return LaunchRDDProcessIfNeeded()->Then(
managerThread, __func__,
[params = CreateDecoderParamsForAsync(aParams)](bool) {
auto child = MakeRefPtr<RemoteAudioDecoderChild>();
MediaResult result =
child->InitIPDL(params.AudioConfig(), params.mOptions);
RefPtr<RemoteAudioDecoderChild> child;
MediaResult result(NS_ERROR_DOM_MEDIA_CANCELED);
// We can use child as a ref here because this is a sync dispatch. In
// the error case for InitIPDL, we can't just let the RefPtr go out of
// scope at the end of the method because it will release the
// RemoteAudioDecoderChild on the wrong thread. This will assert in
// RemoteDecoderChild's destructor. Passing the RefPtr by reference
// allows us to release the RemoteAudioDecoderChild on the manager
// thread during this single dispatch.
RefPtr<Runnable> task =
NS_NewRunnableFunction("RemoteDecoderModule::CreateAudioDecoder", [&]() {
child = new RemoteAudioDecoderChild();
result = child->InitIPDL(aParams.AudioConfig(), aParams.mOptions);
if (NS_FAILED(result)) {
return PlatformDecoderModule::CreateDecoderPromise::CreateAndReject(
result, __func__);
// Release RemoteAudioDecoderChild here, while we're on
// manager thread. Don't just let the RefPtr go out of scope.
child = nullptr;
}
return Construct(std::move(child));
},
[](nsresult aResult) {
return PlatformDecoderModule::CreateDecoderPromise::CreateAndReject(
MediaResult(aResult, "Couldn't start RDD process"), __func__);
});
SyncRunnable::DispatchToThread(managerThread, task);
if (NS_FAILED(result)) {
if (aParams.mError) {
*aParams.mError = result;
}
return nullptr;
}
RefPtr<RemoteMediaDataDecoder> object = new RemoteMediaDataDecoder(child);
return object.forget();
}
/* static */
RefPtr<PlatformDecoderModule::CreateDecoderPromise>
already_AddRefed<MediaDataDecoder>
RemoteDecoderManagerChild::CreateVideoDecoder(
const CreateDecoderParams& aParams, RemoteDecodeIn aLocation) {
nsCOMPtr<nsISerialEventTarget> managerThread = GetManagerThread();
if (!managerThread) {
// We got shutdown.
return PlatformDecoderModule::CreateDecoderPromise::CreateAndReject(
NS_ERROR_DOM_MEDIA_CANCELED, __func__);
}
if (!aParams.mKnowsCompositor && aLocation == RemoteDecodeIn::GpuProcess) {
// We don't have an image bridge; don't attempt to decode in the GPU
// process.
return PlatformDecoderModule::CreateDecoderPromise::CreateAndReject(
NS_ERROR_DOM_MEDIA_NOT_SUPPORTED_ERR, __func__);
return nullptr;
}
MOZ_ASSERT(aLocation != RemoteDecodeIn::Unspecified);
RefPtr<RemoteVideoDecoderChild> child;
MediaResult result(NS_ERROR_DOM_MEDIA_CANCELED);
RefPtr<GenericNonExclusivePromise> p =
aLocation == RemoteDecodeIn::GpuProcess
? GenericNonExclusivePromise::CreateAndResolve(true, __func__)
: LaunchRDDProcessIfNeeded();
return p->Then(
managerThread, __func__,
[aLocation, params = CreateDecoderParamsForAsync(aParams)](bool) {
auto child = MakeRefPtr<RemoteVideoDecoderChild>(aLocation);
MediaResult result = child->InitIPDL(
params.VideoConfig(), params.mRate.mValue, params.mOptions,
params.mKnowsCompositor
? &params.mKnowsCompositor->GetTextureFactoryIdentifier()
// We can use child as a ref here because this is a sync dispatch. In
// the error case for InitIPDL, we can't just let the RefPtr go out of
// scope at the end of the method because it will release the
// RemoteVideoDecoderChild on the wrong thread. This will assert in
// RemoteDecoderChild's destructor. Passing the RefPtr by reference
// allows us to release the RemoteVideoDecoderChild on the manager
// thread during this single dispatch.
RefPtr<Runnable> task = NS_NewRunnableFunction(
"RemoteDecoderManagerChild::CreateVideoDecoder", [&]() {
child = new RemoteVideoDecoderChild(aLocation);
result = child->InitIPDL(
aParams.VideoConfig(), aParams.mRate.mValue, aParams.mOptions,
aParams.mKnowsCompositor
? &aParams.mKnowsCompositor->GetTextureFactoryIdentifier()
: nullptr);
if (NS_FAILED(result)) {
return PlatformDecoderModule::CreateDecoderPromise::CreateAndReject(
result, __func__);
// Release RemoteVideoDecoderChild here, while we're on
// manager thread. Don't just let the RefPtr go out of scope.
child = nullptr;
}
return Construct(std::move(child));
},
[](nsresult aResult) {
return PlatformDecoderModule::CreateDecoderPromise::CreateAndReject(
MediaResult(aResult, "Couldn't start RDD process"), __func__);
});
SyncRunnable::DispatchToThread(managerThread, task);
if (NS_FAILED(result)) {
if (aParams.mError) {
*aParams.mError = result;
}
return nullptr;
}
RefPtr<RemoteMediaDataDecoder> object = new RemoteMediaDataDecoder(child);
return object.forget();
}
/* static */
RefPtr<PlatformDecoderModule::CreateDecoderPromise>
RemoteDecoderManagerChild::Construct(RefPtr<RemoteDecoderChild>&& aChild) {
nsCOMPtr<nsISerialEventTarget> managerThread = GetManagerThread();
if (!managerThread) {
// We got shutdown.
return PlatformDecoderModule::CreateDecoderPromise::CreateAndReject(
NS_ERROR_DOM_MEDIA_CANCELED, __func__);
}
MOZ_ASSERT(managerThread->IsOnCurrentThread());
RefPtr<PlatformDecoderModule::CreateDecoderPromise> p =
aChild->SendConstruct()->Then(
managerThread, __func__,
[child = std::move(aChild)](MediaResult aResult) {
if (NS_FAILED(aResult)) {
// We will never get to use this remote decoder, tear it down.
child->DestroyIPDL();
return PlatformDecoderModule::CreateDecoderPromise::
CreateAndReject(aResult, __func__);
}
return PlatformDecoderModule::CreateDecoderPromise::
CreateAndResolve(MakeRefPtr<RemoteMediaDataDecoder>(child),
__func__);
},
[](const mozilla::ipc::ResponseRejectReason& aReason) {
// The parent has died.
return PlatformDecoderModule::CreateDecoderPromise::CreateAndReject(
NS_ERROR_DOM_MEDIA_NEED_NEW_DECODER, __func__);
});
return p;
}
/* static */
RefPtr<GenericNonExclusivePromise>
RemoteDecoderManagerChild::LaunchRDDProcessIfNeeded() {
void RemoteDecoderManagerChild::LaunchRDDProcessIfNeeded(
RemoteDecodeIn aLocation) {
MOZ_DIAGNOSTIC_ASSERT(XRE_IsContentProcess(),
"Only supported from a content process.");
if (aLocation != RemoteDecodeIn::RddProcess) {
// Not targeting RDD process? No need to launch RDD.
return;
}
nsCOMPtr<nsISerialEventTarget> managerThread = GetManagerThread();
if (!managerThread) {
// We got shutdown.
return GenericNonExclusivePromise::CreateAndReject(NS_ERROR_FAILURE,
__func__);
return;
}
StaticMutexAutoLock lock(sLaunchMutex);
if (sLaunchRDDPromise) {
return sLaunchRDDPromise;
}
// We have a couple possible states here. We are in a content process
// and:
// 1) the RDD process has never been launched. RDD should be launched
@ -333,57 +319,40 @@ RemoteDecoderManagerChild::LaunchRDDProcessIfNeeded() {
// LaunchRDDProcess which will launch RDD if necessary, and setup the
// IPC connections between *this* content process and the RDD process.
RefPtr<GenericNonExclusivePromise> p = InvokeAsync(
managerThread, __func__, []() -> RefPtr<GenericNonExclusivePromise> {
bool needsLaunch = true;
RefPtr<Runnable> task = NS_NewRunnableFunction(
"RemoteDecoderManagerChild::LaunchRDDProcessIfNeeded-CheckSend", [&]() {
auto* rps = GetSingleton(RemoteDecodeIn::RddProcess);
if (rps && rps->CanSend()) {
return GenericNonExclusivePromise::CreateAndResolve(true, __func__);
}
nsCOMPtr<nsISerialEventTarget> managerThread = GetManagerThread();
needsLaunch = rps ? !rps->CanSend() : true;
});
if (NS_FAILED(SyncRunnable::DispatchToThread(managerThread, task))) {
return;
};
if (needsLaunch) {
managerThread->Dispatch(NS_NewRunnableFunction(
"RemoteDecoderManagerChild::EnsureRDDProcessAndCreateBridge", [&]() {
ipc::PBackgroundChild* bgActor =
ipc::BackgroundChild::GetForCurrentThread();
if (!managerThread || NS_WARN_IF(!bgActor)) {
return GenericNonExclusivePromise::CreateAndReject(NS_ERROR_FAILURE,
__func__);
if (NS_WARN_IF(!bgActor)) {
return;
}
return bgActor->SendEnsureRDDProcessAndCreateBridge()->Then(
managerThread, __func__,
[](ipc::PBackgroundChild::EnsureRDDProcessAndCreateBridgePromise::
ResolveOrRejectValue&& aResult) {
nsCOMPtr<nsISerialEventTarget> managerThread = GetManagerThread();
if (!managerThread || aResult.IsReject()) {
// The parent process died or we got shutdown
return GenericNonExclusivePromise::CreateAndReject(
NS_ERROR_FAILURE, __func__);
nsresult rv;
Endpoint<PRemoteDecoderManagerChild> endpoint;
Unused << bgActor->SendEnsureRDDProcessAndCreateBridge(&rv,
&endpoint);
if (NS_SUCCEEDED(rv)) {
OpenForRDDProcess(std::move(endpoint));
}
nsresult rv = Get<0>(aResult.ResolveValue());
if (NS_FAILED(rv)) {
return GenericNonExclusivePromise::CreateAndReject(rv,
__func__);
}));
}
OpenForRDDProcess(Get<1>(std::move(aResult.ResolveValue())));
return GenericNonExclusivePromise::CreateAndResolve(true,
__func__);
});
});
p = p->Then(
GetCurrentSerialEventTarget(), __func__,
[](const GenericNonExclusivePromise::ResolveOrRejectValue& aResult) {
StaticMutexAutoLock lock(sLaunchMutex);
sLaunchRDDPromise = nullptr;
return GenericNonExclusivePromise::CreateAndResolveOrReject(aResult,
__func__);
});
sLaunchRDDPromise = p;
return sLaunchRDDPromise;
}
PRemoteDecoderChild* RemoteDecoderManagerChild::AllocPRemoteDecoderChild(
const RemoteDecoderInfoIPDL& /* not used */,
const CreateDecoderParams::OptionSet& aOptions,
const Maybe<layers::TextureFactoryIdentifier>& aIdentifier) {
const Maybe<layers::TextureFactoryIdentifier>& aIdentifier, bool* aSuccess,
nsCString* /* not used */) {
// RemoteDecoderModule is responsible for creating RemoteDecoderChild
// classes.
MOZ_ASSERT(false,

Просмотреть файл

@ -11,8 +11,6 @@
namespace mozilla {
class RemoteDecoderChild;
enum class RemoteDecodeIn {
Unspecified,
RddProcess,
@ -37,13 +35,14 @@ class RemoteDecoderManagerChild final
static bool Supports(RemoteDecodeIn aLocation,
const SupportDecoderParams& aParams,
DecoderDoctorDiagnostics* aDiagnostics);
static RefPtr<PlatformDecoderModule::CreateDecoderPromise> CreateAudioDecoder(
static already_AddRefed<MediaDataDecoder> CreateAudioDecoder(
const CreateDecoderParams& aParams);
static RefPtr<PlatformDecoderModule::CreateDecoderPromise> CreateVideoDecoder(
static already_AddRefed<MediaDataDecoder> CreateVideoDecoder(
const CreateDecoderParams& aParams, RemoteDecodeIn aLocation);
// Can be called from any thread.
static nsISerialEventTarget* GetManagerThread();
static void LaunchRDDProcessIfNeeded(RemoteDecodeIn aLocation);
// Can be called from any thread, dispatches the request to the IPDL thread
// internally and will be ignored if the IPDL actor has been destroyed.
@ -92,20 +91,18 @@ class RemoteDecoderManagerChild final
PRemoteDecoderChild* AllocPRemoteDecoderChild(
const RemoteDecoderInfoIPDL& aRemoteDecoderInfo,
const CreateDecoderParams::OptionSet& aOptions,
const Maybe<layers::TextureFactoryIdentifier>& aIdentifier);
const Maybe<layers::TextureFactoryIdentifier>& aIdentifier,
bool* aSuccess, nsCString* aErrorDescription);
bool DeallocPRemoteDecoderChild(PRemoteDecoderChild* actor);
private:
explicit RemoteDecoderManagerChild(RemoteDecodeIn aLocation);
~RemoteDecoderManagerChild() = default;
static RefPtr<PlatformDecoderModule::CreateDecoderPromise> Construct(
RefPtr<RemoteDecoderChild>&& aChild);
static void OpenForRDDProcess(
Endpoint<PRemoteDecoderManagerChild>&& aEndpoint);
static void OpenForGPUProcess(
Endpoint<PRemoteDecoderManagerChild>&& aEndpoint);
static RefPtr<GenericNonExclusivePromise> LaunchRDDProcessIfNeeded();
RefPtr<RemoteDecoderManagerChild> mIPDLSelfRef;
// The location for decoding, Rdd or Gpu process.

Просмотреть файл

@ -14,11 +14,11 @@
#include "RemoteAudioDecoder.h"
#include "RemoteVideoDecoder.h"
#include "VideoUtils.h" // for MediaThreadType
#include "mozilla/RDDParent.h"
#include "mozilla/SyncRunnable.h"
#include "mozilla/gfx/GPUParent.h"
#include "mozilla/layers/ImageDataSerializer.h"
#include "mozilla/layers/VideoBridgeChild.h"
#include "mozilla/gfx/GPUParent.h"
#include "mozilla/RDDParent.h"
namespace mozilla {
@ -182,7 +182,8 @@ void RemoteDecoderManagerParent::ActorDestroy(
PRemoteDecoderParent* RemoteDecoderManagerParent::AllocPRemoteDecoderParent(
const RemoteDecoderInfoIPDL& aRemoteDecoderInfo,
const CreateDecoderParams::OptionSet& aOptions,
const Maybe<layers::TextureFactoryIdentifier>& aIdentifier) {
const Maybe<layers::TextureFactoryIdentifier>& aIdentifier, bool* aSuccess,
nsCString* aErrorDescription) {
RefPtr<TaskQueue> decodeTaskQueue =
new TaskQueue(GetMediaThreadPool(MediaThreadType::PLATFORM_DECODER),
"RemoteVideoDecoderParent::mDecodeTaskQueue");
@ -193,13 +194,15 @@ PRemoteDecoderParent* RemoteDecoderManagerParent::AllocPRemoteDecoderParent(
aRemoteDecoderInfo.get_VideoDecoderInfoIPDL();
return new RemoteVideoDecoderParent(
this, decoderInfo.videoInfo(), decoderInfo.framerate(), aOptions,
aIdentifier, sRemoteDecoderManagerParentThread, decodeTaskQueue);
aIdentifier, sRemoteDecoderManagerParentThread, decodeTaskQueue,
aSuccess, aErrorDescription);
}
if (aRemoteDecoderInfo.type() == RemoteDecoderInfoIPDL::TAudioInfo) {
return new RemoteAudioDecoderParent(
this, aRemoteDecoderInfo.get_AudioInfo(), aOptions,
sRemoteDecoderManagerParentThread, decodeTaskQueue);
sRemoteDecoderManagerParentThread, decodeTaskQueue, aSuccess,
aErrorDescription);
}
MOZ_CRASH("unrecognized type of RemoteDecoderInfoIPDL union");

Просмотреть файл

@ -57,9 +57,15 @@ class RemoteDecoderManagerParent final
PRemoteDecoderParent* AllocPRemoteDecoderParent(
const RemoteDecoderInfoIPDL& aRemoteDecoderInfo,
const CreateDecoderParams::OptionSet& aOptions,
const Maybe<layers::TextureFactoryIdentifier>& aIdentifier);
const Maybe<layers::TextureFactoryIdentifier>& aIdentifier,
bool* aSuccess, nsCString* aErrorDescription);
bool DeallocPRemoteDecoderParent(PRemoteDecoderParent* actor);
mozilla::ipc::IPCResult RecvSupports(
const RemoteDecoderInfoIPDL& aInfo,
const Maybe<layers::TextureFactoryIdentifier>& aIdentifier,
bool* aSuccess, DecoderDoctorDiagnostics* aDiagnostics);
mozilla::ipc::IPCResult RecvReadback(const SurfaceDescriptorGPUVideo& aSD,
SurfaceDescriptor* aResult);
mozilla::ipc::IPCResult RecvDeallocateSurfaceDescriptorGPUVideo(

Просмотреть файл

@ -5,6 +5,11 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "RemoteDecoderModule.h"
#include "mozilla/StaticPrefs_media.h"
#include "mozilla/SyncRunnable.h"
#include "mozilla/dom/ContentChild.h" // for launching RDD w/ ContentChild
#include "mozilla/layers/SynchronousTask.h"
#ifdef MOZ_AV1
# include "AOMDecoder.h"
#endif
@ -56,9 +61,10 @@ bool RemoteDecoderModule::Supports(
return supports;
}
RefPtr<RemoteDecoderModule::CreateDecoderPromise>
RemoteDecoderModule::AsyncCreateDecoder(const CreateDecoderParams& aParams) {
if (aParams.mConfig.IsAudio()) {
already_AddRefed<MediaDataDecoder> RemoteDecoderModule::CreateAudioDecoder(
const CreateDecoderParams& aParams) {
RemoteDecoderManagerChild::LaunchRDDProcessIfNeeded(mLocation);
// OpusDataDecoder will check this option to provide the same info
// that IsDefaultPlaybackDeviceMono provides. We want to avoid calls
// to IsDefaultPlaybackDeviceMono on RDD because initializing audio
@ -69,8 +75,13 @@ RemoteDecoderModule::AsyncCreateDecoder(const CreateDecoderParams& aParams) {
params.mOptions += CreateDecoderParams::Option::DefaultPlaybackDeviceMono;
return RemoteDecoderManagerChild::CreateAudioDecoder(params);
}
return RemoteDecoderManagerChild::CreateAudioDecoder(aParams);
}
}
already_AddRefed<MediaDataDecoder> RemoteDecoderModule::CreateVideoDecoder(
const CreateDecoderParams& aParams) {
RemoteDecoderManagerChild::LaunchRDDProcessIfNeeded(mLocation);
return RemoteDecoderManagerChild::CreateVideoDecoder(aParams, mLocation);
}

Просмотреть файл

@ -26,18 +26,11 @@ class RemoteDecoderModule : public PlatformDecoderModule {
bool Supports(const SupportDecoderParams& aParams,
DecoderDoctorDiagnostics* aDiagnostics) const override;
RefPtr<CreateDecoderPromise> AsyncCreateDecoder(
already_AddRefed<MediaDataDecoder> CreateVideoDecoder(
const CreateDecoderParams& aParams) override;
already_AddRefed<MediaDataDecoder> CreateVideoDecoder(
const CreateDecoderParams& aParams) override {
MOZ_CRASH("Not available");
}
already_AddRefed<MediaDataDecoder> CreateAudioDecoder(
const CreateDecoderParams& aParams) override {
MOZ_CRASH("Not available");
}
const CreateDecoderParams& aParams) override;
private:
explicit RemoteDecoderModule(RemoteDecodeIn aLocation);

Просмотреть файл

@ -10,13 +10,11 @@
namespace mozilla {
RemoteDecoderParent::RemoteDecoderParent(
RemoteDecoderManagerParent* aParent,
const CreateDecoderParams::OptionSet& aOptions,
nsISerialEventTarget* aManagerThread, TaskQueue* aDecodeTaskQueue)
RemoteDecoderParent::RemoteDecoderParent(RemoteDecoderManagerParent* aParent,
nsISerialEventTarget* aManagerThread,
TaskQueue* aDecodeTaskQueue)
: ShmemRecycleAllocator(this),
mParent(aParent),
mOptions(aOptions),
mDecodeTaskQueue(aDecodeTaskQueue),
mManagerThread(aManagerThread) {
MOZ_COUNT_CTOR(RemoteDecoderParent);

Просмотреть файл

@ -24,14 +24,12 @@ class RemoteDecoderParent : public ShmemRecycleAllocator<RemoteDecoderParent>,
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(RemoteDecoderParent)
RemoteDecoderParent(RemoteDecoderManagerParent* aParent,
const CreateDecoderParams::OptionSet& aOptions,
nsISerialEventTarget* aManagerThread,
TaskQueue* aDecodeTaskQueue);
void Destroy();
// PRemoteDecoderParent
virtual IPCResult RecvConstruct(ConstructResolver&& aResolver) = 0;
IPCResult RecvInit(InitResolver&& aResolver);
IPCResult RecvDecode(ArrayOfRemoteMediaRawData* aData,
DecodeResolver&& aResolver);
@ -51,7 +49,6 @@ class RemoteDecoderParent : public ShmemRecycleAllocator<RemoteDecoderParent>,
DecodedOutputIPDL& aDecodedData) = 0;
const RefPtr<RemoteDecoderManagerParent> mParent;
const CreateDecoderParams::OptionSet mOptions;
const RefPtr<TaskQueue> mDecodeTaskQueue;
RefPtr<MediaDataDecoder> mDecoder;

Просмотреть файл

@ -5,30 +5,19 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "RemoteMediaDataDecoder.h"
#include "RemoteDecoderChild.h"
#include "base/thread.h"
#include "IRemoteDecoderChild.h"
#include "RemoteDecoderManagerChild.h"
namespace mozilla {
RemoteMediaDataDecoder::RemoteMediaDataDecoder(RemoteDecoderChild* aChild)
RemoteMediaDataDecoder::RemoteMediaDataDecoder(IRemoteDecoderChild* aChild)
: mChild(aChild) {}
RemoteMediaDataDecoder::~RemoteMediaDataDecoder() {
if (mChild) {
// Shutdown didn't get called. This can happen if the creation of the
// decoder got interrupted while pending.
nsCOMPtr<nsISerialEventTarget> thread =
RemoteDecoderManagerChild::GetManagerThread();
MOZ_ASSERT(thread);
thread->Dispatch(NS_NewRunnableFunction(
"RemoteMediaDataDecoderShutdown", [child = std::move(mChild), thread] {
child->Shutdown()->Then(
thread, __func__,
[child](const ShutdownPromise::ResolveOrRejectValue& aValue) {
child->DestroyIPDL();
});
}));
}
/* Shutdown method should have been called. */
MOZ_ASSERT(!mChild);
}
RefPtr<MediaDataDecoder::InitPromise> RemoteMediaDataDecoder::Init() {

Просмотреть файл

@ -11,7 +11,8 @@
namespace mozilla {
class RemoteDecoderChild;
class GpuDecoderModule;
class IRemoteDecoderChild;
class RemoteDecoderManagerChild;
class RemoteMediaDataDecoder;
@ -26,7 +27,8 @@ class RemoteMediaDataDecoder
: public MediaDataDecoder,
public DecoderDoctorLifeLogger<RemoteMediaDataDecoder> {
public:
explicit RemoteMediaDataDecoder(RemoteDecoderChild* aChild);
friend class GpuDecoderModule;
friend class RemoteDecoderManagerChild;
// MediaDataDecoder
RefPtr<InitPromise> Init() override;
@ -43,12 +45,13 @@ class RemoteMediaDataDecoder
ConversionRequired NeedsConversion() const override;
private:
explicit RemoteMediaDataDecoder(IRemoteDecoderChild* aChild);
~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<RemoteDecoderChild> mChild;
RefPtr<IRemoteDecoderChild> mChild;
// Only ever written/modified during decoder initialisation.
// As such can be accessed from any threads after that.
nsCString mDescription = "RemoteMediaDataDecoder"_ns;

Просмотреть файл

@ -123,21 +123,25 @@ MediaResult RemoteVideoDecoderChild::InitIPDL(
}
mIPDLSelfRef = this;
bool success = false;
nsCString errorDescription;
VideoDecoderInfoIPDL decoderInfo(aVideoInfo, aFramerate);
Unused << manager->SendPRemoteDecoderConstructor(this, decoderInfo, aOptions,
ToMaybe(aIdentifier));
ToMaybe(aIdentifier),
&success, &errorDescription);
return NS_OK;
return success ? MediaResult(NS_OK)
: MediaResult(NS_ERROR_DOM_MEDIA_FATAL_ERR, errorDescription);
}
RemoteVideoDecoderParent::RemoteVideoDecoderParent(
RemoteDecoderManagerParent* aParent, const VideoInfo& aVideoInfo,
float aFramerate, const CreateDecoderParams::OptionSet& aOptions,
const Maybe<layers::TextureFactoryIdentifier>& aIdentifier,
nsISerialEventTarget* aManagerThread, TaskQueue* aDecodeTaskQueue)
: RemoteDecoderParent(aParent, aOptions, aManagerThread, aDecodeTaskQueue),
mVideoInfo(aVideoInfo),
mFramerate(aFramerate) {
nsISerialEventTarget* aManagerThread, TaskQueue* aDecodeTaskQueue,
bool* aSuccess, nsCString* aErrorDescription)
: RemoteDecoderParent(aParent, aManagerThread, aDecodeTaskQueue),
mVideoInfo(aVideoInfo) {
if (aIdentifier) {
// Check to see if we have a direct PVideoBridge connection to the
// destination process specified in aIdentifier, and create a
@ -146,37 +150,34 @@ RemoteVideoDecoderParent::RemoteVideoDecoderParent(
mKnowsCompositor =
KnowsCompositorVideo::TryCreateForIdentifier(*aIdentifier);
}
}
IPCResult RemoteVideoDecoderParent::RecvConstruct(
ConstructResolver&& aResolver) {
// It is possible for CreateDecoder() below to fail. In that case, we need to
// free the ImageContainer to avoid it leaking.
auto imageContainer = MakeRefPtr<layers::ImageContainer>();
if (mKnowsCompositor && XRE_IsRDDProcess()) {
// Ensure to allocate recycle allocator
imageContainer->EnsureRecycleAllocatorForRDD(mKnowsCompositor);
}
MediaResult error(NS_OK);
auto params = CreateDecoderParams{
mVideoInfo, mKnowsCompositor,
imageContainer, CreateDecoderParams::VideoFrameRate(mFramerate),
mOptions, CreateDecoderParams::NoWrapper(true),
};
imageContainer, CreateDecoderParams::VideoFrameRate(aFramerate),
aOptions, CreateDecoderParams::NoWrapper(true),
&error};
mParent->EnsurePDMFactory().CreateDecoder(params)->Then(
GetCurrentSerialEventTarget(), __func__,
[resolver = std::move(aResolver), self = RefPtr{this}](
PlatformDecoderModule::CreateDecoderPromise::ResolveOrRejectValue&&
aValue) {
if (aValue.IsReject()) {
resolver(aValue.RejectValue());
return;
auto& factory = aParent->EnsurePDMFactory();
RefPtr<MediaDataDecoder> decoder = factory.CreateDecoder(params);
if (NS_FAILED(error)) {
MOZ_ASSERT(aErrorDescription);
*aErrorDescription = error.Description();
}
MOZ_ASSERT(aValue.ResolveValue());
self->mDecoder =
new MediaDataDecoderProxy(aValue.ResolveValue().forget(),
do_AddRef(self->mDecodeTaskQueue.get()));
resolver(NS_OK);
});
return IPC_OK();
if (decoder) {
mDecoder = new MediaDataDecoderProxy(decoder.forget(),
do_AddRef(mDecodeTaskQueue.get()));
}
*aSuccess = !!mDecoder;
}
MediaResult RemoteVideoDecoderParent::ProcessDecodedData(

Просмотреть файл

@ -58,11 +58,10 @@ class RemoteVideoDecoderParent final : public RemoteDecoderParent {
RemoteDecoderManagerParent* aParent, const VideoInfo& aVideoInfo,
float aFramerate, const CreateDecoderParams::OptionSet& aOptions,
const Maybe<layers::TextureFactoryIdentifier>& aIdentifier,
nsISerialEventTarget* aManagerThread, TaskQueue* aDecodeTaskQueue);
nsISerialEventTarget* aManagerThread, TaskQueue* aDecodeTaskQueue,
bool* aSuccess, nsCString* aErrorDescription);
protected:
IPCResult RecvConstruct(ConstructResolver&& aResolver) override;
MediaResult ProcessDecodedData(MediaDataDecoder::DecodedData&& aData,
DecodedOutputIPDL& aDecodedData) override;
@ -73,7 +72,7 @@ class RemoteVideoDecoderParent final : public RemoteDecoderParent {
// passed a deserialized VideoInfo from RecvPRemoteDecoderConstructor
// which is destroyed when RecvPRemoteDecoderConstructor returns.
const VideoInfo mVideoInfo;
const float mFramerate;
RefPtr<KnowsCompositorVideo> mKnowsCompositor;
};

Просмотреть файл

@ -13,6 +13,7 @@ IPDL_SOURCES += [
]
EXPORTS.mozilla += [
"IRemoteDecoderChild.h",
"RDDChild.h",
"RDDParent.h",
"RDDProcessHost.h",

Просмотреть файл

@ -195,13 +195,27 @@ RefPtr<ShutdownPromise> AllocationWrapper::Shutdown() {
/* static */ RefPtr<AllocationWrapper::AllocateDecoderPromise>
AllocationWrapper::CreateDecoder(const CreateDecoderParams& aParams,
AllocPolicy* aPolicy) {
// aParams.mConfig is guaranteed to stay alive during the lifetime of the
// MediaDataDecoder, so keeping a pointer to the object is safe.
const TrackInfo* config = &aParams.mConfig;
DecoderDoctorDiagnostics* diagnostics = aParams.mDiagnostics;
RefPtr<layers::ImageContainer> imageContainer = aParams.mImageContainer;
RefPtr<layers::KnowsCompositor> knowsCompositor = aParams.mKnowsCompositor;
RefPtr<GMPCrashHelper> crashHelper = aParams.mCrashHelper;
CreateDecoderParams::UseNullDecoder useNullDecoder = aParams.mUseNullDecoder;
CreateDecoderParams::NoWrapper noWrapper = aParams.mNoWrapper;
TrackInfo::TrackType type = aParams.mType;
MediaEventProducer<TrackInfo::TrackType>* onWaitingForKeyEvent =
aParams.mOnWaitingForKeyEvent;
CreateDecoderParams::OptionSet options = aParams.mOptions;
CreateDecoderParams::VideoFrameRate rate = aParams.mRate;
RefPtr<AllocateDecoderPromise> p =
(aPolicy ? aPolicy : GlobalAllocPolicy::Instance(aParams.mType))
->Alloc()
->Then(
GetCurrentSerialEventTarget(), __func__,
[params =
CreateDecoderParamsForAsync(aParams)](RefPtr<Token> aToken) {
[=](RefPtr<Token> aToken) {
// result may not always be updated by
// PDMFactory::CreateDecoder either when the creation
// succeeded or failed, as such it must be initialized to a
@ -209,23 +223,29 @@ AllocationWrapper::CreateDecoder(const CreateDecoderParams& aParams,
MediaResult result =
MediaResult(NS_ERROR_DOM_MEDIA_FATAL_ERR,
nsPrintfCString("error creating %s decoder",
TrackTypeToStr(params.mType)));
TrackTypeToStr(type)));
RefPtr<PDMFactory> pdm = new PDMFactory();
RefPtr<PlatformDecoderModule::CreateDecoderPromise> p =
pdm->CreateDecoder(params)->Then(
GetCurrentSerialEventTarget(), __func__,
[aToken](RefPtr<MediaDataDecoder>&& aDecoder) mutable {
CreateDecoderParams params{*config,
diagnostics,
imageContainer,
&result,
knowsCompositor,
crashHelper,
useNullDecoder,
noWrapper,
type,
onWaitingForKeyEvent,
options,
rate};
RefPtr<MediaDataDecoder> decoder = pdm->CreateDecoder(params);
if (decoder) {
RefPtr<AllocationWrapper> wrapper =
new AllocationWrapper(aDecoder.forget(),
aToken.forget());
return AllocateDecoderPromise::CreateAndResolve(
wrapper, __func__);
},
[](const MediaResult& aError) {
return AllocateDecoderPromise::CreateAndReject(
aError, __func__);
});
return p;
new AllocationWrapper(decoder.forget(), aToken.forget());
return AllocateDecoderPromise::CreateAndResolve(wrapper,
__func__);
}
return AllocateDecoderPromise::CreateAndReject(result,
__func__);
},
[]() {
return AllocateDecoderPromise::CreateAndReject(

Просмотреть файл

@ -28,7 +28,6 @@
#include "mozilla/TaskQueue.h"
#include "mozilla/gfx/gfxVars.h"
#include "nsIXULRuntime.h" // for BrowserTabsRemoteAutostart
#include "nsPrintfCString.h"
#ifdef XP_WIN
# include "WMFDecoderModule.h"
@ -289,59 +288,49 @@ void PDMFactory::EnsureInit() {
SyncRunnable::DispatchToThread(mainTarget, runnable);
}
RefPtr<PlatformDecoderModule::CreateDecoderPromise> PDMFactory::CreateDecoder(
already_AddRefed<MediaDataDecoder> PDMFactory::CreateDecoder(
const CreateDecoderParams& aParams) {
RefPtr<MediaDataDecoder> decoder;
const TrackInfo& config = aParams.mConfig;
if (aParams.mUseNullDecoder.mUse) {
MOZ_ASSERT(mNullPDM);
return CreateDecoderWithPDM(mNullPDM, aParams);
}
bool isEncrypted = mEMEPDM && aParams.mConfig.mCrypto.IsEncrypted();
decoder = CreateDecoderWithPDM(mNullPDM, aParams);
} else {
bool isEncrypted = mEMEPDM && config.mCrypto.IsEncrypted();
if (isEncrypted) {
return CreateDecoderWithPDM(mEMEPDM, aParams);
decoder = CreateDecoderWithPDM(mEMEPDM, aParams);
} else {
DecoderDoctorDiagnostics* diagnostics = aParams.mDiagnostics;
if (diagnostics) {
// If libraries failed to load, the following loop over mCurrentPDMs
// will not even try to use them. So we record failures now.
diagnostics->SetFailureFlags(mFailureFlags);
}
return CheckAndMaybeCreateDecoder(CreateDecoderParamsForAsync(aParams), 0);
}
RefPtr<PlatformDecoderModule::CreateDecoderPromise>
PDMFactory::CheckAndMaybeCreateDecoder(CreateDecoderParamsForAsync&& aParams,
uint32_t aIndex) {
uint32_t i = aIndex;
auto params = SupportDecoderParams(aParams);
for (; i < mCurrentPDMs.Length(); i++) {
if (!mCurrentPDMs[i]->Supports(params, nullptr /* diagnostic */)) {
for (auto& current : mCurrentPDMs) {
if (!current->Supports(SupportDecoderParams(aParams), diagnostics)) {
continue;
}
RefPtr<PlatformDecoderModule::CreateDecoderPromise> p =
CreateDecoderWithPDM(mCurrentPDMs[i], aParams)
->Then(
GetCurrentSerialEventTarget(), __func__,
[](RefPtr<MediaDataDecoder>&& aDecoder) {
return PlatformDecoderModule::CreateDecoderPromise::
CreateAndResolve(std::move(aDecoder), __func__);
},
[self = RefPtr{this}, i, params = std::move(aParams)](
const MediaResult& aError) mutable {
// Try the next PDM.
return self->CheckAndMaybeCreateDecoder(std::move(params),
i + 1);
});
return p;
decoder = CreateDecoderWithPDM(current, aParams);
if (decoder) {
break;
}
return PlatformDecoderModule::CreateDecoderPromise::CreateAndReject(
MediaResult(NS_ERROR_DOM_MEDIA_FATAL_ERR,
nsPrintfCString("Error no decoder found for %s",
aParams.mConfig->mMimeType.get())
.get()),
__func__);
}
}
}
if (!decoder) {
NS_WARNING("Unable to create a decoder, no platform found.");
return nullptr;
}
return decoder.forget();
}
RefPtr<PlatformDecoderModule::CreateDecoderPromise>
PDMFactory::CreateDecoderWithPDM(PlatformDecoderModule* aPDM,
const CreateDecoderParams& aParams) {
already_AddRefed<MediaDataDecoder> PDMFactory::CreateDecoderWithPDM(
PlatformDecoderModule* aPDM, const CreateDecoderParams& aParams) {
MOZ_ASSERT(aPDM);
MediaResult result = NS_OK;
RefPtr<MediaDataDecoder> m;
MediaResult* result = aParams.mError;
SupportChecker supportChecker;
const TrackInfo& config = aParams.mConfig;
@ -349,53 +338,61 @@ PDMFactory::CreateDecoderWithPDM(PlatformDecoderModule* aPDM,
auto checkResult = supportChecker.Check();
if (checkResult.mReason != SupportChecker::Reason::kSupported) {
DecoderDoctorDiagnostics* diagnostics = aParams.mDiagnostics;
if (checkResult.mReason ==
SupportChecker::Reason::kVideoFormatNotSupported) {
result = checkResult.mMediaResult;
if (diagnostics) {
diagnostics->SetVideoNotSupported();
}
if (result) {
*result = checkResult.mMediaResult;
}
} else if (checkResult.mReason ==
SupportChecker::Reason::kAudioFormatNotSupported) {
result = checkResult.mMediaResult;
if (diagnostics) {
diagnostics->SetAudioNotSupported();
}
return PlatformDecoderModule::CreateDecoderPromise::CreateAndReject(
result, __func__);
if (result) {
*result = checkResult.mMediaResult;
}
}
return nullptr;
}
if (config.IsAudio()) {
RefPtr<PlatformDecoderModule::CreateDecoderPromise> p;
p = aPDM->AsyncCreateDecoder(aParams)->Then(
GetCurrentSerialEventTarget(), __func__,
[params = CreateDecoderParamsForAsync(aParams)](
RefPtr<MediaDataDecoder>&& aDecoder) {
RefPtr<MediaDataDecoder> decoder = std::move(aDecoder);
if (!params.mNoWrapper.mDontUseWrapper) {
decoder =
new AudioTrimmer(decoder.forget(), CreateDecoderParams(params));
m = aPDM->CreateAudioDecoder(aParams);
if (m && !aParams.mNoWrapper.mDontUseWrapper) {
m = new AudioTrimmer(m.forget(), aParams);
}
return PlatformDecoderModule::CreateDecoderPromise::CreateAndResolve(
decoder, __func__);
},
[](const MediaResult& aError) {
return PlatformDecoderModule::CreateDecoderPromise::CreateAndReject(
aError, __func__);
});
return p;
return m.forget();
}
if (!config.IsVideo()) {
return PlatformDecoderModule::CreateDecoderPromise::CreateAndReject(
MediaResult(
*result = MediaResult(
NS_ERROR_DOM_MEDIA_FATAL_ERR,
RESULT_DETAIL(
"Decoder configuration error, expected audio or video.")),
__func__);
RESULT_DETAIL("Decoder configuration error, expected audio or video."));
return nullptr;
}
if ((MP4Decoder::IsH264(config.mMimeType) ||
VPXDecoder::IsVPX(config.mMimeType)) &&
!aParams.mUseNullDecoder.mUse && !aParams.mNoWrapper.mDontUseWrapper) {
return MediaChangeMonitor::Create(aPDM, aParams);
RefPtr<MediaChangeMonitor> h = new MediaChangeMonitor(aPDM, aParams);
const MediaResult result = h->GetLastError();
if (NS_SUCCEEDED(result) || result == NS_ERROR_NOT_INITIALIZED) {
// The MediaChangeMonitor either successfully created the wrapped decoder,
// or there wasn't enough initialization data to do so (such as what can
// happen with AVC3). Otherwise, there was some problem, for example WMF
// DLLs were missing.
m = std::move(h);
} else if (aParams.mError) {
*aParams.mError = result;
}
return aPDM->AsyncCreateDecoder(aParams);
} else {
m = aPDM->CreateVideoDecoder(aParams);
}
return m.forget();
}
bool PDMFactory::SupportsMimeType(

Просмотреть файл

@ -32,8 +32,11 @@ class PDMFactory final {
static already_AddRefed<PDMFactory> PDMFactoryForGpu();
// Factory method that creates the appropriate PlatformDecoderModule for
// the platform we're running on.
RefPtr<PlatformDecoderModule::CreateDecoderPromise> CreateDecoder(
// the platform we're running on. Caller is responsible for deleting this
// instance. It's expected that there will be multiple
// PlatformDecoderModules alive at the same time.
// This is called on the decode task queue.
already_AddRefed<MediaDataDecoder> CreateDecoder(
const CreateDecoderParams& aParams);
bool SupportsMimeType(const nsACString& aMimeType,
@ -104,11 +107,8 @@ class PDMFactory final {
const SupportDecoderParams& aParams,
DecoderDoctorDiagnostics* aDiagnostics) const;
RefPtr<PlatformDecoderModule::CreateDecoderPromise> CreateDecoderWithPDM(
already_AddRefed<MediaDataDecoder> CreateDecoderWithPDM(
PlatformDecoderModule* aPDM, const CreateDecoderParams& aParams);
RefPtr<PlatformDecoderModule::CreateDecoderPromise>
CheckAndMaybeCreateDecoder(CreateDecoderParamsForAsync&& aParams,
uint32_t aIndex);
nsTArray<RefPtr<PlatformDecoderModule>> mCurrentPDMs;
RefPtr<PlatformDecoderModule> mEMEPDM;

Просмотреть файл

@ -1,53 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim:set ts=2 sw=2 sts=2 et cindent: */
/* 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 "PlatformDecoderModule.h"
#include "ImageContainer.h"
#include "nsPrintfCString.h"
namespace mozilla {
CreateDecoderParamsForAsync::CreateDecoderParamsForAsync(
const CreateDecoderParams& aParams)
: mConfig(aParams.mConfig.Clone()),
mImageContainer(aParams.mImageContainer),
mKnowsCompositor(aParams.mKnowsCompositor),
mCrashHelper(aParams.mCrashHelper),
mUseNullDecoder(aParams.mUseNullDecoder),
mNoWrapper(aParams.mNoWrapper),
mType(aParams.mType),
mOnWaitingForKeyEvent(aParams.mOnWaitingForKeyEvent),
mOptions(aParams.mOptions),
mRate(aParams.mRate) {}
CreateDecoderParamsForAsync::CreateDecoderParamsForAsync(
CreateDecoderParamsForAsync&& aParams) = default;
RefPtr<PlatformDecoderModule::CreateDecoderPromise>
PlatformDecoderModule::AsyncCreateDecoder(const CreateDecoderParams& aParams) {
RefPtr<MediaDataDecoder> decoder;
MediaResult result = NS_OK;
if (aParams.mConfig.IsAudio()) {
decoder = CreateAudioDecoder(CreateDecoderParams{aParams, &result});
} else if (aParams.mConfig.IsVideo()) {
decoder = CreateVideoDecoder(CreateDecoderParams{aParams, &result});
}
if (!decoder) {
if (NS_FAILED(result)) {
return CreateDecoderPromise::CreateAndReject(result, __func__);
}
return CreateDecoderPromise::CreateAndReject(
MediaResult(NS_ERROR_DOM_MEDIA_FATAL_ERR,
nsPrintfCString("Error creating decoder for %s",
aParams.mConfig.mMimeType.get())
.get()),
__func__);
}
return CreateDecoderPromise::CreateAndResolve(decoder, __func__);
}
} // namespace mozilla

Просмотреть файл

@ -34,6 +34,7 @@ namespace layers {
class ImageContainer;
} // namespace layers
class GpuDecoderModule;
class MediaDataDecoder;
class RemoteDecoderModule;
class CDMProxy;
@ -79,36 +80,6 @@ struct VideoFrameRate {
} // namespace media
struct CreateDecoderParams;
struct CreateDecoderParamsForAsync {
using Option = media::Option;
using OptionSet = media::OptionSet;
explicit CreateDecoderParamsForAsync(const CreateDecoderParams& aParams);
CreateDecoderParamsForAsync(CreateDecoderParamsForAsync&& aParams);
const VideoInfo& VideoConfig() const {
MOZ_ASSERT(mConfig->IsVideo());
return *mConfig->GetAsVideoInfo();
}
const AudioInfo& AudioConfig() const {
MOZ_ASSERT(mConfig->IsAudio());
return *mConfig->GetAsAudioInfo();
}
UniquePtr<TrackInfo> mConfig;
const RefPtr<layers::ImageContainer> mImageContainer;
const RefPtr<layers::KnowsCompositor> mKnowsCompositor;
const RefPtr<GMPCrashHelper> mCrashHelper;
const media::UseNullDecoder mUseNullDecoder;
const media::NoWrapper mNoWrapper;
const TrackInfo::TrackType mType = TrackInfo::kUndefinedTrack;
std::function<MediaEventProducer<TrackInfo::TrackType>*()>
mOnWaitingForKeyEvent;
const OptionSet mOptions = OptionSet(Option::Default);
const media::VideoFrameRate mRate;
};
struct MOZ_STACK_CLASS CreateDecoderParams final {
using Option = media::Option;
using OptionSet = media::OptionSet;
@ -117,19 +88,6 @@ struct MOZ_STACK_CLASS CreateDecoderParams final {
using VideoFrameRate = media::VideoFrameRate;
explicit CreateDecoderParams(const TrackInfo& aConfig) : mConfig(aConfig) {}
CreateDecoderParams(const CreateDecoderParams& aParams) = default;
MOZ_IMPLICIT CreateDecoderParams(const CreateDecoderParamsForAsync& aParams)
: mConfig(*aParams.mConfig.get()),
mImageContainer(aParams.mImageContainer),
mKnowsCompositor(aParams.mKnowsCompositor),
mCrashHelper(aParams.mCrashHelper),
mUseNullDecoder(aParams.mUseNullDecoder),
mNoWrapper(aParams.mNoWrapper),
mType(aParams.mType),
mOnWaitingForKeyEvent(aParams.mOnWaitingForKeyEvent),
mOptions(aParams.mOptions),
mRate(aParams.mRate) {}
template <typename T1, typename... Ts>
CreateDecoderParams(const TrackInfo& aConfig, T1&& a1, Ts&&... args)
@ -160,23 +118,23 @@ struct MOZ_STACK_CLASS CreateDecoderParams final {
return layers::LayersBackend::LAYERS_NONE;
}
// CreateDecoderParams is a MOZ_STACK_CLASS, it is only used to
// simplify the passing of arguments to Create*Decoder.
// It is safe to use references and raw pointers.
const TrackInfo& mConfig;
DecoderDoctorDiagnostics* mDiagnostics = nullptr;
layers::ImageContainer* mImageContainer = nullptr;
MediaResult* mError = nullptr;
layers::KnowsCompositor* mKnowsCompositor = nullptr;
GMPCrashHelper* mCrashHelper = nullptr;
RefPtr<layers::KnowsCompositor> mKnowsCompositor;
RefPtr<GMPCrashHelper> mCrashHelper;
media::UseNullDecoder mUseNullDecoder;
media::NoWrapper mNoWrapper;
TrackInfo::TrackType mType = TrackInfo::kUndefinedTrack;
std::function<MediaEventProducer<TrackInfo::TrackType>*()>
mOnWaitingForKeyEvent;
MediaEventProducer<TrackInfo::TrackType>* mOnWaitingForKeyEvent = nullptr;
OptionSet mOptions = OptionSet(Option::Default);
media::VideoFrameRate mRate;
private:
void Set(DecoderDoctorDiagnostics* aDiagnostics) {
mDiagnostics = aDiagnostics;
}
void Set(layers::ImageContainer* aImageContainer) {
mImageContainer = aImageContainer;
}
@ -195,27 +153,9 @@ struct MOZ_STACK_CLASS CreateDecoderParams final {
}
}
void Set(TrackInfo::TrackType aType) { mType = aType; }
void Set(std::function<MediaEventProducer<TrackInfo::TrackType>*()>&&
aOnWaitingForKey) {
mOnWaitingForKeyEvent = std::move(aOnWaitingForKey);
}
void Set(const std::function<MediaEventProducer<TrackInfo::TrackType>*()>&
aOnWaitingForKey) {
void Set(MediaEventProducer<TrackInfo::TrackType>* aOnWaitingForKey) {
mOnWaitingForKeyEvent = aOnWaitingForKey;
}
void Set(const CreateDecoderParams& aParams) {
// Set all but mTrackInfo;
mImageContainer = aParams.mImageContainer;
mError = aParams.mError;
mKnowsCompositor = aParams.mKnowsCompositor;
mCrashHelper = aParams.mCrashHelper;
mUseNullDecoder = aParams.mUseNullDecoder;
mNoWrapper = aParams.mNoWrapper;
mType = aParams.mType;
mOnWaitingForKeyEvent = aParams.mOnWaitingForKeyEvent;
mOptions = aParams.mOptions;
mRate = aParams.mRate;
}
template <typename T1, typename T2, typename... Ts>
void Set(T1&& a1, T2&& a2, Ts&&... args) {
Set(std::forward<T1>(a1));
@ -234,6 +174,7 @@ struct MOZ_STACK_CLASS SupportDecoderParams final {
explicit SupportDecoderParams(const CreateDecoderParams& aParams)
: mConfig(aParams.mConfig),
mDiagnostics(aParams.mDiagnostics),
mError(aParams.mError),
mKnowsCompositor(aParams.mKnowsCompositor),
mUseNullDecoder(aParams.mUseNullDecoder),
@ -329,16 +270,13 @@ class PlatformDecoderModule {
SupportsColorDepth(videoInfo->mColorDepth, aDiagnostics);
}
typedef MozPromise<RefPtr<MediaDataDecoder>, MediaResult,
/* IsExclusive = */ true>
CreateDecoderPromise;
protected:
PlatformDecoderModule() = default;
virtual ~PlatformDecoderModule() = default;
friend class MediaChangeMonitor;
friend class PDMFactory;
friend class GpuDecoderModule;
friend class EMEDecoderModule;
friend class RemoteDecoderModule;
@ -352,11 +290,14 @@ class PlatformDecoderModule {
// Creates a Video decoder. The layers backend is passed in so that
// decoders can determine whether hardware accelerated decoding can be used.
// Asynchronous decoding of video should be done in runnables dispatched
// to aVideoTaskQueue. If the task queue isn't needed, the decoder should
// not hold a reference to it.
// On Windows the task queue's threads in have MSCOM initialized with
// COINIT_MULTITHREADED.
// Returns nullptr if the decoder can't be created.
// It is not safe to store a reference to aParams or aParams.mConfig as the
// object isn't guaranteed to live after the call.
// It is safe to store a reference to aConfig.
// This is called on the decode task queue.
// CreateVideoDecoder may need to make additional checks if the
// CreateDecoderParams argument is actually supported and return nullptr if
// not to allow for fallback PDMs to be tried.
@ -364,20 +305,19 @@ class PlatformDecoderModule {
const CreateDecoderParams& aParams) = 0;
// Creates an Audio decoder with the specified properties.
// Asynchronous decoding of audio should be done in runnables dispatched to
// aAudioTaskQueue. If the task queue isn't needed, the decoder should
// not hold a reference to it.
// Returns nullptr if the decoder can't be created.
// On Windows the task queue's threads in have MSCOM initialized with
// COINIT_MULTITHREADED.
// It is not safe to store a reference to aParams or aParams.mConfig as the
// object isn't guaranteed to live after the call.
// It is safe to store a reference to aConfig.
// This is called on the decode task queue.
// CreateAudioDecoder may need to make additional checks if the
// CreateDecoderParams argument is actually supported and return nullptr if
// not to allow for fallback PDMs to be tried.
virtual already_AddRefed<MediaDataDecoder> CreateAudioDecoder(
const CreateDecoderParams& aParams) = 0;
// Asychronously create a decoder.
virtual RefPtr<CreateDecoderPromise> AsyncCreateDecoder(
const CreateDecoderParams& aParams);
};
DDLoggedTypeDeclName(MediaDataDecoder);
@ -395,7 +335,10 @@ DDLoggedTypeDeclName(MediaDataDecoder);
// Don't block inside these functions, unless it's explicitly noted that you
// should (like in Flush()).
//
// Decoding is done asynchronously.
// Decoding is done asynchronously. Any async work can be done on the
// TaskQueue passed into the PlatformDecoderModules's Create*Decoder()
// function. This may not be necessary for platforms with async APIs
// for decoding.
class MediaDataDecoder : public DecoderDoctorLifeLogger<MediaDataDecoder> {
protected:
virtual ~MediaDataDecoder() = default;
@ -412,7 +355,7 @@ class MediaDataDecoder : public DecoderDoctorLifeLogger<MediaDataDecoder> {
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(MediaDataDecoder)
// Initialize the decoder. The decoder should be ready to decode once
// the promise resolves. The decoder should do any initialization here, rather
// promise resolves. The decoder should do any initialization here, rather
// than in its constructor or PlatformDecoderModule::Create*Decoder(),
// so that if the MediaFormatReader needs to shutdown during initialization,
// it can call Shutdown() to cancel this operation. Any initialization
@ -470,9 +413,6 @@ class MediaDataDecoder : public DecoderDoctorLifeLogger<MediaDataDecoder> {
// completed shutdown. The reader calls Flush() before calling Shutdown(). The
// reader will delete the decoder once the promise is resolved.
// The ShutdownPromise must only ever be resolved.
// Shutdown() may not be called if init hasn't been called first. It is
// possible under some circumstances for the decoder to be deleted without
// Init having been called first.
virtual RefPtr<ShutdownPromise> Shutdown() = 0;
// Called from the state machine task queue or main thread. Decoder needs to

Просмотреть файл

@ -50,7 +50,7 @@ class AOMDecoder : public MediaDataDecoder,
// AOM decoder state
aom_codec_ctx_t mCodec;
const VideoInfo mInfo;
const VideoInfo& mInfo;
};
} // namespace mozilla

Просмотреть файл

@ -124,7 +124,7 @@ bool AgnosticDecoderModule::Supports(
already_AddRefed<MediaDataDecoder> AgnosticDecoderModule::CreateVideoDecoder(
const CreateDecoderParams& aParams) {
if (!Supports(SupportDecoderParams(aParams), nullptr /* diagnostic */)) {
if (!Supports(SupportDecoderParams(aParams), aParams.mDiagnostics)) {
return nullptr;
}
RefPtr<MediaDataDecoder> m;
@ -155,7 +155,7 @@ already_AddRefed<MediaDataDecoder> AgnosticDecoderModule::CreateVideoDecoder(
already_AddRefed<MediaDataDecoder> AgnosticDecoderModule::CreateAudioDecoder(
const CreateDecoderParams& aParams) {
if (!Supports(SupportDecoderParams(aParams), nullptr /* diagnostic */)) {
if (!Supports(SupportDecoderParams(aParams), aParams.mDiagnostics)) {
return nullptr;
}
RefPtr<MediaDataDecoder> m;

Просмотреть файл

@ -40,7 +40,7 @@ class DAV1DDecoder : public MediaDataDecoder,
Dav1dContext* mContext = nullptr;
const VideoInfo mInfo;
const VideoInfo& mInfo;
const RefPtr<TaskQueue> mTaskQueue;
const RefPtr<layers::ImageContainer> mImageContainer;
const RefPtr<layers::KnowsCompositor> mImageAllocator;

Просмотреть файл

@ -39,6 +39,7 @@ OpusDataDecoder::OpusDataDecoder(const CreateDecoderParams& aParams)
CreateDecoderParams::Option::DefaultPlaybackDeviceMono)) {}
OpusDataDecoder::~OpusDataDecoder() {
MOZ_ASSERT(mThread->IsOnCurrentThread());
if (mOpusDecoder) {
opus_multistream_decoder_destroy(mOpusDecoder);
mOpusDecoder = nullptr;
@ -46,8 +47,7 @@ OpusDataDecoder::~OpusDataDecoder() {
}
RefPtr<ShutdownPromise> OpusDataDecoder::Shutdown() {
// mThread may not be set if Init hasn't been called first.
MOZ_ASSERT(!mThread || mThread->IsOnCurrentThread());
MOZ_ASSERT(mThread->IsOnCurrentThread());
return ShutdownPromise::CreateAndResolve(true, __func__);
}

Просмотреть файл

@ -47,7 +47,7 @@ class OpusDataDecoder : public MediaDataDecoder,
private:
nsresult DecodeHeader(const unsigned char* aData, size_t aLength);
const AudioInfo mInfo;
const AudioInfo& mInfo;
nsCOMPtr<nsISerialEventTarget> mThread;
// Opus decoder state

Просмотреть файл

@ -51,7 +51,7 @@ class TheoraDecoder : public MediaDataDecoder,
th_dec_ctx* mTheoraDecoderContext;
int mPacketCount;
const VideoInfo mInfo;
const VideoInfo& mInfo;
};
} // namespace mozilla

Просмотреть файл

@ -209,7 +209,7 @@ class VPXDecoder : public MediaDataDecoder,
// VPx alpha decoder state
vpx_codec_ctx_t mVPXAlpha;
const VideoInfo mInfo;
const VideoInfo& mInfo;
const Codec mCodec;
const bool mLowLatency;

Просмотреть файл

@ -42,6 +42,7 @@ VorbisDataDecoder::VorbisDataDecoder(const CreateDecoderParams& aParams)
}
VorbisDataDecoder::~VorbisDataDecoder() {
MOZ_ASSERT(mThread->IsOnCurrentThread());
vorbis_block_clear(&mVorbisBlock);
vorbis_dsp_clear(&mVorbisDsp);
vorbis_info_clear(&mVorbisInfo);
@ -49,8 +50,7 @@ VorbisDataDecoder::~VorbisDataDecoder() {
}
RefPtr<ShutdownPromise> VorbisDataDecoder::Shutdown() {
// mThread may not be set if Init hasn't been called first.
MOZ_ASSERT(!mThread || mThread->IsOnCurrentThread());
MOZ_ASSERT(mThread->IsOnCurrentThread());
return ShutdownPromise::CreateAndResolve(true, __func__);
}

Просмотреть файл

@ -42,7 +42,7 @@ class VorbisDataDecoder : public MediaDataDecoder,
private:
nsresult DecodeHeader(const unsigned char* aData, size_t aLength);
const AudioInfo mInfo;
const AudioInfo& mInfo;
nsCOMPtr<nsISerialEventTarget> mThread;
// Vorbis decoder state

Просмотреть файл

@ -47,8 +47,7 @@ WaveDataDecoder::WaveDataDecoder(const CreateDecoderParams& aParams)
: mInfo(aParams.AudioConfig()) {}
RefPtr<ShutdownPromise> WaveDataDecoder::Shutdown() {
// mThread may not be set if Init hasn't been called first.
MOZ_ASSERT(!mThread || mThread->IsOnCurrentThread());
MOZ_ASSERT(mThread->IsOnCurrentThread());
return ShutdownPromise::CreateAndResolve(true, __func__);
}

Просмотреть файл

@ -31,7 +31,7 @@ class WaveDataDecoder : public MediaDataDecoder,
}
private:
const AudioInfo mInfo;
const AudioInfo& mInfo;
nsCOMPtr<nsISerialEventTarget> mThread;
};

Просмотреть файл

@ -14,11 +14,11 @@
#include "DecryptThroughputLimit.h"
#include "GMPDecoderModule.h"
#include "GMPService.h"
#include "GMPVideoDecoder.h"
#include "MP4Decoder.h"
#include "MediaInfo.h"
#include "PDMFactory.h"
#include "mozilla/CDMProxy.h"
#include "GMPVideoDecoder.h"
#include "MP4Decoder.h"
#include "mozilla/EMEUtils.h"
#include "mozilla/StaticPrefs_media.h"
#include "mozilla/UniquePtr.h"
@ -74,8 +74,7 @@ class EMEDecryptor : public MediaDataDecoder,
public:
EMEDecryptor(MediaDataDecoder* aDecoder, CDMProxy* aProxy,
TrackInfo::TrackType aType,
const std::function<MediaEventProducer<TrackInfo::TrackType>*()>&
aOnWaitingForKey,
MediaEventProducer<TrackInfo::TrackType>* aOnWaitingForKey,
UniquePtr<ADTSSampleConverter> aConverter = nullptr)
: mDecoder(aDecoder),
mProxy(aProxy),
@ -243,8 +242,7 @@ class EMEDecryptor : public MediaDataDecoder,
}
RefPtr<ShutdownPromise> Shutdown() override {
// mThread may not be set if Init hasn't been called first.
MOZ_ASSERT(!mThread || mThread->IsOnCurrentThread());
MOZ_ASSERT(mThread->IsOnCurrentThread());
MOZ_ASSERT(!mIsShutdown);
mIsShutdown = true;
mSamplesWaitingForKey->BreakCycles();
@ -376,47 +374,37 @@ static already_AddRefed<MediaDataDecoderProxy> CreateDecoderWrapper(
return decoder.forget();
}
RefPtr<EMEDecoderModule::CreateDecoderPromise>
EMEDecoderModule::AsyncCreateDecoder(const CreateDecoderParams& aParams) {
already_AddRefed<MediaDataDecoder> EMEDecoderModule::CreateVideoDecoder(
const CreateDecoderParams& aParams) {
MOZ_ASSERT(aParams.mConfig.mCrypto.IsEncrypted());
MOZ_ASSERT(mPDM);
if (aParams.mConfig.IsVideo()) {
if (StaticPrefs::media_eme_video_blank()) {
EME_LOG(
"EMEDecoderModule::CreateVideoDecoder() creating a blank decoder.");
EME_LOG("EMEDecoderModule::CreateVideoDecoder() creating a blank decoder.");
RefPtr<PlatformDecoderModule> m(BlankDecoderModule::Create());
RefPtr<MediaDataDecoder> decoder = m->CreateVideoDecoder(aParams);
return EMEDecoderModule::CreateDecoderPromise::CreateAndResolve(decoder,
__func__);
return m->CreateVideoDecoder(aParams);
}
if (SupportsMimeType(aParams.mConfig.mMimeType, nullptr)) {
// GMP decodes. Assume that means it can decrypt too.
return EMEDecoderModule::CreateDecoderPromise::CreateAndResolve(
CreateDecoderWrapper(mProxy, aParams), __func__);
RefPtr<MediaDataDecoderProxy> wrapper =
CreateDecoderWrapper(mProxy, aParams);
return wrapper.forget();
}
RefPtr<EMEDecoderModule::CreateDecoderPromise> p =
mPDM->CreateDecoder(aParams)->Then(
GetCurrentSerialEventTarget(), __func__,
[self = RefPtr{this},
params = CreateDecoderParamsForAsync(aParams)](
RefPtr<MediaDataDecoder>&& aDecoder) {
RefPtr<MediaDataDecoder> emeDecoder(
new EMEDecryptor(aDecoder, self->mProxy, params.mType,
params.mOnWaitingForKeyEvent));
return EMEDecoderModule::CreateDecoderPromise::CreateAndResolve(
emeDecoder, __func__);
},
[](const MediaResult& aError) {
return EMEDecoderModule::CreateDecoderPromise::CreateAndReject(
aError, __func__);
});
return p;
MOZ_ASSERT(mPDM);
RefPtr<MediaDataDecoder> decoder(mPDM->CreateDecoder(aParams));
if (!decoder) {
return nullptr;
}
MOZ_ASSERT(aParams.mConfig.IsAudio());
RefPtr<MediaDataDecoder> emeDecoder(new EMEDecryptor(
decoder, mProxy, aParams.mType, aParams.mOnWaitingForKeyEvent));
return emeDecoder.forget();
}
already_AddRefed<MediaDataDecoder> EMEDecoderModule::CreateAudioDecoder(
const CreateDecoderParams& aParams) {
MOZ_ASSERT(aParams.mConfig.mCrypto.IsEncrypted());
// We don't support using the GMP to decode audio.
MOZ_ASSERT(!SupportsMimeType(aParams.mConfig.mMimeType, nullptr));
@ -425,9 +413,7 @@ EMEDecoderModule::AsyncCreateDecoder(const CreateDecoderParams& aParams) {
if (StaticPrefs::media_eme_audio_blank()) {
EME_LOG("EMEDecoderModule::CreateAudioDecoder() creating a blank decoder.");
RefPtr<PlatformDecoderModule> m(BlankDecoderModule::Create());
RefPtr<MediaDataDecoder> decoder = m->CreateAudioDecoder(aParams);
return EMEDecoderModule::CreateDecoderPromise::CreateAndResolve(decoder,
__func__);
return m->CreateAudioDecoder(aParams);
}
UniquePtr<ADTSSampleConverter> converter = nullptr;
@ -437,23 +423,15 @@ EMEDecoderModule::AsyncCreateDecoder(const CreateDecoderParams& aParams) {
converter = MakeUnique<ADTSSampleConverter>(aParams.AudioConfig());
}
RefPtr<EMEDecoderModule::CreateDecoderPromise> p =
mPDM->CreateDecoder(aParams)->Then(
GetCurrentSerialEventTarget(), __func__,
[self = RefPtr{this}, params = CreateDecoderParamsForAsync(aParams),
converter = std::move(converter)](
RefPtr<MediaDataDecoder>&& aDecoder) mutable {
RefPtr<MediaDataDecoder> emeDecoder(new EMEDecryptor(
aDecoder, self->mProxy, params.mType,
params.mOnWaitingForKeyEvent, std::move(converter)));
return EMEDecoderModule::CreateDecoderPromise::CreateAndResolve(
emeDecoder, __func__);
},
[](const MediaResult& aError) {
return EMEDecoderModule::CreateDecoderPromise::CreateAndReject(
aError, __func__);
});
return p;
RefPtr<MediaDataDecoder> decoder(mPDM->CreateDecoder(aParams));
if (!decoder) {
return nullptr;
}
RefPtr<MediaDataDecoder> emeDecoder(
new EMEDecryptor(decoder, mProxy, aParams.mType,
aParams.mOnWaitingForKeyEvent, std::move(converter)));
return emeDecoder.forget();
}
bool EMEDecoderModule::SupportsMimeType(

Просмотреть файл

@ -21,20 +21,13 @@ class EMEDecoderModule : public PlatformDecoderModule {
EMEDecoderModule(CDMProxy* aProxy, PDMFactory* aPDM);
protected:
RefPtr<CreateDecoderPromise> AsyncCreateDecoder(
// Decode thread.
already_AddRefed<MediaDataDecoder> CreateVideoDecoder(
const CreateDecoderParams& aParams) override;
// Decode thread.
already_AddRefed<MediaDataDecoder> CreateVideoDecoder(
const CreateDecoderParams& aParams) override {
MOZ_CRASH("Not used");
}
// Decode thread.
already_AddRefed<MediaDataDecoder> CreateAudioDecoder(
const CreateDecoderParams& aParams) override {
MOZ_CRASH("Not used");
}
const CreateDecoderParams& aParams) override;
bool SupportsMimeType(const nsACString& aMimeType,
DecoderDoctorDiagnostics* aDiagnostics) const override;

Просмотреть файл

@ -5,7 +5,6 @@
* You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "SamplesWaitingForKey.h"
#include "MediaData.h"
#include "MediaEventSource.h"
#include "mozilla/CDMCaps.h"
@ -16,12 +15,11 @@ namespace mozilla {
SamplesWaitingForKey::SamplesWaitingForKey(
CDMProxy* aProxy, TrackInfo::TrackType aType,
const std::function<MediaEventProducer<TrackInfo::TrackType>*()>&
aOnWaitingForKeyEvent)
MediaEventProducer<TrackInfo::TrackType>* aOnWaitingForKey)
: mMutex("SamplesWaitingForKey"),
mProxy(aProxy),
mType(aType),
mOnWaitingForKeyEvent(aOnWaitingForKeyEvent) {}
mOnWaitingForKeyEvent(aOnWaitingForKey) {}
SamplesWaitingForKey::~SamplesWaitingForKey() { Flush(); }
@ -42,8 +40,8 @@ SamplesWaitingForKey::WaitIfKeyNotUsable(MediaRawData* aSample) {
MutexAutoLock lock(mMutex);
mSamples.AppendElement(std::move(entry));
}
if (mOnWaitingForKeyEvent && mOnWaitingForKeyEvent()) {
mOnWaitingForKeyEvent()->Notify(mType);
if (mOnWaitingForKeyEvent) {
mOnWaitingForKeyEvent->Notify(mType);
}
caps->NotifyWhenKeyIdUsable(aSample->mCrypto.mKeyId, this);
return p;

Просмотреть файл

@ -7,8 +7,6 @@
#ifndef SamplesWaitingForKey_h_
#define SamplesWaitingForKey_h_
#include <functional>
#include "MediaInfo.h"
#include "mozilla/MozPromise.h"
#include "mozilla/Mutex.h"
@ -34,8 +32,7 @@ class SamplesWaitingForKey {
SamplesWaitingForKey(
CDMProxy* aProxy, TrackInfo::TrackType aType,
const std::function<MediaEventProducer<TrackInfo::TrackType>*()>&
aOnWaitingForKeyEvent);
MediaEventProducer<TrackInfo::TrackType>* aOnWaitingForKey);
// Returns a promise that will be resolved if or when a key for decoding the
// sample becomes usable.
@ -59,8 +56,7 @@ class SamplesWaitingForKey {
};
nsTArray<SampleEntry> mSamples;
const TrackInfo::TrackType mType;
const std::function<MediaEventProducer<TrackInfo::TrackType>*()>
mOnWaitingForKeyEvent;
MediaEventProducer<TrackInfo::TrackType>* const mOnWaitingForKeyEvent;
};
} // namespace mozilla

Просмотреть файл

@ -33,6 +33,7 @@ static bool IsOnGMPThread() {
GMPVideoDecoderParams::GMPVideoDecoderParams(const CreateDecoderParams& aParams)
: mConfig(aParams.VideoConfig()),
mImageContainer(aParams.mImageContainer),
mLayersBackend(aParams.GetLayersBackend()),
mCrashHelper(aParams.mCrashHelper) {}
void GMPVideoDecoder::Decoded(GMPVideoi420Frame* aDecodedFrame) {

Просмотреть файл

@ -16,12 +16,13 @@
namespace mozilla {
struct MOZ_STACK_CLASS GMPVideoDecoderParams {
struct GMPVideoDecoderParams {
explicit GMPVideoDecoderParams(const CreateDecoderParams& aParams);
const VideoInfo& mConfig;
layers::ImageContainer* mImageContainer;
GMPCrashHelper* mCrashHelper;
layers::LayersBackend mLayersBackend;
RefPtr<GMPCrashHelper> mCrashHelper;
};
DDLoggedTypeDeclNameAndBase(GMPVideoDecoder, MediaDataDecoder);

Просмотреть файл

@ -2,20 +2,20 @@
* 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 <jni.h>
#include "mozilla/java/HardwareCodecCapabilityUtilsWrappers.h"
#include "MediaInfo.h"
#include "OpusDecoder.h"
#include "RemoteDataDecoder.h"
#include "TheoraDecoder.h"
#include "VPXDecoder.h"
#include "VorbisDecoder.h"
#include "mozilla/StaticPrefs_media.h"
#include "mozilla/java/HardwareCodecCapabilityUtilsWrappers.h"
#include "nsIGfxInfo.h"
#include "nsPromiseFlatString.h"
#include "prlog.h"
#include <jni.h>
#undef LOG
#define LOG(arg, ...) \
MOZ_LOG( \

Просмотреть файл

@ -47,10 +47,7 @@ class RemoteDataDecoder : public MediaDataDecoder,
void ReturnDecodedData();
void DrainComplete();
void Error(const MediaResult& aError);
void AssertOnThread() const {
// mThread may not be set if Init hasn't been called first.
MOZ_ASSERT(!mThread || mThread->IsOnCurrentThread());
}
void AssertOnThread() const { MOZ_ASSERT(mThread->IsOnCurrentThread()); }
enum class State { DRAINED, DRAINABLE, DRAINING, SHUTDOWN };
void SetState(State aState) {

Просмотреть файл

@ -91,15 +91,13 @@ RefPtr<MediaDataDecoder::DecodePromise> AppleATDecoder::Drain() {
}
RefPtr<ShutdownPromise> AppleATDecoder::Shutdown() {
// mThread may not be set if Init hasn't been called first.
MOZ_ASSERT(!mThread || mThread->IsOnCurrentThread());
MOZ_ASSERT(mThread->IsOnCurrentThread());
ProcessShutdown();
return ShutdownPromise::CreateAndResolve(true, __func__);
}
void AppleATDecoder::ProcessShutdown() {
// mThread may not be set if Init hasn't been called first.
MOZ_ASSERT(!mThread || mThread->IsOnCurrentThread());
MOZ_ASSERT(mThread->IsOnCurrentThread());
if (mStream) {
OSStatus rv = AudioFileStreamClose(mStream);

Просмотреть файл

@ -35,7 +35,7 @@ class AppleATDecoder : public MediaDataDecoder,
}
// Callbacks also need access to the config.
const AudioInfo mConfig;
const AudioInfo& mConfig;
// Use to extract magic cookie for HE-AAC detection.
nsTArray<uint8_t> mMagicCookie;

Просмотреть файл

@ -54,7 +54,7 @@ nsresult AppleDecoderModule::Startup() {
already_AddRefed<MediaDataDecoder> AppleDecoderModule::CreateVideoDecoder(
const CreateDecoderParams& aParams) {
if (!Supports(SupportDecoderParams(aParams), nullptr /* diagnostics */)) {
if (!Supports(SupportDecoderParams(aParams), aParams.mDiagnostics)) {
return nullptr;
}
RefPtr<MediaDataDecoder> decoder;
@ -67,7 +67,7 @@ already_AddRefed<MediaDataDecoder> AppleDecoderModule::CreateVideoDecoder(
already_AddRefed<MediaDataDecoder> AppleDecoderModule::CreateAudioDecoder(
const CreateDecoderParams& aParams) {
if (!Supports(SupportDecoderParams(aParams), nullptr /* diagnostics */)) {
if (!Supports(SupportDecoderParams(aParams), aParams.mDiagnostics)) {
return nullptr;
}
RefPtr<MediaDataDecoder> decoder = new AppleATDecoder(aParams.AudioConfig());

Просмотреть файл

@ -32,7 +32,7 @@ class FFmpegDecoderModule : public PlatformDecoderModule {
already_AddRefed<MediaDataDecoder> CreateVideoDecoder(
const CreateDecoderParams& aParams) override {
if (!Supports(SupportDecoderParams(aParams), nullptr)) {
if (!Supports(SupportDecoderParams(aParams), aParams.mDiagnostics)) {
return nullptr;
}
RefPtr<MediaDataDecoder> decoder = new FFmpegVideoDecoder<V>(
@ -46,7 +46,7 @@ class FFmpegDecoderModule : public PlatformDecoderModule {
already_AddRefed<MediaDataDecoder> CreateAudioDecoder(
const CreateDecoderParams& aParams) override {
if (!Supports(SupportDecoderParams(aParams), nullptr)) {
if (!Supports(SupportDecoderParams(aParams), aParams.mDiagnostics)) {
return nullptr;
}
RefPtr<MediaDataDecoder> decoder =

Просмотреть файл

@ -39,7 +39,6 @@ UNIFIED_SOURCES += [
"AllocationPolicy.cpp",
"PDMFactory.cpp",
"PEMFactory.cpp",
"PlatformDecoderModule.cpp",
"wrappers/AudioTrimmer.cpp",
"wrappers/MediaChangeMonitor.cpp",
"wrappers/MediaDataDecoderProxy.cpp",

Просмотреть файл

@ -195,8 +195,7 @@ RefPtr<MediaDataDecoder::DecodePromise> OmxDataDecoder::Drain() {
RefPtr<ShutdownPromise> OmxDataDecoder::Shutdown() {
LOG("");
// mThread may not be set if Init hasn't been called first.
MOZ_ASSERT(!mThread || mThread->IsOnCurrentThread());
MOZ_ASSERT(mThread->IsOnCurrentThread());
mShuttingDown = true;

Просмотреть файл

@ -56,8 +56,8 @@ RefPtr<MediaDataDecoder::DecodePromise> AudioTrimmer::Drain() {
}
RefPtr<ShutdownPromise> AudioTrimmer::Shutdown() {
// mThread may not be set if Init hasn't been called first.
MOZ_ASSERT(!mThread || mThread->IsOnCurrentThread());
MOZ_ASSERT(mThread->IsOnCurrentThread(),
"We're not on the thread we were first initialized on");
return mDecoder->Shutdown();
}

Просмотреть файл

@ -7,6 +7,7 @@
#include "MediaChangeMonitor.h"
#include "AnnexB.h"
#include "DecoderDoctorDiagnostics.h"
#include "H264.h"
#include "ImageContainer.h"
#include "MP4Decoder.h"
@ -244,54 +245,32 @@ class VPXChangeMonitor : public MediaChangeMonitor::CodecChangeMonitor {
RefPtr<TrackInfoSharedPtr> mTrackInfo;
};
MediaChangeMonitor::MediaChangeMonitor(
PlatformDecoderModule* aPDM,
UniquePtr<CodecChangeMonitor>&& aCodecChangeMonitor,
MediaDataDecoder* aDecoder, const CreateDecoderParams& aParams)
: mChangeMonitor(std::move(aCodecChangeMonitor)),
mPDM(aPDM),
MediaChangeMonitor::MediaChangeMonitor(PlatformDecoderModule* aPDM,
const CreateDecoderParams& aParams)
: mPDM(aPDM),
mCurrentConfig(aParams.VideoConfig()),
mDecoder(aDecoder),
mParams(aParams) {}
/* static */
RefPtr<PlatformDecoderModule::CreateDecoderPromise> MediaChangeMonitor::Create(
PlatformDecoderModule* aPDM, const CreateDecoderParams& aParams) {
UniquePtr<CodecChangeMonitor> changeMonitor;
const VideoInfo& currentConfig = aParams.VideoConfig();
if (VPXDecoder::IsVPX(currentConfig.mMimeType)) {
changeMonitor = MakeUnique<VPXChangeMonitor>(currentConfig);
mKnowsCompositor(aParams.mKnowsCompositor),
mImageContainer(aParams.mImageContainer),
mDecoder(nullptr),
mGMPCrashHelper(aParams.mCrashHelper),
mLastError(NS_OK),
mErrorIfNoInitializationData(aParams.mOptions.contains(
CreateDecoderParams::Option::ErrorIfNoInitializationData)),
mType(aParams.mType),
mOnWaitingForKeyEvent(aParams.mOnWaitingForKeyEvent),
mDecoderOptions(aParams.mOptions),
mRate(aParams.mRate) {
mInConstructor = true;
if (VPXDecoder::IsVPX(mCurrentConfig.mMimeType)) {
mChangeMonitor = MakeUnique<VPXChangeMonitor>(mCurrentConfig);
} else {
MOZ_ASSERT(MP4Decoder::IsH264(currentConfig.mMimeType));
changeMonitor = MakeUnique<H264ChangeMonitor>(
currentConfig, aParams.mOptions.contains(
CreateDecoderParams::Option::FullH264Parsing));
MOZ_ASSERT(MP4Decoder::IsH264(mCurrentConfig.mMimeType));
mChangeMonitor = MakeUnique<H264ChangeMonitor>(
mCurrentConfig,
mDecoderOptions.contains(CreateDecoderParams::Option::FullH264Parsing));
}
if (!changeMonitor->CanBeInstantiated()) {
// nothing found yet, will try again later
return PlatformDecoderModule::CreateDecoderPromise::CreateAndResolve(
new MediaChangeMonitor(aPDM, std::move(changeMonitor), nullptr,
aParams),
__func__);
}
RefPtr<PlatformDecoderModule::CreateDecoderPromise> p =
aPDM->AsyncCreateDecoder(aParams)->Then(
GetCurrentSerialEventTarget(), __func__,
[params = CreateDecoderParamsForAsync(aParams), pdm = RefPtr{aPDM},
changeMonitor = std::move(changeMonitor)](
RefPtr<MediaDataDecoder>&& aDecoder) mutable {
RefPtr<MediaDataDecoder> decoder = new MediaChangeMonitor(
pdm, std::move(changeMonitor), aDecoder, params);
return PlatformDecoderModule::CreateDecoderPromise::
CreateAndResolve(decoder, __func__);
},
[](MediaResult aError) {
return PlatformDecoderModule::CreateDecoderPromise::CreateAndReject(
aError, __func__);
});
return p;
mLastError = CreateDecoder(aParams.mDiagnostics);
mInConstructor = false;
}
MediaChangeMonitor::~MediaChangeMonitor() = default;
@ -326,8 +305,7 @@ RefPtr<MediaDataDecoder::InitPromise> MediaChangeMonitor::Init() {
RefPtr<MediaDataDecoder::DecodePromise> MediaChangeMonitor::Decode(
MediaRawData* aSample) {
AssertOnThread();
MOZ_RELEASE_ASSERT(mFlushPromise.IsEmpty(),
"Flush operation didn't complete");
MOZ_RELEASE_ASSERT(mFlushPromise.IsEmpty(), "Flush operatin didn't complete");
MOZ_RELEASE_ASSERT(
!mDecodePromiseRequest.Exists() && !mInitPromiseRequest.Exists(),
@ -337,8 +315,7 @@ RefPtr<MediaDataDecoder::DecodePromise> MediaChangeMonitor::Decode(
if (rv == NS_ERROR_NOT_INITIALIZED) {
// We are missing the required init data to create the decoder.
if (mParams.mOptions.contains(
CreateDecoderParams::Option::ErrorIfNoInitializationData)) {
if (mErrorIfNoInitializationData) {
// This frame can't be decoded and should be treated as an error.
return DecodePromise::CreateAndReject(rv, __func__);
}
@ -381,8 +358,8 @@ RefPtr<MediaDataDecoder::FlushPromise> MediaChangeMonitor::Flush() {
/*
When we detect a change of content in the byte stream, we first drain the
current decoder (1), flush (2), shut it down (3) create a new decoder (4)
and initialize it (5). It is possible for MediaChangeMonitor::Flush to be
current decoder (1), flush (2), shut it down (3) create a new decoder and
initialize it (4). It is possible for MediaChangeMonitor::Flush to be
called during any of those times. If during (1):
- mDrainRequest will not be empty.
- The old decoder can still be used, with the current extradata as
@ -399,17 +376,12 @@ RefPtr<MediaDataDecoder::FlushPromise> MediaChangeMonitor::Flush() {
- The old decoder is no longer referenced by the MediaChangeMonitor.
If during (4):
- mDecoderRequest won't be empty.
- mDecoder is not set. Steps will continue to (5) to set and initialize it
If during (5):
- mInitPromiseRequest won't be empty.
- mDecoder is set but not usable yet.
*/
if (mDrainRequest.Exists() || mFlushRequest.Exists() ||
mShutdownRequest.Exists() || mDecoderRequest.Exists() ||
mInitPromiseRequest.Exists()) {
mShutdownRequest.Exists() || mInitPromiseRequest.Exists()) {
// We let the current decoder complete and will resume after.
RefPtr<FlushPromise> p = mFlushPromise.Ensure(__func__);
return p;
@ -483,48 +455,49 @@ void MediaChangeMonitor::SetSeekThreshold(const media::TimeUnit& aTime) {
}
}
RefPtr<MediaChangeMonitor::CreateDecoderPromise>
MediaChangeMonitor::CreateDecoder() {
MOZ_ASSERT(mThread && mThread->IsOnCurrentThread());
MediaResult MediaChangeMonitor::CreateDecoder(
DecoderDoctorDiagnostics* aDiagnostics) {
// This is the only one of two methods to run outside the init thread when
// called from the constructor.
MOZ_ASSERT(mInConstructor || (mThread && mThread->IsOnCurrentThread()));
if (!mChangeMonitor->CanBeInstantiated()) {
// nothing found yet, will try again later
return NS_ERROR_NOT_INITIALIZED;
}
mCurrentConfig = *mChangeMonitor->Config().GetAsVideoInfo();
RefPtr<CreateDecoderPromise> p =
mPDM->AsyncCreateDecoder({mCurrentConfig, mParams})
->Then(
GetCurrentSerialEventTarget(), __func__,
[self = RefPtr{this}, this](RefPtr<MediaDataDecoder>&& aDecoder) {
mDecoder = std::move(aDecoder);
DDLINKCHILD("decoder", mDecoder.get());
return CreateDecoderPromise::CreateAndResolve(true, __func__);
},
[self = RefPtr{this}, this](const MediaResult& aError) {
// We failed to create a decoder with the existing PDM; attempt
// once again with a PDMFactory.
MediaResult error = NS_OK;
mDecoder = mPDM->CreateVideoDecoder(
{mCurrentConfig, aDiagnostics, mImageContainer, mKnowsCompositor,
mGMPCrashHelper, mType, mOnWaitingForKeyEvent, mDecoderOptions, mRate,
&error});
if (!mDecoder) {
// We failed to create a decoder with the existing PDM; attempt once again
// with a PDMFactory.
RefPtr<PDMFactory> factory = new PDMFactory();
RefPtr<CreateDecoderPromise> p =
factory
->CreateDecoder({mCurrentConfig, mParams,
CreateDecoderParams::NoWrapper(true)})
->Then(
GetCurrentSerialEventTarget(), __func__,
[self, this](RefPtr<MediaDataDecoder>&& aDecoder) {
mDecoder = std::move(aDecoder);
mDecoder = factory->CreateDecoder(
{mCurrentConfig, aDiagnostics, mImageContainer, mKnowsCompositor,
mGMPCrashHelper, mType, mOnWaitingForKeyEvent, mDecoderOptions, mRate,
&error, CreateDecoderParams::NoWrapper(true)});
if (!mDecoder) {
if (NS_FAILED(error)) {
// The decoder supports CreateDecoderParam::mError, returns the value.
return error;
}
return MediaResult(NS_ERROR_DOM_MEDIA_FATAL_ERR,
RESULT_DETAIL("Unable to create decoder"));
}
}
DDLINKCHILD("decoder", mDecoder.get());
return CreateDecoderPromise::CreateAndResolve(
true, __func__);
},
[self](const MediaResult& aError) {
return CreateDecoderPromise::CreateAndReject(
aError, __func__);
});
return p;
});
mDecoderInitialized = false;
mNeedKeyframe = true;
return p;
return NS_OK;
}
MediaResult MediaChangeMonitor::CreateDecoderAndInit(MediaRawData* aSample) {
@ -533,16 +506,11 @@ MediaResult MediaChangeMonitor::CreateDecoderAndInit(MediaRawData* aSample) {
return rv;
}
if (!mChangeMonitor->CanBeInstantiated()) {
// Nothing found yet, will try again later.
return NS_ERROR_NOT_INITIALIZED;
}
rv = CreateDecoder(/* DecoderDoctorDiagnostics* */ nullptr);
CreateDecoder()
->Then(
GetCurrentSerialEventTarget(), __func__,
[self = RefPtr{this}, this, sample = RefPtr{aSample}] {
mDecoderRequest.Complete();
if (NS_SUCCEEDED(rv)) {
RefPtr<MediaChangeMonitor> self = this;
RefPtr<MediaRawData> sample = aSample;
mDecoder->Init()
->Then(
GetCurrentSerialEventTarget(), __func__,
@ -572,25 +540,13 @@ MediaResult MediaChangeMonitor::CreateDecoderAndInit(MediaRawData* aSample) {
mDecodePromise.Reject(
MediaResult(
NS_ERROR_DOM_MEDIA_FATAL_ERR,
RESULT_DETAIL("Unable to initialize decoder")),
RESULT_DETAIL("Unable to initialize H264 decoder")),
__func__);
})
->Track(mInitPromiseRequest);
},
[self = RefPtr{this}, this](const MediaResult& aError) {
mDecoderRequest.Complete();
if (!mFlushPromise.IsEmpty()) {
// A Flush is pending, abort the current operation.
mFlushPromise.Reject(aError, __func__);
return;
}
mDecodePromise.Reject(
MediaResult(NS_ERROR_DOM_MEDIA_FATAL_ERR,
RESULT_DETAIL("Unable to create decoder")),
__func__);
})
->Track(mDecoderRequest);
return NS_ERROR_DOM_MEDIA_INITIALIZING_DECODER;
}
return rv;
}
bool MediaChangeMonitor::CanRecycleDecoder() const {

Просмотреть файл

@ -14,6 +14,8 @@
namespace mozilla {
class DecoderDoctorDiagnostics;
DDLoggedTypeDeclNameAndBase(MediaChangeMonitor, MediaDataDecoder);
// MediaChangeMonitor is a MediaDataDecoder wrapper used to ensure that
@ -27,8 +29,9 @@ DDLoggedTypeDeclNameAndBase(MediaChangeMonitor, MediaDataDecoder);
class MediaChangeMonitor : public MediaDataDecoder,
public DecoderDoctorLifeLogger<MediaChangeMonitor> {
public:
static RefPtr<PlatformDecoderModule::CreateDecoderPromise> Create(
PlatformDecoderModule* aPDM, const CreateDecoderParams& aParams);
MediaChangeMonitor(PlatformDecoderModule* aPDM,
const CreateDecoderParams& aParams);
virtual ~MediaChangeMonitor();
RefPtr<InitPromise> Init() override;
RefPtr<DecodePromise> Decode(MediaRawData* aSample) override;
@ -57,6 +60,7 @@ class MediaChangeMonitor : public MediaDataDecoder,
// Default so no conversion is performed.
return ConversionRequired::kNeedNone;
}
MediaResult GetLastError() const { return mLastError; }
class CodecChangeMonitor {
public:
@ -70,25 +74,16 @@ class MediaChangeMonitor : public MediaDataDecoder,
};
private:
MediaChangeMonitor(PlatformDecoderModule* aPDM,
UniquePtr<CodecChangeMonitor>&& aCodecChangeMonitor,
MediaDataDecoder* aDecoder,
const CreateDecoderParams& aParams);
virtual ~MediaChangeMonitor();
UniquePtr<CodecChangeMonitor> mChangeMonitor;
void AssertOnThread() const {
// mThread may not be set if Init hasn't been called first.
MOZ_ASSERT(!mThread || mThread->IsOnCurrentThread());
}
void AssertOnThread() const { MOZ_ASSERT(mThread->IsOnCurrentThread()); }
bool CanRecycleDecoder() const;
typedef MozPromise<bool, MediaResult, true /* exclusive */>
CreateDecoderPromise;
// 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.
RefPtr<CreateDecoderPromise> CreateDecoder();
MediaResult CreateDecoder(DecoderDoctorDiagnostics* aDiagnostics);
MediaResult CreateDecoderAndInit(MediaRawData* aSample);
MediaResult CheckForChange(MediaRawData* aSample);
@ -97,12 +92,12 @@ class MediaChangeMonitor : public MediaDataDecoder,
void FlushThenShutdownDecoder(MediaRawData* aPendingSample);
RefPtr<ShutdownPromise> ShutdownDecoder();
UniquePtr<CodecChangeMonitor> mChangeMonitor;
RefPtr<PlatformDecoderModule> mPDM;
VideoInfo mCurrentConfig;
RefPtr<layers::KnowsCompositor> mKnowsCompositor;
RefPtr<layers::ImageContainer> mImageContainer;
nsCOMPtr<nsISerialEventTarget> mThread;
RefPtr<MediaDataDecoder> mDecoder;
MozPromiseRequestHolder<CreateDecoderPromise> mDecoderRequest;
MozPromiseRequestHolder<InitPromise> mInitPromiseRequest;
MozPromiseHolder<InitPromise> mInitPromise;
MozPromiseRequestHolder<DecodePromise> mDecodePromiseRequest;
@ -114,11 +109,19 @@ class MediaChangeMonitor : public MediaDataDecoder,
RefPtr<ShutdownPromise> mShutdownPromise;
MozPromiseHolder<FlushPromise> mFlushPromise;
RefPtr<GMPCrashHelper> mGMPCrashHelper;
MediaResult mLastError;
bool mNeedKeyframe = true;
const bool mErrorIfNoInitializationData;
const TrackInfo::TrackType mType;
MediaEventProducer<TrackInfo::TrackType>* const mOnWaitingForKeyEvent;
const CreateDecoderParams::OptionSet mDecoderOptions;
const CreateDecoderParams::VideoFrameRate mRate;
Maybe<bool> mCanRecycleDecoder;
Maybe<MediaDataDecoder::ConversionRequired> mConversionRequired;
// Used for debugging purposes only
Atomic<bool> mInConstructor;
bool mDecoderInitialized = false;
const CreateDecoderParamsForAsync mParams;
};
} // namespace mozilla

Просмотреть файл

@ -123,8 +123,7 @@ class MediaDecodeTask final : public Runnable {
void Decode();
void OnCreateDecoderCompleted(RefPtr<MediaDataDecoder> aDecoder);
MOZ_CAN_RUN_SCRIPT void OnCreateDecoderFailed(const MediaResult& aError);
MediaResult CreateDecoder(const AudioInfo& info);
MOZ_CAN_RUN_SCRIPT void OnInitDemuxerCompleted();
MOZ_CAN_RUN_SCRIPT void OnInitDemuxerFailed(const MediaResult& aError);
@ -270,28 +269,12 @@ void MediaDecodeTask::OnInitDemuxerCompleted() {
}
}
RefPtr<PDMFactory> pdm = new PDMFactory();
pdm->CreateDecoder(
{*mMediaInfo.mAudio.GetAsAudioInfo(), TrackInfo::kAudioTrack})
->Then(PSupervisorTaskQueue(), __func__, this,
&MediaDecodeTask::OnCreateDecoderCompleted,
&MediaDecodeTask::OnCreateDecoderFailed);
}
void MediaDecodeTask::OnCreateDecoderCompleted(
RefPtr<MediaDataDecoder> aDecoder) {
MOZ_ASSERT(OnPSupervisorTaskQueue());
mDecoder = new MediaDataDecoderProxy(aDecoder.forget(),
do_AddRef(mPDecoderTaskQueue.get()));
InitDecoder();
}
void MediaDecodeTask::OnCreateDecoderFailed(const MediaResult& aError) {
MOZ_ASSERT(OnPSupervisorTaskQueue());
if (NS_FAILED(CreateDecoder(*mMediaInfo.mAudio.GetAsAudioInfo()))) {
LOG("MediaDecodeTask: Could not create a decoder.");
ReportFailureOnMainThread(WebAudioDecodeJob::UnknownContent);
return;
}
InitDecoder();
}
void MediaDecodeTask::OnInitDemuxerFailed(const MediaResult& aError) {
@ -301,6 +284,30 @@ void MediaDecodeTask::OnInitDemuxerFailed(const MediaResult& aError) {
ReportFailureOnMainThread(WebAudioDecodeJob::InvalidContent);
}
MediaResult MediaDecodeTask::CreateDecoder(const AudioInfo& info) {
MOZ_ASSERT(OnPSupervisorTaskQueue());
RefPtr<PDMFactory> pdm = new PDMFactory();
// result may not be updated by PDMFactory::CreateDecoder, as such it must be
// initialized to a fatal error by default.
MediaResult result =
MediaResult(NS_ERROR_DOM_MEDIA_FATAL_ERR,
nsPrintfCString("error creating %s decoder",
TrackTypeToStr(TrackInfo::kAudioTrack)));
RefPtr<MediaDataDecoder> decoder =
pdm->CreateDecoder({info, &result, TrackInfo::kAudioTrack});
if (decoder) {
mDecoder = new MediaDataDecoderProxy(decoder.forget(),
do_AddRef(mPDecoderTaskQueue.get()));
return NS_OK;
}
MOZ_RELEASE_ASSERT(NS_FAILED(result), "PDM returned an invalid error code");
return result;
}
void MediaDecodeTask::InitDecoder() {
MOZ_ASSERT(OnPSupervisorTaskQueue());

Просмотреть файл

@ -3,11 +3,9 @@
* You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "MediaDataCodec.h"
#include "PDMFactory.h"
#include "WebrtcGmpVideoCodec.h"
#include "WebrtcMediaDataDecoderCodec.h"
#include "WebrtcMediaDataEncoderCodec.h"
#include "WebrtcGmpVideoCodec.h"
#include "mozilla/StaticPrefs_media.h"
namespace mozilla {
@ -41,27 +39,7 @@ WebrtcVideoDecoder* MediaDataCodec::CreateDecoder(
default:
return nullptr;
}
nsAutoCString codec;
switch (aCodecType) {
case webrtc::VideoCodecType::kVideoCodecVP8:
codec = "video/vp8";
break;
case webrtc::VideoCodecType::kVideoCodecVP9:
codec = "video/vp9";
break;
case webrtc::VideoCodecType::kVideoCodecH264:
codec = "video/avc";
break;
default:
return nullptr;
}
RefPtr<PDMFactory> pdm = new PDMFactory();
if (!pdm->SupportsMimeType(codec, nullptr /* dddoctor */)) {
return nullptr;
}
return new WebrtcMediaDataDecoder(codec);
return new WebrtcMediaDataDecoder();
}
} // namespace mozilla

Просмотреть файл

@ -15,24 +15,38 @@
namespace mozilla {
WebrtcMediaDataDecoder::WebrtcMediaDataDecoder(nsACString& aCodecMimeType)
WebrtcMediaDataDecoder::WebrtcMediaDataDecoder()
: mThreadPool(GetMediaThreadPool(MediaThreadType::SUPERVISOR)),
mTaskQueue(new TaskQueue(do_AddRef(mThreadPool),
"WebrtcMediaDataDecoder::mTaskQueue")),
mImageContainer(layers::LayerManager::CreateImageContainer(
layers::ImageContainer::ASYNCHRONOUS)),
mFactory(new PDMFactory()),
mTrackType(TrackInfo::kUndefinedTrack),
mCodecType(aCodecMimeType) {}
mTrackType(TrackInfo::kUndefinedTrack) {}
WebrtcMediaDataDecoder::~WebrtcMediaDataDecoder() {}
int32_t WebrtcMediaDataDecoder::InitDecode(
const webrtc::VideoCodec* aCodecSettings, int32_t aNumberOfCores) {
nsCString codec;
switch (aCodecSettings->codecType) {
case webrtc::VideoCodecType::kVideoCodecVP8:
codec = "video/vp8";
break;
case webrtc::VideoCodecType::kVideoCodecVP9:
codec = "video/vp9";
break;
case webrtc::VideoCodecType::kVideoCodecH264:
codec = "video/avc";
break;
default:
return WEBRTC_VIDEO_CODEC_ERROR;
}
mTrackType = TrackInfo::kVideoTrack;
mInfo = VideoInfo(aCodecSettings->width, aCodecSettings->height);
mInfo.mMimeType = mCodecType;
mInfo.mMimeType = codec;
return CreateDecoder();
}
@ -142,35 +156,13 @@ int32_t WebrtcMediaDataDecoder::CreateDecoder() {
Release();
}
RefPtr<TaskQueue> tq =
new TaskQueue(GetMediaThreadPool(MediaThreadType::PLATFORM_DECODER),
"webrtc decode TaskQueue");
RefPtr<MediaDataDecoder> decoder;
media::Await(do_AddRef(mThreadPool), InvokeAsync(tq, __func__, [&] {
RefPtr<GenericPromise> p =
mFactory
->CreateDecoder(
RefPtr<MediaDataDecoder> decoder = mFactory->CreateDecoder(
{mInfo,
CreateDecoderParams::OptionSet(
CreateDecoderParams::Option::LowLatency,
CreateDecoderParams::Option::FullH264Parsing,
CreateDecoderParams::Option::
ErrorIfNoInitializationData),
mTrackType, mImageContainer, knowsCompositor})
->Then(
tq, __func__,
[&](RefPtr<MediaDataDecoder>&& aDecoder) {
decoder = std::move(aDecoder);
return GenericPromise::CreateAndResolve(
true, __func__);
},
[](const MediaResult& aResult) {
return GenericPromise::CreateAndReject(
NS_ERROR_DOM_MEDIA_FATAL_ERR, __func__);
});
return p;
}));
CreateDecoderParams::Option::ErrorIfNoInitializationData),
mTrackType, mImageContainer, knowsCompositor});
if (!decoder) {
return WEBRTC_VIDEO_CODEC_ERROR;
@ -178,7 +170,11 @@ int32_t WebrtcMediaDataDecoder::CreateDecoder() {
// We need to wrap our decoder in a MediaDataDecoderProxy so that it always
// run on an nsISerialEventTarget (which the webrtc code doesn't do)
mDecoder = new MediaDataDecoderProxy(decoder.forget(), tq.forget());
mDecoder = new MediaDataDecoderProxy(
decoder.forget(),
MakeAndAddRef<TaskQueue>(
GetMediaThreadPool(MediaThreadType::PLATFORM_DECODER),
"webrtc decode TaskQueue"));
media::Await(
do_AddRef(mThreadPool), mDecoder->Init(),

Просмотреть файл

@ -29,7 +29,7 @@ class TaskQueue;
class WebrtcMediaDataDecoder : public WebrtcVideoDecoder {
public:
explicit WebrtcMediaDataDecoder(nsACString& aCodecMimeType);
WebrtcMediaDataDecoder();
// Implement VideoDecoder interface.
uint64_t PluginID() const override { return 0; }
@ -66,7 +66,6 @@ class WebrtcMediaDataDecoder : public WebrtcVideoDecoder {
MediaResult mError = NS_OK;
MediaDataDecoder::DecodedData mResults;
const nsCString mCodecType;
};
} // namespace mozilla

Просмотреть файл

@ -761,7 +761,7 @@ bool BackgroundParentImpl::DeallocPCamerasParent(
}
auto BackgroundParentImpl::AllocPUDPSocketParent(
const Maybe<PrincipalInfo>& /* unused */, const nsCString& /* unused */)
const Maybe<PrincipalInfo>& /* unused */, const nsCString & /* unused */)
-> PUDPSocketParent* {
RefPtr<UDPSocketParent> p = new UDPSocketParent(this);
@ -1314,27 +1314,14 @@ mozilla::ipc::IPCResult BackgroundParentImpl::RecvPEndpointForReportConstructor(
mozilla::ipc::IPCResult
BackgroundParentImpl::RecvEnsureRDDProcessAndCreateBridge(
EnsureRDDProcessAndCreateBridgeResolver&& aResolver) {
nsresult* aRv, Endpoint<PRemoteDecoderManagerChild>* aEndpoint) {
RDDProcessManager* rdd = RDDProcessManager::Get();
using Type =
Tuple<const nsresult&, Endpoint<mozilla::PRemoteDecoderManagerChild>&&>;
if (!rdd) {
aResolver(
Type(NS_ERROR_NOT_AVAILABLE, Endpoint<PRemoteDecoderManagerChild>()));
if (rdd && rdd->EnsureRDDProcessAndCreateBridge(OtherPid(), aEndpoint)) {
*aRv = NS_OK;
} else {
rdd->EnsureRDDProcessAndCreateBridge(OtherPid())
->Then(GetCurrentSerialEventTarget(), __func__,
[resolver = std::move(aResolver)](
mozilla::RDDProcessManager::EnsureRDDPromise::
ResolveOrRejectValue&& aValue) mutable {
if (aValue.IsReject()) {
resolver(Type(aValue.RejectValue(),
Endpoint<PRemoteDecoderManagerChild>()));
return;
}
resolver(Type(NS_OK, std::move(aValue.ResolveValue())));
});
*aRv = NS_ERROR_NOT_AVAILABLE;
}
return IPC_OK();
}

Просмотреть файл

@ -392,7 +392,7 @@ class BackgroundParentImpl : public PBackgroundParent,
const PrincipalInfo& aPrincipalInfo) override;
mozilla::ipc::IPCResult RecvEnsureRDDProcessAndCreateBridge(
EnsureRDDProcessAndCreateBridgeResolver&& aResolver) override;
nsresult* aRv, Endpoint<PRemoteDecoderManagerChild>* aEndpoint) override;
bool DeallocPEndpointForReportParent(
PEndpointForReportParent* aActor) override;

Просмотреть файл

@ -263,7 +263,8 @@ parent:
uint32_t aProviderFlags,
uint32_t aCertVerifierFlags);
async EnsureRDDProcessAndCreateBridge()
// See Bug 1518344 - Investigate using async for PBackground::EnsureRDDProcessAndCreateBridge
sync EnsureRDDProcessAndCreateBridge()
returns (nsresult rv, Endpoint<PRemoteDecoderManagerChild> aEndpoint);
child:

Просмотреть файл

@ -882,8 +882,12 @@ description = legacy sync IPC - please add detailed description
description = legacy sync IPC - please add detailed description
[PGMPVideoEncoder::NeedShmem]
description = legacy sync IPC - please add detailed description
[PRemoteDecoderManager::PRemoteDecoder]
description = See Bug 1505976 - investigate changing to async instead of matching GPU pattern
[PRemoteDecoderManager::Readback]
description = legacy sync IPC - please add detailed description
[PBackground::EnsureRDDProcessAndCreateBridge]
description = See Bug 1518344 - investigate using async for PBackground::EnsureRDDProcessAndCreateBridge
[PBackgroundStorage::Preload]
description = legacy sync IPC - please add detailed description
[PBackgroundLSDatabase::PBackgroundLSSnapshot]

Просмотреть файл

@ -294,8 +294,6 @@ class WeakPtr {
#endif
}
explicit WeakPtr(const RefPtr<T>& aOther) : WeakPtr(aOther.get()) {}
// Ensure that mRef is dereferenceable in the uninitialized state.
WeakPtr() : mRef(new WeakReference(nullptr)) {}