| 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 |