diff options
author | dalecurtis@chromium.org <dalecurtis@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-05-03 02:08:23 +0000 |
---|---|---|
committer | dalecurtis@chromium.org <dalecurtis@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-05-03 02:08:23 +0000 |
commit | a6c2d93ff440b7693f35f7fc576f5818c638e6da (patch) | |
tree | 470f103d972769bfb9d4382019ae841a77e0b247 /media/base/audio_buffer_unittest.cc | |
parent | ec37323959db7c1d7b388dc08b1d318ddb46ec06 (diff) | |
download | chromium_src-a6c2d93ff440b7693f35f7fc576f5818c638e6da.zip chromium_src-a6c2d93ff440b7693f35f7fc576f5818c638e6da.tar.gz chromium_src-a6c2d93ff440b7693f35f7fc576f5818c638e6da.tar.bz2 |
Support start trimming post-decoding. Use it with FFmpegDemuxer.
FFmpeg has packet side data indicating how many frames should be
trimmed after decoding, we should use it to improve playback of
mp3 and aac audio via <audio> tag.
Specifically:
- AudioBuffer:TrimRange(start,end) is now supported.
- DecoderBuffer:discard_padding() is now a pair of (front, back)
which indicates how much to trim off the front and rear of the
data corresponding to the encoded buffer.
- AudioDiscardHelper has been updated to implement this trimming.
- FFmpegDemuxer inserts FFmpeg's skip_samples into DecoderBuffer.
This change paves the way for MediaSource to use this feature to
implement gapless playback support.
BUG=360961
TEST=new unittests!
NOTRY=true
Review URL: https://codereview.chromium.org/251893002
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@268002 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'media/base/audio_buffer_unittest.cc')
-rw-r--r-- | media/base/audio_buffer_unittest.cc | 119 |
1 files changed, 117 insertions, 2 deletions
diff --git a/media/base/audio_buffer_unittest.cc b/media/base/audio_buffer_unittest.cc index 55ff4ed..c0fbf6b 100644 --- a/media/base/audio_buffer_unittest.cc +++ b/media/base/audio_buffer_unittest.cc @@ -11,16 +11,123 @@ namespace media { static const int kSampleRate = 48000; -static void VerifyBus(AudioBus* bus, int frames, float start, float increment) { + +static void VerifyBusWithOffset(AudioBus* bus, + int offset, + int frames, + float start, + float increment) { for (int ch = 0; ch < bus->channels(); ++ch) { const float v = start + ch * bus->frames() * increment; - for (int i = 0; i < frames; ++i) { + for (int i = offset; i < frames; ++i) { ASSERT_FLOAT_EQ(v + i * increment, bus->channel(ch)[i]) << "i=" << i << ", ch=" << ch; } } } +static void VerifyBus(AudioBus* bus, int frames, float start, float increment) { + VerifyBusWithOffset(bus, 0, frames, start, increment); +} + +static void TrimRangeTest(SampleFormat sample_format) { + const ChannelLayout channel_layout = CHANNEL_LAYOUT_4_0; + const int channels = ChannelLayoutToChannelCount(channel_layout); + const int frames = kSampleRate / 10; + const base::TimeDelta timestamp = base::TimeDelta(); + const base::TimeDelta duration = base::TimeDelta::FromMilliseconds(100); + scoped_refptr<AudioBuffer> buffer = MakeAudioBuffer<float>(sample_format, + channel_layout, + channels, + kSampleRate, + 0, + 1, + frames, + timestamp); + EXPECT_EQ(frames, buffer->frame_count()); + EXPECT_EQ(timestamp, buffer->timestamp()); + EXPECT_EQ(duration, buffer->duration()); + + scoped_ptr<AudioBus> bus = AudioBus::Create(channels, frames); + + // Verify all frames before trimming. + buffer->ReadFrames(frames, 0, 0, bus.get()); + VerifyBus(bus.get(), frames, 0, 1); + + // Trim 10ms of frames from the middle of the buffer. + int trim_start = frames / 2; + const int trim_length = kSampleRate / 100; + const base::TimeDelta trim_duration = base::TimeDelta::FromMilliseconds(10); + buffer->TrimRange(trim_start, trim_start + trim_length); + EXPECT_EQ(frames - trim_length, buffer->frame_count()); + EXPECT_EQ(timestamp, buffer->timestamp()); + EXPECT_EQ(duration - trim_duration, buffer->duration()); + bus->Zero(); + buffer->ReadFrames(buffer->frame_count(), 0, 0, bus.get()); + VerifyBus(bus.get(), trim_start, 0, 1); + VerifyBusWithOffset( + bus.get(), trim_start, buffer->frame_count() - trim_start, 0, 1); + + // Trim 10ms of frames from the start, which just adjusts the buffer's + // internal start offset. + buffer->TrimStart(trim_length); + trim_start -= trim_length; + EXPECT_EQ(frames - 2 * trim_length, buffer->frame_count()); + EXPECT_EQ(timestamp + trim_duration, buffer->timestamp()); + EXPECT_EQ(duration - 2 * trim_duration, buffer->duration()); + bus->Zero(); + buffer->ReadFrames(buffer->frame_count(), 0, 0, bus.get()); + VerifyBus(bus.get(), trim_start, trim_length, 1); + VerifyBusWithOffset( + bus.get(), trim_start, buffer->frame_count() - trim_start, 0, 1); + + // Trim 10ms of frames from the end, which just adjusts the buffer's frame + // count. + buffer->TrimEnd(trim_length); + EXPECT_EQ(frames - 3 * trim_length, buffer->frame_count()); + EXPECT_EQ(timestamp + trim_duration, buffer->timestamp()); + EXPECT_EQ(duration - 3 * trim_duration, buffer->duration()); + bus->Zero(); + buffer->ReadFrames(buffer->frame_count(), 0, 0, bus.get()); + VerifyBus(bus.get(), trim_start, trim_length, 1); + VerifyBusWithOffset( + bus.get(), trim_start, buffer->frame_count() - trim_start, 0, 1); + + // Trim another 10ms from the inner portion of the buffer. + buffer->TrimRange(trim_start, trim_start + trim_length); + EXPECT_EQ(frames - 4 * trim_length, buffer->frame_count()); + EXPECT_EQ(timestamp + trim_duration, buffer->timestamp()); + EXPECT_EQ(duration - 4 * trim_duration, buffer->duration()); + bus->Zero(); + buffer->ReadFrames(buffer->frame_count(), 0, 0, bus.get()); + VerifyBus(bus.get(), trim_start, trim_length, 1); + VerifyBusWithOffset( + bus.get(), trim_start, buffer->frame_count() - trim_start, 0, 1); + + // Trim off the end using TrimRange() to ensure end index is exclusive. + buffer->TrimRange(buffer->frame_count() - trim_length, buffer->frame_count()); + EXPECT_EQ(frames - 5 * trim_length, buffer->frame_count()); + EXPECT_EQ(timestamp + trim_duration, buffer->timestamp()); + EXPECT_EQ(duration - 5 * trim_duration, buffer->duration()); + bus->Zero(); + buffer->ReadFrames(buffer->frame_count(), 0, 0, bus.get()); + VerifyBus(bus.get(), trim_start, trim_length, 1); + VerifyBusWithOffset( + bus.get(), trim_start, buffer->frame_count() - trim_start, 0, 1); + + // Trim off the start using TrimRange() to ensure start index is inclusive. + buffer->TrimRange(0, trim_length); + trim_start -= trim_length; + EXPECT_EQ(frames - 6 * trim_length, buffer->frame_count()); + EXPECT_EQ(timestamp + trim_duration, buffer->timestamp()); + EXPECT_EQ(duration - 6 * trim_duration, buffer->duration()); + bus->Zero(); + buffer->ReadFrames(buffer->frame_count(), 0, 0, bus.get()); + VerifyBus(bus.get(), trim_start, 2 * trim_length, 1); + VerifyBusWithOffset( + bus.get(), trim_start, buffer->frame_count() - trim_start, 0, 1); +} + TEST(AudioBufferTest, CopyFrom) { const ChannelLayout kChannelLayout = CHANNEL_LAYOUT_MONO; scoped_refptr<AudioBuffer> original_buffer = @@ -312,4 +419,12 @@ TEST(AudioBufferTest, Trim) { EXPECT_EQ(base::TimeDelta(), buffer->duration()); } +TEST(AudioBufferTest, TrimRangePlanar) { + TrimRangeTest(kSampleFormatPlanarF32); +} + +TEST(AudioBufferTest, TrimRangeInterleaved) { + TrimRangeTest(kSampleFormatF32); +} + } // namespace media |