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

Side by Side Diff: content/browser/media/media_internals.cc

Issue 2160963002: Add watch time metrics for HTML5 media playback. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Only log watch time once. Created 4 years, 4 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
« no previous file with comments | « no previous file | media/base/media_log.cc » ('j') | tools/metrics/histograms/histograms.xml » ('J')
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 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 #include "content/browser/media/media_internals.h" 5 #include "content/browser/media/media_internals.h"
6 6
7 #include <stddef.h> 7 #include <stddef.h>
8 8
9 #include <memory> 9 #include <memory>
10 #include <utility> 10 #include <utility>
11 11
12 #include "base/macros.h" 12 #include "base/macros.h"
13 #include "base/metrics/histogram.h" 13 #include "base/metrics/histogram.h"
14 #include "base/strings/string16.h" 14 #include "base/strings/string16.h"
15 #include "base/strings/string_number_conversions.h" 15 #include "base/strings/string_number_conversions.h"
16 #include "base/strings/stringprintf.h" 16 #include "base/strings/stringprintf.h"
17 #include "build/build_config.h" 17 #include "build/build_config.h"
18 #include "content/browser/renderer_host/media/media_stream_manager.h" 18 #include "content/browser/renderer_host/media/media_stream_manager.h"
19 #include "content/public/browser/browser_thread.h" 19 #include "content/public/browser/browser_thread.h"
20 #include "content/public/browser/notification_service.h" 20 #include "content/public/browser/notification_service.h"
21 #include "content/public/browser/notification_types.h" 21 #include "content/public/browser/notification_types.h"
22 #include "content/public/browser/render_frame_host.h" 22 #include "content/public/browser/render_frame_host.h"
23 #include "content/public/browser/render_process_host.h" 23 #include "content/public/browser/render_process_host.h"
24 #include "content/public/browser/web_contents.h" 24 #include "content/public/browser/web_contents.h"
25 #include "content/public/browser/web_ui.h" 25 #include "content/public/browser/web_ui.h"
26 #include "media/base/audio_parameters.h" 26 #include "media/base/audio_parameters.h"
27 #include "media/base/media_log_event.h" 27 #include "media/base/media_log_event.h"
28 #include "media/blink/watch_time_reporter.h"
28 #include "media/filters/gpu_video_decoder.h" 29 #include "media/filters/gpu_video_decoder.h"
29 30
30 #if !defined(OS_ANDROID) 31 #if !defined(OS_ANDROID)
31 #include "media/filters/decrypting_video_decoder.h" 32 #include "media/filters/decrypting_video_decoder.h"
32 #endif 33 #endif
33 34
34 namespace { 35 namespace {
35 36
36 static base::LazyInstance<content::MediaInternals>::Leaky g_media_internals = 37 static base::LazyInstance<content::MediaInternals>::Leaky g_media_internals =
37 LAZY_INSTANCE_INITIALIZER; 38 LAZY_INSTANCE_INITIALIZER;
(...skipping 244 matching lines...) Expand 10 before | Expand all | Expand 10 after
282 // Called when a render process is terminated. Reports the pipeline status to 283 // Called when a render process is terminated. Reports the pipeline status to
283 // UMA for every player associated with the renderer process and then deletes 284 // UMA for every player associated with the renderer process and then deletes
284 // the player state. 285 // the player state.
285 void OnProcessTerminated(int render_process_id); 286 void OnProcessTerminated(int render_process_id);
286 287
287 // Helper function to save the event payload to RendererPlayerMap. 288 // Helper function to save the event payload to RendererPlayerMap.
288 void SavePlayerState(int render_process_id, 289 void SavePlayerState(int render_process_id,
289 const media::MediaLogEvent& event); 290 const media::MediaLogEvent& event);
290 291
291 private: 292 private:
293 struct WatchTimeInfo {
294 base::TimeDelta all_watch_time = media::kNoTimestamp;
295 base::TimeDelta mse_watch_time = media::kNoTimestamp;
296 base::TimeDelta eme_watch_time = media::kNoTimestamp;
297 base::TimeDelta src_watch_time = media::kNoTimestamp;
298 base::TimeDelta ac_watch_time = media::kNoTimestamp;
299 base::TimeDelta battery_watch_time = media::kNoTimestamp;
300 };
301
292 struct PipelineInfo { 302 struct PipelineInfo {
293 bool has_pipeline = false; 303 bool has_pipeline = false;
294 media::PipelineStatus last_pipeline_status = media::PIPELINE_OK; 304 media::PipelineStatus last_pipeline_status = media::PIPELINE_OK;
295 bool has_audio = false; 305 bool has_audio = false;
296 bool has_video = false; 306 bool has_video = false;
297 bool video_dds = false; 307 bool video_dds = false;
298 bool video_decoder_changed = false; 308 bool video_decoder_changed = false;
299 std::string audio_codec_name; 309 std::string audio_codec_name;
300 std::string video_codec_name; 310 std::string video_codec_name;
301 std::string video_decoder; 311 std::string video_decoder;
312 WatchTimeInfo watch_time_info;
302 }; 313 };
303 314
304 // Helper function to report PipelineStatus associated with a player to UMA. 315 // Helper function to report PipelineStatus associated with a player to UMA.
305 void ReportUMAForPipelineStatus(const PipelineInfo& player_info); 316 void ReportUMAForPipelineStatus(const PipelineInfo& player_info);
306 317
307 // Helper to generate PipelineStatus UMA name for AudioVideo streams. 318 // Helper to generate PipelineStatus UMA name for AudioVideo streams.
308 std::string GetUMANameForAVStream(const PipelineInfo& player_info); 319 std::string GetUMANameForAVStream(const PipelineInfo& player_info);
309 320
321 // Saves the watch time info from |event| under |key| at |watch_time| if |key|
322 // is present in |event.params|.
323 void MaybeSaveWatchTime(const media::MediaLogEvent& event,
324 const char* key,
325 base::TimeDelta* watch_time) {
326 if (!event.params.HasKey(key))
327 return;
328
329 double in_seconds;
330 const bool result =
331 event.params.GetDoubleWithoutPathExpansion(key, &in_seconds);
332 DCHECK(result);
333 *watch_time = base::TimeDelta::FromSecondsD(in_seconds);
334
335 DVLOG(2) << "Saved watch time for " << key << " of " << *watch_time;
336 }
337
310 // Key is player id. 338 // Key is player id.
311 typedef std::map<int, PipelineInfo> PlayerInfoMap; 339 typedef std::map<int, PipelineInfo> PlayerInfoMap;
312 340
313 // Key is renderer id. 341 // Key is renderer id.
314 typedef std::map<int, PlayerInfoMap> RendererPlayerMap; 342 typedef std::map<int, PlayerInfoMap> RendererPlayerMap;
315 343
316 // Stores player information per renderer. 344 // Stores player information per renderer.
317 RendererPlayerMap renderer_info_; 345 RendererPlayerMap renderer_info_;
318 346
319 DISALLOW_COPY_AND_ASSIGN(MediaInternalsUMAHandler); 347 DISALLOW_COPY_AND_ASSIGN(MediaInternalsUMAHandler);
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
362 &player_info[event.id].video_decoder); 390 &player_info[event.id].video_decoder);
363 if (!previous_video_decoder.empty() && 391 if (!previous_video_decoder.empty() &&
364 previous_video_decoder != player_info[event.id].video_decoder) { 392 previous_video_decoder != player_info[event.id].video_decoder) {
365 player_info[event.id].video_decoder_changed = true; 393 player_info[event.id].video_decoder_changed = true;
366 } 394 }
367 } 395 }
368 if (event.params.HasKey("video_dds")) { 396 if (event.params.HasKey("video_dds")) {
369 event.params.GetBoolean("video_dds", &player_info[event.id].video_dds); 397 event.params.GetBoolean("video_dds", &player_info[event.id].video_dds);
370 } 398 }
371 break; 399 break;
400 case media::MediaLogEvent::Type::WATCH_TIME_UPDATE: {
401 DVLOG(2) << "Processing watch time update.";
402 WatchTimeInfo& wti = player_info[event.id].watch_time_info;
403 MaybeSaveWatchTime(event,
404 media::WatchTimeReporter::kHistogramAudioVideoAll,
405 &wti.all_watch_time);
406 MaybeSaveWatchTime(event,
407 media::WatchTimeReporter::kHistogramAudioVideoMse,
408 &wti.mse_watch_time);
409 MaybeSaveWatchTime(event,
410 media::WatchTimeReporter::kHistogramAudioVideoEme,
411 &wti.eme_watch_time);
412 MaybeSaveWatchTime(event,
413 media::WatchTimeReporter::kHistogramAudioVideoSrc,
414 &wti.src_watch_time);
415 MaybeSaveWatchTime(event,
416 media::WatchTimeReporter::kHistogramAudioVideoBattery,
417 &wti.battery_watch_time);
418 MaybeSaveWatchTime(event,
419 media::WatchTimeReporter::kHistogramAudioVideoAc,
420 &wti.ac_watch_time);
421 break;
422 }
372 default: 423 default:
373 break; 424 break;
374 } 425 }
375 return; 426 return;
376 } 427 }
377 428
378 std::string MediaInternals::MediaInternalsUMAHandler::GetUMANameForAVStream( 429 std::string MediaInternals::MediaInternalsUMAHandler::GetUMANameForAVStream(
379 const PipelineInfo& player_info) { 430 const PipelineInfo& player_info) {
380 DCHECK_CURRENTLY_ON(BrowserThread::UI); 431 DCHECK_CURRENTLY_ON(BrowserThread::UI);
381 static const char kPipelineUmaPrefix[] = "Media.PipelineStatus.AudioVideo."; 432 static const char kPipelineUmaPrefix[] = "Media.PipelineStatus.AudioVideo.";
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after
439 UMA_HISTOGRAM_ENUMERATION("Media.PipelineStatus.Unsupported", 490 UMA_HISTOGRAM_ENUMERATION("Media.PipelineStatus.Unsupported",
440 player_info.last_pipeline_status, 491 player_info.last_pipeline_status,
441 media::PIPELINE_STATUS_MAX + 1); 492 media::PIPELINE_STATUS_MAX + 1);
442 } 493 }
443 // Report whether video decoder fallback happened, but only if a video decoder 494 // Report whether video decoder fallback happened, but only if a video decoder
444 // was reported. 495 // was reported.
445 if (!player_info.video_decoder.empty()) { 496 if (!player_info.video_decoder.empty()) {
446 UMA_HISTOGRAM_BOOLEAN("Media.VideoDecoderFallback", 497 UMA_HISTOGRAM_BOOLEAN("Media.VideoDecoderFallback",
447 player_info.video_decoder_changed); 498 player_info.video_decoder_changed);
448 } 499 }
500
501 // Use a macro instead of a function so we can use the histogram macro (which
502 // checks that the uma name is a static value).
503 #define MAYBE_RECORD_WATCH_TIME(uma_name, watch_time) \
504 if (player_info.watch_time_info.watch_time != media::kNoTimestamp) { \
505 UMA_HISTOGRAM_LONG_TIMES(media::WatchTimeReporter::uma_name, \
506 player_info.watch_time_info.watch_time); \
507 }
508
509 MAYBE_RECORD_WATCH_TIME(kHistogramAudioVideoAll, all_watch_time);
510 MAYBE_RECORD_WATCH_TIME(kHistogramAudioVideoMse, mse_watch_time);
511 MAYBE_RECORD_WATCH_TIME(kHistogramAudioVideoEme, eme_watch_time);
512 MAYBE_RECORD_WATCH_TIME(kHistogramAudioVideoSrc, src_watch_time);
513 MAYBE_RECORD_WATCH_TIME(kHistogramAudioVideoBattery, battery_watch_time);
514 MAYBE_RECORD_WATCH_TIME(kHistogramAudioVideoAc, ac_watch_time);
515 #undef MAYBE_RECORD_WATCH_TIME
449 } 516 }
450 517
451 void MediaInternals::MediaInternalsUMAHandler::OnProcessTerminated( 518 void MediaInternals::MediaInternalsUMAHandler::OnProcessTerminated(
452 int render_process_id) { 519 int render_process_id) {
453 DCHECK_CURRENTLY_ON(BrowserThread::UI); 520 DCHECK_CURRENTLY_ON(BrowserThread::UI);
454 521
455 auto players_it = renderer_info_.find(render_process_id); 522 auto players_it = renderer_info_.find(render_process_id);
456 if (players_it == renderer_info_.end()) 523 if (players_it == renderer_info_.end())
457 return; 524 return;
458 auto it = players_it->second.begin(); 525 auto it = players_it->second.begin();
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after
522 589
523 *update = SerializeUpdate("media.onMediaEvent", &dict); 590 *update = SerializeUpdate("media.onMediaEvent", &dict);
524 return true; 591 return true;
525 } 592 }
526 593
527 void MediaInternals::OnMediaEvents( 594 void MediaInternals::OnMediaEvents(
528 int render_process_id, const std::vector<media::MediaLogEvent>& events) { 595 int render_process_id, const std::vector<media::MediaLogEvent>& events) {
529 DCHECK_CURRENTLY_ON(BrowserThread::UI); 596 DCHECK_CURRENTLY_ON(BrowserThread::UI);
530 // Notify observers that |event| has occurred. 597 // Notify observers that |event| has occurred.
531 for (const auto& event : events) { 598 for (const auto& event : events) {
532 if (CanUpdate()) { 599 // Some events should not be recorded in the UI.
533 base::string16 update; 600 if (event.type != media::MediaLogEvent::Type::WATCH_TIME_UPDATE) {
534 if (ConvertEventToUpdate(render_process_id, event, &update)) 601 if (CanUpdate()) {
535 SendUpdate(update); 602 base::string16 update;
603 if (ConvertEventToUpdate(render_process_id, event, &update))
604 SendUpdate(update);
605 }
606 SaveEvent(render_process_id, event);
536 } 607 }
537
538 SaveEvent(render_process_id, event);
539 uma_handler_->SavePlayerState(render_process_id, event); 608 uma_handler_->SavePlayerState(render_process_id, event);
540 } 609 }
541 } 610 }
542 611
543 void MediaInternals::AddUpdateCallback(const UpdateCallback& callback) { 612 void MediaInternals::AddUpdateCallback(const UpdateCallback& callback) {
544 DCHECK_CURRENTLY_ON(BrowserThread::UI); 613 DCHECK_CURRENTLY_ON(BrowserThread::UI);
545 update_callbacks_.push_back(callback); 614 update_callbacks_.push_back(callback);
546 615
547 base::AutoLock auto_lock(lock_); 616 base::AutoLock auto_lock(lock_);
548 can_update_ = true; 617 can_update_ = true;
(...skipping 156 matching lines...) Expand 10 before | Expand all | Expand 10 after
705 audio_streams_cached_data_.GetDictionary(cache_key, &existing_dict)); 774 audio_streams_cached_data_.GetDictionary(cache_key, &existing_dict));
706 existing_dict->MergeDictionary(value); 775 existing_dict->MergeDictionary(value);
707 } 776 }
708 } 777 }
709 778
710 if (CanUpdate()) 779 if (CanUpdate())
711 SendUpdate(SerializeUpdate(function, value)); 780 SendUpdate(SerializeUpdate(function, value));
712 } 781 }
713 782
714 } // namespace content 783 } // namespace content
OLDNEW
« no previous file with comments | « no previous file | media/base/media_log.cc » ('j') | tools/metrics/histograms/histograms.xml » ('J')

Powered by Google App Engine
This is Rietveld 408576698