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 "media/filters/decoder_stream.h" | 5 #include "media/filters/decoder_stream.h" |
6 | 6 |
7 #include "base/bind.h" | 7 #include "base/bind.h" |
8 #include "base/callback_helpers.h" | 8 #include "base/callback_helpers.h" |
9 #include "base/debug/trace_event.h" | 9 #include "base/debug/trace_event.h" |
10 #include "base/location.h" | 10 #include "base/location.h" |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
44 ScopedVector<Decoder> decoders, | 44 ScopedVector<Decoder> decoders, |
45 const SetDecryptorReadyCB& set_decryptor_ready_cb) | 45 const SetDecryptorReadyCB& set_decryptor_ready_cb) |
46 : task_runner_(task_runner), | 46 : task_runner_(task_runner), |
47 state_(STATE_UNINITIALIZED), | 47 state_(STATE_UNINITIALIZED), |
48 stream_(NULL), | 48 stream_(NULL), |
49 decoder_selector_( | 49 decoder_selector_( |
50 new DecoderSelector<StreamType>(task_runner, | 50 new DecoderSelector<StreamType>(task_runner, |
51 decoders.Pass(), | 51 decoders.Pass(), |
52 set_decryptor_ready_cb)), | 52 set_decryptor_ready_cb)), |
53 active_splice_(false), | 53 active_splice_(false), |
| 54 pending_decode_requests_(0), |
54 weak_factory_(this) {} | 55 weak_factory_(this) {} |
55 | 56 |
56 template <DemuxerStream::Type StreamType> | 57 template <DemuxerStream::Type StreamType> |
57 DecoderStream<StreamType>::~DecoderStream() { | 58 DecoderStream<StreamType>::~DecoderStream() { |
58 DCHECK(state_ == STATE_UNINITIALIZED || state_ == STATE_STOPPED) << state_; | 59 DCHECK(state_ == STATE_UNINITIALIZED || state_ == STATE_STOPPED) << state_; |
59 } | 60 } |
60 | 61 |
61 template <DemuxerStream::Type StreamType> | 62 template <DemuxerStream::Type StreamType> |
62 void DecoderStream<StreamType>::Initialize(DemuxerStream* stream, | 63 void DecoderStream<StreamType>::Initialize(DemuxerStream* stream, |
63 bool low_delay, | 64 bool low_delay, |
(...skipping 16 matching lines...) Expand all Loading... |
80 stream, low_delay, | 81 stream, low_delay, |
81 base::Bind(&DecoderStream<StreamType>::OnDecoderSelected, | 82 base::Bind(&DecoderStream<StreamType>::OnDecoderSelected, |
82 weak_factory_.GetWeakPtr())); | 83 weak_factory_.GetWeakPtr())); |
83 } | 84 } |
84 | 85 |
85 template <DemuxerStream::Type StreamType> | 86 template <DemuxerStream::Type StreamType> |
86 void DecoderStream<StreamType>::Read(const ReadCB& read_cb) { | 87 void DecoderStream<StreamType>::Read(const ReadCB& read_cb) { |
87 FUNCTION_DVLOG(2); | 88 FUNCTION_DVLOG(2); |
88 DCHECK(task_runner_->BelongsToCurrentThread()); | 89 DCHECK(task_runner_->BelongsToCurrentThread()); |
89 DCHECK(state_ == STATE_NORMAL || state_ == STATE_FLUSHING_DECODER || | 90 DCHECK(state_ == STATE_NORMAL || state_ == STATE_FLUSHING_DECODER || |
90 state_ == STATE_ERROR) << state_; | 91 state_ == STATE_ERROR || state_ == STATE_REINITIALIZING_DECODER || |
| 92 state_ == STATE_PENDING_DEMUXER_READ) |
| 93 << state_; |
91 // No two reads in the flight at any time. | 94 // No two reads in the flight at any time. |
92 DCHECK(read_cb_.is_null()); | 95 DCHECK(read_cb_.is_null()); |
93 // No read during resetting or stopping process. | 96 // No read during resetting or stopping process. |
94 DCHECK(reset_cb_.is_null()); | 97 DCHECK(reset_cb_.is_null()); |
95 DCHECK(stop_cb_.is_null()); | 98 DCHECK(stop_cb_.is_null()); |
96 | 99 |
| 100 read_cb_ = read_cb; |
| 101 |
97 if (state_ == STATE_ERROR) { | 102 if (state_ == STATE_ERROR) { |
98 task_runner_->PostTask(FROM_HERE, base::Bind( | 103 task_runner_->PostTask(FROM_HERE, |
99 read_cb, DECODE_ERROR, scoped_refptr<Output>())); | 104 base::Bind(base::ResetAndReturn(&read_cb_), |
| 105 DECODE_ERROR, |
| 106 scoped_refptr<Output>())); |
100 return; | 107 return; |
101 } | 108 } |
102 | 109 |
103 read_cb_ = read_cb; | 110 if (!ready_outputs_.empty()) { |
| 111 task_runner_->PostTask(FROM_HERE, base::Bind( |
| 112 base::ResetAndReturn(&read_cb_), OK, ready_outputs_.front())); |
| 113 ready_outputs_.pop_front(); |
| 114 } |
| 115 |
| 116 // Decoder may be in reinitializing state as result of the previous Read(). |
| 117 if (state_ == STATE_REINITIALIZING_DECODER) |
| 118 return; |
| 119 |
| 120 if (!CanDecodeMore()) |
| 121 return; |
104 | 122 |
105 if (state_ == STATE_FLUSHING_DECODER) { | 123 if (state_ == STATE_FLUSHING_DECODER) { |
106 FlushDecoder(); | 124 FlushDecoder(); |
107 return; | 125 return; |
108 } | 126 } |
109 | 127 |
110 scoped_refptr<Output> output = decoder_->GetDecodeOutput(); | 128 if (state_ != STATE_PENDING_DEMUXER_READ) |
111 | 129 ReadFromDemuxerStream(); |
112 // If the decoder has queued output ready to go we don't need a demuxer read. | |
113 if (output) { | |
114 task_runner_->PostTask( | |
115 FROM_HERE, base::Bind(base::ResetAndReturn(&read_cb_), OK, output)); | |
116 return; | |
117 } | |
118 | |
119 ReadFromDemuxerStream(); | |
120 } | 130 } |
121 | 131 |
122 template <DemuxerStream::Type StreamType> | 132 template <DemuxerStream::Type StreamType> |
123 void DecoderStream<StreamType>::Reset(const base::Closure& closure) { | 133 void DecoderStream<StreamType>::Reset(const base::Closure& closure) { |
124 FUNCTION_DVLOG(2); | 134 FUNCTION_DVLOG(2); |
125 DCHECK(task_runner_->BelongsToCurrentThread()); | 135 DCHECK(task_runner_->BelongsToCurrentThread()); |
126 DCHECK(state_ != STATE_UNINITIALIZED && state_ != STATE_STOPPED) << state_; | 136 DCHECK(state_ != STATE_UNINITIALIZED && state_ != STATE_STOPPED) << state_; |
127 DCHECK(reset_cb_.is_null()); | 137 DCHECK(reset_cb_.is_null()); |
128 DCHECK(stop_cb_.is_null()); | 138 DCHECK(stop_cb_.is_null()); |
129 | 139 |
130 reset_cb_ = closure; | 140 reset_cb_ = closure; |
131 | 141 |
| 142 if (!read_cb_.is_null()) { |
| 143 task_runner_->PostTask(FROM_HERE, base::Bind( |
| 144 base::ResetAndReturn(&read_cb_), ABORTED, scoped_refptr<Output>())); |
| 145 } |
| 146 |
| 147 ready_outputs_.clear(); |
| 148 |
132 // During decoder reinitialization, the Decoder does not need to be and | 149 // During decoder reinitialization, the Decoder does not need to be and |
133 // cannot be Reset(). |decrypting_demuxer_stream_| was reset before decoder | 150 // cannot be Reset(). |decrypting_demuxer_stream_| was reset before decoder |
134 // reinitialization. | 151 // reinitialization. |
135 if (state_ == STATE_REINITIALIZING_DECODER) | 152 if (state_ == STATE_REINITIALIZING_DECODER) |
136 return; | 153 return; |
137 | 154 |
138 // During pending demuxer read and when not using DecryptingDemuxerStream, | 155 // During pending demuxer read and when not using DecryptingDemuxerStream, |
139 // the Decoder will be reset after demuxer read is returned | 156 // the Decoder will be reset after demuxer read is returned |
140 // (in OnBufferReady()). | 157 // (in OnBufferReady()). |
141 if (state_ == STATE_PENDING_DEMUXER_READ && !decrypting_demuxer_stream_) | 158 if (state_ == STATE_PENDING_DEMUXER_READ && !decrypting_demuxer_stream_) |
142 return; | 159 return; |
143 | 160 |
144 // The Decoder API guarantees that if Decoder::Reset() is called during | |
145 // a pending decode, the decode callback must be fired before the reset | |
146 // callback is fired. Therefore, we can call Decoder::Reset() regardless | |
147 // of if we have a pending decode and always satisfy the reset callback when | |
148 // the decoder reset is finished. | |
149 if (decrypting_demuxer_stream_) { | 161 if (decrypting_demuxer_stream_) { |
150 decrypting_demuxer_stream_->Reset(base::Bind( | 162 decrypting_demuxer_stream_->Reset(base::Bind( |
151 &DecoderStream<StreamType>::ResetDecoder, weak_factory_.GetWeakPtr())); | 163 &DecoderStream<StreamType>::ResetDecoder, weak_factory_.GetWeakPtr())); |
152 return; | 164 return; |
153 } | 165 } |
154 | 166 |
155 ResetDecoder(); | 167 ResetDecoder(); |
156 } | 168 } |
157 | 169 |
158 template <DemuxerStream::Type StreamType> | 170 template <DemuxerStream::Type StreamType> |
159 void DecoderStream<StreamType>::Stop(const base::Closure& closure) { | 171 void DecoderStream<StreamType>::Stop(const base::Closure& closure) { |
160 FUNCTION_DVLOG(2); | 172 FUNCTION_DVLOG(2); |
161 DCHECK(task_runner_->BelongsToCurrentThread()); | 173 DCHECK(task_runner_->BelongsToCurrentThread()); |
162 DCHECK_NE(state_, STATE_STOPPED) << state_; | 174 DCHECK_NE(state_, STATE_STOPPED) << state_; |
163 DCHECK(stop_cb_.is_null()); | 175 DCHECK(stop_cb_.is_null()); |
164 | 176 |
165 stop_cb_ = closure; | 177 stop_cb_ = closure; |
166 | 178 |
167 if (state_ == STATE_INITIALIZING) { | 179 if (state_ == STATE_INITIALIZING) { |
168 decoder_selector_->Abort(); | 180 decoder_selector_->Abort(); |
169 return; | 181 return; |
170 } | 182 } |
171 | 183 |
172 DCHECK(init_cb_.is_null()); | 184 DCHECK(init_cb_.is_null()); |
173 | 185 |
174 // All pending callbacks will be dropped. | 186 // All pending callbacks will be dropped. |
175 weak_factory_.InvalidateWeakPtrs(); | 187 weak_factory_.InvalidateWeakPtrs(); |
176 | 188 |
177 // Post callbacks to prevent reentrance into this object. | 189 // Post callbacks to prevent reentrance into this object. |
178 if (!read_cb_.is_null()) | 190 if (!read_cb_.is_null()) { |
179 task_runner_->PostTask(FROM_HERE, base::Bind( | 191 task_runner_->PostTask(FROM_HERE, base::Bind( |
180 base::ResetAndReturn(&read_cb_), ABORTED, scoped_refptr<Output>())); | 192 base::ResetAndReturn(&read_cb_), ABORTED, scoped_refptr<Output>())); |
| 193 } |
181 if (!reset_cb_.is_null()) | 194 if (!reset_cb_.is_null()) |
182 task_runner_->PostTask(FROM_HERE, base::ResetAndReturn(&reset_cb_)); | 195 task_runner_->PostTask(FROM_HERE, base::ResetAndReturn(&reset_cb_)); |
183 | 196 |
184 if (decrypting_demuxer_stream_) { | 197 if (decrypting_demuxer_stream_) { |
185 decrypting_demuxer_stream_->Stop(base::Bind( | 198 decrypting_demuxer_stream_->Stop(base::Bind( |
186 &DecoderStream<StreamType>::StopDecoder, weak_factory_.GetWeakPtr())); | 199 &DecoderStream<StreamType>::StopDecoder, weak_factory_.GetWeakPtr())); |
187 return; | 200 return; |
188 } | 201 } |
189 | 202 |
190 // We may not have a |decoder_| if Stop() was called during initialization. | 203 // We may not have a |decoder_| if Stop() was called during initialization. |
(...skipping 15 matching lines...) Expand all Loading... |
206 return decoder_->CanReadWithoutStalling(); | 219 return decoder_->CanReadWithoutStalling(); |
207 } | 220 } |
208 | 221 |
209 template <> | 222 template <> |
210 bool DecoderStream<DemuxerStream::AUDIO>::CanReadWithoutStalling() const { | 223 bool DecoderStream<DemuxerStream::AUDIO>::CanReadWithoutStalling() const { |
211 DCHECK(task_runner_->BelongsToCurrentThread()); | 224 DCHECK(task_runner_->BelongsToCurrentThread()); |
212 return true; | 225 return true; |
213 } | 226 } |
214 | 227 |
215 template <DemuxerStream::Type StreamType> | 228 template <DemuxerStream::Type StreamType> |
| 229 bool DecoderStream<StreamType>::CanDecodeMore() const { |
| 230 DCHECK(task_runner_->BelongsToCurrentThread()); |
| 231 |
| 232 // Limit total number of outputs stored in |ready_outputs_| and being decoded. |
| 233 // It only makes sense to saturate decoder completely when output queue is |
| 234 // empty. |
| 235 int num_decodes = |
| 236 static_cast<int>(ready_outputs_.size()) + pending_decode_requests_; |
| 237 return num_decodes < decoder_->GetMaxDecodeRequests(); |
| 238 } |
| 239 |
| 240 template <> |
| 241 bool DecoderStream<DemuxerStream::AUDIO>::CanDecodeMore() const { |
| 242 DCHECK(task_runner_->BelongsToCurrentThread()); |
| 243 return !pending_decode_requests_ && ready_outputs_.empty(); |
| 244 } |
| 245 |
| 246 template <DemuxerStream::Type StreamType> |
216 void DecoderStream<StreamType>::OnDecoderSelected( | 247 void DecoderStream<StreamType>::OnDecoderSelected( |
217 scoped_ptr<Decoder> selected_decoder, | 248 scoped_ptr<Decoder> selected_decoder, |
218 scoped_ptr<DecryptingDemuxerStream> decrypting_demuxer_stream) { | 249 scoped_ptr<DecryptingDemuxerStream> decrypting_demuxer_stream) { |
219 FUNCTION_DVLOG(2); | 250 FUNCTION_DVLOG(2); |
220 DCHECK(task_runner_->BelongsToCurrentThread()); | 251 DCHECK(task_runner_->BelongsToCurrentThread()); |
221 DCHECK_EQ(state_, STATE_INITIALIZING) << state_; | 252 DCHECK_EQ(state_, STATE_INITIALIZING) << state_; |
222 DCHECK(!init_cb_.is_null()); | 253 DCHECK(!init_cb_.is_null()); |
223 DCHECK(read_cb_.is_null()); | 254 DCHECK(read_cb_.is_null()); |
224 DCHECK(reset_cb_.is_null()); | 255 DCHECK(reset_cb_.is_null()); |
225 | 256 |
(...skipping 22 matching lines...) Expand all Loading... |
248 | 279 |
249 template <DemuxerStream::Type StreamType> | 280 template <DemuxerStream::Type StreamType> |
250 void DecoderStream<StreamType>::SatisfyRead( | 281 void DecoderStream<StreamType>::SatisfyRead( |
251 Status status, | 282 Status status, |
252 const scoped_refptr<Output>& output) { | 283 const scoped_refptr<Output>& output) { |
253 DCHECK(!read_cb_.is_null()); | 284 DCHECK(!read_cb_.is_null()); |
254 base::ResetAndReturn(&read_cb_).Run(status, output); | 285 base::ResetAndReturn(&read_cb_).Run(status, output); |
255 } | 286 } |
256 | 287 |
257 template <DemuxerStream::Type StreamType> | 288 template <DemuxerStream::Type StreamType> |
258 void DecoderStream<StreamType>::AbortRead() { | |
259 // Abort read during pending reset. It is safe to fire the |read_cb_| directly | |
260 // instead of posting it because the renderer won't call into this class | |
261 // again when it's in kFlushing state. | |
262 // TODO(xhwang): Improve the resetting process to avoid this dependency on the | |
263 // caller. | |
264 DCHECK(!reset_cb_.is_null()); | |
265 SatisfyRead(ABORTED, NULL); | |
266 } | |
267 | |
268 template <DemuxerStream::Type StreamType> | |
269 void DecoderStream<StreamType>::Decode( | 289 void DecoderStream<StreamType>::Decode( |
270 const scoped_refptr<DecoderBuffer>& buffer) { | 290 const scoped_refptr<DecoderBuffer>& buffer) { |
271 FUNCTION_DVLOG(2); | 291 FUNCTION_DVLOG(2); |
272 DCHECK(state_ == STATE_NORMAL || state_ == STATE_FLUSHING_DECODER) << state_; | 292 DCHECK(state_ == STATE_NORMAL || state_ == STATE_FLUSHING_DECODER) << state_; |
273 DCHECK(!read_cb_.is_null()); | 293 DCHECK(CanDecodeMore()); |
274 DCHECK(reset_cb_.is_null()); | 294 DCHECK(reset_cb_.is_null()); |
275 DCHECK(stop_cb_.is_null()); | 295 DCHECK(stop_cb_.is_null()); |
276 DCHECK(buffer); | 296 DCHECK(buffer); |
277 | 297 |
278 int buffer_size = buffer->end_of_stream() ? 0 : buffer->data_size(); | 298 int buffer_size = buffer->end_of_stream() ? 0 : buffer->data_size(); |
279 | 299 |
280 TRACE_EVENT_ASYNC_BEGIN0("media", GetTraceString<StreamType>(), this); | 300 TRACE_EVENT_ASYNC_BEGIN0("media", GetTraceString<StreamType>(), this); |
| 301 ++pending_decode_requests_; |
281 decoder_->Decode(buffer, | 302 decoder_->Decode(buffer, |
282 base::Bind(&DecoderStream<StreamType>::OnDecodeOutputReady, | 303 base::Bind(&DecoderStream<StreamType>::OnDecodeOutputReady, |
283 weak_factory_.GetWeakPtr(), | 304 weak_factory_.GetWeakPtr(), |
284 buffer_size)); | 305 buffer_size)); |
285 } | 306 } |
286 | 307 |
287 template <DemuxerStream::Type StreamType> | 308 template <DemuxerStream::Type StreamType> |
288 void DecoderStream<StreamType>::FlushDecoder() { | 309 void DecoderStream<StreamType>::FlushDecoder() { |
289 Decode(DecoderBuffer::CreateEOSBuffer()); | 310 if (pending_decode_requests_ == 0) |
| 311 Decode(DecoderBuffer::CreateEOSBuffer()); |
290 } | 312 } |
291 | 313 |
292 template <DemuxerStream::Type StreamType> | 314 template <DemuxerStream::Type StreamType> |
293 void DecoderStream<StreamType>::OnDecodeOutputReady( | 315 void DecoderStream<StreamType>::OnDecodeOutputReady( |
294 int buffer_size, | 316 int buffer_size, |
295 typename Decoder::Status status, | 317 typename Decoder::Status status, |
296 const scoped_refptr<Output>& output) { | 318 const scoped_refptr<Output>& output) { |
297 FUNCTION_DVLOG(2); | 319 FUNCTION_DVLOG(2) << status << " " << output; |
298 DCHECK(state_ == STATE_NORMAL || state_ == STATE_FLUSHING_DECODER) << state_; | 320 DCHECK(state_ == STATE_NORMAL || state_ == STATE_FLUSHING_DECODER || |
299 DCHECK(!read_cb_.is_null()); | 321 state_ == STATE_PENDING_DEMUXER_READ || state_ == STATE_ERROR) |
| 322 << state_; |
300 DCHECK(stop_cb_.is_null()); | 323 DCHECK(stop_cb_.is_null()); |
301 DCHECK_EQ(status == Decoder::kOk, output != NULL); | 324 DCHECK_EQ(status == Decoder::kOk, output != NULL); |
| 325 DCHECK_GT(pending_decode_requests_, 0); |
| 326 |
| 327 --pending_decode_requests_; |
302 | 328 |
303 TRACE_EVENT_ASYNC_END0("media", GetTraceString<StreamType>(), this); | 329 TRACE_EVENT_ASYNC_END0("media", GetTraceString<StreamType>(), this); |
304 | 330 |
| 331 if (state_ == STATE_ERROR) { |
| 332 DCHECK(read_cb_.is_null()); |
| 333 return; |
| 334 } |
| 335 |
305 if (status == Decoder::kDecodeError) { | 336 if (status == Decoder::kDecodeError) { |
306 state_ = STATE_ERROR; | 337 state_ = STATE_ERROR; |
307 SatisfyRead(DECODE_ERROR, NULL); | 338 ready_outputs_.clear(); |
| 339 if (!read_cb_.is_null()) |
| 340 SatisfyRead(DECODE_ERROR, NULL); |
308 return; | 341 return; |
309 } | 342 } |
310 | 343 |
311 if (status == Decoder::kDecryptError) { | 344 if (status == Decoder::kDecryptError) { |
312 state_ = STATE_ERROR; | 345 state_ = STATE_ERROR; |
313 SatisfyRead(DECRYPT_ERROR, NULL); | 346 ready_outputs_.clear(); |
| 347 if (!read_cb_.is_null()) |
| 348 SatisfyRead(DECRYPT_ERROR, NULL); |
314 return; | 349 return; |
315 } | 350 } |
316 | 351 |
317 if (status == Decoder::kAborted) { | 352 if (status == Decoder::kAborted) { |
318 SatisfyRead(ABORTED, NULL); | 353 if (!read_cb_.is_null()) |
| 354 SatisfyRead(ABORTED, NULL); |
319 return; | 355 return; |
320 } | 356 } |
321 | 357 |
322 // Any successful decode counts! | 358 // Any successful decode counts! |
323 if (buffer_size > 0) { | 359 if (buffer_size > 0) { |
324 StreamTraits::ReportStatistics(statistics_cb_, buffer_size); | 360 StreamTraits::ReportStatistics(statistics_cb_, buffer_size); |
325 } | 361 } |
326 | 362 |
327 // Drop decoding result if Reset() was called during decoding. | 363 // Drop decoding result if Reset() was called during decoding. |
328 // The resetting process will be handled when the decoder is reset. | 364 // The resetting process will be handled when the decoder is reset. |
329 if (!reset_cb_.is_null()) { | 365 if (!reset_cb_.is_null()) |
330 AbortRead(); | |
331 return; | 366 return; |
332 } | |
333 | 367 |
334 // Decoder flushed. Reinitialize the decoder. | 368 // Decoder flushed. Reinitialize the decoder. |
335 if (state_ == STATE_FLUSHING_DECODER && | 369 if (state_ == STATE_FLUSHING_DECODER && |
336 status == Decoder::kOk && output->end_of_stream()) { | 370 status == Decoder::kOk && output->end_of_stream()) { |
337 ReinitializeDecoder(); | 371 ReinitializeDecoder(); |
338 return; | 372 return; |
339 } | 373 } |
340 | 374 |
341 if (status == Decoder::kNotEnoughData) { | 375 if (status == Decoder::kNotEnoughData) { |
342 if (state_ == STATE_NORMAL) | 376 if (state_ == STATE_NORMAL) |
343 ReadFromDemuxerStream(); | 377 ReadFromDemuxerStream(); |
344 else if (state_ == STATE_FLUSHING_DECODER) | 378 else if (state_ == STATE_FLUSHING_DECODER) |
345 FlushDecoder(); | 379 FlushDecoder(); |
346 return; | 380 return; |
347 } | 381 } |
348 | 382 |
349 DCHECK(output); | 383 DCHECK(output); |
350 SatisfyRead(OK, output); | 384 |
| 385 // Store decoded output. |
| 386 ready_outputs_.push_back(output); |
| 387 scoped_refptr<Output> extra_output; |
| 388 while ((extra_output = decoder_->GetDecodeOutput()) != NULL) { |
| 389 ready_outputs_.push_back(extra_output); |
| 390 } |
| 391 |
| 392 // Satisfy outstanding read request, if any. |
| 393 if (!read_cb_.is_null()) { |
| 394 scoped_refptr<Output> read_result = ready_outputs_.front(); |
| 395 ready_outputs_.pop_front(); |
| 396 SatisfyRead(OK, output); |
| 397 } |
351 } | 398 } |
352 | 399 |
353 template <DemuxerStream::Type StreamType> | 400 template <DemuxerStream::Type StreamType> |
354 void DecoderStream<StreamType>::ReadFromDemuxerStream() { | 401 void DecoderStream<StreamType>::ReadFromDemuxerStream() { |
355 FUNCTION_DVLOG(2); | 402 FUNCTION_DVLOG(2); |
356 DCHECK_EQ(state_, STATE_NORMAL) << state_; | 403 DCHECK_EQ(state_, STATE_NORMAL) << state_; |
357 DCHECK(!read_cb_.is_null()); | 404 DCHECK(CanDecodeMore()); |
358 DCHECK(reset_cb_.is_null()); | 405 DCHECK(reset_cb_.is_null()); |
359 DCHECK(stop_cb_.is_null()); | 406 DCHECK(stop_cb_.is_null()); |
360 | 407 |
361 state_ = STATE_PENDING_DEMUXER_READ; | 408 state_ = STATE_PENDING_DEMUXER_READ; |
362 stream_->Read(base::Bind(&DecoderStream<StreamType>::OnBufferReady, | 409 stream_->Read(base::Bind(&DecoderStream<StreamType>::OnBufferReady, |
363 weak_factory_.GetWeakPtr())); | 410 weak_factory_.GetWeakPtr())); |
364 } | 411 } |
365 | 412 |
366 template <DemuxerStream::Type StreamType> | 413 template <DemuxerStream::Type StreamType> |
367 void DecoderStream<StreamType>::OnBufferReady( | 414 void DecoderStream<StreamType>::OnBufferReady( |
368 DemuxerStream::Status status, | 415 DemuxerStream::Status status, |
369 const scoped_refptr<DecoderBuffer>& buffer) { | 416 const scoped_refptr<DecoderBuffer>& buffer) { |
370 FUNCTION_DVLOG(2) << ": " << status; | 417 FUNCTION_DVLOG(2) << ": " << status; |
371 DCHECK(task_runner_->BelongsToCurrentThread()); | 418 DCHECK(task_runner_->BelongsToCurrentThread()); |
372 DCHECK_EQ(state_, STATE_PENDING_DEMUXER_READ) << state_; | 419 DCHECK(state_ == STATE_PENDING_DEMUXER_READ || state_ == STATE_ERROR || |
| 420 state_ == STATE_STOPPED) |
| 421 << state_; |
373 DCHECK_EQ(buffer.get() != NULL, status == DemuxerStream::kOk) << status; | 422 DCHECK_EQ(buffer.get() != NULL, status == DemuxerStream::kOk) << status; |
374 DCHECK(!read_cb_.is_null()); | |
375 DCHECK(stop_cb_.is_null()); | 423 DCHECK(stop_cb_.is_null()); |
376 | 424 |
| 425 // Decoding has been stopped (e.g due to an error). |
| 426 if (state_ != STATE_PENDING_DEMUXER_READ) { |
| 427 DCHECK(state_ == STATE_ERROR || state_ == STATE_STOPPED); |
| 428 DCHECK(read_cb_.is_null()); |
| 429 return; |
| 430 } |
| 431 |
377 state_ = STATE_NORMAL; | 432 state_ = STATE_NORMAL; |
378 | 433 |
379 if (status == DemuxerStream::kConfigChanged) { | 434 if (status == DemuxerStream::kConfigChanged) { |
380 FUNCTION_DVLOG(2) << ": " << "ConfigChanged"; | 435 FUNCTION_DVLOG(2) << ": " << "ConfigChanged"; |
381 DCHECK(stream_->SupportsConfigChanges()); | 436 DCHECK(stream_->SupportsConfigChanges()); |
382 | 437 |
383 if (!config_change_observer_cb_.is_null()) | 438 if (!config_change_observer_cb_.is_null()) |
384 config_change_observer_cb_.Run(); | 439 config_change_observer_cb_.Run(); |
385 | 440 |
386 state_ = STATE_FLUSHING_DECODER; | 441 state_ = STATE_FLUSHING_DECODER; |
387 if (!reset_cb_.is_null()) { | 442 if (!reset_cb_.is_null()) { |
388 AbortRead(); | |
389 // If we are using DecryptingDemuxerStream, we already called DDS::Reset() | 443 // If we are using DecryptingDemuxerStream, we already called DDS::Reset() |
390 // which will continue the resetting process in it's callback. | 444 // which will continue the resetting process in it's callback. |
391 if (!decrypting_demuxer_stream_) | 445 if (!decrypting_demuxer_stream_) |
392 Reset(base::ResetAndReturn(&reset_cb_)); | 446 Reset(base::ResetAndReturn(&reset_cb_)); |
393 // Reinitialization will continue after Reset() is done. | 447 // Reinitialization will continue after Reset() is done. |
394 } else { | 448 } else { |
395 FlushDecoder(); | 449 FlushDecoder(); |
396 } | 450 } |
397 return; | 451 return; |
398 } | 452 } |
399 | 453 |
400 if (!reset_cb_.is_null()) { | 454 if (!reset_cb_.is_null()) { |
401 AbortRead(); | |
402 // If we are using DecryptingDemuxerStream, we already called DDS::Reset() | 455 // If we are using DecryptingDemuxerStream, we already called DDS::Reset() |
403 // which will continue the resetting process in it's callback. | 456 // which will continue the resetting process in it's callback. |
404 if (!decrypting_demuxer_stream_) | 457 if (!decrypting_demuxer_stream_) |
405 Reset(base::ResetAndReturn(&reset_cb_)); | 458 Reset(base::ResetAndReturn(&reset_cb_)); |
406 return; | 459 return; |
407 } | 460 } |
408 | 461 |
409 if (status == DemuxerStream::kAborted) { | 462 if (status == DemuxerStream::kAborted) { |
410 SatisfyRead(DEMUXER_READ_ABORTED, NULL); | 463 SatisfyRead(DEMUXER_READ_ABORTED, NULL); |
411 return; | 464 return; |
412 } | 465 } |
413 | 466 |
414 if (!splice_observer_cb_.is_null() && !buffer->end_of_stream()) { | 467 if (!splice_observer_cb_.is_null() && !buffer->end_of_stream()) { |
415 const bool has_splice_ts = buffer->splice_timestamp() != kNoTimestamp(); | 468 const bool has_splice_ts = buffer->splice_timestamp() != kNoTimestamp(); |
416 if (active_splice_ || has_splice_ts) { | 469 if (active_splice_ || has_splice_ts) { |
417 splice_observer_cb_.Run(buffer->splice_timestamp()); | 470 splice_observer_cb_.Run(buffer->splice_timestamp()); |
418 active_splice_ = has_splice_ts; | 471 active_splice_ = has_splice_ts; |
419 } | 472 } |
420 } | 473 } |
421 | 474 |
422 DCHECK(status == DemuxerStream::kOk) << status; | 475 DCHECK(status == DemuxerStream::kOk) << status; |
423 Decode(buffer); | 476 Decode(buffer); |
| 477 |
| 478 // Read more data if the decoder supports multiple parallel decoding requests. |
| 479 if (CanDecodeMore() && !buffer->end_of_stream()) |
| 480 ReadFromDemuxerStream(); |
424 } | 481 } |
425 | 482 |
426 template <DemuxerStream::Type StreamType> | 483 template <DemuxerStream::Type StreamType> |
427 void DecoderStream<StreamType>::ReinitializeDecoder() { | 484 void DecoderStream<StreamType>::ReinitializeDecoder() { |
428 FUNCTION_DVLOG(2); | 485 FUNCTION_DVLOG(2); |
429 DCHECK(task_runner_->BelongsToCurrentThread()); | 486 DCHECK(task_runner_->BelongsToCurrentThread()); |
430 DCHECK_EQ(state_, STATE_FLUSHING_DECODER) << state_; | 487 DCHECK_EQ(state_, STATE_FLUSHING_DECODER) << state_; |
| 488 DCHECK_EQ(pending_decode_requests_, 0); |
431 | 489 |
432 DCHECK(StreamTraits::GetDecoderConfig(*stream_).IsValidConfig()); | 490 DCHECK(StreamTraits::GetDecoderConfig(*stream_).IsValidConfig()); |
433 state_ = STATE_REINITIALIZING_DECODER; | 491 state_ = STATE_REINITIALIZING_DECODER; |
434 DecoderStreamTraits<StreamType>::Initialize( | 492 DecoderStreamTraits<StreamType>::Initialize( |
435 decoder_.get(), | 493 decoder_.get(), |
436 StreamTraits::GetDecoderConfig(*stream_), | 494 StreamTraits::GetDecoderConfig(*stream_), |
437 low_delay_, | 495 low_delay_, |
438 base::Bind(&DecoderStream<StreamType>::OnDecoderReinitialized, | 496 base::Bind(&DecoderStream<StreamType>::OnDecoderReinitialized, |
439 weak_factory_.GetWeakPtr())); | 497 weak_factory_.GetWeakPtr())); |
440 } | 498 } |
441 | 499 |
442 template <DemuxerStream::Type StreamType> | 500 template <DemuxerStream::Type StreamType> |
443 void DecoderStream<StreamType>::OnDecoderReinitialized(PipelineStatus status) { | 501 void DecoderStream<StreamType>::OnDecoderReinitialized(PipelineStatus status) { |
444 FUNCTION_DVLOG(2); | 502 FUNCTION_DVLOG(2); |
445 DCHECK(task_runner_->BelongsToCurrentThread()); | 503 DCHECK(task_runner_->BelongsToCurrentThread()); |
446 DCHECK_EQ(state_, STATE_REINITIALIZING_DECODER) << state_; | 504 DCHECK_EQ(state_, STATE_REINITIALIZING_DECODER) << state_; |
447 DCHECK(stop_cb_.is_null()); | 505 DCHECK(stop_cb_.is_null()); |
448 | 506 |
449 // ReinitializeDecoder() can be called in two cases: | 507 // ReinitializeDecoder() can be called in two cases: |
450 // 1, Flushing decoder finished (see OnDecodeOutputReady()). | 508 // 1, Flushing decoder finished (see OnDecodeOutputReady()). |
451 // 2, Reset() was called during flushing decoder (see OnDecoderReset()). | 509 // 2, Reset() was called during flushing decoder (see OnDecoderReset()). |
452 // Also, Reset() can be called during pending ReinitializeDecoder(). | 510 // Also, Reset() can be called during pending ReinitializeDecoder(). |
453 // This function needs to handle them all! | 511 // This function needs to handle them all! |
454 | 512 |
455 state_ = (status == PIPELINE_OK) ? STATE_NORMAL : STATE_ERROR; | 513 state_ = (status == PIPELINE_OK) ? STATE_NORMAL : STATE_ERROR; |
456 | 514 |
457 if (!reset_cb_.is_null()) { | 515 if (!reset_cb_.is_null()) { |
458 if (!read_cb_.is_null()) | |
459 AbortRead(); | |
460 base::ResetAndReturn(&reset_cb_).Run(); | 516 base::ResetAndReturn(&reset_cb_).Run(); |
| 517 return; |
461 } | 518 } |
462 | 519 |
463 if (read_cb_.is_null()) | 520 if (read_cb_.is_null()) |
464 return; | 521 return; |
465 | 522 |
466 if (state_ == STATE_ERROR) { | 523 if (state_ == STATE_ERROR) { |
467 SatisfyRead(DECODE_ERROR, NULL); | 524 SatisfyRead(DECODE_ERROR, NULL); |
468 return; | 525 return; |
469 } | 526 } |
470 | 527 |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
518 decrypting_demuxer_stream_.reset(); | 575 decrypting_demuxer_stream_.reset(); |
519 // Post |stop_cb_| because pending |read_cb_| and/or |reset_cb_| are also | 576 // Post |stop_cb_| because pending |read_cb_| and/or |reset_cb_| are also |
520 // posted in Stop(). | 577 // posted in Stop(). |
521 task_runner_->PostTask(FROM_HERE, base::ResetAndReturn(&stop_cb_)); | 578 task_runner_->PostTask(FROM_HERE, base::ResetAndReturn(&stop_cb_)); |
522 } | 579 } |
523 | 580 |
524 template class DecoderStream<DemuxerStream::VIDEO>; | 581 template class DecoderStream<DemuxerStream::VIDEO>; |
525 template class DecoderStream<DemuxerStream::AUDIO>; | 582 template class DecoderStream<DemuxerStream::AUDIO>; |
526 | 583 |
527 } // namespace media | 584 } // namespace media |
OLD | NEW |