| 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/decoder_buffer.h" |
| 10 #include "media/base/demuxer.h" | 11 #include "media/base/demuxer.h" |
| 11 #include "media/base/pipeline.h" | 12 #include "media/base/pipeline.h" |
| 12 #include "media/ffmpeg/ffmpeg_common.h" | 13 #include "media/ffmpeg/ffmpeg_common.h" |
| 13 | 14 |
| 14 namespace media { | 15 namespace media { |
| 15 | 16 |
| 16 // Returns true if the decode result was an error. | 17 // Returns true if the decode result was an error. |
| 17 static bool IsErrorResult(int result, int decoded_size) { | 18 static bool IsErrorResult(int result, int decoded_size) { |
| 18 return result < 0 || | 19 return result < 0 || |
| 19 decoded_size < 0 || | 20 decoded_size < 0 || |
| (...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 161 | 162 |
| 162 void FFmpegAudioDecoder::DoRead(const ReadCB& read_cb) { | 163 void FFmpegAudioDecoder::DoRead(const ReadCB& read_cb) { |
| 163 DCHECK_EQ(MessageLoop::current(), message_loop_); | 164 DCHECK_EQ(MessageLoop::current(), message_loop_); |
| 164 DCHECK(!read_cb.is_null()); | 165 DCHECK(!read_cb.is_null()); |
| 165 CHECK(read_cb_.is_null()) << "Overlapping decodes are not supported."; | 166 CHECK(read_cb_.is_null()) << "Overlapping decodes are not supported."; |
| 166 | 167 |
| 167 read_cb_ = read_cb; | 168 read_cb_ = read_cb; |
| 168 ReadFromDemuxerStream(); | 169 ReadFromDemuxerStream(); |
| 169 } | 170 } |
| 170 | 171 |
| 171 void FFmpegAudioDecoder::DoDecodeBuffer(const scoped_refptr<Buffer>& input) { | 172 void FFmpegAudioDecoder::DoDecodeBuffer( |
| 173 const scoped_refptr<DecoderBuffer>& input) { |
| 172 DCHECK_EQ(MessageLoop::current(), message_loop_); | 174 DCHECK_EQ(MessageLoop::current(), message_loop_); |
| 173 DCHECK(!read_cb_.is_null()); | 175 DCHECK(!read_cb_.is_null()); |
| 174 | 176 |
| 175 if (!input) { | 177 if (!input) { |
| 176 // DemuxeStream::Read() was aborted so we abort the decoder's pending read. | 178 // DemuxeStream::Read() was aborted so we abort the decoder's pending read. |
| 177 DeliverSamples(NULL); | 179 DeliverSamples(NULL); |
| 178 return; | 180 return; |
| 179 } | 181 } |
| 180 | 182 |
| 181 // FFmpeg tends to seek Ogg audio streams in the middle of nowhere, giving us | 183 // FFmpeg tends to seek Ogg audio streams in the middle of nowhere, giving us |
| 182 // a whole bunch of AV_NOPTS_VALUE packets. Discard them until we find | 184 // a whole bunch of AV_NOPTS_VALUE packets. Discard them until we find |
| 183 // something valid. Refer to http://crbug.com/49709 | 185 // something valid. Refer to http://crbug.com/49709 |
| 184 if (input->GetTimestamp() == kNoTimestamp() && | 186 if (input->GetTimestamp() == kNoTimestamp() && |
| 185 estimated_next_timestamp_ == kNoTimestamp() && | 187 estimated_next_timestamp_ == kNoTimestamp() && |
| 186 !input->IsEndOfStream()) { | 188 !input->IsEndOfStream()) { |
| 187 ReadFromDemuxerStream(); | 189 ReadFromDemuxerStream(); |
| 188 return; | 190 return; |
| 189 } | 191 } |
| 190 | 192 |
| 191 AVPacket packet; | 193 AVPacket packet; |
| 192 av_init_packet(&packet); | 194 av_init_packet(&packet); |
| 193 if (input->IsEndOfStream()) { | 195 packet.data = const_cast<uint8*>(input->GetData()); |
| 194 packet.data = NULL; | 196 packet.size = input->GetDataSize(); |
| 195 packet.size = 0; | |
| 196 } else { | |
| 197 packet.data = const_cast<uint8*>(input->GetData()); | |
| 198 packet.size = input->GetDataSize(); | |
| 199 } | |
| 200 | 197 |
| 201 PipelineStatistics statistics; | 198 PipelineStatistics statistics; |
| 202 statistics.audio_bytes_decoded = input->GetDataSize(); | 199 statistics.audio_bytes_decoded = input->GetDataSize(); |
| 203 | 200 |
| 204 int decoded_audio_size = decoded_audio_size_; | 201 int decoded_audio_size = decoded_audio_size_; |
| 205 int result = avcodec_decode_audio3( | 202 int result = avcodec_decode_audio3( |
| 206 codec_context_, reinterpret_cast<int16_t*>(decoded_audio_), | 203 codec_context_, reinterpret_cast<int16_t*>(decoded_audio_), |
| 207 &decoded_audio_size, &packet); | 204 &decoded_audio_size, &packet); |
| 208 | 205 |
| 209 if (IsErrorResult(result, decoded_audio_size)) { | 206 if (IsErrorResult(result, decoded_audio_size)) { |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 249 ReadFromDemuxerStream(); | 246 ReadFromDemuxerStream(); |
| 250 } | 247 } |
| 251 } | 248 } |
| 252 | 249 |
| 253 void FFmpegAudioDecoder::ReadFromDemuxerStream() { | 250 void FFmpegAudioDecoder::ReadFromDemuxerStream() { |
| 254 DCHECK(!read_cb_.is_null()); | 251 DCHECK(!read_cb_.is_null()); |
| 255 | 252 |
| 256 demuxer_stream_->Read(base::Bind(&FFmpegAudioDecoder::DecodeBuffer, this)); | 253 demuxer_stream_->Read(base::Bind(&FFmpegAudioDecoder::DecodeBuffer, this)); |
| 257 } | 254 } |
| 258 | 255 |
| 259 void FFmpegAudioDecoder::DecodeBuffer(const scoped_refptr<Buffer>& buffer) { | 256 void FFmpegAudioDecoder::DecodeBuffer( |
| 257 const scoped_refptr<DecoderBuffer>& buffer) { |
| 260 // TODO(scherkus): fix FFmpegDemuxerStream::Read() to not execute our read | 258 // TODO(scherkus): fix FFmpegDemuxerStream::Read() to not execute our read |
| 261 // callback on the same execution stack so we can get rid of forced task post. | 259 // callback on the same execution stack so we can get rid of forced task post. |
| 262 message_loop_->PostTask(FROM_HERE, base::Bind( | 260 message_loop_->PostTask(FROM_HERE, base::Bind( |
| 263 &FFmpegAudioDecoder::DoDecodeBuffer, this, buffer)); | 261 &FFmpegAudioDecoder::DoDecodeBuffer, this, buffer)); |
| 264 } | 262 } |
| 265 | 263 |
| 266 void FFmpegAudioDecoder::UpdateDurationAndTimestamp( | 264 void FFmpegAudioDecoder::UpdateDurationAndTimestamp( |
| 267 const Buffer* input, | 265 const Buffer* input, |
| 268 DataBuffer* output) { | 266 DataBuffer* output) { |
| 269 // Always calculate duration based on the actual number of samples decoded. | 267 // Always calculate duration based on the actual number of samples decoded. |
| (...skipping 24 matching lines...) Expand all Loading... |
| 294 } | 292 } |
| 295 | 293 |
| 296 void FFmpegAudioDecoder::DeliverSamples(const scoped_refptr<Buffer>& samples) { | 294 void FFmpegAudioDecoder::DeliverSamples(const scoped_refptr<Buffer>& samples) { |
| 297 // Reset the callback before running to protect against reentrancy. | 295 // Reset the callback before running to protect against reentrancy. |
| 298 ReadCB read_cb = read_cb_; | 296 ReadCB read_cb = read_cb_; |
| 299 read_cb_.Reset(); | 297 read_cb_.Reset(); |
| 300 read_cb.Run(samples); | 298 read_cb.Run(samples); |
| 301 } | 299 } |
| 302 | 300 |
| 303 } // namespace media | 301 } // namespace media |
| OLD | NEW |