| Index: media/filters/decoder_stream.cc
|
| diff --git a/media/filters/decoder_stream.cc b/media/filters/decoder_stream.cc
|
| index 4b03587253fa06cccd378d527ddf8f1de8e7ff5a..26e9790f520e40855baf18506259402b214b4917 100644
|
| --- a/media/filters/decoder_stream.cc
|
| +++ b/media/filters/decoder_stream.cc
|
| @@ -59,6 +59,7 @@ DecoderStream<StreamType>::DecoderStream(
|
| decoding_eos_(false),
|
| pending_decode_requests_(0),
|
| duration_tracker_(8),
|
| + sequence_token_(0),
|
| weak_factory_(this) {}
|
|
|
| template <DemuxerStream::Type StreamType>
|
| @@ -253,6 +254,7 @@ void DecoderStream<StreamType>::OnDecoderSelected(
|
| DCHECK(decoder_);
|
| }
|
|
|
| + ++sequence_token_;
|
| previous_decoder_ = std::move(decoder_);
|
| decoded_frames_since_fallback_ = 0;
|
| decoder_ = std::move(selected_decoder);
|
| @@ -319,12 +321,14 @@ void DecoderStream<StreamType>::Decode(
|
| else if (buffer->duration() != kNoTimestamp())
|
| duration_tracker_.AddSample(buffer->duration());
|
|
|
| + if (!decoded_frames_since_fallback_ && !previous_decoder_)
|
| + pending_buffers_.push_back(buffer);
|
| +
|
| ++pending_decode_requests_;
|
| decoder_->Decode(buffer,
|
| base::Bind(&DecoderStream<StreamType>::OnDecodeDone,
|
| - weak_factory_.GetWeakPtr(),
|
| - buffer_size,
|
| - buffer->end_of_stream()));
|
| + weak_factory_.GetWeakPtr(), sequence_token_,
|
| + buffer_size, buffer->end_of_stream()));
|
| }
|
|
|
| template <DemuxerStream::Type StreamType>
|
| @@ -333,10 +337,15 @@ void DecoderStream<StreamType>::FlushDecoder() {
|
| }
|
|
|
| template <DemuxerStream::Type StreamType>
|
| -void DecoderStream<StreamType>::OnDecodeDone(int buffer_size,
|
| +void DecoderStream<StreamType>::OnDecodeDone(int sequence_token,
|
| + int buffer_size,
|
| bool end_of_stream,
|
| typename Decoder::Status status) {
|
| FUNCTION_DVLOG(2) << ": " << status;
|
| + // Ignore stale calls from a previous decoder.
|
| + if (sequence_token_ != sequence_token)
|
| + return;
|
| +
|
| DCHECK(state_ == STATE_NORMAL || state_ == STATE_FLUSHING_DECODER ||
|
| state_ == STATE_PENDING_DEMUXER_READ || state_ == STATE_ERROR)
|
| << state_;
|
| @@ -363,6 +372,19 @@ void DecoderStream<StreamType>::OnDecodeDone(int buffer_size,
|
|
|
| switch (status) {
|
| case Decoder::kDecodeError:
|
| + if (!decoded_frames_since_fallback_) {
|
| + pending_decode_requests_ = 0;
|
| + state_ = STATE_REINITIALIZING_DECODER;
|
| + decoder_selector_->SelectDecoder(
|
| + stream_, nullptr,
|
| + base::Bind(&DecoderStream<StreamType>::OnDecoderSelected,
|
| + weak_factory_.GetWeakPtr()),
|
| + base::Bind(&DecoderStream<StreamType>::OnDecodeOutputReady,
|
| + weak_factory_.GetWeakPtr()),
|
| + waiting_for_decryption_key_cb_);
|
| + return;
|
| + }
|
| +
|
| state_ = STATE_ERROR;
|
| MEDIA_LOG(ERROR, media_log_) << GetStreamTypeString() << " decode error";
|
| ready_outputs_.clear();
|
| @@ -430,8 +452,8 @@ void DecoderStream<StreamType>::OnDecodeOutputReady(
|
|
|
| // Destruct any previous decoder once we've decoded enough frames to ensure
|
| // that it's no longer in use.
|
| - if (previous_decoder_ &&
|
| - ++decoded_frames_since_fallback_ > limits::kMaxVideoFrames) {
|
| + if (++decoded_frames_since_fallback_ > limits::kMaxVideoFrames &&
|
| + previous_decoder_) {
|
| previous_decoder_.reset();
|
| }
|
| }
|
| @@ -443,6 +465,13 @@ void DecoderStream<StreamType>::ReadFromDemuxerStream() {
|
| DCHECK(CanDecodeMore());
|
| DCHECK(reset_cb_.is_null());
|
|
|
| + if (!pending_buffers_.empty() && previous_decoder_) {
|
| + scoped_refptr<DecoderBuffer> buffer = pending_buffers_.front();
|
| + pending_buffers_.pop_front();
|
| + Decode(buffer);
|
| + return;
|
| + }
|
| +
|
| state_ = STATE_PENDING_DEMUXER_READ;
|
| stream_->Read(base::Bind(&DecoderStream<StreamType>::OnBufferReady,
|
| weak_factory_.GetWeakPtr()));
|
|
|