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

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: Fix seeking before metadata crash. 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/media_log.h"
13 #include "media/base/timestamp_constants.h"
14 #include "media/blink/media_blink_export.h"
15 #include "ui/gfx/geometry/size.h"
16
17 namespace media {
18
19 // Class for monitoring and reporting watch time in response to various state
20 // changes during the playback of media. At present we are only recording the
21 // watch time for audio+video playbacks.
22 // TODO(dalecurtis): We want to introduce a similar "listening time" metric in
23 // the near future to track audio only cases.
24 //
25 // Watch time for our purposes is defined as the amount of elapsed media time
26 // for audio+video media. A minimum of 7 seconds of unmuted, foreground media
27 // must be watched to start watch time monitoring. Watch time is checked every
28 // 5 seconds from then on and reported to multiple buckets: All, MSE, SRC, EME,
29 // AC, and battery.
30 //
31 // Any one of paused, hidden, or muted is sufficient to stop watch time metric
32 // reports. Each of these has a hysteresis where if the state change is undone
33 // within 5 seconds, the watch time will be counted as uninterrupted.
34 //
35 // Power events (on/off battery power) have a similar hysteresis, but unlike
36 // the aforementioned properties, will not stop metric collection.
37 //
38 // Each seek event will result in a new watch time metric being started and the
39 // old metric finalized as accurately as possible.
40 class MEDIA_BLINK_EXPORT WatchTimeReporter : base::PowerObserver {
41 public:
42 using GetMediaTimeCB = base::Callback<base::TimeDelta(void)>;
43
44 // Constructor for the reporter; all requested metadata should be fully known
45 // before attempting construction as incorrect values will result in the wrong
46 // watch time metrics being reported.
47 //
48 // |media_log| is used to continuously log the watch time values for eventual
49 // recording to a histogram upon finalization.
50 //
51 // |initial_video_size| required to ensure that the video track has sufficient
52 // size for watch time reporting.
53 //
54 // |get_media_time_cb| must return the current playback time in terms of media
55 // time, not wall clock time! Using media time instead of wall clock time
56 // allows us to avoid a whole class of issues around clock changes during
57 // suspend and resume.
58 // TODO(dalecurtis): Should we only report when rate == 1.0? Should we scale
59 // the elapsed media time instead?
60 WatchTimeReporter(bool has_audio,
61 bool has_video,
62 bool is_mse,
63 bool is_encrypted,
64 scoped_refptr<MediaLog> media_log,
65 const gfx::Size& initial_video_size,
66 const GetMediaTimeCB& get_media_time_cb);
67 ~WatchTimeReporter() override;
68
69 // These methods are used to ensure that watch time is only reported for
70 // media that is actually playing. They should be called whenever the media
71 // starts or stops playing for any reason.
72 void OnPlaying();
73 void OnPaused();
74
75 // This will immediately finalize any outstanding watch time reports and stop
76 // the reporting timer. Clients should call OnPlaying() upon seek completion
77 // to restart the reporting timer.
78 void OnSeeking();
79
80 // This method is used to ensure that watch time is only reported for media
81 // that is actually audible to the user. It should be called whenever the
82 // volume changes.
83 //
84 // Note: This does not catch all cases. E.g., headphones that are being
85 // listened too, or even OS level volume state.
86 void OnVolumeChange(double volume);
87
88 // These methods are used to ensure that watch time is only reported for
89 // videos that are actually visible to the user. They should be called when
90 // the video is shown or hidden respectively.
91 //
92 // TODO(dalecurtis): At present, this is only called when the entire content
93 // window goes into the foreground or background respectively; i.e. it does
94 // not catch cases where the video is in the foreground but out of the view
95 // port. We need a method for rejecting out of view port videos.
96 void OnShown();
97 void OnHidden();
98
99 private:
100 friend class WatchTimeReporterTest;
101
102 // base::PowerObserver implementation.
103 //
104 // We only observe power source changes. We don't need to observe suspend and
105 // resume events because we report watch time in terms of elapsed media time
106 // and not in terms of elapsed real time.
107 void OnPowerStateChange(bool on_battery_power) override;
108
109 bool ShouldReportWatchTime();
110 void MaybeStartReportingTimer(base::TimeDelta start_timestamp);
111 enum class FinalizeTime { IMMEDIATELY, ON_NEXT_UPDATE };
112 void MaybeFinalizeWatchTime(FinalizeTime finalize_time);
113 void UpdateWatchTime();
114
115 // Initialized during construction.
116 const bool has_audio_;
117 const bool has_video_;
118 const bool is_mse_;
119 const bool is_encrypted_;
120 scoped_refptr<MediaLog> media_log_;
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 watch times 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