| 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 241 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 252 | 252 |
| 253 MediaInternals::MediaInternalsUMAHandler::MediaInternalsUMAHandler() { | 253 MediaInternals::MediaInternalsUMAHandler::MediaInternalsUMAHandler() { |
| 254 registrar_.Add(this, NOTIFICATION_RENDERER_PROCESS_TERMINATED, | 254 registrar_.Add(this, NOTIFICATION_RENDERER_PROCESS_TERMINATED, |
| 255 NotificationService::AllBrowserContextsAndSources()); | 255 NotificationService::AllBrowserContextsAndSources()); |
| 256 } | 256 } |
| 257 | 257 |
| 258 void MediaInternals::MediaInternalsUMAHandler::Observe( | 258 void MediaInternals::MediaInternalsUMAHandler::Observe( |
| 259 int type, | 259 int type, |
| 260 const NotificationSource& source, | 260 const NotificationSource& source, |
| 261 const NotificationDetails& details) { | 261 const NotificationDetails& details) { |
| 262 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 262 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| 263 DCHECK_EQ(type, NOTIFICATION_RENDERER_PROCESS_TERMINATED); | 263 DCHECK_EQ(type, NOTIFICATION_RENDERER_PROCESS_TERMINATED); |
| 264 RenderProcessHost* process = Source<RenderProcessHost>(source).ptr(); | 264 RenderProcessHost* process = Source<RenderProcessHost>(source).ptr(); |
| 265 | 265 |
| 266 // Post the task to the IO thread to avoid race in updating renderer_info_ map | 266 // Post the task to the IO thread to avoid race in updating renderer_info_ map |
| 267 // by both SavePlayerState & LogAndClearPlayersInRenderer from different | 267 // by both SavePlayerState & LogAndClearPlayersInRenderer from different |
| 268 // threads. | 268 // threads. |
| 269 // Using base::Unretained() on MediaInternalsUMAHandler is safe since | 269 // Using base::Unretained() on MediaInternalsUMAHandler is safe since |
| 270 // it is owned by MediaInternals and share the same lifetime | 270 // it is owned by MediaInternals and share the same lifetime |
| 271 BrowserThread::PostTask( | 271 BrowserThread::PostTask( |
| 272 BrowserThread::IO, FROM_HERE, | 272 BrowserThread::IO, FROM_HERE, |
| 273 base::Bind(&MediaInternalsUMAHandler::LogAndClearPlayersInRenderer, | 273 base::Bind(&MediaInternalsUMAHandler::LogAndClearPlayersInRenderer, |
| 274 base::Unretained(this), process->GetID())); | 274 base::Unretained(this), process->GetID())); |
| 275 } | 275 } |
| 276 | 276 |
| 277 void MediaInternals::MediaInternalsUMAHandler::SavePlayerState( | 277 void MediaInternals::MediaInternalsUMAHandler::SavePlayerState( |
| 278 const media::MediaLogEvent& event, | 278 const media::MediaLogEvent& event, |
| 279 int render_process_id) { | 279 int render_process_id) { |
| 280 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 280 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 281 PlayerInfoMap& player_info = renderer_info_[render_process_id]; | 281 PlayerInfoMap& player_info = renderer_info_[render_process_id]; |
| 282 switch (event.type) { | 282 switch (event.type) { |
| 283 case media::MediaLogEvent::PIPELINE_ERROR: { | 283 case media::MediaLogEvent::PIPELINE_ERROR: { |
| 284 int status; | 284 int status; |
| 285 event.params.GetInteger("pipeline_error", &status); | 285 event.params.GetInteger("pipeline_error", &status); |
| 286 player_info[event.id].last_pipeline_status = | 286 player_info[event.id].last_pipeline_status = |
| 287 static_cast<media::PipelineStatus>(status); | 287 static_cast<media::PipelineStatus>(status); |
| 288 break; | 288 break; |
| 289 } | 289 } |
| 290 case media::MediaLogEvent::PROPERTY_CHANGE: | 290 case media::MediaLogEvent::PROPERTY_CHANGE: |
| (...skipping 27 matching lines...) Expand all Loading... |
| 318 } | 318 } |
| 319 break; | 319 break; |
| 320 default: | 320 default: |
| 321 break; | 321 break; |
| 322 } | 322 } |
| 323 return; | 323 return; |
| 324 } | 324 } |
| 325 | 325 |
| 326 std::string MediaInternals::MediaInternalsUMAHandler::GetUMANameForAVStream( | 326 std::string MediaInternals::MediaInternalsUMAHandler::GetUMANameForAVStream( |
| 327 const PipelineInfo& player_info) { | 327 const PipelineInfo& player_info) { |
| 328 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 328 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 329 static const char kPipelineUmaPrefix[] = "Media.PipelineStatus.AudioVideo."; | 329 static const char kPipelineUmaPrefix[] = "Media.PipelineStatus.AudioVideo."; |
| 330 std::string uma_name = kPipelineUmaPrefix; | 330 std::string uma_name = kPipelineUmaPrefix; |
| 331 if (player_info.video_codec_name == "vp8") { | 331 if (player_info.video_codec_name == "vp8") { |
| 332 uma_name += "VP8."; | 332 uma_name += "VP8."; |
| 333 } else if (player_info.video_codec_name == "vp9") { | 333 } else if (player_info.video_codec_name == "vp9") { |
| 334 uma_name += "VP9."; | 334 uma_name += "VP9."; |
| 335 } else if (player_info.video_codec_name == "h264") { | 335 } else if (player_info.video_codec_name == "h264") { |
| 336 uma_name += "H264."; | 336 uma_name += "H264."; |
| 337 } else { | 337 } else { |
| 338 return uma_name + "Other"; | 338 return uma_name + "Other"; |
| (...skipping 11 matching lines...) Expand all Loading... |
| 350 if (player_info.video_decoder == media::GpuVideoDecoder::kDecoderName) { | 350 if (player_info.video_decoder == media::GpuVideoDecoder::kDecoderName) { |
| 351 uma_name += "HW"; | 351 uma_name += "HW"; |
| 352 } else { | 352 } else { |
| 353 uma_name += "SW"; | 353 uma_name += "SW"; |
| 354 } | 354 } |
| 355 return uma_name; | 355 return uma_name; |
| 356 } | 356 } |
| 357 | 357 |
| 358 void MediaInternals::MediaInternalsUMAHandler::ReportUMAForPipelineStatus( | 358 void MediaInternals::MediaInternalsUMAHandler::ReportUMAForPipelineStatus( |
| 359 const PipelineInfo& player_info) { | 359 const PipelineInfo& player_info) { |
| 360 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 360 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 361 if (player_info.has_video && player_info.has_audio) { | 361 if (player_info.has_video && player_info.has_audio) { |
| 362 base::LinearHistogram::FactoryGet( | 362 base::LinearHistogram::FactoryGet( |
| 363 GetUMANameForAVStream(player_info), 1, media::PIPELINE_STATUS_MAX, | 363 GetUMANameForAVStream(player_info), 1, media::PIPELINE_STATUS_MAX, |
| 364 media::PIPELINE_STATUS_MAX + 1, | 364 media::PIPELINE_STATUS_MAX + 1, |
| 365 base::HistogramBase::kUmaTargetedHistogramFlag) | 365 base::HistogramBase::kUmaTargetedHistogramFlag) |
| 366 ->Add(player_info.last_pipeline_status); | 366 ->Add(player_info.last_pipeline_status); |
| 367 } else if (player_info.has_audio) { | 367 } else if (player_info.has_audio) { |
| 368 UMA_HISTOGRAM_ENUMERATION("Media.PipelineStatus.AudioOnly", | 368 UMA_HISTOGRAM_ENUMERATION("Media.PipelineStatus.AudioOnly", |
| 369 player_info.last_pipeline_status, | 369 player_info.last_pipeline_status, |
| 370 media::PIPELINE_STATUS_MAX + 1); | 370 media::PIPELINE_STATUS_MAX + 1); |
| 371 } else if (player_info.has_video) { | 371 } else if (player_info.has_video) { |
| 372 UMA_HISTOGRAM_ENUMERATION("Media.PipelineStatus.VideoOnly", | 372 UMA_HISTOGRAM_ENUMERATION("Media.PipelineStatus.VideoOnly", |
| 373 player_info.last_pipeline_status, | 373 player_info.last_pipeline_status, |
| 374 media::PIPELINE_STATUS_MAX + 1); | 374 media::PIPELINE_STATUS_MAX + 1); |
| 375 } else { | 375 } else { |
| 376 UMA_HISTOGRAM_ENUMERATION("Media.PipelineStatus.Unsupported", | 376 UMA_HISTOGRAM_ENUMERATION("Media.PipelineStatus.Unsupported", |
| 377 player_info.last_pipeline_status, | 377 player_info.last_pipeline_status, |
| 378 media::PIPELINE_STATUS_MAX + 1); | 378 media::PIPELINE_STATUS_MAX + 1); |
| 379 } | 379 } |
| 380 // Report whether video decoder fallback happened, but only if a video decoder | 380 // Report whether video decoder fallback happened, but only if a video decoder |
| 381 // was reported. | 381 // was reported. |
| 382 if (!player_info.video_decoder.empty()) { | 382 if (!player_info.video_decoder.empty()) { |
| 383 UMA_HISTOGRAM_BOOLEAN("Media.VideoDecoderFallback", | 383 UMA_HISTOGRAM_BOOLEAN("Media.VideoDecoderFallback", |
| 384 player_info.video_decoder_changed); | 384 player_info.video_decoder_changed); |
| 385 } | 385 } |
| 386 } | 386 } |
| 387 | 387 |
| 388 void MediaInternals::MediaInternalsUMAHandler::LogAndClearPlayersInRenderer( | 388 void MediaInternals::MediaInternalsUMAHandler::LogAndClearPlayersInRenderer( |
| 389 int render_process_id) { | 389 int render_process_id) { |
| 390 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 390 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 391 auto players_it = renderer_info_.find(render_process_id); | 391 auto players_it = renderer_info_.find(render_process_id); |
| 392 if (players_it == renderer_info_.end()) | 392 if (players_it == renderer_info_.end()) |
| 393 return; | 393 return; |
| 394 auto it = players_it->second.begin(); | 394 auto it = players_it->second.begin(); |
| 395 while (it != players_it->second.end()) { | 395 while (it != players_it->second.end()) { |
| 396 ReportUMAForPipelineStatus(it->second); | 396 ReportUMAForPipelineStatus(it->second); |
| 397 players_it->second.erase(it++); | 397 players_it->second.erase(it++); |
| 398 } | 398 } |
| 399 } | 399 } |
| 400 | 400 |
| 401 MediaInternals* MediaInternals::GetInstance() { | 401 MediaInternals* MediaInternals::GetInstance() { |
| 402 return g_media_internals.Pointer(); | 402 return g_media_internals.Pointer(); |
| 403 } | 403 } |
| 404 | 404 |
| 405 MediaInternals::MediaInternals() | 405 MediaInternals::MediaInternals() |
| 406 : owner_ids_(), uma_handler_(new MediaInternalsUMAHandler()) { | 406 : owner_ids_(), uma_handler_(new MediaInternalsUMAHandler()) { |
| 407 } | 407 } |
| 408 | 408 |
| 409 MediaInternals::~MediaInternals() {} | 409 MediaInternals::~MediaInternals() {} |
| 410 | 410 |
| 411 void MediaInternals::OnMediaEvents( | 411 void MediaInternals::OnMediaEvents( |
| 412 int render_process_id, const std::vector<media::MediaLogEvent>& events) { | 412 int render_process_id, const std::vector<media::MediaLogEvent>& events) { |
| 413 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 413 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 414 // Notify observers that |event| has occurred. | 414 // Notify observers that |event| has occurred. |
| 415 for (auto event = events.begin(); event != events.end(); ++event) { | 415 for (auto event = events.begin(); event != events.end(); ++event) { |
| 416 base::DictionaryValue dict; | 416 base::DictionaryValue dict; |
| 417 dict.SetInteger("renderer", render_process_id); | 417 dict.SetInteger("renderer", render_process_id); |
| 418 dict.SetInteger("player", event->id); | 418 dict.SetInteger("player", event->id); |
| 419 dict.SetString("type", media::MediaLog::EventTypeToString(event->type)); | 419 dict.SetString("type", media::MediaLog::EventTypeToString(event->type)); |
| 420 | 420 |
| 421 // TODO(dalecurtis): This is technically not correct. TimeTicks "can't" be | 421 // TODO(dalecurtis): This is technically not correct. TimeTicks "can't" be |
| 422 // converted to to a human readable time format. See base/time/time.h. | 422 // converted to to a human readable time format. See base/time/time.h. |
| 423 const double ticks = event->time.ToInternalValue(); | 423 const double ticks = event->time.ToInternalValue(); |
| (...skipping 10 matching lines...) Expand all Loading... |
| 434 } else { | 434 } else { |
| 435 dict.Set("params", event->params.DeepCopy()); | 435 dict.Set("params", event->params.DeepCopy()); |
| 436 } | 436 } |
| 437 | 437 |
| 438 SendUpdate(SerializeUpdate("media.onMediaEvent", &dict)); | 438 SendUpdate(SerializeUpdate("media.onMediaEvent", &dict)); |
| 439 uma_handler_->SavePlayerState(*event, render_process_id); | 439 uma_handler_->SavePlayerState(*event, render_process_id); |
| 440 } | 440 } |
| 441 } | 441 } |
| 442 | 442 |
| 443 void MediaInternals::AddUpdateCallback(const UpdateCallback& callback) { | 443 void MediaInternals::AddUpdateCallback(const UpdateCallback& callback) { |
| 444 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 444 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 445 update_callbacks_.push_back(callback); | 445 update_callbacks_.push_back(callback); |
| 446 } | 446 } |
| 447 | 447 |
| 448 void MediaInternals::RemoveUpdateCallback(const UpdateCallback& callback) { | 448 void MediaInternals::RemoveUpdateCallback(const UpdateCallback& callback) { |
| 449 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 449 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 450 for (size_t i = 0; i < update_callbacks_.size(); ++i) { | 450 for (size_t i = 0; i < update_callbacks_.size(); ++i) { |
| 451 if (update_callbacks_[i].Equals(callback)) { | 451 if (update_callbacks_[i].Equals(callback)) { |
| 452 update_callbacks_.erase(update_callbacks_.begin() + i); | 452 update_callbacks_.erase(update_callbacks_.begin() + i); |
| 453 return; | 453 return; |
| 454 } | 454 } |
| 455 } | 455 } |
| 456 NOTREACHED(); | 456 NOTREACHED(); |
| 457 } | 457 } |
| 458 | 458 |
| 459 void MediaInternals::SendAudioStreamData() { | 459 void MediaInternals::SendAudioStreamData() { |
| 460 base::string16 audio_stream_update; | 460 base::string16 audio_stream_update; |
| 461 { | 461 { |
| 462 base::AutoLock auto_lock(lock_); | 462 base::AutoLock auto_lock(lock_); |
| 463 audio_stream_update = SerializeUpdate( | 463 audio_stream_update = SerializeUpdate( |
| 464 "media.onReceiveAudioStreamData", &audio_streams_cached_data_); | 464 "media.onReceiveAudioStreamData", &audio_streams_cached_data_); |
| 465 } | 465 } |
| 466 SendUpdate(audio_stream_update); | 466 SendUpdate(audio_stream_update); |
| 467 } | 467 } |
| 468 | 468 |
| 469 void MediaInternals::SendVideoCaptureDeviceCapabilities() { | 469 void MediaInternals::SendVideoCaptureDeviceCapabilities() { |
| 470 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 470 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 471 SendUpdate(SerializeUpdate("media.onReceiveVideoCaptureCapabilities", | 471 SendUpdate(SerializeUpdate("media.onReceiveVideoCaptureCapabilities", |
| 472 &video_capture_capabilities_cached_data_)); | 472 &video_capture_capabilities_cached_data_)); |
| 473 } | 473 } |
| 474 | 474 |
| 475 void MediaInternals::UpdateVideoCaptureDeviceCapabilities( | 475 void MediaInternals::UpdateVideoCaptureDeviceCapabilities( |
| 476 const media::VideoCaptureDeviceInfos& video_capture_device_infos) { | 476 const media::VideoCaptureDeviceInfos& video_capture_device_infos) { |
| 477 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 477 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 478 video_capture_capabilities_cached_data_.Clear(); | 478 video_capture_capabilities_cached_data_.Clear(); |
| 479 | 479 |
| 480 for (const auto& video_capture_device_info : video_capture_device_infos) { | 480 for (const auto& video_capture_device_info : video_capture_device_infos) { |
| 481 base::ListValue* format_list = new base::ListValue(); | 481 base::ListValue* format_list = new base::ListValue(); |
| 482 for (const auto& format : video_capture_device_info.supported_formats) | 482 for (const auto& format : video_capture_device_info.supported_formats) |
| 483 format_list->AppendString(format.ToString()); | 483 format_list->AppendString(format.ToString()); |
| 484 | 484 |
| 485 base::DictionaryValue* device_dict = new base::DictionaryValue(); | 485 base::DictionaryValue* device_dict = new base::DictionaryValue(); |
| 486 device_dict->SetString("id", video_capture_device_info.name.id()); | 486 device_dict->SetString("id", video_capture_device_info.name.id()); |
| 487 device_dict->SetString( | 487 device_dict->SetString( |
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 542 const std::string& function, | 542 const std::string& function, |
| 543 const base::DictionaryValue* value) { | 543 const base::DictionaryValue* value) { |
| 544 SendUpdate(SerializeUpdate(function, value)); | 544 SendUpdate(SerializeUpdate(function, value)); |
| 545 | 545 |
| 546 base::AutoLock auto_lock(lock_); | 546 base::AutoLock auto_lock(lock_); |
| 547 scoped_ptr<base::Value> out_value; | 547 scoped_ptr<base::Value> out_value; |
| 548 CHECK(audio_streams_cached_data_.Remove(cache_key, &out_value)); | 548 CHECK(audio_streams_cached_data_.Remove(cache_key, &out_value)); |
| 549 } | 549 } |
| 550 | 550 |
| 551 } // namespace content | 551 } // namespace content |
| OLD | NEW |