Chromium Code Reviews| 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/base/time_conversions.h" | |
| 12 #include "chromecast/media/base/decrypt_context.h" | 13 #include "chromecast/media/base/decrypt_context.h" |
| 13 #include "chromecast/media/cdm/browser_cdm_cast.h" | 14 #include "chromecast/media/cdm/browser_cdm_cast.h" |
| 14 #include "chromecast/media/cma/backend/media_clock_device.h" | 15 #include "chromecast/media/cma/base/backend_client_callbacks.h" |
| 15 #include "chromecast/media/cma/backend/media_component_device.h" | |
| 16 #include "chromecast/media/cma/base/buffering_frame_provider.h" | 16 #include "chromecast/media/cma/base/buffering_frame_provider.h" |
| 17 #include "chromecast/media/cma/base/buffering_state.h" | 17 #include "chromecast/media/cma/base/buffering_state.h" |
| 18 #include "chromecast/media/cma/base/cma_logging.h" | 18 #include "chromecast/media/cma/base/cma_logging.h" |
| 19 #include "chromecast/media/cma/base/coded_frame_provider.h" | 19 #include "chromecast/media/cma/base/coded_frame_provider.h" |
| 20 #include "chromecast/media/cma/base/decoder_buffer_base.h" | 20 #include "chromecast/media/cma/base/decoder_buffer_base.h" |
| 21 #include "chromecast/media/cma/base/decoder_buffer_impl.h" | |
| 21 #include "chromecast/media/cma/pipeline/decrypt_util.h" | 22 #include "chromecast/media/cma/pipeline/decrypt_util.h" |
| 23 #include "chromecast/public/media/decrypt_config.h" | |
| 24 #include "chromecast/public/media/media_clock_device.h" | |
| 25 #include "chromecast/public/media/media_component_device.h" | |
| 22 #include "media/base/audio_decoder_config.h" | 26 #include "media/base/audio_decoder_config.h" |
| 23 #include "media/base/bind_to_current_loop.h" | 27 #include "media/base/bind_to_current_loop.h" |
| 24 #include "media/base/buffers.h" | 28 #include "media/base/buffers.h" |
| 25 #include "media/base/decrypt_config.h" | 29 #include "media/base/decrypt_config.h" |
| 26 | 30 |
| 27 namespace chromecast { | 31 namespace chromecast { |
| 28 namespace media { | 32 namespace media { |
| 29 | 33 |
| 30 namespace { | 34 namespace { |
| 31 | 35 |
| 32 const int kNoCallbackId = -1; | 36 const int kNoCallbackId = -1; |
| 33 | 37 |
| 34 } // namespace | 38 } // namespace |
| 35 | 39 |
| 36 AvPipelineImpl::AvPipelineImpl( | 40 AvPipelineImpl::AvPipelineImpl(MediaComponentDevice* media_component_device, |
| 37 MediaComponentDevice* media_component_device, | 41 const UpdateConfigCB& update_config_cb) |
| 38 const UpdateConfigCB& update_config_cb) | |
| 39 : update_config_cb_(update_config_cb), | 42 : update_config_cb_(update_config_cb), |
| 40 media_component_device_(media_component_device), | 43 media_component_device_(media_component_device), |
| 41 state_(kUninitialized), | 44 state_(kUninitialized), |
| 42 buffered_time_(::media::kNoTimestamp()), | 45 buffered_time_(TimeDelta::Invalid()), |
| 43 playable_buffered_time_(::media::kNoTimestamp()), | 46 playable_buffered_time_(TimeDelta::Invalid()), |
| 44 enable_feeding_(false), | 47 enable_feeding_(false), |
| 45 pending_read_(false), | 48 pending_read_(false), |
| 46 pending_push_(false), | 49 pending_push_(false), |
| 47 enable_time_update_(false), | 50 enable_time_update_(false), |
| 48 pending_time_update_task_(false), | 51 pending_time_update_task_(false), |
| 49 media_keys_(NULL), | 52 media_keys_(NULL), |
| 50 media_keys_callback_id_(kNoCallbackId), | 53 media_keys_callback_id_(kNoCallbackId), |
| 51 weak_factory_(this) { | 54 weak_factory_(this) { |
| 52 DCHECK(media_component_device); | 55 DCHECK(media_component_device); |
| 53 weak_this_ = weak_factory_.GetWeakPtr(); | 56 weak_this_ = weak_factory_.GetWeakPtr(); |
| 54 thread_checker_.DetachFromThread(); | 57 thread_checker_.DetachFromThread(); |
| 55 } | 58 } |
| 56 | 59 |
| 57 AvPipelineImpl::~AvPipelineImpl() { | 60 AvPipelineImpl::~AvPipelineImpl() { |
| 58 DCHECK(thread_checker_.CalledOnValidThread()); | 61 DCHECK(thread_checker_.CalledOnValidThread()); |
| 59 media_component_device_->SetClient(MediaComponentDevice::Client()); | 62 media_component_device_->SetClient(nullptr); |
| 60 | 63 |
| 61 if (media_keys_ && media_keys_callback_id_ != kNoCallbackId) | 64 if (media_keys_ && media_keys_callback_id_ != kNoCallbackId) |
| 62 media_keys_->UnregisterPlayer(media_keys_callback_id_); | 65 media_keys_->UnregisterPlayer(media_keys_callback_id_); |
| 63 } | 66 } |
| 64 | 67 |
| 65 void AvPipelineImpl::TransitionToState(State state) { | 68 void AvPipelineImpl::TransitionToState(State state) { |
| 66 DCHECK(thread_checker_.CalledOnValidThread()); | 69 DCHECK(thread_checker_.CalledOnValidThread()); |
| 67 state_ = state; | 70 state_ = state; |
| 68 } | 71 } |
| 69 | 72 |
| (...skipping 16 matching lines...) Expand all Loading... | |
| 86 void AvPipelineImpl::SetClient(const AvPipelineClient& client) { | 89 void AvPipelineImpl::SetClient(const AvPipelineClient& client) { |
| 87 DCHECK(thread_checker_.CalledOnValidThread()); | 90 DCHECK(thread_checker_.CalledOnValidThread()); |
| 88 DCHECK_EQ(state_, kUninitialized); | 91 DCHECK_EQ(state_, kUninitialized); |
| 89 client_ = client; | 92 client_ = client; |
| 90 } | 93 } |
| 91 | 94 |
| 92 bool AvPipelineImpl::Initialize() { | 95 bool AvPipelineImpl::Initialize() { |
| 93 DCHECK(thread_checker_.CalledOnValidThread()); | 96 DCHECK(thread_checker_.CalledOnValidThread()); |
| 94 DCHECK_EQ(state_, kUninitialized); | 97 DCHECK_EQ(state_, kUninitialized); |
| 95 | 98 |
| 96 MediaComponentDevice::Client client; | 99 media_component_device_->SetClient(new MediaComponentDeviceClientImpl( |
| 97 client.eos_cb = base::Bind(&AvPipelineImpl::OnEos, weak_this_); | 100 base::Bind(&AvPipelineImpl::OnEos, weak_this_))); |
| 98 media_component_device_->SetClient(client); | |
| 99 if (!media_component_device_->SetState(MediaComponentDevice::kStateIdle)) | 101 if (!media_component_device_->SetState(MediaComponentDevice::kStateIdle)) |
| 100 return false; | 102 return false; |
| 101 | 103 |
| 102 return true; | 104 return true; |
| 103 } | 105 } |
| 104 | 106 |
| 105 bool AvPipelineImpl::StartPlayingFrom( | 107 bool AvPipelineImpl::StartPlayingFrom( |
| 106 base::TimeDelta time, | 108 base::TimeDelta time, |
| 107 const scoped_refptr<BufferingState>& buffering_state) { | 109 const scoped_refptr<BufferingState>& buffering_state) { |
| 108 DCHECK(thread_checker_.CalledOnValidThread()); | 110 DCHECK(thread_checker_.CalledOnValidThread()); |
| 109 DCHECK_EQ(state_, kFlushed); | 111 DCHECK_EQ(state_, kFlushed); |
| 110 | 112 |
| 111 // Media time where rendering should start | 113 // Media time where rendering should start |
| 112 // and switch to a state where the audio device accepts incoming buffers. | 114 // and switch to a state where the audio device accepts incoming buffers. |
| 113 if (!media_component_device_->SetStartPts(time) || | 115 TimeDelta start_time = FromBaseTimeDelta(time); |
| 116 if (!media_component_device_->SetStartPts(start_time) || | |
| 114 !media_component_device_->SetState(MediaComponentDevice::kStatePaused)) { | 117 !media_component_device_->SetState(MediaComponentDevice::kStatePaused)) { |
| 115 return false; | 118 return false; |
| 116 } | 119 } |
| 117 | 120 |
| 118 // Buffering related initialization. | 121 // Buffering related initialization. |
| 119 DCHECK(frame_provider_); | 122 DCHECK(frame_provider_); |
| 120 buffering_state_ = buffering_state; | 123 buffering_state_ = buffering_state; |
| 121 if (buffering_state_.get()) | 124 if (buffering_state_.get()) |
| 122 buffering_state_->SetMediaTime(time); | 125 buffering_state_->SetMediaTime(time); |
| 123 | 126 |
| (...skipping 18 matching lines...) Expand all Loading... | |
| 142 pending_push_ = false; | 145 pending_push_ = false; |
| 143 | 146 |
| 144 // Break the feeding loop. | 147 // Break the feeding loop. |
| 145 enable_feeding_ = false; | 148 enable_feeding_ = false; |
| 146 | 149 |
| 147 // Remove any pending buffer. | 150 // Remove any pending buffer. |
| 148 pending_buffer_ = scoped_refptr<DecoderBufferBase>(); | 151 pending_buffer_ = scoped_refptr<DecoderBufferBase>(); |
| 149 | 152 |
| 150 // Finally, remove any frames left in the frame provider. | 153 // Finally, remove any frames left in the frame provider. |
| 151 pending_read_ = false; | 154 pending_read_ = false; |
| 152 buffered_time_ = ::media::kNoTimestamp(); | 155 buffered_time_ = TimeDelta::Invalid(); |
|
gunsch
2015/07/27 17:14:49
To me, this re-affirms not having our own TimeDelt
servolk
2015/07/27 21:25:47
If our goal is to fully decouple CMA backend code
halliwell
2015/07/28 02:19:35
I've removed TimeDelta. It made initial refactori
| |
| 153 playable_buffered_time_ = ::media::kNoTimestamp(); | 156 playable_buffered_time_ = TimeDelta::Invalid(); |
| 154 non_playable_frames_.clear(); | 157 non_playable_frames_.clear(); |
| 155 frame_provider_->Flush(done_cb); | 158 frame_provider_->Flush(done_cb); |
| 156 } | 159 } |
| 157 | 160 |
| 158 void AvPipelineImpl::Stop() { | 161 void AvPipelineImpl::Stop() { |
| 159 DCHECK(thread_checker_.CalledOnValidThread()); | 162 DCHECK(thread_checker_.CalledOnValidThread()); |
| 160 | 163 |
| 161 // Stop can be called from any state. | 164 // Stop can be called from any state. |
| 162 if (state_ == kUninitialized || state_ == kStopped) | 165 if (state_ == kUninitialized || state_ == kStopped) |
| 163 return; | 166 return; |
| (...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 275 // If we do have the clear key, decrypt the pending buffer | 278 // If we do have the clear key, decrypt the pending buffer |
| 276 // and reset the decryption context (not needed anymore). | 279 // and reset the decryption context (not needed anymore). |
| 277 crypto::SymmetricKey* key = decrypt_context->GetKey(); | 280 crypto::SymmetricKey* key = decrypt_context->GetKey(); |
| 278 if (key != NULL) { | 281 if (key != NULL) { |
| 279 pending_buffer_ = DecryptDecoderBuffer(pending_buffer_, key); | 282 pending_buffer_ = DecryptDecoderBuffer(pending_buffer_, key); |
| 280 decrypt_context = scoped_refptr<DecryptContext>(); | 283 decrypt_context = scoped_refptr<DecryptContext>(); |
| 281 } | 284 } |
| 282 } | 285 } |
| 283 | 286 |
| 284 if (!pending_buffer_->end_of_stream() && buffering_state_.get()) { | 287 if (!pending_buffer_->end_of_stream() && buffering_state_.get()) { |
| 285 base::TimeDelta timestamp = pending_buffer_->timestamp(); | 288 base::TimeDelta timestamp = ToBaseTimeDelta(pending_buffer_->timestamp()); |
| 286 if (timestamp != ::media::kNoTimestamp()) | 289 if (timestamp != ::media::kNoTimestamp()) |
| 287 buffering_state_->SetMaxRenderingTime(timestamp); | 290 buffering_state_->SetMaxRenderingTime(timestamp); |
| 288 } | 291 } |
| 289 | 292 |
| 293 CastKeySystem key_system = | |
| 294 decrypt_context ? decrypt_context->key_system() : KEY_SYSTEM_NONE; | |
| 290 MediaComponentDevice::FrameStatus status = media_component_device_->PushFrame( | 295 MediaComponentDevice::FrameStatus status = media_component_device_->PushFrame( |
| 291 decrypt_context, | 296 key_system, new DecoderBufferImpl(pending_buffer_), |
| 292 pending_buffer_, | 297 new FrameStatusCBImpl( |
| 293 base::Bind(&AvPipelineImpl::OnFramePushed, weak_this_)); | 298 base::Bind(&AvPipelineImpl::OnFramePushed, weak_this_))); |
| 294 pending_buffer_ = scoped_refptr<DecoderBufferBase>(); | 299 pending_buffer_ = scoped_refptr<DecoderBufferBase>(); |
| 295 | 300 |
| 296 pending_push_ = (status == MediaComponentDevice::kFramePending); | 301 pending_push_ = (status == MediaComponentDevice::kFramePending); |
| 297 if (!pending_push_) | 302 if (!pending_push_) |
| 298 OnFramePushed(status); | 303 OnFramePushed(status); |
| 299 } | 304 } |
| 300 | 305 |
| 301 void AvPipelineImpl::OnFramePushed(MediaComponentDevice::FrameStatus status) { | 306 void AvPipelineImpl::OnFramePushed(MediaComponentDevice::FrameStatus status) { |
| 302 DCHECK(thread_checker_.CalledOnValidThread()); | 307 DCHECK(thread_checker_.CalledOnValidThread()); |
| 303 pending_push_ = false; | 308 pending_push_ = false; |
| (...skipping 24 matching lines...) Expand all Loading... | |
| 328 } | 333 } |
| 329 | 334 |
| 330 void AvPipelineImpl::OnFrameBuffered( | 335 void AvPipelineImpl::OnFrameBuffered( |
| 331 const scoped_refptr<DecoderBufferBase>& buffer, | 336 const scoped_refptr<DecoderBufferBase>& buffer, |
| 332 bool is_at_max_capacity) { | 337 bool is_at_max_capacity) { |
| 333 DCHECK(thread_checker_.CalledOnValidThread()); | 338 DCHECK(thread_checker_.CalledOnValidThread()); |
| 334 | 339 |
| 335 if (!buffering_state_.get()) | 340 if (!buffering_state_.get()) |
| 336 return; | 341 return; |
| 337 | 342 |
| 338 if (!buffer->end_of_stream() && | 343 if (!buffer->end_of_stream() && (buffered_time_ == TimeDelta::Invalid() || |
| 339 (buffered_time_ == ::media::kNoTimestamp() || | 344 buffered_time_ < buffer->timestamp())) { |
| 340 buffered_time_ < buffer->timestamp())) { | |
| 341 buffered_time_ = buffer->timestamp(); | 345 buffered_time_ = buffer->timestamp(); |
| 342 } | 346 } |
| 343 | 347 |
| 344 if (is_at_max_capacity) | 348 if (is_at_max_capacity) |
| 345 buffering_state_->NotifyMaxCapacity(buffered_time_); | 349 buffering_state_->NotifyMaxCapacity(ToBaseTimeDelta(buffered_time_)); |
| 346 | 350 |
| 347 // No need to update the list of playable frames, | 351 // No need to update the list of playable frames, |
| 348 // if we are already blocking on a frame. | 352 // if we are already blocking on a frame. |
| 349 bool update_playable_frames = non_playable_frames_.empty(); | 353 bool update_playable_frames = non_playable_frames_.empty(); |
| 350 non_playable_frames_.push_back(buffer); | 354 non_playable_frames_.push_back(buffer); |
| 351 if (update_playable_frames) | 355 if (update_playable_frames) |
| 352 UpdatePlayableFrames(); | 356 UpdatePlayableFrames(); |
| 353 } | 357 } |
| 354 | 358 |
| 355 void AvPipelineImpl::UpdatePlayableFrames() { | 359 void AvPipelineImpl::UpdatePlayableFrames() { |
| 356 while (!non_playable_frames_.empty()) { | 360 while (!non_playable_frames_.empty()) { |
| 357 const scoped_refptr<DecoderBufferBase>& non_playable_frame = | 361 const scoped_refptr<DecoderBufferBase>& non_playable_frame = |
| 358 non_playable_frames_.front(); | 362 non_playable_frames_.front(); |
| 359 | 363 |
| 360 if (non_playable_frame->end_of_stream()) { | 364 if (non_playable_frame->end_of_stream()) { |
| 361 buffering_state_->NotifyEos(); | 365 buffering_state_->NotifyEos(); |
| 362 } else { | 366 } else { |
| 363 const ::media::DecryptConfig* decrypt_config = | 367 const DecryptConfig* decrypt_config = |
| 364 non_playable_frame->decrypt_config(); | 368 non_playable_frame->decrypt_config(); |
| 365 if (decrypt_config && | 369 if (decrypt_config && |
| 366 !(media_keys_ && | 370 !(media_keys_ && |
| 367 media_keys_->GetDecryptContext(decrypt_config->key_id()).get())) { | 371 media_keys_->GetDecryptContext(decrypt_config->key_id()).get())) { |
| 368 // The frame is still not playable. All the following are thus not | 372 // The frame is still not playable. All the following are thus not |
| 369 // playable. | 373 // playable. |
| 370 break; | 374 break; |
| 371 } | 375 } |
| 372 | 376 |
| 373 if (playable_buffered_time_ == ::media::kNoTimestamp() || | 377 if (playable_buffered_time_ == TimeDelta::Invalid() || |
| 374 playable_buffered_time_ < non_playable_frame->timestamp()) { | 378 playable_buffered_time_ < non_playable_frame->timestamp()) { |
| 375 playable_buffered_time_ = non_playable_frame->timestamp(); | 379 playable_buffered_time_ = non_playable_frame->timestamp(); |
| 376 buffering_state_->SetBufferedTime(playable_buffered_time_); | 380 buffering_state_->SetBufferedTime( |
| 381 ToBaseTimeDelta(playable_buffered_time_)); | |
| 377 } | 382 } |
| 378 } | 383 } |
| 379 | 384 |
| 380 // The frame is playable: remove it from the list of non playable frames. | 385 // The frame is playable: remove it from the list of non playable frames. |
| 381 non_playable_frames_.pop_front(); | 386 non_playable_frames_.pop_front(); |
| 382 } | 387 } |
| 383 } | 388 } |
| 384 | 389 |
| 385 } // namespace media | 390 } // namespace media |
| 386 } // namespace chromecast | 391 } // namespace chromecast |
| OLD | NEW |