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.
9 #include "base/bind_helpers.h"
10 #include "base/memory/scoped_ptr.h"
11 #include "media/base/audio_bus.h"
12 #include "media/base/media.h"
13 #include "media/cast/audio_sender/audio_encoder.h"
14 #include "media/cast/cast_config.h"
15 #include "media/cast/cast_environment.h"
16 #include "media/cast/test/fake_single_thread_task_runner.h"
17 #include "media/cast/test/utility/audio_utility.h"
18 #include "testing/gtest/include/gtest/gtest.h"
23 static const int64 kStartMillisecond
= GG_INT64_C(12345678900000);
27 class TestEncodedAudioFrameReceiver
{
29 explicit TestEncodedAudioFrameReceiver(transport::AudioCodec codec
)
30 : codec_(codec
), frames_received_(0) {}
31 virtual ~TestEncodedAudioFrameReceiver() {}
33 int frames_received() const { return frames_received_
; }
35 void SetRecordedTimeLowerBound(const base::TimeTicks
& t
) { lower_bound_
= t
; }
37 void SetRecordedTimeUpperBound(const base::TimeTicks
& t
) { upper_bound_
= t
; }
39 void FrameEncoded(scoped_ptr
<transport::EncodedAudioFrame
> encoded_frame
,
40 const base::TimeTicks
& recorded_time
) {
41 EXPECT_EQ(codec_
, encoded_frame
->codec
);
42 EXPECT_EQ(static_cast<uint8
>(frames_received_
& 0xff),
43 encoded_frame
->frame_id
);
44 EXPECT_LT(0u, encoded_frame
->rtp_timestamp
);
45 EXPECT_TRUE(!encoded_frame
->data
.empty());
47 EXPECT_LE(lower_bound_
, recorded_time
);
48 lower_bound_
= recorded_time
;
49 EXPECT_GT(upper_bound_
, recorded_time
);
55 const transport::AudioCodec codec_
;
57 base::TimeTicks lower_bound_
;
58 base::TimeTicks upper_bound_
;
60 DISALLOW_COPY_AND_ASSIGN(TestEncodedAudioFrameReceiver
);
64 const int64
* durations_in_ms
;
67 TestScenario(const int64
* d
, size_t n
)
68 : durations_in_ms(d
), num_durations(n
) {}
70 std::string
ToString() const {
71 std::ostringstream out
;
72 for (size_t i
= 0; i
< num_durations
; ++i
) {
75 out
<< durations_in_ms
[i
];
83 class AudioEncoderTest
: public ::testing::TestWithParam
<TestScenario
> {
86 InitializeMediaLibraryForTesting();
87 testing_clock_
= new base::SimpleTestTickClock();
88 testing_clock_
->Advance(
89 base::TimeDelta::FromMilliseconds(kStartMillisecond
));
92 virtual void SetUp() {
93 task_runner_
= new test::FakeSingleThreadTaskRunner(testing_clock_
);
95 new CastEnvironment(scoped_ptr
<base::TickClock
>(testing_clock_
).Pass(),
102 GetDefaultCastSenderLoggingConfig());
105 virtual ~AudioEncoderTest() {}
107 void RunTestForCodec(transport::AudioCodec codec
) {
108 const TestScenario
& scenario
= GetParam();
109 SCOPED_TRACE(::testing::Message() << "Durations: " << scenario
.ToString());
111 CreateObjectsForCodec(codec
);
113 receiver_
->SetRecordedTimeLowerBound(testing_clock_
->NowTicks());
114 for (size_t i
= 0; i
< scenario
.num_durations
; ++i
) {
115 const base::TimeDelta duration
=
116 base::TimeDelta::FromMilliseconds(scenario
.durations_in_ms
[i
]);
117 receiver_
->SetRecordedTimeUpperBound(testing_clock_
->NowTicks() +
120 const scoped_ptr
<AudioBus
> bus(
121 audio_bus_factory_
->NextAudioBus(duration
));
123 const int last_count
= release_callback_count_
;
124 audio_encoder_
->InsertAudio(
126 testing_clock_
->NowTicks(),
127 base::Bind(&AudioEncoderTest::IncrementReleaseCallbackCounter
,
128 base::Unretained(this)));
129 task_runner_
->RunTasks();
130 EXPECT_EQ(1, release_callback_count_
- last_count
)
131 << "Release callback was not invoked once.";
133 testing_clock_
->Advance(duration
);
136 DVLOG(1) << "Received " << receiver_
->frames_received()
137 << " frames for this test run: " << scenario
.ToString();
141 void CreateObjectsForCodec(transport::AudioCodec codec
) {
142 AudioSenderConfig audio_config
;
143 audio_config
.codec
= codec
;
144 audio_config
.use_external_encoder
= false;
145 audio_config
.frequency
= kDefaultAudioSamplingRate
;
146 audio_config
.channels
= 2;
147 audio_config
.bitrate
= kDefaultAudioEncoderBitrate
;
148 audio_config
.rtp_config
.payload_type
= 127;
150 audio_bus_factory_
.reset(
151 new TestAudioBusFactory(audio_config
.channels
,
152 audio_config
.frequency
,
153 TestAudioBusFactory::kMiddleANoteFreq
,
156 receiver_
.reset(new TestEncodedAudioFrameReceiver(codec
));
158 audio_encoder_
= new AudioEncoder(
161 base::Bind(&TestEncodedAudioFrameReceiver::FrameEncoded
,
162 base::Unretained(receiver_
.get())));
163 release_callback_count_
= 0;
166 void IncrementReleaseCallbackCounter() { ++release_callback_count_
; }
168 base::SimpleTestTickClock
* testing_clock_
; // Owned by CastEnvironment.
169 scoped_refptr
<test::FakeSingleThreadTaskRunner
> task_runner_
;
170 scoped_ptr
<TestAudioBusFactory
> audio_bus_factory_
;
171 scoped_ptr
<TestEncodedAudioFrameReceiver
> receiver_
;
172 scoped_refptr
<AudioEncoder
> audio_encoder_
;
173 scoped_refptr
<CastEnvironment
> cast_environment_
;
174 int release_callback_count_
;
176 DISALLOW_COPY_AND_ASSIGN(AudioEncoderTest
);
179 TEST_P(AudioEncoderTest
, EncodeOpus
) { RunTestForCodec(transport::kOpus
); }
181 TEST_P(AudioEncoderTest
, EncodePcm16
) { RunTestForCodec(transport::kPcm16
); }
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};
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};
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};
210 INSTANTIATE_TEST_CASE_P(
211 AudioEncoderTestScenarios
,
214 TestScenario(kOneCall_3Millis
, arraysize(kOneCall_3Millis
)),
215 TestScenario(kOneCall_10Millis
, arraysize(kOneCall_10Millis
)),
216 TestScenario(kOneCall_13Millis
, arraysize(kOneCall_13Millis
)),
217 TestScenario(kOneCall_20Millis
, arraysize(kOneCall_20Millis
)),
218 TestScenario(kTwoCalls_3Millis
, arraysize(kTwoCalls_3Millis
)),
219 TestScenario(kTwoCalls_10Millis
, arraysize(kTwoCalls_10Millis
)),
220 TestScenario(kTwoCalls_Mixed1
, arraysize(kTwoCalls_Mixed1
)),
221 TestScenario(kTwoCalls_Mixed2
, arraysize(kTwoCalls_Mixed2
)),
222 TestScenario(kTwoCalls_Mixed3
, arraysize(kTwoCalls_Mixed3
)),
223 TestScenario(kTwoCalls_Mixed4
, arraysize(kTwoCalls_Mixed4
)),
224 TestScenario(kManyCalls_3Millis
, arraysize(kManyCalls_3Millis
)),
225 TestScenario(kManyCalls_10Millis
, arraysize(kManyCalls_10Millis
)),
226 TestScenario(kManyCalls_Mixed1
, arraysize(kManyCalls_Mixed1
)),
227 TestScenario(kManyCalls_Mixed2
, arraysize(kManyCalls_Mixed2
)),
228 TestScenario(kManyCalls_Mixed3
, arraysize(kManyCalls_Mixed3
)),
229 TestScenario(kManyCalls_Mixed4
, arraysize(kManyCalls_Mixed4
)),
230 TestScenario(kManyCalls_Mixed5
, arraysize(kManyCalls_Mixed5
))));