| 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/media/cma/pipeline/av_pipeline_impl.h" | 5 #include "chromecast/media/cma/pipeline/av_pipeline_impl.h" |
| 6 | 6 |
| 7 #include "base/bind.h" | 7 #include "base/bind.h" |
| 8 #include "base/location.h" | 8 #include "base/location.h" |
| 9 #include "base/single_thread_task_runner.h" | 9 #include "base/single_thread_task_runner.h" |
| 10 #include "base/strings/string_number_conversions.h" | 10 #include "base/strings/string_number_conversions.h" |
| 11 #include "base/thread_task_runner_handle.h" | 11 #include "base/thread_task_runner_handle.h" |
| 12 #include "chromecast/media/base/decrypt_context_impl.h" | 12 #include "chromecast/media/base/decrypt_context_impl.h" |
| 13 #include "chromecast/media/cdm/browser_cdm_cast.h" | 13 #include "chromecast/media/cdm/browser_cdm_cast.h" |
| 14 #include "chromecast/media/cma/base/buffering_frame_provider.h" | 14 #include "chromecast/media/cma/base/buffering_frame_provider.h" |
| 15 #include "chromecast/media/cma/base/buffering_state.h" | 15 #include "chromecast/media/cma/base/buffering_state.h" |
| 16 #include "chromecast/media/cma/base/cast_decoder_buffer_impl.h" | 16 #include "chromecast/media/cma/base/cast_decoder_buffer_impl.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/coded_frame_provider.h" | 18 #include "chromecast/media/cma/base/coded_frame_provider.h" |
| 19 #include "chromecast/media/cma/base/decoder_buffer_base.h" | 19 #include "chromecast/media/cma/base/decoder_buffer_base.h" |
| 20 #include "chromecast/media/cma/pipeline/decrypt_util.h" | 20 #include "chromecast/media/cma/pipeline/decrypt_util.h" |
| 21 #include "chromecast/media/cma/pipeline/frame_status_cb_impl.h" | |
| 22 #include "chromecast/media/cma/pipeline/media_component_device_client_impl.h" | |
| 23 #include "chromecast/public/media/cast_decrypt_config.h" | 21 #include "chromecast/public/media/cast_decrypt_config.h" |
| 24 #include "chromecast/public/media/media_clock_device.h" | |
| 25 #include "chromecast/public/media/media_component_device.h" | |
| 26 #include "media/base/audio_decoder_config.h" | 22 #include "media/base/audio_decoder_config.h" |
| 27 #include "media/base/bind_to_current_loop.h" | 23 #include "media/base/bind_to_current_loop.h" |
| 28 #include "media/base/decrypt_config.h" | 24 #include "media/base/decrypt_config.h" |
| 29 #include "media/base/timestamp_constants.h" | 25 #include "media/base/timestamp_constants.h" |
| 30 | 26 |
| 31 namespace chromecast { | 27 namespace chromecast { |
| 32 namespace media { | 28 namespace media { |
| 33 | 29 |
| 34 namespace { | 30 namespace { |
| 35 | 31 |
| 36 const int kNoCallbackId = -1; | 32 const int kNoCallbackId = -1; |
| 37 | 33 |
| 38 } // namespace | 34 } // namespace |
| 39 | 35 |
| 40 AvPipelineImpl::AvPipelineImpl(MediaComponentDevice* media_component_device, | 36 AvPipelineImpl::AvPipelineImpl(MediaPipelineBackend::Decoder* decoder, |
| 41 const UpdateConfigCB& update_config_cb) | 37 const UpdateConfigCB& update_config_cb) |
| 42 : update_config_cb_(update_config_cb), | 38 : update_config_cb_(update_config_cb), |
| 43 media_component_device_(media_component_device), | 39 decoder_(decoder), |
| 44 state_(kUninitialized), | 40 state_(kUninitialized), |
| 45 buffered_time_(::media::kNoTimestamp()), | 41 buffered_time_(::media::kNoTimestamp()), |
| 46 playable_buffered_time_(::media::kNoTimestamp()), | 42 playable_buffered_time_(::media::kNoTimestamp()), |
| 47 enable_feeding_(false), | 43 enable_feeding_(false), |
| 48 pending_read_(false), | 44 pending_read_(false), |
| 49 pending_push_(false), | |
| 50 enable_time_update_(false), | 45 enable_time_update_(false), |
| 51 pending_time_update_task_(false), | 46 pending_time_update_task_(false), |
| 52 media_keys_(NULL), | 47 media_keys_(NULL), |
| 53 media_keys_callback_id_(kNoCallbackId), | 48 media_keys_callback_id_(kNoCallbackId), |
| 54 weak_factory_(this) { | 49 weak_factory_(this) { |
| 55 DCHECK(media_component_device); | 50 DCHECK(decoder_); |
| 56 weak_this_ = weak_factory_.GetWeakPtr(); | 51 weak_this_ = weak_factory_.GetWeakPtr(); |
| 57 thread_checker_.DetachFromThread(); | 52 thread_checker_.DetachFromThread(); |
| 58 } | 53 } |
| 59 | 54 |
| 60 AvPipelineImpl::~AvPipelineImpl() { | 55 AvPipelineImpl::~AvPipelineImpl() { |
| 61 DCHECK(thread_checker_.CalledOnValidThread()); | 56 DCHECK(thread_checker_.CalledOnValidThread()); |
| 62 media_component_device_->SetClient(nullptr); | |
| 63 | 57 |
| 64 if (media_keys_ && media_keys_callback_id_ != kNoCallbackId) | 58 if (media_keys_ && media_keys_callback_id_ != kNoCallbackId) |
| 65 media_keys_->UnregisterPlayer(media_keys_callback_id_); | 59 media_keys_->UnregisterPlayer(media_keys_callback_id_); |
| 66 } | 60 } |
| 67 | 61 |
| 68 void AvPipelineImpl::TransitionToState(State state) { | 62 void AvPipelineImpl::TransitionToState(State state) { |
| 69 DCHECK(thread_checker_.CalledOnValidThread()); | 63 DCHECK(thread_checker_.CalledOnValidThread()); |
| 70 state_ = state; | 64 state_ = state; |
| 71 } | 65 } |
| 72 | 66 |
| 73 void AvPipelineImpl::SetCodedFrameProvider( | 67 void AvPipelineImpl::SetCodedFrameProvider( |
| 74 scoped_ptr<CodedFrameProvider> frame_provider, | 68 scoped_ptr<CodedFrameProvider> frame_provider, |
| 75 size_t max_buffer_size, | 69 size_t max_buffer_size, |
| 76 size_t max_frame_size) { | 70 size_t max_frame_size) { |
| 77 DCHECK_EQ(state_, kUninitialized); | 71 DCHECK_EQ(state_, kUninitialized); |
| 78 DCHECK(frame_provider); | 72 DCHECK(frame_provider); |
| 79 | 73 |
| 80 // Wrap the incoming frame provider to add some buffering capabilities. | 74 // Wrap the incoming frame provider to add some buffering capabilities. |
| 81 frame_provider_.reset( | 75 frame_provider_.reset( |
| 82 new BufferingFrameProvider( | 76 new BufferingFrameProvider( |
| 83 frame_provider.Pass(), | 77 frame_provider.Pass(), |
| 84 max_buffer_size, | 78 max_buffer_size, |
| 85 max_frame_size, | 79 max_frame_size, |
| 86 base::Bind(&AvPipelineImpl::OnFrameBuffered, weak_this_))); | 80 base::Bind(&AvPipelineImpl::OnFrameBuffered, weak_this_))); |
| 87 } | 81 } |
| 88 | 82 |
| 89 void AvPipelineImpl::SetClient(const AvPipelineClient& client) { | |
| 90 DCHECK(thread_checker_.CalledOnValidThread()); | |
| 91 DCHECK_EQ(state_, kUninitialized); | |
| 92 client_ = client; | |
| 93 } | |
| 94 | |
| 95 bool AvPipelineImpl::Initialize() { | |
| 96 DCHECK(thread_checker_.CalledOnValidThread()); | |
| 97 DCHECK_EQ(state_, kUninitialized); | |
| 98 | |
| 99 media_component_device_->SetClient(new MediaComponentDeviceClientImpl( | |
| 100 base::Bind(&AvPipelineImpl::OnEos, weak_this_))); | |
| 101 if (!media_component_device_->SetState(MediaComponentDevice::kStateIdle)) | |
| 102 return false; | |
| 103 | |
| 104 return true; | |
| 105 } | |
| 106 | |
| 107 bool AvPipelineImpl::StartPlayingFrom( | 83 bool AvPipelineImpl::StartPlayingFrom( |
| 108 base::TimeDelta time, | 84 base::TimeDelta time, |
| 109 const scoped_refptr<BufferingState>& buffering_state) { | 85 const scoped_refptr<BufferingState>& buffering_state) { |
| 110 DCHECK(thread_checker_.CalledOnValidThread()); | 86 DCHECK(thread_checker_.CalledOnValidThread()); |
| 111 DCHECK_EQ(state_, kFlushed); | 87 DCHECK_EQ(state_, kFlushed); |
| 112 | 88 |
| 113 // Media time where rendering should start | |
| 114 // and switch to a state where the audio device accepts incoming buffers. | |
| 115 if (!media_component_device_->SetStartPts(time.InMicroseconds()) || | |
| 116 !media_component_device_->SetState(MediaComponentDevice::kStatePaused)) { | |
| 117 return false; | |
| 118 } | |
| 119 | |
| 120 // Buffering related initialization. | 89 // Buffering related initialization. |
| 121 DCHECK(frame_provider_); | 90 DCHECK(frame_provider_); |
| 122 buffering_state_ = buffering_state; | 91 buffering_state_ = buffering_state; |
| 123 if (buffering_state_.get()) | 92 if (buffering_state_.get()) |
| 124 buffering_state_->SetMediaTime(time); | 93 buffering_state_->SetMediaTime(time); |
| 125 | 94 |
| 126 if (!media_component_device_->SetState(MediaComponentDevice::kStateRunning)) | |
| 127 return false; | |
| 128 | |
| 129 // Start feeding the pipeline. | 95 // Start feeding the pipeline. |
| 130 enable_feeding_ = true; | 96 enable_feeding_ = true; |
| 131 base::ThreadTaskRunnerHandle::Get()->PostTask( | 97 base::ThreadTaskRunnerHandle::Get()->PostTask( |
| 132 FROM_HERE, base::Bind(&AvPipelineImpl::FetchBufferIfNeeded, weak_this_)); | 98 FROM_HERE, base::Bind(&AvPipelineImpl::FetchBufferIfNeeded, weak_this_)); |
| 133 | 99 |
| 134 return true; | 100 return true; |
| 135 } | 101 } |
| 136 | 102 |
| 137 void AvPipelineImpl::Flush(const base::Closure& done_cb) { | 103 void AvPipelineImpl::Flush(const base::Closure& done_cb) { |
| 138 DCHECK(thread_checker_.CalledOnValidThread()); | 104 DCHECK(thread_checker_.CalledOnValidThread()); |
| 139 DCHECK_EQ(state_, kFlushing); | 105 DCHECK_EQ(state_, kFlushing); |
| 140 DCHECK_EQ( | 106 |
| 141 media_component_device_->GetState(), MediaComponentDevice::kStateRunning); | |
| 142 // Note: returning to idle state aborts any pending frame push. | 107 // Note: returning to idle state aborts any pending frame push. |
| 143 media_component_device_->SetState(MediaComponentDevice::kStateIdle); | 108 pushed_buffer_.reset(); |
| 144 pending_push_ = false; | |
| 145 | 109 |
| 146 // Break the feeding loop. | 110 // Break the feeding loop. |
| 147 enable_feeding_ = false; | 111 enable_feeding_ = false; |
| 148 | 112 |
| 149 // Remove any pending buffer. | 113 // Remove any pending buffer. |
| 150 pending_buffer_ = scoped_refptr<DecoderBufferBase>(); | 114 pending_buffer_ = scoped_refptr<DecoderBufferBase>(); |
| 151 | 115 |
| 152 // Finally, remove any frames left in the frame provider. | 116 // Finally, remove any frames left in the frame provider. |
| 153 pending_read_ = false; | 117 pending_read_ = false; |
| 154 buffered_time_ = ::media::kNoTimestamp(); | 118 buffered_time_ = ::media::kNoTimestamp(); |
| 155 playable_buffered_time_ = ::media::kNoTimestamp(); | 119 playable_buffered_time_ = ::media::kNoTimestamp(); |
| 156 non_playable_frames_.clear(); | 120 non_playable_frames_.clear(); |
| 157 frame_provider_->Flush(done_cb); | 121 frame_provider_->Flush(done_cb); |
| 158 } | 122 } |
| 159 | 123 |
| 160 void AvPipelineImpl::Stop() { | 124 void AvPipelineImpl::Stop() { |
| 161 DCHECK(thread_checker_.CalledOnValidThread()); | 125 DCHECK(thread_checker_.CalledOnValidThread()); |
| 162 | 126 |
| 163 // Stop can be called from any state. | 127 // Stop can be called from any state. |
| 164 if (state_ == kUninitialized || state_ == kStopped) | 128 if (state_ == kUninitialized || state_ == kStopped) |
| 165 return; | 129 return; |
| 166 | 130 |
| 167 // Stop feeding the pipeline. | 131 // Stop feeding the pipeline. |
| 168 enable_feeding_ = false; | 132 enable_feeding_ = false; |
| 169 | |
| 170 // Release hardware resources on Stop. | |
| 171 if (media_component_device_->GetState() == | |
| 172 MediaComponentDevice::kStatePaused || | |
| 173 media_component_device_->GetState() == | |
| 174 MediaComponentDevice::kStateRunning) { | |
| 175 media_component_device_->SetState(MediaComponentDevice::kStateIdle); | |
| 176 } | |
| 177 if (media_component_device_->GetState() == MediaComponentDevice::kStateIdle) { | |
| 178 media_component_device_->SetState( | |
| 179 MediaComponentDevice::kStateUninitialized); | |
| 180 } | |
| 181 } | 133 } |
| 182 | 134 |
| 183 void AvPipelineImpl::SetCdm(BrowserCdmCast* media_keys) { | 135 void AvPipelineImpl::SetCdm(BrowserCdmCast* media_keys) { |
| 184 DCHECK(thread_checker_.CalledOnValidThread()); | 136 DCHECK(thread_checker_.CalledOnValidThread()); |
| 185 DCHECK(media_keys); | 137 DCHECK(media_keys); |
| 186 | 138 |
| 187 if (media_keys_ && media_keys_callback_id_ != kNoCallbackId) | 139 if (media_keys_ && media_keys_callback_id_ != kNoCallbackId) |
| 188 media_keys_->UnregisterPlayer(media_keys_callback_id_); | 140 media_keys_->UnregisterPlayer(media_keys_callback_id_); |
| 189 | 141 |
| 190 media_keys_ = media_keys; | 142 media_keys_ = media_keys; |
| 191 media_keys_callback_id_ = media_keys_->RegisterPlayer( | 143 media_keys_callback_id_ = media_keys_->RegisterPlayer( |
| 192 base::Bind(&AvPipelineImpl::OnCdmStateChanged, weak_this_), | 144 base::Bind(&AvPipelineImpl::OnCdmStateChanged, weak_this_), |
| 193 base::Bind(&AvPipelineImpl::OnCdmDestroyed, weak_this_)); | 145 base::Bind(&AvPipelineImpl::OnCdmDestroyed, weak_this_)); |
| 194 } | 146 } |
| 195 | 147 |
| 196 void AvPipelineImpl::OnEos() { | |
| 197 DCHECK(thread_checker_.CalledOnValidThread()); | |
| 198 CMALOG(kLogControl) << __FUNCTION__; | |
| 199 if (state_ != kPlaying) | |
| 200 return; | |
| 201 | |
| 202 if (!client_.eos_cb.is_null()) | |
| 203 client_.eos_cb.Run(); | |
| 204 } | |
| 205 | |
| 206 void AvPipelineImpl::FetchBufferIfNeeded() { | 148 void AvPipelineImpl::FetchBufferIfNeeded() { |
| 207 DCHECK(thread_checker_.CalledOnValidThread()); | 149 DCHECK(thread_checker_.CalledOnValidThread()); |
| 208 if (!enable_feeding_) | 150 if (!enable_feeding_) |
| 209 return; | 151 return; |
| 210 | 152 |
| 211 if (pending_read_ || pending_buffer_.get()) | 153 if (pending_read_ || pending_buffer_.get()) |
| 212 return; | 154 return; |
| 213 | 155 |
| 214 pending_read_ = true; | 156 pending_read_ = true; |
| 215 frame_provider_->Read( | 157 frame_provider_->Read( |
| (...skipping 22 matching lines...) Expand all Loading... |
| 238 return; | 180 return; |
| 239 | 181 |
| 240 // Initiate a read if there isn't already one. | 182 // Initiate a read if there isn't already one. |
| 241 if (!pending_buffer_.get() && !pending_read_) { | 183 if (!pending_buffer_.get() && !pending_read_) { |
| 242 base::ThreadTaskRunnerHandle::Get()->PostTask( | 184 base::ThreadTaskRunnerHandle::Get()->PostTask( |
| 243 FROM_HERE, | 185 FROM_HERE, |
| 244 base::Bind(&AvPipelineImpl::FetchBufferIfNeeded, weak_this_)); | 186 base::Bind(&AvPipelineImpl::FetchBufferIfNeeded, weak_this_)); |
| 245 return; | 187 return; |
| 246 } | 188 } |
| 247 | 189 |
| 248 if (!pending_buffer_.get() || pending_push_) | 190 if (!pending_buffer_.get() || pushed_buffer_) |
| 249 return; | 191 return; |
| 250 | 192 |
| 251 // Break the feeding loop when the end of stream is reached. | 193 // Break the feeding loop when the end of stream is reached. |
| 252 if (pending_buffer_->end_of_stream()) { | 194 if (pending_buffer_->end_of_stream()) { |
| 253 CMALOG(kLogControl) << __FUNCTION__ << ": EOS reached, stopped feeding"; | 195 CMALOG(kLogControl) << __FUNCTION__ << ": EOS reached, stopped feeding"; |
| 254 enable_feeding_ = false; | 196 enable_feeding_ = false; |
| 255 } | 197 } |
| 256 | 198 |
| 257 scoped_ptr<DecryptContextImpl> decrypt_context; | 199 scoped_ptr<DecryptContextImpl> decrypt_context; |
| 258 if (!pending_buffer_->end_of_stream() && | 200 if (!pending_buffer_->end_of_stream() && |
| (...skipping 23 matching lines...) Expand all Loading... |
| 282 decrypt_context.reset(); | 224 decrypt_context.reset(); |
| 283 } | 225 } |
| 284 } | 226 } |
| 285 | 227 |
| 286 if (!pending_buffer_->end_of_stream() && buffering_state_.get()) { | 228 if (!pending_buffer_->end_of_stream() && buffering_state_.get()) { |
| 287 base::TimeDelta timestamp = pending_buffer_->timestamp(); | 229 base::TimeDelta timestamp = pending_buffer_->timestamp(); |
| 288 if (timestamp != ::media::kNoTimestamp()) | 230 if (timestamp != ::media::kNoTimestamp()) |
| 289 buffering_state_->SetMaxRenderingTime(timestamp); | 231 buffering_state_->SetMaxRenderingTime(timestamp); |
| 290 } | 232 } |
| 291 | 233 |
| 292 MediaComponentDevice::FrameStatus status = media_component_device_->PushFrame( | 234 DCHECK(!pushed_buffer_); |
| 293 decrypt_context.release(), new CastDecoderBufferImpl(pending_buffer_), | 235 pushed_buffer_.reset(new CastDecoderBufferImpl(pending_buffer_)); |
| 294 new FrameStatusCBImpl( | 236 MediaPipelineBackend::BufferStatus status = |
| 295 base::Bind(&AvPipelineImpl::OnFramePushed, weak_this_))); | 237 decoder_->PushBuffer(decrypt_context.release(), pushed_buffer_.get()); |
| 296 pending_buffer_ = scoped_refptr<DecoderBufferBase>(); | 238 pending_buffer_ = scoped_refptr<DecoderBufferBase>(); |
| 297 | 239 |
| 298 pending_push_ = (status == MediaComponentDevice::kFramePending); | 240 if (status != MediaPipelineBackend::kBufferPending) |
| 299 if (!pending_push_) | 241 OnBufferPushed(status); |
| 300 OnFramePushed(status); | |
| 301 } | 242 } |
| 302 | 243 |
| 303 void AvPipelineImpl::OnFramePushed(MediaComponentDevice::FrameStatus status) { | 244 void AvPipelineImpl::OnBufferPushed(MediaPipelineBackend::BufferStatus status) { |
| 304 DCHECK(thread_checker_.CalledOnValidThread()); | 245 DCHECK(thread_checker_.CalledOnValidThread()); |
| 305 pending_push_ = false; | 246 pushed_buffer_.reset(); |
| 306 if (status == MediaComponentDevice::kFrameFailed) { | 247 if (status == MediaPipelineBackend::kBufferFailed) { |
| 307 LOG(WARNING) << "AvPipelineImpl: PushFrame failed"; | 248 LOG(WARNING) << "AvPipelineImpl: PushFrame failed"; |
| 308 enable_feeding_ = false; | 249 enable_feeding_ = false; |
| 309 state_ = kError; | 250 state_ = kError; |
| 310 return; | 251 return; |
| 311 } | 252 } |
| 312 base::ThreadTaskRunnerHandle::Get()->PostTask( | 253 base::ThreadTaskRunnerHandle::Get()->PostTask( |
| 313 FROM_HERE, base::Bind(&AvPipelineImpl::ProcessPendingBuffer, weak_this_)); | 254 FROM_HERE, base::Bind(&AvPipelineImpl::ProcessPendingBuffer, weak_this_)); |
| 314 } | 255 } |
| 315 | 256 |
| 316 void AvPipelineImpl::OnCdmStateChanged() { | 257 void AvPipelineImpl::OnCdmStateChanged() { |
| (...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 378 } | 319 } |
| 379 } | 320 } |
| 380 | 321 |
| 381 // The frame is playable: remove it from the list of non playable frames. | 322 // The frame is playable: remove it from the list of non playable frames. |
| 382 non_playable_frames_.pop_front(); | 323 non_playable_frames_.pop_front(); |
| 383 } | 324 } |
| 384 } | 325 } |
| 385 | 326 |
| 386 } // namespace media | 327 } // namespace media |
| 387 } // namespace chromecast | 328 } // namespace chromecast |
| OLD | NEW |