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.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/backend/media_clock_device.h" | |
15 #include "chromecast/media/cma/backend/media_component_device.h" | |
16 #include "chromecast/media/cma/base/buffering_frame_provider.h" | 14 #include "chromecast/media/cma/base/buffering_frame_provider.h" |
17 #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" |
18 #include "chromecast/media/cma/base/cma_logging.h" | 17 #include "chromecast/media/cma/base/cma_logging.h" |
19 #include "chromecast/media/cma/base/coded_frame_provider.h" | 18 #include "chromecast/media/cma/base/coded_frame_provider.h" |
20 #include "chromecast/media/cma/base/decoder_buffer_base.h" | 19 #include "chromecast/media/cma/base/decoder_buffer_base.h" |
21 #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" |
| 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_(::media::kNoTimestamp()), |
43 playable_buffered_time_(::media::kNoTimestamp()), | 46 playable_buffered_time_(::media::kNoTimestamp()), |
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 if (!media_component_device_->SetStartPts(time.InMicroseconds()) || |
114 !media_component_device_->SetState(MediaComponentDevice::kStatePaused)) { | 116 !media_component_device_->SetState(MediaComponentDevice::kStatePaused)) { |
115 return false; | 117 return false; |
116 } | 118 } |
117 | 119 |
118 // Buffering related initialization. | 120 // Buffering related initialization. |
119 DCHECK(frame_provider_); | 121 DCHECK(frame_provider_); |
120 buffering_state_ = buffering_state; | 122 buffering_state_ = buffering_state; |
121 if (buffering_state_.get()) | 123 if (buffering_state_.get()) |
122 buffering_state_->SetMediaTime(time); | 124 buffering_state_->SetMediaTime(time); |
123 | 125 |
(...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
245 | 247 |
246 if (!pending_buffer_.get() || pending_push_) | 248 if (!pending_buffer_.get() || pending_push_) |
247 return; | 249 return; |
248 | 250 |
249 // Break the feeding loop when the end of stream is reached. | 251 // Break the feeding loop when the end of stream is reached. |
250 if (pending_buffer_->end_of_stream()) { | 252 if (pending_buffer_->end_of_stream()) { |
251 CMALOG(kLogControl) << __FUNCTION__ << ": EOS reached, stopped feeding"; | 253 CMALOG(kLogControl) << __FUNCTION__ << ": EOS reached, stopped feeding"; |
252 enable_feeding_ = false; | 254 enable_feeding_ = false; |
253 } | 255 } |
254 | 256 |
255 scoped_refptr<DecryptContext> decrypt_context; | 257 scoped_ptr<DecryptContextImpl> decrypt_context; |
256 if (!pending_buffer_->end_of_stream() && | 258 if (!pending_buffer_->end_of_stream() && |
257 pending_buffer_->decrypt_config()) { | 259 pending_buffer_->decrypt_config()) { |
258 // Verify that CDM has the key ID. | 260 // Verify that CDM has the key ID. |
259 // Should not send the frame if the key ID is not available yet. | 261 // Should not send the frame if the key ID is not available yet. |
260 std::string key_id(pending_buffer_->decrypt_config()->key_id()); | 262 std::string key_id(pending_buffer_->decrypt_config()->key_id()); |
261 if (!media_keys_) { | 263 if (!media_keys_) { |
262 CMALOG(kLogControl) << "No CDM for frame: pts=" | 264 CMALOG(kLogControl) << "No CDM for frame: pts=" |
263 << pending_buffer_->timestamp().InMilliseconds(); | 265 << pending_buffer_->timestamp().InMilliseconds(); |
264 return; | 266 return; |
265 } | 267 } |
266 decrypt_context = media_keys_->GetDecryptContext(key_id); | 268 decrypt_context = media_keys_->GetDecryptContext(key_id); |
267 if (!decrypt_context.get()) { | 269 if (!decrypt_context.get()) { |
268 CMALOG(kLogControl) << "frame(pts=" | 270 CMALOG(kLogControl) << "frame(pts=" |
269 << pending_buffer_->timestamp().InMilliseconds() | 271 << pending_buffer_->timestamp().InMilliseconds() |
270 << "): waiting for key id " | 272 << "): waiting for key id " |
271 << base::HexEncode(&key_id[0], key_id.size()); | 273 << base::HexEncode(&key_id[0], key_id.size()); |
272 return; | 274 return; |
273 } | 275 } |
274 | 276 |
275 // If we do have the clear key, decrypt the pending buffer | 277 // If we do have the clear key, decrypt the pending buffer |
276 // and reset the decryption context (not needed anymore). | 278 // and reset the decryption context (not needed anymore). |
277 crypto::SymmetricKey* key = decrypt_context->GetKey(); | 279 crypto::SymmetricKey* key = decrypt_context->GetKey(); |
278 if (key != NULL) { | 280 if (key != NULL) { |
279 pending_buffer_ = DecryptDecoderBuffer(pending_buffer_, key); | 281 pending_buffer_ = DecryptDecoderBuffer(pending_buffer_, key); |
280 decrypt_context = scoped_refptr<DecryptContext>(); | 282 decrypt_context.reset(); |
281 } | 283 } |
282 } | 284 } |
283 | 285 |
284 if (!pending_buffer_->end_of_stream() && buffering_state_.get()) { | 286 if (!pending_buffer_->end_of_stream() && buffering_state_.get()) { |
285 base::TimeDelta timestamp = pending_buffer_->timestamp(); | 287 base::TimeDelta timestamp = pending_buffer_->timestamp(); |
286 if (timestamp != ::media::kNoTimestamp()) | 288 if (timestamp != ::media::kNoTimestamp()) |
287 buffering_state_->SetMaxRenderingTime(timestamp); | 289 buffering_state_->SetMaxRenderingTime(timestamp); |
288 } | 290 } |
289 | 291 |
290 MediaComponentDevice::FrameStatus status = media_component_device_->PushFrame( | 292 MediaComponentDevice::FrameStatus status = media_component_device_->PushFrame( |
291 decrypt_context, | 293 decrypt_context.release(), new CastDecoderBufferImpl(pending_buffer_), |
292 pending_buffer_, | 294 new FrameStatusCBImpl( |
293 base::Bind(&AvPipelineImpl::OnFramePushed, weak_this_)); | 295 base::Bind(&AvPipelineImpl::OnFramePushed, weak_this_))); |
294 pending_buffer_ = scoped_refptr<DecoderBufferBase>(); | 296 pending_buffer_ = scoped_refptr<DecoderBufferBase>(); |
295 | 297 |
296 pending_push_ = (status == MediaComponentDevice::kFramePending); | 298 pending_push_ = (status == MediaComponentDevice::kFramePending); |
297 if (!pending_push_) | 299 if (!pending_push_) |
298 OnFramePushed(status); | 300 OnFramePushed(status); |
299 } | 301 } |
300 | 302 |
301 void AvPipelineImpl::OnFramePushed(MediaComponentDevice::FrameStatus status) { | 303 void AvPipelineImpl::OnFramePushed(MediaComponentDevice::FrameStatus status) { |
302 DCHECK(thread_checker_.CalledOnValidThread()); | 304 DCHECK(thread_checker_.CalledOnValidThread()); |
303 pending_push_ = false; | 305 pending_push_ = false; |
(...skipping 24 matching lines...) Expand all Loading... |
328 } | 330 } |
329 | 331 |
330 void AvPipelineImpl::OnFrameBuffered( | 332 void AvPipelineImpl::OnFrameBuffered( |
331 const scoped_refptr<DecoderBufferBase>& buffer, | 333 const scoped_refptr<DecoderBufferBase>& buffer, |
332 bool is_at_max_capacity) { | 334 bool is_at_max_capacity) { |
333 DCHECK(thread_checker_.CalledOnValidThread()); | 335 DCHECK(thread_checker_.CalledOnValidThread()); |
334 | 336 |
335 if (!buffering_state_.get()) | 337 if (!buffering_state_.get()) |
336 return; | 338 return; |
337 | 339 |
338 if (!buffer->end_of_stream() && | 340 if (!buffer->end_of_stream() && (buffered_time_ == ::media::kNoTimestamp() || |
339 (buffered_time_ == ::media::kNoTimestamp() || | 341 buffered_time_ < buffer->timestamp())) { |
340 buffered_time_ < buffer->timestamp())) { | |
341 buffered_time_ = buffer->timestamp(); | 342 buffered_time_ = buffer->timestamp(); |
342 } | 343 } |
343 | 344 |
344 if (is_at_max_capacity) | 345 if (is_at_max_capacity) |
345 buffering_state_->NotifyMaxCapacity(buffered_time_); | 346 buffering_state_->NotifyMaxCapacity(buffered_time_); |
346 | 347 |
347 // No need to update the list of playable frames, | 348 // No need to update the list of playable frames, |
348 // if we are already blocking on a frame. | 349 // if we are already blocking on a frame. |
349 bool update_playable_frames = non_playable_frames_.empty(); | 350 bool update_playable_frames = non_playable_frames_.empty(); |
350 non_playable_frames_.push_back(buffer); | 351 non_playable_frames_.push_back(buffer); |
351 if (update_playable_frames) | 352 if (update_playable_frames) |
352 UpdatePlayableFrames(); | 353 UpdatePlayableFrames(); |
353 } | 354 } |
354 | 355 |
355 void AvPipelineImpl::UpdatePlayableFrames() { | 356 void AvPipelineImpl::UpdatePlayableFrames() { |
356 while (!non_playable_frames_.empty()) { | 357 while (!non_playable_frames_.empty()) { |
357 const scoped_refptr<DecoderBufferBase>& non_playable_frame = | 358 const scoped_refptr<DecoderBufferBase>& non_playable_frame = |
358 non_playable_frames_.front(); | 359 non_playable_frames_.front(); |
359 | 360 |
360 if (non_playable_frame->end_of_stream()) { | 361 if (non_playable_frame->end_of_stream()) { |
361 buffering_state_->NotifyEos(); | 362 buffering_state_->NotifyEos(); |
362 } else { | 363 } else { |
363 const ::media::DecryptConfig* decrypt_config = | 364 const CastDecryptConfig* decrypt_config = |
364 non_playable_frame->decrypt_config(); | 365 non_playable_frame->decrypt_config(); |
365 if (decrypt_config && | 366 if (decrypt_config && |
366 !(media_keys_ && | 367 !(media_keys_ && |
367 media_keys_->GetDecryptContext(decrypt_config->key_id()).get())) { | 368 media_keys_->GetDecryptContext(decrypt_config->key_id()).get())) { |
368 // The frame is still not playable. All the following are thus not | 369 // The frame is still not playable. All the following are thus not |
369 // playable. | 370 // playable. |
370 break; | 371 break; |
371 } | 372 } |
372 | 373 |
373 if (playable_buffered_time_ == ::media::kNoTimestamp() || | 374 if (playable_buffered_time_ == ::media::kNoTimestamp() || |
374 playable_buffered_time_ < non_playable_frame->timestamp()) { | 375 playable_buffered_time_ < non_playable_frame->timestamp()) { |
375 playable_buffered_time_ = non_playable_frame->timestamp(); | 376 playable_buffered_time_ = non_playable_frame->timestamp(); |
376 buffering_state_->SetBufferedTime(playable_buffered_time_); | 377 buffering_state_->SetBufferedTime(playable_buffered_time_); |
377 } | 378 } |
378 } | 379 } |
379 | 380 |
380 // The frame is playable: remove it from the list of non playable frames. | 381 // The frame is playable: remove it from the list of non playable frames. |
381 non_playable_frames_.pop_front(); | 382 non_playable_frames_.pop_front(); |
382 } | 383 } |
383 } | 384 } |
384 | 385 |
385 } // namespace media | 386 } // namespace media |
386 } // namespace chromecast | 387 } // namespace chromecast |
OLD | NEW |