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

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

Issue 1776353006: [Chromecast] Add metrics for logging platform A/V bitrate estimates. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Remove unnecessary initialization Created 4 years, 9 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
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"
11 #include "base/callback.h" 11 #include "base/callback.h"
12 #include "base/callback_helpers.h" 12 #include "base/callback_helpers.h"
13 #include "base/location.h" 13 #include "base/location.h"
14 #include "base/logging.h" 14 #include "base/logging.h"
15 #include "base/single_thread_task_runner.h" 15 #include "base/single_thread_task_runner.h"
16 #include "base/thread_task_runner_handle.h" 16 #include "base/thread_task_runner_handle.h"
17 #include "base/time/time.h"
18 #include "chromecast/base/metrics/cast_metrics_helper.h" 17 #include "chromecast/base/metrics/cast_metrics_helper.h"
19 #include "chromecast/media/cdm/browser_cdm_cast.h" 18 #include "chromecast/media/cdm/browser_cdm_cast.h"
20 #include "chromecast/media/cma/base/buffering_controller.h" 19 #include "chromecast/media/cma/base/buffering_controller.h"
21 #include "chromecast/media/cma/base/buffering_state.h" 20 #include "chromecast/media/cma/base/buffering_state.h"
22 #include "chromecast/media/cma/base/cma_logging.h" 21 #include "chromecast/media/cma/base/cma_logging.h"
23 #include "chromecast/media/cma/base/coded_frame_provider.h" 22 #include "chromecast/media/cma/base/coded_frame_provider.h"
24 #include "chromecast/media/cma/pipeline/audio_decoder_software_wrapper.h" 23 #include "chromecast/media/cma/pipeline/audio_decoder_software_wrapper.h"
25 #include "chromecast/media/cma/pipeline/audio_pipeline_impl.h" 24 #include "chromecast/media/cma/pipeline/audio_pipeline_impl.h"
26 #include "chromecast/media/cma/pipeline/video_pipeline_impl.h" 25 #include "chromecast/media/cma/pipeline/video_pipeline_impl.h"
27 #include "chromecast/public/media/media_pipeline_backend.h" 26 #include "chromecast/public/media/media_pipeline_backend.h"
(...skipping 17 matching lines...) Expand all
45 base::TimeDelta::FromMilliseconds(300)); 44 base::TimeDelta::FromMilliseconds(300));
46 45
47 // Interval between two updates of the media time. 46 // Interval between two updates of the media time.
48 const base::TimeDelta kTimeUpdateInterval( 47 const base::TimeDelta kTimeUpdateInterval(
49 base::TimeDelta::FromMilliseconds(250)); 48 base::TimeDelta::FromMilliseconds(250));
50 49
51 // Interval between two updates of the statistics is equal to: 50 // Interval between two updates of the statistics is equal to:
52 // kTimeUpdateInterval * kStatisticsUpdatePeriod. 51 // kTimeUpdateInterval * kStatisticsUpdatePeriod.
53 const int kStatisticsUpdatePeriod = 4; 52 const int kStatisticsUpdatePeriod = 4;
54 53
54 void LogEstimatedBitrate(int decoded_bytes,
55 base::TimeDelta elapsed_time,
56 const char* tag,
57 const char* metric) {
58 int estimated_bitrate_in_kbps =
59 8 * decoded_bytes / elapsed_time.InMilliseconds();
60
61 if (estimated_bitrate_in_kbps <= 0)
62 return;
63
64 CMALOG(kLogControl) << "Estimated " << tag << " bitrate is "
65 << estimated_bitrate_in_kbps << " kbps";
66 metrics::CastMetricsHelper* metrics_helper =
67 metrics::CastMetricsHelper::GetInstance();
68 metrics_helper->RecordSimpleActionWithValue(metric,
69 estimated_bitrate_in_kbps);
70 }
71
55 } // namespace 72 } // namespace
56 73
57 struct MediaPipelineImpl::FlushTask { 74 struct MediaPipelineImpl::FlushTask {
58 bool audio_flushed; 75 bool audio_flushed;
59 bool video_flushed; 76 bool video_flushed;
60 base::Closure done_cb; 77 base::Closure done_cb;
61 }; 78 };
62 79
63 MediaPipelineImpl::MediaPipelineImpl() 80 MediaPipelineImpl::MediaPipelineImpl()
64 : cdm_(nullptr), 81 : cdm_(nullptr),
65 backend_state_(BACKEND_STATE_UNINITIALIZED), 82 backend_state_(BACKEND_STATE_UNINITIALIZED),
66 playback_rate_(1.0f), 83 playback_rate_(1.0f),
67 audio_decoder_(nullptr), 84 audio_decoder_(nullptr),
68 video_decoder_(nullptr), 85 video_decoder_(nullptr),
69 pending_time_update_task_(false), 86 pending_time_update_task_(false),
70 statistics_rolling_counter_(0), 87 statistics_rolling_counter_(0),
88 audio_bytes_for_bitrate_estimation_(0),
89 video_bytes_for_bitrate_estimation_(0),
71 weak_factory_(this) { 90 weak_factory_(this) {
72 CMALOG(kLogControl) << __FUNCTION__; 91 CMALOG(kLogControl) << __FUNCTION__;
73 weak_this_ = weak_factory_.GetWeakPtr(); 92 weak_this_ = weak_factory_.GetWeakPtr();
74 thread_checker_.DetachFromThread(); 93 thread_checker_.DetachFromThread();
75 } 94 }
76 95
77 MediaPipelineImpl::~MediaPipelineImpl() { 96 MediaPipelineImpl::~MediaPipelineImpl() {
78 CMALOG(kLogControl) << __FUNCTION__; 97 CMALOG(kLogControl) << __FUNCTION__;
79 DCHECK(thread_checker_.CalledOnValidThread()); 98 DCHECK(thread_checker_.CalledOnValidThread());
80 99
(...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after
197 } 216 }
198 backend_state_ = BACKEND_STATE_INITIALIZED; 217 backend_state_ = BACKEND_STATE_INITIALIZED;
199 } 218 }
200 219
201 // Start the backend. 220 // Start the backend.
202 if (!media_pipeline_backend_->Start(time.InMicroseconds())) { 221 if (!media_pipeline_backend_->Start(time.InMicroseconds())) {
203 OnError(::media::PIPELINE_ERROR_ABORT); 222 OnError(::media::PIPELINE_ERROR_ABORT);
204 return; 223 return;
205 } 224 }
206 backend_state_ = BACKEND_STATE_PLAYING; 225 backend_state_ = BACKEND_STATE_PLAYING;
226 ResetBitrateState();
207 metrics::CastMetricsHelper::GetInstance()->RecordSimpleAction( 227 metrics::CastMetricsHelper::GetInstance()->RecordSimpleAction(
208 "Cast.Platform.Playing"); 228 "Cast.Platform.Playing");
209 229
210 // Enable time updates. 230 // Enable time updates.
211 statistics_rolling_counter_ = 0; 231 statistics_rolling_counter_ = 0;
212 if (!pending_time_update_task_) { 232 if (!pending_time_update_task_) {
213 pending_time_update_task_ = true; 233 pending_time_update_task_ = true;
214 base::ThreadTaskRunnerHandle::Get()->PostTask( 234 base::ThreadTaskRunnerHandle::Get()->PostTask(
215 FROM_HERE, base::Bind(&MediaPipelineImpl::UpdateMediaTime, weak_this_)); 235 FROM_HERE, base::Bind(&MediaPipelineImpl::UpdateMediaTime, weak_this_));
216 } 236 }
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after
311 331
312 playback_rate_ = rate; 332 playback_rate_ = rate;
313 if (buffering_controller_ && buffering_controller_->IsBuffering()) 333 if (buffering_controller_ && buffering_controller_->IsBuffering())
314 return; 334 return;
315 335
316 if (rate != 0.0f) { 336 if (rate != 0.0f) {
317 media_pipeline_backend_->SetPlaybackRate(rate); 337 media_pipeline_backend_->SetPlaybackRate(rate);
318 if (backend_state_ == BACKEND_STATE_PAUSED) { 338 if (backend_state_ == BACKEND_STATE_PAUSED) {
319 media_pipeline_backend_->Resume(); 339 media_pipeline_backend_->Resume();
320 backend_state_ = BACKEND_STATE_PLAYING; 340 backend_state_ = BACKEND_STATE_PLAYING;
341 ResetBitrateState();
321 metrics::CastMetricsHelper::GetInstance()->RecordSimpleAction( 342 metrics::CastMetricsHelper::GetInstance()->RecordSimpleAction(
322 "Cast.Platform.Playing"); 343 "Cast.Platform.Playing");
323 } 344 }
324 } else if (backend_state_ == BACKEND_STATE_PLAYING) { 345 } else if (backend_state_ == BACKEND_STATE_PLAYING) {
325 media_pipeline_backend_->Pause(); 346 media_pipeline_backend_->Pause();
326 backend_state_ = BACKEND_STATE_PAUSED; 347 backend_state_ = BACKEND_STATE_PAUSED;
327 metrics::CastMetricsHelper::GetInstance()->RecordSimpleAction( 348 metrics::CastMetricsHelper::GetInstance()->RecordSimpleAction(
328 "Cast.Platform.Pause"); 349 "Cast.Platform.Pause");
329 } 350 }
330 } 351 }
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after
408 pending_time_update_task_ = false; 429 pending_time_update_task_ = false;
409 if ((backend_state_ != BACKEND_STATE_PLAYING) && 430 if ((backend_state_ != BACKEND_STATE_PLAYING) &&
410 (backend_state_ != BACKEND_STATE_PAUSED)) 431 (backend_state_ != BACKEND_STATE_PAUSED))
411 return; 432 return;
412 433
413 if (statistics_rolling_counter_ == 0) { 434 if (statistics_rolling_counter_ == 0) {
414 if (audio_pipeline_) 435 if (audio_pipeline_)
415 audio_pipeline_->UpdateStatistics(); 436 audio_pipeline_->UpdateStatistics();
416 if (video_pipeline_) 437 if (video_pipeline_)
417 video_pipeline_->UpdateStatistics(); 438 video_pipeline_->UpdateStatistics();
439
440 if (backend_state_ == BACKEND_STATE_PLAYING) {
441 base::TimeTicks current_time = base::TimeTicks::Now();
442 audio_bytes_for_bitrate_estimation_ +=
443 audio_pipeline_->bytes_decoded_since_last_update();
halliwell 2016/03/11 21:22:36 It's possible to not have an audio pipeline, so ne
ejason 2016/03/11 22:14:45 Good catch, oversight on my part. Done.
444 video_bytes_for_bitrate_estimation_ +=
445 video_pipeline_->bytes_decoded_since_last_update();
halliwell 2016/03/11 21:22:36 Ditto.
ejason 2016/03/11 22:14:46 Done.
446 elapsed_time_delta_ += current_time - last_sample_time_;
447 if (elapsed_time_delta_.InMilliseconds() > 5000) {
448 LogEstimatedBitrate(audio_bytes_for_bitrate_estimation_,
449 elapsed_time_delta_, "audio",
450 "Cast.Platform.AudioBitrate");
451 LogEstimatedBitrate(video_bytes_for_bitrate_estimation_,
452 elapsed_time_delta_, "video",
453 "Cast.Platform.VideoBitrate");
454 ResetBitrateState();
455 }
456 last_sample_time_ = current_time;
457 }
418 } 458 }
459
419 statistics_rolling_counter_ = 460 statistics_rolling_counter_ =
420 (statistics_rolling_counter_ + 1) % kStatisticsUpdatePeriod; 461 (statistics_rolling_counter_ + 1) % kStatisticsUpdatePeriod;
421 462
422 base::TimeDelta media_time = base::TimeDelta::FromMicroseconds( 463 base::TimeDelta media_time = base::TimeDelta::FromMicroseconds(
423 media_pipeline_backend_->GetCurrentPts()); 464 media_pipeline_backend_->GetCurrentPts());
424 if (media_time == ::media::kNoTimestamp()) { 465 if (media_time == ::media::kNoTimestamp()) {
425 pending_time_update_task_ = true; 466 pending_time_update_task_ = true;
426 base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( 467 base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
427 FROM_HERE, base::Bind(&MediaPipelineImpl::UpdateMediaTime, weak_this_), 468 FROM_HERE, base::Bind(&MediaPipelineImpl::UpdateMediaTime, weak_this_),
428 kTimeUpdateInterval); 469 kTimeUpdateInterval);
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
461 DCHECK(thread_checker_.CalledOnValidThread()); 502 DCHECK(thread_checker_.CalledOnValidThread());
462 DCHECK_NE(error, ::media::PIPELINE_OK) << "PIPELINE_OK is not an error!"; 503 DCHECK_NE(error, ::media::PIPELINE_OK) << "PIPELINE_OK is not an error!";
463 504
464 metrics::CastMetricsHelper::GetInstance()->RecordSimpleAction( 505 metrics::CastMetricsHelper::GetInstance()->RecordSimpleAction(
465 "Cast.Platform.Error"); 506 "Cast.Platform.Error");
466 507
467 if (!client_.error_cb.is_null()) 508 if (!client_.error_cb.is_null())
468 client_.error_cb.Run(error); 509 client_.error_cb.Run(error);
469 } 510 }
470 511
512 void MediaPipelineImpl::ResetBitrateState() {
513 elapsed_time_delta_ = base::TimeDelta::FromSeconds(0);
514 audio_bytes_for_bitrate_estimation_ = 0;
515 video_bytes_for_bitrate_estimation_ = 0;
516 last_sample_time_ = base::TimeTicks::Now();
517 }
518
471 } // namespace media 519 } // namespace media
472 } // namespace chromecast 520 } // namespace chromecast
OLDNEW
« no previous file with comments | « chromecast/media/cma/pipeline/media_pipeline_impl.h ('k') | chromecast/media/cma/pipeline/video_pipeline_impl.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698