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/renderer/media/cma_renderer.h" | 5 #include "chromecast/renderer/media/cma_renderer.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 #include <utility> | 8 #include <utility> |
9 #include <vector> | 9 #include <vector> |
10 | 10 |
11 #include "base/bind.h" | 11 #include "base/bind.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/single_thread_task_runner.h" | 14 #include "base/single_thread_task_runner.h" |
15 #include "base/threading/thread_task_runner_handle.h" | 15 #include "base/threading/thread_task_runner_handle.h" |
16 #include "chromecast/media/cma/base/balanced_media_task_runner_factory.h" | 16 #include "chromecast/media/cma/base/balanced_media_task_runner_factory.h" |
17 #include "chromecast/media/cma/base/cma_logging.h" | 17 #include "chromecast/media/cma/base/cma_logging.h" |
18 #include "chromecast/media/cma/base/demuxer_stream_adapter.h" | 18 #include "chromecast/media/cma/base/demuxer_stream_adapter.h" |
19 #include "chromecast/media/cma/pipeline/av_pipeline_client.h" | 19 #include "chromecast/media/cma/pipeline/av_pipeline_client.h" |
20 #include "chromecast/media/cma/pipeline/media_pipeline_client.h" | 20 #include "chromecast/media/cma/pipeline/media_pipeline_client.h" |
21 #include "chromecast/media/cma/pipeline/video_pipeline_client.h" | 21 #include "chromecast/media/cma/pipeline/video_pipeline_client.h" |
22 #include "chromecast/renderer/media/audio_pipeline_proxy.h" | 22 #include "chromecast/renderer/media/audio_pipeline_proxy.h" |
23 #include "chromecast/renderer/media/hole_frame_factory.h" | 23 #include "chromecast/renderer/media/hole_frame_factory.h" |
24 #include "chromecast/renderer/media/media_pipeline_proxy.h" | 24 #include "chromecast/renderer/media/media_pipeline_proxy.h" |
25 #include "chromecast/renderer/media/video_pipeline_proxy.h" | 25 #include "chromecast/renderer/media/video_pipeline_proxy.h" |
26 #include "media/base/bind_to_current_loop.h" | 26 #include "media/base/bind_to_current_loop.h" |
27 #include "media/base/demuxer_stream_provider.h" | 27 #include "media/base/demuxer_stream_provider.h" |
28 #include "media/base/pipeline_status.h" | 28 #include "media/base/pipeline_status.h" |
| 29 #include "media/base/renderer_client.h" |
29 #include "media/base/time_delta_interpolator.h" | 30 #include "media/base/time_delta_interpolator.h" |
30 #include "media/base/video_renderer_sink.h" | 31 #include "media/base/video_renderer_sink.h" |
31 #include "media/renderers/gpu_video_accelerator_factories.h" | 32 #include "media/renderers/gpu_video_accelerator_factories.h" |
32 #include "ui/gfx/geometry/size.h" | 33 #include "ui/gfx/geometry/size.h" |
33 | 34 |
34 namespace chromecast { | 35 namespace chromecast { |
35 namespace media { | 36 namespace media { |
36 | 37 |
37 namespace { | 38 namespace { |
38 | 39 |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
79 base::ResetAndReturn(&init_cb_).Run(::media::PIPELINE_ERROR_ABORT); | 80 base::ResetAndReturn(&init_cb_).Run(::media::PIPELINE_ERROR_ABORT); |
80 else if (!flush_cb_.is_null()) | 81 else if (!flush_cb_.is_null()) |
81 base::ResetAndReturn(&flush_cb_).Run(); | 82 base::ResetAndReturn(&flush_cb_).Run(); |
82 | 83 |
83 if (has_audio_ || has_video_) | 84 if (has_audio_ || has_video_) |
84 media_pipeline_->Stop(); | 85 media_pipeline_->Stop(); |
85 } | 86 } |
86 | 87 |
87 void CmaRenderer::Initialize( | 88 void CmaRenderer::Initialize( |
88 ::media::DemuxerStreamProvider* demuxer_stream_provider, | 89 ::media::DemuxerStreamProvider* demuxer_stream_provider, |
89 const ::media::PipelineStatusCB& init_cb, | 90 ::media::RendererClient* client, |
90 const ::media::StatisticsCB& statistics_cb, | 91 const ::media::PipelineStatusCB& init_cb) { |
91 const ::media::BufferingStateCB& buffering_state_cb, | |
92 const base::Closure& ended_cb, | |
93 const ::media::PipelineStatusCB& error_cb, | |
94 const base::Closure& waiting_for_decryption_key_cb) { | |
95 CMALOG(kLogControl) << __FUNCTION__; | 92 CMALOG(kLogControl) << __FUNCTION__; |
96 DCHECK(thread_checker_.CalledOnValidThread()); | 93 DCHECK(thread_checker_.CalledOnValidThread()); |
97 DCHECK_EQ(state_, kUninitialized) << state_; | 94 DCHECK_EQ(state_, kUninitialized) << state_; |
98 DCHECK(!init_cb.is_null()); | 95 DCHECK(!init_cb.is_null()); |
99 DCHECK(!statistics_cb.is_null()); | |
100 DCHECK(!ended_cb.is_null()); | |
101 DCHECK(!error_cb.is_null()); | |
102 DCHECK(!buffering_state_cb.is_null()); | |
103 DCHECK(!waiting_for_decryption_key_cb.is_null()); | |
104 DCHECK(demuxer_stream_provider->GetStream(::media::DemuxerStream::AUDIO) || | 96 DCHECK(demuxer_stream_provider->GetStream(::media::DemuxerStream::AUDIO) || |
105 demuxer_stream_provider->GetStream(::media::DemuxerStream::VIDEO)); | 97 demuxer_stream_provider->GetStream(::media::DemuxerStream::VIDEO)); |
106 | 98 |
107 // Deferred from ctor so as to initialise on correct thread. | 99 // Deferred from ctor so as to initialise on correct thread. |
108 hole_frame_factory_.reset(new HoleFrameFactory(gpu_factories_)); | 100 hole_frame_factory_.reset(new HoleFrameFactory(gpu_factories_)); |
109 | 101 |
110 BeginStateTransition(); | 102 BeginStateTransition(); |
111 | 103 |
112 demuxer_stream_provider_ = demuxer_stream_provider; | 104 demuxer_stream_provider_ = demuxer_stream_provider; |
113 statistics_cb_ = statistics_cb; | 105 client_ = client; |
114 buffering_state_cb_ = buffering_state_cb; | |
115 ended_cb_ = ended_cb; | |
116 error_cb_ = error_cb; | |
117 waiting_for_decryption_key_cb_ = waiting_for_decryption_key_cb; | |
118 | 106 |
119 MediaPipelineClient media_pipeline_client; | 107 MediaPipelineClient media_pipeline_client; |
120 media_pipeline_client.error_cb = ::media::BindToCurrentLoop(error_cb_); | 108 media_pipeline_client.error_cb = |
| 109 ::media::BindToCurrentLoop(base::Bind(&CmaRenderer::OnError, weak_this_)); |
121 media_pipeline_client.buffering_state_cb = ::media::BindToCurrentLoop( | 110 media_pipeline_client.buffering_state_cb = ::media::BindToCurrentLoop( |
122 base::Bind(&CmaRenderer::OnBufferingNotification, weak_this_)); | 111 base::Bind(&CmaRenderer::OnBufferingNotification, weak_this_)); |
123 media_pipeline_client.time_update_cb = ::media::BindToCurrentLoop( | 112 media_pipeline_client.time_update_cb = ::media::BindToCurrentLoop( |
124 base::Bind(&CmaRenderer::OnPlaybackTimeUpdated, weak_this_)); | 113 base::Bind(&CmaRenderer::OnPlaybackTimeUpdated, weak_this_)); |
125 media_pipeline_client.pipeline_backend_created_cb = | 114 media_pipeline_client.pipeline_backend_created_cb = |
126 base::Bind(&MediaPipelineClientDummyCallback); | 115 base::Bind(&MediaPipelineClientDummyCallback); |
127 media_pipeline_client.pipeline_backend_destroyed_cb = | 116 media_pipeline_client.pipeline_backend_destroyed_cb = |
128 base::Bind(&MediaPipelineClientDummyCallback); | 117 base::Bind(&MediaPipelineClientDummyCallback); |
129 media_pipeline_->SetClient(media_pipeline_client); | 118 media_pipeline_->SetClient(media_pipeline_client); |
130 | 119 |
(...skipping 23 matching lines...) Expand all Loading... |
154 time_interpolator_->StopInterpolating(); | 143 time_interpolator_->StopInterpolating(); |
155 } | 144 } |
156 } | 145 } |
157 | 146 |
158 void CmaRenderer::StartPlayingFrom(base::TimeDelta time) { | 147 void CmaRenderer::StartPlayingFrom(base::TimeDelta time) { |
159 CMALOG(kLogControl) << __FUNCTION__ << ": " << time.InMilliseconds(); | 148 CMALOG(kLogControl) << __FUNCTION__ << ": " << time.InMilliseconds(); |
160 DCHECK(thread_checker_.CalledOnValidThread()); | 149 DCHECK(thread_checker_.CalledOnValidThread()); |
161 BeginStateTransition(); | 150 BeginStateTransition(); |
162 | 151 |
163 if (state_ == kError) { | 152 if (state_ == kError) { |
164 error_cb_.Run(::media::PIPELINE_ERROR_ABORT); | 153 client_->OnError(::media::PIPELINE_ERROR_ABORT); |
165 CompleteStateTransition(kError); | 154 CompleteStateTransition(kError); |
166 return; | 155 return; |
167 } | 156 } |
168 | 157 |
169 // Create a video hole frame just before starting playback. | 158 // Create a video hole frame just before starting playback. |
170 // Note that instead of creating the video hole frame in Initialize(), we do | 159 // Note that instead of creating the video hole frame in Initialize(), we do |
171 // it here because paint_cb_ (which eventually calls OnOpacityChanged) | 160 // it here because paint_cb_ (which eventually calls OnOpacityChanged) |
172 // expects the current state to not be HaveNothing. And the place where | 161 // expects the current state to not be HaveNothing. And the place where |
173 // the ready state is changed to HaveMetadata (OnPipelineMetadata) is | 162 // the ready state is changed to HaveMetadata (OnPipelineMetadata) is |
174 // right before the pipeline calls StartPlayingFrom (in | 163 // right before the pipeline calls StartPlayingFrom (in |
(...skipping 190 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
365 base::ResetAndReturn(&init_cb_).Run(status); | 354 base::ResetAndReturn(&init_cb_).Run(status); |
366 return; | 355 return; |
367 } | 356 } |
368 | 357 |
369 has_video_ = video_stream_present; | 358 has_video_ = video_stream_present; |
370 CompleteStateTransition(kFlushed); | 359 CompleteStateTransition(kFlushed); |
371 base::ResetAndReturn(&init_cb_).Run(::media::PIPELINE_OK); | 360 base::ResetAndReturn(&init_cb_).Run(::media::PIPELINE_OK); |
372 } | 361 } |
373 | 362 |
374 void CmaRenderer::OnWaitForKey(bool is_audio) { | 363 void CmaRenderer::OnWaitForKey(bool is_audio) { |
375 waiting_for_decryption_key_cb_.Run(); | 364 client_->OnWaitingForDecryptionKey(); |
376 } | 365 } |
377 | 366 |
378 void CmaRenderer::OnEosReached(bool is_audio) { | 367 void CmaRenderer::OnEosReached(bool is_audio) { |
379 DCHECK(thread_checker_.CalledOnValidThread()); | 368 DCHECK(thread_checker_.CalledOnValidThread()); |
380 if (state_ != kPlaying) { | 369 if (state_ != kPlaying) { |
381 LOG(WARNING) << __FUNCTION__ << " Ignoring a late EOS event"; | 370 LOG(WARNING) << __FUNCTION__ << " Ignoring a late EOS event"; |
382 return; | 371 return; |
383 } | 372 } |
384 | 373 |
385 if (is_audio) { | 374 if (is_audio) { |
386 DCHECK(!received_audio_eos_); | 375 DCHECK(!received_audio_eos_); |
387 received_audio_eos_ = true; | 376 received_audio_eos_ = true; |
388 } else { | 377 } else { |
389 DCHECK(!received_video_eos_); | 378 DCHECK(!received_video_eos_); |
390 received_video_eos_ = true; | 379 received_video_eos_ = true; |
391 } | 380 } |
392 | 381 |
393 bool audio_finished = !has_audio_ || received_audio_eos_; | 382 bool audio_finished = !has_audio_ || received_audio_eos_; |
394 bool video_finished = !has_video_ || received_video_eos_; | 383 bool video_finished = !has_video_ || received_video_eos_; |
395 CMALOG(kLogControl) << __FUNCTION__ << " audio_finished=" << audio_finished | 384 CMALOG(kLogControl) << __FUNCTION__ << " audio_finished=" << audio_finished |
396 << " video_finished=" << video_finished; | 385 << " video_finished=" << video_finished; |
397 if (audio_finished && video_finished) | 386 if (audio_finished && video_finished) |
398 ended_cb_.Run(); | 387 client_->OnEnded(); |
399 } | 388 } |
400 | 389 |
401 void CmaRenderer::OnStatisticsUpdated( | 390 void CmaRenderer::OnStatisticsUpdated( |
402 const ::media::PipelineStatistics& stats) { | 391 const ::media::PipelineStatistics& stats) { |
403 DCHECK(thread_checker_.CalledOnValidThread()); | 392 DCHECK(thread_checker_.CalledOnValidThread()); |
404 statistics_cb_.Run(stats); | 393 client_->OnStatisticsUpdate(stats); |
405 } | 394 } |
406 | 395 |
407 void CmaRenderer::OnNaturalSizeChanged(const gfx::Size& size) { | 396 void CmaRenderer::OnNaturalSizeChanged(const gfx::Size& size) { |
408 DCHECK(thread_checker_.CalledOnValidThread()); | 397 DCHECK(thread_checker_.CalledOnValidThread()); |
409 video_renderer_sink_->PaintFrameUsingOldRenderingPath( | 398 video_renderer_sink_->PaintFrameUsingOldRenderingPath( |
410 hole_frame_factory_->CreateHoleFrame(size)); | 399 hole_frame_factory_->CreateHoleFrame(size)); |
411 } | 400 } |
412 | 401 |
413 void CmaRenderer::OnPlaybackTimeUpdated(base::TimeDelta time, | 402 void CmaRenderer::OnPlaybackTimeUpdated(base::TimeDelta time, |
414 base::TimeDelta max_time, | 403 base::TimeDelta max_time, |
(...skipping 11 matching lines...) Expand all Loading... |
426 std::min(max_time, time + base::TimeTicks::Now() - capture_time); | 415 std::min(max_time, time + base::TimeTicks::Now() - capture_time); |
427 | 416 |
428 base::AutoLock auto_lock(time_interpolator_lock_); | 417 base::AutoLock auto_lock(time_interpolator_lock_); |
429 time_interpolator_->SetBounds(lower_bound, max_time); | 418 time_interpolator_->SetBounds(lower_bound, max_time); |
430 } | 419 } |
431 | 420 |
432 void CmaRenderer::OnBufferingNotification( | 421 void CmaRenderer::OnBufferingNotification( |
433 ::media::BufferingState buffering_state) { | 422 ::media::BufferingState buffering_state) { |
434 CMALOG(kLogControl) << __FUNCTION__ << ": state=" << state_ | 423 CMALOG(kLogControl) << __FUNCTION__ << ": state=" << state_ |
435 << ", buffering=" << buffering_state; | 424 << ", buffering=" << buffering_state; |
436 buffering_state_cb_.Run(buffering_state); | 425 DCHECK(thread_checker_.CalledOnValidThread()); |
| 426 client_->OnBufferingStateChange(buffering_state); |
437 } | 427 } |
438 | 428 |
439 void CmaRenderer::OnFlushDone() { | 429 void CmaRenderer::OnFlushDone() { |
440 DCHECK(thread_checker_.CalledOnValidThread()); | 430 DCHECK(thread_checker_.CalledOnValidThread()); |
441 | 431 |
442 if (state_ == kError) { | 432 if (state_ == kError) { |
443 // If OnError was called while the flush was in progress, | 433 // If OnError was called while the flush was in progress, |
444 // |flush_cb_| must be null. | 434 // |flush_cb_| must be null. |
445 DCHECK(flush_cb_.is_null()); | 435 DCHECK(flush_cb_.is_null()); |
446 return; | 436 return; |
447 } | 437 } |
448 | 438 |
449 CompleteStateTransition(kFlushed); | 439 CompleteStateTransition(kFlushed); |
450 base::ResetAndReturn(&flush_cb_).Run(); | 440 base::ResetAndReturn(&flush_cb_).Run(); |
451 } | 441 } |
452 | 442 |
453 void CmaRenderer::OnError(::media::PipelineStatus error) { | 443 void CmaRenderer::OnError(::media::PipelineStatus error) { |
454 DCHECK(thread_checker_.CalledOnValidThread()); | 444 DCHECK(thread_checker_.CalledOnValidThread()); |
455 DCHECK_NE(::media::PIPELINE_OK, error) << "PIPELINE_OK isn't an error!"; | 445 DCHECK_NE(::media::PIPELINE_OK, error) << "PIPELINE_OK isn't an error!"; |
456 LOG(ERROR) << "CMA error encountered: " << error; | 446 LOG(ERROR) << "CMA error encountered: " << error; |
457 | 447 |
458 State old_state = state_; | 448 State old_state = state_; |
459 CompleteStateTransition(kError); | 449 CompleteStateTransition(kError); |
460 | 450 |
461 if (old_state != kError) { | 451 if (old_state != kError) { |
462 if (!init_cb_.is_null()) { | 452 if (!init_cb_.is_null()) { |
463 base::ResetAndReturn(&init_cb_).Run(error); | 453 base::ResetAndReturn(&init_cb_).Run(error); |
464 return; | 454 return; |
465 } | 455 } |
466 error_cb_.Run(error); | 456 client_->OnError(error); |
467 } | 457 } |
468 | 458 |
469 // After OnError() returns, the pipeline may destroy |this|. | 459 // After OnError() returns, the pipeline may destroy |this|. |
470 if (!flush_cb_.is_null()) | 460 if (!flush_cb_.is_null()) |
471 base::ResetAndReturn(&flush_cb_).Run(); | 461 base::ResetAndReturn(&flush_cb_).Run(); |
472 } | 462 } |
473 | 463 |
474 void CmaRenderer::BeginStateTransition() { | 464 void CmaRenderer::BeginStateTransition() { |
475 DCHECK(!is_pending_transition_) << state_; | 465 DCHECK(!is_pending_transition_) << state_; |
476 is_pending_transition_ = true; | 466 is_pending_transition_ = true; |
477 } | 467 } |
478 | 468 |
479 void CmaRenderer::CompleteStateTransition(State new_state) { | 469 void CmaRenderer::CompleteStateTransition(State new_state) { |
480 state_ = new_state; | 470 state_ = new_state; |
481 is_pending_transition_ = false; | 471 is_pending_transition_ = false; |
482 } | 472 } |
483 | 473 |
484 } // namespace media | 474 } // namespace media |
485 } // namespace chromecast | 475 } // namespace chromecast |
OLD | NEW |