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 <stdint.h> 6 7 #include <sstream> 8 #include <string> 9 10 #include "base/bind.h" 11 #include "base/bind_helpers.h" 12 #include "base/memory/scoped_ptr.h" 13 #include "media/base/audio_bus.h" 14 #include "media/base/media.h" 15 #include "media/cast/cast_environment.h" 16 #include "media/cast/sender/audio_encoder.h" 17 #include "media/cast/test/fake_single_thread_task_runner.h" 18 #include "media/cast/test/utility/audio_utility.h" 19 #include "testing/gtest/include/gtest/gtest.h" 20 21 namespace media { 22 namespace cast { 23 24 static const int kNumChannels = 2; 25 26 namespace { 27 28 class TestEncodedAudioFrameReceiver { 29 public: 30 explicit TestEncodedAudioFrameReceiver(Codec codec) 31 : codec_(codec), frames_received_(0), rtp_lower_bound_(0) {} 32 virtual ~TestEncodedAudioFrameReceiver() {} 33 34 int frames_received() const { return frames_received_; } 35 36 void SetCaptureTimeBounds(const base::TimeTicks& lower_bound, 37 const base::TimeTicks& upper_bound) { 38 lower_bound_ = lower_bound; 39 upper_bound_ = upper_bound; 40 } 41 42 void FrameEncoded(scoped_ptr<EncodedFrame> encoded_frame, 43 int samples_skipped) { 44 EXPECT_EQ(encoded_frame->dependency, EncodedFrame::KEY); 45 EXPECT_EQ(static_cast<uint8>(frames_received_ & 0xff), 46 encoded_frame->frame_id); 47 EXPECT_EQ(encoded_frame->frame_id, encoded_frame->referenced_frame_id); 48 // RTP timestamps should be monotonically increasing and integer multiples 49 // of the fixed frame size. 50 EXPECT_LE(rtp_lower_bound_, encoded_frame->rtp_timestamp); 51 rtp_lower_bound_ = encoded_frame->rtp_timestamp; 52 // Note: In audio_encoder.cc, 100 is the fixed audio frame rate. 53 const int kSamplesPerFrame = kDefaultAudioSamplingRate / 100; 54 EXPECT_EQ(0u, encoded_frame->rtp_timestamp % kSamplesPerFrame); 55 EXPECT_TRUE(!encoded_frame->data.empty()); 56 57 EXPECT_LE(lower_bound_, encoded_frame->reference_time); 58 lower_bound_ = encoded_frame->reference_time; 59 EXPECT_GT(upper_bound_, encoded_frame->reference_time); 60 61 ++frames_received_; 62 } 63 64 private: 65 const Codec codec_; 66 int frames_received_; 67 uint32 rtp_lower_bound_; 68 base::TimeTicks lower_bound_; 69 base::TimeTicks upper_bound_; 70 71 DISALLOW_COPY_AND_ASSIGN(TestEncodedAudioFrameReceiver); 72 }; 73 74 struct TestScenario { 75 const int64* durations_in_ms; 76 size_t num_durations; 77 78 TestScenario(const int64* d, size_t n) 79 : durations_in_ms(d), num_durations(n) {} 80 81 std::string ToString() const { 82 std::ostringstream out; 83 for (size_t i = 0; i < num_durations; ++i) { 84 if (i > 0) 85 out << ", "; 86 out << durations_in_ms[i]; 87 } 88 return out.str(); 89 } 90 }; 91 92 } // namespace 93 94 class AudioEncoderTest : public ::testing::TestWithParam<TestScenario> { 95 public: 96 AudioEncoderTest() { 97 InitializeMediaLibraryForTesting(); 98 testing_clock_ = new base::SimpleTestTickClock(); 99 testing_clock_->Advance(base::TimeTicks::Now() - base::TimeTicks()); 100 } 101 102 virtual void SetUp() { 103 task_runner_ = new test::FakeSingleThreadTaskRunner(testing_clock_); 104 cast_environment_ = 105 new CastEnvironment(scoped_ptr<base::TickClock>(testing_clock_).Pass(), 106 task_runner_, 107 task_runner_, 108 task_runner_); 109 } 110 111 virtual ~AudioEncoderTest() {} 112 113 void RunTestForCodec(Codec codec) { 114 const TestScenario& scenario = GetParam(); 115 SCOPED_TRACE(::testing::Message() << "Durations: " << scenario.ToString()); 116 117 CreateObjectsForCodec(codec); 118 119 // Note: In audio_encoder.cc, 10 ms is the fixed frame duration. 120 const base::TimeDelta frame_duration = 121 base::TimeDelta::FromMilliseconds(10); 122 123 for (size_t i = 0; i < scenario.num_durations; ++i) { 124 const bool simulate_missing_data = scenario.durations_in_ms[i] < 0; 125 const base::TimeDelta duration = base::TimeDelta::FromMilliseconds( 126 std::abs(scenario.durations_in_ms[i])); 127 receiver_->SetCaptureTimeBounds( 128 testing_clock_->NowTicks() - frame_duration, 129 testing_clock_->NowTicks() + duration); 130 if (simulate_missing_data) { 131 task_runner_->RunTasks(); 132 testing_clock_->Advance(duration); 133 } else { 134 audio_encoder_->InsertAudio(audio_bus_factory_->NextAudioBus(duration), 135 testing_clock_->NowTicks()); 136 task_runner_->RunTasks(); 137 testing_clock_->Advance(duration); 138 } 139 } 140 141 DVLOG(1) << "Received " << receiver_->frames_received() 142 << " frames for this test run: " << scenario.ToString(); 143 } 144 145 private: 146 void CreateObjectsForCodec(Codec codec) { 147 audio_bus_factory_.reset( 148 new TestAudioBusFactory(kNumChannels, 149 kDefaultAudioSamplingRate, 150 TestAudioBusFactory::kMiddleANoteFreq, 151 0.5f)); 152 153 receiver_.reset(new TestEncodedAudioFrameReceiver(codec)); 154 155 audio_encoder_.reset(new AudioEncoder( 156 cast_environment_, 157 kNumChannels, 158 kDefaultAudioSamplingRate, 159 kDefaultAudioEncoderBitrate, 160 codec, 161 base::Bind(&TestEncodedAudioFrameReceiver::FrameEncoded, 162 base::Unretained(receiver_.get())))); 163 } 164 165 base::SimpleTestTickClock* testing_clock_; // Owned by CastEnvironment. 166 scoped_refptr<test::FakeSingleThreadTaskRunner> task_runner_; 167 scoped_ptr<TestAudioBusFactory> audio_bus_factory_; 168 scoped_ptr<TestEncodedAudioFrameReceiver> receiver_; 169 scoped_ptr<AudioEncoder> audio_encoder_; 170 scoped_refptr<CastEnvironment> cast_environment_; 171 172 DISALLOW_COPY_AND_ASSIGN(AudioEncoderTest); 173 }; 174 175 TEST_P(AudioEncoderTest, EncodeOpus) { 176 RunTestForCodec(CODEC_AUDIO_OPUS); 177 } 178 179 TEST_P(AudioEncoderTest, EncodePcm16) { 180 RunTestForCodec(CODEC_AUDIO_PCM16); 181 } 182 183 static const int64 kOneCall_3Millis[] = {3}; 184 static const int64 kOneCall_10Millis[] = {10}; 185 static const int64 kOneCall_13Millis[] = {13}; 186 static const int64 kOneCall_20Millis[] = {20}; 187 188 static const int64 kTwoCalls_3Millis[] = {3, 3}; 189 static const int64 kTwoCalls_10Millis[] = {10, 10}; 190 static const int64 kTwoCalls_Mixed1[] = {3, 10}; 191 static const int64 kTwoCalls_Mixed2[] = {10, 3}; 192 static const int64 kTwoCalls_Mixed3[] = {3, 17}; 193 static const int64 kTwoCalls_Mixed4[] = {17, 3}; 194 195 static const int64 kManyCalls_3Millis[] = {3, 3, 3, 3, 3, 3, 3, 3, 196 3, 3, 3, 3, 3, 3, 3}; 197 static const int64 kManyCalls_10Millis[] = {10, 10, 10, 10, 10, 10, 10, 10, 198 10, 10, 10, 10, 10, 10, 10}; 199 static const int64 kManyCalls_Mixed1[] = {3, 10, 3, 10, 3, 10, 3, 10, 3, 200 10, 3, 10, 3, 10, 3, 10, 3, 10}; 201 static const int64 kManyCalls_Mixed2[] = {10, 3, 10, 3, 10, 3, 10, 3, 10, 3, 202 10, 3, 10, 3, 10, 3, 10, 3, 10, 3}; 203 static const int64 kManyCalls_Mixed3[] = {3, 1, 4, 1, 5, 9, 2, 6, 5, 3, 5, 8, 204 9, 7, 9, 3, 2, 3, 8, 4, 6, 2, 6, 4}; 205 static const int64 kManyCalls_Mixed4[] = {31, 4, 15, 9, 26, 53, 5, 8, 9, 206 7, 9, 32, 38, 4, 62, 64, 3}; 207 static const int64 kManyCalls_Mixed5[] = {3, 14, 15, 9, 26, 53, 58, 9, 7, 208 9, 3, 23, 8, 4, 6, 2, 6, 43}; 209 210 static const int64 kOneBigUnderrun[] = {10, 10, 10, 10, -1000, 10, 10, 10}; 211 static const int64 kTwoBigUnderruns[] = {10, 10, 10, 10, -712, 10, 10, 10, 212 -1311, 10, 10, 10}; 213 static const int64 kMixedUnderruns[] = {31, -64, 4, 15, 9, 26, -53, 5, 8, -9, 214 7, 9, 32, 38, -4, 62, -64, 3}; 215 216 INSTANTIATE_TEST_CASE_P( 217 AudioEncoderTestScenarios, 218 AudioEncoderTest, 219 ::testing::Values( 220 TestScenario(kOneCall_3Millis, arraysize(kOneCall_3Millis)), 221 TestScenario(kOneCall_10Millis, arraysize(kOneCall_10Millis)), 222 TestScenario(kOneCall_13Millis, arraysize(kOneCall_13Millis)), 223 TestScenario(kOneCall_20Millis, arraysize(kOneCall_20Millis)), 224 TestScenario(kTwoCalls_3Millis, arraysize(kTwoCalls_3Millis)), 225 TestScenario(kTwoCalls_10Millis, arraysize(kTwoCalls_10Millis)), 226 TestScenario(kTwoCalls_Mixed1, arraysize(kTwoCalls_Mixed1)), 227 TestScenario(kTwoCalls_Mixed2, arraysize(kTwoCalls_Mixed2)), 228 TestScenario(kTwoCalls_Mixed3, arraysize(kTwoCalls_Mixed3)), 229 TestScenario(kTwoCalls_Mixed4, arraysize(kTwoCalls_Mixed4)), 230 TestScenario(kManyCalls_3Millis, arraysize(kManyCalls_3Millis)), 231 TestScenario(kManyCalls_10Millis, arraysize(kManyCalls_10Millis)), 232 TestScenario(kManyCalls_Mixed1, arraysize(kManyCalls_Mixed1)), 233 TestScenario(kManyCalls_Mixed2, arraysize(kManyCalls_Mixed2)), 234 TestScenario(kManyCalls_Mixed3, arraysize(kManyCalls_Mixed3)), 235 TestScenario(kManyCalls_Mixed4, arraysize(kManyCalls_Mixed4)), 236 TestScenario(kManyCalls_Mixed5, arraysize(kManyCalls_Mixed5)), 237 TestScenario(kOneBigUnderrun, arraysize(kOneBigUnderrun)), 238 TestScenario(kTwoBigUnderruns, arraysize(kTwoBigUnderruns)), 239 TestScenario(kMixedUnderruns, arraysize(kMixedUnderruns)))); 240 241 } // namespace cast 242 } // namespace media 243