Bug 1362212 - Implement HTMLMediaElement.reportCanPlayTelemetry. r=gerald
Defer determining whether we have usable decoders to an off-main thread in
order to avoid janking the main thread.
MozReview-Commit-ID: Ape5zEBBMrz
--- a/dom/html/HTMLMediaElement.cpp
+++ b/dom/html/HTMLMediaElement.cpp
@@ -91,21 +91,28 @@
#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 "DecoderTraits.h"
#include "MediaContainerType.h"
+#include "MP4Decoder.h"
#include "ImageContainer.h"
#include "nsRange.h"
#include <algorithm>
#include <cmath>
+#ifdef XP_WIN
+#include "Objbase.h"
+// Some Windows header defines this, so undef it as it conflicts with our
+// function of the same name.
+#undef GetCurrentTime
+#endif
static mozilla::LazyLogModule gMediaElementLog("nsMediaElement");
static mozilla::LazyLogModule gMediaElementEventsLog("nsMediaElementEvents");
#define LOG(type, msg) MOZ_LOG(gMediaElementLog, type, msg)
#define LOG_EVENT(type, msg) MOZ_LOG(gMediaElementEventsLog, type, msg)
#include "nsIContentSecurityPolicy.h"
@@ -7451,10 +7458,48 @@ HTMLMediaElement::AsyncRejectSeekDOMProm
nsCOMPtr<nsIRunnable> r = NS_NewRunnableFunction([=] () {
promise->MaybeReject(NS_ERROR_DOM_ABORT_ERR);
});
mAbstractMainThread->Dispatch(r.forget());
mSeekDOMPromise = nullptr;
}
}
+void
+HTMLMediaElement::ReportCanPlayTelemetry()
+{
+ LOG(LogLevel::Debug, ("%s", __func__));
+
+ RefPtr<nsIThread> thread;
+ nsresult rv = NS_NewNamedThread("MediaTelemetry", getter_AddRefs(thread));
+ if (NS_WARN_IF(NS_FAILED(rv))) {
+ return;
+ }
+
+ thread->Dispatch(
+ NS_NewRunnableFunction([thread]() {
+#if XP_WIN
+ // Windows Media Foundation requires MSCOM to be inited.
+ HRESULT hr = CoInitializeEx(0, COINIT_MULTITHREADED);
+ MOZ_ASSERT(hr == S_OK);
+#endif
+ bool aac = MP4Decoder::IsSupportedType(
+ MediaContainerType(MEDIAMIMETYPE("audio/mp4")), nullptr);
+ bool h264 = MP4Decoder::IsSupportedType(
+ MediaContainerType(MEDIAMIMETYPE("video/mp4")), nullptr);
+#if XP_WIN
+ CoUninitialize();
+#endif
+ AbstractThread::MainThread()->Dispatch(
+ NS_NewRunnableFunction([thread, aac, h264]() {
+ LOG(LogLevel::Debug, ("MediaTelemetry aac=%d h264=%d", aac, h264));
+ Telemetry::Accumulate(
+ Telemetry::HistogramID::VIDEO_CAN_CREATE_AAC_DECODER, aac);
+ Telemetry::Accumulate(
+ Telemetry::HistogramID::VIDEO_CAN_CREATE_H264_DECODER, h264);
+ thread->AsyncShutdown();
+ }));
+ }),
+ NS_DISPATCH_NORMAL);
+}
+
} // namespace dom
} // namespace mozilla
--- a/dom/html/HTMLMediaElement.h
+++ b/dom/html/HTMLMediaElement.h
@@ -97,16 +97,18 @@ public:
MOZ_DECLARE_WEAKREFERENCE_TYPENAME(HTMLMediaElement)
CORSMode GetCORSMode() {
return mCORSMode;
}
explicit HTMLMediaElement(already_AddRefed<mozilla::dom::NodeInfo>& aNodeInfo);
+ void ReportCanPlayTelemetry();
+
/**
* This is used when the browser is constructing a video element to play
* a channel that we've already started loading. The src attribute and
* <source> children are ignored.
* @param aChannel the channel to use
* @param aListener returns a stream listener that should receive
* notifications for the stream
*/
--- a/dom/media/MediaPrefs.h
+++ b/dom/media/MediaPrefs.h
@@ -176,16 +176,18 @@ private:
#endif
#if defined(MOZ_WIDGET_GTK)
DECL_MEDIA_PREF("media.rust.mp4parser", EnableRustMP4Parser, bool, true);
#else
DECL_MEDIA_PREF("media.rust.mp4parser", EnableRustMP4Parser, bool, false);
#endif
+ DECL_MEDIA_PREF("media.mp4.enabled", MP4Enabled, bool, false);
+
// Error/warning handling, Decoder Doctor
DECL_MEDIA_PREF("media.playback.warnings-as-errors", MediaWarningsAsErrors, bool, false);
DECL_MEDIA_PREF("media.playback.warnings-as-errors.stagefright-vs-rust",
MediaWarningsAsErrorsStageFrightVsRust, bool, false);
public:
// Manage the singleton:
static MediaPrefs& GetSingleton();
--- a/dom/media/fmp4/MP4Decoder.cpp
+++ b/dom/media/fmp4/MP4Decoder.cpp
@@ -176,17 +176,17 @@ MP4Decoder::IsAAC(const nsACString& aMim
{
return aMimeType.EqualsLiteral("audio/mp4a-latm");
}
/* static */
bool
MP4Decoder::IsEnabled()
{
- return Preferences::GetBool("media.mp4.enabled", true);
+ return MediaPrefs::MP4Enabled();
}
// sTestH264ExtraData represents the content of the avcC atom found in
// an AVC1 h264 video. It contains the H264 SPS and PPS NAL.
// the structure of the avcC atom is as follow:
// write(0x1); // version, always 1
// write(sps[0].data[1]); // profile
// write(sps[0].data[2]); // compatibility