--- a/dom/locales/en-US/chrome/dom/dom.properties
+++ b/dom/locales/en-US/chrome/dom/dom.properties
@@ -102,21 +102,24 @@ MediaLoadInvalidURI=Invalid URI. Load of
# LOCALIZATION NOTE: %1$S is the media resource's format/codec type (basically equivalent to the file type, e.g. MP4,AVI,WMV,MOV etc), %2$S is the URL of the media resource which failed to load.
MediaLoadUnsupportedTypeAttribute=Specified "type" attribute of "%1$S" is not supported. Load of media resource %2$S failed.
# LOCALIZATION NOTE: %1$S is the "media" attribute value of the <source> element. It is a media query. %2$S is the URL of the media resource which failed to load.
MediaLoadSourceMediaNotMatched=Specified "media" attribute of "%1$S" does not match the environment. Load of media resource %2$S failed.
# LOCALIZATION NOTE: %1$S is the MIME type HTTP header being sent by the web server, %2$S is the URL of the media resource which failed to load.
MediaLoadUnsupportedMimeType=HTTP "Content-Type" of "%1$S" is not supported. Load of media resource %2$S failed.
# LOCALIZATION NOTE: %S is the URL of the media resource which failed to load because of error in decoding.
MediaLoadDecodeError=Media resource %S could not be decoded.
+MediaWidevineNoWMFNoSilverlight=Trying to play Widevine with no Windows Media Foundation (nor Silverlight fallback), see https://support.mozilla.org/kb/fix-video-audio-problems-firefox-windows
+# LOCALIZATION NOTE: %S is a comma-separated list of codecs (e.g. 'video/mp4, video/webm')
+MediaWMFNeeded=To play video formats %S, you need to install extra Microsoft software, see https://support.mozilla.org/kb/fix-video-audio-problems-firefox-windows
+# LOCALIZATION NOTE: %S is a comma-separated list of codecs (e.g. 'video/mp4, video/webm')
+MediaPlatformDecoderNotFound=The video on this page can't be played. Your system may not have the required video codecs for: %S
# LOCALIZATION NOTE: %S is a comma-separated list of codecs (e.g. 'video/mp4, video/webm')
MediaCannotPlayNoDecoders=Cannot play media. No decoders for requested formats: %S
# LOCALIZATION NOTE: %S is a comma-separated list of codecs (e.g. 'video/mp4, video/webm')
-MediaPlatformDecoderNotFound=The video on this page can't be played. Your system may not have the required video codecs for: %S
-# LOCALIZATION NOTE: %S is a comma-separated list of codecs (e.g. 'video/mp4, video/webm')
MediaNoDecoders=No decoders for some of the requested formats: %S
# LOCALIZATION NOTE: Do not translate "MediaRecorder".
MediaRecorderMultiTracksNotSupported=MediaRecorder does not support recording multiple tracks of the same type at this time.
# LOCALIZATION NOTE: %S is the ID of the MediaStreamTrack passed to MediaStream.addTrack(). Do not translate "MediaStreamTrack" and "AudioChannel".
MediaStreamAddTrackDifferentAudioChannel=MediaStreamTrack %S could not be added since it belongs to a different AudioChannel.
# LOCALIZATION NOTE: Do not translate "MediaStream", "stop()" and "MediaStreamTrack"
MediaStreamStopDeprecatedWarning=MediaStream.stop() is deprecated and will soon be removed. Use MediaStreamTrack.stop() instead.
# LOCALIZATION NOTE: Do not translate "DOMException", "code" and "name"
--- a/dom/media/DecoderDoctorDiagnostics.cpp
+++ b/dom/media/DecoderDoctorDiagnostics.cpp
@@ -261,41 +261,42 @@ DispatchNotification(nsISupports* aSubje
obs->NotifyObservers(aSubject, "decoder-doctor-notification", json.get());
}
}
void
DecoderDoctorDocumentWatcher::ReportAnalysis(
dom::DecoderDoctorNotificationType aNotificationType,
const char* aReportStringId,
- const nsAString& aFormats)
+ const nsAString& aParams)
{
MOZ_ASSERT(NS_IsMainThread());
if (!mDocument) {
return;
}
- const char16_t* params[] = { aFormats.Data() };
+ // 'params' will only be forwarded for non-empty strings.
+ const char16_t* params[1] = { aParams.Data() };
DD_DEBUG("DecoderDoctorDocumentWatcher[%p, doc=%p]::ReportAnalysis() ReportToConsole - aMsg='%s' params[0]='%s'",
this, mDocument, aReportStringId,
- NS_ConvertUTF16toUTF8(params[0]).get());
+ aParams.IsEmpty() ? "<no params>" : NS_ConvertUTF16toUTF8(params[0]).get());
nsContentUtils::ReportToConsole(nsIScriptError::warningFlag,
NS_LITERAL_CSTRING("Media"),
mDocument,
nsContentUtils::eDOM_PROPERTIES,
aReportStringId,
- params,
- ArrayLength(params));
+ aParams.IsEmpty() ? nullptr : params,
+ aParams.IsEmpty() ? 0 : 1);
// For now, disable all front-end notifications by default.
// TODO: Future bugs will use finer-grained filtering instead.
if (Preferences::GetBool("media.decoderdoctor.enable-notification-bar", false)) {
DispatchNotification(
- mDocument->GetInnerWindow(), aNotificationType, aFormats);
+ mDocument->GetInnerWindow(), aNotificationType, aParams);
}
}
enum SilverlightPresence {
eNoSilverlight,
eSilverlightDisabled,
eSilverlightEnabled
};
@@ -316,89 +317,143 @@ CheckSilverlight()
return plugin->IsEnabled() ? eSilverlightEnabled : eSilverlightDisabled;
}
}
}
return eNoSilverlight;
}
+static void AppendToStringList(nsAString& list, const nsAString& item)
+{
+ if (!list.IsEmpty()) {
+ list += NS_LITERAL_STRING(", ");
+ }
+ list += item;
+}
+
void
DecoderDoctorDocumentWatcher::SynthesizeAnalysis()
{
MOZ_ASSERT(NS_IsMainThread());
bool canPlay = false;
+#if defined(XP_WIN)
+ bool WMFNeeded = false;
+#endif
#if defined(MOZ_FFMPEG)
bool FFMpegNeeded = false;
#endif
+ nsAutoString playableFormats;
nsAutoString unplayableFormats;
+ nsAutoString supportedKeySystems;
nsAutoString unsupportedKeySystems;
+ DecoderDoctorDiagnostics::KeySystemIssue lastKeySystemIssue =
+ DecoderDoctorDiagnostics::eUnset;
for (auto& diag : mDiagnosticsSequence) {
switch (diag.mDecoderDoctorDiagnostics.Type()) {
case DecoderDoctorDiagnostics::eFormatSupportCheck:
if (diag.mDecoderDoctorDiagnostics.CanPlay()) {
canPlay = true;
+ AppendToStringList(playableFormats,
+ diag.mDecoderDoctorDiagnostics.Format());
} else {
+#if defined(XP_WIN)
+ if (diag.mDecoderDoctorDiagnostics.DidWMFFailToLoad()) {
+ WMFNeeded = true;
+ }
+#endif
#if defined(MOZ_FFMPEG)
if (diag.mDecoderDoctorDiagnostics.DidFFmpegFailToLoad()) {
FFMpegNeeded = true;
}
#endif
- if (!unplayableFormats.IsEmpty()) {
- unplayableFormats += NS_LITERAL_STRING(", ");
- }
- unplayableFormats += diag.mDecoderDoctorDiagnostics.Format();
+ AppendToStringList(unplayableFormats,
+ diag.mDecoderDoctorDiagnostics.Format());
}
break;
case DecoderDoctorDiagnostics::eMediaKeySystemAccessRequest:
- if (!diag.mDecoderDoctorDiagnostics.IsKeySystemSupported()) {
- if (!unsupportedKeySystems.IsEmpty()) {
- unsupportedKeySystems += NS_LITERAL_STRING(", ");
+ if (diag.mDecoderDoctorDiagnostics.IsKeySystemSupported()) {
+ AppendToStringList(supportedKeySystems,
+ diag.mDecoderDoctorDiagnostics.KeySystem());
+ } else {
+ AppendToStringList(unsupportedKeySystems,
+ diag.mDecoderDoctorDiagnostics.KeySystem());
+ DecoderDoctorDiagnostics::KeySystemIssue issue =
+ diag.mDecoderDoctorDiagnostics.GetKeySystemIssue();
+ if (issue != DecoderDoctorDiagnostics::eUnset) {
+ lastKeySystemIssue = issue;
}
- unsupportedKeySystems += diag.mDecoderDoctorDiagnostics.KeySystem();
}
break;
default:
MOZ_ASSERT(diag.mDecoderDoctorDiagnostics.Type()
== DecoderDoctorDiagnostics::eFormatSupportCheck
|| diag.mDecoderDoctorDiagnostics.Type()
== DecoderDoctorDiagnostics::eMediaKeySystemAccessRequest);
break;
}
}
- if (!canPlay) {
+ // Look at Key System issues first, as they may influence format checks.
+ if (!unsupportedKeySystems.IsEmpty() && supportedKeySystems.IsEmpty()) {
+ // No supported key systems!
+ switch (lastKeySystemIssue) {
+ case DecoderDoctorDiagnostics::eWidevineWithNoWMF:
+ if (CheckSilverlight() != eSilverlightEnabled) {
+ DD_DEBUG("DecoderDoctorDocumentWatcher[%p, doc=%p]::SynthesizeAnalysis() - unsupported key systems: %s, widevine without WMF nor Silverlight",
+ this, mDocument, NS_ConvertUTF16toUTF8(unplayableFormats).get());
+ ReportAnalysis(dom::DecoderDoctorNotificationType::Platform_decoder_not_found,
+ "MediaWidevineNoWMFNoSilverlight", NS_LITERAL_STRING(""));
+ return;
+ }
+ break;
+ default:
+ break;
+ }
+ }
+
+ if (!canPlay && !unplayableFormats.IsEmpty()) {
+#if defined(XP_WIN)
+ if (WMFNeeded) {
+ DD_DEBUG("DecoderDoctorDocumentWatcher[%p, doc=%p]::SynthesizeAnalysis() - formats: %s -> Cannot play media because WMF was not found",
+ this, mDocument, NS_ConvertUTF16toUTF8(unplayableFormats).get());
+ ReportAnalysis(dom::DecoderDoctorNotificationType::Platform_decoder_not_found,
+ "MediaWMFNeeded", unplayableFormats);
+ return;
+ }
+#endif
#if defined(MOZ_FFMPEG)
if (FFMpegNeeded) {
DD_DEBUG("DecoderDoctorDocumentWatcher[%p, doc=%p]::SynthesizeAnalysis() - unplayable formats: %s -> Cannot play media because platform decoder was not found",
this, mDocument, NS_ConvertUTF16toUTF8(unplayableFormats).get());
ReportAnalysis(dom::DecoderDoctorNotificationType::Platform_decoder_not_found,
"MediaPlatformDecoderNotFound", unplayableFormats);
- } else
+ return;
+ }
#endif
- {
- DD_WARN("DecoderDoctorDocumentWatcher[%p, doc=%p]::SynthesizeAnalysis() - Cannot play media, unplayable formats: %s",
- this, mDocument, NS_ConvertUTF16toUTF8(unplayableFormats).get());
- ReportAnalysis(dom::DecoderDoctorNotificationType::Cannot_play,
- "MediaCannotPlayNoDecoders", unplayableFormats);
- }
- } else if (!unplayableFormats.IsEmpty()) {
+ DD_WARN("DecoderDoctorDocumentWatcher[%p, doc=%p]::SynthesizeAnalysis() - Cannot play media, unplayable formats: %s",
+ this, mDocument, NS_ConvertUTF16toUTF8(unplayableFormats).get());
+ ReportAnalysis(dom::DecoderDoctorNotificationType::Cannot_play,
+ "MediaCannotPlayNoDecoders", unplayableFormats);
+ return;
+ }
+ if (!unplayableFormats.IsEmpty()) {
DD_INFO("DecoderDoctorDocumentWatcher[%p, doc=%p]::SynthesizeAnalysis() - Can play media, but no decoders for some requested formats: %s",
this, mDocument, NS_ConvertUTF16toUTF8(unplayableFormats).get());
if (Preferences::GetBool("media.decoderdoctor.verbose", false)) {
ReportAnalysis(
dom::DecoderDoctorNotificationType::Can_play_but_some_missing_decoders,
"MediaNoDecoders", unplayableFormats);
}
- } else {
- DD_DEBUG("DecoderDoctorDocumentWatcher[%p, doc=%p]::SynthesizeAnalysis() - Can play media, decoders available for all requested formats",
- this, mDocument);
+ return;
}
+ DD_DEBUG("DecoderDoctorDocumentWatcher[%p, doc=%p]::SynthesizeAnalysis() - Can play media, decoders available for all requested formats",
+ this, mDocument);
}
void
DecoderDoctorDocumentWatcher::AddDiagnostics(DecoderDoctorDiagnostics&& aDiagnostics,
const char* aCallSite)
{
MOZ_ASSERT(NS_IsMainThread());