Bug 1293145 - Simulate video-decode-suspend for telemetry purposes - r=kamidphish

After a video has been playing while hidden for a certain time, count the time
until it is not hidden anymore (or it has finished playing), to test-drive how
much decoding time would have been saved by the video-decode-suspend feature.

Note that this is done inside HTMLMediaElement by simulating what should happen
in the MDSM, because instrumenting the MDSM itself and friends would have been
harder and more intrusive.

MozReview-Commit-ID: LdxhPtmoXeA

--HG--
extra : rebase_source : 151e1f1383ab5c445eb8c957be8363340cdc4ab1
This commit is contained in:
Gerald Squelart 2016-08-08 10:14:39 +08:00
Родитель 8765fa4359
Коммит d78a374b2d
2 изменённых файлов: 85 добавлений и 9 удалений

Просмотреть файл

@ -48,9 +48,10 @@
#include "MediaError.h"
#include "MediaDecoder.h"
#include "nsICategoryManager.h"
#include "MediaPrefs.h"
#include "MediaResource.h"
#include "nsICategoryManager.h"
#include "nsIContentPolicy.h"
#include "nsContentPolicyUtils.h"
#include "nsCycleCollectionParticipant.h"
@ -2558,6 +2559,10 @@ HTMLMediaElement::~HTMLMediaElement()
if (mProgressTimer) {
StopProgress();
}
if (mVideoDecodeSuspendTimer) {
mVideoDecodeSuspendTimer->Cancel();
mVideoDecodeSuspendTimer = nullptr;
}
if (mSrcStream) {
EndSrcMediaStreamPlayback();
}
@ -3032,6 +3037,42 @@ nsresult HTMLMediaElement::BindToTree(nsIDocument* aDocument, nsIContent* aParen
return rv;
}
/* static */
void HTMLMediaElement::VideoDecodeSuspendTimerCallback(nsITimer* aTimer, void* aClosure)
{
MOZ_ASSERT(NS_IsMainThread());
auto element = static_cast<HTMLMediaElement*>(aClosure);
element->mVideoDecodeSuspendTime.Start();
element->mVideoDecodeSuspendTimer = nullptr;
}
void HTMLMediaElement::HiddenVideoStart()
{
MOZ_ASSERT(NS_IsMainThread());
mHiddenPlayTime.Start();
if (mVideoDecodeSuspendTimer) {
// Already started, just keep it running.
return;
}
mVideoDecodeSuspendTimer = do_CreateInstance("@mozilla.org/timer;1");
mVideoDecodeSuspendTimer->InitWithNamedFuncCallback(
VideoDecodeSuspendTimerCallback, this,
MediaPrefs::MDSMSuspendBackgroundVideoDelay(), nsITimer::TYPE_ONE_SHOT,
"HTMLMediaElement::VideoDecodeSuspendTimerCallback");
}
void HTMLMediaElement::HiddenVideoStop()
{
MOZ_ASSERT(NS_IsMainThread());
mHiddenPlayTime.Pause();
mVideoDecodeSuspendTime.Pause();
if (!mVideoDecodeSuspendTimer) {
return;
}
mVideoDecodeSuspendTimer->Cancel();
mVideoDecodeSuspendTimer = nullptr;
}
#ifdef MOZ_EME
void
HTMLMediaElement::ReportEMETelemetry()
@ -3118,6 +3159,7 @@ HTMLMediaElement::ReportTelemetry()
// We have a valid video.
double playTime = mPlayTime.Total();
double hiddenPlayTime = mHiddenPlayTime.Total();
double videoDecodeSuspendTime = mVideoDecodeSuspendTime.Total();
Telemetry::Accumulate(Telemetry::VIDEO_PLAY_TIME_MS, SECONDS_TO_MS(playTime));
LOG(LogLevel::Debug, ("%p VIDEO_PLAY_TIME_MS = %f", this, playTime));
@ -3126,8 +3168,7 @@ HTMLMediaElement::ReportTelemetry()
LOG(LogLevel::Debug, ("%p VIDEO_HIDDEN_PLAY_TIME_MS = %f", this, hiddenPlayTime));
if (playTime > 0.0) {
// We have actually played something -> Report hidden/total ratio.
uint32_t hiddenPercentage = uint32_t(hiddenPlayTime / playTime * 100.0 + 0.5);
// We have actually played something -> Report some valid-video telemetry.
// Keyed by audio+video or video alone, and by a resolution range.
nsCString key(mMediaInfo.HasAudio() ? "AV," : "V,");
@ -3149,6 +3190,7 @@ HTMLMediaElement::ReportTelemetry()
}
key.AppendASCII(resolution);
uint32_t hiddenPercentage = uint32_t(hiddenPlayTime / playTime * 100.0 + 0.5);
Telemetry::Accumulate(Telemetry::VIDEO_HIDDEN_PLAY_TIME_PERCENTAGE,
key,
hiddenPercentage);
@ -3159,6 +3201,17 @@ HTMLMediaElement::ReportTelemetry()
LOG(LogLevel::Debug, ("%p VIDEO_HIDDEN_PLAY_TIME_PERCENTAGE = %u, keys: '%s' and 'All'",
this, hiddenPercentage, key.get()));
uint32_t videoDecodeSuspendPercentage =
uint32_t(videoDecodeSuspendTime / playTime * 100.0 + 0.5);
Telemetry::Accumulate(Telemetry::VIDEO_INFERRED_DECODE_SUSPEND_PERCENTAGE,
key,
videoDecodeSuspendPercentage);
Telemetry::Accumulate(Telemetry::VIDEO_INFERRED_DECODE_SUSPEND_PERCENTAGE,
NS_LITERAL_CSTRING("All"),
videoDecodeSuspendPercentage);
LOG(LogLevel::Debug, ("%p VIDEO_INFERRED_DECODE_SUSPEND_PERCENTAGE = %u, keys: '%s' and 'All'",
this, videoDecodeSuspendPercentage, key.get()));
if (data.mInterKeyframeCount != 0) {
uint32_t average_ms =
uint32_t(std::min<uint64_t>(double(data.mInterKeyframeSum_us)
@ -4708,14 +4761,14 @@ nsresult HTMLMediaElement::DispatchAsyncEvent(const nsAString& aName)
if ((aName.EqualsLiteral("play") || aName.EqualsLiteral("playing"))) {
mPlayTime.Start();
if (IsHidden()) {
mHiddenPlayTime.Start();
HiddenVideoStart();
}
} else if (aName.EqualsLiteral("waiting")) {
mPlayTime.Pause();
mHiddenPlayTime.Pause();
HiddenVideoStop();
} else if (aName.EqualsLiteral("pause")) {
mPlayTime.Pause();
mHiddenPlayTime.Pause();
HiddenVideoStop();
}
return NS_OK;
@ -4913,10 +4966,10 @@ HTMLMediaElement::NotifyOwnerDocumentActivityChangedInternal()
bool visible = !IsHidden();
if (visible) {
// Visible -> Just pause hidden play time (no-op if already paused).
mHiddenPlayTime.Pause();
HiddenVideoStop();
} else if (mPlayTime.IsStarted()) {
// Not visible, play time is running -> Start hidden play time if needed.
mHiddenPlayTime.Start();
HiddenVideoStart();
}
if (mDecoder && !IsBeingDestroyed()) {

Просмотреть файл

@ -1125,6 +1125,23 @@ protected:
return isPaused;
}
/**
* Video has been playing while hidden and, if feature was enabled, would
* trigger suspending decoder.
* Used to track hidden-video-decode-suspend telemetry.
*/
static void VideoDecodeSuspendTimerCallback(nsITimer* aTimer, void* aClosure);
/**
* Video is now both: playing and hidden.
* Used to track hidden-video telemetry.
*/
void HiddenVideoStart();
/**
* Video is not playing anymore and/or has become visible.
* Used to track hidden-video telemetry.
*/
void HiddenVideoStop();
#ifdef MOZ_EME
void ReportEMETelemetry();
#endif
@ -1375,9 +1392,12 @@ protected:
// Range of time played.
RefPtr<TimeRanges> mPlayed;
// Timer used for updating progress events
// Timer used for updating progress events.
nsCOMPtr<nsITimer> mProgressTimer;
// Timer used to simulate video-suspend.
nsCOMPtr<nsITimer> mVideoDecodeSuspendTimer;
#ifdef MOZ_EME
// Encrypted Media Extension media keys.
RefPtr<MediaKeys> mMediaKeys;
@ -1636,6 +1656,9 @@ private:
// Total time a video has spent playing while hidden.
TimeDurationAccumulator mHiddenPlayTime;
// Total time a video has (or would have) spent in video-decode-suspend mode.
TimeDurationAccumulator mVideoDecodeSuspendTime;
// Indicates if user has interacted with the element.
// Used to block autoplay when disabled.
bool mHasUserInteraction;