| 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 |