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

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: Comments. 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.h » ('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 <utility> 10 #include <utility>
(...skipping 271 matching lines...) Expand 10 before | Expand all | Expand 10 after
282 // Called when a render process is terminated. Reports the pipeline status to 282 // 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 283 // UMA for every player associated with the renderer process and then deletes
284 // the player state. 284 // the player state.
285 void OnProcessTerminated(int render_process_id); 285 void OnProcessTerminated(int render_process_id);
286 286
287 // Helper function to save the event payload to RendererPlayerMap. 287 // Helper function to save the event payload to RendererPlayerMap.
288 void SavePlayerState(int render_process_id, 288 void SavePlayerState(int render_process_id,
289 const media::MediaLogEvent& event); 289 const media::MediaLogEvent& event);
290 290
291 private: 291 private:
292 struct WatchTimeInfo {
293 base::TimeDelta all_watch_time = media::kNoTimestamp;
294 base::TimeDelta mse_watch_time = media::kNoTimestamp;
295 base::TimeDelta eme_watch_time = media::kNoTimestamp;
296 base::TimeDelta src_watch_time = media::kNoTimestamp;
297 base::TimeDelta ac_watch_time = media::kNoTimestamp;
298 base::TimeDelta battery_watch_time = media::kNoTimestamp;
299 };
300
292 struct PipelineInfo { 301 struct PipelineInfo {
293 bool has_pipeline = false; 302 bool has_pipeline = false;
294 media::PipelineStatus last_pipeline_status = media::PIPELINE_OK; 303 media::PipelineStatus last_pipeline_status = media::PIPELINE_OK;
295 bool has_audio = false; 304 bool has_audio = false;
296 bool has_video = false; 305 bool has_video = false;
297 bool video_dds = false; 306 bool video_dds = false;
298 bool video_decoder_changed = false; 307 bool video_decoder_changed = false;
299 std::string audio_codec_name; 308 std::string audio_codec_name;
300 std::string video_codec_name; 309 std::string video_codec_name;
301 std::string video_decoder; 310 std::string video_decoder;
311 WatchTimeInfo watch_time_info;
302 }; 312 };
303 313
304 // Helper function to report PipelineStatus associated with a player to UMA. 314 // Helper function to report PipelineStatus associated with a player to UMA.
305 void ReportUMAForPipelineStatus(const PipelineInfo& player_info); 315 void ReportUMAForPipelineStatus(const PipelineInfo& player_info);
306 316
307 // Helper to generate PipelineStatus UMA name for AudioVideo streams. 317 // Helper to generate PipelineStatus UMA name for AudioVideo streams.
308 std::string GetUMANameForAVStream(const PipelineInfo& player_info); 318 std::string GetUMANameForAVStream(const PipelineInfo& player_info);
309 319
320 // Saves the watch time info from |event| under |key| at |watch_time| if |key|
321 // is present in |event.params|.
322 void MaybeSaveWatchTime(const media::MediaLogEvent& event,
323 const char* key,
324 base::TimeDelta* watch_time) {
325 if (!event.params.HasKey(key))
326 return;
327
328 double in_seconds;
329 const bool result =
330 event.params.GetDoubleWithoutPathExpansion(key, &in_seconds);
331 DCHECK(result);
332 *watch_time = base::TimeDelta::FromSecondsD(in_seconds);
333
334 DVLOG(2) << "Saved watch time for " << key << " of " << *watch_time;
335 }
336
337 enum class FinalizeType { EVERYTHING, POWER_ONLY };
338 void FinalizeWatchTime(WatchTimeInfo* watch_time_info,
339 FinalizeType finalize_type) {
340 // Use a macro instead of a function so we can use the histogram macro (which
341 // checks that the uma name is a static value). We use a custom time range for
342 // the histogram macro to capitalize on common expected watch times.
343 #define MAYBE_RECORD_WATCH_TIME(uma_name, watch_time) \
344 if (watch_time_info->watch_time != media::kNoTimestamp) { \
345 UMA_HISTOGRAM_CUSTOM_TIMES( \
346 media::MediaLog::uma_name, watch_time_info->watch_time, \
347 base::TimeDelta::FromSeconds(7), base::TimeDelta::FromHours(10), 50); \
348 watch_time_info->watch_time = media::kNoTimestamp; \
349 }
350
351 if (finalize_type == FinalizeType::EVERYTHING) {
352 MAYBE_RECORD_WATCH_TIME(kWatchTimeAudioVideoAll, all_watch_time);
353 MAYBE_RECORD_WATCH_TIME(kWatchTimeAudioVideoMse, mse_watch_time);
354 MAYBE_RECORD_WATCH_TIME(kWatchTimeAudioVideoEme, eme_watch_time);
355 MAYBE_RECORD_WATCH_TIME(kWatchTimeAudioVideoSrc, src_watch_time);
356 } else {
357 DCHECK_EQ(finalize_type, FinalizeType::POWER_ONLY);
358 }
359 MAYBE_RECORD_WATCH_TIME(kWatchTimeAudioVideoBattery, battery_watch_time);
360 MAYBE_RECORD_WATCH_TIME(kWatchTimeAudioVideoAc, ac_watch_time);
361 #undef MAYBE_RECORD_WATCH_TIME
362 }
363
310 // Key is player id. 364 // Key is player id.
311 typedef std::map<int, PipelineInfo> PlayerInfoMap; 365 typedef std::map<int, PipelineInfo> PlayerInfoMap;
312 366
313 // Key is renderer id. 367 // Key is renderer id.
314 typedef std::map<int, PlayerInfoMap> RendererPlayerMap; 368 typedef std::map<int, PlayerInfoMap> RendererPlayerMap;
315 369
316 // Stores player information per renderer. 370 // Stores player information per renderer.
317 RendererPlayerMap renderer_info_; 371 RendererPlayerMap renderer_info_;
318 372
319 DISALLOW_COPY_AND_ASSIGN(MediaInternalsUMAHandler); 373 DISALLOW_COPY_AND_ASSIGN(MediaInternalsUMAHandler);
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
362 &player_info[event.id].video_decoder); 416 &player_info[event.id].video_decoder);
363 if (!previous_video_decoder.empty() && 417 if (!previous_video_decoder.empty() &&
364 previous_video_decoder != player_info[event.id].video_decoder) { 418 previous_video_decoder != player_info[event.id].video_decoder) {
365 player_info[event.id].video_decoder_changed = true; 419 player_info[event.id].video_decoder_changed = true;
366 } 420 }
367 } 421 }
368 if (event.params.HasKey("video_dds")) { 422 if (event.params.HasKey("video_dds")) {
369 event.params.GetBoolean("video_dds", &player_info[event.id].video_dds); 423 event.params.GetBoolean("video_dds", &player_info[event.id].video_dds);
370 } 424 }
371 break; 425 break;
426 case media::MediaLogEvent::Type::WATCH_TIME_UPDATE: {
427 DVLOG(2) << "Processing watch time update.";
428 WatchTimeInfo& wti = player_info[event.id].watch_time_info;
429 MaybeSaveWatchTime(event, media::MediaLog::kWatchTimeAudioVideoAll,
430 &wti.all_watch_time);
431 MaybeSaveWatchTime(event, media::MediaLog::kWatchTimeAudioVideoMse,
432 &wti.mse_watch_time);
433 MaybeSaveWatchTime(event, media::MediaLog::kWatchTimeAudioVideoEme,
434 &wti.eme_watch_time);
435 MaybeSaveWatchTime(event, media::MediaLog::kWatchTimeAudioVideoSrc,
436 &wti.src_watch_time);
437 MaybeSaveWatchTime(event, media::MediaLog::kWatchTimeAudioVideoBattery,
438 &wti.battery_watch_time);
439 MaybeSaveWatchTime(event, media::MediaLog::kWatchTimeAudioVideoAc,
440 &wti.ac_watch_time);
441
442 if (event.params.HasKey(media::MediaLog::kWatchTimeFinalize)) {
443 bool should_finalize;
444 DCHECK(event.params.GetBoolean(media::MediaLog::kWatchTimeFinalize,
445 &should_finalize) &&
446 should_finalize);
447 FinalizeWatchTime(&wti, FinalizeType::EVERYTHING);
448 } else if (event.params.HasKey(
449 media::MediaLog::kWatchTimeFinalizePower)) {
450 bool should_finalize;
451 DCHECK(event.params.GetBoolean(media::MediaLog::kWatchTimeFinalizePower,
452 &should_finalize) &&
453 should_finalize);
454 FinalizeWatchTime(&wti, FinalizeType::POWER_ONLY);
455 }
456 break;
457 }
458 case media::MediaLogEvent::Type::WEBMEDIAPLAYER_DESTROYED: {
459 // Upon player destruction report UMA data; if the player is not torn down
460 // before process exit, it will be logged during OnProcessTerminated().
461 auto it = player_info.find(event.id);
462 if (it == player_info.end())
463 break;
464
465 ReportUMAForPipelineStatus(it->second);
466 player_info.erase(it);
467 }
372 default: 468 default:
373 break; 469 break;
374 } 470 }
375 return; 471 return;
376 } 472 }
377 473
378 std::string MediaInternals::MediaInternalsUMAHandler::GetUMANameForAVStream( 474 std::string MediaInternals::MediaInternalsUMAHandler::GetUMANameForAVStream(
379 const PipelineInfo& player_info) { 475 const PipelineInfo& player_info) {
380 DCHECK_CURRENTLY_ON(BrowserThread::UI); 476 DCHECK_CURRENTLY_ON(BrowserThread::UI);
381 static const char kPipelineUmaPrefix[] = "Media.PipelineStatus.AudioVideo."; 477 static const char kPipelineUmaPrefix[] = "Media.PipelineStatus.AudioVideo.";
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after
451 void MediaInternals::MediaInternalsUMAHandler::OnProcessTerminated( 547 void MediaInternals::MediaInternalsUMAHandler::OnProcessTerminated(
452 int render_process_id) { 548 int render_process_id) {
453 DCHECK_CURRENTLY_ON(BrowserThread::UI); 549 DCHECK_CURRENTLY_ON(BrowserThread::UI);
454 550
455 auto players_it = renderer_info_.find(render_process_id); 551 auto players_it = renderer_info_.find(render_process_id);
456 if (players_it == renderer_info_.end()) 552 if (players_it == renderer_info_.end())
457 return; 553 return;
458 auto it = players_it->second.begin(); 554 auto it = players_it->second.begin();
459 while (it != players_it->second.end()) { 555 while (it != players_it->second.end()) {
460 ReportUMAForPipelineStatus(it->second); 556 ReportUMAForPipelineStatus(it->second);
557 FinalizeWatchTime(&(it->second.watch_time_info), FinalizeType::EVERYTHING);
461 players_it->second.erase(it++); 558 players_it->second.erase(it++);
462 } 559 }
463 renderer_info_.erase(players_it); 560 renderer_info_.erase(players_it);
464 } 561 }
465 562
466 MediaInternals* MediaInternals::GetInstance() { 563 MediaInternals* MediaInternals::GetInstance() {
467 return g_media_internals.Pointer(); 564 return g_media_internals.Pointer();
468 } 565 }
469 566
470 MediaInternals::MediaInternals() 567 MediaInternals::MediaInternals()
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
522 619
523 *update = SerializeUpdate("media.onMediaEvent", &dict); 620 *update = SerializeUpdate("media.onMediaEvent", &dict);
524 return true; 621 return true;
525 } 622 }
526 623
527 void MediaInternals::OnMediaEvents( 624 void MediaInternals::OnMediaEvents(
528 int render_process_id, const std::vector<media::MediaLogEvent>& events) { 625 int render_process_id, const std::vector<media::MediaLogEvent>& events) {
529 DCHECK_CURRENTLY_ON(BrowserThread::UI); 626 DCHECK_CURRENTLY_ON(BrowserThread::UI);
530 // Notify observers that |event| has occurred. 627 // Notify observers that |event| has occurred.
531 for (const auto& event : events) { 628 for (const auto& event : events) {
532 if (CanUpdate()) { 629 // Some events should not be recorded in the UI.
533 base::string16 update; 630 if (event.type != media::MediaLogEvent::Type::WATCH_TIME_UPDATE) {
534 if (ConvertEventToUpdate(render_process_id, event, &update)) 631 if (CanUpdate()) {
535 SendUpdate(update); 632 base::string16 update;
633 if (ConvertEventToUpdate(render_process_id, event, &update))
634 SendUpdate(update);
635 }
636 SaveEvent(render_process_id, event);
536 } 637 }
537
538 SaveEvent(render_process_id, event);
539 uma_handler_->SavePlayerState(render_process_id, event); 638 uma_handler_->SavePlayerState(render_process_id, event);
540 } 639 }
541 } 640 }
542 641
543 void MediaInternals::AddUpdateCallback(const UpdateCallback& callback) { 642 void MediaInternals::AddUpdateCallback(const UpdateCallback& callback) {
544 DCHECK_CURRENTLY_ON(BrowserThread::UI); 643 DCHECK_CURRENTLY_ON(BrowserThread::UI);
545 update_callbacks_.push_back(callback); 644 update_callbacks_.push_back(callback);
546 645
547 base::AutoLock auto_lock(lock_); 646 base::AutoLock auto_lock(lock_);
548 can_update_ = true; 647 can_update_ = true;
(...skipping 163 matching lines...) Expand 10 before | Expand all | Expand 10 after
712 audio_streams_cached_data_.GetDictionary(cache_key, &existing_dict)); 811 audio_streams_cached_data_.GetDictionary(cache_key, &existing_dict));
713 existing_dict->MergeDictionary(value); 812 existing_dict->MergeDictionary(value);
714 } 813 }
715 } 814 }
716 815
717 if (CanUpdate()) 816 if (CanUpdate())
718 SendUpdate(SerializeUpdate(function, value)); 817 SendUpdate(SerializeUpdate(function, value));
719 } 818 }
720 819
721 } // namespace content 820 } // namespace content
OLDNEW
« no previous file with comments | « no previous file | media/base/media_log.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698