--- a/dom/html/HTMLMediaElement.cpp
+++ b/dom/html/HTMLMediaElement.cpp
@@ -2893,17 +2893,18 @@ HTMLMediaElement::GetCanPlay(const nsASt
return CANPLAY_NO;
nsAutoString codecs;
rv = parser.GetParameter("codecs", codecs);
NS_ConvertUTF16toUTF8 mimeTypeUTF8(mimeType);
return DecoderTraits::CanHandleMediaType(mimeTypeUTF8.get(),
NS_SUCCEEDED(rv),
- codecs);
+ codecs,
+ /* DecoderDoctorDiagnostics* */ nullptr);
}
NS_IMETHODIMP
HTMLMediaElement::CanPlayType(const nsAString& aType, nsAString& aResult)
{
switch (GetCanPlay(aType)) {
case CANPLAY_NO:
aResult.Truncate();
@@ -2959,17 +2960,19 @@ nsresult HTMLMediaElement::InitializeDec
NS_ASSERTION(mLoadingSrc, "mLoadingSrc must already be set");
NS_ASSERTION(mDecoder == nullptr, "Shouldn't have a decoder");
nsAutoCString mimeType;
aChannel->GetContentType(mimeType);
NS_ASSERTION(!mimeType.IsEmpty(), "We should have the Content-Type.");
- RefPtr<MediaDecoder> decoder = DecoderTraits::CreateDecoder(mimeType, this);
+ RefPtr<MediaDecoder> decoder =
+ DecoderTraits::CreateDecoder(mimeType, this,
+ /* DecoderDoctorDiagnostics* */ nullptr);
if (!decoder) {
nsAutoString src;
GetCurrentSrc(src);
NS_ConvertUTF8toUTF16 mimeUTF16(mimeType);
const char16_t* params[] = { mimeUTF16.get(), src.get() };
ReportLoadError("MediaLoadUnsupportedMimeType", params, ArrayLength(params));
return NS_ERROR_FAILURE;
}
--- a/dom/media/ADTSDecoder.cpp
+++ b/dom/media/ADTSDecoder.cpp
@@ -29,17 +29,18 @@ ADTSDecoder::CreateStateMachine()
return new MediaDecoderStateMachine(this, reader);
}
/* static */ bool
ADTSDecoder::IsEnabled()
{
PDMFactory::Init();
RefPtr<PDMFactory> platform = new PDMFactory();
- return platform->SupportsMimeType(NS_LITERAL_CSTRING("audio/mp4a-latm"));
+ return platform->SupportsMimeType(NS_LITERAL_CSTRING("audio/mp4a-latm"),
+ /* DecoderDoctorDiagnostics* */ nullptr);
}
/* static */ bool
ADTSDecoder::CanHandleMediaType(const nsACString& aType,
const nsAString& aCodecs)
{
if (aType.EqualsASCII("audio/aac") || aType.EqualsASCII("audio/aacp")) {
return IsEnabled() && (aCodecs.IsEmpty() || aCodecs.EqualsASCII("aac"));
--- a/dom/media/Benchmark.cpp
+++ b/dom/media/Benchmark.cpp
@@ -19,16 +19,17 @@ namespace mozilla {
// Update this version number to force re-running the benchmark. Such as when
// an improvement to FFVP9 or LIBVPX is deemed worthwhile.
const uint32_t VP9Benchmark::sBenchmarkVersionID = 1;
const char* VP9Benchmark::sBenchmarkFpsPref = "media.benchmark.vp9.fps";
const char* VP9Benchmark::sBenchmarkFpsVersionCheck = "media.benchmark.vp9.versioncheck";
bool VP9Benchmark::sHasRunTest = false;
+// static
bool
VP9Benchmark::IsVP9DecodeFast()
{
MOZ_ASSERT(NS_IsMainThread());
bool hasPref = Preferences::HasUserValue(sBenchmarkFpsPref);
uint32_t hadRecentUpdate = Preferences::GetUint(sBenchmarkFpsVersionCheck, 0U);
@@ -195,17 +196,18 @@ BenchmarkPlayback::DemuxNextSample()
}
void
BenchmarkPlayback::InitDecoder(TrackInfo&& aInfo)
{
MOZ_ASSERT(OnThread());
RefPtr<PDMFactory> platform = new PDMFactory();
- mDecoder = platform->CreateDecoder(aInfo, mDecoderTaskQueue, this);
+ mDecoder = platform->CreateDecoder(aInfo, mDecoderTaskQueue, this,
+ /* DecoderDoctorDiagnostics* */ nullptr);
if (!mDecoder) {
MainThreadShutdown();
return;
}
RefPtr<Benchmark> ref(mMainThreadState);
mDecoder->Init()->Then(
Thread(), __func__,
[this, ref](TrackInfo::TrackType aTrackType) {
--- a/dom/media/DecoderTraits.cpp
+++ b/dom/media/DecoderTraits.cpp
@@ -299,27 +299,29 @@ IsDirectShowSupportedType(const nsACStri
{
return DirectShowDecoder::GetSupportedCodecs(aType, nullptr);
}
#endif
#ifdef MOZ_FMP4
static bool
IsMP4SupportedType(const nsACString& aType,
+ DecoderDoctorDiagnostics* aDiagnostics,
const nsAString& aCodecs = EmptyString())
{
- return MP4Decoder::CanHandleMediaType(aType, aCodecs);
+ return MP4Decoder::CanHandleMediaType(aType, aCodecs, aDiagnostics);
}
#endif
/* static */ bool
-DecoderTraits::IsMP4TypeAndEnabled(const nsACString& aType)
+DecoderTraits::IsMP4TypeAndEnabled(const nsACString& aType,
+ DecoderDoctorDiagnostics* aDiagnostics)
{
#ifdef MOZ_FMP4
- return IsMP4SupportedType(aType);
+ return IsMP4SupportedType(aType, aDiagnostics);
#else
return false;
#endif
}
static bool
IsMP3SupportedType(const nsACString& aType,
const nsAString& aCodecs = EmptyString())
@@ -341,17 +343,18 @@ IsAACSupportedType(const nsACString& aTy
static bool
IsWAVSupportedType(const nsACString& aType,
const nsAString& aCodecs = EmptyString())
{
return WaveDecoder::CanHandleMediaType(aType, aCodecs);
}
/* static */
-bool DecoderTraits::ShouldHandleMediaType(const char* aMIMEType)
+bool DecoderTraits::ShouldHandleMediaType(const char* aMIMEType,
+ DecoderDoctorDiagnostics* aDiagnostics)
{
if (IsWaveType(nsDependentCString(aMIMEType))) {
// We should not return true for Wave types, since there are some
// Wave codecs actually in use in the wild that we don't support, and
// we should allow those to be handled by plugins or helper apps.
// Furthermore people can play Wave files on most platforms by other
// means.
return false;
@@ -363,23 +366,25 @@ bool DecoderTraits::ShouldHandleMediaTyp
if (nsDependentCString(aMIMEType).EqualsASCII("video/quicktime")) {
RefPtr<nsPluginHost> pluginHost = nsPluginHost::GetInst();
if (pluginHost &&
pluginHost->HavePluginForType(nsDependentCString(aMIMEType))) {
return false;
}
}
- return CanHandleMediaType(aMIMEType, false, EmptyString()) != CANPLAY_NO;
+ return CanHandleMediaType(aMIMEType, false, EmptyString(), aDiagnostics)
+ != CANPLAY_NO;
}
/* static */
CanPlayStatus
DecoderTraits::CanHandleCodecsType(const char* aMIMEType,
- const nsAString& aRequestedCodecs)
+ const nsAString& aRequestedCodecs,
+ DecoderDoctorDiagnostics* aDiagnostics)
{
char const* const* codecList = nullptr;
#ifdef MOZ_RAW
if (IsRawType(nsDependentCString(aMIMEType))) {
codecList = gRawCodecs;
}
#endif
if (IsOggType(nsDependentCString(aMIMEType))) {
@@ -395,18 +400,18 @@ DecoderTraits::CanHandleCodecsType(const
} else {
// We can only reach this position if a particular codec was requested,
// webm is supported and working: the codec must be invalid.
return CANPLAY_NO;
}
}
#endif
#ifdef MOZ_FMP4
- if (IsMP4TypeAndEnabled(nsDependentCString(aMIMEType))) {
- if (IsMP4SupportedType(nsDependentCString(aMIMEType), aRequestedCodecs)) {
+ if (IsMP4TypeAndEnabled(nsDependentCString(aMIMEType), aDiagnostics)) {
+ if (IsMP4SupportedType(nsDependentCString(aMIMEType), aDiagnostics, aRequestedCodecs)) {
return CANPLAY_YES;
} else {
// We can only reach this position if a particular codec was requested,
// fmp4 is supported and working: the codec must be invalid.
return CANPLAY_NO;
}
}
#endif
@@ -462,38 +467,41 @@ DecoderTraits::CanHandleCodecsType(const
return CANPLAY_YES;
}
/* static */
CanPlayStatus
DecoderTraits::CanHandleMediaType(const char* aMIMEType,
bool aHaveRequestedCodecs,
- const nsAString& aRequestedCodecs)
+ const nsAString& aRequestedCodecs,
+ DecoderDoctorDiagnostics* aDiagnostics)
{
MOZ_ASSERT(NS_IsMainThread());
if (aHaveRequestedCodecs) {
- CanPlayStatus result = CanHandleCodecsType(aMIMEType, aRequestedCodecs);
+ CanPlayStatus result = CanHandleCodecsType(aMIMEType,
+ aRequestedCodecs,
+ aDiagnostics);
if (result == CANPLAY_NO || result == CANPLAY_YES) {
return result;
}
}
#ifdef MOZ_RAW
if (IsRawType(nsDependentCString(aMIMEType))) {
return CANPLAY_MAYBE;
}
#endif
if (IsOggType(nsDependentCString(aMIMEType))) {
return CANPLAY_MAYBE;
}
if (IsWaveType(nsDependentCString(aMIMEType))) {
return CANPLAY_MAYBE;
}
- if (IsMP4TypeAndEnabled(nsDependentCString(aMIMEType))) {
+ if (IsMP4TypeAndEnabled(nsDependentCString(aMIMEType), aDiagnostics)) {
return CANPLAY_MAYBE;
}
#if !defined(MOZ_OMX_WEBM_DECODER)
if (IsWebMTypeAndEnabled(nsDependentCString(aMIMEType))) {
return CANPLAY_MAYBE;
}
#endif
if (IsMP3SupportedType(nsDependentCString(aMIMEType))) {
@@ -524,23 +532,25 @@ DecoderTraits::CanHandleMediaType(const
}
#endif
return CANPLAY_NO;
}
// Instantiates but does not initialize decoder.
static
already_AddRefed<MediaDecoder>
-InstantiateDecoder(const nsACString& aType, MediaDecoderOwner* aOwner)
+InstantiateDecoder(const nsACString& aType,
+ MediaDecoderOwner* aOwner,
+ DecoderDoctorDiagnostics* aDiagnostics)
{
MOZ_ASSERT(NS_IsMainThread());
RefPtr<MediaDecoder> decoder;
#ifdef MOZ_FMP4
- if (IsMP4SupportedType(aType)) {
+ if (IsMP4SupportedType(aType, aDiagnostics)) {
decoder = new MP4Decoder(aOwner);
return decoder.forget();
}
#endif
if (IsMP3SupportedType(aType)) {
decoder = new MP3Decoder(aOwner);
return decoder.forget();
}
@@ -611,33 +621,35 @@ InstantiateDecoder(const nsACString& aTy
}
#endif
return nullptr;
}
/* static */
already_AddRefed<MediaDecoder>
-DecoderTraits::CreateDecoder(const nsACString& aType, MediaDecoderOwner* aOwner)
+DecoderTraits::CreateDecoder(const nsACString& aType,
+ MediaDecoderOwner* aOwner,
+ DecoderDoctorDiagnostics* aDiagnostics)
{
MOZ_ASSERT(NS_IsMainThread());
- return InstantiateDecoder(aType, aOwner);
+ return InstantiateDecoder(aType, aOwner, aDiagnostics);
}
/* static */
MediaDecoderReader* DecoderTraits::CreateReader(const nsACString& aType, AbstractMediaDecoder* aDecoder)
{
MOZ_ASSERT(NS_IsMainThread());
MediaDecoderReader* decoderReader = nullptr;
if (!aDecoder) {
return decoderReader;
}
#ifdef MOZ_FMP4
- if (IsMP4SupportedType(aType)) {
+ if (IsMP4SupportedType(aType, /* DecoderDoctorDiagnostics* */ nullptr)) {
decoderReader = new MediaFormatReader(aDecoder, new MP4Demuxer(aDecoder->GetResource()));
} else
#endif
if (IsMP3SupportedType(aType)) {
decoderReader = new MediaFormatReader(aDecoder, new mp3::MP3Demuxer(aDecoder->GetResource()));
} else
if (IsAACSupportedType(aType)) {
decoderReader = new MediaFormatReader(aDecoder, new ADTSDemuxer(aDecoder->GetResource()));
@@ -701,17 +713,17 @@ bool DecoderTraits::IsSupportedInVideoDo
(IsOmxSupportedType(aType) &&
!IsB2GSupportOnlyType(aType)) ||
#endif
IsWebMSupportedType(aType) ||
#ifdef MOZ_ANDROID_OMX
(MediaDecoder::IsAndroidMediaPluginEnabled() && IsAndroidMediaType(aType)) ||
#endif
#ifdef MOZ_FMP4
- IsMP4SupportedType(aType) ||
+ IsMP4SupportedType(aType, /* DecoderDoctorDiagnostics* */ nullptr) ||
#endif
IsMP3SupportedType(aType) ||
IsAACSupportedType(aType) ||
#ifdef MOZ_DIRECTSHOW
IsDirectShowSupportedType(aType) ||
#endif
#ifdef NECKO_PROTOCOL_rtsp
IsRtspSupportedType(aType) ||
--- a/dom/media/DecoderTraits.h
+++ b/dom/media/DecoderTraits.h
@@ -10,16 +10,17 @@
#include "nsCOMPtr.h"
class nsAString;
class nsACString;
namespace mozilla {
class AbstractMediaDecoder;
+class DecoderDoctorDiagnostics;
class MediaDecoder;
class MediaDecoderOwner;
class MediaDecoderReader;
enum CanPlayStatus {
CANPLAY_NO,
CANPLAY_MAYBE,
CANPLAY_YES
@@ -30,36 +31,40 @@ public:
// Returns the CanPlayStatus indicating if we can handle this
// MIME type. The MIME type should not include the codecs parameter.
// That parameter should be passed in aRequestedCodecs, and will only be
// used if whether a given MIME type being handled depends on the
// codec that will be used. If the codecs parameter has not been
// specified, pass false in aHaveRequestedCodecs.
static CanPlayStatus CanHandleMediaType(const char* aMIMEType,
bool aHaveRequestedCodecs,
- const nsAString& aRequestedCodecs);
+ const nsAString& aRequestedCodecs,
+ DecoderDoctorDiagnostics* aDiagnostics);
// Returns the CanPlayStatus indicating if we can handle this MIME type and
// codecs type natively, excluding any plugins-based reader (such as
// GStreamer)
// The MIME type should not include the codecs parameter.
// That parameter is passed in aRequestedCodecs.
static CanPlayStatus CanHandleCodecsType(const char* aMIMEType,
- const nsAString& aRequestedCodecs);
+ const nsAString& aRequestedCodecs,
+ DecoderDoctorDiagnostics* aDiagnostics);
// Returns true if we should handle this MIME type when it appears
// as an <object> or as a toplevel page. If, in practice, our support
// for the type is more limited than appears in the wild, we should return
// false here even if CanHandleMediaType would return true.
- static bool ShouldHandleMediaType(const char* aMIMEType);
+ static bool ShouldHandleMediaType(const char* aMIMEType,
+ DecoderDoctorDiagnostics* aDiagnostics);
// Create a decoder for the given aType. Returns null if we
// were unable to create the decoder.
static already_AddRefed<MediaDecoder> CreateDecoder(const nsACString& aType,
- MediaDecoderOwner* aOwner);
+ MediaDecoderOwner* aOwner,
+ DecoderDoctorDiagnostics* aDiagnostics);
// Create a reader for thew given MIME type aType. Returns null
// if we were unable to create the reader.
static MediaDecoderReader* CreateReader(const nsACString& aType,
AbstractMediaDecoder* aDecoder);
// Returns true if MIME type aType is supported in video documents,
// or false otherwise. Not all platforms support all MIME types, and
@@ -67,15 +72,16 @@ public:
static bool IsSupportedInVideoDocument(const nsACString& aType);
// Returns true if we should not start decoder until we receive
// OnConnected signal. (currently RTSP only)
static bool DecoderWaitsForOnConnected(const nsACString& aType);
static bool IsWebMTypeAndEnabled(const nsACString& aType);
static bool IsWebMAudioType(const nsACString& aType);
- static bool IsMP4TypeAndEnabled(const nsACString& aType);
+ static bool IsMP4TypeAndEnabled(const nsACString& aType,
+ DecoderDoctorDiagnostics* aDiagnostics);
};
} // namespace mozilla
#endif
--- a/dom/media/MP3Decoder.cpp
+++ b/dom/media/MP3Decoder.cpp
@@ -29,17 +29,18 @@ MP3Decoder::CreateStateMachine() {
return new MediaDecoderStateMachine(this, reader);
}
/* static */
bool
MP3Decoder::IsEnabled() {
PDMFactory::Init();
RefPtr<PDMFactory> platform = new PDMFactory();
- return platform->SupportsMimeType(NS_LITERAL_CSTRING("audio/mpeg"));
+ return platform->SupportsMimeType(NS_LITERAL_CSTRING("audio/mpeg"),
+ /* DecoderDoctorDiagnostics* */ nullptr);
}
/* static */
bool MP3Decoder::CanHandleMediaType(const nsACString& aType,
const nsAString& aCodecs)
{
if (aType.EqualsASCII("audio/mp3") || aType.EqualsASCII("audio/mpeg")) {
return IsEnabled() &&
--- a/dom/media/MediaFormatReader.cpp
+++ b/dom/media/MediaFormatReader.cpp
@@ -390,27 +390,29 @@ MediaFormatReader::EnsureDecoderCreated(
switch (aTrack) {
case TrackType::kAudioTrack:
decoder.mDecoder =
mPlatform->CreateDecoder(decoder.mInfo ?
*decoder.mInfo->GetAsAudioInfo() :
mInfo.mAudio,
decoder.mTaskQueue,
- decoder.mCallback);
+ decoder.mCallback,
+ /* DecoderDoctorDiagnostics* */ nullptr);
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,
+ /* DecoderDoctorDiagnostics* */ nullptr,
mLayersBackendType,
GetImageContainer());
break;
default:
break;
}
if (decoder.mDecoder ) {
decoder.mDescription = decoder.mDecoder->GetDescriptionName();
--- a/dom/media/eme/MediaKeySystemAccess.cpp
+++ b/dom/media/eme/MediaKeySystemAccess.cpp
@@ -356,17 +356,18 @@ GMPDecryptsAndGeckoDecodesH264(mozIGecko
MOZ_ASSERT(HaveGMPFor(aGMPService,
NS_ConvertUTF16toUTF8(aKeySystem),
NS_LITERAL_CSTRING(GMP_API_DECRYPTOR)));
MOZ_ASSERT(IsH264ContentType(aContentType));
return !HaveGMPFor(aGMPService,
NS_ConvertUTF16toUTF8(aKeySystem),
NS_LITERAL_CSTRING(GMP_API_VIDEO_DECODER),
NS_LITERAL_CSTRING("h264")) &&
- MP4Decoder::CanHandleMediaType(aContentType);
+ MP4Decoder::CanHandleMediaType(aContentType,
+ /* DecoderDoctorDiagnostics* */ nullptr);
}
static bool
GMPDecryptsAndGeckoDecodesAAC(mozIGeckoMediaPluginService* aGMPService,
const nsAString& aKeySystem,
const nsAString& aContentType)
{
MOZ_ASSERT(HaveGMPFor(aGMPService,
@@ -381,17 +382,18 @@ GMPDecryptsAndGeckoDecodesAAC(mozIGeckoM
#if defined(MOZ_WIDEVINE_EME) && defined(XP_WIN)
// Widevine CDM doesn't include an AAC decoder. So if WMF can't
// decode AAC, and a codec wasn't specified, be conservative
// and reject the MediaKeys request, since our policy is to prevent
// the Adobe GMP's unencrypted AAC decoding path being used to
// decode content decrypted by the Widevine CDM.
(!aKeySystem.EqualsLiteral("com.widevine.alpha") || WMFDecoderModule::HasAAC()) &&
#endif
- MP4Decoder::CanHandleMediaType(aContentType);
+ MP4Decoder::CanHandleMediaType(aContentType,
+ /* DecoderDoctorDiagnostics* */ nullptr);
}
static bool
IsSupportedAudio(mozIGeckoMediaPluginService* aGMPService,
const nsAString& aKeySystem,
const nsAString& aAudioType)
{
return IsAACContentType(aAudioType) &&
--- a/dom/media/fmp4/MP4Decoder.cpp
+++ b/dom/media/fmp4/MP4Decoder.cpp
@@ -85,17 +85,18 @@ IsWhitelistedH264Codec(const nsAString&
profile == H264_PROFILE_MAIN ||
profile == H264_PROFILE_EXTENDED ||
profile == H264_PROFILE_HIGH);
}
/* static */
bool
MP4Decoder::CanHandleMediaType(const nsACString& aMIMETypeExcludingCodecs,
- const nsAString& aCodecs)
+ const nsAString& aCodecs,
+ DecoderDoctorDiagnostics* aDiagnostics)
{
if (!IsEnabled()) {
return false;
}
// Whitelist MP4 types, so they explicitly match what we encounter on
// the web, as opposed to what we use internally (i.e. what our demuxers
// etc output).
@@ -148,37 +149,40 @@ MP4Decoder::CanHandleMediaType(const nsA
return false;
}
}
// Verify that we have a PDM that supports the whitelisted types.
PDMFactory::Init();
RefPtr<PDMFactory> platform = new PDMFactory();
for (const nsCString& codecMime : codecMimes) {
- if (!platform->SupportsMimeType(codecMime)) {
+ if (!platform->SupportsMimeType(codecMime, aDiagnostics)) {
return false;
}
}
return true;
}
/* static */ bool
-MP4Decoder::CanHandleMediaType(const nsAString& aContentType)
+MP4Decoder::CanHandleMediaType(const nsAString& aContentType,
+ DecoderDoctorDiagnostics* aDiagnostics)
{
nsContentTypeParser parser(aContentType);
nsAutoString mimeType;
nsresult rv = parser.GetType(mimeType);
if (NS_FAILED(rv)) {
return false;
}
nsString codecs;
parser.GetParameter("codecs", codecs);
- return CanHandleMediaType(NS_ConvertUTF16toUTF8(mimeType), codecs);
+ return CanHandleMediaType(NS_ConvertUTF16toUTF8(mimeType),
+ codecs,
+ aDiagnostics);
}
/* static */
bool
MP4Decoder::IsEnabled()
{
return Preferences::GetBool("media.mp4.enabled", true);
}
@@ -226,17 +230,19 @@ CreateTestH264Decoder(layers::LayersBack
aConfig.mExtraData = new MediaByteBuffer();
aConfig.mExtraData->AppendElements(sTestH264ExtraData,
MOZ_ARRAY_LENGTH(sTestH264ExtraData));
PDMFactory::Init();
RefPtr<PDMFactory> platform = new PDMFactory();
RefPtr<MediaDataDecoder> decoder(
- platform->CreateDecoder(aConfig, aTaskQueue, nullptr, aBackend, nullptr));
+ platform->CreateDecoder(aConfig, aTaskQueue, nullptr,
+ /* DecoderDoctorDiagnostics* */ nullptr,
+ aBackend, nullptr));
return decoder.forget();
}
/* static */ already_AddRefed<dom::Promise>
MP4Decoder::IsVideoAccelerated(layers::LayersBackend aBackend, nsIGlobalObject* aParent)
{
MOZ_ASSERT(NS_IsMainThread());
--- a/dom/media/fmp4/MP4Decoder.h
+++ b/dom/media/fmp4/MP4Decoder.h
@@ -27,19 +27,21 @@ public:
MediaDecoderStateMachine* CreateStateMachine() override;
// Returns true if aMIMEType is a type that we think we can render with the
// a MP4 platform decoder backend. If aCodecs is non emtpy, it is filled
// with a comma-delimited list of codecs to check support for. Notes in
// out params wether the codecs string contains AAC or H.264.
static bool CanHandleMediaType(const nsACString& aMIMETypeExcludingCodecs,
- const nsAString& aCodecs);
+ const nsAString& aCodecs,
+ DecoderDoctorDiagnostics* aDiagnostics);
- static bool CanHandleMediaType(const nsAString& aMIMEType);
+ static bool CanHandleMediaType(const nsAString& aMIMEType,
+ DecoderDoctorDiagnostics* aDiagnostics);
// Returns true if the MP4 backend is preffed on.
static bool IsEnabled();
static already_AddRefed<dom::Promise>
IsVideoAccelerated(layers::LayersBackend aBackend, nsIGlobalObject* aParent);
void GetMozDebugReaderData(nsAString& aString) override;
--- a/dom/media/gtest/TestMediaDataDecoder.cpp
+++ b/dom/media/gtest/TestMediaDataDecoder.cpp
@@ -37,17 +37,18 @@ public:
}
private:
RefPtr<Benchmark> mBenchmark;
};
TEST(MediaDataDecoder, H264)
{
- if (!DecoderTraits::IsMP4TypeAndEnabled(NS_LITERAL_CSTRING("video/mp4"))) {
+ if (!DecoderTraits::IsMP4TypeAndEnabled(NS_LITERAL_CSTRING("video/mp4")
+ , /* DecoderDoctorDiagnostics* */ nullptr)) {
EXPECT_TRUE(true);
} else {
RefPtr<MediaResource> resource =
new MockMediaResource("gizmo.mp4", NS_LITERAL_CSTRING("video/mp4"));
nsresult rv = resource->Open(nullptr);
EXPECT_TRUE(NS_SUCCEEDED(rv));
BenchmarkRunner runner(new Benchmark(new MP4Demuxer(resource)));
--- a/dom/media/mediasource/MediaSource.cpp
+++ b/dom/media/mediasource/MediaSource.cpp
@@ -70,26 +70,27 @@ static const char* const gMediaSourceTyp
// 1. If MP4/H264 isn't supported:
// * Windows XP
// * Windows Vista and Server 2008 without the optional "Platform Update Supplement"
// * N/KN editions (Europe and Korea) of Windows 7/8/8.1/10 without the
// optional "Windows Media Feature Pack"
// 2. If H264 hardware acceleration is not available.
// 3. The CPU is considered to be fast enough
static bool
-IsWebMForced()
+IsWebMForced(DecoderDoctorDiagnostics* aDiagnostics)
{
bool mp4supported =
- DecoderTraits::IsMP4TypeAndEnabled(NS_LITERAL_CSTRING("video/mp4"));
+ DecoderTraits::IsMP4TypeAndEnabled(NS_LITERAL_CSTRING("video/mp4"),
+ aDiagnostics);
bool hwsupported = gfxPlatform::GetPlatform()->CanUseHardwareVideoDecoding();
return !mp4supported || !hwsupported || VP9Benchmark::IsVP9DecodeFast();
}
static nsresult
-IsTypeSupported(const nsAString& aType)
+IsTypeSupported(const nsAString& aType, DecoderDoctorDiagnostics* aDiagnostics)
{
if (aType.IsEmpty()) {
return NS_ERROR_DOM_INVALID_ACCESS_ERR;
}
nsContentTypeParser parser(aType);
nsAutoString mimeType;
nsresult rv = parser.GetType(mimeType);
if (NS_FAILED(rv)) {
@@ -97,36 +98,38 @@ IsTypeSupported(const nsAString& aType)
}
NS_ConvertUTF16toUTF8 mimeTypeUTF8(mimeType);
nsAutoString codecs;
bool hasCodecs = NS_SUCCEEDED(parser.GetParameter("codecs", codecs));
for (uint32_t i = 0; gMediaSourceTypes[i]; ++i) {
if (mimeType.EqualsASCII(gMediaSourceTypes[i])) {
- if (DecoderTraits::IsMP4TypeAndEnabled(mimeTypeUTF8)) {
+ if (DecoderTraits::IsMP4TypeAndEnabled(mimeTypeUTF8, aDiagnostics)) {
if (!Preferences::GetBool("media.mediasource.mp4.enabled", false)) {
return NS_ERROR_DOM_NOT_SUPPORTED_ERR;
}
if (hasCodecs &&
DecoderTraits::CanHandleCodecsType(mimeTypeUTF8.get(),
- codecs) == CANPLAY_NO) {
+ codecs,
+ aDiagnostics) == CANPLAY_NO) {
return NS_ERROR_DOM_NOT_SUPPORTED_ERR;
}
return NS_OK;
} else if (DecoderTraits::IsWebMTypeAndEnabled(mimeTypeUTF8)) {
if (!(Preferences::GetBool("media.mediasource.webm.enabled", false) ||
(Preferences::GetBool("media.mediasource.webm.audio.enabled", true) &&
DecoderTraits::IsWebMAudioType(mimeTypeUTF8)) ||
- IsWebMForced())) {
+ IsWebMForced(aDiagnostics))) {
return NS_ERROR_DOM_NOT_SUPPORTED_ERR;
}
if (hasCodecs &&
DecoderTraits::CanHandleCodecsType(mimeTypeUTF8.get(),
- codecs) == CANPLAY_NO) {
+ codecs,
+ aDiagnostics) == CANPLAY_NO) {
return NS_ERROR_DOM_NOT_SUPPORTED_ERR;
}
return NS_OK;
}
}
}
return NS_ERROR_DOM_NOT_SUPPORTED_ERR;
@@ -215,17 +218,18 @@ MediaSource::SetDuration(double aDuratio
MSE_API("SetDuration(aDuration=%f)", aDuration);
mDecoder->SetMediaSourceDuration(aDuration, aAction);
}
already_AddRefed<SourceBuffer>
MediaSource::AddSourceBuffer(const nsAString& aType, ErrorResult& aRv)
{
MOZ_ASSERT(NS_IsMainThread());
- nsresult rv = mozilla::IsTypeSupported(aType);
+ nsresult rv = mozilla::IsTypeSupported(aType,
+ /* DecoderDoctorDiagnostics* */ nullptr);
MSE_API("AddSourceBuffer(aType=%s)%s",
NS_ConvertUTF16toUTF8(aType).get(),
rv == NS_OK ? "" : " [not supported]");
if (NS_FAILED(rv)) {
aRv.Throw(rv);
return nullptr;
}
if (mSourceBuffers->Length() >= MAX_SOURCE_BUFFERS) {
@@ -334,17 +338,18 @@ MediaSource::EndOfStream(const Optional<
aRv.Throw(NS_ERROR_DOM_INVALID_ACCESS_ERR);
}
}
/* static */ bool
MediaSource::IsTypeSupported(const GlobalObject&, const nsAString& aType)
{
MOZ_ASSERT(NS_IsMainThread());
- nsresult rv = mozilla::IsTypeSupported(aType);
+ nsresult rv = mozilla::IsTypeSupported(aType,
+ /* DecoderDoctorDiagnostics* */ nullptr);
#define this nullptr
MSE_API("IsTypeSupported(aType=%s)%s ",
NS_ConvertUTF16toUTF8(aType).get(), rv == NS_OK ? "OK" : "[not supported]");
#undef this // don't ever remove this line !
return NS_SUCCEEDED(rv);
}
/* static */ bool
--- a/dom/media/platforms/PDMFactory.cpp
+++ b/dom/media/platforms/PDMFactory.cpp
@@ -139,64 +139,69 @@ PDMFactory::PDMFactory()
PDMFactory::~PDMFactory()
{
}
already_AddRefed<MediaDataDecoder>
PDMFactory::CreateDecoder(const TrackInfo& aConfig,
FlushableTaskQueue* aTaskQueue,
MediaDataDecoderCallback* aCallback,
+ DecoderDoctorDiagnostics* aDiagnostics,
layers::LayersBackend aLayersBackend,
layers::ImageContainer* aImageContainer)
{
bool isEncrypted = mEMEPDM && aConfig.mCrypto.mValid;
if (isEncrypted) {
return CreateDecoderWithPDM(mEMEPDM,
aConfig,
aTaskQueue,
aCallback,
+ aDiagnostics,
aLayersBackend,
aImageContainer);
}
for (auto& current : mCurrentPDMs) {
- if (!current->SupportsMimeType(aConfig.mMimeType)) {
+ if (!current->SupportsMimeType(aConfig.mMimeType, aDiagnostics)) {
continue;
}
RefPtr<MediaDataDecoder> m =
CreateDecoderWithPDM(current,
aConfig,
aTaskQueue,
aCallback,
+ aDiagnostics,
aLayersBackend,
aImageContainer);
if (m) {
return m.forget();
}
}
NS_WARNING("Unable to create a decoder, no platform found.");
return nullptr;
}
already_AddRefed<MediaDataDecoder>
PDMFactory::CreateDecoderWithPDM(PlatformDecoderModule* aPDM,
const TrackInfo& aConfig,
FlushableTaskQueue* aTaskQueue,
MediaDataDecoderCallback* aCallback,
+ DecoderDoctorDiagnostics* aDiagnostics,
layers::LayersBackend aLayersBackend,
layers::ImageContainer* aImageContainer)
{
MOZ_ASSERT(aPDM);
RefPtr<MediaDataDecoder> m;
if (aConfig.GetAsAudioInfo()) {
m = aPDM->CreateAudioDecoder(*aConfig.GetAsAudioInfo(),
aTaskQueue,
- aCallback);
+ aCallback,
+ aDiagnostics);
return m.forget();
}
if (!aConfig.GetAsVideoInfo()) {
return nullptr;
}
MediaDataDecoderCallback* callback = aCallback;
@@ -211,46 +216,49 @@ PDMFactory::CreateDecoderWithPDM(Platfor
if (H264Converter::IsH264(aConfig)) {
RefPtr<H264Converter> h
= new H264Converter(aPDM,
*aConfig.GetAsVideoInfo(),
aLayersBackend,
aImageContainer,
aTaskQueue,
- callback);
+ callback,
+ aDiagnostics);
const nsresult rv = h->GetLastError();
if (NS_SUCCEEDED(rv) || rv == NS_ERROR_NOT_INITIALIZED) {
// The H264Converter either successfully created the wrapped decoder,
// or there wasn't enough AVCC data to do so. Otherwise, there was some
// problem, for example WMF DLLs were missing.
m = h.forget();
}
} else {
m = aPDM->CreateVideoDecoder(*aConfig.GetAsVideoInfo(),
aLayersBackend,
aImageContainer,
aTaskQueue,
- callback);
+ callback,
+ aDiagnostics);
}
if (callbackWrapper && m) {
m = new DecoderFuzzingWrapper(m.forget(), callbackWrapper.forget());
}
return m.forget();
}
bool
-PDMFactory::SupportsMimeType(const nsACString& aMimeType) const
+PDMFactory::SupportsMimeType(const nsACString& aMimeType,
+ DecoderDoctorDiagnostics* aDiagnostics) const
{
if (mEMEPDM) {
- return mEMEPDM->SupportsMimeType(aMimeType);
+ return mEMEPDM->SupportsMimeType(aMimeType, aDiagnostics);
}
- RefPtr<PlatformDecoderModule> current = GetDecoder(aMimeType);
+ RefPtr<PlatformDecoderModule> current = GetDecoder(aMimeType, aDiagnostics);
return !!current;
}
void
PDMFactory::CreatePDMs()
{
RefPtr<PlatformDecoderModule> m;
@@ -319,21 +327,22 @@ PDMFactory::StartupPDM(PlatformDecoderMo
if (aPDM && NS_SUCCEEDED(aPDM->Startup())) {
mCurrentPDMs.AppendElement(aPDM);
return true;
}
return false;
}
already_AddRefed<PlatformDecoderModule>
-PDMFactory::GetDecoder(const nsACString& aMimeType) const
+PDMFactory::GetDecoder(const nsACString& aMimeType,
+ DecoderDoctorDiagnostics* aDiagnostics) const
{
RefPtr<PlatformDecoderModule> pdm;
for (auto& current : mCurrentPDMs) {
- if (current->SupportsMimeType(aMimeType)) {
+ if (current->SupportsMimeType(aMimeType, aDiagnostics)) {
pdm = current;
break;
}
}
return pdm.forget();
}
#ifdef MOZ_EME
--- a/dom/media/platforms/PDMFactory.h
+++ b/dom/media/platforms/PDMFactory.h
@@ -8,16 +8,18 @@
#define PDMFactory_h_
#include "PlatformDecoderModule.h"
class CDMProxy;
namespace mozilla {
+class DecoderDoctorDiagnostics;
+
class PDMFactory final {
public:
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(PDMFactory)
PDMFactory();
// Call on the main thread to initialize the static state
// needed by Create().
@@ -27,20 +29,22 @@ public:
// 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 TrackInfo& aConfig,
FlushableTaskQueue* aTaskQueue,
MediaDataDecoderCallback* aCallback,
+ DecoderDoctorDiagnostics* aDiagnostics,
layers::LayersBackend aLayersBackend = layers::LayersBackend::LAYERS_NONE,
layers::ImageContainer* aImageContainer = nullptr);
- bool SupportsMimeType(const nsACString& aMimeType) const;
+ bool SupportsMimeType(const nsACString& aMimeType,
+ DecoderDoctorDiagnostics* aDiagnostics) const;
#ifdef MOZ_EME
// Creates a PlatformDecoderModule that uses a CDMProxy to decrypt or
// decrypt-and-decode EME encrypted content. If the CDM only decrypts and
// does not decode, we create a PDM and use that to create MediaDataDecoders
// that we use on on aTaskQueue to decode the decrypted stream.
// This is called on the decode task queue.
void SetCDMProxy(CDMProxy* aProxy);
@@ -48,23 +52,25 @@ public:
private:
virtual ~PDMFactory();
void CreatePDMs();
// Startup the provided PDM and add it to our list if successful.
bool StartupPDM(PlatformDecoderModule* aPDM);
// Returns the first PDM in our list supporting the mimetype.
already_AddRefed<PlatformDecoderModule>
- GetDecoder(const nsACString& aMimeType) const;
+ GetDecoder(const nsACString& aMimeType,
+ DecoderDoctorDiagnostics* aDiagnostics) const;
already_AddRefed<MediaDataDecoder>
CreateDecoderWithPDM(PlatformDecoderModule* aPDM,
const TrackInfo& aConfig,
FlushableTaskQueue* aTaskQueue,
MediaDataDecoderCallback* aCallback,
+ DecoderDoctorDiagnostics* aDiagnostics,
layers::LayersBackend aLayersBackend,
layers::ImageContainer* aImageContainer);
// PDM pref caches...
static bool sUseBlankDecoder;
#ifdef MOZ_GONK_MEDIACODEC
static bool sGonkDecoderEnabled;
#endif
--- a/dom/media/platforms/PlatformDecoderModule.h
+++ b/dom/media/platforms/PlatformDecoderModule.h
@@ -15,16 +15,17 @@
#include "mozilla/RefPtr.h"
#include <queue>
namespace mozilla {
class TrackInfo;
class AudioInfo;
class VideoInfo;
class MediaRawData;
+class DecoderDoctorDiagnostics;
namespace layers {
class ImageContainer;
} // namespace layers
class MediaDataDecoder;
class MediaDataDecoderCallback;
class FlushableTaskQueue;
@@ -48,17 +49,18 @@ class PlatformDecoderModule {
public:
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(PlatformDecoderModule)
// Perform any per-instance initialization.
// This is called on the decode task queue.
virtual nsresult Startup() { return NS_OK; };
// Indicates if the PlatformDecoderModule supports decoding of aMimeType.
- virtual bool SupportsMimeType(const nsACString& aMimeType) const = 0;
+ virtual bool SupportsMimeType(const nsACString& aMimeType,
+ DecoderDoctorDiagnostics* aDiagnostics) const = 0;
enum ConversionRequired {
kNeedNone,
kNeedAVCC,
kNeedAnnexB,
};
// Indicates that the decoder requires a specific format.
@@ -84,32 +86,34 @@ protected:
// Returns nullptr if the decoder can't be created.
// It is safe to store a reference to aConfig.
// This is called on the decode task queue.
virtual already_AddRefed<MediaDataDecoder>
CreateVideoDecoder(const VideoInfo& aConfig,
layers::LayersBackend aLayersBackend,
layers::ImageContainer* aImageContainer,
FlushableTaskQueue* aVideoTaskQueue,
- MediaDataDecoderCallback* aCallback) = 0;
+ MediaDataDecoderCallback* aCallback,
+ DecoderDoctorDiagnostics* aDiagnostics) = 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.
// Output and errors should be returned to the reader via aCallback.
// 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 safe to store a reference to aConfig.
// This is called on the decode task queue.
virtual already_AddRefed<MediaDataDecoder>
CreateAudioDecoder(const AudioInfo& aConfig,
FlushableTaskQueue* aAudioTaskQueue,
- MediaDataDecoderCallback* aCallback) = 0;
+ MediaDataDecoderCallback* aCallback,
+ DecoderDoctorDiagnostics* aDiagnostics) = 0;
};
// A callback used by MediaDataDecoder to return output/errors to the
// MediaFormatReader.
// Implementation is threadsafe, and can be called on any thread.
class MediaDataDecoderCallback {
public:
virtual ~MediaDataDecoderCallback() {}
--- a/dom/media/platforms/agnostic/AgnosticDecoderModule.cpp
+++ b/dom/media/platforms/agnostic/AgnosticDecoderModule.cpp
@@ -8,47 +8,50 @@
#include "OpusDecoder.h"
#include "VorbisDecoder.h"
#include "VPXDecoder.h"
#include "WAVDecoder.h"
namespace mozilla {
bool
-AgnosticDecoderModule::SupportsMimeType(const nsACString& aMimeType) const
+AgnosticDecoderModule::SupportsMimeType(const nsACString& aMimeType,
+ DecoderDoctorDiagnostics* aDiagnostics) const
{
return VPXDecoder::IsVPX(aMimeType) ||
OpusDataDecoder::IsOpus(aMimeType) ||
VorbisDataDecoder::IsVorbis(aMimeType) ||
WaveDataDecoder::IsWave(aMimeType);
}
already_AddRefed<MediaDataDecoder>
AgnosticDecoderModule::CreateVideoDecoder(const VideoInfo& aConfig,
layers::LayersBackend aLayersBackend,
layers::ImageContainer* aImageContainer,
FlushableTaskQueue* aVideoTaskQueue,
- MediaDataDecoderCallback* aCallback)
+ MediaDataDecoderCallback* aCallback,
+ DecoderDoctorDiagnostics* aDiagnostics)
{
RefPtr<MediaDataDecoder> m;
if (VPXDecoder::IsVPX(aConfig.mMimeType)) {
m = new VPXDecoder(*aConfig.GetAsVideoInfo(),
aImageContainer,
aVideoTaskQueue,
aCallback);
}
return m.forget();
}
already_AddRefed<MediaDataDecoder>
AgnosticDecoderModule::CreateAudioDecoder(const AudioInfo& aConfig,
FlushableTaskQueue* aAudioTaskQueue,
- MediaDataDecoderCallback* aCallback)
+ MediaDataDecoderCallback* aCallback,
+ DecoderDoctorDiagnostics* aDiagnostics)
{
RefPtr<MediaDataDecoder> m;
if (VorbisDataDecoder::IsVorbis(aConfig.mMimeType)) {
m = new VorbisDataDecoder(*aConfig.GetAsAudioInfo(),
aAudioTaskQueue,
aCallback);
} else if (OpusDataDecoder::IsOpus(aConfig.mMimeType)) {
--- a/dom/media/platforms/agnostic/AgnosticDecoderModule.h
+++ b/dom/media/platforms/agnostic/AgnosticDecoderModule.h
@@ -5,35 +5,38 @@
namespace mozilla {
class AgnosticDecoderModule : public PlatformDecoderModule {
public:
AgnosticDecoderModule() = default;
virtual ~AgnosticDecoderModule() = default;
- bool SupportsMimeType(const nsACString& aMimeType) const override;
+ bool SupportsMimeType(const nsACString& aMimeType,
+ DecoderDoctorDiagnostics* aDiagnostics) const override;
ConversionRequired
DecoderNeedsConversion(const TrackInfo& aConfig) const override
{
return ConversionRequired::kNeedNone;
}
protected:
// Decode thread.
already_AddRefed<MediaDataDecoder>
CreateVideoDecoder(const VideoInfo& aConfig,
layers::LayersBackend aLayersBackend,
layers::ImageContainer* aImageContainer,
FlushableTaskQueue* aVideoTaskQueue,
- MediaDataDecoderCallback* aCallback) override;
+ MediaDataDecoderCallback* aCallback,
+ DecoderDoctorDiagnostics* aDiagnostics) override;
// Decode thread.
already_AddRefed<MediaDataDecoder>
CreateAudioDecoder(const AudioInfo& aConfig,
FlushableTaskQueue* aAudioTaskQueue,
- MediaDataDecoderCallback* aCallback) override;
+ MediaDataDecoderCallback* aCallback,
+ DecoderDoctorDiagnostics* aDiagnostics) override;
};
} // namespace mozilla
#endif /* AgnosticDecoderModule_h_ */
--- a/dom/media/platforms/agnostic/BlankDecoderModule.cpp
+++ b/dom/media/platforms/agnostic/BlankDecoderModule.cpp
@@ -225,45 +225,48 @@ class BlankDecoderModule : public Platfo
public:
// Decode thread.
already_AddRefed<MediaDataDecoder>
CreateVideoDecoder(const VideoInfo& aConfig,
layers::LayersBackend aLayersBackend,
layers::ImageContainer* aImageContainer,
FlushableTaskQueue* aVideoTaskQueue,
- MediaDataDecoderCallback* aCallback) override {
+ MediaDataDecoderCallback* aCallback,
+ DecoderDoctorDiagnostics* aDiagnostics) override {
BlankVideoDataCreator* creator = new BlankVideoDataCreator(
aConfig.mDisplay.width, aConfig.mDisplay.height, aImageContainer);
RefPtr<MediaDataDecoder> decoder =
new BlankMediaDataDecoder<BlankVideoDataCreator>(creator,
aVideoTaskQueue,
aCallback,
TrackInfo::kVideoTrack);
return decoder.forget();
}
// Decode thread.
already_AddRefed<MediaDataDecoder>
CreateAudioDecoder(const AudioInfo& aConfig,
FlushableTaskQueue* aAudioTaskQueue,
- MediaDataDecoderCallback* aCallback) override {
+ MediaDataDecoderCallback* aCallback,
+ DecoderDoctorDiagnostics* aDiagnostics) override {
BlankAudioDataCreator* creator = new BlankAudioDataCreator(
aConfig.mChannels, aConfig.mRate);
RefPtr<MediaDataDecoder> decoder =
new BlankMediaDataDecoder<BlankAudioDataCreator>(creator,
aAudioTaskQueue,
aCallback,
TrackInfo::kAudioTrack);
return decoder.forget();
}
bool
- SupportsMimeType(const nsACString& aMimeType) const override
+ SupportsMimeType(const nsACString& aMimeType,
+ DecoderDoctorDiagnostics* aDiagnostics) const override
{
return true;
}
ConversionRequired
DecoderNeedsConversion(const TrackInfo& aConfig) const override
{
return kNeedNone;
--- a/dom/media/platforms/agnostic/eme/EMEDecoderModule.cpp
+++ b/dom/media/platforms/agnostic/eme/EMEDecoderModule.cpp
@@ -236,17 +236,18 @@ CreateDecoderWrapper(MediaDataDecoderCal
return decoder.forget();
}
already_AddRefed<MediaDataDecoder>
EMEDecoderModule::CreateVideoDecoder(const VideoInfo& aConfig,
layers::LayersBackend aLayersBackend,
layers::ImageContainer* aImageContainer,
FlushableTaskQueue* aVideoTaskQueue,
- MediaDataDecoderCallback* aCallback)
+ MediaDataDecoderCallback* aCallback,
+ DecoderDoctorDiagnostics* aDiagnostics)
{
MOZ_ASSERT(aConfig.mCrypto.mValid);
if (mCDMDecodesVideo) {
RefPtr<MediaDataDecoderProxy> wrapper = CreateDecoderWrapper(aCallback, mProxy, aVideoTaskQueue);
wrapper->SetProxyTarget(new EMEVideoDecoder(mProxy,
aConfig,
aLayersBackend,
@@ -256,48 +257,50 @@ EMEDecoderModule::CreateVideoDecoder(con
return wrapper.forget();
}
MOZ_ASSERT(mPDM);
RefPtr<MediaDataDecoder> decoder(
mPDM->CreateDecoder(aConfig,
aVideoTaskQueue,
aCallback,
+ aDiagnostics,
aLayersBackend,
aImageContainer));
if (!decoder) {
return nullptr;
}
RefPtr<MediaDataDecoder> emeDecoder(new EMEDecryptor(decoder,
aCallback,
mProxy,
AbstractThread::GetCurrent()->AsTaskQueue()));
return emeDecoder.forget();
}
already_AddRefed<MediaDataDecoder>
EMEDecoderModule::CreateAudioDecoder(const AudioInfo& aConfig,
FlushableTaskQueue* aAudioTaskQueue,
- MediaDataDecoderCallback* aCallback)
+ MediaDataDecoderCallback* aCallback,
+ DecoderDoctorDiagnostics* aDiagnostics)
{
MOZ_ASSERT(aConfig.mCrypto.mValid);
if (mCDMDecodesAudio) {
RefPtr<MediaDataDecoderProxy> wrapper = CreateDecoderWrapper(aCallback, mProxy, aAudioTaskQueue);
wrapper->SetProxyTarget(new EMEAudioDecoder(mProxy,
aConfig,
aAudioTaskQueue,
wrapper->Callback()));
return wrapper.forget();
}
MOZ_ASSERT(mPDM);
RefPtr<MediaDataDecoder> decoder(
- mPDM->CreateDecoder(aConfig, aAudioTaskQueue, aCallback));
+ mPDM->CreateDecoder(aConfig, aAudioTaskQueue, aCallback, aDiagnostics));
if (!decoder) {
return nullptr;
}
RefPtr<MediaDataDecoder> emeDecoder(new EMEDecryptor(decoder,
aCallback,
mProxy,
AbstractThread::GetCurrent()->AsTaskQueue()));
@@ -310,16 +313,17 @@ EMEDecoderModule::DecoderNeedsConversion
if (aConfig.IsVideo()) {
return kNeedAVCC;
} else {
return kNeedNone;
}
}
bool
-EMEDecoderModule::SupportsMimeType(const nsACString& aMimeType) const
+EMEDecoderModule::SupportsMimeType(const nsACString& aMimeType,
+ DecoderDoctorDiagnostics* aDiagnostics) const
{
Maybe<nsCString> gmp;
gmp.emplace(NS_ConvertUTF16toUTF8(mProxy->KeySystem()));
return GMPDecoderModule::SupportsMimeType(aMimeType, gmp);
}
} // namespace mozilla
--- a/dom/media/platforms/agnostic/eme/EMEDecoderModule.h
+++ b/dom/media/platforms/agnostic/eme/EMEDecoderModule.h
@@ -28,29 +28,32 @@ public:
protected:
// Decode thread.
already_AddRefed<MediaDataDecoder>
CreateVideoDecoder(const VideoInfo& aConfig,
layers::LayersBackend aLayersBackend,
layers::ImageContainer* aImageContainer,
FlushableTaskQueue* aVideoTaskQueue,
- MediaDataDecoderCallback* aCallback) override;
+ MediaDataDecoderCallback* aCallback,
+ DecoderDoctorDiagnostics* aDiagnostics) override;
// Decode thread.
already_AddRefed<MediaDataDecoder>
CreateAudioDecoder(const AudioInfo& aConfig,
FlushableTaskQueue* aAudioTaskQueue,
- MediaDataDecoderCallback* aCallback) override;
+ MediaDataDecoderCallback* aCallback,
+ DecoderDoctorDiagnostics* aDiagnostics) override;
ConversionRequired
DecoderNeedsConversion(const TrackInfo& aConfig) const override;
bool
- SupportsMimeType(const nsACString& aMimeType) const override;
+ SupportsMimeType(const nsACString& aMimeType,
+ DecoderDoctorDiagnostics* aDiagnostics) const override;
private:
RefPtr<CDMProxy> mProxy;
// Will be null if CDM has decoding capability.
RefPtr<PDMFactory> mPDM;
// We run the PDM on its own task queue.
RefPtr<TaskQueue> mTaskQueue;
bool mCDMDecodesAudio;
--- a/dom/media/platforms/agnostic/gmp/GMPDecoderModule.cpp
+++ b/dom/media/platforms/agnostic/gmp/GMPDecoderModule.cpp
@@ -43,17 +43,18 @@ CreateDecoderWrapper(MediaDataDecoderCal
return decoder.forget();
}
already_AddRefed<MediaDataDecoder>
GMPDecoderModule::CreateVideoDecoder(const VideoInfo& aConfig,
layers::LayersBackend aLayersBackend,
layers::ImageContainer* aImageContainer,
FlushableTaskQueue* aVideoTaskQueue,
- MediaDataDecoderCallback* aCallback)
+ MediaDataDecoderCallback* aCallback,
+ DecoderDoctorDiagnostics* aDiagnostics)
{
if (!aConfig.mMimeType.EqualsLiteral("video/avc")) {
return nullptr;
}
RefPtr<MediaDataDecoderProxy> wrapper = CreateDecoderWrapper(aCallback);
wrapper->SetProxyTarget(new GMPVideoDecoder(aConfig,
aLayersBackend,
@@ -61,17 +62,18 @@ GMPDecoderModule::CreateVideoDecoder(con
aVideoTaskQueue,
wrapper->Callback()));
return wrapper.forget();
}
already_AddRefed<MediaDataDecoder>
GMPDecoderModule::CreateAudioDecoder(const AudioInfo& aConfig,
FlushableTaskQueue* aAudioTaskQueue,
- MediaDataDecoderCallback* aCallback)
+ MediaDataDecoderCallback* aCallback,
+ DecoderDoctorDiagnostics* aDiagnostics)
{
if (!aConfig.mMimeType.EqualsLiteral("audio/mp4a-latm")) {
return nullptr;
}
RefPtr<MediaDataDecoderProxy> wrapper = CreateDecoderWrapper(aCallback);
wrapper->SetProxyTarget(new GMPAudioDecoder(aConfig,
aAudioTaskQueue,
@@ -97,21 +99,23 @@ HasGMPFor(const nsACString& aAPI,
{
MOZ_ASSERT(NS_IsMainThread());
#ifdef XP_WIN
// gmp-clearkey uses WMF for decoding, so if we're using clearkey we must
// verify that WMF works before continuing.
if (aGMP.EqualsLiteral("org.w3.clearkey")) {
RefPtr<WMFDecoderModule> pdm(new WMFDecoderModule());
if (aCodec.EqualsLiteral("aac") &&
- !pdm->SupportsMimeType(NS_LITERAL_CSTRING("audio/mp4a-latm"))) {
+ !pdm->SupportsMimeType(NS_LITERAL_CSTRING("audio/mp4a-latm"),
+ /* DecoderDoctorDiagnostics* */ nullptr)) {
return false;
}
if (aCodec.EqualsLiteral("h264") &&
- !pdm->SupportsMimeType(NS_LITERAL_CSTRING("video/avc"))) {
+ !pdm->SupportsMimeType(NS_LITERAL_CSTRING("video/avc"),
+ /* DecoderDoctorDiagnostics* */ nullptr)) {
return false;
}
}
#endif
nsTArray<nsCString> tags;
tags.AppendElement(aCodec);
tags.AppendElement(aGMP);
nsCOMPtr<mozIGeckoMediaPluginService> mps =
@@ -220,14 +224,15 @@ GMPDecoderModule::SupportsMimeType(const
return true;
}
}
return false;
}
bool
-GMPDecoderModule::SupportsMimeType(const nsACString& aMimeType) const
+GMPDecoderModule::SupportsMimeType(const nsACString& aMimeType,
+ DecoderDoctorDiagnostics* aDiagnostics) const
{
return SupportsMimeType(aMimeType, PreferredGMP(aMimeType));
}
} // namespace mozilla
--- a/dom/media/platforms/agnostic/gmp/GMPDecoderModule.h
+++ b/dom/media/platforms/agnostic/gmp/GMPDecoderModule.h
@@ -32,29 +32,32 @@ public:
virtual ~GMPDecoderModule();
// Decode thread.
already_AddRefed<MediaDataDecoder>
CreateVideoDecoder(const VideoInfo& aConfig,
layers::LayersBackend aLayersBackend,
layers::ImageContainer* aImageContainer,
FlushableTaskQueue* aVideoTaskQueue,
- MediaDataDecoderCallback* aCallback) override;
+ MediaDataDecoderCallback* aCallback,
+ DecoderDoctorDiagnostics* aDiagnostics) override;
// Decode thread.
already_AddRefed<MediaDataDecoder>
CreateAudioDecoder(const AudioInfo& aConfig,
FlushableTaskQueue* aAudioTaskQueue,
- MediaDataDecoderCallback* aCallback) override;
+ MediaDataDecoderCallback* aCallback,
+ DecoderDoctorDiagnostics* aDiagnostics) override;
ConversionRequired
DecoderNeedsConversion(const TrackInfo& aConfig) const override;
bool
- SupportsMimeType(const nsACString& aMimeType) const override;
+ SupportsMimeType(const nsACString& aMimeType,
+ DecoderDoctorDiagnostics* aDiagnostics) const override;
// Main thread only.
static void Init();
static const Maybe<nsCString> PreferredGMP(const nsACString& aMimeType);
static bool SupportsMimeType(const nsACString& aMimeType,
const Maybe<nsCString>& aGMP);
--- a/dom/media/platforms/android/AndroidDecoderModule.cpp
+++ b/dom/media/platforms/android/AndroidDecoderModule.cpp
@@ -237,17 +237,18 @@ public:
numChannels,
sampleRate);
INVOKE_CALLBACK(Output, data);
return NS_OK;
}
};
bool
-AndroidDecoderModule::SupportsMimeType(const nsACString& aMimeType) const
+AndroidDecoderModule::SupportsMimeType(const nsACString& aMimeType,
+ DecoderDoctorDiagnostics* aDiagnostics) const
{
if (!AndroidBridge::Bridge() ||
AndroidBridge::Bridge()->GetAPIVersion() < 16) {
return false;
}
if (aMimeType.EqualsLiteral("video/mp4") ||
aMimeType.EqualsLiteral("video/avc")) {
@@ -275,17 +276,18 @@ AndroidDecoderModule::SupportsMimeType(c
return widget::HardwareCodecCapabilityUtils::FindDecoderCodecInfoForMimeType(
nsCString(TranslateMimeType(aMimeType)));
}
already_AddRefed<MediaDataDecoder>
AndroidDecoderModule::CreateVideoDecoder(
const VideoInfo& aConfig, layers::LayersBackend aLayersBackend,
layers::ImageContainer* aImageContainer, FlushableTaskQueue* aVideoTaskQueue,
- MediaDataDecoderCallback* aCallback)
+ MediaDataDecoderCallback* aCallback,
+ DecoderDoctorDiagnostics* aDiagnostics)
{
MediaFormat::LocalRef format;
NS_ENSURE_SUCCESS(MediaFormat::CreateVideoFormat(
TranslateMimeType(aConfig.mMimeType),
aConfig.mDisplay.width,
aConfig.mDisplay.height,
&format), nullptr);
@@ -294,17 +296,18 @@ AndroidDecoderModule::CreateVideoDecoder
new VideoDataDecoder(aConfig, format, aCallback, aImageContainer);
return decoder.forget();
}
already_AddRefed<MediaDataDecoder>
AndroidDecoderModule::CreateAudioDecoder(
const AudioInfo& aConfig, FlushableTaskQueue* aAudioTaskQueue,
- MediaDataDecoderCallback* aCallback)
+ MediaDataDecoderCallback* aCallback,
+ DecoderDoctorDiagnostics* aDiagnostics)
{
MOZ_ASSERT(aConfig.mBitDepth == 16, "We only handle 16-bit audio!");
MediaFormat::LocalRef format;
LOG("CreateAudioFormat with mimeType=%s, mRate=%d, channels=%d",
aConfig.mMimeType.Data(), aConfig.mRate, aConfig.mChannels);
--- a/dom/media/platforms/android/AndroidDecoderModule.h
+++ b/dom/media/platforms/android/AndroidDecoderModule.h
@@ -20,28 +20,31 @@ typedef std::queue<RefPtr<MediaRawData>>
class AndroidDecoderModule : public PlatformDecoderModule {
public:
already_AddRefed<MediaDataDecoder>
CreateVideoDecoder(const VideoInfo& aConfig,
layers::LayersBackend aLayersBackend,
layers::ImageContainer* aImageContainer,
FlushableTaskQueue* aVideoTaskQueue,
- MediaDataDecoderCallback* aCallback) override;
+ MediaDataDecoderCallback* aCallback,
+ DecoderDoctorDiagnostics* aDiagnostics) override;
already_AddRefed<MediaDataDecoder>
CreateAudioDecoder(const AudioInfo& aConfig,
FlushableTaskQueue* aAudioTaskQueue,
- MediaDataDecoderCallback* aCallback) override;
+ MediaDataDecoderCallback* aCallback,
+ DecoderDoctorDiagnostics* aDiagnostics) override;
AndroidDecoderModule() {}
virtual ~AndroidDecoderModule() {}
- bool SupportsMimeType(const nsACString& aMimeType) const override;
+ bool SupportsMimeType(const nsACString& aMimeType,
+ DecoderDoctorDiagnostics* aDiagnostics) const override;
ConversionRequired
DecoderNeedsConversion(const TrackInfo& aConfig) const override;
};
class MediaCodecDataDecoder : public MediaDataDecoder {
public:
--- a/dom/media/platforms/apple/AppleDecoderModule.cpp
+++ b/dom/media/platforms/apple/AppleDecoderModule.cpp
@@ -78,17 +78,18 @@ AppleDecoderModule::Startup()
return NS_OK;
}
already_AddRefed<MediaDataDecoder>
AppleDecoderModule::CreateVideoDecoder(const VideoInfo& aConfig,
layers::LayersBackend aLayersBackend,
layers::ImageContainer* aImageContainer,
FlushableTaskQueue* aVideoTaskQueue,
- MediaDataDecoderCallback* aCallback)
+ MediaDataDecoderCallback* aCallback,
+ DecoderDoctorDiagnostics* aDiagnostics)
{
RefPtr<MediaDataDecoder> decoder;
if (sIsVDAAvailable && (!sIsVTHWAvailable || sForceVDA)) {
decoder =
AppleVDADecoder::CreateVDADecoder(aConfig,
aVideoTaskQueue,
aCallback,
@@ -104,25 +105,27 @@ AppleDecoderModule::CreateVideoDecoder(c
new AppleVTDecoder(aConfig, aVideoTaskQueue, aCallback, aImageContainer);
}
return decoder.forget();
}
already_AddRefed<MediaDataDecoder>
AppleDecoderModule::CreateAudioDecoder(const AudioInfo& aConfig,
FlushableTaskQueue* aAudioTaskQueue,
- MediaDataDecoderCallback* aCallback)
+ MediaDataDecoderCallback* aCallback,
+ DecoderDoctorDiagnostics* aDiagnostics)
{
RefPtr<MediaDataDecoder> decoder =
new AppleATDecoder(aConfig, aAudioTaskQueue, aCallback);
return decoder.forget();
}
bool
-AppleDecoderModule::SupportsMimeType(const nsACString& aMimeType) const
+AppleDecoderModule::SupportsMimeType(const nsACString& aMimeType,
+ DecoderDoctorDiagnostics* aDiagnostics) const
{
return (sIsCoreMediaAvailable &&
(aMimeType.EqualsLiteral("audio/mpeg") ||
aMimeType.EqualsLiteral("audio/mp4a-latm"))) ||
((sIsVTAvailable || sIsVDAAvailable) &&
(aMimeType.EqualsLiteral("video/mp4") ||
aMimeType.EqualsLiteral("video/avc")));
}
--- a/dom/media/platforms/apple/AppleDecoderModule.h
+++ b/dom/media/platforms/apple/AppleDecoderModule.h
@@ -19,25 +19,28 @@ public:
nsresult Startup() override;
// Decode thread.
already_AddRefed<MediaDataDecoder>
CreateVideoDecoder(const VideoInfo& aConfig,
layers::LayersBackend aLayersBackend,
layers::ImageContainer* aImageContainer,
FlushableTaskQueue* aVideoTaskQueue,
- MediaDataDecoderCallback* aCallback) override;
+ MediaDataDecoderCallback* aCallback,
+ DecoderDoctorDiagnostics* aDiagnostics) override;
// Decode thread.
already_AddRefed<MediaDataDecoder>
CreateAudioDecoder(const AudioInfo& aConfig,
FlushableTaskQueue* aAudioTaskQueue,
- MediaDataDecoderCallback* aCallback) override;
+ MediaDataDecoderCallback* aCallback,
+ DecoderDoctorDiagnostics* aDiagnostics) override;
- bool SupportsMimeType(const nsACString& aMimeType) const override;
+ bool SupportsMimeType(const nsACString& aMimeType,
+ DecoderDoctorDiagnostics* aDiagnostics) const override;
ConversionRequired
DecoderNeedsConversion(const TrackInfo& aConfig) const override;
static void Init();
static bool sCanUseHardwareVideoDecoder;
--- a/dom/media/platforms/ffmpeg/FFmpegDecoderModule.h
+++ b/dom/media/platforms/ffmpeg/FFmpegDecoderModule.h
@@ -30,39 +30,42 @@ public:
explicit FFmpegDecoderModule(FFmpegLibWrapper* aLib) : mLib(aLib) {}
virtual ~FFmpegDecoderModule() {}
already_AddRefed<MediaDataDecoder>
CreateVideoDecoder(const VideoInfo& aConfig,
layers::LayersBackend aLayersBackend,
layers::ImageContainer* aImageContainer,
FlushableTaskQueue* aVideoTaskQueue,
- MediaDataDecoderCallback* aCallback) override
+ MediaDataDecoderCallback* aCallback,
+ DecoderDoctorDiagnostics* aDiagnostics) override
{
RefPtr<MediaDataDecoder> decoder =
new FFmpegVideoDecoder<V>(mLib, aVideoTaskQueue, aCallback, aConfig,
aImageContainer);
return decoder.forget();
}
already_AddRefed<MediaDataDecoder>
CreateAudioDecoder(const AudioInfo& aConfig,
FlushableTaskQueue* aAudioTaskQueue,
- MediaDataDecoderCallback* aCallback) override
+ MediaDataDecoderCallback* aCallback,
+ DecoderDoctorDiagnostics* aDiagnostics) override
{
#ifdef USING_MOZFFVPX
return nullptr;
#else
RefPtr<MediaDataDecoder> decoder =
new FFmpegAudioDecoder<V>(mLib, aAudioTaskQueue, aCallback, aConfig);
return decoder.forget();
#endif
}
- bool SupportsMimeType(const nsACString& aMimeType) const override
+ bool SupportsMimeType(const nsACString& aMimeType,
+ DecoderDoctorDiagnostics* aDiagnostics) const override
{
AVCodecID videoCodec = FFmpegVideoDecoder<V>::GetCodecId(aMimeType);
#ifdef USING_MOZFFVPX
if (videoCodec == AV_CODEC_ID_NONE) {
return false;
}
return !!FFmpegDataDecoder<V>::FindAVCodec(mLib, videoCodec);
#else
--- a/dom/media/platforms/gonk/GonkDecoderModule.cpp
+++ b/dom/media/platforms/gonk/GonkDecoderModule.cpp
@@ -26,28 +26,30 @@ GonkDecoderModule::Init()
MOZ_ASSERT(NS_IsMainThread(), "Must be on main thread.");
}
already_AddRefed<MediaDataDecoder>
GonkDecoderModule::CreateVideoDecoder(const VideoInfo& aConfig,
mozilla::layers::LayersBackend aLayersBackend,
mozilla::layers::ImageContainer* aImageContainer,
FlushableTaskQueue* aVideoTaskQueue,
- MediaDataDecoderCallback* aCallback)
+ MediaDataDecoderCallback* aCallback,
+ DecoderDoctorDiagnostics* aDiagnostics)
{
RefPtr<MediaDataDecoder> decoder =
new GonkMediaDataDecoder(new GonkVideoDecoderManager(aImageContainer, aConfig),
aVideoTaskQueue, aCallback);
return decoder.forget();
}
already_AddRefed<MediaDataDecoder>
GonkDecoderModule::CreateAudioDecoder(const AudioInfo& aConfig,
FlushableTaskQueue* aAudioTaskQueue,
- MediaDataDecoderCallback* aCallback)
+ MediaDataDecoderCallback* aCallback,
+ DecoderDoctorDiagnostics* aDiagnostics)
{
RefPtr<MediaDataDecoder> decoder =
new GonkMediaDataDecoder(new GonkAudioDecoderManager(aConfig),
aAudioTaskQueue, aCallback);
return decoder.forget();
}
PlatformDecoderModule::ConversionRequired
@@ -56,17 +58,18 @@ GonkDecoderModule::DecoderNeedsConversio
if (aConfig.IsVideo()) {
return kNeedAnnexB;
} else {
return kNeedNone;
}
}
bool
-GonkDecoderModule::SupportsMimeType(const nsACString& aMimeType) const
+GonkDecoderModule::SupportsMimeType(const nsACString& aMimeType,
+ DecoderDoctorDiagnostics* aDiagnostics) const
{
return aMimeType.EqualsLiteral("audio/mp4a-latm") ||
aMimeType.EqualsLiteral("audio/3gpp") ||
aMimeType.EqualsLiteral("audio/amr-wb") ||
aMimeType.EqualsLiteral("audio/mpeg") ||
aMimeType.EqualsLiteral("video/mp4") ||
aMimeType.EqualsLiteral("video/mp4v-es") ||
aMimeType.EqualsLiteral("video/avc") ||
--- a/dom/media/platforms/gonk/GonkDecoderModule.h
+++ b/dom/media/platforms/gonk/GonkDecoderModule.h
@@ -17,28 +17,31 @@ public:
virtual ~GonkDecoderModule();
// Decode thread.
already_AddRefed<MediaDataDecoder>
CreateVideoDecoder(const VideoInfo& aConfig,
mozilla::layers::LayersBackend aLayersBackend,
mozilla::layers::ImageContainer* aImageContainer,
FlushableTaskQueue* aVideoTaskQueue,
- MediaDataDecoderCallback* aCallback) override;
+ MediaDataDecoderCallback* aCallback,
+ DecoderDoctorDiagnostics* aDiagnostics) override;
// Decode thread.
already_AddRefed<MediaDataDecoder>
CreateAudioDecoder(const AudioInfo& aConfig,
FlushableTaskQueue* aAudioTaskQueue,
- MediaDataDecoderCallback* aCallback) override;
+ MediaDataDecoderCallback* aCallback,
+ DecoderDoctorDiagnostics* aDiagnostics) override;
static void Init();
ConversionRequired
DecoderNeedsConversion(const TrackInfo& aConfig) const override;
- bool SupportsMimeType(const nsACString& aMimeType) const override;
+ bool SupportsMimeType(const nsACString& aMimeType,
+ DecoderDoctorDiagnostics* aDiagnostics) const override;
};
} // namespace mozilla
#endif
--- a/dom/media/platforms/omx/OmxDecoderModule.cpp
+++ b/dom/media/platforms/omx/OmxDecoderModule.cpp
@@ -11,26 +11,28 @@
namespace mozilla {
already_AddRefed<MediaDataDecoder>
OmxDecoderModule::CreateVideoDecoder(const VideoInfo& aConfig,
mozilla::layers::LayersBackend aLayersBackend,
mozilla::layers::ImageContainer* aImageContainer,
FlushableTaskQueue* aVideoTaskQueue,
- MediaDataDecoderCallback* aCallback)
+ MediaDataDecoderCallback* aCallback,
+ DecoderDoctorDiagnostics* aDiagnostics)
{
RefPtr<OmxDataDecoder> decoder = new OmxDataDecoder(aConfig, aCallback, aImageContainer);
return decoder.forget();
}
already_AddRefed<MediaDataDecoder>
OmxDecoderModule::CreateAudioDecoder(const AudioInfo& aConfig,
FlushableTaskQueue* aAudioTaskQueue,
- MediaDataDecoderCallback* aCallback)
+ MediaDataDecoderCallback* aCallback,
+ DecoderDoctorDiagnostics* aDiagnostics)
{
RefPtr<OmxDataDecoder> decoder = new OmxDataDecoder(aConfig, aCallback, nullptr);
return decoder.forget();
}
void
OmxDecoderModule::Init()
{
@@ -39,14 +41,15 @@ OmxDecoderModule::Init()
PlatformDecoderModule::ConversionRequired
OmxDecoderModule::DecoderNeedsConversion(const TrackInfo& aConfig) const
{
return kNeedNone;
}
bool
-OmxDecoderModule::SupportsMimeType(const nsACString& aMimeType) const
+OmxDecoderModule::SupportsMimeType(const nsACString& aMimeType,
+ DecoderDoctorDiagnostics* aDiagnostics) const
{
return OmxPlatformLayer::SupportsMimeType(aMimeType);
}
}
--- a/dom/media/platforms/omx/OmxDecoderModule.h
+++ b/dom/media/platforms/omx/OmxDecoderModule.h
@@ -13,25 +13,28 @@ namespace mozilla {
class OmxDecoderModule : public PlatformDecoderModule {
public:
already_AddRefed<MediaDataDecoder>
CreateVideoDecoder(const VideoInfo& aConfig,
mozilla::layers::LayersBackend aLayersBackend,
mozilla::layers::ImageContainer* aImageContainer,
FlushableTaskQueue* aVideoTaskQueue,
- MediaDataDecoderCallback* aCallback) override;
+ MediaDataDecoderCallback* aCallback,
+ DecoderDoctorDiagnostics* aDiagnostics) override;
already_AddRefed<MediaDataDecoder>
CreateAudioDecoder(const AudioInfo& aConfig,
FlushableTaskQueue* aAudioTaskQueue,
- MediaDataDecoderCallback* aCallback) override;
+ MediaDataDecoderCallback* aCallback,
+ DecoderDoctorDiagnostics* aDiagnostics) override;
static void Init();
- bool SupportsMimeType(const nsACString& aMimeType) const override;
+ bool SupportsMimeType(const nsACString& aMimeType,
+ DecoderDoctorDiagnostics* aDiagnostics) const override;
ConversionRequired DecoderNeedsConversion(const TrackInfo& aConfig) const override;
};
} // namespace mozilla
#endif // OmxDecoderModule_h_
--- a/dom/media/platforms/wmf/WMFDecoderModule.cpp
+++ b/dom/media/platforms/wmf/WMFDecoderModule.cpp
@@ -97,17 +97,18 @@ WMFDecoderModule::Startup()
return mWMFInitialized ? NS_OK : NS_ERROR_FAILURE;
}
already_AddRefed<MediaDataDecoder>
WMFDecoderModule::CreateVideoDecoder(const VideoInfo& aConfig,
layers::LayersBackend aLayersBackend,
layers::ImageContainer* aImageContainer,
FlushableTaskQueue* aVideoTaskQueue,
- MediaDataDecoderCallback* aCallback)
+ MediaDataDecoderCallback* aCallback,
+ DecoderDoctorDiagnostics* aDiagnostics)
{
nsAutoPtr<WMFVideoMFTManager> manager(
new WMFVideoMFTManager(aConfig,
aLayersBackend,
aImageContainer,
sDXVAEnabled));
if (!manager->Init()) {
@@ -118,17 +119,18 @@ WMFDecoderModule::CreateVideoDecoder(con
new WMFMediaDataDecoder(manager.forget(), aVideoTaskQueue, aCallback);
return decoder.forget();
}
already_AddRefed<MediaDataDecoder>
WMFDecoderModule::CreateAudioDecoder(const AudioInfo& aConfig,
FlushableTaskQueue* aAudioTaskQueue,
- MediaDataDecoderCallback* aCallback)
+ MediaDataDecoderCallback* aCallback,
+ DecoderDoctorDiagnostics* aDiagnostics)
{
nsAutoPtr<WMFAudioMFTManager> manager(new WMFAudioMFTManager(aConfig));
if (!manager->Init()) {
return nullptr;
}
RefPtr<MediaDataDecoder> decoder =
@@ -208,17 +210,18 @@ WMFDecoderModule::HasH264()
/* static */ bool
WMFDecoderModule::HasAAC()
{
return CanCreateWMFDecoder<CLSID_CMSAACDecMFT>();
}
bool
-WMFDecoderModule::SupportsMimeType(const nsACString& aMimeType) const
+WMFDecoderModule::SupportsMimeType(const nsACString& aMimeType,
+ DecoderDoctorDiagnostics* aDiagnostics) const
{
if ((aMimeType.EqualsLiteral("audio/mp4a-latm") ||
aMimeType.EqualsLiteral("audio/mp4")) &&
WMFDecoderModule::HasAAC()) {
return true;
}
if ((aMimeType.EqualsLiteral("video/avc") ||
aMimeType.EqualsLiteral("video/mp4")) &&
--- a/dom/media/platforms/wmf/WMFDecoderModule.h
+++ b/dom/media/platforms/wmf/WMFDecoderModule.h
@@ -19,24 +19,27 @@ public:
// Initializes the module, loads required dynamic libraries, etc.
nsresult Startup() override;
already_AddRefed<MediaDataDecoder>
CreateVideoDecoder(const VideoInfo& aConfig,
layers::LayersBackend aLayersBackend,
layers::ImageContainer* aImageContainer,
FlushableTaskQueue* aVideoTaskQueue,
- MediaDataDecoderCallback* aCallback) override;
+ MediaDataDecoderCallback* aCallback,
+ DecoderDoctorDiagnostics* aDiagnostics) override;
already_AddRefed<MediaDataDecoder>
CreateAudioDecoder(const AudioInfo& aConfig,
FlushableTaskQueue* aAudioTaskQueue,
- MediaDataDecoderCallback* aCallback) override;
+ MediaDataDecoderCallback* aCallback,
+ DecoderDoctorDiagnostics* aDiagnostics) override;
- bool SupportsMimeType(const nsACString& aMimeType) const override;
+ bool SupportsMimeType(const nsACString& aMimeType,
+ DecoderDoctorDiagnostics* aDiagnostics) const override;
ConversionRequired
DecoderNeedsConversion(const TrackInfo& aConfig) const override;
// Called on main thread.
static void Init();
// Called from any thread, must call init first
--- a/dom/media/platforms/wrappers/H264Converter.cpp
+++ b/dom/media/platforms/wrappers/H264Converter.cpp
@@ -15,29 +15,30 @@
namespace mozilla
{
H264Converter::H264Converter(PlatformDecoderModule* aPDM,
const VideoInfo& aConfig,
layers::LayersBackend aLayersBackend,
layers::ImageContainer* aImageContainer,
FlushableTaskQueue* aVideoTaskQueue,
- MediaDataDecoderCallback* aCallback)
+ MediaDataDecoderCallback* aCallback,
+ DecoderDoctorDiagnostics* aDiagnostics)
: mPDM(aPDM)
, mOriginalConfig(aConfig)
, mCurrentConfig(aConfig)
, mLayersBackend(aLayersBackend)
, mImageContainer(aImageContainer)
, mVideoTaskQueue(aVideoTaskQueue)
, mCallback(aCallback)
, mDecoder(nullptr)
, mNeedAVCC(aPDM->DecoderNeedsConversion(aConfig) == PlatformDecoderModule::kNeedAVCC)
, mLastError(NS_OK)
{
- CreateDecoder();
+ CreateDecoder(aDiagnostics);
}
H264Converter::~H264Converter()
{
}
RefPtr<MediaDataDecoder::InitPromise>
H264Converter::Init()
@@ -127,34 +128,35 @@ H264Converter::IsHardwareAccelerated(nsA
{
if (mDecoder) {
return mDecoder->IsHardwareAccelerated(aFailureReason);
}
return MediaDataDecoder::IsHardwareAccelerated(aFailureReason);
}
nsresult
-H264Converter::CreateDecoder()
+H264Converter::CreateDecoder(DecoderDoctorDiagnostics* aDiagnostics)
{
if (mNeedAVCC && !mp4_demuxer::AnnexB::HasSPS(mCurrentConfig.mExtraData)) {
// nothing found yet, will try again later
return NS_ERROR_NOT_INITIALIZED;
}
UpdateConfigFromExtraData(mCurrentConfig.mExtraData);
if (!mNeedAVCC) {
// When using a decoder handling AnnexB, we get here only once from the
// constructor. We do want to get the dimensions extracted from the SPS.
mOriginalConfig = mCurrentConfig;
}
mDecoder = mPDM->CreateVideoDecoder(mNeedAVCC ? mCurrentConfig : mOriginalConfig,
mLayersBackend,
mImageContainer,
mVideoTaskQueue,
- mCallback);
+ mCallback,
+ aDiagnostics);
if (!mDecoder) {
mLastError = NS_ERROR_FAILURE;
return NS_ERROR_FAILURE;
}
return NS_OK;
}
nsresult
@@ -162,17 +164,17 @@ H264Converter::CreateDecoderAndInit(Medi
{
RefPtr<MediaByteBuffer> extra_data =
mp4_demuxer::AnnexB::ExtractExtraData(aSample);
if (!mp4_demuxer::AnnexB::HasSPS(extra_data)) {
return NS_ERROR_NOT_INITIALIZED;
}
UpdateConfigFromExtraData(extra_data);
- nsresult rv = CreateDecoder();
+ nsresult rv = CreateDecoder(/* DecoderDoctorDiagnostics* */ nullptr);
if (NS_SUCCEEDED(rv)) {
// Queue the incoming sample.
mMediaRawSamples.AppendElement(aSample);
RefPtr<H264Converter> self = this;
mInitPromiseRequest.Begin(mDecoder->Init()
--- a/dom/media/platforms/wrappers/H264Converter.h
+++ b/dom/media/platforms/wrappers/H264Converter.h
@@ -21,17 +21,18 @@ namespace mozilla {
class H264Converter : public MediaDataDecoder {
public:
H264Converter(PlatformDecoderModule* aPDM,
const VideoInfo& aConfig,
layers::LayersBackend aLayersBackend,
layers::ImageContainer* aImageContainer,
FlushableTaskQueue* aVideoTaskQueue,
- MediaDataDecoderCallback* aCallback);
+ MediaDataDecoderCallback* aCallback,
+ DecoderDoctorDiagnostics* aDiagnostics);
virtual ~H264Converter();
RefPtr<InitPromise> Init() override;
nsresult Input(MediaRawData* aSample) override;
nsresult Flush() override;
nsresult Drain() override;
nsresult Shutdown() override;
bool IsHardwareAccelerated(nsACString& aFailureReason) const override;
@@ -46,17 +47,17 @@ public:
// Return true if mimetype is H.264.
static bool IsH264(const TrackInfo& aConfig);
nsresult GetLastError() const { return mLastError; }
private:
// Will create the required MediaDataDecoder if need AVCC and we have a SPS NAL.
// Returns NS_ERROR_FAILURE if error is permanent and can't be recovered and
// will set mError accordingly.
- nsresult CreateDecoder();
+ nsresult CreateDecoder(DecoderDoctorDiagnostics* aDiagnostics);
nsresult CreateDecoderAndInit(MediaRawData* aSample);
nsresult CheckForSPSChange(MediaRawData* aSample);
void UpdateConfigFromExtraData(MediaByteBuffer* aExtraData);
void OnDecoderInitDone(const TrackType aTrackType);
void OnDecoderInitFailed(MediaDataDecoder::DecoderFailureReason aReason);
RefPtr<PlatformDecoderModule> mPDM;
--- a/dom/media/wave/WaveDecoder.cpp
+++ b/dom/media/wave/WaveDecoder.cpp
@@ -37,17 +37,18 @@ bool
WaveDecoder::IsEnabled()
{
MOZ_ASSERT(NS_IsMainThread());
if (!Preferences::GetBool("media.wave.decoder.enabled", false)) {
return false;
}
PDMFactory::Init();
RefPtr<PDMFactory> platform = new PDMFactory();
- return platform->SupportsMimeType(NS_LITERAL_CSTRING("audio/x-wav"));
+ return platform->SupportsMimeType(NS_LITERAL_CSTRING("audio/x-wav"),
+ /* DecoderDoctorDiagnostics* */ nullptr);
}
/* static */
bool
WaveDecoder::CanHandleMediaType(const nsACString& aType,
const nsAString& aCodecs)
{
if (aType.EqualsASCII("audio/wave") || aType.EqualsASCII("audio/x-wav") ||
--- a/layout/build/nsContentDLF.cpp
+++ b/layout/build/nsContentDLF.cpp
@@ -207,17 +207,18 @@ nsContentDLF::CreateInstance(const char*
if (!MayUseXULXBL(aChannel)) {
return NS_ERROR_REMOTE_XUL;
}
return CreateXULDocument(aCommand, aChannel, aLoadGroup, aContainer,
aExtraInfo, aDocListener, aDocViewer);
}
- if (mozilla::DecoderTraits::ShouldHandleMediaType(contentType.get())) {
+ if (mozilla::DecoderTraits::ShouldHandleMediaType(contentType.get(),
+ /* DecoderDoctorDiagnostics* */ nullptr)) {
return CreateDocument(aCommand,
aChannel, aLoadGroup,
aContainer, kVideoDocumentCID,
aDocListener, aDocViewer);
}
// Try image types
if (IsImageContentType(contentType.get())) {