Fix FullScreen crash in Webapp
[platform/framework/web/chromium-efl.git] / media / remoting / metrics.cc
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.
4
5 #include "media/remoting/metrics.h"
6
7 #include "base/metrics/histogram_functions.h"
8 #include "base/metrics/histogram_macros.h"
9 #include "media/base/sample_rates.h"
10
11 namespace media {
12 namespace remoting {
13
14 namespace {
15
16 ////////////////////////////////////////////////////////////////////////////////
17 // BEGIN: These were all borrowed from src/media/filters/ffmpeg_demuxer.cc.
18 // Some videos just want to watch the world burn, with a height of 0; cap the
19 // "infinite" aspect ratio resulting.
20 constexpr int kInfiniteRatio = 99999;
21
22 // Common aspect ratios (multiplied by 100 and truncated) used for histogramming
23 // video sizes.  These were taken on 20111103 from
24 // http://wikipedia.org/wiki/Aspect_ratio_(image)#Previous_and_currently_used_aspect_ratios
25 constexpr int kCommonAspectRatios100[] = {
26     100, 115, 133, 137, 143, 150, 155, 160,  166,
27     175, 177, 185, 200, 210, 220, 221, 235,  237,
28     240, 255, 259, 266, 276, 293, 400, 1200, kInfiniteRatio,
29 };
30
31 // END: Code borrowed from src/media/filter/ffmpeg_demuxer.cc.
32 ////////////////////////////////////////////////////////////////////////////////
33
34 // Buckets for video width histograms.
35 constexpr int kVideoWidthBuckets[] = {
36     180,  240,  320,  480,  640,  720,  872,  940,   1280,
37     1440, 1600, 1760, 1920, 2560, 3840, 7680, 16384,
38 };
39
40 }  // namespace
41
42 SessionMetricsRecorder::SessionMetricsRecorder()
43     : last_audio_codec_(AudioCodec::kUnknown),
44       last_channel_layout_(CHANNEL_LAYOUT_NONE),
45       last_sample_rate_(0),
46       last_video_codec_(VideoCodec::kUnknown),
47       last_video_profile_(VIDEO_CODEC_PROFILE_UNKNOWN) {}
48
49 SessionMetricsRecorder::~SessionMetricsRecorder() = default;
50
51 void SessionMetricsRecorder::WillStartSession(StartTrigger trigger) {
52   DCHECK(!start_trigger_);
53   start_trigger_ = trigger;
54   start_time_ = base::TimeTicks::Now();
55 }
56
57 void SessionMetricsRecorder::DidStartSession() {
58   UMA_HISTOGRAM_ENUMERATION("Media.Remoting.SessionStartTrigger",
59                             *start_trigger_, START_TRIGGER_MAX + 1);
60   if (last_audio_codec_ != AudioCodec::kUnknown)
61     RecordAudioConfiguration();
62   if (last_video_codec_ != VideoCodec::kUnknown)
63     RecordVideoConfiguration();
64   RecordTrackConfiguration();
65 }
66
67 void SessionMetricsRecorder::StartSessionFailed(
68     mojom::RemotingStartFailReason reason) {
69   UMA_HISTOGRAM_ENUMERATION("Media.Remoting.SessionStartFailedReason", reason);
70 }
71
72 void SessionMetricsRecorder::WillStopSession(StopTrigger trigger) {
73   if (!start_trigger_)
74     return;
75
76   // Record what triggered the end of the session.
77   UMA_HISTOGRAM_ENUMERATION("Media.Remoting.SessionStopTrigger", trigger,
78                             STOP_TRIGGER_MAX + 1);
79
80   // Record the session duration.
81   const base::TimeDelta session_duration = base::TimeTicks::Now() - start_time_;
82   UMA_HISTOGRAM_CUSTOM_TIMES("Media.Remoting.SessionDuration", session_duration,
83                              base::Seconds(15), base::Hours(12), 50);
84
85   if (session_duration <= base::Seconds(15)) {
86     // Record the session duration in finer scale for short sessions
87     UMA_HISTOGRAM_CUSTOM_TIMES("Media.Remoting.ShortSessionDuration",
88                                session_duration, base::Seconds(0.1),
89                                base::Seconds(15), 60);
90
91     if (session_duration <= base::Seconds(0.1)) {
92       UMA_HISTOGRAM_ENUMERATION(
93           "Media.Remoting.SessionStopTrigger.Duration0To100MilliSec", trigger,
94           STOP_TRIGGER_MAX + 1);
95     } else if (session_duration <= base::Seconds(1)) {
96       UMA_HISTOGRAM_ENUMERATION(
97           "Media.Remoting.SessionStopTrigger.Duration100MilliSecTo1Sec",
98           trigger, STOP_TRIGGER_MAX + 1);
99     } else if (session_duration <= base::Seconds(3)) {
100       UMA_HISTOGRAM_ENUMERATION(
101           "Media.Remoting.SessionStopTrigger.Duration1To3Sec", trigger,
102           STOP_TRIGGER_MAX + 1);
103     } else if (session_duration <= base::Seconds(5)) {
104       UMA_HISTOGRAM_ENUMERATION(
105           "Media.Remoting.SessionStopTrigger.Duration3To5Sec", trigger,
106           STOP_TRIGGER_MAX + 1);
107     } else if (session_duration <= base::Seconds(10)) {
108       UMA_HISTOGRAM_ENUMERATION(
109           "Media.Remoting.SessionStopTrigger.Duration5To10Sec", trigger,
110           STOP_TRIGGER_MAX + 1);
111     } else {
112       UMA_HISTOGRAM_ENUMERATION(
113           "Media.Remoting.SessionStopTrigger.Duration10To15Sec", trigger,
114           STOP_TRIGGER_MAX + 1);
115     }
116   }
117
118   // Reset |start_trigger_| since metrics recording of the current remoting
119   // session has now completed.
120   start_trigger_ = absl::nullopt;
121 }
122
123 void SessionMetricsRecorder::OnPipelineMetadataChanged(
124     const PipelineMetadata& metadata) {
125   if (metadata.has_audio && metadata.audio_decoder_config.IsValidConfig()) {
126     const auto& config = metadata.audio_decoder_config;
127     // While in a remoting session, record audio configuration changes.
128     const bool need_to_record_audio_configuration =
129         start_trigger_ && (config.codec() != last_audio_codec_ ||
130                            config.channel_layout() != last_channel_layout_ ||
131                            config.samples_per_second() != last_sample_rate_);
132     last_audio_codec_ = config.codec();
133     last_channel_layout_ = config.channel_layout();
134     last_sample_rate_ = config.samples_per_second();
135     if (need_to_record_audio_configuration)
136       RecordAudioConfiguration();
137   } else {
138     last_audio_codec_ = AudioCodec::kUnknown;
139     last_channel_layout_ = CHANNEL_LAYOUT_NONE;
140     last_sample_rate_ = 0;
141   }
142
143   if (metadata.has_video && metadata.video_decoder_config.IsValidConfig()) {
144     const auto& config = metadata.video_decoder_config;
145     // While in a remoting session, record video configuration changes.
146     const bool need_to_record_video_configuration =
147         start_trigger_ && (config.codec() != last_video_codec_ ||
148                            config.profile() != last_video_profile_ ||
149                            metadata.natural_size != last_natural_size_);
150     last_video_codec_ = config.codec();
151     last_video_profile_ = config.profile();
152     last_natural_size_ = metadata.natural_size;
153     if (need_to_record_video_configuration)
154       RecordVideoConfiguration();
155   } else {
156     last_video_codec_ = VideoCodec::kUnknown;
157     last_video_profile_ = VIDEO_CODEC_PROFILE_UNKNOWN;
158     last_natural_size_ = gfx::Size();
159   }
160
161   // While in a remoting session, record whether audio or video media streams
162   // started or ended.
163   if (start_trigger_)
164     RecordTrackConfiguration();
165 }
166
167 void SessionMetricsRecorder::OnRemotePlaybackDisabled(bool disabled) {
168   if (remote_playback_is_disabled_ &&
169       disabled == remote_playback_is_disabled_.value()) {
170     return;  // De-dupe redundant notifications.
171   }
172   UMA_HISTOGRAM_BOOLEAN("Media.Remoting.RemotePlaybackEnabledByPage",
173                         !disabled);
174   remote_playback_is_disabled_ = disabled;
175 }
176
177 void SessionMetricsRecorder::RecordVideoPixelRateSupport(
178     PixelRateSupport support) {
179   if (did_record_pixel_rate_support_) {
180     return;
181   }
182   did_record_pixel_rate_support_ = true;
183   base::UmaHistogramEnumeration("Media.Remoting.VideoPixelRateSupport",
184                                 support);
185 }
186
187 void SessionMetricsRecorder::RecordCompatibility(
188     RemotingCompatibility compatibility) {
189   if (did_record_compatibility_) {
190     return;
191   }
192   did_record_compatibility_ = true;
193   base::UmaHistogramEnumeration("Media.Remoting.Compatibility", compatibility);
194 }
195
196 void SessionMetricsRecorder::RecordAudioConfiguration() {
197   base::UmaHistogramEnumeration("Media.Remoting.AudioCodec", last_audio_codec_);
198   UMA_HISTOGRAM_ENUMERATION("Media.Remoting.AudioChannelLayout",
199                             last_channel_layout_, CHANNEL_LAYOUT_MAX + 1);
200   AudioSampleRate asr;
201   if (ToAudioSampleRate(last_sample_rate_, &asr)) {
202     UMA_HISTOGRAM_ENUMERATION("Media.Remoting.AudioSamplesPerSecond", asr,
203                               kAudioSampleRateMax + 1);
204   } else {
205     UMA_HISTOGRAM_COUNTS_1M("Media.Remoting.AudioSamplesPerSecondUnexpected",
206                             last_sample_rate_);
207   }
208 }
209
210 void SessionMetricsRecorder::RecordVideoConfiguration() {
211   base::UmaHistogramEnumeration("Media.Remoting.VideoCodec", last_video_codec_);
212   UMA_HISTOGRAM_ENUMERATION("Media.Remoting.VideoCodecProfile",
213                             last_video_profile_, VIDEO_CODEC_PROFILE_MAX + 1);
214   UMA_HISTOGRAM_CUSTOM_ENUMERATION(
215       "Media.Remoting.VideoNaturalWidth", last_natural_size_.width(),
216       base::CustomHistogram::ArrayToCustomEnumRanges(kVideoWidthBuckets));
217   // Intentionally use integer division to truncate the result.
218   const int aspect_ratio_100 =
219       last_natural_size_.height()
220           ? (last_natural_size_.width() * 100) / last_natural_size_.height()
221           : kInfiniteRatio;
222   UMA_HISTOGRAM_CUSTOM_ENUMERATION(
223       "Media.Remoting.VideoAspectRatio", aspect_ratio_100,
224       base::CustomHistogram::ArrayToCustomEnumRanges(kCommonAspectRatios100));
225 }
226
227 void SessionMetricsRecorder::RecordTrackConfiguration() {
228   TrackConfiguration config = NEITHER_AUDIO_NOR_VIDEO;
229   if (last_audio_codec_ != AudioCodec::kUnknown)
230     config = AUDIO_ONLY;
231   if (last_video_codec_ != VideoCodec::kUnknown) {
232     if (config == AUDIO_ONLY)
233       config = AUDIO_AND_VIDEO;
234     else
235       config = VIDEO_ONLY;
236   }
237   UMA_HISTOGRAM_ENUMERATION("Media.Remoting.TrackConfiguration", config,
238                             TRACK_CONFIGURATION_MAX + 1);
239 }
240
241 RendererMetricsRecorder::RendererMetricsRecorder()
242     : start_time_(base::TimeTicks::Now()) {}
243
244 RendererMetricsRecorder::~RendererMetricsRecorder() = default;
245
246 void RendererMetricsRecorder::OnRendererInitialized() {
247   const base::TimeDelta elapsed_since_start =
248       base::TimeTicks::Now() - start_time_;
249   UMA_HISTOGRAM_CUSTOM_TIMES("Media.Remoting.TimeUntilRemoteInitialized",
250                              elapsed_since_start, base::Milliseconds(10),
251                              base::Seconds(30), 50);
252 }
253
254 void RendererMetricsRecorder::OnEvidenceOfPlayoutAtReceiver() {
255   if (did_record_first_playout_)
256     return;
257   const base::TimeDelta elapsed_since_start =
258       base::TimeTicks::Now() - start_time_;
259   UMA_HISTOGRAM_CUSTOM_TIMES("Media.Remoting.TimeUntilFirstPlayout",
260                              elapsed_since_start, base::Milliseconds(10),
261                              base::Seconds(30), 50);
262   did_record_first_playout_ = true;
263 }
264
265 void RendererMetricsRecorder::OnAudioRateEstimate(int kilobits_per_second) {
266   UMA_HISTOGRAM_CUSTOM_COUNTS("Media.Remoting.AudioBitrate",
267                               kilobits_per_second, 1, 1024, 50);
268 }
269
270 void RendererMetricsRecorder::OnVideoRateEstimate(int kilobits_per_second) {
271   UMA_HISTOGRAM_CUSTOM_COUNTS("Media.Remoting.VideoBitrate",
272                               kilobits_per_second, 1, 16 * 1024, 50);
273 }
274
275 }  // namespace remoting
276 }  // namespace media