| OLD | NEW |
| 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 "base/metrics/histogram.h" | 7 #include "base/metrics/histogram.h" |
| 8 #include "base/strings/string16.h" | 8 #include "base/strings/string16.h" |
| 9 #include "base/strings/string_number_conversions.h" | 9 #include "base/strings/string_number_conversions.h" |
| 10 #include "base/strings/stringprintf.h" | 10 #include "base/strings/stringprintf.h" |
| (...skipping 246 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 257 void Observe(int type, | 257 void Observe(int type, |
| 258 const NotificationSource& source, | 258 const NotificationSource& source, |
| 259 const NotificationDetails& details) override; | 259 const NotificationDetails& details) override; |
| 260 | 260 |
| 261 // Reports the pipeline status to UMA for every player | 261 // Reports the pipeline status to UMA for every player |
| 262 // associated with the renderer process and then deletes the player state. | 262 // associated with the renderer process and then deletes the player state. |
| 263 void LogAndClearPlayersInRenderer(int render_process_id); | 263 void LogAndClearPlayersInRenderer(int render_process_id); |
| 264 | 264 |
| 265 // Helper function to save the event payload to RendererPlayerMap. | 265 // Helper function to save the event payload to RendererPlayerMap. |
| 266 void SavePlayerState(const media::MediaLogEvent& event, | 266 void SavePlayerState(const media::MediaLogEvent& event, |
| 267 const base::string16& event_serialized, |
| 267 int render_process_id); | 268 int render_process_id); |
| 268 | 269 |
| 270 std::vector<base::string16> GetHistoricalEvents(); |
| 271 |
| 269 private: | 272 private: |
| 270 struct PipelineInfo { | 273 struct PipelineInfo { |
| 271 media::PipelineStatus last_pipeline_status; | 274 media::PipelineStatus last_pipeline_status; |
| 272 bool has_audio; | 275 bool has_audio; |
| 273 bool has_video; | 276 bool has_video; |
| 274 bool video_dds; | 277 bool video_dds; |
| 275 bool video_decoder_changed; | 278 bool video_decoder_changed; |
| 276 std::string audio_codec_name; | 279 std::string audio_codec_name; |
| 277 std::string video_codec_name; | 280 std::string video_codec_name; |
| 278 std::string video_decoder; | 281 std::string video_decoder; |
| 282 // Remember media log events so that when a new media internals page is |
| 283 // opened they can be replayed. |
| 284 std::vector<base::string16> media_log_event_history; |
| 279 PipelineInfo() | 285 PipelineInfo() |
| 280 : last_pipeline_status(media::PIPELINE_OK), | 286 : last_pipeline_status(media::PIPELINE_OK), |
| 281 has_audio(false), | 287 has_audio(false), |
| 282 has_video(false), | 288 has_video(false), |
| 283 video_dds(false), | 289 video_dds(false), |
| 284 video_decoder_changed(false) {} | 290 video_decoder_changed(false) {} |
| 285 }; | 291 }; |
| 286 | 292 |
| 287 // Helper function to report PipelineStatus associated with a player to UMA. | 293 // Helper function to report PipelineStatus associated with a player to UMA. |
| 288 void ReportUMAForPipelineStatus(const PipelineInfo& player_info); | 294 void ReportUMAForPipelineStatus(const PipelineInfo& player_info); |
| (...skipping 25 matching lines...) Expand all Loading... |
| 314 const NotificationSource& source, | 320 const NotificationSource& source, |
| 315 const NotificationDetails& details) { | 321 const NotificationDetails& details) { |
| 316 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 322 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| 317 DCHECK_EQ(type, NOTIFICATION_RENDERER_PROCESS_TERMINATED); | 323 DCHECK_EQ(type, NOTIFICATION_RENDERER_PROCESS_TERMINATED); |
| 318 RenderProcessHost* process = Source<RenderProcessHost>(source).ptr(); | 324 RenderProcessHost* process = Source<RenderProcessHost>(source).ptr(); |
| 319 | 325 |
| 320 // Post the task to the IO thread to avoid race in updating renderer_info_ map | 326 // Post the task to the IO thread to avoid race in updating renderer_info_ map |
| 321 // by both SavePlayerState & LogAndClearPlayersInRenderer from different | 327 // by both SavePlayerState & LogAndClearPlayersInRenderer from different |
| 322 // threads. | 328 // threads. |
| 323 // Using base::Unretained() on MediaInternalsUMAHandler is safe since | 329 // Using base::Unretained() on MediaInternalsUMAHandler is safe since |
| 324 // it is owned by MediaInternals and share the same lifetime | 330 // it is owned by MediaInternals and shares the same lifetime. |
| 325 BrowserThread::PostTask( | 331 BrowserThread::PostTask( |
| 326 BrowserThread::IO, FROM_HERE, | 332 BrowserThread::IO, FROM_HERE, |
| 327 base::Bind(&MediaInternalsUMAHandler::LogAndClearPlayersInRenderer, | 333 base::Bind(&MediaInternalsUMAHandler::LogAndClearPlayersInRenderer, |
| 328 base::Unretained(this), process->GetID())); | 334 base::Unretained(this), process->GetID())); |
| 329 } | 335 } |
| 330 | 336 |
| 331 void MediaInternals::MediaInternalsUMAHandler::SavePlayerState( | 337 void MediaInternals::MediaInternalsUMAHandler::SavePlayerState( |
| 332 const media::MediaLogEvent& event, | 338 const media::MediaLogEvent& event, |
| 339 const base::string16& event_serialized, |
| 333 int render_process_id) { | 340 int render_process_id) { |
| 334 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 341 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 335 PlayerInfoMap& player_info = renderer_info_[render_process_id]; | 342 PlayerInfoMap& player_info = renderer_info_[render_process_id]; |
| 343 // This can grow unbounded.. |
| 344 player_info[event.id].media_log_event_history.push_back(event_serialized); |
| 336 switch (event.type) { | 345 switch (event.type) { |
| 337 case media::MediaLogEvent::PIPELINE_ERROR: { | 346 case media::MediaLogEvent::PIPELINE_ERROR: { |
| 338 int status; | 347 int status; |
| 339 event.params.GetInteger("pipeline_error", &status); | 348 event.params.GetInteger("pipeline_error", &status); |
| 340 player_info[event.id].last_pipeline_status = | 349 player_info[event.id].last_pipeline_status = |
| 341 static_cast<media::PipelineStatus>(status); | 350 static_cast<media::PipelineStatus>(status); |
| 342 break; | 351 break; |
| 343 } | 352 } |
| 344 case media::MediaLogEvent::PROPERTY_CHANGE: | 353 case media::MediaLogEvent::PROPERTY_CHANGE: |
| 345 if (event.params.HasKey("found_audio_stream")) { | 354 if (event.params.HasKey("found_audio_stream")) { |
| (...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 443 int render_process_id) { | 452 int render_process_id) { |
| 444 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 453 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 445 auto players_it = renderer_info_.find(render_process_id); | 454 auto players_it = renderer_info_.find(render_process_id); |
| 446 if (players_it == renderer_info_.end()) | 455 if (players_it == renderer_info_.end()) |
| 447 return; | 456 return; |
| 448 auto it = players_it->second.begin(); | 457 auto it = players_it->second.begin(); |
| 449 while (it != players_it->second.end()) { | 458 while (it != players_it->second.end()) { |
| 450 ReportUMAForPipelineStatus(it->second); | 459 ReportUMAForPipelineStatus(it->second); |
| 451 players_it->second.erase(it++); | 460 players_it->second.erase(it++); |
| 452 } | 461 } |
| 462 renderer_info_.erase(players_it); |
| 463 } |
| 464 |
| 465 std::vector<base::string16> |
| 466 MediaInternals::MediaInternalsUMAHandler::GetHistoricalEvents() { |
| 467 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 468 |
| 469 std::vector<base::string16> all_events; |
| 470 for (const auto& renderer_info_it : renderer_info_) { |
| 471 for (const auto& player_info_it : renderer_info_it.second) { |
| 472 const auto& player_events = player_info_it.second.media_log_event_history; |
| 473 all_events.insert(all_events.end(), player_events.begin(), |
| 474 player_events.end()); |
| 475 } |
| 476 } |
| 477 |
| 478 return all_events; |
| 453 } | 479 } |
| 454 | 480 |
| 455 MediaInternals* MediaInternals::GetInstance() { | 481 MediaInternals* MediaInternals::GetInstance() { |
| 456 return g_media_internals.Pointer(); | 482 return g_media_internals.Pointer(); |
| 457 } | 483 } |
| 458 | 484 |
| 459 MediaInternals::MediaInternals() | 485 MediaInternals::MediaInternals() |
| 460 : owner_ids_(), uma_handler_(new MediaInternalsUMAHandler()) { | 486 : owner_ids_(), uma_handler_(new MediaInternalsUMAHandler()) { |
| 461 } | 487 } |
| 462 | 488 |
| (...skipping 23 matching lines...) Expand all Loading... |
| 486 status > static_cast<int>(media::PIPELINE_STATUS_MAX)) { | 512 status > static_cast<int>(media::PIPELINE_STATUS_MAX)) { |
| 487 continue; | 513 continue; |
| 488 } | 514 } |
| 489 media::PipelineStatus error = static_cast<media::PipelineStatus>(status); | 515 media::PipelineStatus error = static_cast<media::PipelineStatus>(status); |
| 490 dict.SetString("params.pipeline_error", | 516 dict.SetString("params.pipeline_error", |
| 491 media::MediaLog::PipelineStatusToString(error)); | 517 media::MediaLog::PipelineStatusToString(error)); |
| 492 } else { | 518 } else { |
| 493 dict.Set("params", event->params.DeepCopy()); | 519 dict.Set("params", event->params.DeepCopy()); |
| 494 } | 520 } |
| 495 | 521 |
| 496 SendUpdate(SerializeUpdate("media.onMediaEvent", &dict)); | 522 const base::string16 update(SerializeUpdate("media.onMediaEvent", &dict)); |
| 497 uma_handler_->SavePlayerState(*event, render_process_id); | 523 SendUpdate(update); |
| 524 uma_handler_->SavePlayerState(*event, update, render_process_id); |
| 498 } | 525 } |
| 499 } | 526 } |
| 500 | 527 |
| 501 void MediaInternals::AddUpdateCallback(const UpdateCallback& callback) { | 528 void MediaInternals::AddUpdateCallback(const UpdateCallback& callback) { |
| 502 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 529 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 503 update_callbacks_.push_back(callback); | 530 update_callbacks_.push_back(callback); |
| 504 } | 531 } |
| 505 | 532 |
| 506 void MediaInternals::RemoveUpdateCallback(const UpdateCallback& callback) { | 533 void MediaInternals::RemoveUpdateCallback(const UpdateCallback& callback) { |
| 507 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 534 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 508 for (size_t i = 0; i < update_callbacks_.size(); ++i) { | 535 for (size_t i = 0; i < update_callbacks_.size(); ++i) { |
| 509 if (update_callbacks_[i].Equals(callback)) { | 536 if (update_callbacks_[i].Equals(callback)) { |
| 510 update_callbacks_.erase(update_callbacks_.begin() + i); | 537 update_callbacks_.erase(update_callbacks_.begin() + i); |
| 511 return; | 538 return; |
| 512 } | 539 } |
| 513 } | 540 } |
| 514 NOTREACHED(); | 541 NOTREACHED(); |
| 515 } | 542 } |
| 516 | 543 |
| 544 void MediaInternals::SendHistoricalMediaEvents() { |
| 545 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 546 for (const auto& event : uma_handler_->GetHistoricalEvents()) |
| 547 SendUpdate(event); |
| 548 } |
| 549 |
| 517 void MediaInternals::SendAudioStreamData() { | 550 void MediaInternals::SendAudioStreamData() { |
| 518 base::string16 audio_stream_update; | 551 base::string16 audio_stream_update; |
| 519 { | 552 { |
| 520 base::AutoLock auto_lock(lock_); | 553 base::AutoLock auto_lock(lock_); |
| 521 audio_stream_update = SerializeUpdate( | 554 audio_stream_update = SerializeUpdate( |
| 522 "media.onReceiveAudioStreamData", &audio_streams_cached_data_); | 555 "media.onReceiveAudioStreamData", &audio_streams_cached_data_); |
| 523 } | 556 } |
| 524 SendUpdate(audio_stream_update); | 557 SendUpdate(audio_stream_update); |
| 525 } | 558 } |
| 526 | 559 |
| (...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 607 CHECK( | 640 CHECK( |
| 608 audio_streams_cached_data_.GetDictionary(cache_key, &existing_dict)); | 641 audio_streams_cached_data_.GetDictionary(cache_key, &existing_dict)); |
| 609 existing_dict->MergeDictionary(value); | 642 existing_dict->MergeDictionary(value); |
| 610 } | 643 } |
| 611 } | 644 } |
| 612 | 645 |
| 613 SendUpdate(SerializeUpdate(function, value)); | 646 SendUpdate(SerializeUpdate(function, value)); |
| 614 } | 647 } |
| 615 | 648 |
| 616 } // namespace content | 649 } // namespace content |
| OLD | NEW |