| Index: media/filters/ffmpeg_audio_decoder.cc
|
| diff --git a/media/filters/ffmpeg_audio_decoder.cc b/media/filters/ffmpeg_audio_decoder.cc
|
| index 3a0ab344641e9d4f279858075b00befac52782bc..61aa02ba82c19ce92ae77d7547d1a9dda92a44b7 100644
|
| --- a/media/filters/ffmpeg_audio_decoder.cc
|
| +++ b/media/filters/ffmpeg_audio_decoder.cc
|
| @@ -52,8 +52,7 @@ FFmpegAudioDecoder::FFmpegAudioDecoder(MessageLoop* message_loop)
|
| channel_layout_(CHANNEL_LAYOUT_NONE),
|
| samples_per_second_(0),
|
| decoded_audio_size_(AVCODEC_MAX_AUDIO_FRAME_SIZE),
|
| - decoded_audio_(static_cast<uint8*>(av_malloc(decoded_audio_size_))),
|
| - pending_reads_(0) {
|
| + decoded_audio_(static_cast<uint8*>(av_malloc(decoded_audio_size_))) {
|
| }
|
|
|
| FFmpegAudioDecoder::~FFmpegAudioDecoder() {
|
| @@ -87,11 +86,11 @@ void FFmpegAudioDecoder::Initialize(
|
| ref_stream, callback, stats_callback));
|
| }
|
|
|
| -void FFmpegAudioDecoder::ProduceAudioSamples(scoped_refptr<Buffer> buffer) {
|
| - message_loop_->PostTask(
|
| - FROM_HERE,
|
| - base::Bind(&FFmpegAudioDecoder::DoProduceAudioSamples, this,
|
| - buffer));
|
| +void FFmpegAudioDecoder::Read(const ReadCB& callback) {
|
| + // Complete operation asynchronously on different stack of execution as per
|
| + // the API contract of AudioDecoder::Read()
|
| + message_loop_->PostTask(FROM_HERE, base::Bind(
|
| + &FFmpegAudioDecoder::DoRead, this, callback));
|
| }
|
|
|
| int FFmpegAudioDecoder::bits_per_channel() {
|
| @@ -156,16 +155,18 @@ void FFmpegAudioDecoder::DoFlush(const base::Closure& callback) {
|
| callback.Run();
|
| }
|
|
|
| -void FFmpegAudioDecoder::DoProduceAudioSamples(
|
| - const scoped_refptr<Buffer>& output) {
|
| - output_buffers_.push_back(output);
|
| +void FFmpegAudioDecoder::DoRead(const ReadCB& callback) {
|
| + DCHECK_EQ(MessageLoop::current(), message_loop_);
|
| + DCHECK(!callback.is_null());
|
| + CHECK(read_cb_.is_null()) << "Overlapping decodes are not supported.";
|
| +
|
| + read_cb_ = callback;
|
| ReadFromDemuxerStream();
|
| }
|
|
|
| void FFmpegAudioDecoder::DoDecodeBuffer(const scoped_refptr<Buffer>& input) {
|
| - DCHECK(!output_buffers_.empty());
|
| - DCHECK_GT(pending_reads_, 0);
|
| - pending_reads_--;
|
| + DCHECK_EQ(MessageLoop::current(), message_loop_);
|
| + DCHECK(!read_cb_.is_null());
|
|
|
| // FFmpeg tends to seek Ogg audio streams in the middle of nowhere, giving us
|
| // a whole bunch of AV_NOPTS_VALUE packets. Discard them until we find
|
| @@ -233,27 +234,23 @@ void FFmpegAudioDecoder::DoDecodeBuffer(const scoped_refptr<Buffer>& input) {
|
| // Decoding finished successfully, update stats and execute callback.
|
| stats_callback_.Run(statistics);
|
| if (output) {
|
| - DCHECK_GT(output_buffers_.size(), 0u);
|
| - output_buffers_.pop_front();
|
| -
|
| - ConsumeAudioSamples(output);
|
| + DeliverSamples(output);
|
| } else {
|
| ReadFromDemuxerStream();
|
| }
|
| }
|
|
|
| void FFmpegAudioDecoder::ReadFromDemuxerStream() {
|
| - DCHECK(!output_buffers_.empty())
|
| - << "Reads should only occur if there are output buffers.";
|
| + DCHECK(!read_cb_.is_null());
|
|
|
| - pending_reads_++;
|
| demuxer_stream_->Read(base::Bind(&FFmpegAudioDecoder::DecodeBuffer, this));
|
| }
|
|
|
| void FFmpegAudioDecoder::DecodeBuffer(const scoped_refptr<Buffer>& buffer) {
|
| - message_loop_->PostTask(
|
| - FROM_HERE,
|
| - base::Bind(&FFmpegAudioDecoder::DoDecodeBuffer, this, buffer));
|
| + // TODO(scherkus): fix FFmpegDemuxerStream::Read() to not execute our read
|
| + // callback on the same execution stack so we can get rid of forced task post.
|
| + message_loop_->PostTask(FROM_HERE, base::Bind(
|
| + &FFmpegAudioDecoder::DoDecodeBuffer, this, buffer));
|
| }
|
|
|
| void FFmpegAudioDecoder::UpdateDurationAndTimestamp(
|
| @@ -286,4 +283,11 @@ base::TimeDelta FFmpegAudioDecoder::CalculateDuration(int size) {
|
| return base::TimeDelta::FromMicroseconds(static_cast<int64>(microseconds));
|
| }
|
|
|
| +void FFmpegAudioDecoder::DeliverSamples(const scoped_refptr<Buffer>& samples) {
|
| + // Reset the callback before running to protect against reentrancy.
|
| + ReadCB read_cb = read_cb_;
|
| + read_cb_.Reset();
|
| + read_cb.Run(samples);
|
| +}
|
| +
|
| } // namespace media
|
|
|