Index: media/filters/decoder_stream.cc |
diff --git a/media/filters/decoder_stream.cc b/media/filters/decoder_stream.cc |
index 4f712be2f2227883e37710fd9ae5a1b6b9bd9751..cedba00f43ba8fd420c22b1d71975d9911556a49 100644 |
--- a/media/filters/decoder_stream.cc |
+++ b/media/filters/decoder_stream.cc |
@@ -80,6 +80,8 @@ void DecoderStream<StreamType>::Initialize(DemuxerStream* stream, |
decoder_selector_->SelectDecoder( |
stream, low_delay, |
base::Bind(&DecoderStream<StreamType>::OnDecoderSelected, |
+ weak_factory_.GetWeakPtr()), |
+ base::Bind(&DecoderStream<StreamType>::OnDecodeOutputReady, |
weak_factory_.GetWeakPtr())); |
} |
@@ -113,19 +115,7 @@ void DecoderStream<StreamType>::Read(const ReadCB& read_cb) { |
ready_outputs_.pop_front(); |
} |
- // Decoder may be in reinitializing state as result of the previous Read(). |
- if (state_ == STATE_REINITIALIZING_DECODER) |
- return; |
- |
- if (!CanDecodeMore()) |
- return; |
- |
- if (state_ == STATE_FLUSHING_DECODER) { |
- FlushDecoder(); |
- return; |
- } |
- |
- if (state_ != STATE_PENDING_DEMUXER_READ) |
+ if (state_ == STATE_NORMAL && CanDecodeMore()) |
ReadFromDemuxerStream(); |
} |
@@ -216,7 +206,7 @@ void DecoderStream<StreamType>::Stop(const base::Closure& closure) { |
template <DemuxerStream::Type StreamType> |
bool DecoderStream<StreamType>::CanReadWithoutStalling() const { |
DCHECK(task_runner_->BelongsToCurrentThread()); |
- return decoder_->CanReadWithoutStalling(); |
+ return !ready_outputs_.empty() || decoder_->CanReadWithoutStalling(); |
} |
template <> |
@@ -226,6 +216,16 @@ bool DecoderStream<DemuxerStream::AUDIO>::CanReadWithoutStalling() const { |
} |
template <DemuxerStream::Type StreamType> |
+int DecoderStream<StreamType>::GetMaxDecodeRequests() const { |
+ return decoder_->GetMaxDecodeRequests(); |
+} |
+ |
+template <> |
+int DecoderStream<DemuxerStream::AUDIO>::GetMaxDecodeRequests() const { |
+ return 1; |
+} |
+ |
+template <DemuxerStream::Type StreamType> |
bool DecoderStream<StreamType>::CanDecodeMore() const { |
DCHECK(task_runner_->BelongsToCurrentThread()); |
@@ -234,13 +234,7 @@ bool DecoderStream<StreamType>::CanDecodeMore() const { |
// empty. |
int num_decodes = |
static_cast<int>(ready_outputs_.size()) + pending_decode_requests_; |
- return num_decodes < decoder_->GetMaxDecodeRequests(); |
-} |
- |
-template <> |
-bool DecoderStream<DemuxerStream::AUDIO>::CanDecodeMore() const { |
- DCHECK(task_runner_->BelongsToCurrentThread()); |
- return !pending_decode_requests_ && ready_outputs_.empty(); |
+ return num_decodes < GetMaxDecodeRequests(); |
} |
template <DemuxerStream::Type StreamType> |
@@ -290,7 +284,7 @@ void DecoderStream<StreamType>::Decode( |
const scoped_refptr<DecoderBuffer>& buffer) { |
FUNCTION_DVLOG(2); |
DCHECK(state_ == STATE_NORMAL || state_ == STATE_FLUSHING_DECODER) << state_; |
- DCHECK(CanDecodeMore()); |
+ DCHECK_LT(pending_decode_requests_, GetMaxDecodeRequests()); |
DCHECK(reset_cb_.is_null()); |
DCHECK(stop_cb_.is_null()); |
DCHECK(buffer); |
@@ -300,28 +294,26 @@ void DecoderStream<StreamType>::Decode( |
TRACE_EVENT_ASYNC_BEGIN0("media", GetTraceString<StreamType>(), this); |
++pending_decode_requests_; |
decoder_->Decode(buffer, |
- base::Bind(&DecoderStream<StreamType>::OnDecodeOutputReady, |
+ base::Bind(&DecoderStream<StreamType>::OnDecodeDone, |
weak_factory_.GetWeakPtr(), |
- buffer_size)); |
+ buffer_size, |
+ buffer->end_of_stream())); |
} |
template <DemuxerStream::Type StreamType> |
void DecoderStream<StreamType>::FlushDecoder() { |
- if (pending_decode_requests_ == 0) |
- Decode(DecoderBuffer::CreateEOSBuffer()); |
+ Decode(DecoderBuffer::CreateEOSBuffer()); |
} |
template <DemuxerStream::Type StreamType> |
-void DecoderStream<StreamType>::OnDecodeOutputReady( |
- int buffer_size, |
- typename Decoder::Status status, |
- const scoped_refptr<Output>& output) { |
- FUNCTION_DVLOG(2) << status << " " << output; |
+void DecoderStream<StreamType>::OnDecodeDone(int buffer_size, |
+ bool end_of_stream, |
+ typename Decoder::Status status) { |
+ FUNCTION_DVLOG(2) << status; |
DCHECK(state_ == STATE_NORMAL || state_ == STATE_FLUSHING_DECODER || |
state_ == STATE_PENDING_DEMUXER_READ || state_ == STATE_ERROR) |
<< state_; |
DCHECK(stop_cb_.is_null()); |
- DCHECK_EQ(status == Decoder::kOk, output != NULL); |
DCHECK_GT(pending_decode_requests_, 0); |
--pending_decode_requests_; |
@@ -333,31 +325,54 @@ void DecoderStream<StreamType>::OnDecodeOutputReady( |
return; |
} |
- if (status == Decoder::kDecodeError) { |
- state_ = STATE_ERROR; |
- ready_outputs_.clear(); |
- if (!read_cb_.is_null()) |
- SatisfyRead(DECODE_ERROR, NULL); |
+ // Drop decoding result if Reset() was called during decoding. |
+ // The resetting process will be handled when the decoder is reset. |
+ if (!reset_cb_.is_null()) |
return; |
- } |
- if (status == Decoder::kDecryptError) { |
- state_ = STATE_ERROR; |
- ready_outputs_.clear(); |
- if (!read_cb_.is_null()) |
- SatisfyRead(DECRYPT_ERROR, NULL); |
- return; |
+ switch (status) { |
+ case Decoder::kDecodeError: |
+ case Decoder::kDecryptError: |
+ state_ = STATE_ERROR; |
+ ready_outputs_.clear(); |
+ if (!read_cb_.is_null()) |
+ SatisfyRead(DECODE_ERROR, NULL); |
+ break; |
+ |
+ case Decoder::kAborted: |
+ // Decoder can return kAborted only when Reset is pending. |
+ NOTREACHED(); |
+ break; |
+ |
+ case Decoder::kOk: |
+ // Any successful decode counts! |
+ if (buffer_size > 0) { |
+ StreamTraits::ReportStatistics(statistics_cb_, buffer_size); |
+ } |
+ |
+ if (state_ == STATE_NORMAL) { |
+ if (CanDecodeMore() && !end_of_stream) |
+ ReadFromDemuxerStream(); |
+ } else if (state_ == STATE_FLUSHING_DECODER) { |
+ if (!pending_decode_requests_) |
+ ReinitializeDecoder(); |
+ } |
+ break; |
} |
+} |
- if (status == Decoder::kAborted) { |
- if (!read_cb_.is_null()) |
- SatisfyRead(ABORTED, NULL); |
- return; |
- } |
+template <DemuxerStream::Type StreamType> |
+void DecoderStream<StreamType>::OnDecodeOutputReady( |
+ const scoped_refptr<Output>& output) { |
+ FUNCTION_DVLOG(2) << output; |
+ DCHECK(output); |
+ DCHECK(state_ == STATE_NORMAL || state_ == STATE_FLUSHING_DECODER || |
+ state_ == STATE_PENDING_DEMUXER_READ || state_ == STATE_ERROR) |
+ << state_; |
- // Any successful decode counts! |
- if (buffer_size > 0) { |
- StreamTraits::ReportStatistics(statistics_cb_, buffer_size); |
+ if (state_ == STATE_ERROR) { |
+ DCHECK(read_cb_.is_null()); |
+ return; |
} |
// Drop decoding result if Reset() was called during decoding. |
@@ -365,29 +380,13 @@ void DecoderStream<StreamType>::OnDecodeOutputReady( |
if (!reset_cb_.is_null()) |
return; |
- // Decoder flushed. Reinitialize the decoder. |
- if (state_ == STATE_FLUSHING_DECODER && |
- status == Decoder::kOk && output->end_of_stream()) { |
- ReinitializeDecoder(); |
- return; |
- } |
- |
- if (status == Decoder::kNotEnoughData) { |
- if (state_ == STATE_NORMAL) |
- ReadFromDemuxerStream(); |
- else if (state_ == STATE_FLUSHING_DECODER) |
- FlushDecoder(); |
+ if (state_ == STATE_FLUSHING_DECODER && output->end_of_stream()) { |
+ // ReinitializeDecoder() will be called from OnDecodeDone(). |
return; |
} |
- DCHECK(output); |
- |
// Store decoded output. |
ready_outputs_.push_back(output); |
- scoped_refptr<Output> extra_output; |
- while ((extra_output = decoder_->GetDecodeOutput()) != NULL) { |
- ready_outputs_.push_back(extra_output); |
- } |
// Satisfy outstanding read request, if any. |
if (!read_cb_.is_null()) { |
@@ -460,7 +459,8 @@ void DecoderStream<StreamType>::OnBufferReady( |
} |
if (status == DemuxerStream::kAborted) { |
- SatisfyRead(DEMUXER_READ_ABORTED, NULL); |
+ if (!read_cb_.is_null()) |
+ SatisfyRead(DEMUXER_READ_ABORTED, NULL); |
return; |
} |
@@ -494,6 +494,8 @@ void DecoderStream<StreamType>::ReinitializeDecoder() { |
StreamTraits::GetDecoderConfig(*stream_), |
low_delay_, |
base::Bind(&DecoderStream<StreamType>::OnDecoderReinitialized, |
+ weak_factory_.GetWeakPtr()), |
+ base::Bind(&DecoderStream<StreamType>::OnDecodeOutputReady, |
weak_factory_.GetWeakPtr())); |
} |