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

Side by Side Diff: chromecast/renderer/media/cma_renderer.cc

Issue 1372393007: [Chromecast] Upgrade to new CMA backend API (Closed) Base URL: https://chromium.googlesource.com/chromium/src@master
Patch Set: Address alokp@ comments Created 5 years, 2 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/filters/cma_renderer.h" 5 #include "chromecast/renderer/media/cma_renderer.h"
6 6
7 #include "base/bind.h" 7 #include "base/bind.h"
8 #include "base/callback_helpers.h" 8 #include "base/callback_helpers.h"
9 #include "base/location.h" 9 #include "base/location.h"
10 #include "base/single_thread_task_runner.h" 10 #include "base/single_thread_task_runner.h"
11 #include "base/thread_task_runner_handle.h" 11 #include "base/thread_task_runner_handle.h"
12 #include "chromecast/media/cma/base/balanced_media_task_runner_factory.h" 12 #include "chromecast/media/cma/base/balanced_media_task_runner_factory.h"
13 #include "chromecast/media/cma/base/cma_logging.h" 13 #include "chromecast/media/cma/base/cma_logging.h"
14 #include "chromecast/media/cma/filters/demuxer_stream_adapter.h"
15 #include "chromecast/media/cma/filters/hole_frame_factory.h"
16 #include "chromecast/media/cma/pipeline/audio_pipeline.h"
17 #include "chromecast/media/cma/pipeline/av_pipeline_client.h" 14 #include "chromecast/media/cma/pipeline/av_pipeline_client.h"
18 #include "chromecast/media/cma/pipeline/media_pipeline.h"
19 #include "chromecast/media/cma/pipeline/media_pipeline_client.h" 15 #include "chromecast/media/cma/pipeline/media_pipeline_client.h"
20 #include "chromecast/media/cma/pipeline/video_pipeline.h"
21 #include "chromecast/media/cma/pipeline/video_pipeline_client.h" 16 #include "chromecast/media/cma/pipeline/video_pipeline_client.h"
17 #include "chromecast/renderer/media/audio_pipeline_proxy.h"
18 #include "chromecast/renderer/media/demuxer_stream_adapter.h"
19 #include "chromecast/renderer/media/hole_frame_factory.h"
20 #include "chromecast/renderer/media/media_pipeline_proxy.h"
21 #include "chromecast/renderer/media/video_pipeline_proxy.h"
22 #include "media/base/bind_to_current_loop.h" 22 #include "media/base/bind_to_current_loop.h"
23 #include "media/base/demuxer_stream_provider.h" 23 #include "media/base/demuxer_stream_provider.h"
24 #include "media/base/pipeline_status.h" 24 #include "media/base/pipeline_status.h"
25 #include "media/base/time_delta_interpolator.h" 25 #include "media/base/time_delta_interpolator.h"
26 #include "media/base/video_renderer_sink.h" 26 #include "media/base/video_renderer_sink.h"
27 #include "media/renderers/gpu_video_accelerator_factories.h" 27 #include "media/renderers/gpu_video_accelerator_factories.h"
28 #include "ui/gfx/geometry/size.h" 28 #include "ui/gfx/geometry/size.h"
29 29
30 namespace chromecast { 30 namespace chromecast {
31 namespace media { 31 namespace media {
32 32
33 namespace { 33 namespace {
34 34
35 // Maximum difference between audio frame PTS and video frame PTS 35 // Maximum difference between audio frame PTS and video frame PTS
36 // for frames read from the DemuxerStream. 36 // for frames read from the DemuxerStream.
37 const base::TimeDelta kMaxDeltaFetcher( 37 const base::TimeDelta kMaxDeltaFetcher(base::TimeDelta::FromMilliseconds(2000));
38 base::TimeDelta::FromMilliseconds(2000));
39 38
40 void MediaPipelineClientDummyCallback() {} 39 void MediaPipelineClientDummyCallback() {
40 }
41 41
42 } // namespace 42 } // namespace
43 43
44 CmaRenderer::CmaRenderer( 44 CmaRenderer::CmaRenderer(
45 scoped_ptr<MediaPipeline> media_pipeline, 45 scoped_ptr<MediaPipelineProxy> media_pipeline,
46 ::media::VideoRendererSink* video_renderer_sink, 46 ::media::VideoRendererSink* video_renderer_sink,
47 const scoped_refptr<::media::GpuVideoAcceleratorFactories>& gpu_factories) 47 const scoped_refptr<::media::GpuVideoAcceleratorFactories>& gpu_factories)
48 : media_task_runner_factory_( 48 : media_task_runner_factory_(
49 new BalancedMediaTaskRunnerFactory(kMaxDeltaFetcher)), 49 new BalancedMediaTaskRunnerFactory(kMaxDeltaFetcher)),
50 media_pipeline_(media_pipeline.Pass()), 50 media_pipeline_(media_pipeline.Pass()),
51 audio_pipeline_(media_pipeline_->GetAudioPipeline()), 51 audio_pipeline_(media_pipeline_->GetAudioPipeline()),
52 video_pipeline_(media_pipeline_->GetVideoPipeline()), 52 video_pipeline_(media_pipeline_->GetVideoPipeline()),
53 video_renderer_sink_(video_renderer_sink), 53 video_renderer_sink_(video_renderer_sink),
54 state_(kUninitialized), 54 state_(kUninitialized),
55 is_pending_transition_(false), 55 is_pending_transition_(false),
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after
115 waiting_for_decryption_key_cb_ = waiting_for_decryption_key_cb; 115 waiting_for_decryption_key_cb_ = waiting_for_decryption_key_cb;
116 116
117 MediaPipelineClient media_pipeline_client; 117 MediaPipelineClient media_pipeline_client;
118 media_pipeline_client.error_cb = error_cb_; 118 media_pipeline_client.error_cb = error_cb_;
119 media_pipeline_client.buffering_state_cb = ::media::BindToCurrentLoop( 119 media_pipeline_client.buffering_state_cb = ::media::BindToCurrentLoop(
120 base::Bind(&CmaRenderer::OnBufferingNotification, weak_this_)); 120 base::Bind(&CmaRenderer::OnBufferingNotification, weak_this_));
121 media_pipeline_client.time_update_cb = ::media::BindToCurrentLoop( 121 media_pipeline_client.time_update_cb = ::media::BindToCurrentLoop(
122 base::Bind(&CmaRenderer::OnPlaybackTimeUpdated, weak_this_)); 122 base::Bind(&CmaRenderer::OnPlaybackTimeUpdated, weak_this_));
123 media_pipeline_client.pipeline_backend_created_cb = 123 media_pipeline_client.pipeline_backend_created_cb =
124 base::Bind(&MediaPipelineClientDummyCallback); 124 base::Bind(&MediaPipelineClientDummyCallback);
125 media_pipeline_client.pipeline_backend_destroyed_cb 125 media_pipeline_client.pipeline_backend_destroyed_cb =
126 = base::Bind(&MediaPipelineClientDummyCallback); 126 base::Bind(&MediaPipelineClientDummyCallback);
127 media_pipeline_->SetClient(media_pipeline_client); 127 media_pipeline_->SetClient(media_pipeline_client);
128 128
129 init_cb_ = init_cb; 129 init_cb_ = init_cb;
130 InitializeAudioPipeline(); 130 InitializeAudioPipeline();
131 } 131 }
132 132
133 void CmaRenderer::Flush(const base::Closure& flush_cb) { 133 void CmaRenderer::Flush(const base::Closure& flush_cb) {
134 CMALOG(kLogControl) << __FUNCTION__; 134 CMALOG(kLogControl) << __FUNCTION__;
135 DCHECK(thread_checker_.CalledOnValidThread()); 135 DCHECK(thread_checker_.CalledOnValidThread());
136 BeginStateTransition(); 136 BeginStateTransition();
137 137
138 DCHECK(flush_cb_.is_null()); 138 DCHECK(flush_cb_.is_null());
139 flush_cb_ = flush_cb; 139 flush_cb_ = flush_cb;
140 140
141 if (state_ == kError) { 141 if (state_ == kError) {
142 OnError(::media::PIPELINE_ERROR_ABORT); 142 OnError(::media::PIPELINE_ERROR_ABORT);
143 return; 143 return;
144 } 144 }
145 145
146 DCHECK_EQ(state_, kPlaying) << state_; 146 DCHECK_EQ(state_, kPlaying) << state_;
147 media_pipeline_->Flush( 147 media_pipeline_->Flush(::media::BindToCurrentLoop(
148 ::media::BindToCurrentLoop( 148 base::Bind(&CmaRenderer::OnFlushDone, weak_this_)));
149 base::Bind(&CmaRenderer::OnFlushDone, weak_this_)));
150 149
151 { 150 {
152 base::AutoLock auto_lock(time_interpolator_lock_); 151 base::AutoLock auto_lock(time_interpolator_lock_);
153 time_interpolator_->StopInterpolating(); 152 time_interpolator_->StopInterpolating();
154 } 153 }
155 } 154 }
156 155
157 void CmaRenderer::StartPlayingFrom(base::TimeDelta time) { 156 void CmaRenderer::StartPlayingFrom(base::TimeDelta time) {
158 CMALOG(kLogControl) << __FUNCTION__ << ": " << time.InMilliseconds(); 157 CMALOG(kLogControl) << __FUNCTION__ << ": " << time.InMilliseconds();
159 DCHECK(thread_checker_.CalledOnValidThread()); 158 DCHECK(thread_checker_.CalledOnValidThread());
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after
241 240
242 void CmaRenderer::InitializeAudioPipeline() { 241 void CmaRenderer::InitializeAudioPipeline() {
243 DCHECK(thread_checker_.CalledOnValidThread()); 242 DCHECK(thread_checker_.CalledOnValidThread());
244 DCHECK_EQ(state_, kUninitialized) << state_; 243 DCHECK_EQ(state_, kUninitialized) << state_;
245 DCHECK(!init_cb_.is_null()); 244 DCHECK(!init_cb_.is_null());
246 245
247 ::media::DemuxerStream* stream = 246 ::media::DemuxerStream* stream =
248 demuxer_stream_provider_->GetStream(::media::DemuxerStream::AUDIO); 247 demuxer_stream_provider_->GetStream(::media::DemuxerStream::AUDIO);
249 ::media::PipelineStatusCB audio_initialization_done_cb = 248 ::media::PipelineStatusCB audio_initialization_done_cb =
250 ::media::BindToCurrentLoop( 249 ::media::BindToCurrentLoop(
251 base::Bind(&CmaRenderer::OnAudioPipelineInitializeDone, weak_this_, 250 base::Bind(&CmaRenderer::OnAudioPipelineInitializeDone,
251 weak_this_,
252 stream != nullptr)); 252 stream != nullptr));
253 if (!stream) { 253 if (!stream) {
254 CMALOG(kLogControl) << __FUNCTION__ << ": no audio stream, skipping init."; 254 CMALOG(kLogControl) << __FUNCTION__ << ": no audio stream, skipping init.";
255 audio_initialization_done_cb.Run(::media::PIPELINE_OK); 255 audio_initialization_done_cb.Run(::media::PIPELINE_OK);
256 return; 256 return;
257 } 257 }
258 258
259 // Receive events from the audio pipeline. 259 // Receive events from the audio pipeline.
260 AvPipelineClient av_pipeline_client; 260 AvPipelineClient av_pipeline_client;
261 av_pipeline_client.eos_cb = ::media::BindToCurrentLoop( 261 av_pipeline_client.eos_cb = ::media::BindToCurrentLoop(
262 base::Bind(&CmaRenderer::OnEosReached, weak_this_, true)); 262 base::Bind(&CmaRenderer::OnEosReached, weak_this_, true));
263 av_pipeline_client.playback_error_cb = ::media::BindToCurrentLoop( 263 av_pipeline_client.playback_error_cb =
264 base::Bind(&CmaRenderer::OnError, weak_this_)); 264 ::media::BindToCurrentLoop(base::Bind(&CmaRenderer::OnError, weak_this_));
265 av_pipeline_client.statistics_cb = ::media::BindToCurrentLoop( 265 av_pipeline_client.statistics_cb = ::media::BindToCurrentLoop(
266 base::Bind(&CmaRenderer::OnStatisticsUpdated, weak_this_)); 266 base::Bind(&CmaRenderer::OnStatisticsUpdated, weak_this_));
267 audio_pipeline_->SetClient(av_pipeline_client); 267 audio_pipeline_->SetClient(av_pipeline_client);
268 268
269 scoped_ptr<CodedFrameProvider> frame_provider(new DemuxerStreamAdapter( 269 scoped_ptr<CodedFrameProvider> frame_provider(new DemuxerStreamAdapter(
270 base::ThreadTaskRunnerHandle::Get(), media_task_runner_factory_, stream)); 270 base::ThreadTaskRunnerHandle::Get(), media_task_runner_factory_, stream));
271 271
272 const ::media::AudioDecoderConfig& config = stream->audio_decoder_config(); 272 const ::media::AudioDecoderConfig& config = stream->audio_decoder_config();
273 if (config.codec() == ::media::kCodecAAC) 273 if (config.codec() == ::media::kCodecAAC)
274 stream->EnableBitstreamConverter(); 274 stream->EnableBitstreamConverter();
(...skipping 25 matching lines...) Expand all
300 300
301 void CmaRenderer::InitializeVideoPipeline() { 301 void CmaRenderer::InitializeVideoPipeline() {
302 DCHECK(thread_checker_.CalledOnValidThread()); 302 DCHECK(thread_checker_.CalledOnValidThread());
303 DCHECK_EQ(state_, kUninitialized) << state_; 303 DCHECK_EQ(state_, kUninitialized) << state_;
304 DCHECK(!init_cb_.is_null()); 304 DCHECK(!init_cb_.is_null());
305 305
306 ::media::DemuxerStream* stream = 306 ::media::DemuxerStream* stream =
307 demuxer_stream_provider_->GetStream(::media::DemuxerStream::VIDEO); 307 demuxer_stream_provider_->GetStream(::media::DemuxerStream::VIDEO);
308 ::media::PipelineStatusCB video_initialization_done_cb = 308 ::media::PipelineStatusCB video_initialization_done_cb =
309 ::media::BindToCurrentLoop( 309 ::media::BindToCurrentLoop(
310 base::Bind(&CmaRenderer::OnVideoPipelineInitializeDone, weak_this_, 310 base::Bind(&CmaRenderer::OnVideoPipelineInitializeDone,
311 weak_this_,
311 stream != nullptr)); 312 stream != nullptr));
312 if (!stream) { 313 if (!stream) {
313 CMALOG(kLogControl) << __FUNCTION__ << ": no video stream, skipping init."; 314 CMALOG(kLogControl) << __FUNCTION__ << ": no video stream, skipping init.";
314 video_initialization_done_cb.Run(::media::PIPELINE_OK); 315 video_initialization_done_cb.Run(::media::PIPELINE_OK);
315 return; 316 return;
316 } 317 }
317 318
318 // Receive events from the video pipeline. 319 // Receive events from the video pipeline.
319 VideoPipelineClient client; 320 VideoPipelineClient client;
320 client.av_pipeline_client.eos_cb = ::media::BindToCurrentLoop( 321 client.av_pipeline_client.eos_cb = ::media::BindToCurrentLoop(
321 base::Bind(&CmaRenderer::OnEosReached, weak_this_, false)); 322 base::Bind(&CmaRenderer::OnEosReached, weak_this_, false));
322 client.av_pipeline_client.playback_error_cb = ::media::BindToCurrentLoop( 323 client.av_pipeline_client.playback_error_cb =
323 base::Bind(&CmaRenderer::OnError, weak_this_)); 324 ::media::BindToCurrentLoop(base::Bind(&CmaRenderer::OnError, weak_this_));
324 client.av_pipeline_client.statistics_cb = ::media::BindToCurrentLoop( 325 client.av_pipeline_client.statistics_cb = ::media::BindToCurrentLoop(
325 base::Bind(&CmaRenderer::OnStatisticsUpdated, weak_this_)); 326 base::Bind(&CmaRenderer::OnStatisticsUpdated, weak_this_));
326 client.natural_size_changed_cb = ::media::BindToCurrentLoop( 327 client.natural_size_changed_cb = ::media::BindToCurrentLoop(
327 base::Bind(&CmaRenderer::OnNaturalSizeChanged, weak_this_)); 328 base::Bind(&CmaRenderer::OnNaturalSizeChanged, weak_this_));
328 video_pipeline_->SetClient(client); 329 video_pipeline_->SetClient(client);
329 330
330 scoped_ptr<CodedFrameProvider> frame_provider(new DemuxerStreamAdapter( 331 scoped_ptr<CodedFrameProvider> frame_provider(new DemuxerStreamAdapter(
331 base::ThreadTaskRunnerHandle::Get(), media_task_runner_factory_, stream)); 332 base::ThreadTaskRunnerHandle::Get(), media_task_runner_factory_, stream));
332 333
333 const ::media::VideoDecoderConfig& config = stream->video_decoder_config(); 334 const ::media::VideoDecoderConfig& config = stream->video_decoder_config();
334 if (config.codec() == ::media::kCodecH264) 335 if (config.codec() == ::media::kCodecH264)
335 stream->EnableBitstreamConverter(); 336 stream->EnableBitstreamConverter();
336 337
337 initial_natural_size_ = config.natural_size(); 338 initial_natural_size_ = config.natural_size();
338 339
339 std::vector<::media::VideoDecoderConfig> configs; 340 std::vector<::media::VideoDecoderConfig> configs;
340 configs.push_back(config); 341 configs.push_back(config);
341 media_pipeline_->InitializeVideo( 342 media_pipeline_->InitializeVideo(
342 configs, 343 configs, frame_provider.Pass(), video_initialization_done_cb);
343 frame_provider.Pass(),
344 video_initialization_done_cb);
345 } 344 }
346 345
347 void CmaRenderer::OnVideoPipelineInitializeDone( 346 void CmaRenderer::OnVideoPipelineInitializeDone(
348 bool video_stream_present, 347 bool video_stream_present,
349 ::media::PipelineStatus status) { 348 ::media::PipelineStatus status) {
350 CMALOG(kLogControl) << __FUNCTION__ << ": state=" << state_; 349 CMALOG(kLogControl) << __FUNCTION__ << ": state=" << state_;
351 DCHECK(thread_checker_.CalledOnValidThread()); 350 DCHECK(thread_checker_.CalledOnValidThread());
352 351
353 // OnError() may be fired at any time, even before initialization is complete. 352 // OnError() may be fired at any time, even before initialization is complete.
354 if (state_ == kError) 353 if (state_ == kError)
(...skipping 21 matching lines...) Expand all
376 if (is_audio) { 375 if (is_audio) {
377 DCHECK(!received_audio_eos_); 376 DCHECK(!received_audio_eos_);
378 received_audio_eos_ = true; 377 received_audio_eos_ = true;
379 } else { 378 } else {
380 DCHECK(!received_video_eos_); 379 DCHECK(!received_video_eos_);
381 received_video_eos_ = true; 380 received_video_eos_ = true;
382 } 381 }
383 382
384 bool audio_finished = !has_audio_ || received_audio_eos_; 383 bool audio_finished = !has_audio_ || received_audio_eos_;
385 bool video_finished = !has_video_ || received_video_eos_; 384 bool video_finished = !has_video_ || received_video_eos_;
386 CMALOG(kLogControl) << __FUNCTION__ 385 CMALOG(kLogControl) << __FUNCTION__ << " audio_finished=" << audio_finished
387 << " audio_finished=" << audio_finished
388 << " video_finished=" << video_finished; 386 << " video_finished=" << video_finished;
389 if (audio_finished && video_finished) 387 if (audio_finished && video_finished)
390 ended_cb_.Run(); 388 ended_cb_.Run();
391 } 389 }
392 390
393 void CmaRenderer::OnStatisticsUpdated( 391 void CmaRenderer::OnStatisticsUpdated(
394 const ::media::PipelineStatistics& stats) { 392 const ::media::PipelineStatistics& stats) {
395 DCHECK(thread_checker_.CalledOnValidThread()); 393 DCHECK(thread_checker_.CalledOnValidThread());
396 statistics_cb_.Run(stats); 394 statistics_cb_.Run(stats);
397 } 395 }
398 396
399 void CmaRenderer::OnNaturalSizeChanged(const gfx::Size& size) { 397 void CmaRenderer::OnNaturalSizeChanged(const gfx::Size& size) {
400 DCHECK(thread_checker_.CalledOnValidThread()); 398 DCHECK(thread_checker_.CalledOnValidThread());
401 video_renderer_sink_->PaintFrameUsingOldRenderingPath( 399 video_renderer_sink_->PaintFrameUsingOldRenderingPath(
402 hole_frame_factory_->CreateHoleFrame(size)); 400 hole_frame_factory_->CreateHoleFrame(size));
403 } 401 }
404 402
405 void CmaRenderer::OnPlaybackTimeUpdated( 403 void CmaRenderer::OnPlaybackTimeUpdated(base::TimeDelta time,
406 base::TimeDelta time, 404 base::TimeDelta max_time,
407 base::TimeDelta max_time, 405 base::TimeTicks capture_time) {
408 base::TimeTicks capture_time) {
409 DCHECK(thread_checker_.CalledOnValidThread()); 406 DCHECK(thread_checker_.CalledOnValidThread());
410 if (state_ != kPlaying) { 407 if (state_ != kPlaying) {
411 LOG(WARNING) << "Ignoring a late time update"; 408 LOG(WARNING) << "Ignoring a late time update";
412 return; 409 return;
413 } 410 }
414 411
415 // TODO(halliwell): arguably, TimeDeltaInterpolator::SetBounds should perform 412 // TODO(halliwell): arguably, TimeDeltaInterpolator::SetBounds should perform
416 // this calculation to avoid calling TimeTicks::Now twice (it's slower and has 413 // this calculation to avoid calling TimeTicks::Now twice (it's slower and has
417 // potential accuracy problems). 414 // potential accuracy problems).
418 base::TimeDelta lower_bound = 415 base::TimeDelta lower_bound =
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after
477 is_pending_transition_ = true; 474 is_pending_transition_ = true;
478 } 475 }
479 476
480 void CmaRenderer::CompleteStateTransition(State new_state) { 477 void CmaRenderer::CompleteStateTransition(State new_state) {
481 state_ = new_state; 478 state_ = new_state;
482 is_pending_transition_ = false; 479 is_pending_transition_ = false;
483 } 480 }
484 481
485 } // namespace media 482 } // namespace media
486 } // namespace chromecast 483 } // namespace chromecast
OLDNEW
« no previous file with comments | « chromecast/renderer/media/cma_renderer.h ('k') | chromecast/renderer/media/demuxer_stream_adapter.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698