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 "base/callback_helpers.h" |
8 #include "media/base/audio_decoder_config.h" | 9 #include "media/base/audio_decoder_config.h" |
9 #include "media/base/data_buffer.h" | 10 #include "media/base/data_buffer.h" |
10 #include "media/base/decoder_buffer.h" | 11 #include "media/base/decoder_buffer.h" |
11 #include "media/base/demuxer.h" | 12 #include "media/base/demuxer.h" |
12 #include "media/base/pipeline.h" | 13 #include "media/base/pipeline.h" |
13 #include "media/ffmpeg/ffmpeg_common.h" | 14 #include "media/ffmpeg/ffmpeg_common.h" |
14 #include "media/filters/ffmpeg_glue.h" | 15 #include "media/filters/ffmpeg_glue.h" |
15 | 16 |
16 namespace media { | 17 namespace media { |
17 | 18 |
(...skipping 140 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
158 void FFmpegAudioDecoder::DoRead(const ReadCB& read_cb) { | 159 void FFmpegAudioDecoder::DoRead(const ReadCB& read_cb) { |
159 DCHECK_EQ(MessageLoop::current(), message_loop_); | 160 DCHECK_EQ(MessageLoop::current(), message_loop_); |
160 DCHECK(!read_cb.is_null()); | 161 DCHECK(!read_cb.is_null()); |
161 CHECK(read_cb_.is_null()) << "Overlapping decodes are not supported."; | 162 CHECK(read_cb_.is_null()) << "Overlapping decodes are not supported."; |
162 | 163 |
163 read_cb_ = read_cb; | 164 read_cb_ = read_cb; |
164 ReadFromDemuxerStream(); | 165 ReadFromDemuxerStream(); |
165 } | 166 } |
166 | 167 |
167 void FFmpegAudioDecoder::DoDecodeBuffer( | 168 void FFmpegAudioDecoder::DoDecodeBuffer( |
| 169 DemuxerStream::Status status, |
168 const scoped_refptr<DecoderBuffer>& input) { | 170 const scoped_refptr<DecoderBuffer>& input) { |
169 DCHECK_EQ(MessageLoop::current(), message_loop_); | 171 DCHECK_EQ(MessageLoop::current(), message_loop_); |
170 DCHECK(!read_cb_.is_null()); | 172 DCHECK(!read_cb_.is_null()); |
171 | 173 |
172 if (!input) { | 174 if (status != DemuxerStream::kOk) { |
173 // DemuxeStream::Read() was aborted so we abort the decoder's pending read. | 175 DCHECK(!input); |
174 DeliverSamples(NULL); | 176 // TODO(acolwell): Add support for reinitializing the decoder when |
| 177 // |status| == kConfigChanged. For now we just trigger a decode error. |
| 178 AudioDecoder::Status decoder_status = |
| 179 (status == DemuxerStream::kAborted) ? kAborted : kDecodeError; |
| 180 base::ResetAndReturn(&read_cb_).Run(decoder_status, NULL); |
175 return; | 181 return; |
176 } | 182 } |
177 | 183 |
178 // FFmpeg tends to seek Ogg audio streams in the middle of nowhere, giving us | 184 // FFmpeg tends to seek Ogg audio streams in the middle of nowhere, giving us |
179 // a whole bunch of AV_NOPTS_VALUE packets. Discard them until we find | 185 // a whole bunch of AV_NOPTS_VALUE packets. Discard them until we find |
180 // something valid. Refer to http://crbug.com/49709 | 186 // something valid. Refer to http://crbug.com/49709 |
181 if (input->GetTimestamp() == kNoTimestamp() && | 187 if (input->GetTimestamp() == kNoTimestamp() && |
182 estimated_next_timestamp_ == kNoTimestamp() && | 188 estimated_next_timestamp_ == kNoTimestamp() && |
183 !input->IsEndOfStream()) { | 189 !input->IsEndOfStream()) { |
184 ReadFromDemuxerStream(); | 190 ReadFromDemuxerStream(); |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
237 estimated_next_timestamp_ = input->GetTimestamp() + input->GetDuration(); | 243 estimated_next_timestamp_ = input->GetTimestamp() + input->GetDuration(); |
238 } else if (IsEndOfStream(result, decoded_audio_size, input)) { | 244 } else if (IsEndOfStream(result, decoded_audio_size, input)) { |
239 // Create an end of stream output buffer. | 245 // Create an end of stream output buffer. |
240 output = new DataBuffer(0); | 246 output = new DataBuffer(0); |
241 output->SetTimestamp(input->GetTimestamp()); | 247 output->SetTimestamp(input->GetTimestamp()); |
242 output->SetDuration(input->GetDuration()); | 248 output->SetDuration(input->GetDuration()); |
243 } | 249 } |
244 | 250 |
245 // Decoding finished successfully, update stats and execute callback. | 251 // Decoding finished successfully, update stats and execute callback. |
246 statistics_cb_.Run(statistics); | 252 statistics_cb_.Run(statistics); |
247 if (output) { | 253 if (output) |
248 DeliverSamples(output); | 254 base::ResetAndReturn(&read_cb_).Run(kOk, output); |
249 } else { | 255 else |
250 ReadFromDemuxerStream(); | 256 ReadFromDemuxerStream(); |
251 } | |
252 } | 257 } |
253 | 258 |
254 void FFmpegAudioDecoder::ReadFromDemuxerStream() { | 259 void FFmpegAudioDecoder::ReadFromDemuxerStream() { |
255 DCHECK(!read_cb_.is_null()); | 260 DCHECK(!read_cb_.is_null()); |
256 | 261 |
257 demuxer_stream_->Read(base::Bind(&FFmpegAudioDecoder::DecodeBuffer, this)); | 262 demuxer_stream_->Read(base::Bind(&FFmpegAudioDecoder::DecodeBuffer, this)); |
258 } | 263 } |
259 | 264 |
260 void FFmpegAudioDecoder::DecodeBuffer( | 265 void FFmpegAudioDecoder::DecodeBuffer( |
| 266 DemuxerStream::Status status, |
261 const scoped_refptr<DecoderBuffer>& buffer) { | 267 const scoped_refptr<DecoderBuffer>& buffer) { |
| 268 DCHECK_EQ(status != DemuxerStream::kOk, !buffer) << status; |
| 269 |
262 // TODO(scherkus): fix FFmpegDemuxerStream::Read() to not execute our read | 270 // TODO(scherkus): fix FFmpegDemuxerStream::Read() to not execute our read |
263 // callback on the same execution stack so we can get rid of forced task post. | 271 // callback on the same execution stack so we can get rid of forced task post. |
264 message_loop_->PostTask(FROM_HERE, base::Bind( | 272 message_loop_->PostTask(FROM_HERE, base::Bind( |
265 &FFmpegAudioDecoder::DoDecodeBuffer, this, buffer)); | 273 &FFmpegAudioDecoder::DoDecodeBuffer, this, status, buffer)); |
266 } | 274 } |
267 | 275 |
268 void FFmpegAudioDecoder::UpdateDurationAndTimestamp( | 276 void FFmpegAudioDecoder::UpdateDurationAndTimestamp( |
269 const Buffer* input, | 277 const Buffer* input, |
270 DataBuffer* output) { | 278 DataBuffer* output) { |
271 // Always calculate duration based on the actual number of samples decoded. | 279 // Always calculate duration based on the actual number of samples decoded. |
272 base::TimeDelta duration = CalculateDuration(output->GetDataSize()); | 280 base::TimeDelta duration = CalculateDuration(output->GetDataSize()); |
273 output->SetDuration(duration); | 281 output->SetDuration(duration); |
274 | 282 |
275 // Use the incoming timestamp if it's valid. | 283 // Use the incoming timestamp if it's valid. |
(...skipping 12 matching lines...) Expand all Loading... |
288 } | 296 } |
289 | 297 |
290 base::TimeDelta FFmpegAudioDecoder::CalculateDuration(int size) { | 298 base::TimeDelta FFmpegAudioDecoder::CalculateDuration(int size) { |
291 int64 denominator = ChannelLayoutToChannelCount(channel_layout_) * | 299 int64 denominator = ChannelLayoutToChannelCount(channel_layout_) * |
292 bits_per_channel_ / 8 * samples_per_second_; | 300 bits_per_channel_ / 8 * samples_per_second_; |
293 double microseconds = size / | 301 double microseconds = size / |
294 (denominator / static_cast<double>(base::Time::kMicrosecondsPerSecond)); | 302 (denominator / static_cast<double>(base::Time::kMicrosecondsPerSecond)); |
295 return base::TimeDelta::FromMicroseconds(static_cast<int64>(microseconds)); | 303 return base::TimeDelta::FromMicroseconds(static_cast<int64>(microseconds)); |
296 } | 304 } |
297 | 305 |
298 void FFmpegAudioDecoder::DeliverSamples(const scoped_refptr<Buffer>& samples) { | |
299 // Reset the callback before running to protect against reentrancy. | |
300 ReadCB read_cb = read_cb_; | |
301 read_cb_.Reset(); | |
302 read_cb.Run(samples); | |
303 } | |
304 | |
305 } // namespace media | 306 } // namespace media |
OLD | NEW |