1// Copyright 2013 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/audio_sender/audio_encoder.h" 16#include "media/cast/cast_config.h" 17#include "media/cast/cast_environment.h" 18#include "media/cast/test/fake_single_thread_task_runner.h" 19#include "media/cast/test/utility/audio_utility.h" 20#include "testing/gtest/include/gtest/gtest.h" 21 22namespace media { 23namespace cast { 24 25static const int64 kStartMillisecond = INT64_C(12345678900000); 26 27namespace { 28 29class TestEncodedAudioFrameReceiver { 30 public: 31 explicit TestEncodedAudioFrameReceiver(transport::AudioCodec codec) 32 : codec_(codec), frames_received_(0), rtp_lower_bound_(0) {} 33 virtual ~TestEncodedAudioFrameReceiver() {} 34 35 int frames_received() const { return frames_received_; } 36 37 void SetCaptureTimeBounds(const base::TimeTicks& lower_bound, 38 const base::TimeTicks& upper_bound) { 39 lower_bound_ = lower_bound; 40 upper_bound_ = upper_bound; 41 } 42 43 void FrameEncoded(scoped_ptr<transport::EncodedFrame> encoded_frame) { 44 EXPECT_EQ(encoded_frame->dependency, transport::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 transport::AudioCodec 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 74struct 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 94class AudioEncoderTest : public ::testing::TestWithParam<TestScenario> { 95 public: 96 AudioEncoderTest() { 97 InitializeMediaLibraryForTesting(); 98 testing_clock_ = new base::SimpleTestTickClock(); 99 testing_clock_->Advance( 100 base::TimeDelta::FromMilliseconds(kStartMillisecond)); 101 } 102 103 virtual void SetUp() { 104 task_runner_ = new test::FakeSingleThreadTaskRunner(testing_clock_); 105 cast_environment_ = 106 new CastEnvironment(scoped_ptr<base::TickClock>(testing_clock_).Pass(), 107 task_runner_, 108 task_runner_, 109 task_runner_); 110 } 111 112 virtual ~AudioEncoderTest() {} 113 114 void RunTestForCodec(transport::AudioCodec codec) { 115 const TestScenario& scenario = GetParam(); 116 SCOPED_TRACE(::testing::Message() << "Durations: " << scenario.ToString()); 117 118 CreateObjectsForCodec(codec); 119 120 // Note: In audio_encoder.cc, 10 ms is the fixed frame duration. 121 const base::TimeDelta frame_duration = 122 base::TimeDelta::FromMilliseconds(10); 123 124 for (size_t i = 0; i < scenario.num_durations; ++i) { 125 const bool simulate_missing_data = scenario.durations_in_ms[i] < 0; 126 const base::TimeDelta duration = base::TimeDelta::FromMilliseconds( 127 std::abs(scenario.durations_in_ms[i])); 128 receiver_->SetCaptureTimeBounds( 129 testing_clock_->NowTicks() - frame_duration, 130 testing_clock_->NowTicks() + duration); 131 if (simulate_missing_data) { 132 task_runner_->RunTasks(); 133 testing_clock_->Advance(duration); 134 } else { 135 audio_encoder_->InsertAudio(audio_bus_factory_->NextAudioBus(duration), 136 testing_clock_->NowTicks()); 137 task_runner_->RunTasks(); 138 testing_clock_->Advance(duration); 139 } 140 } 141 142 DVLOG(1) << "Received " << receiver_->frames_received() 143 << " frames for this test run: " << scenario.ToString(); 144 } 145 146 private: 147 void CreateObjectsForCodec(transport::AudioCodec codec) { 148 AudioSenderConfig audio_config; 149 audio_config.codec = codec; 150 audio_config.use_external_encoder = false; 151 audio_config.frequency = kDefaultAudioSamplingRate; 152 audio_config.channels = 2; 153 audio_config.bitrate = kDefaultAudioEncoderBitrate; 154 audio_config.rtp_config.payload_type = 127; 155 156 audio_bus_factory_.reset( 157 new TestAudioBusFactory(audio_config.channels, 158 audio_config.frequency, 159 TestAudioBusFactory::kMiddleANoteFreq, 160 0.5f)); 161 162 receiver_.reset(new TestEncodedAudioFrameReceiver(codec)); 163 164 audio_encoder_.reset(new AudioEncoder( 165 cast_environment_, 166 audio_config, 167 base::Bind(&TestEncodedAudioFrameReceiver::FrameEncoded, 168 base::Unretained(receiver_.get())))); 169 } 170 171 base::SimpleTestTickClock* testing_clock_; // Owned by CastEnvironment. 172 scoped_refptr<test::FakeSingleThreadTaskRunner> task_runner_; 173 scoped_ptr<TestAudioBusFactory> audio_bus_factory_; 174 scoped_ptr<TestEncodedAudioFrameReceiver> receiver_; 175 scoped_ptr<AudioEncoder> audio_encoder_; 176 scoped_refptr<CastEnvironment> cast_environment_; 177 178 DISALLOW_COPY_AND_ASSIGN(AudioEncoderTest); 179}; 180 181TEST_P(AudioEncoderTest, EncodeOpus) { RunTestForCodec(transport::kOpus); } 182 183TEST_P(AudioEncoderTest, EncodePcm16) { RunTestForCodec(transport::kPcm16); } 184 185static const int64 kOneCall_3Millis[] = {3}; 186static const int64 kOneCall_10Millis[] = {10}; 187static const int64 kOneCall_13Millis[] = {13}; 188static const int64 kOneCall_20Millis[] = {20}; 189 190static const int64 kTwoCalls_3Millis[] = {3, 3}; 191static const int64 kTwoCalls_10Millis[] = {10, 10}; 192static const int64 kTwoCalls_Mixed1[] = {3, 10}; 193static const int64 kTwoCalls_Mixed2[] = {10, 3}; 194static const int64 kTwoCalls_Mixed3[] = {3, 17}; 195static const int64 kTwoCalls_Mixed4[] = {17, 3}; 196 197static const int64 kManyCalls_3Millis[] = {3, 3, 3, 3, 3, 3, 3, 3, 198 3, 3, 3, 3, 3, 3, 3}; 199static const int64 kManyCalls_10Millis[] = {10, 10, 10, 10, 10, 10, 10, 10, 200 10, 10, 10, 10, 10, 10, 10}; 201static const int64 kManyCalls_Mixed1[] = {3, 10, 3, 10, 3, 10, 3, 10, 3, 202 10, 3, 10, 3, 10, 3, 10, 3, 10}; 203static const int64 kManyCalls_Mixed2[] = {10, 3, 10, 3, 10, 3, 10, 3, 10, 3, 204 10, 3, 10, 3, 10, 3, 10, 3, 10, 3}; 205static const int64 kManyCalls_Mixed3[] = {3, 1, 4, 1, 5, 9, 2, 6, 5, 3, 5, 8, 206 9, 7, 9, 3, 2, 3, 8, 4, 6, 2, 6, 4}; 207static const int64 kManyCalls_Mixed4[] = {31, 4, 15, 9, 26, 53, 5, 8, 9, 208 7, 9, 32, 38, 4, 62, 64, 3}; 209static const int64 kManyCalls_Mixed5[] = {3, 14, 15, 9, 26, 53, 58, 9, 7, 210 9, 3, 23, 8, 4, 6, 2, 6, 43}; 211 212static const int64 kOneBigUnderrun[] = {10, 10, 10, 10, -1000, 10, 10, 10}; 213static const int64 kTwoBigUnderruns[] = {10, 10, 10, 10, -712, 10, 10, 10, 214 -1311, 10, 10, 10}; 215static const int64 kMixedUnderruns[] = {31, -64, 4, 15, 9, 26, -53, 5, 8, -9, 216 7, 9, 32, 38, -4, 62, -64, 3}; 217 218INSTANTIATE_TEST_CASE_P( 219 AudioEncoderTestScenarios, 220 AudioEncoderTest, 221 ::testing::Values( 222 TestScenario(kOneCall_3Millis, arraysize(kOneCall_3Millis)), 223 TestScenario(kOneCall_10Millis, arraysize(kOneCall_10Millis)), 224 TestScenario(kOneCall_13Millis, arraysize(kOneCall_13Millis)), 225 TestScenario(kOneCall_20Millis, arraysize(kOneCall_20Millis)), 226 TestScenario(kTwoCalls_3Millis, arraysize(kTwoCalls_3Millis)), 227 TestScenario(kTwoCalls_10Millis, arraysize(kTwoCalls_10Millis)), 228 TestScenario(kTwoCalls_Mixed1, arraysize(kTwoCalls_Mixed1)), 229 TestScenario(kTwoCalls_Mixed2, arraysize(kTwoCalls_Mixed2)), 230 TestScenario(kTwoCalls_Mixed3, arraysize(kTwoCalls_Mixed3)), 231 TestScenario(kTwoCalls_Mixed4, arraysize(kTwoCalls_Mixed4)), 232 TestScenario(kManyCalls_3Millis, arraysize(kManyCalls_3Millis)), 233 TestScenario(kManyCalls_10Millis, arraysize(kManyCalls_10Millis)), 234 TestScenario(kManyCalls_Mixed1, arraysize(kManyCalls_Mixed1)), 235 TestScenario(kManyCalls_Mixed2, arraysize(kManyCalls_Mixed2)), 236 TestScenario(kManyCalls_Mixed3, arraysize(kManyCalls_Mixed3)), 237 TestScenario(kManyCalls_Mixed4, arraysize(kManyCalls_Mixed4)), 238 TestScenario(kManyCalls_Mixed5, arraysize(kManyCalls_Mixed5)), 239 TestScenario(kOneBigUnderrun, arraysize(kOneBigUnderrun)), 240 TestScenario(kTwoBigUnderruns, arraysize(kTwoBigUnderruns)), 241 TestScenario(kMixedUnderruns, arraysize(kMixedUnderruns)))); 242 243} // namespace cast 244} // namespace media 245