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 "base/callback_helpers.h" |
9 #include "base/location.h" | 9 #include "base/location.h" |
10 #include "base/single_thread_task_runner.h" | 10 #include "base/single_thread_task_runner.h" |
(...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
121 frame->buf[0] = av_buffer_create( | 121 frame->buf[0] = av_buffer_create( |
122 frame->data[0], buffer_size_in_bytes, ReleaseAudioBufferImpl, opaque, 0); | 122 frame->data[0], buffer_size_in_bytes, ReleaseAudioBufferImpl, opaque, 0); |
123 return 0; | 123 return 0; |
124 } | 124 } |
125 | 125 |
126 FFmpegAudioDecoder::FFmpegAudioDecoder( | 126 FFmpegAudioDecoder::FFmpegAudioDecoder( |
127 const scoped_refptr<base::SingleThreadTaskRunner>& task_runner) | 127 const scoped_refptr<base::SingleThreadTaskRunner>& task_runner) |
128 : task_runner_(task_runner), | 128 : task_runner_(task_runner), |
129 weak_factory_(this), | 129 weak_factory_(this), |
130 state_(kUninitialized), | 130 state_(kUninitialized), |
131 bytes_per_channel_(0), | |
132 channel_layout_(CHANNEL_LAYOUT_NONE), | |
133 channels_(0), | |
134 samples_per_second_(0), | |
135 av_sample_format_(0), | 131 av_sample_format_(0), |
136 last_input_timestamp_(kNoTimestamp()), | 132 last_input_timestamp_(kNoTimestamp()), |
137 output_frames_to_drop_(0) {} | 133 output_frames_to_drop_(0) {} |
138 | 134 |
139 FFmpegAudioDecoder::~FFmpegAudioDecoder() { | 135 FFmpegAudioDecoder::~FFmpegAudioDecoder() { |
140 DCHECK_EQ(state_, kUninitialized); | 136 DCHECK_EQ(state_, kUninitialized); |
141 DCHECK(!codec_context_); | 137 DCHECK(!codec_context_); |
142 DCHECK(!av_frame_); | 138 DCHECK(!av_frame_); |
143 } | 139 } |
144 | 140 |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
191 | 187 |
192 scoped_refptr<AudioBuffer> FFmpegAudioDecoder::GetDecodeOutput() { | 188 scoped_refptr<AudioBuffer> FFmpegAudioDecoder::GetDecodeOutput() { |
193 DCHECK(task_runner_->BelongsToCurrentThread()); | 189 DCHECK(task_runner_->BelongsToCurrentThread()); |
194 if (queued_audio_.empty()) | 190 if (queued_audio_.empty()) |
195 return NULL; | 191 return NULL; |
196 scoped_refptr<AudioBuffer> out = queued_audio_.front(); | 192 scoped_refptr<AudioBuffer> out = queued_audio_.front(); |
197 queued_audio_.pop_front(); | 193 queued_audio_.pop_front(); |
198 return out; | 194 return out; |
199 } | 195 } |
200 | 196 |
201 int FFmpegAudioDecoder::bits_per_channel() { | |
202 DCHECK(task_runner_->BelongsToCurrentThread()); | |
203 return bytes_per_channel_ * 8; | |
204 } | |
205 | |
206 ChannelLayout FFmpegAudioDecoder::channel_layout() { | |
207 DCHECK(task_runner_->BelongsToCurrentThread()); | |
208 return channel_layout_; | |
209 } | |
210 | |
211 int FFmpegAudioDecoder::samples_per_second() { | |
212 DCHECK(task_runner_->BelongsToCurrentThread()); | |
213 return samples_per_second_; | |
214 } | |
215 | |
216 void FFmpegAudioDecoder::Reset(const base::Closure& closure) { | 197 void FFmpegAudioDecoder::Reset(const base::Closure& closure) { |
217 DCHECK(task_runner_->BelongsToCurrentThread()); | 198 DCHECK(task_runner_->BelongsToCurrentThread()); |
218 | 199 |
219 avcodec_flush_buffers(codec_context_.get()); | 200 avcodec_flush_buffers(codec_context_.get()); |
220 state_ = kNormal; | 201 state_ = kNormal; |
221 ResetTimestampState(); | 202 ResetTimestampState(); |
222 task_runner_->PostTask(FROM_HERE, closure); | 203 task_runner_->PostTask(FROM_HERE, closure); |
223 } | 204 } |
224 | 205 |
225 void FFmpegAudioDecoder::Stop(const base::Closure& closure) { | 206 void FFmpegAudioDecoder::Stop(const base::Closure& closure) { |
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
280 decode_cb.Run(kDecodeError, NULL); | 261 decode_cb.Run(kDecodeError, NULL); |
281 return; | 262 return; |
282 } | 263 } |
283 | 264 |
284 if (!buffer->end_of_stream()) { | 265 if (!buffer->end_of_stream()) { |
285 if (last_input_timestamp_ == kNoTimestamp() && | 266 if (last_input_timestamp_ == kNoTimestamp() && |
286 codec_context_->codec_id == AV_CODEC_ID_VORBIS && | 267 codec_context_->codec_id == AV_CODEC_ID_VORBIS && |
287 buffer->timestamp() < base::TimeDelta()) { | 268 buffer->timestamp() < base::TimeDelta()) { |
288 // Dropping frames for negative timestamps as outlined in section A.2 | 269 // Dropping frames for negative timestamps as outlined in section A.2 |
289 // in the Vorbis spec. http://xiph.org/vorbis/doc/Vorbis_I_spec.html | 270 // in the Vorbis spec. http://xiph.org/vorbis/doc/Vorbis_I_spec.html |
290 output_frames_to_drop_ = floor( | 271 output_frames_to_drop_ = floor(0.5 + -buffer->timestamp().InSecondsF() * |
291 0.5 + -buffer->timestamp().InSecondsF() * samples_per_second_); | 272 config_.samples_per_second()); |
292 } else { | 273 } else { |
293 if (last_input_timestamp_ != kNoTimestamp() && | 274 if (last_input_timestamp_ != kNoTimestamp() && |
294 buffer->timestamp() < last_input_timestamp_) { | 275 buffer->timestamp() < last_input_timestamp_) { |
295 const base::TimeDelta diff = | 276 const base::TimeDelta diff = |
296 buffer->timestamp() - last_input_timestamp_; | 277 buffer->timestamp() - last_input_timestamp_; |
297 DLOG(WARNING) | 278 DLOG(WARNING) |
298 << "Input timestamps are not monotonically increasing! " | 279 << "Input timestamps are not monotonically increasing! " |
299 << " ts " << buffer->timestamp().InMicroseconds() << " us" | 280 << " ts " << buffer->timestamp().InMicroseconds() << " us" |
300 << " diff " << diff.InMicroseconds() << " us"; | 281 << " diff " << diff.InMicroseconds() << " us"; |
301 } | 282 } |
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
386 } else { | 367 } else { |
387 output_timestamp_helper_->SetBaseTimestamp(buffer->timestamp()); | 368 output_timestamp_helper_->SetBaseTimestamp(buffer->timestamp()); |
388 } | 369 } |
389 } | 370 } |
390 | 371 |
391 scoped_refptr<AudioBuffer> output; | 372 scoped_refptr<AudioBuffer> output; |
392 int decoded_frames = 0; | 373 int decoded_frames = 0; |
393 int original_frames = 0; | 374 int original_frames = 0; |
394 int channels = DetermineChannels(av_frame_.get()); | 375 int channels = DetermineChannels(av_frame_.get()); |
395 if (frame_decoded) { | 376 if (frame_decoded) { |
396 | |
397 // TODO(rileya) Remove this check once we properly support midstream audio | |
398 // config changes. | |
399 if (av_frame_->sample_rate != config_.samples_per_second() || | 377 if (av_frame_->sample_rate != config_.samples_per_second() || |
rileya (GONE FROM CHROMIUM)
2014/03/07 01:19:29
jk on the TODO, we still shouldn't expect to see c
| |
400 channels != channels_ || | 378 channels != ChannelLayoutToChannelCount(config_.channel_layout()) || |
DaleCurtis
2014/03/07 02:00:10
Store channels_ ? No need to recompute every pack
| |
401 av_frame_->format != av_sample_format_) { | 379 av_frame_->format != av_sample_format_) { |
402 DLOG(ERROR) << "Unsupported midstream configuration change!" | 380 DLOG(ERROR) << "Unsupported midstream configuration change!" |
403 << " Sample Rate: " << av_frame_->sample_rate << " vs " | 381 << " Sample Rate: " << av_frame_->sample_rate << " vs " |
404 << samples_per_second_ | 382 << config_.samples_per_second() |
405 << ", Channels: " << channels << " vs " | 383 << ", Channels: " << channels << " vs " |
406 << channels_ | 384 << ChannelLayoutToChannelCount(config_.channel_layout()) |
407 << ", Sample Format: " << av_frame_->format << " vs " | 385 << ", Sample Format: " << av_frame_->format << " vs " |
408 << av_sample_format_; | 386 << av_sample_format_; |
409 | 387 |
410 // This is an unrecoverable error, so bail out. | 388 // This is an unrecoverable error, so bail out. |
411 queued_audio_.clear(); | 389 queued_audio_.clear(); |
412 av_frame_unref(av_frame_.get()); | 390 av_frame_unref(av_frame_.get()); |
413 return false; | 391 return false; |
414 } | 392 } |
415 | 393 |
416 // Get the AudioBuffer that the data was decoded into. Adjust the number | 394 // Get the AudioBuffer that the data was decoded into. Adjust the number |
417 // of frames, in case fewer than requested were actually decoded. | 395 // of frames, in case fewer than requested were actually decoded. |
418 output = reinterpret_cast<AudioBuffer*>( | 396 output = reinterpret_cast<AudioBuffer*>( |
419 av_buffer_get_opaque(av_frame_->buf[0])); | 397 av_buffer_get_opaque(av_frame_->buf[0])); |
420 | 398 |
421 DCHECK_EQ(channels_, output->channel_count()); | 399 DCHECK_EQ(ChannelLayoutToChannelCount(config_.channel_layout()), |
400 output->channel_count()); | |
422 original_frames = av_frame_->nb_samples; | 401 original_frames = av_frame_->nb_samples; |
423 int unread_frames = output->frame_count() - original_frames; | 402 int unread_frames = output->frame_count() - original_frames; |
424 DCHECK_GE(unread_frames, 0); | 403 DCHECK_GE(unread_frames, 0); |
425 if (unread_frames > 0) | 404 if (unread_frames > 0) |
426 output->TrimEnd(unread_frames); | 405 output->TrimEnd(unread_frames); |
427 | 406 |
428 // If there are frames to drop, get rid of as many as we can. | 407 // If there are frames to drop, get rid of as many as we can. |
429 if (output_frames_to_drop_ > 0) { | 408 if (output_frames_to_drop_ > 0) { |
430 int drop = std::min(output->frame_count(), output_frames_to_drop_); | 409 int drop = std::min(output->frame_count(), output_frames_to_drop_); |
431 output->TrimStart(drop); | 410 output->TrimStart(drop); |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
474 << " bits per channel: " << config_.bits_per_channel() | 453 << " bits per channel: " << config_.bits_per_channel() |
475 << " samples per second: " << config_.samples_per_second(); | 454 << " samples per second: " << config_.samples_per_second(); |
476 return false; | 455 return false; |
477 } | 456 } |
478 | 457 |
479 if (config_.is_encrypted()) { | 458 if (config_.is_encrypted()) { |
480 DLOG(ERROR) << "Encrypted audio stream not supported"; | 459 DLOG(ERROR) << "Encrypted audio stream not supported"; |
481 return false; | 460 return false; |
482 } | 461 } |
483 | 462 |
484 // TODO(rileya) Remove this check once we properly support midstream audio | |
485 // config changes. | |
486 if (codec_context_.get() && | |
487 (bytes_per_channel_ != config_.bytes_per_channel() || | |
488 channel_layout_ != config_.channel_layout() || | |
489 samples_per_second_ != config_.samples_per_second())) { | |
490 DVLOG(1) << "Unsupported config change :"; | |
491 DVLOG(1) << "\tbytes_per_channel : " << bytes_per_channel_ | |
492 << " -> " << config_.bytes_per_channel(); | |
493 DVLOG(1) << "\tchannel_layout : " << channel_layout_ | |
494 << " -> " << config_.channel_layout(); | |
495 DVLOG(1) << "\tsample_rate : " << samples_per_second_ | |
496 << " -> " << config_.samples_per_second(); | |
497 return false; | |
498 } | |
499 | |
500 // Release existing decoder resources if necessary. | 463 // Release existing decoder resources if necessary. |
501 ReleaseFFmpegResources(); | 464 ReleaseFFmpegResources(); |
502 | 465 |
503 // Initialize AVCodecContext structure. | 466 // Initialize AVCodecContext structure. |
504 codec_context_.reset(avcodec_alloc_context3(NULL)); | 467 codec_context_.reset(avcodec_alloc_context3(NULL)); |
505 AudioDecoderConfigToAVCodecContext(config_, codec_context_.get()); | 468 AudioDecoderConfigToAVCodecContext(config_, codec_context_.get()); |
506 | 469 |
507 codec_context_->opaque = this; | 470 codec_context_->opaque = this; |
508 codec_context_->get_buffer2 = GetAudioBuffer; | 471 codec_context_->get_buffer2 = GetAudioBuffer; |
509 codec_context_->refcounted_frames = 1; | 472 codec_context_->refcounted_frames = 1; |
510 | 473 |
511 AVCodec* codec = avcodec_find_decoder(codec_context_->codec_id); | 474 AVCodec* codec = avcodec_find_decoder(codec_context_->codec_id); |
512 if (!codec || avcodec_open2(codec_context_.get(), codec, NULL) < 0) { | 475 if (!codec || avcodec_open2(codec_context_.get(), codec, NULL) < 0) { |
513 DLOG(ERROR) << "Could not initialize audio decoder: " | 476 DLOG(ERROR) << "Could not initialize audio decoder: " |
514 << codec_context_->codec_id; | 477 << codec_context_->codec_id; |
515 ReleaseFFmpegResources(); | 478 ReleaseFFmpegResources(); |
516 state_ = kUninitialized; | 479 state_ = kUninitialized; |
517 return false; | 480 return false; |
518 } | 481 } |
519 | 482 |
520 // Success! | 483 // Success! |
521 av_frame_.reset(av_frame_alloc()); | 484 av_frame_.reset(av_frame_alloc()); |
522 channel_layout_ = config_.channel_layout(); | |
523 samples_per_second_ = config_.samples_per_second(); | |
524 output_timestamp_helper_.reset( | 485 output_timestamp_helper_.reset( |
525 new AudioTimestampHelper(config_.samples_per_second())); | 486 new AudioTimestampHelper(config_.samples_per_second())); |
526 | 487 |
527 // Store initial values to guard against midstream configuration changes. | 488 av_sample_format_ = codec_context_->sample_fmt; |
528 channels_ = codec_context_->channels; | 489 |
529 if (channels_ != ChannelLayoutToChannelCount(channel_layout_)) { | 490 if (codec_context_->channels != |
491 ChannelLayoutToChannelCount(config_.channel_layout())) { | |
530 DLOG(ERROR) << "Audio configuration specified " | 492 DLOG(ERROR) << "Audio configuration specified " |
531 << ChannelLayoutToChannelCount(channel_layout_) | 493 << ChannelLayoutToChannelCount(config_.channel_layout()) |
532 << " channels, but FFmpeg thinks the file contains " | 494 << " channels, but FFmpeg thinks the file contains " |
533 << channels_ << " channels"; | 495 << codec_context_->channels << " channels"; |
534 return false; | 496 return false; |
535 } | 497 } |
536 av_sample_format_ = codec_context_->sample_fmt; | |
537 sample_format_ = AVSampleFormatToSampleFormat( | |
538 static_cast<AVSampleFormat>(av_sample_format_)); | |
539 bytes_per_channel_ = SampleFormatToBytesPerChannel(sample_format_); | |
540 | |
541 return true; | 498 return true; |
542 } | 499 } |
543 | 500 |
544 void FFmpegAudioDecoder::ResetTimestampState() { | 501 void FFmpegAudioDecoder::ResetTimestampState() { |
545 output_timestamp_helper_->SetBaseTimestamp(kNoTimestamp()); | 502 output_timestamp_helper_->SetBaseTimestamp(kNoTimestamp()); |
546 last_input_timestamp_ = kNoTimestamp(); | 503 last_input_timestamp_ = kNoTimestamp(); |
547 output_frames_to_drop_ = 0; | 504 output_frames_to_drop_ = 0; |
548 } | 505 } |
549 | 506 |
550 } // namespace media | 507 } // namespace media |
OLD | NEW |