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