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" | |
17 #include "chromecast/media/cma/base/cma_logging.h" | 16 #include "chromecast/media/cma/base/cma_logging.h" |
18 #include "chromecast/media/cma/base/coded_frame_provider.h" | 17 #include "chromecast/media/cma/base/coded_frame_provider.h" |
19 #include "chromecast/media/cma/base/decoder_buffer_base.h" | 18 #include "chromecast/media/cma/base/decoder_buffer_base.h" |
20 #include "chromecast/media/cma/pipeline/decrypt_util.h" | 19 #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" | 20 #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" | 21 #include "media/base/audio_decoder_config.h" |
27 #include "media/base/bind_to_current_loop.h" | 22 #include "media/base/bind_to_current_loop.h" |
28 #include "media/base/decrypt_config.h" | 23 #include "media/base/decrypt_config.h" |
29 #include "media/base/timestamp_constants.h" | 24 #include "media/base/timestamp_constants.h" |
30 | 25 |
31 namespace chromecast { | 26 namespace chromecast { |
32 namespace media { | 27 namespace media { |
33 | 28 |
34 namespace { | 29 namespace { |
35 | 30 |
36 const int kNoCallbackId = -1; | 31 const int kNoCallbackId = -1; |
37 | 32 |
38 } // namespace | 33 } // namespace |
39 | 34 |
40 AvPipelineImpl::AvPipelineImpl(MediaComponentDevice* media_component_device, | 35 AvPipelineImpl::AvPipelineImpl(MediaPipelineBackend::Decoder* decoder, |
41 const UpdateConfigCB& update_config_cb) | 36 const UpdateConfigCB& update_config_cb) |
42 : update_config_cb_(update_config_cb), | 37 : update_config_cb_(update_config_cb), |
43 media_component_device_(media_component_device), | 38 decoder_(decoder), |
44 state_(kUninitialized), | 39 state_(kUninitialized), |
45 buffered_time_(::media::kNoTimestamp()), | 40 buffered_time_(::media::kNoTimestamp()), |
46 playable_buffered_time_(::media::kNoTimestamp()), | 41 playable_buffered_time_(::media::kNoTimestamp()), |
47 enable_feeding_(false), | 42 enable_feeding_(false), |
48 pending_read_(false), | 43 pending_read_(false), |
49 pending_push_(false), | 44 pushed_buffer_(nullptr), |
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(new BufferingFrameProvider( |
82 new BufferingFrameProvider( | 76 frame_provider.Pass(), |
83 frame_provider.Pass(), | 77 max_buffer_size, |
84 max_buffer_size, | 78 max_frame_size, |
85 max_frame_size, | 79 base::Bind(&AvPipelineImpl::OnDataBuffered, weak_this_))); |
86 base::Bind(&AvPipelineImpl::OnFrameBuffered, weak_this_))); | |
87 } | |
88 | |
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 } | 80 } |
106 | 81 |
107 bool AvPipelineImpl::StartPlayingFrom( | 82 bool AvPipelineImpl::StartPlayingFrom( |
108 base::TimeDelta time, | 83 base::TimeDelta time, |
109 const scoped_refptr<BufferingState>& buffering_state) { | 84 const scoped_refptr<BufferingState>& buffering_state) { |
110 DCHECK(thread_checker_.CalledOnValidThread()); | 85 DCHECK(thread_checker_.CalledOnValidThread()); |
111 DCHECK_EQ(state_, kFlushed); | 86 DCHECK_EQ(state_, kFlushed); |
112 | 87 |
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. | 88 // Buffering related initialization. |
121 DCHECK(frame_provider_); | 89 DCHECK(frame_provider_); |
122 buffering_state_ = buffering_state; | 90 buffering_state_ = buffering_state; |
123 if (buffering_state_.get()) | 91 if (buffering_state_.get()) |
124 buffering_state_->SetMediaTime(time); | 92 buffering_state_->SetMediaTime(time); |
125 | 93 |
126 if (!media_component_device_->SetState(MediaComponentDevice::kStateRunning)) | |
127 return false; | |
128 | |
129 // Start feeding the pipeline. | 94 // Start feeding the pipeline. |
130 enable_feeding_ = true; | 95 enable_feeding_ = true; |
131 base::ThreadTaskRunnerHandle::Get()->PostTask( | 96 base::ThreadTaskRunnerHandle::Get()->PostTask( |
132 FROM_HERE, base::Bind(&AvPipelineImpl::FetchBufferIfNeeded, weak_this_)); | 97 FROM_HERE, base::Bind(&AvPipelineImpl::FetchBufferIfNeeded, weak_this_)); |
133 | 98 |
134 return true; | 99 return true; |
135 } | 100 } |
136 | 101 |
137 void AvPipelineImpl::Flush(const base::Closure& done_cb) { | 102 void AvPipelineImpl::Flush(const base::Closure& done_cb) { |
138 DCHECK(thread_checker_.CalledOnValidThread()); | 103 DCHECK(thread_checker_.CalledOnValidThread()); |
139 DCHECK_EQ(state_, kFlushing); | 104 DCHECK_EQ(state_, kFlushing); |
140 DCHECK_EQ( | 105 |
141 media_component_device_->GetState(), MediaComponentDevice::kStateRunning); | |
142 // Note: returning to idle state aborts any pending frame push. | 106 // Note: returning to idle state aborts any pending frame push. |
143 media_component_device_->SetState(MediaComponentDevice::kStateIdle); | 107 pushed_buffer_.set_buffer(nullptr); |
144 pending_push_ = false; | |
145 | 108 |
146 // Break the feeding loop. | 109 // Break the feeding loop. |
147 enable_feeding_ = false; | 110 enable_feeding_ = false; |
148 | 111 |
149 // Remove any pending buffer. | 112 // Remove any pending buffer. |
150 pending_buffer_ = scoped_refptr<DecoderBufferBase>(); | 113 pending_buffer_ = scoped_refptr<DecoderBufferBase>(); |
151 | 114 |
152 // Finally, remove any frames left in the frame provider. | 115 // Finally, remove any frames left in the frame provider. |
153 pending_read_ = false; | 116 pending_read_ = false; |
154 buffered_time_ = ::media::kNoTimestamp(); | 117 buffered_time_ = ::media::kNoTimestamp(); |
155 playable_buffered_time_ = ::media::kNoTimestamp(); | 118 playable_buffered_time_ = ::media::kNoTimestamp(); |
156 non_playable_frames_.clear(); | 119 non_playable_frames_.clear(); |
157 frame_provider_->Flush(done_cb); | 120 frame_provider_->Flush(done_cb); |
158 } | 121 } |
159 | 122 |
160 void AvPipelineImpl::Stop() { | 123 void AvPipelineImpl::Stop() { |
161 DCHECK(thread_checker_.CalledOnValidThread()); | 124 DCHECK(thread_checker_.CalledOnValidThread()); |
162 | 125 |
163 // Stop can be called from any state. | 126 // Stop can be called from any state. |
164 if (state_ == kUninitialized || state_ == kStopped) | 127 if (state_ == kUninitialized || state_ == kStopped) |
165 return; | 128 return; |
166 | 129 |
167 // Stop feeding the pipeline. | 130 // Stop feeding the pipeline. |
168 enable_feeding_ = false; | 131 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 } | 132 } |
182 | 133 |
183 void AvPipelineImpl::SetCdm(BrowserCdmCast* media_keys) { | 134 void AvPipelineImpl::SetCdm(BrowserCdmCast* media_keys) { |
184 DCHECK(thread_checker_.CalledOnValidThread()); | 135 DCHECK(thread_checker_.CalledOnValidThread()); |
185 DCHECK(media_keys); | 136 DCHECK(media_keys); |
186 | 137 |
187 if (media_keys_ && media_keys_callback_id_ != kNoCallbackId) | 138 if (media_keys_ && media_keys_callback_id_ != kNoCallbackId) |
188 media_keys_->UnregisterPlayer(media_keys_callback_id_); | 139 media_keys_->UnregisterPlayer(media_keys_callback_id_); |
189 | 140 |
190 media_keys_ = media_keys; | 141 media_keys_ = media_keys; |
191 media_keys_callback_id_ = media_keys_->RegisterPlayer( | 142 media_keys_callback_id_ = media_keys_->RegisterPlayer( |
192 base::Bind(&AvPipelineImpl::OnCdmStateChanged, weak_this_), | 143 base::Bind(&AvPipelineImpl::OnCdmStateChanged, weak_this_), |
193 base::Bind(&AvPipelineImpl::OnCdmDestroyed, weak_this_)); | 144 base::Bind(&AvPipelineImpl::OnCdmDestroyed, weak_this_)); |
194 } | 145 } |
195 | 146 |
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() { | 147 void AvPipelineImpl::FetchBufferIfNeeded() { |
207 DCHECK(thread_checker_.CalledOnValidThread()); | 148 DCHECK(thread_checker_.CalledOnValidThread()); |
208 if (!enable_feeding_) | 149 if (!enable_feeding_) |
209 return; | 150 return; |
210 | 151 |
211 if (pending_read_ || pending_buffer_.get()) | 152 if (pending_read_ || pending_buffer_.get()) |
212 return; | 153 return; |
213 | 154 |
214 pending_read_ = true; | 155 pending_read_ = true; |
215 frame_provider_->Read( | 156 frame_provider_->Read( |
(...skipping 22 matching lines...) Expand all Loading... |
238 return; | 179 return; |
239 | 180 |
240 // Initiate a read if there isn't already one. | 181 // Initiate a read if there isn't already one. |
241 if (!pending_buffer_.get() && !pending_read_) { | 182 if (!pending_buffer_.get() && !pending_read_) { |
242 base::ThreadTaskRunnerHandle::Get()->PostTask( | 183 base::ThreadTaskRunnerHandle::Get()->PostTask( |
243 FROM_HERE, | 184 FROM_HERE, |
244 base::Bind(&AvPipelineImpl::FetchBufferIfNeeded, weak_this_)); | 185 base::Bind(&AvPipelineImpl::FetchBufferIfNeeded, weak_this_)); |
245 return; | 186 return; |
246 } | 187 } |
247 | 188 |
248 if (!pending_buffer_.get() || pending_push_) | 189 if (!pending_buffer_.get() || pushed_buffer_.buffer()) |
249 return; | 190 return; |
250 | 191 |
251 // Break the feeding loop when the end of stream is reached. | 192 // Break the feeding loop when the end of stream is reached. |
252 if (pending_buffer_->end_of_stream()) { | 193 if (pending_buffer_->end_of_stream()) { |
253 CMALOG(kLogControl) << __FUNCTION__ << ": EOS reached, stopped feeding"; | 194 CMALOG(kLogControl) << __FUNCTION__ << ": EOS reached, stopped feeding"; |
254 enable_feeding_ = false; | 195 enable_feeding_ = false; |
255 } | 196 } |
256 | 197 |
257 scoped_ptr<DecryptContextImpl> decrypt_context; | 198 scoped_ptr<DecryptContextImpl> decrypt_context; |
258 if (!pending_buffer_->end_of_stream() && | 199 if (!pending_buffer_->end_of_stream() && |
(...skipping 23 matching lines...) Expand all Loading... |
282 decrypt_context.reset(); | 223 decrypt_context.reset(); |
283 } | 224 } |
284 } | 225 } |
285 | 226 |
286 if (!pending_buffer_->end_of_stream() && buffering_state_.get()) { | 227 if (!pending_buffer_->end_of_stream() && buffering_state_.get()) { |
287 base::TimeDelta timestamp = pending_buffer_->timestamp(); | 228 base::TimeDelta timestamp = pending_buffer_->timestamp(); |
288 if (timestamp != ::media::kNoTimestamp()) | 229 if (timestamp != ::media::kNoTimestamp()) |
289 buffering_state_->SetMaxRenderingTime(timestamp); | 230 buffering_state_->SetMaxRenderingTime(timestamp); |
290 } | 231 } |
291 | 232 |
292 MediaComponentDevice::FrameStatus status = media_component_device_->PushFrame( | 233 DCHECK(!pushed_buffer_.buffer()); |
293 decrypt_context.release(), new CastDecoderBufferImpl(pending_buffer_), | 234 pushed_buffer_.set_buffer(pending_buffer_); |
294 new FrameStatusCBImpl( | 235 MediaPipelineBackend::BufferStatus status = |
295 base::Bind(&AvPipelineImpl::OnFramePushed, weak_this_))); | 236 decoder_->PushBuffer(decrypt_context.release(), &pushed_buffer_); |
296 pending_buffer_ = scoped_refptr<DecoderBufferBase>(); | 237 pending_buffer_ = scoped_refptr<DecoderBufferBase>(); |
297 | 238 |
298 pending_push_ = (status == MediaComponentDevice::kFramePending); | 239 if (status != MediaPipelineBackend::kBufferPending) |
299 if (!pending_push_) | 240 OnBufferPushed(status); |
300 OnFramePushed(status); | |
301 } | 241 } |
302 | 242 |
303 void AvPipelineImpl::OnFramePushed(MediaComponentDevice::FrameStatus status) { | 243 void AvPipelineImpl::OnBufferPushed(MediaPipelineBackend::BufferStatus status) { |
304 DCHECK(thread_checker_.CalledOnValidThread()); | 244 DCHECK(thread_checker_.CalledOnValidThread()); |
305 pending_push_ = false; | 245 pushed_buffer_.set_buffer(nullptr); |
306 if (status == MediaComponentDevice::kFrameFailed) { | 246 if (status == MediaPipelineBackend::kBufferFailed) { |
307 LOG(WARNING) << "AvPipelineImpl: PushFrame failed"; | 247 LOG(WARNING) << "AvPipelineImpl: PushFrame failed"; |
308 enable_feeding_ = false; | 248 enable_feeding_ = false; |
309 state_ = kError; | 249 state_ = kError; |
310 return; | 250 return; |
311 } | 251 } |
312 base::ThreadTaskRunnerHandle::Get()->PostTask( | 252 base::ThreadTaskRunnerHandle::Get()->PostTask( |
313 FROM_HERE, base::Bind(&AvPipelineImpl::ProcessPendingBuffer, weak_this_)); | 253 FROM_HERE, base::Bind(&AvPipelineImpl::ProcessPendingBuffer, weak_this_)); |
314 } | 254 } |
315 | 255 |
316 void AvPipelineImpl::OnCdmStateChanged() { | 256 void AvPipelineImpl::OnCdmStateChanged() { |
317 DCHECK(thread_checker_.CalledOnValidThread()); | 257 DCHECK(thread_checker_.CalledOnValidThread()); |
318 | 258 |
319 // Update the buffering state if needed. | 259 // Update the buffering state if needed. |
320 if (buffering_state_.get()) | 260 if (buffering_state_.get()) |
321 UpdatePlayableFrames(); | 261 UpdatePlayableFrames(); |
322 | 262 |
323 // Process the pending buffer in case the CDM now has the frame key id. | 263 // Process the pending buffer in case the CDM now has the frame key id. |
324 ProcessPendingBuffer(); | 264 ProcessPendingBuffer(); |
325 } | 265 } |
326 | 266 |
327 void AvPipelineImpl::OnCdmDestroyed() { | 267 void AvPipelineImpl::OnCdmDestroyed() { |
328 DCHECK(thread_checker_.CalledOnValidThread()); | 268 DCHECK(thread_checker_.CalledOnValidThread()); |
329 media_keys_ = NULL; | 269 media_keys_ = NULL; |
330 } | 270 } |
331 | 271 |
332 void AvPipelineImpl::OnFrameBuffered( | 272 void AvPipelineImpl::OnDataBuffered( |
333 const scoped_refptr<DecoderBufferBase>& buffer, | 273 const scoped_refptr<DecoderBufferBase>& buffer, |
334 bool is_at_max_capacity) { | 274 bool is_at_max_capacity) { |
335 DCHECK(thread_checker_.CalledOnValidThread()); | 275 DCHECK(thread_checker_.CalledOnValidThread()); |
336 | 276 |
337 if (!buffering_state_.get()) | 277 if (!buffering_state_.get()) |
338 return; | 278 return; |
339 | 279 |
340 if (!buffer->end_of_stream() && (buffered_time_ == ::media::kNoTimestamp() || | 280 if (!buffer->end_of_stream() && (buffered_time_ == ::media::kNoTimestamp() || |
341 buffered_time_ < buffer->timestamp())) { | 281 buffered_time_ < buffer->timestamp())) { |
342 buffered_time_ = buffer->timestamp(); | 282 buffered_time_ = buffer->timestamp(); |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
378 } | 318 } |
379 } | 319 } |
380 | 320 |
381 // The frame is playable: remove it from the list of non playable frames. | 321 // The frame is playable: remove it from the list of non playable frames. |
382 non_playable_frames_.pop_front(); | 322 non_playable_frames_.pop_front(); |
383 } | 323 } |
384 } | 324 } |
385 | 325 |
386 } // namespace media | 326 } // namespace media |
387 } // namespace chromecast | 327 } // namespace chromecast |
OLD | NEW |