Index: media/filters/ffmpeg_audio_decoder.cc |
=================================================================== |
--- media/filters/ffmpeg_audio_decoder.cc (revision 277175) |
+++ media/filters/ffmpeg_audio_decoder.cc (working copy) |
@@ -141,8 +141,7 @@ |
} |
void FFmpegAudioDecoder::Initialize(const AudioDecoderConfig& config, |
- const PipelineStatusCB& status_cb, |
- const OutputCB& output_cb) { |
+ const PipelineStatusCB& status_cb) { |
DCHECK(task_runner_->BelongsToCurrentThread()); |
DCHECK(!config.is_encrypted()); |
@@ -157,7 +156,6 @@ |
} |
// Success! |
- output_cb_ = BindToCurrentLoop(output_cb); |
state_ = kNormal; |
initialize_cb.Run(PIPELINE_OK); |
} |
@@ -170,19 +168,33 @@ |
DecodeCB decode_cb_bound = BindToCurrentLoop(decode_cb); |
if (state_ == kError) { |
- decode_cb_bound.Run(kDecodeError); |
+ decode_cb_bound.Run(kDecodeError, NULL); |
return; |
} |
- // Do nothing if decoding has finished. |
+ // Return empty frames if decoding has finished. |
if (state_ == kDecodeFinished) { |
- decode_cb_bound.Run(kOk); |
+ decode_cb_bound.Run(kOk, AudioBuffer::CreateEOSBuffer()); |
return; |
} |
+ if (!buffer) { |
+ decode_cb_bound.Run(kAborted, NULL); |
+ return; |
+ } |
+ |
DecodeBuffer(buffer, decode_cb_bound); |
} |
+scoped_refptr<AudioBuffer> FFmpegAudioDecoder::GetDecodeOutput() { |
+ DCHECK(task_runner_->BelongsToCurrentThread()); |
+ if (queued_audio_.empty()) |
+ return NULL; |
+ scoped_refptr<AudioBuffer> out = queued_audio_.front(); |
+ queued_audio_.pop_front(); |
+ return out; |
+} |
+ |
void FFmpegAudioDecoder::Reset(const base::Closure& closure) { |
DCHECK(task_runner_->BelongsToCurrentThread()); |
@@ -245,7 +257,7 @@ |
// occurs with some damaged files. |
if (!buffer->end_of_stream() && buffer->timestamp() == kNoTimestamp()) { |
DVLOG(1) << "Received a buffer without timestamps!"; |
- decode_cb.Run(kDecodeError); |
+ decode_cb.Run(kDecodeError, NULL); |
return; |
} |
@@ -259,22 +271,37 @@ |
discard_helper_->Reset(discard_frames); |
} |
+ // Transition to kFlushCodec on the first end of stream buffer. |
+ if (state_ == kNormal && buffer->end_of_stream()) { |
+ state_ = kFlushCodec; |
+ } |
+ |
if (!FFmpegDecode(buffer)) { |
state_ = kError; |
- decode_cb.Run(kDecodeError); |
+ decode_cb.Run(kDecodeError, NULL); |
return; |
} |
- if (buffer->end_of_stream()) { |
- state_ = kDecodeFinished; |
- output_cb_.Run(AudioBuffer::CreateEOSBuffer()); |
+ if (queued_audio_.empty()) { |
+ if (state_ == kFlushCodec) { |
+ DCHECK(buffer->end_of_stream()); |
+ state_ = kDecodeFinished; |
+ decode_cb.Run(kOk, AudioBuffer::CreateEOSBuffer()); |
+ return; |
+ } |
+ |
+ decode_cb.Run(kNotEnoughData, NULL); |
+ return; |
} |
- decode_cb.Run(kOk); |
+ decode_cb.Run(kOk, queued_audio_.front()); |
+ queued_audio_.pop_front(); |
} |
bool FFmpegAudioDecoder::FFmpegDecode( |
const scoped_refptr<DecoderBuffer>& buffer) { |
+ DCHECK(queued_audio_.empty()); |
+ |
AVPacket packet; |
av_init_packet(&packet); |
if (buffer->end_of_stream()) { |
@@ -335,6 +362,7 @@ |
<< " the mimetype."; |
} |
// This is an unrecoverable error, so bail out. |
+ queued_audio_.clear(); |
av_frame_unref(av_frame_.get()); |
return false; |
} |
@@ -357,9 +385,9 @@ |
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()); |
+ queued_audio_.push_back(AudioBuffer::CreateEOSBuffer()); |
} else if (discard_helper_->ProcessBuffers(buffer, output)) { |
- output_cb_.Run(output); |
+ queued_audio_.push_back(output); |
} |
} while (packet.size > 0); |