Chromium Code Reviews| OLD | NEW |
|---|---|
| (Empty) | |
| 1 // Copyright 2017 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 #include "media/remoting/metrics.h" | |
| 6 | |
| 7 #include "base/metrics/histogram_macros.h" | |
| 8 #include "media/audio/sample_rates.h" | |
| 9 | |
| 10 namespace media { | |
| 11 namespace remoting { | |
| 12 | |
| 13 namespace { | |
| 14 | |
| 15 //////////////////////////////////////////////////////////////////////////////// | |
| 16 // BEGIN: These were all borrowed from src/media/filter/ffmpeg_demuxer.cc. | |
| 17 // TODO(miu): This code will be de-duped in a soon-upcoming change. | |
| 18 | |
| 19 // Some videos just want to watch the world burn, with a height of 0; cap the | |
| 20 // "infinite" aspect ratio resulting. | |
| 21 constexpr int kInfiniteRatio = 99999; | |
| 22 | |
| 23 // Common aspect ratios (multiplied by 100 and truncated) used for histogramming | |
| 24 // video sizes. These were taken on 20111103 from | |
| 25 // http://wikipedia.org/wiki/Aspect_ratio_(image)#Previous_and_currently_used_as pect_ratios | |
| 26 constexpr int kCommonAspectRatios100[] = { | |
| 27 100, 115, 133, 137, 143, 150, 155, 160, 166, | |
| 28 175, 177, 185, 200, 210, 220, 221, 235, 237, | |
| 29 240, 255, 259, 266, 276, 293, 400, 1200, kInfiniteRatio, | |
| 30 }; | |
| 31 | |
| 32 void UmaHistogramAspectRatio(const char* name, const gfx::Size& size) { | |
| 33 UMA_HISTOGRAM_CUSTOM_ENUMERATION( | |
| 34 name, | |
|
Steven Holte
2017/01/17 19:40:11
This macro uses a static pointer, so you can't use
miu
2017/01/17 21:09:18
Ah! Good catch. Fixed. I realized I was just using
| |
| 35 // Intentionally use integer division to truncate the result. | |
| 36 size.height() ? (size.width() * 100) / size.height() : kInfiniteRatio, | |
| 37 base::CustomHistogram::ArrayToCustomRanges( | |
| 38 kCommonAspectRatios100, arraysize(kCommonAspectRatios100))); | |
| 39 } | |
| 40 | |
| 41 // END: Code borrowed from src/media/filter/ffmpeg_demuxer.cc. | |
| 42 //////////////////////////////////////////////////////////////////////////////// | |
| 43 | |
| 44 // Buckets for video width histograms. | |
| 45 constexpr int kVideoWidthBuckets[] = { | |
| 46 180, 240, 320, 480, 640, 720, 872, 940, 1280, | |
| 47 1440, 1600, 1760, 1920, 2560, 3840, 7680, 16384, | |
| 48 }; | |
| 49 | |
| 50 void UmaHistogramVideoWidth(const char* name, const gfx::Size& size) { | |
| 51 UMA_HISTOGRAM_CUSTOM_ENUMERATION( | |
|
Steven Holte
2017/01/17 19:40:11
Ditto.
miu
2017/01/17 21:09:18
Done.
| |
| 52 name, size.width(), | |
| 53 base::CustomHistogram::ArrayToCustomRanges( | |
| 54 kVideoWidthBuckets, arraysize(kVideoWidthBuckets))); | |
| 55 } | |
| 56 | |
| 57 } // namespace | |
| 58 | |
| 59 SessionMetricsRecorder::SessionMetricsRecorder() | |
| 60 : last_audio_codec_(kUnknownAudioCodec), | |
| 61 last_channel_layout_(CHANNEL_LAYOUT_NONE), | |
| 62 last_sample_rate_(0), | |
| 63 last_video_codec_(kUnknownVideoCodec), | |
| 64 last_video_profile_(VIDEO_CODEC_PROFILE_UNKNOWN), | |
| 65 remote_playback_is_disabled_(false) {} | |
| 66 | |
| 67 SessionMetricsRecorder::~SessionMetricsRecorder() = default; | |
| 68 | |
| 69 void SessionMetricsRecorder::WillStartSession(StartTrigger trigger) { | |
| 70 DCHECK(!start_trigger_); | |
| 71 start_trigger_ = trigger; | |
| 72 start_time_ = base::TimeTicks::Now(); | |
| 73 } | |
| 74 | |
| 75 void SessionMetricsRecorder::DidStartSession() { | |
| 76 UMA_HISTOGRAM_ENUMERATION("Media.Remoting.SessionStartTrigger", | |
| 77 *start_trigger_, START_TRIGGER_MAX + 1); | |
| 78 if (last_audio_codec_ != kUnknownAudioCodec) | |
| 79 RecordAudioConfiguration(); | |
| 80 if (last_video_codec_ != kUnknownVideoCodec) | |
| 81 RecordVideoConfiguration(); | |
| 82 RecordTrackConfiguration(); | |
| 83 } | |
| 84 | |
| 85 void SessionMetricsRecorder::WillStopSession(StopTrigger trigger) { | |
| 86 if (!start_trigger_) | |
| 87 return; | |
| 88 | |
| 89 // Record what triggered the end of the session. | |
| 90 UMA_HISTOGRAM_ENUMERATION("Media.Remoting.SessionStopTrigger", trigger, | |
| 91 STOP_TRIGGER_MAX + 1); | |
| 92 | |
| 93 // Record the session duration. | |
|
xjz
2017/01/17 05:36:25
nit: DCHECK(!start_time_.is_null());
miu
2017/01/17 21:09:18
I left it out because I think it's pretty obvious
| |
| 94 const base::TimeDelta session_duration = base::TimeTicks::Now() - start_time_; | |
| 95 UMA_HISTOGRAM_CUSTOM_TIMES("Media.Remoting.SessionDuration", session_duration, | |
| 96 base::TimeDelta::FromSeconds(15), | |
| 97 base::TimeDelta::FromHours(12), 50); | |
| 98 | |
| 99 // Reset |start_trigger_| since metrics recording of the current remoting | |
| 100 // session has now completed. | |
| 101 start_trigger_ = base::nullopt; | |
| 102 } | |
| 103 | |
| 104 void SessionMetricsRecorder::OnPipelineMetadataChanged( | |
| 105 const PipelineMetadata& metadata) { | |
| 106 if (metadata.has_audio && metadata.audio_decoder_config.IsValidConfig()) { | |
| 107 const auto& config = metadata.audio_decoder_config; | |
| 108 // While in a remoting session, record audio configuration changes. | |
| 109 const bool need_to_record_audio_configuration = | |
| 110 start_trigger_ && (config.codec() != last_audio_codec_ || | |
| 111 config.channel_layout() != last_channel_layout_ || | |
| 112 config.samples_per_second() != last_sample_rate_); | |
| 113 last_audio_codec_ = config.codec(); | |
| 114 last_channel_layout_ = config.channel_layout(); | |
| 115 last_sample_rate_ = config.samples_per_second(); | |
| 116 if (need_to_record_audio_configuration) | |
| 117 RecordAudioConfiguration(); | |
| 118 } else { | |
| 119 last_audio_codec_ = kUnknownAudioCodec; | |
| 120 last_channel_layout_ = CHANNEL_LAYOUT_NONE; | |
| 121 last_sample_rate_ = 0; | |
| 122 } | |
| 123 | |
| 124 if (metadata.has_video && metadata.video_decoder_config.IsValidConfig()) { | |
| 125 const auto& config = metadata.video_decoder_config; | |
| 126 // While in a remoting session, record video configuration changes. | |
| 127 const bool need_to_record_video_configuration = | |
| 128 start_trigger_ && (config.codec() != last_video_codec_ || | |
| 129 config.profile() != last_video_profile_ || | |
| 130 config.natural_size() != last_natural_size_); | |
|
xjz
2017/01/17 05:36:25
Do we want to record the change of natural size? C
miu
2017/01/17 21:09:18
Done. Yes, that's the better one to use.
| |
| 131 last_video_codec_ = config.codec(); | |
| 132 last_video_profile_ = config.profile(); | |
| 133 last_natural_size_ = config.natural_size(); | |
|
xjz
2017/01/17 05:36:25
As commented above, maybe s/config.natural_size()/
miu
2017/01/17 21:09:18
Done.
| |
| 134 if (need_to_record_video_configuration) | |
| 135 RecordVideoConfiguration(); | |
| 136 } else { | |
| 137 last_video_codec_ = kUnknownVideoCodec; | |
| 138 last_video_profile_ = VIDEO_CODEC_PROFILE_UNKNOWN; | |
| 139 last_natural_size_ = gfx::Size(); | |
| 140 } | |
| 141 | |
| 142 // While in a remoting session, record whether audio or video media streams | |
| 143 // started or ended. | |
| 144 if (start_trigger_) | |
| 145 RecordTrackConfiguration(); | |
| 146 } | |
| 147 | |
| 148 void SessionMetricsRecorder::OnRemotePlaybackDisabled(bool disabled) { | |
| 149 if (disabled == remote_playback_is_disabled_) | |
| 150 return; // De-dupe redundant notifications. | |
| 151 UMA_HISTOGRAM_BOOLEAN("Media.Remoting.AllowedByPage", !disabled); | |
| 152 remote_playback_is_disabled_ = disabled; | |
| 153 } | |
| 154 | |
| 155 void SessionMetricsRecorder::OnPosterImageDownloaded( | |
| 156 base::TimeDelta download_duration, | |
| 157 bool success) { | |
| 158 const auto name = success ? "Media.Remoting.PosterDownloadDuration.Success" | |
| 159 : "Media.Remoting.PosterDownloadDuration.Fail"; | |
| 160 UMA_HISTOGRAM_CUSTOM_TIMES(name, download_duration, | |
|
Steven Holte
2017/01/17 19:40:11
Ditto. For this one you can use UmaHistogramCusto
miu
2017/01/17 21:09:18
Done.
| |
| 161 base::TimeDelta::FromMilliseconds(10), | |
| 162 base::TimeDelta::FromSeconds(30), 50); | |
| 163 } | |
| 164 | |
| 165 void SessionMetricsRecorder::RecordAudioConfiguration() { | |
| 166 UMA_HISTOGRAM_ENUMERATION("Media.Remoting.AudioCodec", last_audio_codec_, | |
| 167 kAudioCodecMax + 1); | |
| 168 UMA_HISTOGRAM_ENUMERATION("Media.Remoting.AudioChannelLayout", | |
| 169 last_channel_layout_, CHANNEL_LAYOUT_MAX + 1); | |
| 170 AudioSampleRate asr; | |
| 171 if (ToAudioSampleRate(last_sample_rate_, &asr)) { | |
| 172 UMA_HISTOGRAM_ENUMERATION("Media.Remoting.AudioSamplesPerSecond", asr, | |
| 173 kAudioSampleRateMax + 1); | |
| 174 } else { | |
| 175 UMA_HISTOGRAM_COUNTS_1M("Media.Remoting.AudioSamplesPerSecondUnexpected", | |
| 176 last_sample_rate_); | |
| 177 } | |
| 178 } | |
| 179 | |
| 180 void SessionMetricsRecorder::RecordVideoConfiguration() { | |
| 181 UMA_HISTOGRAM_ENUMERATION("Media.Remoting.VideoCodec", last_video_codec_, | |
| 182 kVideoCodecMax + 1); | |
| 183 UMA_HISTOGRAM_ENUMERATION("Media.Remoting.VideoCodecProfile", | |
| 184 last_video_profile_, VIDEO_CODEC_PROFILE_MAX + 1); | |
| 185 UmaHistogramVideoWidth("Media.Remoting.VideoNaturalWidth", | |
| 186 last_natural_size_); | |
| 187 UmaHistogramAspectRatio("Media.Remoting.VideoAspectRatio", | |
| 188 last_natural_size_); | |
| 189 } | |
| 190 | |
| 191 void SessionMetricsRecorder::RecordTrackConfiguration() { | |
| 192 TrackConfiguration config = NEITHER_AUDIO_NOR_VIDEO; | |
| 193 if (last_audio_codec_ != kUnknownAudioCodec) | |
| 194 config = AUDIO_ONLY; | |
| 195 if (last_video_codec_ != kUnknownVideoCodec) { | |
| 196 if (config == AUDIO_ONLY) | |
| 197 config = AUDIO_AND_VIDEO; | |
| 198 else | |
| 199 config = VIDEO_ONLY; | |
| 200 } | |
| 201 UMA_HISTOGRAM_ENUMERATION("Media.Remoting.TrackConfiguration", config, | |
| 202 TRACK_CONFIGURATION_MAX + 1); | |
| 203 } | |
| 204 | |
| 205 RendererMetricsRecorder::RendererMetricsRecorder() | |
| 206 : start_time_(base::TimeTicks::Now()), did_record_first_playout_(false) {} | |
| 207 | |
| 208 RendererMetricsRecorder::~RendererMetricsRecorder() = default; | |
| 209 | |
| 210 void RendererMetricsRecorder::OnRendererInitialized() { | |
| 211 const base::TimeDelta elapsed_since_start = | |
| 212 base::TimeTicks::Now() - start_time_; | |
| 213 UMA_HISTOGRAM_CUSTOM_TIMES("Media.Remoting.TimeUntilRemoteInitialized", | |
| 214 elapsed_since_start, | |
| 215 base::TimeDelta::FromMilliseconds(10), | |
| 216 base::TimeDelta::FromSeconds(30), 50); | |
| 217 } | |
| 218 | |
| 219 void RendererMetricsRecorder::OnEvidenceOfPlayoutAtReceiver() { | |
| 220 if (did_record_first_playout_) | |
| 221 return; | |
| 222 const base::TimeDelta elapsed_since_start = | |
| 223 base::TimeTicks::Now() - start_time_; | |
| 224 UMA_HISTOGRAM_CUSTOM_TIMES("Media.Remoting.TimeUntilFirstPlayout", | |
| 225 elapsed_since_start, | |
| 226 base::TimeDelta::FromMilliseconds(10), | |
| 227 base::TimeDelta::FromSeconds(30), 50); | |
| 228 did_record_first_playout_ = true; | |
| 229 } | |
| 230 | |
| 231 void RendererMetricsRecorder::OnAudioRateEstimate(int kilobits_per_second) { | |
| 232 UMA_HISTOGRAM_CUSTOM_COUNTS("Media.Remoting.AudioBitrate", | |
| 233 kilobits_per_second, 1, 1024, 50); | |
| 234 } | |
| 235 | |
| 236 void RendererMetricsRecorder::OnVideoRateEstimate(int kilobits_per_second) { | |
| 237 UMA_HISTOGRAM_CUSTOM_COUNTS("Media.Remoting.VideoBitrate", | |
| 238 kilobits_per_second, 1, 16 * 1024, 50); | |
| 239 } | |
| 240 | |
| 241 } // namespace remoting | |
| 242 } // namespace media | |
| OLD | NEW |