| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "media/filters/ffmpeg_audio_decoder.h" | 5 #include "media/filters/ffmpeg_audio_decoder.h" |
| 6 | 6 |
| 7 #include "base/bind.h" | 7 #include "base/bind.h" |
| 8 #include "media/base/audio_decoder_config.h" | 8 #include "media/base/audio_decoder_config.h" |
| 9 #include "media/base/data_buffer.h" | 9 #include "media/base/data_buffer.h" |
| 10 #include "media/base/demuxer.h" | 10 #include "media/base/demuxer.h" |
| (...skipping 27 matching lines...) Expand all Loading... |
| 38 // Returns true if the decode result was end of stream. | 38 // Returns true if the decode result was end of stream. |
| 39 static bool IsEndOfStream(int result, int decoded_size, Buffer* input) { | 39 static bool IsEndOfStream(int result, int decoded_size, Buffer* input) { |
| 40 // Three conditions to meet to declare end of stream for this decoder: | 40 // Three conditions to meet to declare end of stream for this decoder: |
| 41 // 1. FFmpeg didn't read anything. | 41 // 1. FFmpeg didn't read anything. |
| 42 // 2. FFmpeg didn't output anything. | 42 // 2. FFmpeg didn't output anything. |
| 43 // 3. An end of stream buffer is received. | 43 // 3. An end of stream buffer is received. |
| 44 return result == 0 && decoded_size == 0 && input->IsEndOfStream(); | 44 return result == 0 && decoded_size == 0 && input->IsEndOfStream(); |
| 45 } | 45 } |
| 46 | 46 |
| 47 | 47 |
| 48 FFmpegAudioDecoder::FFmpegAudioDecoder(MessageLoop* message_loop) | 48 FFmpegAudioDecoder::FFmpegAudioDecoder( |
| 49 : message_loop_(message_loop), | 49 const base::Callback<MessageLoop*()>& message_loop_cb) |
| 50 : message_loop_factory_cb_(message_loop_cb), |
| 51 message_loop_(NULL), |
| 50 codec_context_(NULL), | 52 codec_context_(NULL), |
| 51 bits_per_channel_(0), | 53 bits_per_channel_(0), |
| 52 channel_layout_(CHANNEL_LAYOUT_NONE), | 54 channel_layout_(CHANNEL_LAYOUT_NONE), |
| 53 samples_per_second_(0), | 55 samples_per_second_(0), |
| 54 decoded_audio_size_(AVCODEC_MAX_AUDIO_FRAME_SIZE), | 56 decoded_audio_size_(AVCODEC_MAX_AUDIO_FRAME_SIZE), |
| 55 decoded_audio_(static_cast<uint8*>(av_malloc(decoded_audio_size_))) { | 57 decoded_audio_(static_cast<uint8*>(av_malloc(decoded_audio_size_))) { |
| 56 } | 58 } |
| 57 | 59 |
| 58 FFmpegAudioDecoder::~FFmpegAudioDecoder() { | 60 FFmpegAudioDecoder::~FFmpegAudioDecoder() { |
| 59 av_free(decoded_audio_); | 61 av_free(decoded_audio_); |
| 60 | 62 |
| 61 // TODO(scherkus): should we require Stop() to be called? this might end up | 63 // TODO(scherkus): should we require Stop() to be called? this might end up |
| 62 // getting called on a random thread due to refcounting. | 64 // getting called on a random thread due to refcounting. |
| 63 if (codec_context_) { | 65 if (codec_context_) { |
| 64 av_free(codec_context_->extradata); | 66 av_free(codec_context_->extradata); |
| 65 avcodec_close(codec_context_); | 67 avcodec_close(codec_context_); |
| 66 av_free(codec_context_); | 68 av_free(codec_context_); |
| 67 } | 69 } |
| 68 } | 70 } |
| 69 | 71 |
| 70 void FFmpegAudioDecoder::Initialize( | 72 void FFmpegAudioDecoder::Initialize( |
| 71 const scoped_refptr<DemuxerStream>& stream, | 73 const scoped_refptr<DemuxerStream>& stream, |
| 72 const PipelineStatusCB& pipeline_status_cb, | 74 const PipelineStatusCB& pipeline_status_cb, |
| 73 const StatisticsCB& statistics_cb) { | 75 const StatisticsCB& statistics_cb) { |
| 76 if (!message_loop_) { |
| 77 message_loop_ = message_loop_factory_cb_.Run(); |
| 78 message_loop_factory_cb_.Reset(); |
| 79 } else { |
| 80 // TODO(scherkus): initialization currently happens more than once in |
| 81 // PipelineIntegrationTest.BasicPlayback. |
| 82 LOG(ERROR) << "Initialize has already been called."; |
| 83 } |
| 74 message_loop_->PostTask( | 84 message_loop_->PostTask( |
| 75 FROM_HERE, | 85 FROM_HERE, |
| 76 base::Bind(&FFmpegAudioDecoder::DoInitialize, this, | 86 base::Bind(&FFmpegAudioDecoder::DoInitialize, this, |
| 77 stream, pipeline_status_cb, statistics_cb)); | 87 stream, pipeline_status_cb, statistics_cb)); |
| 78 } | 88 } |
| 79 | 89 |
| 80 void FFmpegAudioDecoder::Read(const ReadCB& read_cb) { | 90 void FFmpegAudioDecoder::Read(const ReadCB& read_cb) { |
| 81 // Complete operation asynchronously on different stack of execution as per | 91 // Complete operation asynchronously on different stack of execution as per |
| 82 // the API contract of AudioDecoder::Read() | 92 // the API contract of AudioDecoder::Read() |
| 83 message_loop_->PostTask(FROM_HERE, base::Bind( | 93 message_loop_->PostTask(FROM_HERE, base::Bind( |
| (...skipping 200 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 284 } | 294 } |
| 285 | 295 |
| 286 void FFmpegAudioDecoder::DeliverSamples(const scoped_refptr<Buffer>& samples) { | 296 void FFmpegAudioDecoder::DeliverSamples(const scoped_refptr<Buffer>& samples) { |
| 287 // Reset the callback before running to protect against reentrancy. | 297 // Reset the callback before running to protect against reentrancy. |
| 288 ReadCB read_cb = read_cb_; | 298 ReadCB read_cb = read_cb_; |
| 289 read_cb_.Reset(); | 299 read_cb_.Reset(); |
| 290 read_cb.Run(samples); | 300 read_cb.Run(samples); |
| 291 } | 301 } |
| 292 | 302 |
| 293 } // namespace media | 303 } // namespace media |
| OLD | NEW |