Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(123)

Side by Side Diff: media/filters/decoder_stream.cc

Issue 1879353003: Attempt decoder fallback if first decode fails (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 4 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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 <utility> 7 #include <utility>
8 8
9 #include "base/bind.h" 9 #include "base/bind.h"
10 #include "base/callback_helpers.h" 10 #include "base/callback_helpers.h"
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
52 state_(STATE_UNINITIALIZED), 52 state_(STATE_UNINITIALIZED),
53 stream_(NULL), 53 stream_(NULL),
54 decoder_selector_(new DecoderSelector<StreamType>(task_runner, 54 decoder_selector_(new DecoderSelector<StreamType>(task_runner,
55 std::move(decoders), 55 std::move(decoders),
56 media_log)), 56 media_log)),
57 decoded_frames_since_fallback_(0), 57 decoded_frames_since_fallback_(0),
58 active_splice_(false), 58 active_splice_(false),
59 decoding_eos_(false), 59 decoding_eos_(false),
60 pending_decode_requests_(0), 60 pending_decode_requests_(0),
61 duration_tracker_(8), 61 duration_tracker_(8),
62 weak_factory_(this) {} 62 weak_factory_(this),
63 decode_weak_factory_(this) {}
63 64
64 template <DemuxerStream::Type StreamType> 65 template <DemuxerStream::Type StreamType>
65 DecoderStream<StreamType>::~DecoderStream() { 66 DecoderStream<StreamType>::~DecoderStream() {
66 FUNCTION_DVLOG(2); 67 FUNCTION_DVLOG(2);
67 DCHECK(task_runner_->BelongsToCurrentThread()); 68 DCHECK(task_runner_->BelongsToCurrentThread());
68 69
69 decoder_selector_.reset(); 70 decoder_selector_.reset();
70 71
71 if (!init_cb_.is_null()) { 72 if (!init_cb_.is_null()) {
72 task_runner_->PostTask(FROM_HERE, 73 task_runner_->PostTask(FROM_HERE,
(...skipping 163 matching lines...) Expand 10 before | Expand all | Expand 10 after
236 } 237 }
237 238
238 template <DemuxerStream::Type StreamType> 239 template <DemuxerStream::Type StreamType>
239 void DecoderStream<StreamType>::OnDecoderSelected( 240 void DecoderStream<StreamType>::OnDecoderSelected(
240 scoped_ptr<Decoder> selected_decoder, 241 scoped_ptr<Decoder> selected_decoder,
241 scoped_ptr<DecryptingDemuxerStream> decrypting_demuxer_stream) { 242 scoped_ptr<DecryptingDemuxerStream> decrypting_demuxer_stream) {
242 FUNCTION_DVLOG(2) << ": " 243 FUNCTION_DVLOG(2) << ": "
243 << (selected_decoder ? selected_decoder->GetDisplayName() 244 << (selected_decoder ? selected_decoder->GetDisplayName()
244 : "No decoder selected."); 245 : "No decoder selected.");
245 DCHECK(task_runner_->BelongsToCurrentThread()); 246 DCHECK(task_runner_->BelongsToCurrentThread());
246 DCHECK(state_ == STATE_INITIALIZING || state_ == STATE_REINITIALIZING_DECODER) 247 DCHECK(state_ == STATE_INITIALIZING ||
248 state_ == STATE_REINITIALIZING_DECODER ||
249 state_ == STATE_CONFIG_CHANGE_RECEIVED_WHILE_REINITIALIZING_DECODER)
247 << state_; 250 << state_;
248 if (state_ == STATE_INITIALIZING) { 251 if (state_ == STATE_INITIALIZING) {
249 DCHECK(!init_cb_.is_null()); 252 DCHECK(!init_cb_.is_null());
250 DCHECK(read_cb_.is_null()); 253 DCHECK(read_cb_.is_null());
251 DCHECK(reset_cb_.is_null()); 254 DCHECK(reset_cb_.is_null());
252 } else { 255 } else if (state_ == STATE_REINITIALIZING_DECODER) {
253 DCHECK(decoder_); 256 DCHECK(decoder_);
254 } 257 }
255 258
256 previous_decoder_ = std::move(decoder_); 259 previous_decoder_ = std::move(decoder_);
257 decoded_frames_since_fallback_ = 0; 260 decoded_frames_since_fallback_ = 0;
258 decoder_ = std::move(selected_decoder); 261 decoder_ = std::move(selected_decoder);
259 if (decrypting_demuxer_stream) { 262 if (decrypting_demuxer_stream) {
260 decrypting_demuxer_stream_ = std::move(decrypting_demuxer_stream); 263 decrypting_demuxer_stream_ = std::move(decrypting_demuxer_stream);
261 stream_ = decrypting_demuxer_stream_.get(); 264 stream_ = decrypting_demuxer_stream_.get();
262 } 265 }
263 266
267 // TODO(tguilbert): crbug.com/603713 support config changes on decoder reinit.
268 if (state_ == STATE_CONFIG_CHANGE_RECEIVED_WHILE_REINITIALIZING_DECODER) {
269 CompleteDecoderReinitialization(false);
270 return;
271 }
272
273 // Push the pending buffers to the front of the fallback buffers
274 if (fallback_buffers_.empty()) {
275 fallback_buffers_.swap(pending_buffers_);
276 } else {
277 fallback_buffers_.insert(fallback_buffers_.begin(),
DaleCurtis 2016/04/15 01:19:16 Is it better to just insert at the end of pending_
tguilbert 2016/04/15 20:45:51 While I assume that the amortized cost would be fi
278 pending_buffers_.begin(), pending_buffers_.end());
279 pending_buffers_.clear();
280 }
281
264 if (!decoder_) { 282 if (!decoder_) {
265 if (state_ == STATE_INITIALIZING) { 283 if (state_ == STATE_INITIALIZING) {
266 state_ = STATE_UNINITIALIZED; 284 state_ = STATE_UNINITIALIZED;
267 MEDIA_LOG(ERROR, media_log_) << GetStreamTypeString() 285 MEDIA_LOG(ERROR, media_log_) << GetStreamTypeString()
268 << " decoder initialization failed"; 286 << " decoder initialization failed";
269 base::ResetAndReturn(&init_cb_).Run(false); 287 base::ResetAndReturn(&init_cb_).Run(false);
270 } else { 288 } else {
271 CompleteDecoderReinitialization(false); 289 CompleteDecoderReinitialization(false);
272 } 290 }
273 return; 291 return;
(...skipping 21 matching lines...) Expand all
295 Status status, 313 Status status,
296 const scoped_refptr<Output>& output) { 314 const scoped_refptr<Output>& output) {
297 DCHECK(!read_cb_.is_null()); 315 DCHECK(!read_cb_.is_null());
298 base::ResetAndReturn(&read_cb_).Run(status, output); 316 base::ResetAndReturn(&read_cb_).Run(status, output);
299 } 317 }
300 318
301 template <DemuxerStream::Type StreamType> 319 template <DemuxerStream::Type StreamType>
302 void DecoderStream<StreamType>::Decode( 320 void DecoderStream<StreamType>::Decode(
303 const scoped_refptr<DecoderBuffer>& buffer) { 321 const scoped_refptr<DecoderBuffer>& buffer) {
304 FUNCTION_DVLOG(2); 322 FUNCTION_DVLOG(2);
323
324 // We don't know if the decoder will error out on first decode yet. Save the
325 // buffer to feed it to the fallback decoder later if needed.
326 if (!decoded_frames_since_fallback_)
327 pending_buffers_.push_back(buffer);
328
329 DecodeInternal(buffer);
330 }
331
332 template <DemuxerStream::Type StreamType>
333 void DecoderStream<StreamType>::DecodeInternal(
334 const scoped_refptr<DecoderBuffer>& buffer) {
335 FUNCTION_DVLOG(2);
305 DCHECK(state_ == STATE_NORMAL || state_ == STATE_FLUSHING_DECODER) << state_; 336 DCHECK(state_ == STATE_NORMAL || state_ == STATE_FLUSHING_DECODER) << state_;
306 DCHECK_LT(pending_decode_requests_, GetMaxDecodeRequests()); 337 DCHECK_LT(pending_decode_requests_, GetMaxDecodeRequests());
307 DCHECK(reset_cb_.is_null()); 338 DCHECK(reset_cb_.is_null());
308 DCHECK(buffer.get()); 339 DCHECK(buffer.get());
309 340
310 int buffer_size = buffer->end_of_stream() ? 0 : buffer->data_size(); 341 int buffer_size = buffer->end_of_stream() ? 0 : buffer->data_size();
311 342
312 TRACE_EVENT_ASYNC_BEGIN2( 343 TRACE_EVENT_ASYNC_BEGIN2(
313 "media", GetTraceString<StreamType>(), this, "key frame", 344 "media", GetTraceString<StreamType>(), this, "key frame",
314 !buffer->end_of_stream() && buffer->is_key_frame(), "timestamp (ms)", 345 !buffer->end_of_stream() && buffer->is_key_frame(), "timestamp (ms)",
315 !buffer->end_of_stream() ? buffer->timestamp().InMilliseconds() : 0); 346 !buffer->end_of_stream() ? buffer->timestamp().InMilliseconds() : 0);
316 347
317 if (buffer->end_of_stream()) 348 if (buffer->end_of_stream())
318 decoding_eos_ = true; 349 decoding_eos_ = true;
319 else if (buffer->duration() != kNoTimestamp()) 350 else if (buffer->duration() != kNoTimestamp())
320 duration_tracker_.AddSample(buffer->duration()); 351 duration_tracker_.AddSample(buffer->duration());
321 352
322 ++pending_decode_requests_; 353 ++pending_decode_requests_;
323 decoder_->Decode(buffer, 354 decoder_->Decode(buffer, base::Bind(&DecoderStream<StreamType>::OnDecodeDone,
324 base::Bind(&DecoderStream<StreamType>::OnDecodeDone, 355 decode_weak_factory_.GetWeakPtr(),
325 weak_factory_.GetWeakPtr(), 356 buffer_size, buffer->end_of_stream()));
326 buffer_size,
327 buffer->end_of_stream()));
328 } 357 }
329 358
330 template <DemuxerStream::Type StreamType> 359 template <DemuxerStream::Type StreamType>
331 void DecoderStream<StreamType>::FlushDecoder() { 360 void DecoderStream<StreamType>::FlushDecoder() {
332 Decode(DecoderBuffer::CreateEOSBuffer()); 361 // Decode directly and bypass saving the EOS into |pending_buffers_|.
362 DecodeInternal(DecoderBuffer::CreateEOSBuffer());
333 } 363 }
334 364
335 template <DemuxerStream::Type StreamType> 365 template <DemuxerStream::Type StreamType>
336 void DecoderStream<StreamType>::OnDecodeDone(int buffer_size, 366 void DecoderStream<StreamType>::OnDecodeDone(int buffer_size,
337 bool end_of_stream, 367 bool end_of_stream,
338 DecodeStatus status) { 368 DecodeStatus status) {
339 FUNCTION_DVLOG(2) << ": " << status; 369 FUNCTION_DVLOG(2) << ": " << status;
370
DaleCurtis 2016/04/15 01:19:17 Delete?
tguilbert 2016/04/15 20:45:52 Done.
340 DCHECK(state_ == STATE_NORMAL || state_ == STATE_FLUSHING_DECODER || 371 DCHECK(state_ == STATE_NORMAL || state_ == STATE_FLUSHING_DECODER ||
341 state_ == STATE_PENDING_DEMUXER_READ || state_ == STATE_ERROR) 372 state_ == STATE_PENDING_DEMUXER_READ || state_ == STATE_ERROR)
342 << state_; 373 << state_;
343 DCHECK_GT(pending_decode_requests_, 0); 374 DCHECK_GT(pending_decode_requests_, 0);
344 375
345 --pending_decode_requests_; 376 --pending_decode_requests_;
346 377
347 TRACE_EVENT_ASYNC_END0("media", GetTraceString<StreamType>(), this); 378 TRACE_EVENT_ASYNC_END0("media", GetTraceString<StreamType>(), this);
348 379
349 if (end_of_stream) { 380 if (end_of_stream) {
350 DCHECK(!pending_decode_requests_); 381 DCHECK(!pending_decode_requests_);
351 decoding_eos_ = false; 382 decoding_eos_ = false;
352 } 383 }
353 384
354 if (state_ == STATE_ERROR) { 385 if (state_ == STATE_ERROR) {
355 DCHECK(read_cb_.is_null()); 386 DCHECK(read_cb_.is_null());
356 return; 387 return;
357 } 388 }
358 389
359 // Drop decoding result if Reset() was called during decoding. 390 // Drop decoding result if Reset() was called during decoding.
360 // The resetting process will be handled when the decoder is reset. 391 // The resetting process will be handled when the decoder is reset.
361 if (!reset_cb_.is_null()) 392 if (!reset_cb_.is_null())
362 return; 393 return;
363 394
364 switch (status) { 395 switch (status) {
365 case DecodeStatus::DECODE_ERROR: 396 case DecodeStatus::DECODE_ERROR:
397 if (!decoded_frames_since_fallback_) {
398 pending_decode_requests_ = 0;
399
400 // Prevent all pending decode requests from being called back.
401 decode_weak_factory_.InvalidateWeakPtrs();
402
403 state_ = STATE_REINITIALIZING_DECODER;
404 decoder_selector_->SelectDecoder(
405 stream_, nullptr,
406 base::Bind(&DecoderStream<StreamType>::OnDecoderSelected,
407 weak_factory_.GetWeakPtr()),
408 base::Bind(&DecoderStream<StreamType>::OnDecodeOutputReady,
409 weak_factory_.GetWeakPtr()),
410 waiting_for_decryption_key_cb_);
411 return;
412 }
366 state_ = STATE_ERROR; 413 state_ = STATE_ERROR;
367 MEDIA_LOG(ERROR, media_log_) << GetStreamTypeString() << " decode error"; 414 MEDIA_LOG(ERROR, media_log_) << GetStreamTypeString() << " decode error";
368 ready_outputs_.clear(); 415 ready_outputs_.clear();
369 if (!read_cb_.is_null()) 416 if (!read_cb_.is_null())
370 SatisfyRead(DECODE_ERROR, NULL); 417 SatisfyRead(DECODE_ERROR, NULL);
371 return; 418 return;
372 419
373 case DecodeStatus::ABORTED: 420 case DecodeStatus::ABORTED:
374 // Decoder can return DecodeStatus::ABORTED during Reset() or during 421 // Decoder can return DecodeStatus::ABORTED during Reset() or during
375 // destruction. 422 // destruction.
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
411 if (state_ == STATE_ERROR) { 458 if (state_ == STATE_ERROR) {
412 DCHECK(read_cb_.is_null()); 459 DCHECK(read_cb_.is_null());
413 return; 460 return;
414 } 461 }
415 462
416 // Drop decoding result if Reset() was called during decoding. 463 // Drop decoding result if Reset() was called during decoding.
417 // The resetting process will be handled when the decoder is reset. 464 // The resetting process will be handled when the decoder is reset.
418 if (!reset_cb_.is_null()) 465 if (!reset_cb_.is_null())
419 return; 466 return;
420 467
468 ++decoded_frames_since_fallback_;
469
470 // |decoder_| sucessfully decoded a frame. No need to keep buffers for a
471 // fallback decoder.
472 // Note: |fallback_buffers_| might still have buffers, and we will keep
473 // reading from there before requesting new buffers from |stream_|.
474 pending_buffers_.clear();
475
421 if (!read_cb_.is_null()) { 476 if (!read_cb_.is_null()) {
422 // If |ready_outputs_| was non-empty, the read would have already been 477 // If |ready_outputs_| was non-empty, the read would have already been
423 // satisifed by Read(). 478 // satisifed by Read().
424 DCHECK(ready_outputs_.empty()); 479 DCHECK(ready_outputs_.empty());
425 SatisfyRead(OK, output); 480 SatisfyRead(OK, output);
426 return; 481 return;
427 } 482 }
428 483
429 // Store decoded output. 484 // Store decoded output.
430 ready_outputs_.push_back(output); 485 ready_outputs_.push_back(output);
431 486
432 // Destruct any previous decoder once we've decoded enough frames to ensure 487 // Destruct any previous decoder once we've decoded enough frames to ensure
433 // that it's no longer in use. 488 // that it's no longer in use.
434 if (previous_decoder_ && 489 if (previous_decoder_ &&
435 ++decoded_frames_since_fallback_ > limits::kMaxVideoFrames) { 490 decoded_frames_since_fallback_ > limits::kMaxVideoFrames) {
436 previous_decoder_.reset(); 491 previous_decoder_.reset();
437 } 492 }
438 } 493 }
439 494
440 template <DemuxerStream::Type StreamType> 495 template <DemuxerStream::Type StreamType>
441 void DecoderStream<StreamType>::ReadFromDemuxerStream() { 496 void DecoderStream<StreamType>::ReadFromDemuxerStream() {
442 FUNCTION_DVLOG(2); 497 FUNCTION_DVLOG(2);
443 DCHECK_EQ(state_, STATE_NORMAL); 498 DCHECK_EQ(state_, STATE_NORMAL);
444 DCHECK(CanDecodeMore()); 499 DCHECK(CanDecodeMore());
445 DCHECK(reset_cb_.is_null()); 500 DCHECK(reset_cb_.is_null());
446 501
502 if (!fallback_buffers_.empty()) {
503 scoped_refptr<DecoderBuffer> buffer = fallback_buffers_.front();
504 fallback_buffers_.pop_front();
505 Decode(buffer);
506 return;
507 }
508
447 state_ = STATE_PENDING_DEMUXER_READ; 509 state_ = STATE_PENDING_DEMUXER_READ;
448 stream_->Read(base::Bind(&DecoderStream<StreamType>::OnBufferReady, 510 stream_->Read(base::Bind(&DecoderStream<StreamType>::OnBufferReady,
449 weak_factory_.GetWeakPtr())); 511 weak_factory_.GetWeakPtr()));
450 } 512 }
451 513
452 template <DemuxerStream::Type StreamType> 514 template <DemuxerStream::Type StreamType>
453 void DecoderStream<StreamType>::OnBufferReady( 515 void DecoderStream<StreamType>::OnBufferReady(
454 DemuxerStream::Status status, 516 DemuxerStream::Status status,
455 const scoped_refptr<DecoderBuffer>& buffer) { 517 const scoped_refptr<DecoderBuffer>& buffer) {
456 FUNCTION_DVLOG(2) << ": " << status << ", " 518 FUNCTION_DVLOG(2) << ": " << status << ", "
457 << (buffer.get() ? buffer->AsHumanReadableString() 519 << (buffer.get() ? buffer->AsHumanReadableString()
458 : "NULL"); 520 : "NULL");
459 521
460 DCHECK(task_runner_->BelongsToCurrentThread()); 522 DCHECK(task_runner_->BelongsToCurrentThread());
461 DCHECK(state_ == STATE_PENDING_DEMUXER_READ || state_ == STATE_ERROR) 523 if (decoded_frames_since_fallback_) {
462 << state_; 524 DCHECK(state_ == STATE_PENDING_DEMUXER_READ || state_ == STATE_ERROR)
525 << state_;
526 } else {
527 DCHECK(state_ == STATE_PENDING_DEMUXER_READ || state_ == STATE_ERROR ||
528 STATE_REINITIALIZING_DECODER)
529 << state_;
530 }
463 DCHECK_EQ(buffer.get() != NULL, status == DemuxerStream::kOk) << status; 531 DCHECK_EQ(buffer.get() != NULL, status == DemuxerStream::kOk) << status;
464 532
533 // If parallel decode requests are supported, multiple read requests might
534 // have been sent to the demuxer. The buffers might arrive while the decoder
535 // is reinitializing after falling back on first decode error.
536 if (state_ == STATE_REINITIALIZING_DECODER &&
537 !decoded_frames_since_fallback_) {
538 switch (status) {
539 case DemuxerStream::kOk:
540 // Save valid buffers to be consumed by the new decoder.
541 // |pending_buffers_| is copied to |fallback_buffers| in
542 // OnDecoderSelected().
543 pending_buffers_.push_back(buffer);
544 break;
545 case DemuxerStream::kConfigChanged:
546 // TODO(tguilbert): crbug.com/603713
547 // |decoder_| might have a stale config by the time it is reinitialized.
548 // Ideally, we would save the config from |stream_| and reinitialize the
549 // decoder by playing back the sequence of buffers and config changes.
550 state_ = STATE_CONFIG_CHANGE_RECEIVED_WHILE_REINITIALIZING_DECODER;
551 pending_buffers_.clear();
552 break;
553 case DemuxerStream::kAborted:
554 // |this| will read from the demuxer stream again in OnDecoderSelected()
555 // and receive a kAborted then.
556 pending_buffers_.clear();
557 break;
558 default:
DaleCurtis 2016/04/15 01:19:17 No need for default? We typically prefer to enumer
tguilbert 2016/04/15 20:45:52 Good to know. TY!
559 NOTREACHED();
560 break;
561 }
562 return;
563 }
564
465 // Decoding has been stopped (e.g due to an error). 565 // Decoding has been stopped (e.g due to an error).
466 if (state_ != STATE_PENDING_DEMUXER_READ) { 566 if (state_ != STATE_PENDING_DEMUXER_READ) {
467 DCHECK(state_ == STATE_ERROR); 567 DCHECK(state_ == STATE_ERROR);
468 DCHECK(read_cb_.is_null()); 568 DCHECK(read_cb_.is_null());
469 return; 569 return;
470 } 570 }
471 571
472 state_ = STATE_NORMAL; 572 state_ = STATE_NORMAL;
473 573
474 if (status == DemuxerStream::kConfigChanged) { 574 if (status == DemuxerStream::kConfigChanged) {
475 FUNCTION_DVLOG(2) << ": " << "ConfigChanged"; 575 FUNCTION_DVLOG(2) << ": " << "ConfigChanged";
476 DCHECK(stream_->SupportsConfigChanges()); 576 DCHECK(stream_->SupportsConfigChanges());
477 577
578 // Pending buffers might not match the reinitialiazed decoder's new config
DaleCurtis 2016/04/15 01:19:17 Reinitialized.
tguilbert 2016/04/15 20:45:52 Done.
579 pending_buffers_.clear();
580
478 if (!config_change_observer_cb_.is_null()) 581 if (!config_change_observer_cb_.is_null())
479 config_change_observer_cb_.Run(); 582 config_change_observer_cb_.Run();
480 583
481 state_ = STATE_FLUSHING_DECODER; 584 state_ = STATE_FLUSHING_DECODER;
482 if (!reset_cb_.is_null()) { 585 if (!reset_cb_.is_null()) {
483 // If we are using DecryptingDemuxerStream, we already called DDS::Reset() 586 // If we are using DecryptingDemuxerStream, we already called DDS::Reset()
484 // which will continue the resetting process in it's callback. 587 // which will continue the resetting process in it's callback.
485 if (!decrypting_demuxer_stream_) 588 if (!decrypting_demuxer_stream_)
486 Reset(base::ResetAndReturn(&reset_cb_)); 589 Reset(base::ResetAndReturn(&reset_cb_));
487 // Reinitialization will continue after Reset() is done. 590 // Reinitialization will continue after Reset() is done.
(...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after
604 void DecoderStream<StreamType>::OnDecoderReset() { 707 void DecoderStream<StreamType>::OnDecoderReset() {
605 FUNCTION_DVLOG(2); 708 FUNCTION_DVLOG(2);
606 DCHECK(task_runner_->BelongsToCurrentThread()); 709 DCHECK(task_runner_->BelongsToCurrentThread());
607 DCHECK(state_ == STATE_NORMAL || state_ == STATE_FLUSHING_DECODER || 710 DCHECK(state_ == STATE_NORMAL || state_ == STATE_FLUSHING_DECODER ||
608 state_ == STATE_ERROR || state_ == STATE_END_OF_STREAM) << state_; 711 state_ == STATE_ERROR || state_ == STATE_END_OF_STREAM) << state_;
609 // If Reset() was called during pending read, read callback should be fired 712 // If Reset() was called during pending read, read callback should be fired
610 // before the reset callback is fired. 713 // before the reset callback is fired.
611 DCHECK(read_cb_.is_null()); 714 DCHECK(read_cb_.is_null());
612 DCHECK(!reset_cb_.is_null()); 715 DCHECK(!reset_cb_.is_null());
613 716
717 // Make sure we read directly from the demuxer after a reset.
718 fallback_buffers_.clear();
719 pending_buffers_.clear();
720
614 if (state_ != STATE_FLUSHING_DECODER) { 721 if (state_ != STATE_FLUSHING_DECODER) {
615 state_ = STATE_NORMAL; 722 state_ = STATE_NORMAL;
616 active_splice_ = false; 723 active_splice_ = false;
617 base::ResetAndReturn(&reset_cb_).Run(); 724 base::ResetAndReturn(&reset_cb_).Run();
618 return; 725 return;
619 } 726 }
620 727
621 // The resetting process will be continued in OnDecoderReinitialized(). 728 // The resetting process will be continued in OnDecoderReinitialized().
622 ReinitializeDecoder(); 729 ReinitializeDecoder();
623 } 730 }
624 731
625 template class DecoderStream<DemuxerStream::VIDEO>; 732 template class DecoderStream<DemuxerStream::VIDEO>;
626 template class DecoderStream<DemuxerStream::AUDIO>; 733 template class DecoderStream<DemuxerStream::AUDIO>;
627 734
628 } // namespace media 735 } // namespace media
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698