summaryrefslogtreecommitdiffstats
path: root/media/base/audio_buffer_unittest.cc
diff options
context:
space:
mode:
authordalecurtis@chromium.org <dalecurtis@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-05-03 02:08:23 +0000
committerdalecurtis@chromium.org <dalecurtis@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-05-03 02:08:23 +0000
commita6c2d93ff440b7693f35f7fc576f5818c638e6da (patch)
tree470f103d972769bfb9d4382019ae841a77e0b247 /media/base/audio_buffer_unittest.cc
parentec37323959db7c1d7b388dc08b1d318ddb46ec06 (diff)
downloadchromium_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.cc119
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