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

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

Issue 2780533004: Start recording background video watch time. (Closed)
Patch Set: Add moar tests. Created 3 years, 8 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
1 // Copyright 2016 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #ifndef MEDIA_BLINK_WATCH_TIME_REPORTER_H_ 5 #ifndef MEDIA_BLINK_WATCH_TIME_REPORTER_H_
6 #define MEDIA_BLINK_WATCH_TIME_REPORTER_H_ 6 #define MEDIA_BLINK_WATCH_TIME_REPORTER_H_
7 7
8 #include "base/callback.h" 8 #include "base/callback.h"
9 #include "base/power_monitor/power_observer.h" 9 #include "base/power_monitor/power_observer.h"
10 #include "base/time/time.h" 10 #include "base/time/time.h"
11 #include "base/timer/timer.h" 11 #include "base/timer/timer.h"
12 #include "media/base/media_log.h" 12 #include "media/base/media_log.h"
13 #include "media/base/timestamp_constants.h" 13 #include "media/base/timestamp_constants.h"
14 #include "media/blink/media_blink_export.h" 14 #include "media/blink/media_blink_export.h"
15 #include "ui/gfx/geometry/size.h" 15 #include "ui/gfx/geometry/size.h"
16 16
17 namespace media { 17 namespace media {
18 18
19 // Class for monitoring and reporting watch time in response to various state 19 // Class for monitoring and reporting watch time in response to various state
20 // changes during the playback of media. We record metrics for audio only 20 // changes during the playback of media. We record metrics for audio only
21 // playbacks as well as audio+video playbacks of sufficient size. 21 // playbacks as well as audio+video playbacks of sufficient size.
22 // 22 //
23 // Watch time for our purposes is defined as the amount of elapsed media time 23 // Watch time for our purposes is defined as the amount of elapsed media time
24 // for audio only or audio+video media. A minimum of 7 seconds of unmuted, 24 // for audio only or audio+video media. A minimum of 7 seconds of unmuted media
25 // foreground (where this is video) media must be watched to start watch time 25 // must be watched to start watch time monitoring. Watch time is checked every 5
26 // monitoring. Watch time is checked every 5 seconds from then on and reported 26 // seconds from then on and reported to multiple buckets: All, MSE, SRC, EME,
27 // to multiple buckets: All, MSE, SRC, EME, AC, and battery. 27 // AC, and battery.
28 // 28 //
29 // Any one of paused, hidden (where this is video), or muted is sufficient to 29 // Any one of paused, hidden (where this is video), or muted is sufficient to
30 // stop watch time metric reports. Each of these has a hysteresis where if the 30 // stop watch time metric reports. Each of these has a hysteresis where if the
31 // state change is undone within 5 seconds, the watch time will be counted as 31 // state change is undone within 5 seconds, the watch time will be counted as
32 // uninterrupted. 32 // uninterrupted.
33 // 33 //
34 // If the media is audio+video, foreground watch time is logged to the normal
35 // AudioVideo bucket, while background watch time goes to the specific
36 // AudioVideo.Background bucket. As with other events, there is hysteresis on
37 // change between the foreground and background.
38 //
34 // Power events (on/off battery power) have a similar hysteresis, but unlike 39 // Power events (on/off battery power) have a similar hysteresis, but unlike
35 // the aforementioned properties, will not stop metric collection. 40 // the aforementioned properties, will not stop metric collection.
36 // 41 //
37 // Each seek event will result in a new watch time metric being started and the 42 // Each seek event will result in a new watch time metric being started and the
38 // old metric finalized as accurately as possible. 43 // old metric finalized as accurately as possible.
39 class MEDIA_BLINK_EXPORT WatchTimeReporter : base::PowerObserver { 44 class MEDIA_BLINK_EXPORT WatchTimeReporter : base::PowerObserver {
40 public: 45 public:
41 using GetMediaTimeCB = base::Callback<base::TimeDelta(void)>; 46 using GetMediaTimeCB = base::Callback<base::TimeDelta(void)>;
42 47
43 // Constructor for the reporter; all requested metadata should be fully known 48 // Constructor for the reporter; all requested metadata should be fully known
(...skipping 17 matching lines...) Expand all
61 bool is_mse, 66 bool is_mse,
62 bool is_encrypted, 67 bool is_encrypted,
63 bool is_embedded_media_experience_enabled, 68 bool is_embedded_media_experience_enabled,
64 scoped_refptr<MediaLog> media_log, 69 scoped_refptr<MediaLog> media_log,
65 const gfx::Size& initial_video_size, 70 const gfx::Size& initial_video_size,
66 const GetMediaTimeCB& get_media_time_cb); 71 const GetMediaTimeCB& get_media_time_cb);
67 ~WatchTimeReporter() override; 72 ~WatchTimeReporter() override;
68 73
69 // These methods are used to ensure that watch time is only reported for 74 // 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 75 // media that is actually playing. They should be called whenever the media
71 // starts or stops playing for any reason. 76 // starts or stops playing for any reason. If the media is audio+video and
77 // currently hidden, OnPlaying() will start background watch time reporting.
72 void OnPlaying(); 78 void OnPlaying();
73 void OnPaused(); 79 void OnPaused();
74 80
75 // This will immediately finalize any outstanding watch time reports and stop 81 // This will immediately finalize any outstanding watch time reports and stop
76 // the reporting timer. Clients should call OnPlaying() upon seek completion 82 // the reporting timer. Clients should call OnPlaying() upon seek completion
77 // to restart the reporting timer. 83 // to restart the reporting timer.
78 void OnSeeking(); 84 void OnSeeking();
79 85
80 // This method is used to ensure that watch time is only reported for media 86 // 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 87 // that is actually audible to the user. It should be called whenever the
82 // volume changes. 88 // volume changes.
83 // 89 //
84 // Note: This does not catch all cases. E.g., headphones that are being 90 // Note: This does not catch all cases. E.g., headphones that are being
85 // listened too, or even OS level volume state. 91 // listened too, or even OS level volume state.
86 void OnVolumeChange(double volume); 92 void OnVolumeChange(double volume);
87 93
88 // These methods are used to ensure that watch time is only reported for 94 // 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 95 // videos that are actually visible to the user. They should be called when
90 // the video is shown or hidden respectively. 96 // the video is shown or hidden respectively. OnHidden() will start background
97 // watch time reporting if the media is audio+video.
91 // 98 //
92 // TODO(dalecurtis): At present, this is only called when the entire content 99 // 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 100 // 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 101 // 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. 102 // port. We need a method for rejecting out of view port videos.
96 void OnShown(); 103 void OnShown();
97 void OnHidden(); 104 void OnHidden();
98 105
106 // Setup the reporting interval to be immediate to avoid spinning real time
107 // within the unit test.
108 void set_reporting_interval_for_testing() {
109 reporting_interval_ = base::TimeDelta();
110 }
111
99 private: 112 private:
100 friend class WatchTimeReporterTest; 113 friend class WatchTimeReporterTest;
101 114
115 // Internal constructor for marking background status.
116 WatchTimeReporter(bool has_audio,
117 bool has_video,
118 bool is_mse,
119 bool is_encrypted,
120 bool is_embedded_media_experience_enabled,
121 scoped_refptr<MediaLog> media_log,
122 const gfx::Size& initial_video_size,
123 const GetMediaTimeCB& get_media_time_cb,
124 bool is_background);
125
102 // base::PowerObserver implementation. 126 // base::PowerObserver implementation.
103 // 127 //
104 // We only observe power source changes. We don't need to observe suspend and 128 // 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 129 // resume events because we report watch time in terms of elapsed media time
106 // and not in terms of elapsed real time. 130 // and not in terms of elapsed real time.
107 void OnPowerStateChange(bool on_battery_power) override; 131 void OnPowerStateChange(bool on_battery_power) override;
108 132
109 bool ShouldReportWatchTime(); 133 bool ShouldReportWatchTime();
110 void MaybeStartReportingTimer(base::TimeDelta start_timestamp); 134 void MaybeStartReportingTimer(base::TimeDelta start_timestamp);
111 enum class FinalizeTime { IMMEDIATELY, ON_NEXT_UPDATE }; 135 enum class FinalizeTime { IMMEDIATELY, ON_NEXT_UPDATE };
112 void MaybeFinalizeWatchTime(FinalizeTime finalize_time); 136 void MaybeFinalizeWatchTime(FinalizeTime finalize_time);
113 void UpdateWatchTime(); 137 void UpdateWatchTime();
114 138
115 // Initialized during construction. 139 // Initialized during construction.
116 const bool has_audio_; 140 const bool has_audio_;
117 const bool has_video_; 141 const bool has_video_;
118 const bool is_mse_; 142 const bool is_mse_;
119 const bool is_encrypted_; 143 const bool is_encrypted_;
120 const bool is_embedded_media_experience_enabled_; 144 const bool is_embedded_media_experience_enabled_;
121 scoped_refptr<MediaLog> media_log_; 145 scoped_refptr<MediaLog> media_log_;
122 const gfx::Size initial_video_size_; 146 const gfx::Size initial_video_size_;
123 const GetMediaTimeCB get_media_time_cb_; 147 const GetMediaTimeCB get_media_time_cb_;
148 const bool is_background_;
124 149
125 // The amount of time between each UpdateWatchTime(); this is the frequency by 150 // The amount of time between each UpdateWatchTime(); this is the frequency by
126 // which the watch times are updated. In the event of a process crash or kill 151 // which the watch times are updated. In the event of a process crash or kill
127 // this is also the most amount of watch time that we might lose. 152 // this is also the most amount of watch time that we might lose.
128 base::TimeDelta reporting_interval_ = base::TimeDelta::FromSeconds(5); 153 base::TimeDelta reporting_interval_ = base::TimeDelta::FromSeconds(5);
129 154
130 base::RepeatingTimer reporting_timer_; 155 base::RepeatingTimer reporting_timer_;
131 156
132 // Updated by the OnXXX() methods above. 157 // Updated by the OnXXX() methods above.
133 bool is_on_battery_power_ = false; 158 bool is_on_battery_power_ = false;
134 bool is_playing_ = false; 159 bool is_playing_ = false;
135 bool is_visible_ = true; 160 bool is_visible_ = true;
136 double volume_ = 1.0; 161 double volume_ = 1.0;
137 162
138 // The last media timestamp seen by UpdateWatchTime(). 163 // The last media timestamp seen by UpdateWatchTime().
139 base::TimeDelta last_media_timestamp_ = kNoTimestamp; 164 base::TimeDelta last_media_timestamp_ = kNoTimestamp;
140 165
141 // The starting and ending timestamps used for reporting watch time. 166 // The starting and ending timestamps used for reporting watch time.
142 base::TimeDelta start_timestamp_; 167 base::TimeDelta start_timestamp_;
143 base::TimeDelta end_timestamp_ = kNoTimestamp; 168 base::TimeDelta end_timestamp_ = kNoTimestamp;
144 169
145 // Similar to the above but tracks watch time relative to whether or not 170 // Similar to the above but tracks watch time relative to whether or not
146 // battery or AC power is being used. 171 // battery or AC power is being used.
147 base::TimeDelta start_timestamp_for_power_; 172 base::TimeDelta start_timestamp_for_power_;
148 base::TimeDelta end_timestamp_for_power_ = kNoTimestamp; 173 base::TimeDelta end_timestamp_for_power_ = kNoTimestamp;
149 174
175 // Special case reporter for handling background video watch time. Configured
176 // as an audio only WatchTimeReporter with |is_background_| set to true.
177 std::unique_ptr<WatchTimeReporter> background_reporter_;
178
150 DISALLOW_COPY_AND_ASSIGN(WatchTimeReporter); 179 DISALLOW_COPY_AND_ASSIGN(WatchTimeReporter);
151 }; 180 };
152 181
153 } // namespace media 182 } // namespace media
154 183
155 #endif // MEDIA_BLINK_WATCH_TIME_REPORTER_H_ 184 #endif // MEDIA_BLINK_WATCH_TIME_REPORTER_H_
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698