Bug 1248507 - p3. Use DecoderDoctorDiagnostics - r=jya,bz
DecoderDoctorDiagnostics are now used at places where Firefox Chrome and/or
websites checks whether some media formats may be played:
- audio|video.canPlayType()
- audio|video resource loader
- MediaSource.IsTypeSupported()
- MediaSource.AddSourceBuffer()
MozReview-Commit-ID: B1KdjXODq9j
--- a/dom/html/HTMLMediaElement.cpp
+++ b/dom/html/HTMLMediaElement.cpp
@@ -81,16 +81,17 @@
#include "mozilla/dom/AudioTrack.h"
#include "mozilla/dom/AudioTrackList.h"
#include "mozilla/dom/VideoTrack.h"
#include "mozilla/dom/VideoTrackList.h"
#include "mozilla/dom/TextTrack.h"
#include "nsIContentPolicy.h"
#include "mozilla/Telemetry.h"
+#include "DecoderDoctorDiagnostics.h"
#include "ImageContainer.h"
#include "nsRange.h"
#include <algorithm>
#include <cmath>
static mozilla::LazyLogModule gMediaElementLog("nsMediaElement");
static mozilla::LazyLogModule gMediaElementEventsLog("nsMediaElementEvents");
@@ -1056,22 +1057,29 @@ void HTMLMediaElement::LoadFromSourceChi
if (!child->GetAttr(kNameSpaceID_None, nsGkAtoms::src, src)) {
ReportLoadError("MediaLoadSourceMissingSrc");
DispatchAsyncSourceError(child);
continue;
}
// If we have a type attribute, it must be a supported type.
nsAutoString type;
- if (child->GetAttr(kNameSpaceID_None, nsGkAtoms::type, type) &&
- GetCanPlay(type) == CANPLAY_NO) {
- DispatchAsyncSourceError(child);
- const char16_t* params[] = { type.get(), src.get() };
- ReportLoadError("MediaLoadUnsupportedTypeAttribute", params, ArrayLength(params));
- continue;
+ if (child->GetAttr(kNameSpaceID_None, nsGkAtoms::type, type)) {
+ DecoderDoctorDiagnostics diagnostics;
+ CanPlayStatus canPlay = GetCanPlay(type, &diagnostics);
+ if (canPlay != CANPLAY_NO) {
+ diagnostics.SetCanPlay();
+ }
+ diagnostics.StoreDiagnostics(OwnerDoc(), type, __func__);
+ if (canPlay == CANPLAY_NO) {
+ DispatchAsyncSourceError(child);
+ const char16_t* params[] = { type.get(), src.get() };
+ ReportLoadError("MediaLoadUnsupportedTypeAttribute", params, ArrayLength(params));
+ continue;
+ }
}
nsAutoString media;
HTMLSourceElement *childSrc = HTMLSourceElement::FromContent(child);
MOZ_ASSERT(childSrc, "Expect child to be HTMLSourceElement");
if (childSrc && !childSrc->MatchesCurrentMedia()) {
DispatchAsyncSourceError(child);
const char16_t* params[] = { media.get(), src.get() };
ReportLoadError("MediaLoadSourceMediaNotMatched", params, ArrayLength(params));
@@ -2879,38 +2887,45 @@ void HTMLMediaElement::UnbindFromTree(bo
if (mDecoder) {
MOZ_ASSERT(IsHidden());
mDecoder->NotifyOwnerActivityChanged();
}
}
/* static */
CanPlayStatus
-HTMLMediaElement::GetCanPlay(const nsAString& aType)
+HTMLMediaElement::GetCanPlay(const nsAString& aType,
+ DecoderDoctorDiagnostics* aDiagnostics)
{
nsContentTypeParser parser(aType);
nsAutoString mimeType;
nsresult rv = parser.GetType(mimeType);
if (NS_FAILED(rv))
return CANPLAY_NO;
nsAutoString codecs;
rv = parser.GetParameter("codecs", codecs);
NS_ConvertUTF16toUTF8 mimeTypeUTF8(mimeType);
return DecoderTraits::CanHandleMediaType(mimeTypeUTF8.get(),
NS_SUCCEEDED(rv),
codecs,
- /* DecoderDoctorDiagnostics* */ nullptr);
+ aDiagnostics);
}
NS_IMETHODIMP
HTMLMediaElement::CanPlayType(const nsAString& aType, nsAString& aResult)
{
- switch (GetCanPlay(aType)) {
+ DecoderDoctorDiagnostics diagnostics;
+ CanPlayStatus canPlay = GetCanPlay(aType, &diagnostics);
+ if (canPlay != CANPLAY_NO) {
+ diagnostics.SetCanPlay();
+ }
+ diagnostics.StoreDiagnostics(OwnerDoc(), aType, __func__);
+ switch (canPlay) {
case CANPLAY_NO:
aResult.Truncate();
break;
case CANPLAY_YES:
aResult.AssignLiteral("probably");
break;
default:
case CANPLAY_MAYBE:
@@ -2960,19 +2975,25 @@ 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.");
+ DecoderDoctorDiagnostics diagnostics;
RefPtr<MediaDecoder> decoder =
- DecoderTraits::CreateDecoder(mimeType, this,
- /* DecoderDoctorDiagnostics* */ nullptr);
+ DecoderTraits::CreateDecoder(mimeType, this, &diagnostics);
+ if (decoder) {
+ diagnostics.SetCanPlay();
+ }
+ diagnostics.StoreDiagnostics(OwnerDoc(),
+ NS_ConvertASCIItoUTF16(mimeType),
+ __func__);
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/html/HTMLMediaElement.h
+++ b/dom/html/HTMLMediaElement.h
@@ -34,16 +34,17 @@
// Define to output information on decoding and painting framerate
/* #define DEBUG_FRAME_RATE 1 */
typedef uint16_t nsMediaNetworkState;
typedef uint16_t nsMediaReadyState;
namespace mozilla {
+class DecoderDoctorDiagnostics;
class DOMMediaStream;
class ErrorResult;
class MediaResource;
class MediaDecoder;
class VideoFrameContainer;
namespace dom {
class MediaKeys;
class TextTrack;
@@ -316,17 +317,18 @@ public:
// main thread when/if the size changes.
void UpdateMediaSize(const nsIntSize& aSize);
// Like UpdateMediaSize, but only updates the size if no size has yet
// been set.
void UpdateInitialMediaSize(const nsIntSize& aSize);
// Returns the CanPlayStatus indicating if we can handle the
// full MIME type including the optional codecs parameter.
- static CanPlayStatus GetCanPlay(const nsAString& aType);
+ static CanPlayStatus GetCanPlay(const nsAString& aType,
+ DecoderDoctorDiagnostics* aDiagnostics);
/**
* Called when a child source element is added to this media element. This
* may queue a task to run the select resource algorithm if appropriate.
*/
void NotifyAddedSource();
/**
--- a/dom/media/mediasource/MediaSource.cpp
+++ b/dom/media/mediasource/MediaSource.cpp
@@ -4,16 +4,17 @@
* 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 "MediaSource.h"
#include "AsyncEventRunner.h"
#include "DecoderTraits.h"
#include "Benchmark.h"
+#include "DecoderDoctorDiagnostics.h"
#include "MediaSourceUtils.h"
#include "SourceBuffer.h"
#include "SourceBufferList.h"
#include "mozilla/ErrorResult.h"
#include "mozilla/FloatingPoint.h"
#include "mozilla/Preferences.h"
#include "mozilla/dom/BindingDeclarations.h"
#include "mozilla/dom/HTMLMediaElement.h"
@@ -108,30 +109,36 @@ IsTypeSupported(const nsAString& aType,
return NS_ERROR_DOM_NOT_SUPPORTED_ERR;
}
if (hasCodecs &&
DecoderTraits::CanHandleCodecsType(mimeTypeUTF8.get(),
codecs,
aDiagnostics) == CANPLAY_NO) {
return NS_ERROR_DOM_NOT_SUPPORTED_ERR;
}
+ if (aDiagnostics) {
+ aDiagnostics->SetCanPlay();
+ }
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(aDiagnostics))) {
return NS_ERROR_DOM_NOT_SUPPORTED_ERR;
}
if (hasCodecs &&
DecoderTraits::CanHandleCodecsType(mimeTypeUTF8.get(),
codecs,
aDiagnostics) == CANPLAY_NO) {
return NS_ERROR_DOM_NOT_SUPPORTED_ERR;
}
+ if (aDiagnostics) {
+ aDiagnostics->SetCanPlay();
+ }
return NS_OK;
}
}
}
return NS_ERROR_DOM_NOT_SUPPORTED_ERR;
}
@@ -218,18 +225,28 @@ 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,
- /* DecoderDoctorDiagnostics* */ nullptr);
+ DecoderDoctorDiagnostics diagnostics;
+ nsresult rv = mozilla::IsTypeSupported(aType, &diagnostics);
+ if (NS_SUCCEEDED(rv)) {
+ diagnostics.SetCanPlay();
+ }
+ if (GetOwner()) {
+ diagnostics.StoreDiagnostics(GetOwner()->GetExtantDoc(), aType,
+ "AddSourceBuffer with owner window's doc");
+ } else {
+ diagnostics.StoreDiagnostics(nullptr, aType,
+ "AddSourceBuffer with nothing");
+ }
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) {
@@ -335,21 +352,32 @@ MediaSource::EndOfStream(const Optional<
mDecoder->DecodeError();
break;
default:
aRv.Throw(NS_ERROR_DOM_INVALID_ACCESS_ERR);
}
}
/* static */ bool
-MediaSource::IsTypeSupported(const GlobalObject&, const nsAString& aType)
+MediaSource::IsTypeSupported(const GlobalObject& aOwner, const nsAString& aType)
{
MOZ_ASSERT(NS_IsMainThread());
- nsresult rv = mozilla::IsTypeSupported(aType,
- /* DecoderDoctorDiagnostics* */ nullptr);
+ DecoderDoctorDiagnostics diagnostics;
+ nsresult rv = mozilla::IsTypeSupported(aType, &diagnostics);
+ if (NS_SUCCEEDED(rv)) {
+ diagnostics.SetCanPlay();
+ }
+ nsCOMPtr<nsPIDOMWindowInner> window = do_QueryInterface(aOwner.GetAsSupports());
+ if (window) {
+ diagnostics.StoreDiagnostics(window->GetExtantDoc(), aType,
+ "IsTypeSupported with aOwner window's doc");
+ } else {
+ diagnostics.StoreDiagnostics(nullptr, aType,
+ "IsTypeSupported with nothing");
+ }
#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