| // Copyright (c) 2012 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/basictypes.h" |
| #include "cobalt/media/base/audio_timestamp_helper.h" |
| #include "cobalt/media/base/timestamp_constants.h" |
| #include "starboard/types.h" |
| #include "testing/gtest/include/gtest/gtest.h" |
| |
| namespace cobalt { |
| namespace media { |
| |
| namespace { |
| |
| const int k48kHz = 48000; |
| |
| } // namespace |
| |
| static const int kDefaultSampleRate = 44100; |
| |
| class AudioTimestampHelperTest : public ::testing::Test { |
| public: |
| AudioTimestampHelperTest() : helper_(kDefaultSampleRate) { |
| helper_.SetBaseTimestamp(base::TimeDelta()); |
| } |
| |
| // Adds frames to the helper and returns the current timestamp in |
| // microseconds. |
| int64_t AddFrames(int frames) { |
| helper_.AddFrames(frames); |
| return helper_.GetTimestamp().InMicroseconds(); |
| } |
| |
| int64_t FramesToTarget(int target_in_microseconds) { |
| return helper_.GetFramesToTarget( |
| base::TimeDelta::FromMicroseconds(target_in_microseconds)); |
| } |
| |
| void TestGetFramesToTargetRange(int frame_count, int start, int end) { |
| for (int i = start; i <= end; ++i) { |
| EXPECT_EQ(frame_count, FramesToTarget(i)) << " Failure for timestamp " |
| << i << " us."; |
| } |
| } |
| |
| protected: |
| AudioTimestampHelper helper_; |
| |
| private: |
| DISALLOW_COPY_AND_ASSIGN(AudioTimestampHelperTest); |
| }; |
| |
| TEST_F(AudioTimestampHelperTest, FramesToTime) { |
| // Negative value. |
| EXPECT_EQ(base::TimeDelta::FromSeconds(-1), |
| AudioTimestampHelper::FramesToTime(-48000, k48kHz)); |
| // Zero. |
| EXPECT_EQ(base::TimeDelta::FromMicroseconds(0), |
| AudioTimestampHelper::FramesToTime(0, k48kHz)); |
| // One frame. |
| EXPECT_EQ(base::TimeDelta::FromMicroseconds(20), |
| AudioTimestampHelper::FramesToTime(1, k48kHz)); |
| // Exact value with maximum precision of TimeDelta. |
| EXPECT_EQ(base::TimeDelta::FromMicroseconds(15625), |
| AudioTimestampHelper::FramesToTime(750, k48kHz)); |
| // One second. |
| EXPECT_EQ(base::TimeDelta::FromSeconds(1), |
| AudioTimestampHelper::FramesToTime(48000, k48kHz)); |
| // Argument and return value exceeding 32 bits. |
| EXPECT_EQ(base::TimeDelta::FromSeconds(1000000), |
| AudioTimestampHelper::FramesToTime(48000000000, k48kHz)); |
| } |
| |
| TEST_F(AudioTimestampHelperTest, TimeToFrames) { |
| // Negative value. |
| EXPECT_EQ(-48000, AudioTimestampHelper::TimeToFrames( |
| base::TimeDelta::FromSeconds(-1), k48kHz)); |
| // Zero. |
| EXPECT_EQ(0, AudioTimestampHelper::TimeToFrames( |
| base::TimeDelta::FromMicroseconds(0), k48kHz)); |
| // Any duration less than 21 microseconds will return zero frames at 48 kHz |
| // because each frame is 20.833 microseconds. |
| EXPECT_EQ(0, AudioTimestampHelper::TimeToFrames( |
| base::TimeDelta::FromMicroseconds(20), k48kHz)); |
| EXPECT_EQ(1, AudioTimestampHelper::TimeToFrames( |
| base::TimeDelta::FromMicroseconds(21), k48kHz)); |
| // Exact value with maximum precision of TimeDelta. |
| EXPECT_EQ(750, AudioTimestampHelper::TimeToFrames( |
| base::TimeDelta::FromMicroseconds(15625), k48kHz)); |
| // One second. |
| EXPECT_EQ(48000, AudioTimestampHelper::TimeToFrames( |
| base::TimeDelta::FromSeconds(1), k48kHz)); |
| // Argument and return value exceeding 32 bits. |
| EXPECT_EQ(48000000000, AudioTimestampHelper::TimeToFrames( |
| base::TimeDelta::FromSeconds(1000000), k48kHz)); |
| } |
| |
| TEST_F(AudioTimestampHelperTest, Basic) { |
| EXPECT_EQ(0, helper_.GetTimestamp().InMicroseconds()); |
| |
| // Verify that the output timestamp is always rounded down to the |
| // nearest microsecond. 1 frame @ 44100 is ~22.67573 microseconds, |
| // which is why the timestamp sometimes increments by 23 microseconds |
| // and other times it increments by 22 microseconds. |
| EXPECT_EQ(0, AddFrames(0)); |
| EXPECT_EQ(22, AddFrames(1)); |
| EXPECT_EQ(45, AddFrames(1)); |
| EXPECT_EQ(68, AddFrames(1)); |
| EXPECT_EQ(90, AddFrames(1)); |
| EXPECT_EQ(113, AddFrames(1)); |
| |
| // Verify that adding frames one frame at a time matches the timestamp |
| // returned if the same number of frames are added all at once. |
| base::TimeDelta timestamp_1 = helper_.GetTimestamp(); |
| helper_.SetBaseTimestamp(kNoTimestamp); |
| EXPECT_TRUE(kNoTimestamp == helper_.base_timestamp()); |
| helper_.SetBaseTimestamp(base::TimeDelta()); |
| EXPECT_EQ(0, helper_.GetTimestamp().InMicroseconds()); |
| |
| helper_.AddFrames(5); |
| EXPECT_EQ(113, helper_.GetTimestamp().InMicroseconds()); |
| EXPECT_TRUE(timestamp_1 == helper_.GetTimestamp()); |
| } |
| |
| TEST_F(AudioTimestampHelperTest, GetDuration) { |
| helper_.SetBaseTimestamp(base::TimeDelta::FromMicroseconds(100)); |
| |
| int frame_count = 5; |
| int64_t expected_durations[] = {113, 113, 114, 113, 113, 114}; |
| for (size_t i = 0; i < arraysize(expected_durations); ++i) { |
| base::TimeDelta duration = helper_.GetFrameDuration(frame_count); |
| EXPECT_EQ(expected_durations[i], duration.InMicroseconds()); |
| |
| base::TimeDelta timestamp_1 = helper_.GetTimestamp() + duration; |
| helper_.AddFrames(frame_count); |
| base::TimeDelta timestamp_2 = helper_.GetTimestamp(); |
| EXPECT_TRUE(timestamp_1 == timestamp_2); |
| } |
| } |
| |
| TEST_F(AudioTimestampHelperTest, GetFramesToTarget) { |
| // Verify GetFramesToTarget() rounding behavior. |
| // 1 frame @ 44100 is ~22.67573 microseconds, |
| |
| // Test values less than half of the frame duration. |
| TestGetFramesToTargetRange(0, 0, 11); |
| |
| // Test values between half the frame duration & the |
| // full frame duration. |
| TestGetFramesToTargetRange(1, 12, 22); |
| |
| // Verify that the same number of frames is returned up |
| // to the next half a frame. |
| TestGetFramesToTargetRange(1, 23, 34); |
| |
| // Verify the next 3 ranges. |
| TestGetFramesToTargetRange(2, 35, 56); |
| TestGetFramesToTargetRange(3, 57, 79); |
| TestGetFramesToTargetRange(4, 80, 102); |
| TestGetFramesToTargetRange(5, 103, 124); |
| |
| // Add frames to the helper so negative frame counts can be tested. |
| helper_.AddFrames(5); |
| |
| // Note: The timestamp ranges must match the positive values |
| // tested above to verify that the code is rounding properly. |
| TestGetFramesToTargetRange(0, 103, 124); |
| TestGetFramesToTargetRange(-1, 80, 102); |
| TestGetFramesToTargetRange(-2, 57, 79); |
| TestGetFramesToTargetRange(-3, 35, 56); |
| TestGetFramesToTargetRange(-4, 12, 34); |
| TestGetFramesToTargetRange(-5, 0, 11); |
| } |
| |
| } // namespace media |
| } // namespace cobalt |