Always use 48kHz for OPUS decoding.

Per the specification OPUS should always use 48kHz for decoding.

BUG=392827
TEST=new unittests

Review URL: https://codereview.chromium.org/390543002

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@282989 0039d316-1c4b-4281-b951-d872f2087c98
parent 2b2d95c0
......@@ -285,11 +285,19 @@ void AVCodecContextToAudioDecoderConfig(
ChannelLayout channel_layout = ChannelLayoutToChromeChannelLayout(
codec_context->channel_layout, codec_context->channels);
int sample_rate = codec_context->sample_rate;
if (codec == kCodecOpus) {
// |codec_context->sample_fmt| is not set by FFmpeg because Opus decoding is
// not enabled in FFmpeg. It doesn't matter what value is set here, so long
// as it's valid, the true sample format is selected inside the decoder.
sample_format = kSampleFormatF32;
// Always use 48kHz for OPUS. Technically we should match to the highest
// supported hardware sample rate among [8, 12, 16, 24, 48] kHz, but we
// don't know the hardware sample rate at this point and those rates are
// rarely used for output. See the "Input Sample Rate" section of the spec:
// http://tools.ietf.org/html/draft-terriberry-oggopus-01#page-11
sample_rate = 48000;
}
base::TimeDelta seek_preroll;
......@@ -301,7 +309,7 @@ void AVCodecContextToAudioDecoderConfig(
config->Initialize(codec,
sample_format,
channel_layout,
codec_context->sample_rate,
sample_rate,
codec_context->extradata,
codec_context->extradata_size,
is_encrypted,
......
......@@ -2,64 +2,37 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "base/files/file_path.h"
#include "base/logging.h"
#include "base/path_service.h"
#include "media/base/media.h"
#include "media/ffmpeg/ffmpeg_common.h"
#include "media/filters/ffmpeg_glue.h"
#include "testing/gtest/include/gtest/gtest.h"
using base::TimeDelta;
namespace media {
static AVIndexEntry kIndexEntries[] = {
// pos, timestamp, flags, size, min_distance
{ 0, 0, AVINDEX_KEYFRAME, 0, 0 },
{ 2000, 1000, AVINDEX_KEYFRAME, 0, 0 },
{ 3000, 2000, 0, 0, 0 },
{ 5000, 3000, AVINDEX_KEYFRAME, 0, 0 },
{ 6000, 4000, 0, 0, 0 },
{ 8000, 5000, AVINDEX_KEYFRAME, 0, 0 },
{ 9000, 6000, AVINDEX_KEYFRAME, 0, 0 },
{ 11500, 7000, AVINDEX_KEYFRAME, 0, 0 },
};
static const AVRational kTimeBase = { 1, 1000 };
class FFmpegCommonTest : public testing::Test {
public:
FFmpegCommonTest();
virtual ~FFmpegCommonTest();
protected:
AVStream stream_;
DISALLOW_COPY_AND_ASSIGN(FFmpegCommonTest);
FFmpegCommonTest() { FFmpegGlue::InitializeFFmpeg(); }
virtual ~FFmpegCommonTest() {};
};
static bool InitFFmpeg() {
static bool initialized = false;
if (initialized) {
return true;
}
base::FilePath path;
PathService::Get(base::DIR_MODULE, &path);
return media::InitializeMediaLibrary(path);
}
TEST_F(FFmpegCommonTest, OpusAudioDecoderConfig) {
AVCodecContext context = {0};
context.codec_type = AVMEDIA_TYPE_AUDIO;
context.codec_id = AV_CODEC_ID_OPUS;
context.channel_layout = CHANNEL_LAYOUT_STEREO;
context.channels = 2;
context.sample_fmt = AV_SAMPLE_FMT_FLT;
FFmpegCommonTest::FFmpegCommonTest() {
CHECK(InitFFmpeg());
stream_.time_base = kTimeBase;
stream_.index_entries = kIndexEntries;
stream_.index_entries_allocated_size = sizeof(kIndexEntries);
stream_.nb_index_entries = arraysize(kIndexEntries);
}
// During conversion this sample rate should be changed to 48kHz.
context.sample_rate = 44100;
FFmpegCommonTest::~FFmpegCommonTest() {}
AudioDecoderConfig decoder_config;
AVCodecContextToAudioDecoderConfig(&context, false, &decoder_config, false);
EXPECT_EQ(48000, decoder_config.samples_per_second());
}
TEST_F(FFmpegCommonTest, TimeBaseConversions) {
int64 test_data[][5] = {
const int64 test_data[][5] = {
{1, 2, 1, 500000, 1 },
{1, 3, 1, 333333, 1 },
{1, 3, 2, 666667, 2 },
......@@ -72,7 +45,8 @@ TEST_F(FFmpegCommonTest, TimeBaseConversions) {
time_base.num = static_cast<int>(test_data[i][0]);
time_base.den = static_cast<int>(test_data[i][1]);
TimeDelta time_delta = ConvertFromTimeBase(time_base, test_data[i][2]);
base::TimeDelta time_delta =
ConvertFromTimeBase(time_base, test_data[i][2]);
EXPECT_EQ(time_delta.InMicroseconds(), test_data[i][3]);
EXPECT_EQ(ConvertToTimeBase(time_base, time_delta), test_data[i][4]);
......@@ -150,5 +124,4 @@ TEST_F(FFmpegCommonTest, UTCDateToTime_Invalid) {
}
}
} // namespace media
......@@ -1513,4 +1513,32 @@ TEST_F(PipelineIntegrationTest, BasicPlayback_OddVideoSize) {
ASSERT_TRUE(WaitUntilOnEnded());
}
// Verify that OPUS audio in a webm which reports a 44.1kHz sample rate plays
// correctly at 48kHz
TEST_F(PipelineIntegrationTest, BasicPlayback_Opus441kHz) {
ASSERT_TRUE(Start(GetTestDataFilePath("sfx-opus-441.webm"), PIPELINE_OK));
Play();
ASSERT_TRUE(WaitUntilOnEnded());
EXPECT_EQ(48000,
demuxer_->GetStream(DemuxerStream::AUDIO)
->audio_decoder_config()
.samples_per_second());
}
// Same as above but using MediaSource.
TEST_F(PipelineIntegrationTest, BasicPlayback_MediaSource_Opus441kHz) {
MockMediaSource source(
"sfx-opus-441.webm", kOpusAudioOnlyWebM, kAppendWholeFile);
StartPipelineWithMediaSource(&source);
source.EndOfStream();
Play();
ASSERT_TRUE(WaitUntilOnEnded());
source.Abort();
Stop();
EXPECT_EQ(48000,
demuxer_->GetStream(DemuxerStream::AUDIO)
->audio_decoder_config()
.samples_per_second());
}
} // namespace media
......@@ -58,6 +58,11 @@ bool WebMAudioClient::InitializeConfig(
if (output_samples_per_second_ > 0)
samples_per_second = output_samples_per_second_;
// Always use 48kHz for OPUS. See the "Input Sample Rate" section of the
// spec: http://tools.ietf.org/html/draft-terriberry-oggopus-01#page-11
if (audio_codec == kCodecOpus)
samples_per_second = 48000;
const uint8* extra_data = NULL;
size_t extra_data_size = 0;
if (codec_private.size() > 0) {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment