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

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

Issue 2814843005: media: Add incognito EME playback UMA (Closed)
Patch Set: Created 3 years, 8 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/blink/webmediaplayer_impl.cc » ('j') | no next file with comments »
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 <tuple>
10 #include <utility> 11 #include <utility>
11 12
12 #include "base/macros.h" 13 #include "base/macros.h"
13 #include "base/metrics/histogram_macros.h" 14 #include "base/metrics/histogram_macros.h"
14 #include "base/strings/string16.h" 15 #include "base/strings/string16.h"
15 #include "base/strings/string_number_conversions.h" 16 #include "base/strings/string_number_conversions.h"
16 #include "base/strings/stringprintf.h" 17 #include "base/strings/stringprintf.h"
17 #include "build/build_config.h" 18 #include "build/build_config.h"
18 #include "content/browser/renderer_host/media/media_stream_manager.h" 19 #include "content/browser/renderer_host/media/media_stream_manager.h"
20 #include "content/public/browser/browser_context.h"
19 #include "content/public/browser/browser_thread.h" 21 #include "content/public/browser/browser_thread.h"
20 #include "content/public/browser/notification_service.h" 22 #include "content/public/browser/notification_service.h"
21 #include "content/public/browser/notification_types.h" 23 #include "content/public/browser/notification_types.h"
22 #include "content/public/browser/render_frame_host.h" 24 #include "content/public/browser/render_frame_host.h"
23 #include "content/public/browser/render_process_host.h" 25 #include "content/public/browser/render_process_host.h"
24 #include "content/public/browser/web_contents.h" 26 #include "content/public/browser/web_contents.h"
25 #include "content/public/browser/web_ui.h" 27 #include "content/public/browser/web_ui.h"
26 #include "media/base/audio_parameters.h" 28 #include "media/base/audio_parameters.h"
27 #include "media/base/media_log_event.h" 29 #include "media/base/media_log_event.h"
28 #include "media/filters/gpu_video_decoder.h" 30 #include "media/filters/gpu_video_decoder.h"
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after
83 case media::AudioParameters::AUDIO_BITSTREAM_EAC3: 85 case media::AudioParameters::AUDIO_BITSTREAM_EAC3:
84 return "eac3"; 86 return "eac3";
85 case media::AudioParameters::AUDIO_FAKE: 87 case media::AudioParameters::AUDIO_FAKE:
86 return "fake"; 88 return "fake";
87 } 89 }
88 90
89 NOTREACHED(); 91 NOTREACHED();
90 return "unknown"; 92 return "unknown";
91 } 93 }
92 94
95 bool IsIncognito(int render_process_id) {
ddorwin 2017/04/13 16:52:59 The function name is different from the method it
96 content::RenderProcessHost* render_process_host =
97 content::RenderProcessHost::FromID(render_process_id);
98 DCHECK(render_process_host);
99
100 content::BrowserContext* browser_context =
101 render_process_host->GetBrowserContext();
102 DCHECK(browser_context);
103
104 return browser_context->IsOffTheRecord();
105 }
106
93 const char kAudioLogStatusKey[] = "status"; 107 const char kAudioLogStatusKey[] = "status";
94 const char kAudioLogUpdateFunction[] = "media.updateAudioComponent"; 108 const char kAudioLogUpdateFunction[] = "media.updateAudioComponent";
95 109
96 } // namespace 110 } // namespace
97 111
98 namespace content { 112 namespace content {
99 113
100 class AudioLogImpl : public media::AudioLog { 114 class AudioLogImpl : public media::AudioLog {
101 public: 115 public:
102 AudioLogImpl(int owner_id, 116 AudioLogImpl(int owner_id,
(...skipping 191 matching lines...) Expand 10 before | Expand all | Expand 10 after
294 base::TimeDelta all_watch_time = media::kNoTimestamp; 308 base::TimeDelta all_watch_time = media::kNoTimestamp;
295 base::TimeDelta mse_watch_time = media::kNoTimestamp; 309 base::TimeDelta mse_watch_time = media::kNoTimestamp;
296 base::TimeDelta eme_watch_time = media::kNoTimestamp; 310 base::TimeDelta eme_watch_time = media::kNoTimestamp;
297 base::TimeDelta src_watch_time = media::kNoTimestamp; 311 base::TimeDelta src_watch_time = media::kNoTimestamp;
298 base::TimeDelta ac_watch_time = media::kNoTimestamp; 312 base::TimeDelta ac_watch_time = media::kNoTimestamp;
299 base::TimeDelta battery_watch_time = media::kNoTimestamp; 313 base::TimeDelta battery_watch_time = media::kNoTimestamp;
300 base::TimeDelta embedded_experience_watch_time = media::kNoTimestamp; 314 base::TimeDelta embedded_experience_watch_time = media::kNoTimestamp;
301 }; 315 };
302 316
303 struct PipelineInfo { 317 struct PipelineInfo {
318 explicit PipelineInfo(bool is_incognito) : is_incognito(is_incognito) {}
319
304 bool has_pipeline = false; 320 bool has_pipeline = false;
305 bool has_ever_played = false; 321 bool has_ever_played = false;
306 bool has_reached_have_enough = false; 322 bool has_reached_have_enough = false;
307 media::PipelineStatus last_pipeline_status = media::PIPELINE_OK; 323 media::PipelineStatus last_pipeline_status = media::PIPELINE_OK;
308 bool has_audio = false; 324 bool has_audio = false;
309 bool has_video = false; 325 bool has_video = false;
310 bool video_dds = false; 326 bool video_dds = false;
311 bool video_decoder_changed = false; 327 bool video_decoder_changed = false;
328 bool has_cdm = false;
329 bool is_incognito = false;
312 std::string audio_codec_name; 330 std::string audio_codec_name;
313 std::string video_codec_name; 331 std::string video_codec_name;
314 std::string video_decoder; 332 std::string video_decoder;
315 WatchTimeInfo watch_time_info; 333 WatchTimeInfo watch_time_info;
316 }; 334 };
317 335
318 // Helper function to report PipelineStatus associated with a player to UMA. 336 // Helper function to report PipelineStatus associated with a player to UMA.
319 void ReportUMAForPipelineStatus(const PipelineInfo& player_info); 337 void ReportUMAForPipelineStatus(const PipelineInfo& player_info);
320 338
321 // Helper to generate PipelineStatus UMA name for AudioVideo streams. 339 // Helper to generate PipelineStatus UMA name for AudioVideo streams.
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after
395 DISALLOW_COPY_AND_ASSIGN(MediaInternalsUMAHandler); 413 DISALLOW_COPY_AND_ASSIGN(MediaInternalsUMAHandler);
396 }; 414 };
397 415
398 MediaInternals::MediaInternalsUMAHandler::MediaInternalsUMAHandler() { 416 MediaInternals::MediaInternalsUMAHandler::MediaInternalsUMAHandler() {
399 } 417 }
400 418
401 void MediaInternals::MediaInternalsUMAHandler::SavePlayerState( 419 void MediaInternals::MediaInternalsUMAHandler::SavePlayerState(
402 int render_process_id, 420 int render_process_id,
403 const media::MediaLogEvent& event) { 421 const media::MediaLogEvent& event) {
404 DCHECK_CURRENTLY_ON(BrowserThread::UI); 422 DCHECK_CURRENTLY_ON(BrowserThread::UI);
405 PlayerInfoMap& player_info = renderer_info_[render_process_id]; 423
424 PlayerInfoMap& player_info_map = renderer_info_[render_process_id];
425
426 auto it = player_info_map.find(event.id);
427 if (it == player_info_map.end()) {
428 bool success = false;
429 std::tie(it, success) = player_info_map.emplace(
430 std::make_pair(event.id, PipelineInfo(IsIncognito(render_process_id))));
431 if (!success) {
432 LOG(ERROR) << "Failed to insert a new PipelineInfo.";
433 return;
434 }
435 }
436
437 PipelineInfo& player_info = it->second;
438
406 switch (event.type) { 439 switch (event.type) {
407 case media::MediaLogEvent::PLAY: { 440 case media::MediaLogEvent::PLAY: {
408 player_info[event.id].has_ever_played = true; 441 player_info.has_ever_played = true;
409 break; 442 break;
410 } 443 }
411 case media::MediaLogEvent::PIPELINE_STATE_CHANGED: { 444 case media::MediaLogEvent::PIPELINE_STATE_CHANGED: {
412 player_info[event.id].has_pipeline = true; 445 player_info.has_pipeline = true;
413 break; 446 break;
414 } 447 }
415 case media::MediaLogEvent::PIPELINE_ERROR: { 448 case media::MediaLogEvent::PIPELINE_ERROR: {
416 int status; 449 int status;
417 event.params.GetInteger("pipeline_error", &status); 450 event.params.GetInteger("pipeline_error", &status);
418 player_info[event.id].last_pipeline_status = 451 player_info.last_pipeline_status =
419 static_cast<media::PipelineStatus>(status); 452 static_cast<media::PipelineStatus>(status);
420 break; 453 break;
421 } 454 }
422 case media::MediaLogEvent::PROPERTY_CHANGE: 455 case media::MediaLogEvent::PROPERTY_CHANGE:
423 if (event.params.HasKey("found_audio_stream")) { 456 if (event.params.HasKey("found_audio_stream")) {
424 event.params.GetBoolean("found_audio_stream", 457 event.params.GetBoolean("found_audio_stream", &player_info.has_audio);
425 &player_info[event.id].has_audio);
426 } 458 }
427 if (event.params.HasKey("found_video_stream")) { 459 if (event.params.HasKey("found_video_stream")) {
428 event.params.GetBoolean("found_video_stream", 460 event.params.GetBoolean("found_video_stream", &player_info.has_video);
429 &player_info[event.id].has_video);
430 } 461 }
431 if (event.params.HasKey("audio_codec_name")) { 462 if (event.params.HasKey("audio_codec_name")) {
432 event.params.GetString("audio_codec_name", 463 event.params.GetString("audio_codec_name",
433 &player_info[event.id].audio_codec_name); 464 &player_info.audio_codec_name);
434 } 465 }
435 if (event.params.HasKey("video_codec_name")) { 466 if (event.params.HasKey("video_codec_name")) {
436 event.params.GetString("video_codec_name", 467 event.params.GetString("video_codec_name",
437 &player_info[event.id].video_codec_name); 468 &player_info.video_codec_name);
438 } 469 }
439 if (event.params.HasKey("video_decoder")) { 470 if (event.params.HasKey("video_decoder")) {
440 std::string previous_video_decoder(player_info[event.id].video_decoder); 471 std::string previous_video_decoder(player_info.video_decoder);
441 event.params.GetString("video_decoder", 472 event.params.GetString("video_decoder", &player_info.video_decoder);
442 &player_info[event.id].video_decoder);
443 if (!previous_video_decoder.empty() && 473 if (!previous_video_decoder.empty() &&
444 previous_video_decoder != player_info[event.id].video_decoder) { 474 previous_video_decoder != player_info.video_decoder) {
445 player_info[event.id].video_decoder_changed = true; 475 player_info.video_decoder_changed = true;
446 } 476 }
447 } 477 }
448 if (event.params.HasKey("video_dds")) { 478 if (event.params.HasKey("video_dds")) {
449 event.params.GetBoolean("video_dds", &player_info[event.id].video_dds); 479 event.params.GetBoolean("video_dds", &player_info.video_dds);
480 }
481 if (event.params.HasKey("has_cdm")) {
482 event.params.GetBoolean("has_cdm", &player_info.has_cdm);
450 } 483 }
451 if (event.params.HasKey("pipeline_buffering_state")) { 484 if (event.params.HasKey("pipeline_buffering_state")) {
452 std::string buffering_state; 485 std::string buffering_state;
453 event.params.GetString("pipeline_buffering_state", &buffering_state); 486 event.params.GetString("pipeline_buffering_state", &buffering_state);
454 if (buffering_state == "BUFFERING_HAVE_ENOUGH") 487 if (buffering_state == "BUFFERING_HAVE_ENOUGH")
455 player_info[event.id].has_reached_have_enough = true; 488 player_info.has_reached_have_enough = true;
456 } 489 }
457 break; 490 break;
458 case media::MediaLogEvent::Type::WATCH_TIME_UPDATE: { 491 case media::MediaLogEvent::Type::WATCH_TIME_UPDATE: {
459 DVLOG(2) << "Processing watch time update."; 492 DVLOG(2) << "Processing watch time update.";
460 PipelineInfo& info = player_info[event.id]; 493 WatchTimeInfo& wti = player_info.watch_time_info;
461 WatchTimeInfo& wti = info.watch_time_info;
462 // Save audio only watch time information. 494 // Save audio only watch time information.
463 MaybeSaveWatchTime(event, media::MediaLog::kWatchTimeAudioAll, 495 MaybeSaveWatchTime(event, media::MediaLog::kWatchTimeAudioAll,
464 &wti.all_watch_time); 496 &wti.all_watch_time);
465 MaybeSaveWatchTime(event, media::MediaLog::kWatchTimeAudioMse, 497 MaybeSaveWatchTime(event, media::MediaLog::kWatchTimeAudioMse,
466 &wti.mse_watch_time); 498 &wti.mse_watch_time);
467 MaybeSaveWatchTime(event, media::MediaLog::kWatchTimeAudioEme, 499 MaybeSaveWatchTime(event, media::MediaLog::kWatchTimeAudioEme,
468 &wti.eme_watch_time); 500 &wti.eme_watch_time);
469 MaybeSaveWatchTime(event, media::MediaLog::kWatchTimeAudioSrc, 501 MaybeSaveWatchTime(event, media::MediaLog::kWatchTimeAudioSrc,
470 &wti.src_watch_time); 502 &wti.src_watch_time);
471 MaybeSaveWatchTime(event, media::MediaLog::kWatchTimeAudioBattery, 503 MaybeSaveWatchTime(event, media::MediaLog::kWatchTimeAudioBattery,
(...skipping 19 matching lines...) Expand all
491 &wti.ac_watch_time); 523 &wti.ac_watch_time);
492 MaybeSaveWatchTime( 524 MaybeSaveWatchTime(
493 event, media::MediaLog::kWatchTimeAudioVideoEmbeddedExperience, 525 event, media::MediaLog::kWatchTimeAudioVideoEmbeddedExperience,
494 &wti.embedded_experience_watch_time); 526 &wti.embedded_experience_watch_time);
495 527
496 if (event.params.HasKey(media::MediaLog::kWatchTimeFinalize)) { 528 if (event.params.HasKey(media::MediaLog::kWatchTimeFinalize)) {
497 bool should_finalize; 529 bool should_finalize;
498 DCHECK(event.params.GetBoolean(media::MediaLog::kWatchTimeFinalize, 530 DCHECK(event.params.GetBoolean(media::MediaLog::kWatchTimeFinalize,
499 &should_finalize) && 531 &should_finalize) &&
500 should_finalize); 532 should_finalize);
501 FinalizeWatchTime(info.has_video, &wti, FinalizeType::EVERYTHING); 533 FinalizeWatchTime(player_info.has_video, &wti,
534 FinalizeType::EVERYTHING);
502 } else if (event.params.HasKey( 535 } else if (event.params.HasKey(
503 media::MediaLog::kWatchTimeFinalizePower)) { 536 media::MediaLog::kWatchTimeFinalizePower)) {
504 bool should_finalize; 537 bool should_finalize;
505 DCHECK(event.params.GetBoolean(media::MediaLog::kWatchTimeFinalizePower, 538 DCHECK(event.params.GetBoolean(media::MediaLog::kWatchTimeFinalizePower,
506 &should_finalize) && 539 &should_finalize) &&
507 should_finalize); 540 should_finalize);
508 FinalizeWatchTime(info.has_video, &wti, FinalizeType::POWER_ONLY); 541 FinalizeWatchTime(player_info.has_video, &wti,
542 FinalizeType::POWER_ONLY);
509 } 543 }
510 break; 544 break;
511 } 545 }
512 case media::MediaLogEvent::Type::WEBMEDIAPLAYER_DESTROYED: { 546 case media::MediaLogEvent::Type::WEBMEDIAPLAYER_DESTROYED: {
513 // Upon player destruction report UMA data; if the player is not torn down 547 // Upon player destruction report UMA data; if the player is not torn down
514 // before process exit, it will be logged during OnProcessTerminated(). 548 // before process exit, it will be logged during OnProcessTerminated().
515 auto it = player_info.find(event.id); 549 auto it = player_info_map.find(event.id);
516 if (it == player_info.end()) 550 if (it == player_info_map.end())
517 break; 551 break;
518 552
519 ReportUMAForPipelineStatus(it->second); 553 ReportUMAForPipelineStatus(it->second);
520 player_info.erase(it); 554 player_info_map.erase(it);
521 } 555 }
522 default: 556 default:
523 break; 557 break;
524 } 558 }
525 return; 559 return;
526 } 560 }
527 561
528 std::string MediaInternals::MediaInternalsUMAHandler::GetUMANameForAVStream( 562 std::string MediaInternals::MediaInternalsUMAHandler::GetUMANameForAVStream(
529 const PipelineInfo& player_info) { 563 const PipelineInfo& player_info) {
530 DCHECK_CURRENTLY_ON(BrowserThread::UI); 564 DCHECK_CURRENTLY_ON(BrowserThread::UI);
(...skipping 21 matching lines...) Expand all
552 } 586 }
553 587
554 if (player_info.video_decoder == media::GpuVideoDecoder::kDecoderName) { 588 if (player_info.video_decoder == media::GpuVideoDecoder::kDecoderName) {
555 uma_name += "HW"; 589 uma_name += "HW";
556 } else { 590 } else {
557 uma_name += "SW"; 591 uma_name += "SW";
558 } 592 }
559 return uma_name; 593 return uma_name;
560 } 594 }
561 595
562 void MediaInternals::MediaInternalsUMAHandler::ReportUMAForPipelineStatus( 596 void MediaInternals::MediaInternalsUMAHandler::ReportUMAForPipelineStatus(
ddorwin 2017/04/13 16:52:59 This function name does not make it clear that it
xhwang 2017/04/13 22:36:34 Added a TODO.
563 const PipelineInfo& player_info) { 597 const PipelineInfo& player_info) {
564 DCHECK_CURRENTLY_ON(BrowserThread::UI); 598 DCHECK_CURRENTLY_ON(BrowserThread::UI);
565 599
566 // Don't log pipeline status for players which don't actually have a pipeline; 600 // Don't log pipeline status for players which don't actually have a pipeline;
567 // e.g., the Android MediaSourcePlayer implementation. 601 // e.g., the Android MediaSourcePlayer implementation.
568 if (!player_info.has_pipeline) 602 if (!player_info.has_pipeline)
569 return; 603 return;
570 604
571 if (player_info.has_video && player_info.has_audio) { 605 if (player_info.has_video && player_info.has_audio) {
572 base::LinearHistogram::FactoryGet( 606 base::LinearHistogram::FactoryGet(
(...skipping 19 matching lines...) Expand all
592 } 626 }
593 // Report whether video decoder fallback happened, but only if a video decoder 627 // Report whether video decoder fallback happened, but only if a video decoder
594 // was reported. 628 // was reported.
595 if (!player_info.video_decoder.empty()) { 629 if (!player_info.video_decoder.empty()) {
596 UMA_HISTOGRAM_BOOLEAN("Media.VideoDecoderFallback", 630 UMA_HISTOGRAM_BOOLEAN("Media.VideoDecoderFallback",
597 player_info.video_decoder_changed); 631 player_info.video_decoder_changed);
598 } 632 }
599 633
600 // Report whether this player ever saw a playback event. Used to measure the 634 // Report whether this player ever saw a playback event. Used to measure the
601 // effectiveness of efforts to reduce loaded-but-never-used players. 635 // effectiveness of efforts to reduce loaded-but-never-used players.
602 if (player_info.has_reached_have_enough) 636 if (player_info.has_reached_have_enough) {
603 UMA_HISTOGRAM_BOOLEAN("Media.HasEverPlayed", player_info.has_ever_played); 637 UMA_HISTOGRAM_BOOLEAN("Media.HasEverPlayed", player_info.has_ever_played);
638 }
639
640 // Report whether an encrypted playback is in incognito window, excluding
ddorwin 2017/04/13 16:52:59 Once we have data, we should compare the `false` n
xhwang 2017/04/13 22:36:34 Acknowledged.
641 // loaded-but-never-used players.
642 if (player_info.has_cdm && player_info.has_reached_have_enough)
DaleCurtis 2017/04/12 21:38:19 Needs && player_info.has_ever_played.
xhwang 2017/04/13 22:36:34 Done.
643 UMA_HISTOGRAM_BOOLEAN("Media.EME.IsIncognito", player_info.is_incognito);
604 } 644 }
605 645
606 void MediaInternals::MediaInternalsUMAHandler::OnProcessTerminated( 646 void MediaInternals::MediaInternalsUMAHandler::OnProcessTerminated(
607 int render_process_id) { 647 int render_process_id) {
608 DCHECK_CURRENTLY_ON(BrowserThread::UI); 648 DCHECK_CURRENTLY_ON(BrowserThread::UI);
609 649
610 auto players_it = renderer_info_.find(render_process_id); 650 auto players_it = renderer_info_.find(render_process_id);
611 if (players_it == renderer_info_.end()) 651 if (players_it == renderer_info_.end())
612 return; 652 return;
613 auto it = players_it->second.begin(); 653 auto it = players_it->second.begin();
(...skipping 258 matching lines...) Expand 10 before | Expand all | Expand 10 after
872 audio_streams_cached_data_.GetDictionary(cache_key, &existing_dict)); 912 audio_streams_cached_data_.GetDictionary(cache_key, &existing_dict));
873 existing_dict->MergeDictionary(value); 913 existing_dict->MergeDictionary(value);
874 } 914 }
875 } 915 }
876 916
877 if (CanUpdate()) 917 if (CanUpdate())
878 SendUpdate(SerializeUpdate(function, value)); 918 SendUpdate(SerializeUpdate(function, value));
879 } 919 }
880 920
881 } // namespace content 921 } // namespace content
OLDNEW
« no previous file with comments | « no previous file | media/blink/webmediaplayer_impl.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698