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 |