Bug 1297003 - Part1-Store the error information in MediaResult while creating a/v decoders
MozReview-Commit-ID: I6R4bX778n7
--- a/dom/media/MediaFormatReader.cpp
+++ b/dom/media/MediaFormatReader.cpp
@@ -375,20 +375,23 @@ MediaFormatReader::OnDemuxerInitFailed(c
}
MediaResult
MediaFormatReader::EnsureDecoderCreated(TrackType aTrack)
{
MOZ_ASSERT(OnTaskQueue());
MOZ_DIAGNOSTIC_ASSERT(!IsSuspended());
+ auto decoderCreatingError = "error creating decoder";
+ MediaResult result = MediaResult(NS_ERROR_DOM_MEDIA_FATAL_ERR, decoderCreatingError);
auto& decoder = GetDecoderData(aTrack);
if (decoder.mDecoder) {
- return NS_OK;
+ result = NS_OK;
+ return result;
}
if (!mPlatform) {
mPlatform = new PDMFactory();
if (IsEncrypted()) {
MOZ_ASSERT(mCDMProxy);
mPlatform->SetCDMProxy(mCDMProxy);
}
@@ -400,44 +403,48 @@ MediaFormatReader::EnsureDecoderCreated(
switch (aTrack) {
case TrackType::kAudioTrack: {
decoder.mDecoder = mPlatform->CreateDecoder({
decoder.mInfo ? *decoder.mInfo->GetAsAudioInfo() : mInfo.mAudio,
decoder.mTaskQueue,
decoder.mCallback.get(),
mCrashHelper,
- decoder.mIsBlankDecode
+ decoder.mIsBlankDecode,
+ &result
});
break;
}
case TrackType::kVideoTrack: {
// Decoders use the layers backend to decide if they can use hardware decoding,
// so specify LAYERS_NONE if we want to forcibly disable it.
decoder.mDecoder = mPlatform->CreateDecoder({
mVideo.mInfo ? *mVideo.mInfo->GetAsVideoInfo() : mInfo.mVideo,
decoder.mTaskQueue,
decoder.mCallback.get(),
mLayersBackendType,
GetImageContainer(),
mCrashHelper,
- decoder.mIsBlankDecode
+ decoder.mIsBlankDecode,
+ &result
});
break;
}
default:
break;
}
- if (decoder.mDecoder ) {
+ if (decoder.mDecoder) {
decoder.mDescription = decoder.mDecoder->GetDescriptionName();
- return NS_OK;
+ result = MediaResult(NS_OK);
+ return result;
}
- decoder.mDescription = "error creating decoder";
- return MediaResult(NS_ERROR_DOM_MEDIA_FATAL_ERR, "error creating decoder");
+
+ decoder.mDescription = decoderCreatingError;
+ return result;
}
bool
MediaFormatReader::EnsureDecoderInitialized(TrackType aTrack)
{
MOZ_ASSERT(OnTaskQueue());
MOZ_DIAGNOSTIC_ASSERT(!IsSuspended());
--- a/dom/media/platforms/PDMFactory.cpp
+++ b/dom/media/platforms/PDMFactory.cpp
@@ -78,24 +78,40 @@ public:
};
StaticAutoPtr<PDMFactoryImpl> PDMFactory::sInstance;
StaticMutex PDMFactory::sMonitor;
class SupportChecker
{
public:
- enum class Result : uint8_t
+ enum class Reason : uint8_t
{
kSupported,
kVideoFormatNotSupported,
kAudioFormatNotSupported,
kUnknown,
};
+ struct CheckResult
+ {
+ explicit CheckResult(Reason aReason,
+ MediaResult aResult = MediaResult(NS_OK))
+ : mReason(aReason),
+ mMediaResult(mozilla::Move(aResult))
+ {}
+ CheckResult(const CheckResult& aOther) = default;
+ CheckResult(CheckResult&& aOther) = default;
+ CheckResult& operator=(const CheckResult& aOther) = default;
+ CheckResult& operator=(CheckResult&& aOther) = default;
+
+ Reason mReason;
+ MediaResult mMediaResult;
+ };
+
template<class Func>
void
AddToCheckList(Func&& aChecker)
{
mCheckerList.AppendElement(mozilla::Forward<Func>(aChecker));
}
void
@@ -108,40 +124,44 @@ public:
[mimeType, extraData]() {
if (MP4Decoder::IsH264(mimeType)) {
mp4_demuxer::SPSData spsdata;
// WMF H.264 Video Decoder and Apple ATDecoder
// do not support YUV444 format.
// For consistency, all decoders should be checked.
if (mp4_demuxer::H264::DecodeSPSFromExtraData(extraData, spsdata) &&
spsdata.chroma_format_idc == PDMFactory::kYUV444) {
- return SupportChecker::Result::kVideoFormatNotSupported;
+ return CheckResult(SupportChecker::Reason::kVideoFormatNotSupported,
+ MediaResult(NS_ERROR_DOM_MEDIA_FATAL_ERR,
+ RESULT_DETAIL("Decoder may not have the capability to handle"
+ " the requested video format"
+ " with YUV444 chroma subsampling.")));
}
}
- return SupportChecker::Result::kSupported;
+ return CheckResult(SupportChecker::Reason::kSupported);
});
}
}
- SupportChecker::Result
+ SupportChecker::CheckResult
Check()
{
for (auto& checker : mCheckerList) {
auto result = checker();
- if (result != SupportChecker::Result::kSupported) {
+ if (result.mReason != SupportChecker::Reason::kSupported) {
return result;
}
}
- return SupportChecker::Result::kSupported;
+ return CheckResult(SupportChecker::Reason::kSupported);
}
void Clear() { mCheckerList.Clear(); }
private:
- nsTArray<mozilla::function<SupportChecker::Result()>> mCheckerList;
+ nsTArray<mozilla::function<CheckResult()>> mCheckerList;
}; // SupportChecker
PDMFactory::PDMFactory()
{
EnsureInit();
CreatePDMs();
CreateBlankPDM();
}
@@ -224,40 +244,51 @@ PDMFactory::CreateDecoder(const CreateDe
}
already_AddRefed<MediaDataDecoder>
PDMFactory::CreateDecoderWithPDM(PlatformDecoderModule* aPDM,
const CreateDecoderParams& aParams)
{
MOZ_ASSERT(aPDM);
RefPtr<MediaDataDecoder> m;
+ MediaResult* result = aParams.mError;
SupportChecker supportChecker;
const TrackInfo& config = aParams.mConfig;
supportChecker.AddMediaFormatChecker(config);
- auto reason = supportChecker.Check();
- if (reason != SupportChecker::Result::kSupported) {
+ auto checkResult = supportChecker.Check();
+ if (checkResult.mReason != SupportChecker::Reason::kSupported) {
DecoderDoctorDiagnostics* diagnostics = aParams.mDiagnostics;
- if (diagnostics) {
- if (reason == SupportChecker::Result::kVideoFormatNotSupported) {
+ if (checkResult.mReason == SupportChecker::Reason::kVideoFormatNotSupported) {
+ if (diagnostics) {
diagnostics->SetVideoNotSupported();
- } else if (reason == SupportChecker::Result::kAudioFormatNotSupported) {
+ }
+ if (result) {
+ *result = checkResult.mMediaResult;
+ }
+ } else if (checkResult.mReason == SupportChecker::Reason::kAudioFormatNotSupported) {
+ if (diagnostics) {
diagnostics->SetAudioNotSupported();
}
+ if (result) {
+ *result = checkResult.mMediaResult;
+ }
}
return nullptr;
}
if (config.IsAudio()) {
m = aPDM->CreateAudioDecoder(aParams);
return m.forget();
}
if (!config.IsVideo()) {
+ *result = MediaResult(NS_ERROR_DOM_MEDIA_FATAL_ERR,
+ RESULT_DETAIL("Decoder configuration error, expected audio or video."));
return nullptr;
}
MediaDataDecoderCallback* callback = aParams.mCallback;
RefPtr<DecoderCallbackFuzzingWrapper> callbackWrapper;
if (MediaPrefs::PDMFuzzingEnabled()) {
callbackWrapper = new DecoderCallbackFuzzingWrapper(callback);
callbackWrapper->SetVideoOutputMinimumInterval(
--- a/dom/media/platforms/PlatformDecoderModule.h
+++ b/dom/media/platforms/PlatformDecoderModule.h
@@ -29,17 +29,17 @@ class ImageContainer;
class MediaDataDecoder;
class MediaDataDecoderCallback;
class TaskQueue;
class CDMProxy;
static LazyLogModule sPDMLog("PlatformDecoderModule");
-struct CreateDecoderParams {
+struct MOZ_STACK_CLASS CreateDecoderParams final {
explicit CreateDecoderParams(const TrackInfo& aConfig)
: mConfig(aConfig)
{}
template <typename T1, typename... Ts>
CreateDecoderParams(const TrackInfo& aConfig, T1&& a1, Ts&&... args)
: mConfig(aConfig)
{
@@ -58,25 +58,27 @@ struct CreateDecoderParams {
return *mConfig.GetAsAudioInfo();
}
const TrackInfo& mConfig;
TaskQueue* mTaskQueue = nullptr;
MediaDataDecoderCallback* mCallback = nullptr;
DecoderDoctorDiagnostics* mDiagnostics = nullptr;
layers::ImageContainer* mImageContainer = nullptr;
+ MediaResult* mError = nullptr;
layers::LayersBackend mLayersBackend = layers::LayersBackend::LAYERS_NONE;
RefPtr<GMPCrashHelper> mCrashHelper;
bool mUseBlankDecoder = false;
private:
void Set(TaskQueue* aTaskQueue) { mTaskQueue = aTaskQueue; }
void Set(MediaDataDecoderCallback* aCallback) { mCallback = aCallback; }
void Set(DecoderDoctorDiagnostics* aDiagnostics) { mDiagnostics = aDiagnostics; }
void Set(layers::ImageContainer* aImageContainer) { mImageContainer = aImageContainer; }
+ void Set(MediaResult* aError) { mError = aError; }
void Set(layers::LayersBackend aLayersBackend) { mLayersBackend = aLayersBackend; }
void Set(GMPCrashHelper* aCrashHelper) { mCrashHelper = aCrashHelper; }
void Set(bool aUseBlankDecoder) { mUseBlankDecoder = aUseBlankDecoder; }
template <typename T1, typename T2, typename... Ts>
void Set(T1&& a1, T2&& a2, Ts&&... args)
{
Set(mozilla::Forward<T1>(a1));
Set(mozilla::Forward<T2>(a2), mozilla::Forward<Ts>(args)...);