| 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);
|
|
|
|
|