Chromium Code Reviews| OLD | NEW |
|---|---|
| (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_ | |
| OLD | NEW |