Chromium Code Reviews| OLD | NEW |
|---|---|
| (Empty) | |
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | |
| 2 // Use of this source code is governed by a BSD-style license that can be | |
| 3 // found in the LICENSE file. | |
| 4 | |
| 5 #include "base/memory/scoped_ptr.h" | |
| 6 #include "media/base/audio_buffer.h" | |
| 7 #include "media/base/audio_discard_helper.h" | |
| 8 #include "media/base/buffers.h" | |
| 9 #include "media/base/decoder_buffer.h" | |
| 10 #include "media/base/test_helpers.h" | |
| 11 #include "testing/gtest/include/gtest/gtest.h" | |
| 12 | |
| 13 namespace media { | |
| 14 | |
| 15 static const int kSampleRate = 48000; | |
| 16 | |
| 17 static scoped_refptr<DecoderBuffer> CreateEncodedBuffer( | |
| 18 base::TimeDelta timestamp, | |
| 19 base::TimeDelta duration) { | |
| 20 scoped_refptr<DecoderBuffer> result(new DecoderBuffer(1)); | |
| 21 result->set_timestamp(timestamp); | |
| 22 result->set_duration(duration); | |
| 23 return result; | |
| 24 } | |
| 25 | |
| 26 static scoped_refptr<AudioBuffer> CreateDecodedBuffer(int frames) { | |
| 27 return MakeAudioBuffer(kSampleFormatPlanarF32, | |
| 28 CHANNEL_LAYOUT_MONO, | |
| 29 1, | |
| 30 kSampleRate, | |
| 31 0.0f, | |
| 32 0.01f, | |
| 33 frames, | |
| 34 kNoTimestamp(), | |
| 35 kNoTimestamp()); | |
| 36 } | |
| 37 | |
| 38 TEST(AudioDiscardHelperTest, TimeDeltaToFrames) { | |
| 39 AudioDiscardHelper discard_helper(kSampleRate); | |
| 40 | |
| 41 EXPECT_EQ(0, discard_helper.TimeDeltaToFrames(base::TimeDelta())); | |
| 42 EXPECT_EQ( | |
| 43 kSampleRate / 100, | |
| 44 discard_helper.TimeDeltaToFrames(base::TimeDelta::FromMilliseconds(10))); | |
| 45 | |
| 46 // Ensure partial frames are always rounded up. The equation below calculates | |
| 47 // a frame count with a fractional part < 0.5. | |
| 48 const int small_remainder = | |
| 49 base::Time::kMicrosecondsPerSecond * (kSampleRate - 0.9) / kSampleRate; | |
| 50 EXPECT_EQ(kSampleRate, | |
| 51 discard_helper.TimeDeltaToFrames( | |
| 52 base::TimeDelta::FromMicroseconds(small_remainder))); | |
| 53 } | |
| 54 | |
| 55 TEST(AudioDiscardHelperTest, BasicProcessBuffers) { | |
| 56 AudioDiscardHelper discard_helper(kSampleRate); | |
| 57 ASSERT_FALSE(discard_helper.initialized()); | |
| 58 | |
| 59 const base::TimeDelta kTimestamp = base::TimeDelta(); | |
| 60 | |
| 61 // Use an estimated duration which doesn't match the number of decoded frames | |
| 62 // to ensure the helper is correctly setting durations based on output frames. | |
| 63 const base::TimeDelta kEstimatedDuration = | |
| 64 base::TimeDelta::FromMilliseconds(9); | |
| 65 const base::TimeDelta kActualDuration = base::TimeDelta::FromMilliseconds(10); | |
| 66 const int kTestFrames = discard_helper.TimeDeltaToFrames(kActualDuration); | |
| 67 | |
| 68 scoped_refptr<DecoderBuffer> encoded_buffer = | |
| 69 CreateEncodedBuffer(kTimestamp, kEstimatedDuration); | |
| 70 scoped_refptr<AudioBuffer> decoded_buffer = CreateDecodedBuffer(kTestFrames); | |
| 71 | |
| 72 // Verify the basic case where nothing is discarded. | |
| 73 ASSERT_TRUE(discard_helper.ProcessBuffers(encoded_buffer, decoded_buffer)); | |
| 74 ASSERT_TRUE(discard_helper.initialized()); | |
| 75 EXPECT_EQ(kTimestamp, decoded_buffer->timestamp()); | |
| 76 EXPECT_EQ(kActualDuration, decoded_buffer->duration()); | |
| 77 EXPECT_EQ(kTestFrames, decoded_buffer->frame_count()); | |
| 78 | |
| 79 // Verify a Reset() takes us back to an uninitialized state. | |
| 80 discard_helper.Reset(0); | |
| 81 ASSERT_FALSE(discard_helper.initialized()); | |
| 82 | |
| 83 // Verify a NULL output buffer returns false. | |
| 84 ASSERT_FALSE(discard_helper.ProcessBuffers(encoded_buffer, NULL)); | |
| 85 } | |
| 86 | |
| 87 TEST(AudioDiscardHelperTest, ProcessBuffersWithInitialDiscard) { | |
| 88 AudioDiscardHelper discard_helper(kSampleRate); | |
| 89 ASSERT_FALSE(discard_helper.initialized()); | |
| 90 | |
| 91 const base::TimeDelta kTimestamp = base::TimeDelta(); | |
| 92 const base::TimeDelta kDuration = base::TimeDelta::FromMilliseconds(10); | |
| 93 const int kTestFrames = discard_helper.TimeDeltaToFrames(kDuration); | |
| 94 | |
| 95 // Tell the helper we want to discard half of the initial frames. | |
| 96 discard_helper.Reset(kTestFrames / 2); | |
| 97 | |
| 98 scoped_refptr<DecoderBuffer> encoded_buffer = | |
| 99 CreateEncodedBuffer(kTimestamp, kDuration); | |
| 100 scoped_refptr<AudioBuffer> decoded_buffer = CreateDecodedBuffer(kTestFrames); | |
| 101 | |
| 102 // Verify half the frames end up discarded. | |
| 103 ASSERT_TRUE(discard_helper.ProcessBuffers(encoded_buffer, decoded_buffer)); | |
| 104 ASSERT_TRUE(discard_helper.initialized()); | |
| 105 EXPECT_EQ(kTimestamp, decoded_buffer->timestamp()); | |
| 106 EXPECT_EQ(kDuration / 2, decoded_buffer->duration()); | |
| 107 EXPECT_EQ(kTestFrames / 2, decoded_buffer->frame_count()); | |
| 108 } | |
| 109 | |
| 110 TEST(AudioDiscardHelperTest, ProcessBuffersWithLargeInitialDiscard) { | |
| 111 AudioDiscardHelper discard_helper(kSampleRate); | |
| 112 ASSERT_FALSE(discard_helper.initialized()); | |
| 113 | |
| 114 const base::TimeDelta kTimestamp = base::TimeDelta(); | |
| 115 const base::TimeDelta kDuration = base::TimeDelta::FromMilliseconds(10); | |
| 116 const int kTestFrames = discard_helper.TimeDeltaToFrames(kDuration); | |
| 117 | |
| 118 // Tell the helper we want to discard 1.5 buffers worth of frames. | |
| 119 discard_helper.Reset(kTestFrames * 1.5); | |
| 120 | |
| 121 scoped_refptr<DecoderBuffer> encoded_buffer = | |
| 122 CreateEncodedBuffer(kTimestamp, kDuration); | |
| 123 scoped_refptr<AudioBuffer> decoded_buffer = CreateDecodedBuffer(kTestFrames); | |
| 124 | |
| 125 // The first call should fail since no output buffer remains. | |
| 126 ASSERT_FALSE(discard_helper.ProcessBuffers(encoded_buffer, decoded_buffer)); | |
| 127 ASSERT_TRUE(discard_helper.initialized()); | |
| 128 | |
| 129 // Generate another set of buffers and expect half the output frames. | |
| 130 encoded_buffer = CreateEncodedBuffer(kTimestamp + kDuration, kDuration); | |
| 131 decoded_buffer = CreateDecodedBuffer(kTestFrames); | |
| 132 ASSERT_TRUE(discard_helper.ProcessBuffers(encoded_buffer, decoded_buffer)); | |
| 133 | |
| 134 // The timestamp should match that of the initial buffer. | |
| 135 EXPECT_EQ(kTimestamp, decoded_buffer->timestamp()); | |
| 136 EXPECT_EQ(kDuration / 2, decoded_buffer->duration()); | |
| 137 EXPECT_EQ(kTestFrames / 2, decoded_buffer->frame_count()); | |
| 138 } | |
| 139 | |
| 140 TEST(AudioDiscardHelperTest, AllowNonMonotonicTimestamps) { | |
| 141 AudioDiscardHelper discard_helper(kSampleRate); | |
| 142 ASSERT_FALSE(discard_helper.initialized()); | |
| 143 | |
| 144 const base::TimeDelta kTimestamp = base::TimeDelta(); | |
| 145 const base::TimeDelta kDuration = base::TimeDelta::FromMilliseconds(10); | |
| 146 const int kTestFrames = discard_helper.TimeDeltaToFrames(kDuration); | |
| 147 | |
| 148 scoped_refptr<DecoderBuffer> encoded_buffer = | |
| 149 CreateEncodedBuffer(kTimestamp, kDuration); | |
| 150 scoped_refptr<AudioBuffer> decoded_buffer = CreateDecodedBuffer(kTestFrames); | |
| 151 | |
| 152 ASSERT_TRUE(discard_helper.ProcessBuffers(encoded_buffer, decoded_buffer)); | |
| 153 ASSERT_TRUE(discard_helper.initialized()); | |
| 154 EXPECT_EQ(kTimestamp, decoded_buffer->timestamp()); | |
| 155 EXPECT_EQ(kDuration, decoded_buffer->duration()); | |
| 156 EXPECT_EQ(kTestFrames, decoded_buffer->frame_count()); | |
| 157 | |
| 158 // Process the same input buffer again to ensure input timestamps which go | |
|
wolenetz
2014/04/28 21:52:07
nit: timestamp really isn't going backwards in tim
DaleCurtis
2014/04/28 23:09:03
kTimestamp on buffer 2 is now behind kTimestamp+kD
| |
| 159 // backwards in time are not errors. | |
| 160 ASSERT_TRUE(discard_helper.ProcessBuffers(encoded_buffer, decoded_buffer)); | |
| 161 EXPECT_EQ(kTimestamp + kDuration, decoded_buffer->timestamp()); | |
| 162 EXPECT_EQ(kDuration, decoded_buffer->duration()); | |
| 163 EXPECT_EQ(kTestFrames, decoded_buffer->frame_count()); | |
| 164 } | |
| 165 | |
| 166 TEST(AudioDiscardHelperTest, DiscardPadding) { | |
|
wolenetz
2014/04/28 21:52:07
Versus ProcessBuffersWithInitialDiscard and Initia
DaleCurtis
2014/04/28 23:09:03
Done. Doing so required improving the accuracy of
| |
| 167 AudioDiscardHelper discard_helper(kSampleRate); | |
| 168 ASSERT_FALSE(discard_helper.initialized()); | |
| 169 | |
| 170 const base::TimeDelta kTimestamp = base::TimeDelta(); | |
| 171 const base::TimeDelta kDuration = base::TimeDelta::FromMilliseconds(10); | |
| 172 const int kTestFrames = discard_helper.TimeDeltaToFrames(kDuration); | |
| 173 | |
| 174 scoped_refptr<DecoderBuffer> encoded_buffer = | |
| 175 CreateEncodedBuffer(kTimestamp, kDuration); | |
| 176 scoped_refptr<AudioBuffer> decoded_buffer = CreateDecodedBuffer(kTestFrames); | |
| 177 | |
| 178 // Set a discard padding equivalent to half the buffer. | |
| 179 encoded_buffer->set_discard_padding(kDuration / 2); | |
| 180 | |
| 181 ASSERT_TRUE(discard_helper.ProcessBuffers(encoded_buffer, decoded_buffer)); | |
| 182 ASSERT_TRUE(discard_helper.initialized()); | |
| 183 EXPECT_EQ(kTimestamp, decoded_buffer->timestamp()); | |
| 184 EXPECT_EQ(kDuration / 2, decoded_buffer->duration()); | |
| 185 EXPECT_EQ(kTestFrames / 2, decoded_buffer->frame_count()); | |
| 186 } | |
| 187 | |
| 188 TEST(AudioDiscardHelperTest, InitialDiscardAndDiscardPadding) { | |
| 189 AudioDiscardHelper discard_helper(kSampleRate); | |
| 190 ASSERT_FALSE(discard_helper.initialized()); | |
| 191 | |
| 192 const base::TimeDelta kTimestamp = base::TimeDelta(); | |
| 193 const base::TimeDelta kDuration = base::TimeDelta::FromMilliseconds(10); | |
| 194 const int kTestFrames = discard_helper.TimeDeltaToFrames(kDuration); | |
| 195 | |
| 196 scoped_refptr<DecoderBuffer> encoded_buffer = | |
| 197 CreateEncodedBuffer(kTimestamp, kDuration); | |
| 198 scoped_refptr<AudioBuffer> decoded_buffer = CreateDecodedBuffer(kTestFrames); | |
| 199 | |
| 200 // Set a discard padding equivalent to a quarter of the buffer. | |
| 201 encoded_buffer->set_discard_padding(kDuration / 4); | |
| 202 | |
| 203 // Set an initial discard of a quarter of the buffer. | |
| 204 discard_helper.Reset(kTestFrames / 4); | |
| 205 | |
| 206 ASSERT_TRUE(discard_helper.ProcessBuffers(encoded_buffer, decoded_buffer)); | |
| 207 ASSERT_TRUE(discard_helper.initialized()); | |
| 208 EXPECT_EQ(kTimestamp, decoded_buffer->timestamp()); | |
| 209 EXPECT_EQ(kDuration / 2, decoded_buffer->duration()); | |
| 210 EXPECT_EQ(kTestFrames / 2, decoded_buffer->frame_count()); | |
| 211 } | |
| 212 | |
|
wolenetz
2014/04/28 21:52:07
nit: remove extra line.
DaleCurtis
2014/04/28 23:09:03
Done.
| |
| 213 | |
| 214 } // namespace media | |
| OLD | NEW |