1 // Copyright 2017 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #ifndef MEDIA_MOJO_SERVICES_WATCH_TIME_RECORDER_H_
6 #define MEDIA_MOJO_SERVICES_WATCH_TIME_RECORDER_H_
10 #include "base/compiler_specific.h"
11 #include "base/containers/flat_map.h"
12 #include "base/time/time.h"
13 #include "media/base/audio_codecs.h"
14 #include "media/base/pipeline_status.h"
15 #include "media/base/video_codecs.h"
16 #include "media/mojo/mojom/watch_time_recorder.mojom.h"
17 #include "media/mojo/services/media_mojo_export.h"
18 #include "services/metrics/public/cpp/ukm_source_id.h"
23 // See mojom::WatchTimeRecorder for documentation.
24 class MEDIA_MOJO_EXPORT WatchTimeRecorder : public mojom::WatchTimeRecorder {
26 using RecordAggregateWatchTimeCallback =
27 base::OnceCallback<void(base::TimeDelta total_watch_time,
28 base::TimeDelta time_stamp,
32 WatchTimeRecorder(mojom::PlaybackPropertiesPtr properties,
33 ukm::SourceId source_id,
36 RecordAggregateWatchTimeCallback record_playback_cb);
38 WatchTimeRecorder(const WatchTimeRecorder&) = delete;
39 WatchTimeRecorder& operator=(const WatchTimeRecorder&) = delete;
41 ~WatchTimeRecorder() override;
43 // mojom::WatchTimeRecorder implementation:
44 void RecordWatchTime(WatchTimeKey key, base::TimeDelta watch_time) override;
45 void FinalizeWatchTime(
46 const std::vector<WatchTimeKey>& watch_time_keys) override;
47 void OnError(const PipelineStatus& status) override;
48 void UpdateSecondaryProperties(
49 mojom::SecondaryPlaybackPropertiesPtr secondary_properties) override;
50 void SetAutoplayInitiated(bool value) override;
51 void OnDurationChanged(base::TimeDelta duration) override;
52 void UpdateVideoDecodeStats(uint32_t video_frames_decoded,
53 uint32_t video_frames_dropped) override;
54 void UpdateUnderflowCount(int32_t total_count) override;
55 void UpdateUnderflowDuration(int32_t total_completed_count,
56 base::TimeDelta total_duration) override;
57 void OnCurrentTimestampChanged(base::TimeDelta current_timestamp) override;
60 // Records a UKM event based on |aggregate_watch_time_info_|; only recorded
61 // with a complete finalize (destruction or empty FinalizeWatchTime call).
62 // Clears |aggregate_watch_time_info_| upon completion.
63 void RecordUkmPlaybackData();
64 bool ShouldRecordUma() const;
66 const mojom::PlaybackPropertiesPtr properties_;
68 const ukm::SourceId source_id_;
70 // Are UKM reports for the main frame or for a subframe?
71 const bool is_top_frame_;
73 // The provider ID which constructed this recorder. Used to record a UKM entry
74 // at destruction that can be correlated with the final status for the
75 // associated WebMediaPlayerImpl instance.
76 const uint64_t player_id_;
78 // Mapping of WatchTime metric keys to MeanTimeBetweenRebuffers (MTBR), smooth
79 // rate (had zero rebuffers), and discard (<7s watch time) keys.
80 struct ExtendedMetricsKeyMap {
81 ExtendedMetricsKeyMap(const ExtendedMetricsKeyMap& copy);
82 ExtendedMetricsKeyMap(WatchTimeKey watch_time_key,
83 base::StringPiece mtbr_key,
84 base::StringPiece smooth_rate_key,
85 base::StringPiece discard_key);
86 const WatchTimeKey watch_time_key;
87 const base::StringPiece mtbr_key;
88 const base::StringPiece smooth_rate_key;
89 const base::StringPiece discard_key;
91 const std::vector<ExtendedMetricsKeyMap> extended_metrics_keys_;
93 using WatchTimeInfo = base::flat_map<WatchTimeKey, base::TimeDelta>;
94 WatchTimeInfo watch_time_info_;
96 // Aggregate record of all watch time for a given set of secondary properties.
97 struct WatchTimeUkmRecord {
98 explicit WatchTimeUkmRecord(
99 mojom::SecondaryPlaybackPropertiesPtr properties);
100 WatchTimeUkmRecord(WatchTimeUkmRecord&& record);
101 ~WatchTimeUkmRecord();
103 // Properties for this segment of UKM watch time.
104 mojom::SecondaryPlaybackPropertiesPtr secondary_properties;
106 // Sum of all watch time data since the last complete finalize.
107 WatchTimeInfo aggregate_watch_time_info;
109 // Total underflow count and duration for this segment of UKM watch time.
110 int total_underflow_count = 0;
111 int total_completed_underflow_count = 0;
112 base::TimeDelta total_underflow_duration;
114 uint32_t total_video_frames_decoded = 0;
115 uint32_t total_video_frames_dropped = 0;
118 // List of all watch time segments. A new entry is added for every secondary
120 std::vector<WatchTimeUkmRecord> ukm_records_;
122 uint32_t video_frames_decoded_ = 0;
123 uint32_t video_frames_dropped_ = 0;
125 int underflow_count_ = 0;
126 int completed_underflow_count_ = 0;
127 base::TimeDelta underflow_duration_;
129 PipelineStatusCodes pipeline_status_ = PIPELINE_OK;
130 base::TimeDelta duration_ = kNoTimestamp;
131 base::TimeDelta last_timestamp_ = kNoTimestamp;
132 absl::optional<bool> autoplay_initiated_;
133 RecordAggregateWatchTimeCallback record_playback_cb_;
138 #endif // MEDIA_MOJO_SERVICES_WATCH_TIME_RECORDER_H_