Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 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 "chromecast/media/cma/pipeline/media_pipeline_impl.h" | 5 #include "chromecast/media/cma/pipeline/media_pipeline_impl.h" |
| 6 | 6 |
| 7 #include <algorithm> | 7 #include <algorithm> |
| 8 #include <utility> | 8 #include <utility> |
| 9 | 9 |
| 10 #include "base/bind.h" | 10 #include "base/bind.h" |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 44 base::TimeDelta::FromMilliseconds(300)); | 44 base::TimeDelta::FromMilliseconds(300)); |
| 45 | 45 |
| 46 // Interval between two updates of the media time. | 46 // Interval between two updates of the media time. |
| 47 const base::TimeDelta kTimeUpdateInterval( | 47 const base::TimeDelta kTimeUpdateInterval( |
| 48 base::TimeDelta::FromMilliseconds(250)); | 48 base::TimeDelta::FromMilliseconds(250)); |
| 49 | 49 |
| 50 // Interval between two updates of the statistics is equal to: | 50 // Interval between two updates of the statistics is equal to: |
| 51 // kTimeUpdateInterval * kStatisticsUpdatePeriod. | 51 // kTimeUpdateInterval * kStatisticsUpdatePeriod. |
| 52 const int kStatisticsUpdatePeriod = 4; | 52 const int kStatisticsUpdatePeriod = 4; |
| 53 | 53 |
| 54 // Stall duration threshold that triggers a playback stall event. | |
| 55 constexpr int kPlaybackStallEventThreshold = 2500; | |
|
alokp
2016/06/03 19:55:28
Add "Ms" suffix to make the unit clear.
ejason
2016/06/03 21:18:31
Done.
| |
| 56 | |
| 54 void LogEstimatedBitrate(int decoded_bytes, | 57 void LogEstimatedBitrate(int decoded_bytes, |
| 55 base::TimeDelta elapsed_time, | 58 base::TimeDelta elapsed_time, |
| 56 const char* tag, | 59 const char* tag, |
| 57 const char* metric) { | 60 const char* metric) { |
| 58 int estimated_bitrate_in_kbps = | 61 int estimated_bitrate_in_kbps = |
| 59 8 * decoded_bytes / elapsed_time.InMilliseconds(); | 62 8 * decoded_bytes / elapsed_time.InMilliseconds(); |
| 60 | 63 |
| 61 if (estimated_bitrate_in_kbps <= 0) | 64 if (estimated_bitrate_in_kbps <= 0) |
| 62 return; | 65 return; |
| 63 | 66 |
| (...skipping 13 matching lines...) Expand all Loading... | |
| 77 base::Closure done_cb; | 80 base::Closure done_cb; |
| 78 }; | 81 }; |
| 79 | 82 |
| 80 MediaPipelineImpl::MediaPipelineImpl() | 83 MediaPipelineImpl::MediaPipelineImpl() |
| 81 : cdm_(nullptr), | 84 : cdm_(nullptr), |
| 82 backend_state_(BACKEND_STATE_UNINITIALIZED), | 85 backend_state_(BACKEND_STATE_UNINITIALIZED), |
| 83 playback_rate_(1.0f), | 86 playback_rate_(1.0f), |
| 84 audio_decoder_(nullptr), | 87 audio_decoder_(nullptr), |
| 85 video_decoder_(nullptr), | 88 video_decoder_(nullptr), |
| 86 pending_time_update_task_(false), | 89 pending_time_update_task_(false), |
| 90 last_media_time_(::media::kNoTimestamp()), | |
| 87 statistics_rolling_counter_(0), | 91 statistics_rolling_counter_(0), |
| 88 audio_bytes_for_bitrate_estimation_(0), | 92 audio_bytes_for_bitrate_estimation_(0), |
| 89 video_bytes_for_bitrate_estimation_(0), | 93 video_bytes_for_bitrate_estimation_(0), |
| 94 playback_stalled_(false), | |
| 95 playback_stalled_notification_sent_(false), | |
| 90 weak_factory_(this) { | 96 weak_factory_(this) { |
| 91 CMALOG(kLogControl) << __FUNCTION__; | 97 CMALOG(kLogControl) << __FUNCTION__; |
| 92 weak_this_ = weak_factory_.GetWeakPtr(); | 98 weak_this_ = weak_factory_.GetWeakPtr(); |
| 93 thread_checker_.DetachFromThread(); | 99 thread_checker_.DetachFromThread(); |
| 94 } | 100 } |
| 95 | 101 |
| 96 MediaPipelineImpl::~MediaPipelineImpl() { | 102 MediaPipelineImpl::~MediaPipelineImpl() { |
| 97 CMALOG(kLogControl) << __FUNCTION__; | 103 CMALOG(kLogControl) << __FUNCTION__; |
| 98 DCHECK(thread_checker_.CalledOnValidThread()); | 104 DCHECK(thread_checker_.CalledOnValidThread()); |
| 99 | 105 |
| (...skipping 316 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 416 metrics::CastMetricsHelper::GetInstance()->RecordApplicationEvent( | 422 metrics::CastMetricsHelper::GetInstance()->RecordApplicationEvent( |
| 417 "Cast.Platform.Pause"); | 423 "Cast.Platform.Pause"); |
| 418 } else if (!is_buffering && (backend_state_ == BACKEND_STATE_PAUSED)) { | 424 } else if (!is_buffering && (backend_state_ == BACKEND_STATE_PAUSED)) { |
| 419 // Once we finish buffering, we need to honour the desired playback rate | 425 // Once we finish buffering, we need to honour the desired playback rate |
| 420 // (rather than just resuming). This way, if playback was paused while | 426 // (rather than just resuming). This way, if playback was paused while |
| 421 // buffering, it will remain paused rather than incorrectly resuming. | 427 // buffering, it will remain paused rather than incorrectly resuming. |
| 422 SetPlaybackRate(playback_rate_); | 428 SetPlaybackRate(playback_rate_); |
| 423 } | 429 } |
| 424 } | 430 } |
| 425 | 431 |
| 432 void MediaPipelineImpl::CheckForPlaybackStall(base::TimeDelta media_time, | |
| 433 base::TimeTicks current_stc) { | |
| 434 DCHECK(media_time != ::media::kNoTimestamp()); | |
| 435 | |
| 436 // A playback stall is defined as a scenario where the underlying media | |
| 437 // pipeline has unexpectedly stopped making forward progress. The pipeline is | |
| 438 // NOT stalled if: | |
| 439 // | |
| 440 // 1. Media time is progressing | |
| 441 // 2. The backend is paused | |
| 442 // 3. We are currently buffering (this is captured in a separate event) | |
| 443 if (media_time != last_media_time_ || | |
| 444 backend_state_ != BACKEND_STATE_PLAYING || | |
| 445 (buffering_controller_ && buffering_controller_->IsBuffering())) { | |
| 446 if (playback_stalled_) { | |
| 447 // Transition out of the stalled condition. | |
| 448 base::TimeDelta stall_duration = current_stc - playback_stalled_time_; | |
| 449 CMALOG(kLogControl) | |
| 450 << "Transitioning out of stalled state. Stall duration was " | |
| 451 << stall_duration.InMilliseconds() << " ms"; | |
| 452 playback_stalled_ = false; | |
| 453 playback_stalled_notification_sent_ = false; | |
| 454 } | |
| 455 return; | |
| 456 } | |
| 457 | |
| 458 // Check to see if this is a new stall condition. | |
| 459 if (!playback_stalled_) { | |
| 460 playback_stalled_ = true; | |
| 461 playback_stalled_time_ = current_stc; | |
| 462 return; | |
| 463 } | |
| 464 | |
| 465 // If we are in an existing stall, check to see if we've been stalled for more | |
| 466 // than 2.5 s. If so, send a single notification of the stall event. | |
| 467 if (!playback_stalled_notification_sent_) { | |
| 468 base::TimeDelta current_stall_duration = | |
| 469 current_stc - playback_stalled_time_; | |
| 470 if (current_stall_duration.InMilliseconds() >= | |
| 471 kPlaybackStallEventThreshold) { | |
| 472 CMALOG(kLogControl) << "Playback stalled"; | |
| 473 metrics::CastMetricsHelper::GetInstance()->RecordApplicationEvent( | |
| 474 "Cast.Platform.PlaybackStall"); | |
| 475 playback_stalled_notification_sent_ = true; | |
| 476 } | |
| 477 return; | |
| 478 } | |
| 479 } | |
| 480 | |
| 426 void MediaPipelineImpl::UpdateMediaTime() { | 481 void MediaPipelineImpl::UpdateMediaTime() { |
| 427 pending_time_update_task_ = false; | 482 pending_time_update_task_ = false; |
| 428 if ((backend_state_ != BACKEND_STATE_PLAYING) && | 483 if ((backend_state_ != BACKEND_STATE_PLAYING) && |
| 429 (backend_state_ != BACKEND_STATE_PAUSED)) | 484 (backend_state_ != BACKEND_STATE_PAUSED)) |
| 430 return; | 485 return; |
| 431 | 486 |
| 432 if (statistics_rolling_counter_ == 0) { | 487 if (statistics_rolling_counter_ == 0) { |
| 433 if (audio_pipeline_) | 488 if (audio_pipeline_) |
| 434 audio_pipeline_->UpdateStatistics(); | 489 audio_pipeline_->UpdateStatistics(); |
| 435 if (video_pipeline_) | 490 if (video_pipeline_) |
| (...skipping 30 matching lines...) Expand all Loading... | |
| 466 media_pipeline_backend_->GetCurrentPts()); | 521 media_pipeline_backend_->GetCurrentPts()); |
| 467 if (media_time == ::media::kNoTimestamp()) { | 522 if (media_time == ::media::kNoTimestamp()) { |
| 468 pending_time_update_task_ = true; | 523 pending_time_update_task_ = true; |
| 469 base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( | 524 base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( |
| 470 FROM_HERE, base::Bind(&MediaPipelineImpl::UpdateMediaTime, weak_this_), | 525 FROM_HERE, base::Bind(&MediaPipelineImpl::UpdateMediaTime, weak_this_), |
| 471 kTimeUpdateInterval); | 526 kTimeUpdateInterval); |
| 472 return; | 527 return; |
| 473 } | 528 } |
| 474 base::TimeTicks stc = base::TimeTicks::Now(); | 529 base::TimeTicks stc = base::TimeTicks::Now(); |
| 475 | 530 |
| 531 CheckForPlaybackStall(media_time, stc); | |
| 532 | |
| 476 base::TimeDelta max_rendering_time = media_time; | 533 base::TimeDelta max_rendering_time = media_time; |
| 477 if (buffering_controller_) { | 534 if (buffering_controller_) { |
| 478 buffering_controller_->SetMediaTime(media_time); | 535 buffering_controller_->SetMediaTime(media_time); |
| 479 | 536 |
| 480 // Receiving the same time twice in a row means playback isn't moving, | 537 // Receiving the same time twice in a row means playback isn't moving, |
| 481 // so don't interpolate ahead. | 538 // so don't interpolate ahead. |
| 482 if (media_time != last_media_time_) { | 539 if (media_time != last_media_time_) { |
| 483 max_rendering_time = buffering_controller_->GetMaxRenderingTime(); | 540 max_rendering_time = buffering_controller_->GetMaxRenderingTime(); |
| 484 if (max_rendering_time == ::media::kNoTimestamp()) | 541 if (max_rendering_time == ::media::kNoTimestamp()) |
| 485 max_rendering_time = media_time; | 542 max_rendering_time = media_time; |
| (...skipping 27 matching lines...) Expand all Loading... | |
| 513 | 570 |
| 514 void MediaPipelineImpl::ResetBitrateState() { | 571 void MediaPipelineImpl::ResetBitrateState() { |
| 515 elapsed_time_delta_ = base::TimeDelta::FromSeconds(0); | 572 elapsed_time_delta_ = base::TimeDelta::FromSeconds(0); |
| 516 audio_bytes_for_bitrate_estimation_ = 0; | 573 audio_bytes_for_bitrate_estimation_ = 0; |
| 517 video_bytes_for_bitrate_estimation_ = 0; | 574 video_bytes_for_bitrate_estimation_ = 0; |
| 518 last_sample_time_ = base::TimeTicks::Now(); | 575 last_sample_time_ = base::TimeTicks::Now(); |
| 519 } | 576 } |
| 520 | 577 |
| 521 } // namespace media | 578 } // namespace media |
| 522 } // namespace chromecast | 579 } // namespace chromecast |
| OLD | NEW |