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 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
43 const scoped_refptr<base::SingleThreadTaskRunner>& task_runner, | 43 const scoped_refptr<base::SingleThreadTaskRunner>& task_runner, |
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 weak_factory_(this) {} | 53 pending_decode_requests_(0), |
54 weak_factory_(this) { | |
55 } | |
54 | 56 |
55 template <DemuxerStream::Type StreamType> | 57 template <DemuxerStream::Type StreamType> |
56 DecoderStream<StreamType>::~DecoderStream() { | 58 DecoderStream<StreamType>::~DecoderStream() { |
57 DCHECK(state_ == STATE_UNINITIALIZED || state_ == STATE_STOPPED) << state_; | 59 DCHECK(state_ == STATE_UNINITIALIZED || state_ == STATE_STOPPED) << state_; |
58 } | 60 } |
59 | 61 |
60 template <DemuxerStream::Type StreamType> | 62 template <DemuxerStream::Type StreamType> |
61 void DecoderStream<StreamType>::Initialize(DemuxerStream* stream, | 63 void DecoderStream<StreamType>::Initialize(DemuxerStream* stream, |
62 const StatisticsCB& statistics_cb, | 64 const StatisticsCB& statistics_cb, |
63 const InitCB& init_cb) { | 65 const InitCB& init_cb) { |
(...skipping 13 matching lines...) Expand all Loading... | |
77 stream, | 79 stream, |
78 base::Bind(&DecoderStream<StreamType>::OnDecoderSelected, | 80 base::Bind(&DecoderStream<StreamType>::OnDecoderSelected, |
79 weak_factory_.GetWeakPtr())); | 81 weak_factory_.GetWeakPtr())); |
80 } | 82 } |
81 | 83 |
82 template <DemuxerStream::Type StreamType> | 84 template <DemuxerStream::Type StreamType> |
83 void DecoderStream<StreamType>::Read(const ReadCB& read_cb) { | 85 void DecoderStream<StreamType>::Read(const ReadCB& read_cb) { |
84 FUNCTION_DVLOG(2); | 86 FUNCTION_DVLOG(2); |
85 DCHECK(task_runner_->BelongsToCurrentThread()); | 87 DCHECK(task_runner_->BelongsToCurrentThread()); |
86 DCHECK(state_ == STATE_NORMAL || state_ == STATE_FLUSHING_DECODER || | 88 DCHECK(state_ == STATE_NORMAL || state_ == STATE_FLUSHING_DECODER || |
87 state_ == STATE_ERROR) << state_; | 89 state_ == STATE_ERROR || state_ == STATE_REINITIALIZING_DECODER) |
xhwang
2014/04/17 01:06:47
|state_| can also be STATE_PENDING_DEMUXER_READ. I
Sergey Ulanov
2014/04/23 02:44:21
Done. Also added a unittest that coverts this case
| |
90 << state_; | |
88 // No two reads in the flight at any time. | 91 // No two reads in the flight at any time. |
89 DCHECK(read_cb_.is_null()); | 92 DCHECK(read_cb_.is_null()); |
90 // No read during resetting or stopping process. | 93 // No read during resetting or stopping process. |
91 DCHECK(reset_cb_.is_null()); | 94 DCHECK(reset_cb_.is_null()); |
92 DCHECK(stop_cb_.is_null()); | 95 DCHECK(stop_cb_.is_null()); |
93 | 96 |
94 if (state_ == STATE_ERROR) { | 97 if (state_ == STATE_ERROR) { |
95 task_runner_->PostTask(FROM_HERE, base::Bind( | 98 task_runner_->PostTask(FROM_HERE, base::Bind( |
96 read_cb, DECODE_ERROR, scoped_refptr<Output>())); | 99 read_cb, DECODE_ERROR, scoped_refptr<Output>())); |
97 return; | 100 return; |
98 } | 101 } |
99 | 102 |
100 read_cb_ = read_cb; | 103 read_cb_ = read_cb; |
101 | 104 |
105 if (!ready_output_buffers_.empty()) { | |
106 task_runner_->PostTask(FROM_HERE, base::Bind( | |
107 base::ResetAndReturn(&read_cb_), OK, ready_output_buffers_.front())); | |
108 ready_output_buffers_.pop_front(); | |
109 } | |
110 | |
111 if (state_ == STATE_REINITIALIZING_DECODER) | |
xhwang
2014/04/17 01:06:47
Might worth a comment how this could happen.
Sergey Ulanov
2014/04/23 02:44:21
Done.
| |
112 return; | |
113 | |
114 if (!CanDecodeAnotherBuffer()) | |
115 return; | |
116 | |
102 if (state_ == STATE_FLUSHING_DECODER) { | 117 if (state_ == STATE_FLUSHING_DECODER) { |
103 FlushDecoder(); | 118 FlushDecoder(); |
104 return; | 119 return; |
105 } | 120 } |
106 | 121 |
107 scoped_refptr<Output> output = decoder_->GetDecodeOutput(); | 122 if (state_ != STATE_PENDING_DEMUXER_READ) |
108 | 123 ReadFromDemuxerStream(); |
109 // If the decoder has queued output ready to go we don't need a demuxer read. | |
110 if (output) { | |
111 task_runner_->PostTask( | |
112 FROM_HERE, base::Bind(base::ResetAndReturn(&read_cb_), OK, output)); | |
113 return; | |
114 } | |
115 | |
116 ReadFromDemuxerStream(); | |
117 } | 124 } |
118 | 125 |
119 template <DemuxerStream::Type StreamType> | 126 template <DemuxerStream::Type StreamType> |
120 void DecoderStream<StreamType>::Reset(const base::Closure& closure) { | 127 void DecoderStream<StreamType>::Reset(const base::Closure& closure) { |
121 FUNCTION_DVLOG(2); | 128 FUNCTION_DVLOG(2); |
122 DCHECK(task_runner_->BelongsToCurrentThread()); | 129 DCHECK(task_runner_->BelongsToCurrentThread()); |
123 DCHECK(state_ != STATE_UNINITIALIZED && state_ != STATE_STOPPED) << state_; | 130 DCHECK(state_ != STATE_UNINITIALIZED && state_ != STATE_STOPPED) << state_; |
124 DCHECK(reset_cb_.is_null()); | 131 DCHECK(reset_cb_.is_null()); |
125 DCHECK(stop_cb_.is_null()); | 132 DCHECK(stop_cb_.is_null()); |
126 | 133 |
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
203 return decoder_->CanReadWithoutStalling(); | 210 return decoder_->CanReadWithoutStalling(); |
204 } | 211 } |
205 | 212 |
206 template <> | 213 template <> |
207 bool DecoderStream<DemuxerStream::AUDIO>::CanReadWithoutStalling() const { | 214 bool DecoderStream<DemuxerStream::AUDIO>::CanReadWithoutStalling() const { |
208 DCHECK(task_runner_->BelongsToCurrentThread()); | 215 DCHECK(task_runner_->BelongsToCurrentThread()); |
209 return true; | 216 return true; |
210 } | 217 } |
211 | 218 |
212 template <DemuxerStream::Type StreamType> | 219 template <DemuxerStream::Type StreamType> |
220 bool DecoderStream<StreamType>::CanDecodeAnotherBuffer() const { | |
221 DCHECK(task_runner_->BelongsToCurrentThread()); | |
222 int buffers_in_queue = | |
xhwang
2014/04/17 01:06:47
In media/ we use "buffer" for compressed data, e.g
Sergey Ulanov
2014/04/23 02:44:21
Renamed
buffers_in_queue -> num_decodes
ready_
| |
223 static_cast<int>(ready_output_buffers_.size()) + pending_decode_requests_; | |
224 return buffers_in_queue < decoder_->GetMaxDecodeRequests(); | |
xhwang
2014/04/17 01:06:47
Probably add a comment about why we choose to do t
Sergey Ulanov
2014/04/23 02:44:21
Done.
| |
225 } | |
226 | |
227 template <> | |
228 bool DecoderStream<DemuxerStream::AUDIO>::CanDecodeAnotherBuffer() const { | |
229 DCHECK(task_runner_->BelongsToCurrentThread()); | |
230 return !pending_decode_requests_ && ready_output_buffers_.empty(); | |
231 } | |
232 | |
233 template <DemuxerStream::Type StreamType> | |
213 void DecoderStream<StreamType>::OnDecoderSelected( | 234 void DecoderStream<StreamType>::OnDecoderSelected( |
214 scoped_ptr<Decoder> selected_decoder, | 235 scoped_ptr<Decoder> selected_decoder, |
215 scoped_ptr<DecryptingDemuxerStream> decrypting_demuxer_stream) { | 236 scoped_ptr<DecryptingDemuxerStream> decrypting_demuxer_stream) { |
216 FUNCTION_DVLOG(2); | 237 FUNCTION_DVLOG(2); |
217 DCHECK(task_runner_->BelongsToCurrentThread()); | 238 DCHECK(task_runner_->BelongsToCurrentThread()); |
218 DCHECK_EQ(state_, STATE_INITIALIZING) << state_; | 239 DCHECK_EQ(state_, STATE_INITIALIZING) << state_; |
219 DCHECK(!init_cb_.is_null()); | 240 DCHECK(!init_cb_.is_null()); |
220 DCHECK(read_cb_.is_null()); | 241 DCHECK(read_cb_.is_null()); |
221 DCHECK(reset_cb_.is_null()); | 242 DCHECK(reset_cb_.is_null()); |
222 | 243 |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
260 // caller. | 281 // caller. |
261 DCHECK(!reset_cb_.is_null()); | 282 DCHECK(!reset_cb_.is_null()); |
262 SatisfyRead(ABORTED, NULL); | 283 SatisfyRead(ABORTED, NULL); |
263 } | 284 } |
264 | 285 |
265 template <DemuxerStream::Type StreamType> | 286 template <DemuxerStream::Type StreamType> |
266 void DecoderStream<StreamType>::Decode( | 287 void DecoderStream<StreamType>::Decode( |
267 const scoped_refptr<DecoderBuffer>& buffer) { | 288 const scoped_refptr<DecoderBuffer>& buffer) { |
268 FUNCTION_DVLOG(2); | 289 FUNCTION_DVLOG(2); |
269 DCHECK(state_ == STATE_NORMAL || state_ == STATE_FLUSHING_DECODER) << state_; | 290 DCHECK(state_ == STATE_NORMAL || state_ == STATE_FLUSHING_DECODER) << state_; |
270 DCHECK(!read_cb_.is_null()); | 291 DCHECK(CanDecodeAnotherBuffer()); |
271 DCHECK(reset_cb_.is_null()); | 292 DCHECK(reset_cb_.is_null()); |
272 DCHECK(stop_cb_.is_null()); | 293 DCHECK(stop_cb_.is_null()); |
273 DCHECK(buffer); | 294 DCHECK(buffer); |
274 | 295 |
275 int buffer_size = buffer->end_of_stream() ? 0 : buffer->data_size(); | 296 int buffer_size = buffer->end_of_stream() ? 0 : buffer->data_size(); |
276 | 297 |
277 TRACE_EVENT_ASYNC_BEGIN0("media", GetTraceString<StreamType>(), this); | 298 TRACE_EVENT_ASYNC_BEGIN0("media", GetTraceString<StreamType>(), this); |
299 ++pending_decode_requests_; | |
278 decoder_->Decode(buffer, | 300 decoder_->Decode(buffer, |
279 base::Bind(&DecoderStream<StreamType>::OnDecodeOutputReady, | 301 base::Bind(&DecoderStream<StreamType>::OnDecodeOutputReady, |
280 weak_factory_.GetWeakPtr(), | 302 weak_factory_.GetWeakPtr(), |
281 buffer_size)); | 303 buffer_size)); |
282 } | 304 } |
283 | 305 |
284 template <DemuxerStream::Type StreamType> | 306 template <DemuxerStream::Type StreamType> |
285 void DecoderStream<StreamType>::FlushDecoder() { | 307 void DecoderStream<StreamType>::FlushDecoder() { |
286 Decode(DecoderBuffer::CreateEOSBuffer()); | 308 Decode(DecoderBuffer::CreateEOSBuffer()); |
287 } | 309 } |
288 | 310 |
289 template <DemuxerStream::Type StreamType> | 311 template <DemuxerStream::Type StreamType> |
290 void DecoderStream<StreamType>::OnDecodeOutputReady( | 312 void DecoderStream<StreamType>::OnDecodeOutputReady( |
291 int buffer_size, | 313 int buffer_size, |
292 typename Decoder::Status status, | 314 typename Decoder::Status status, |
293 const scoped_refptr<Output>& output) { | 315 const scoped_refptr<Output>& output) { |
294 FUNCTION_DVLOG(2); | 316 FUNCTION_DVLOG(2); |
295 DCHECK(state_ == STATE_NORMAL || state_ == STATE_FLUSHING_DECODER) << state_; | 317 DCHECK(state_ == STATE_NORMAL || state_ == STATE_FLUSHING_DECODER) << state_; |
296 DCHECK(!read_cb_.is_null()); | |
297 DCHECK(stop_cb_.is_null()); | 318 DCHECK(stop_cb_.is_null()); |
298 DCHECK_EQ(status == Decoder::kOk, output != NULL); | 319 DCHECK_EQ(status == Decoder::kOk, output != NULL); |
320 DCHECK_GT(pending_decode_requests_, 0); | |
321 | |
322 --pending_decode_requests_; | |
299 | 323 |
300 TRACE_EVENT_ASYNC_END0("media", GetTraceString<StreamType>(), this); | 324 TRACE_EVENT_ASYNC_END0("media", GetTraceString<StreamType>(), this); |
301 | 325 |
302 if (status == Decoder::kDecodeError) { | 326 if (status == Decoder::kDecodeError) { |
303 state_ = STATE_ERROR; | 327 state_ = STATE_ERROR; |
304 SatisfyRead(DECODE_ERROR, NULL); | 328 SatisfyRead(DECODE_ERROR, NULL); |
305 return; | 329 return; |
306 } | 330 } |
xhwang
2014/04/17 01:06:47
Now we could have multiple Decode() calls in fligh
Sergey Ulanov
2014/04/23 02:44:21
Done. Also added unittests for this case.
| |
307 | 331 |
308 if (status == Decoder::kDecryptError) { | 332 if (status == Decoder::kDecryptError) { |
309 state_ = STATE_ERROR; | 333 state_ = STATE_ERROR; |
310 SatisfyRead(DECRYPT_ERROR, NULL); | 334 SatisfyRead(DECRYPT_ERROR, NULL); |
311 return; | 335 return; |
312 } | 336 } |
313 | 337 |
314 if (status == Decoder::kAborted) { | 338 if (status == Decoder::kAborted) { |
315 SatisfyRead(ABORTED, NULL); | 339 SatisfyRead(ABORTED, NULL); |
316 return; | 340 return; |
317 } | 341 } |
318 | 342 |
319 // Any successful decode counts! | 343 // Any successful decode counts! |
320 if (buffer_size > 0) { | 344 if (buffer_size > 0) { |
321 StreamTraits::ReportStatistics(statistics_cb_, buffer_size); | 345 StreamTraits::ReportStatistics(statistics_cb_, buffer_size); |
322 } | 346 } |
323 | 347 |
324 // Drop decoding result if Reset() was called during decoding. | 348 // Drop decoding result if Reset() was called during decoding. |
325 // The resetting process will be handled when the decoder is reset. | 349 // The resetting process will be handled when the decoder is reset. |
326 if (!reset_cb_.is_null()) { | 350 if (!reset_cb_.is_null()) { |
327 AbortRead(); | 351 AbortRead(); |
xhwang
2014/04/17 01:06:47
ditto. We only need to AbortRead() once.
Sergey Ulanov
2014/04/23 02:44:21
Removed AbortRead(). Reads are aborted from Reset(
| |
328 return; | 352 return; |
329 } | 353 } |
330 | 354 |
331 // Decoder flushed. Reinitialize the decoder. | 355 // Decoder flushed. Reinitialize the decoder. |
332 if (state_ == STATE_FLUSHING_DECODER && | 356 if (state_ == STATE_FLUSHING_DECODER && |
333 status == Decoder::kOk && output->end_of_stream()) { | 357 status == Decoder::kOk && output->end_of_stream()) { |
334 ReinitializeDecoder(); | 358 ReinitializeDecoder(); |
335 return; | 359 return; |
336 } | 360 } |
337 | 361 |
338 if (status == Decoder::kNotEnoughData) { | 362 if (status == Decoder::kNotEnoughData) { |
339 if (state_ == STATE_NORMAL) | 363 if (state_ == STATE_NORMAL) |
340 ReadFromDemuxerStream(); | 364 ReadFromDemuxerStream(); |
341 else if (state_ == STATE_FLUSHING_DECODER) | 365 else if (state_ == STATE_FLUSHING_DECODER) |
342 FlushDecoder(); | 366 FlushDecoder(); |
343 return; | 367 return; |
344 } | 368 } |
345 | 369 |
346 DCHECK(output); | 370 DCHECK(output); |
347 SatisfyRead(OK, output); | 371 |
372 // Store decoded output. | |
373 ready_output_buffers_.push_back(output); | |
374 scoped_refptr<Output> extra_output; | |
375 while ((extra_output = decoder_->GetDecodeOutput()) != NULL) { | |
xhwang
2014/04/17 01:06:47
Now GetDecodeOutput() will always return NULL for
Sergey Ulanov
2014/04/23 02:44:21
Added TODO in video_decoder.h.
| |
376 ready_output_buffers_.push_back(extra_output); | |
377 } | |
378 | |
379 // Satisfy outstanding read request, if any. | |
380 if (!read_cb_.is_null()) { | |
381 scoped_refptr<Output> read_result = ready_output_buffers_.front(); | |
382 ready_output_buffers_.pop_front(); | |
383 SatisfyRead(OK, output); | |
384 } | |
348 } | 385 } |
349 | 386 |
350 template <DemuxerStream::Type StreamType> | 387 template <DemuxerStream::Type StreamType> |
351 void DecoderStream<StreamType>::ReadFromDemuxerStream() { | 388 void DecoderStream<StreamType>::ReadFromDemuxerStream() { |
352 FUNCTION_DVLOG(2); | 389 FUNCTION_DVLOG(2); |
353 DCHECK_EQ(state_, STATE_NORMAL) << state_; | 390 DCHECK_EQ(state_, STATE_NORMAL) << state_; |
354 DCHECK(!read_cb_.is_null()); | 391 DCHECK(CanDecodeAnotherBuffer()); |
355 DCHECK(reset_cb_.is_null()); | 392 DCHECK(reset_cb_.is_null()); |
356 DCHECK(stop_cb_.is_null()); | 393 DCHECK(stop_cb_.is_null()); |
357 | 394 |
358 state_ = STATE_PENDING_DEMUXER_READ; | 395 state_ = STATE_PENDING_DEMUXER_READ; |
359 stream_->Read(base::Bind(&DecoderStream<StreamType>::OnBufferReady, | 396 stream_->Read(base::Bind(&DecoderStream<StreamType>::OnBufferReady, |
360 weak_factory_.GetWeakPtr())); | 397 weak_factory_.GetWeakPtr())); |
361 } | 398 } |
362 | 399 |
363 template <DemuxerStream::Type StreamType> | 400 template <DemuxerStream::Type StreamType> |
364 void DecoderStream<StreamType>::OnBufferReady( | 401 void DecoderStream<StreamType>::OnBufferReady( |
365 DemuxerStream::Status status, | 402 DemuxerStream::Status status, |
366 const scoped_refptr<DecoderBuffer>& buffer) { | 403 const scoped_refptr<DecoderBuffer>& buffer) { |
367 FUNCTION_DVLOG(2) << ": " << status; | 404 FUNCTION_DVLOG(2) << ": " << status; |
368 DCHECK(task_runner_->BelongsToCurrentThread()); | 405 DCHECK(task_runner_->BelongsToCurrentThread()); |
369 DCHECK_EQ(state_, STATE_PENDING_DEMUXER_READ) << state_; | 406 DCHECK_EQ(state_, STATE_PENDING_DEMUXER_READ) << state_; |
370 DCHECK_EQ(buffer.get() != NULL, status == DemuxerStream::kOk) << status; | 407 DCHECK_EQ(buffer.get() != NULL, status == DemuxerStream::kOk) << status; |
371 DCHECK(!read_cb_.is_null()); | |
372 DCHECK(stop_cb_.is_null()); | 408 DCHECK(stop_cb_.is_null()); |
373 | 409 |
374 state_ = STATE_NORMAL; | 410 state_ = STATE_NORMAL; |
375 | 411 |
376 if (status == DemuxerStream::kConfigChanged) { | 412 if (status == DemuxerStream::kConfigChanged) { |
377 FUNCTION_DVLOG(2) << ": " << "ConfigChanged"; | 413 FUNCTION_DVLOG(2) << ": " << "ConfigChanged"; |
378 DCHECK(stream_->SupportsConfigChanges()); | 414 DCHECK(stream_->SupportsConfigChanges()); |
379 | 415 |
380 if (!config_change_observer_cb_.is_null()) | 416 if (!config_change_observer_cb_.is_null()) |
381 config_change_observer_cb_.Run(); | 417 config_change_observer_cb_.Run(); |
(...skipping 26 matching lines...) Expand all Loading... | |
408 return; | 444 return; |
409 } | 445 } |
410 | 446 |
411 if (!splice_observer_cb_.is_null() && !buffer->end_of_stream() && | 447 if (!splice_observer_cb_.is_null() && !buffer->end_of_stream() && |
412 buffer->splice_timestamp() != kNoTimestamp()) { | 448 buffer->splice_timestamp() != kNoTimestamp()) { |
413 splice_observer_cb_.Run(buffer->splice_timestamp()); | 449 splice_observer_cb_.Run(buffer->splice_timestamp()); |
414 } | 450 } |
415 | 451 |
416 DCHECK(status == DemuxerStream::kOk) << status; | 452 DCHECK(status == DemuxerStream::kOk) << status; |
417 Decode(buffer); | 453 Decode(buffer); |
454 | |
455 // Read more data if the decoder supports multiple parallel decoding requests. | |
456 if (state_ == STATE_NORMAL && CanDecodeAnotherBuffer()) { | |
xhwang
2014/04/17 01:06:47
We set state_ to be STATE_NORMAL on line 410, so h
Sergey Ulanov
2014/04/23 02:44:21
Done.
| |
457 ReadFromDemuxerStream(); | |
458 } | |
418 } | 459 } |
419 | 460 |
420 template <DemuxerStream::Type StreamType> | 461 template <DemuxerStream::Type StreamType> |
421 void DecoderStream<StreamType>::ReinitializeDecoder() { | 462 void DecoderStream<StreamType>::ReinitializeDecoder() { |
422 FUNCTION_DVLOG(2); | 463 FUNCTION_DVLOG(2); |
423 DCHECK(task_runner_->BelongsToCurrentThread()); | 464 DCHECK(task_runner_->BelongsToCurrentThread()); |
424 DCHECK_EQ(state_, STATE_FLUSHING_DECODER) << state_; | 465 DCHECK_EQ(state_, STATE_FLUSHING_DECODER) << state_; |
466 DCHECK_EQ(pending_decode_requests_, 0); | |
425 | 467 |
426 DCHECK(StreamTraits::GetDecoderConfig(*stream_).IsValidConfig()); | 468 DCHECK(StreamTraits::GetDecoderConfig(*stream_).IsValidConfig()); |
427 state_ = STATE_REINITIALIZING_DECODER; | 469 state_ = STATE_REINITIALIZING_DECODER; |
428 decoder_->Initialize( | 470 decoder_->Initialize( |
429 StreamTraits::GetDecoderConfig(*stream_), | 471 StreamTraits::GetDecoderConfig(*stream_), |
430 base::Bind(&DecoderStream<StreamType>::OnDecoderReinitialized, | 472 base::Bind(&DecoderStream<StreamType>::OnDecoderReinitialized, |
431 weak_factory_.GetWeakPtr())); | 473 weak_factory_.GetWeakPtr())); |
432 } | 474 } |
433 | 475 |
434 template <DemuxerStream::Type StreamType> | 476 template <DemuxerStream::Type StreamType> |
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
510 decrypting_demuxer_stream_.reset(); | 552 decrypting_demuxer_stream_.reset(); |
511 // Post |stop_cb_| because pending |read_cb_| and/or |reset_cb_| are also | 553 // Post |stop_cb_| because pending |read_cb_| and/or |reset_cb_| are also |
512 // posted in Stop(). | 554 // posted in Stop(). |
513 task_runner_->PostTask(FROM_HERE, base::ResetAndReturn(&stop_cb_)); | 555 task_runner_->PostTask(FROM_HERE, base::ResetAndReturn(&stop_cb_)); |
514 } | 556 } |
515 | 557 |
516 template class DecoderStream<DemuxerStream::VIDEO>; | 558 template class DecoderStream<DemuxerStream::VIDEO>; |
517 template class DecoderStream<DemuxerStream::AUDIO>; | 559 template class DecoderStream<DemuxerStream::AUDIO>; |
518 | 560 |
519 } // namespace media | 561 } // namespace media |
OLD | NEW |