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

Side by Side Diff: chromecast/media/cma/pipeline/media_pipeline_impl.cc

Issue 2032813002: [Chromecast] Log playback stall event. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Clarify units on playback stall threshold Created 4 years, 6 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 | « chromecast/media/cma/pipeline/media_pipeline_impl.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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 kPlaybackStallEventThresholdMs = 2500;
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
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
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 kPlaybackStallEventThresholdMs) {
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
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
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
OLDNEW
« no previous file with comments | « chromecast/media/cma/pipeline/media_pipeline_impl.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698