Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(290)

Side by Side Diff: media/blink/watch_time_reporter.h

Issue 2160963002: Add watch time metrics for HTML5 media playback. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Comments, couple more tests. Created 4 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright 2016 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #ifndef MEDIA_BLINK_WATCH_TIME_REPORTER_H_
6 #define MEDIA_BLINK_WATCH_TIME_REPORTER_H_
7
8 #include "base/callback.h"
9 #include "base/power_monitor/power_observer.h"
10 #include "base/time/time.h"
11 #include "base/timer/timer.h"
12 #include "media/base/timestamp_constants.h"
13 #include "media/blink/media_blink_export.h"
14 #include "ui/gfx/geometry/size.h"
15
16 namespace media {
17
18 // Class for monitoring and reporting watch time in response to various state
19 // changes during the playback of media. At present we are only recording the
20 // watch time for audio+video playbacks.
21 // TODO(dalecurtis): We want to introduce a similar "listening time" metric in
22 // the near future to track audio only cases.
23 //
24 // Watch time for our purposes is defined as the amount of elapsed media time
25 // for audio+video media. A minimum of 7 seconds of unmuted, foreground media
26 // must be watched to start watch time monitoring. Watch time is checked every
27 // 5 seconds from then on and reported to multiple buckets: All, MSE, SRC, EME,
28 // AC, and battery.
29 //
30 // Any one of paused, hidden, or muted is sufficient to stop watch time metric
31 // reports. Each of these has a hysteresis where if the state change is undone
32 // within 5 seconds, the watch time will be counted as uninterrupted.
33 //
34 // Power events (on/off battery power) have a similar hysteresis, but unlike
35 // the aforementioned properties, will not stop metric collection.
36 //
37 // Each seek event will result in a new watch time metric being started and the
38 // old metric finalized as accurately as possible.
39 class MEDIA_BLINK_EXPORT WatchTimeReporter : base::PowerObserver {
40 public:
41 // Constructor for the reporter; all requested metadata should be fully known
42 // before attempting construction as incorrect values will result in the wrong
43 // watch time metrics being reported.
44 //
45 // |initial_video_size| required to ensure that the video track has sufficient
46 // size for watch time reporting.
47 //
48 // |get_media_time_cb| must return the current playback time in terms of media
49 // time, not wall clock time! Using media time instead of wall clock time
50 // allows us to avoid a whole class of issues around clock changes during
51 // suspend and resume.
52 // TODO(dalecurtis): Should we only report when rate == 1.0? Should we scale
53 // the elapsed media time instead?
54 using GetMediaTimeCB = base::Callback<base::TimeDelta(void)>;
sandersd (OOO until July 31) 2016/08/04 23:06:26 Move above comment.
DaleCurtis 2016/08/08 23:16:42 Done.
55 WatchTimeReporter(bool has_audio,
56 bool has_video,
57 bool is_mse,
58 bool is_encrypted,
59 const gfx::Size& initial_video_size,
60 const GetMediaTimeCB& get_media_time_cb);
61 ~WatchTimeReporter() override;
62
63 // These methods are used to ensure that watch time is only reported for
64 // media that is actually playing. They should be called whenever the media
65 // starts or stops playing for any reason.
66 void OnPlaying();
67 void OnPaused();
68
69 // This will finalize any outstanding watch time reports and start a new
70 // reporting session beginning from |seek_timestamp|.
71 void OnSeeking(base::TimeDelta seek_timestamp);
72
73 // This method is used to ensure that watch time is only reported for media
74 // that is actually audible to the user. It should be called whenever the
75 // volume changes.
76 //
77 // Note: This does not catch all cases. E.g., headphones that are being
78 // listened too, or even OS level volume state.
79 void OnVolumeChange(double volume);
80
81 // These methods are used to ensure that watch time is only reported for
82 // videos that are actually visible to the user. They should be called when
83 // the video is shown or hidden respectively.
84 //
85 // TODO(dalecurtis): At present, this is only called when the entire content
86 // window goes into the foreground or background respectively; i.e. it does
87 // not catch cases where the video is in the foreground but out of the view
88 // port. We need a method for rejecting out of view port videos.
89 void OnShown();
90 void OnHidden();
91
92 private:
93 friend class WatchTimeReporterTest;
94
95 // Histogram names used for reporting. Exported for testing purposes only.
96 static const char kHistogramAudioVideoAll[];
97 static const char kHistogramAudioVideoMse[];
98 static const char kHistogramAudioVideoEme[];
99 static const char kHistogramAudioVideoSrc[];
100 static const char kHistogramAudioVideoBattery[];
101 static const char kHistogramAudioVideoAc[];
102
103 // base::PowerObserver implementation.
104 //
105 // We only observe power source changes. We don't need to observe suspend and
106 // resume events because we report watch time in terms of elapsed media time
107 // and not in terms of elapsed real time.
108 void OnPowerStateChange(bool on_battery_power) override;
109
110 bool ShouldReportWatchTime();
111 void StartReportingTimer(base::TimeDelta start_timestamp);
sandersd (OOO until July 31) 2016/08/04 23:06:26 nit: MaybeStart/MaybeFinalize?
DaleCurtis 2016/08/08 23:16:42 Done.
112 enum class FinalizeTime { IMMEDIATELY, ON_NEXT_UPDATE };
113 void FinalizeWatchTime(FinalizeTime finalize_time);
114 void UpdateWatchTime();
115
116 // Initialized during construction.
117 const bool has_audio_;
118 const bool has_video_;
119 const bool is_mse_;
120 const bool is_encrypted_;
121 const gfx::Size initial_video_size_;
122 const GetMediaTimeCB get_media_time_cb_;
123
124 // The amount of time between each UpdateWatchTime(); this is the frequency by
125 // which the histograms are updated. In the event of a process crash or kill
126 // this is also the most amount of watch time that we might lose.
127 base::TimeDelta reporting_interval_ = base::TimeDelta::FromSeconds(5);
128
129 base::RepeatingTimer reporting_timer_;
130
131 // Updated by the OnXXX() methods above.
132 bool is_on_battery_power_ = false;
133 bool is_playing_ = false;
134 bool is_visible_ = true;
135 double volume_ = 1.0;
136
137 // The last media timestamp seen by UpdateWatchTime().
138 base::TimeDelta last_media_timestamp_ = kNoTimestamp;
139
140 // The starting and ending timestamps used for reporting watch time.
141 base::TimeDelta start_timestamp_;
142 base::TimeDelta end_timestamp_ = kNoTimestamp;
143
144 // Similar to the above but tracks watch time relative to whether or not
145 // battery or AC power is being used.
146 base::TimeDelta start_timestamp_for_power_;
147 base::TimeDelta end_timestamp_for_power_ = kNoTimestamp;
148
149 DISALLOW_COPY_AND_ASSIGN(WatchTimeReporter);
150 };
151
152 } // namespace media
153
154 #endif // MEDIA_BLINK_WATCH_TIME_REPORTER_H_
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698