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 <stdint.h> | 7 #include <stdint.h> |
8 | 8 |
9 #include "base/callback_helpers.h" | 9 #include "base/callback_helpers.h" |
10 #include "base/single_thread_task_runner.h" | 10 #include "base/single_thread_task_runner.h" |
(...skipping 374 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
385 av_frame_.reset(); | 385 av_frame_.reset(); |
386 } | 386 } |
387 | 387 |
388 bool FFmpegAudioDecoder::ConfigureDecoder() { | 388 bool FFmpegAudioDecoder::ConfigureDecoder() { |
389 DCHECK(config_.IsValidConfig()); | 389 DCHECK(config_.IsValidConfig()); |
390 DCHECK(!config_.is_encrypted()); | 390 DCHECK(!config_.is_encrypted()); |
391 | 391 |
392 // Release existing decoder resources if necessary. | 392 // Release existing decoder resources if necessary. |
393 ReleaseFFmpegResources(); | 393 ReleaseFFmpegResources(); |
394 | 394 |
395 // Use OpusAudioDecoder for Opus for now, even if FFmpeg claims to support | |
396 // Opus decode. Failure to configure here should lead to fall-back to | |
397 // OpusAudioDecoder. | |
398 // TODO(wolenetz,dalecurtis): Remove OpusAudioDecoder and use | |
399 // FFmpegAudioDecoder instead for Opus. | |
400 if (config_.codec() == kCodecOpus) { | |
401 MEDIA_LOG(DEBUG, media_log_) | |
402 << "Opus decode via FFmpegAudioDecoder is disabled"; | |
403 state_ = kUninitialized; | |
404 return false; | |
405 } | |
406 | |
407 // Initialize AVCodecContext structure. | 395 // Initialize AVCodecContext structure. |
408 codec_context_.reset(avcodec_alloc_context3(NULL)); | 396 codec_context_.reset(avcodec_alloc_context3(NULL)); |
409 AudioDecoderConfigToAVCodecContext(config_, codec_context_.get()); | 397 AudioDecoderConfigToAVCodecContext(config_, codec_context_.get()); |
410 | 398 |
411 codec_context_->opaque = this; | 399 codec_context_->opaque = this; |
412 codec_context_->get_buffer2 = GetAudioBuffer; | 400 codec_context_->get_buffer2 = GetAudioBuffer; |
413 codec_context_->refcounted_frames = 1; | 401 codec_context_->refcounted_frames = 1; |
414 | 402 |
| 403 if (config_.codec() == kCodecOpus) |
| 404 codec_context_->request_sample_fmt = AV_SAMPLE_FMT_FLT; |
| 405 |
415 AVCodec* codec = avcodec_find_decoder(codec_context_->codec_id); | 406 AVCodec* codec = avcodec_find_decoder(codec_context_->codec_id); |
416 if (!codec || avcodec_open2(codec_context_.get(), codec, NULL) < 0) { | 407 if (!codec || avcodec_open2(codec_context_.get(), codec, NULL) < 0) { |
417 DLOG(ERROR) << "Could not initialize audio decoder: " | 408 DLOG(ERROR) << "Could not initialize audio decoder: " |
418 << codec_context_->codec_id; | 409 << codec_context_->codec_id; |
419 ReleaseFFmpegResources(); | 410 ReleaseFFmpegResources(); |
420 state_ = kUninitialized; | 411 state_ = kUninitialized; |
421 return false; | 412 return false; |
422 } | 413 } |
423 | 414 |
424 // Success! | 415 // Success! |
425 av_frame_.reset(av_frame_alloc()); | 416 av_frame_.reset(av_frame_alloc()); |
426 av_sample_format_ = codec_context_->sample_fmt; | 417 av_sample_format_ = codec_context_->sample_fmt; |
427 | 418 |
428 if (codec_context_->channels != | 419 if (codec_context_->channels != |
429 ChannelLayoutToChannelCount(config_.channel_layout())) { | 420 ChannelLayoutToChannelCount(config_.channel_layout())) { |
430 DLOG(ERROR) << "Audio configuration specified " | 421 DLOG(ERROR) << "Audio configuration specified " |
431 << ChannelLayoutToChannelCount(config_.channel_layout()) | 422 << ChannelLayoutToChannelCount(config_.channel_layout()) |
432 << " channels, but FFmpeg thinks the file contains " | 423 << " channels, but FFmpeg thinks the file contains " |
433 << codec_context_->channels << " channels"; | 424 << codec_context_->channels << " channels"; |
434 ReleaseFFmpegResources(); | 425 ReleaseFFmpegResources(); |
435 state_ = kUninitialized; | 426 state_ = kUninitialized; |
436 return false; | 427 return false; |
437 } | 428 } |
438 | 429 |
439 ResetTimestampState(); | 430 ResetTimestampState(); |
440 return true; | 431 return true; |
441 } | 432 } |
442 | 433 |
443 void FFmpegAudioDecoder::ResetTimestampState() { | 434 void FFmpegAudioDecoder::ResetTimestampState() { |
444 discard_helper_.reset(new AudioDiscardHelper(config_.samples_per_second(), | 435 // Opus codec delay is handled by ffmpeg. |
445 config_.codec_delay())); | 436 const int codec_delay = |
446 discard_helper_->Reset(config_.codec_delay()); | 437 config_.codec() == kCodecOpus ? 0 : config_.codec_delay(); |
| 438 discard_helper_.reset( |
| 439 new AudioDiscardHelper(config_.samples_per_second(), codec_delay, |
| 440 config_.codec() == kCodecVorbis)); |
| 441 discard_helper_->Reset(codec_delay); |
447 } | 442 } |
448 | 443 |
449 } // namespace media | 444 } // namespace media |
OLD | NEW |