Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1379)

Unified Diff: media/base/audio_discard_helper_unittest.cc

Issue 259453003: Introduce AudioDiscardHelper. Refactor audio decoders to use it. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Simplify! Created 6 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: media/base/audio_discard_helper_unittest.cc
diff --git a/media/base/audio_discard_helper_unittest.cc b/media/base/audio_discard_helper_unittest.cc
new file mode 100644
index 0000000000000000000000000000000000000000..1a6b592120da4b8425361e606a89b28cb334c1b9
--- /dev/null
+++ b/media/base/audio_discard_helper_unittest.cc
@@ -0,0 +1,214 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/memory/scoped_ptr.h"
+#include "media/base/audio_buffer.h"
+#include "media/base/audio_discard_helper.h"
+#include "media/base/buffers.h"
+#include "media/base/decoder_buffer.h"
+#include "media/base/test_helpers.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace media {
+
+static const int kSampleRate = 48000;
+
+static scoped_refptr<DecoderBuffer> CreateEncodedBuffer(
+ base::TimeDelta timestamp,
+ base::TimeDelta duration) {
+ scoped_refptr<DecoderBuffer> result(new DecoderBuffer(1));
+ result->set_timestamp(timestamp);
+ result->set_duration(duration);
+ return result;
+}
+
+static scoped_refptr<AudioBuffer> CreateDecodedBuffer(int frames) {
+ return MakeAudioBuffer(kSampleFormatPlanarF32,
+ CHANNEL_LAYOUT_MONO,
+ 1,
+ kSampleRate,
+ 0.0f,
+ 0.01f,
+ frames,
+ kNoTimestamp(),
+ kNoTimestamp());
+}
+
+TEST(AudioDiscardHelperTest, TimeDeltaToFrames) {
+ AudioDiscardHelper discard_helper(kSampleRate);
+
+ EXPECT_EQ(0, discard_helper.TimeDeltaToFrames(base::TimeDelta()));
+ EXPECT_EQ(
+ kSampleRate / 100,
+ discard_helper.TimeDeltaToFrames(base::TimeDelta::FromMilliseconds(10)));
+
+ // Ensure partial frames are always rounded up. The equation below calculates
+ // a frame count with a fractional part < 0.5.
+ const int small_remainder =
+ base::Time::kMicrosecondsPerSecond * (kSampleRate - 0.9) / kSampleRate;
+ EXPECT_EQ(kSampleRate,
+ discard_helper.TimeDeltaToFrames(
+ base::TimeDelta::FromMicroseconds(small_remainder)));
+}
+
+TEST(AudioDiscardHelperTest, BasicProcessBuffers) {
+ AudioDiscardHelper discard_helper(kSampleRate);
+ ASSERT_FALSE(discard_helper.initialized());
+
+ const base::TimeDelta kTimestamp = base::TimeDelta();
+
+ // Use an estimated duration which doesn't match the number of decoded frames
+ // to ensure the helper is correctly setting durations based on output frames.
+ const base::TimeDelta kEstimatedDuration =
+ base::TimeDelta::FromMilliseconds(9);
+ const base::TimeDelta kActualDuration = base::TimeDelta::FromMilliseconds(10);
+ const int kTestFrames = discard_helper.TimeDeltaToFrames(kActualDuration);
+
+ scoped_refptr<DecoderBuffer> encoded_buffer =
+ CreateEncodedBuffer(kTimestamp, kEstimatedDuration);
+ scoped_refptr<AudioBuffer> decoded_buffer = CreateDecodedBuffer(kTestFrames);
+
+ // Verify the basic case where nothing is discarded.
+ ASSERT_TRUE(discard_helper.ProcessBuffers(encoded_buffer, decoded_buffer));
+ ASSERT_TRUE(discard_helper.initialized());
+ EXPECT_EQ(kTimestamp, decoded_buffer->timestamp());
+ EXPECT_EQ(kActualDuration, decoded_buffer->duration());
+ EXPECT_EQ(kTestFrames, decoded_buffer->frame_count());
+
+ // Verify a Reset() takes us back to an uninitialized state.
+ discard_helper.Reset(0);
+ ASSERT_FALSE(discard_helper.initialized());
+
+ // Verify a NULL output buffer returns false.
+ ASSERT_FALSE(discard_helper.ProcessBuffers(encoded_buffer, NULL));
+}
+
+TEST(AudioDiscardHelperTest, ProcessBuffersWithInitialDiscard) {
+ AudioDiscardHelper discard_helper(kSampleRate);
+ ASSERT_FALSE(discard_helper.initialized());
+
+ const base::TimeDelta kTimestamp = base::TimeDelta();
+ const base::TimeDelta kDuration = base::TimeDelta::FromMilliseconds(10);
+ const int kTestFrames = discard_helper.TimeDeltaToFrames(kDuration);
+
+ // Tell the helper we want to discard half of the initial frames.
+ discard_helper.Reset(kTestFrames / 2);
+
+ scoped_refptr<DecoderBuffer> encoded_buffer =
+ CreateEncodedBuffer(kTimestamp, kDuration);
+ scoped_refptr<AudioBuffer> decoded_buffer = CreateDecodedBuffer(kTestFrames);
+
+ // Verify half the frames end up discarded.
+ ASSERT_TRUE(discard_helper.ProcessBuffers(encoded_buffer, decoded_buffer));
+ ASSERT_TRUE(discard_helper.initialized());
+ EXPECT_EQ(kTimestamp, decoded_buffer->timestamp());
+ EXPECT_EQ(kDuration / 2, decoded_buffer->duration());
+ EXPECT_EQ(kTestFrames / 2, decoded_buffer->frame_count());
+}
+
+TEST(AudioDiscardHelperTest, ProcessBuffersWithLargeInitialDiscard) {
+ AudioDiscardHelper discard_helper(kSampleRate);
+ ASSERT_FALSE(discard_helper.initialized());
+
+ const base::TimeDelta kTimestamp = base::TimeDelta();
+ const base::TimeDelta kDuration = base::TimeDelta::FromMilliseconds(10);
+ const int kTestFrames = discard_helper.TimeDeltaToFrames(kDuration);
+
+ // Tell the helper we want to discard 1.5 buffers worth of frames.
+ discard_helper.Reset(kTestFrames * 1.5);
+
+ scoped_refptr<DecoderBuffer> encoded_buffer =
+ CreateEncodedBuffer(kTimestamp, kDuration);
+ scoped_refptr<AudioBuffer> decoded_buffer = CreateDecodedBuffer(kTestFrames);
+
+ // The first call should fail since no output buffer remains.
+ ASSERT_FALSE(discard_helper.ProcessBuffers(encoded_buffer, decoded_buffer));
+ ASSERT_TRUE(discard_helper.initialized());
+
+ // Generate another set of buffers and expect half the output frames.
+ encoded_buffer = CreateEncodedBuffer(kTimestamp + kDuration, kDuration);
+ decoded_buffer = CreateDecodedBuffer(kTestFrames);
+ ASSERT_TRUE(discard_helper.ProcessBuffers(encoded_buffer, decoded_buffer));
+
+ // The timestamp should match that of the initial buffer.
+ EXPECT_EQ(kTimestamp, decoded_buffer->timestamp());
+ EXPECT_EQ(kDuration / 2, decoded_buffer->duration());
+ EXPECT_EQ(kTestFrames / 2, decoded_buffer->frame_count());
+}
+
+TEST(AudioDiscardHelperTest, AllowNonMonotonicTimestamps) {
+ AudioDiscardHelper discard_helper(kSampleRate);
+ ASSERT_FALSE(discard_helper.initialized());
+
+ const base::TimeDelta kTimestamp = base::TimeDelta();
+ const base::TimeDelta kDuration = base::TimeDelta::FromMilliseconds(10);
+ const int kTestFrames = discard_helper.TimeDeltaToFrames(kDuration);
+
+ scoped_refptr<DecoderBuffer> encoded_buffer =
+ CreateEncodedBuffer(kTimestamp, kDuration);
+ scoped_refptr<AudioBuffer> decoded_buffer = CreateDecodedBuffer(kTestFrames);
+
+ ASSERT_TRUE(discard_helper.ProcessBuffers(encoded_buffer, decoded_buffer));
+ ASSERT_TRUE(discard_helper.initialized());
+ EXPECT_EQ(kTimestamp, decoded_buffer->timestamp());
+ EXPECT_EQ(kDuration, decoded_buffer->duration());
+ EXPECT_EQ(kTestFrames, decoded_buffer->frame_count());
+
+ // 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
+ // backwards in time are not errors.
+ ASSERT_TRUE(discard_helper.ProcessBuffers(encoded_buffer, decoded_buffer));
+ EXPECT_EQ(kTimestamp + kDuration, decoded_buffer->timestamp());
+ EXPECT_EQ(kDuration, decoded_buffer->duration());
+ EXPECT_EQ(kTestFrames, decoded_buffer->frame_count());
+}
+
+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
+ AudioDiscardHelper discard_helper(kSampleRate);
+ ASSERT_FALSE(discard_helper.initialized());
+
+ const base::TimeDelta kTimestamp = base::TimeDelta();
+ const base::TimeDelta kDuration = base::TimeDelta::FromMilliseconds(10);
+ const int kTestFrames = discard_helper.TimeDeltaToFrames(kDuration);
+
+ scoped_refptr<DecoderBuffer> encoded_buffer =
+ CreateEncodedBuffer(kTimestamp, kDuration);
+ scoped_refptr<AudioBuffer> decoded_buffer = CreateDecodedBuffer(kTestFrames);
+
+ // Set a discard padding equivalent to half the buffer.
+ encoded_buffer->set_discard_padding(kDuration / 2);
+
+ ASSERT_TRUE(discard_helper.ProcessBuffers(encoded_buffer, decoded_buffer));
+ ASSERT_TRUE(discard_helper.initialized());
+ EXPECT_EQ(kTimestamp, decoded_buffer->timestamp());
+ EXPECT_EQ(kDuration / 2, decoded_buffer->duration());
+ EXPECT_EQ(kTestFrames / 2, decoded_buffer->frame_count());
+}
+
+TEST(AudioDiscardHelperTest, InitialDiscardAndDiscardPadding) {
+ AudioDiscardHelper discard_helper(kSampleRate);
+ ASSERT_FALSE(discard_helper.initialized());
+
+ const base::TimeDelta kTimestamp = base::TimeDelta();
+ const base::TimeDelta kDuration = base::TimeDelta::FromMilliseconds(10);
+ const int kTestFrames = discard_helper.TimeDeltaToFrames(kDuration);
+
+ scoped_refptr<DecoderBuffer> encoded_buffer =
+ CreateEncodedBuffer(kTimestamp, kDuration);
+ scoped_refptr<AudioBuffer> decoded_buffer = CreateDecodedBuffer(kTestFrames);
+
+ // Set a discard padding equivalent to a quarter of the buffer.
+ encoded_buffer->set_discard_padding(kDuration / 4);
+
+ // Set an initial discard of a quarter of the buffer.
+ discard_helper.Reset(kTestFrames / 4);
+
+ ASSERT_TRUE(discard_helper.ProcessBuffers(encoded_buffer, decoded_buffer));
+ ASSERT_TRUE(discard_helper.initialized());
+ EXPECT_EQ(kTimestamp, decoded_buffer->timestamp());
+ EXPECT_EQ(kDuration / 2, decoded_buffer->duration());
+ EXPECT_EQ(kTestFrames / 2, decoded_buffer->frame_count());
+}
+
wolenetz 2014/04/28 21:52:07 nit: remove extra line.
DaleCurtis 2014/04/28 23:09:03 Done.
+
+} // namespace media

Powered by Google App Engine
This is Rietveld 408576698