Index: media/filters/ffmpeg_audio_decoder.cc |
diff --git a/media/filters/ffmpeg_audio_decoder.cc b/media/filters/ffmpeg_audio_decoder.cc |
index 51b02c2d214aface2edf18c53c79562bd82f0692..b3a2cba02faeaa604aea921b20ab260f083917f4 100644 |
--- a/media/filters/ffmpeg_audio_decoder.cc |
+++ b/media/filters/ffmpeg_audio_decoder.cc |
@@ -213,34 +213,6 @@ void FFmpegAudioDecoder::DecodeBuffer( |
DCHECK(buffer); |
- // During decode, because reads are issued asynchronously, it is possible to |
- // receive multiple end of stream buffers since each decode is acked. When the |
- // first end of stream buffer is read, FFmpeg may still have frames queued |
- // up in the decoder so we need to go through the decode loop until it stops |
- // giving sensible data. After that, the decoder should output empty |
- // frames. There are three states the decoder can be in: |
- // |
- // kNormal: This is the starting state. Buffers are decoded. Decode errors |
- // are discarded. |
- // kFlushCodec: There isn't any more input data. Call avcodec_decode_audio4 |
- // until no more data is returned to flush out remaining |
- // frames. The input buffer is ignored at this point. |
- // kDecodeFinished: All calls return empty frames. |
- // kError: Unexpected error happened. |
- // |
- // These are the possible state transitions. |
- // |
- // kNormal -> kFlushCodec: |
- // When buffer->end_of_stream() is first true. |
- // kNormal -> kError: |
- // A decoding error occurs and decoding needs to stop. |
- // kFlushCodec -> kDecodeFinished: |
- // When avcodec_decode_audio4() returns 0 data. |
- // kFlushCodec -> kError: |
- // When avcodec_decode_audio4() errors out. |
- // (any state) -> kNormal: |
- // Any time Reset() is called. |
- |
// Make sure we are notified if http://crbug.com/49709 returns. Issue also |
// occurs with some damaged files. |
if (!buffer->end_of_stream() && buffer->timestamp() == kNoTimestamp()) { |
@@ -249,22 +221,28 @@ void FFmpegAudioDecoder::DecodeBuffer( |
return; |
} |
- if (!FFmpegDecode(buffer)) { |
- state_ = kError; |
- decode_cb.Run(kDecodeError); |
- return; |
- } |
+ bool has_produced_frame; |
+ do { |
+ has_produced_frame = false; |
+ if (!FFmpegDecode(buffer, &has_produced_frame)) { |
+ state_ = kError; |
+ decode_cb.Run(kDecodeError); |
+ return; |
+ } |
+ // Repeat to flush the decoder after receiving EOS buffer. |
+ } while (buffer->end_of_stream() && has_produced_frame); |
- if (buffer->end_of_stream()) { |
+ if (buffer->end_of_stream()) |
state_ = kDecodeFinished; |
- output_cb_.Run(AudioBuffer::CreateEOSBuffer()); |
- } |
decode_cb.Run(kOk); |
} |
bool FFmpegAudioDecoder::FFmpegDecode( |
- const scoped_refptr<DecoderBuffer>& buffer) { |
+ const scoped_refptr<DecoderBuffer>& buffer, |
+ bool* has_produced_frame) { |
+ DCHECK(!*has_produced_frame); |
+ |
AVPacket packet; |
av_init_packet(&packet); |
if (buffer->end_of_stream()) { |
@@ -347,8 +325,8 @@ bool FFmpegAudioDecoder::FFmpegDecode( |
const int decoded_frames = frame_decoded ? output->frame_count() : 0; |
if (IsEndOfStream(result, decoded_frames, buffer)) { |
DCHECK_EQ(packet.size, 0); |
- output_cb_.Run(AudioBuffer::CreateEOSBuffer()); |
} else if (discard_helper_->ProcessBuffers(buffer, output)) { |
+ *has_produced_frame = true; |
output_cb_.Run(output); |
} |
} while (packet.size > 0); |