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.
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"
24 static const int kNumChannels
= 2;
28 class TestEncodedAudioFrameReceiver
{
30 TestEncodedAudioFrameReceiver() : frames_received_(0), rtp_lower_bound_(0) {}
31 virtual ~TestEncodedAudioFrameReceiver() {}
33 int frames_received() const { return frames_received_
; }
35 void SetCaptureTimeBounds(const base::TimeTicks
& lower_bound
,
36 const base::TimeTicks
& upper_bound
) {
37 lower_bound_
= lower_bound
;
38 upper_bound_
= upper_bound
;
41 void SetSamplesPerFrame(int samples_per_frame
) {
42 samples_per_frame_
= samples_per_frame
;
45 void FrameEncoded(scoped_ptr
<SenderEncodedFrame
> encoded_frame
,
46 int samples_skipped
) {
47 EXPECT_EQ(encoded_frame
->dependency
, EncodedFrame::KEY
);
48 EXPECT_EQ(static_cast<uint8
>(frames_received_
& 0xff),
49 encoded_frame
->frame_id
);
50 EXPECT_EQ(encoded_frame
->frame_id
, encoded_frame
->referenced_frame_id
);
51 // RTP timestamps should be monotonically increasing and integer multiples
52 // of the fixed frame size.
53 EXPECT_LE(rtp_lower_bound_
, encoded_frame
->rtp_timestamp
);
54 rtp_lower_bound_
= encoded_frame
->rtp_timestamp
;
55 EXPECT_EQ(0u, encoded_frame
->rtp_timestamp
% samples_per_frame_
);
56 EXPECT_TRUE(!encoded_frame
->data
.empty());
58 EXPECT_LE(lower_bound_
, encoded_frame
->reference_time
);
59 lower_bound_
= encoded_frame
->reference_time
;
60 EXPECT_GT(upper_bound_
, encoded_frame
->reference_time
);
62 EXPECT_LE(0.0, encoded_frame
->deadline_utilization
);
63 EXPECT_EQ(-1.0, encoded_frame
->lossy_utilization
);
70 uint32 rtp_lower_bound_
;
71 int samples_per_frame_
;
72 base::TimeTicks lower_bound_
;
73 base::TimeTicks upper_bound_
;
75 DISALLOW_COPY_AND_ASSIGN(TestEncodedAudioFrameReceiver
);
79 const int64
* durations_in_ms
;
82 TestScenario(const int64
* d
, size_t n
)
83 : durations_in_ms(d
), num_durations(n
) {}
85 std::string
ToString() const {
86 std::ostringstream out
;
87 for (size_t i
= 0; i
< num_durations
; ++i
) {
90 out
<< durations_in_ms
[i
];
98 class AudioEncoderTest
: public ::testing::TestWithParam
<TestScenario
> {
101 InitializeMediaLibrary();
102 testing_clock_
= new base::SimpleTestTickClock();
103 testing_clock_
->Advance(base::TimeTicks::Now() - base::TimeTicks());
107 task_runner_
= new test::FakeSingleThreadTaskRunner(testing_clock_
);
109 new CastEnvironment(scoped_ptr
<base::TickClock
>(testing_clock_
).Pass(),
115 virtual ~AudioEncoderTest() {}
117 void RunTestForCodec(Codec codec
) {
118 const TestScenario
& scenario
= GetParam();
119 SCOPED_TRACE(::testing::Message() << "Durations: " << scenario
.ToString());
121 CreateObjectsForCodec(codec
);
123 const base::TimeDelta frame_duration
= audio_encoder_
->GetFrameDuration();
125 for (size_t i
= 0; i
< scenario
.num_durations
; ++i
) {
126 const bool simulate_missing_data
= scenario
.durations_in_ms
[i
] < 0;
127 const base::TimeDelta duration
= base::TimeDelta::FromMilliseconds(
128 std::abs(scenario
.durations_in_ms
[i
]));
129 receiver_
->SetCaptureTimeBounds(
130 testing_clock_
->NowTicks() - frame_duration
,
131 testing_clock_
->NowTicks() + duration
);
132 if (simulate_missing_data
) {
133 task_runner_
->RunTasks();
134 testing_clock_
->Advance(duration
);
136 audio_encoder_
->InsertAudio(audio_bus_factory_
->NextAudioBus(duration
),
137 testing_clock_
->NowTicks());
138 task_runner_
->RunTasks();
139 testing_clock_
->Advance(duration
);
143 DVLOG(1) << "Received " << receiver_
->frames_received()
144 << " frames for this test run: " << scenario
.ToString();
148 void CreateObjectsForCodec(Codec codec
) {
149 audio_bus_factory_
.reset(
150 new TestAudioBusFactory(kNumChannels
,
151 kDefaultAudioSamplingRate
,
152 TestAudioBusFactory::kMiddleANoteFreq
,
155 receiver_
.reset(new TestEncodedAudioFrameReceiver());
157 audio_encoder_
.reset(new AudioEncoder(
160 kDefaultAudioSamplingRate
,
161 kDefaultAudioEncoderBitrate
,
163 base::Bind(&TestEncodedAudioFrameReceiver::FrameEncoded
,
164 base::Unretained(receiver_
.get()))));
166 receiver_
->SetSamplesPerFrame(audio_encoder_
->GetSamplesPerFrame());
169 base::SimpleTestTickClock
* testing_clock_
; // Owned by CastEnvironment.
170 scoped_refptr
<test::FakeSingleThreadTaskRunner
> task_runner_
;
171 scoped_ptr
<TestAudioBusFactory
> audio_bus_factory_
;
172 scoped_ptr
<TestEncodedAudioFrameReceiver
> receiver_
;
173 scoped_ptr
<AudioEncoder
> audio_encoder_
;
174 scoped_refptr
<CastEnvironment
> cast_environment_
;
176 DISALLOW_COPY_AND_ASSIGN(AudioEncoderTest
);
179 TEST_P(AudioEncoderTest
, EncodeOpus
) {
180 RunTestForCodec(CODEC_AUDIO_OPUS
);
183 TEST_P(AudioEncoderTest
, EncodePcm16
) {
184 RunTestForCodec(CODEC_AUDIO_PCM16
);
187 #if defined(OS_MACOSX)
188 TEST_P(AudioEncoderTest
, EncodeAac
) {
189 RunTestForCodec(CODEC_AUDIO_AAC
);
193 static const int64 kOneCall_3Millis
[] = {3};
194 static const int64 kOneCall_10Millis
[] = {10};
195 static const int64 kOneCall_13Millis
[] = {13};
196 static const int64 kOneCall_20Millis
[] = {20};
198 static const int64 kTwoCalls_3Millis
[] = {3, 3};
199 static const int64 kTwoCalls_10Millis
[] = {10, 10};
200 static const int64 kTwoCalls_Mixed1
[] = {3, 10};
201 static const int64 kTwoCalls_Mixed2
[] = {10, 3};
202 static const int64 kTwoCalls_Mixed3
[] = {3, 17};
203 static const int64 kTwoCalls_Mixed4
[] = {17, 3};
205 static const int64 kManyCalls_3Millis
[] = {3, 3, 3, 3, 3, 3, 3, 3,
206 3, 3, 3, 3, 3, 3, 3};
207 static const int64 kManyCalls_10Millis
[] = {10, 10, 10, 10, 10, 10, 10, 10,
208 10, 10, 10, 10, 10, 10, 10};
209 static const int64 kManyCalls_Mixed1
[] = {3, 10, 3, 10, 3, 10, 3, 10, 3,
210 10, 3, 10, 3, 10, 3, 10, 3, 10};
211 static const int64 kManyCalls_Mixed2
[] = {10, 3, 10, 3, 10, 3, 10, 3, 10, 3,
212 10, 3, 10, 3, 10, 3, 10, 3, 10, 3};
213 static const int64 kManyCalls_Mixed3
[] = {3, 1, 4, 1, 5, 9, 2, 6, 5, 3, 5, 8,
214 9, 7, 9, 3, 2, 3, 8, 4, 6, 2, 6, 4};
215 static const int64 kManyCalls_Mixed4
[] = {31, 4, 15, 9, 26, 53, 5, 8, 9,
216 7, 9, 32, 38, 4, 62, 64, 3};
217 static const int64 kManyCalls_Mixed5
[] = {3, 14, 15, 9, 26, 53, 58, 9, 7,
218 9, 3, 23, 8, 4, 6, 2, 6, 43};
220 static const int64 kOneBigUnderrun
[] = {10, 10, 10, 10, -1000, 10, 10, 10};
221 static const int64 kTwoBigUnderruns
[] = {10, 10, 10, 10, -712, 10, 10, 10,
223 static const int64 kMixedUnderruns
[] = {31, -64, 4, 15, 9, 26, -53, 5, 8, -9,
224 7, 9, 32, 38, -4, 62, -64, 3};
226 INSTANTIATE_TEST_CASE_P(
227 AudioEncoderTestScenarios
,
230 TestScenario(kOneCall_3Millis
, arraysize(kOneCall_3Millis
)),
231 TestScenario(kOneCall_10Millis
, arraysize(kOneCall_10Millis
)),
232 TestScenario(kOneCall_13Millis
, arraysize(kOneCall_13Millis
)),
233 TestScenario(kOneCall_20Millis
, arraysize(kOneCall_20Millis
)),
234 TestScenario(kTwoCalls_3Millis
, arraysize(kTwoCalls_3Millis
)),
235 TestScenario(kTwoCalls_10Millis
, arraysize(kTwoCalls_10Millis
)),
236 TestScenario(kTwoCalls_Mixed1
, arraysize(kTwoCalls_Mixed1
)),
237 TestScenario(kTwoCalls_Mixed2
, arraysize(kTwoCalls_Mixed2
)),
238 TestScenario(kTwoCalls_Mixed3
, arraysize(kTwoCalls_Mixed3
)),
239 TestScenario(kTwoCalls_Mixed4
, arraysize(kTwoCalls_Mixed4
)),
240 TestScenario(kManyCalls_3Millis
, arraysize(kManyCalls_3Millis
)),
241 TestScenario(kManyCalls_10Millis
, arraysize(kManyCalls_10Millis
)),
242 TestScenario(kManyCalls_Mixed1
, arraysize(kManyCalls_Mixed1
)),
243 TestScenario(kManyCalls_Mixed2
, arraysize(kManyCalls_Mixed2
)),
244 TestScenario(kManyCalls_Mixed3
, arraysize(kManyCalls_Mixed3
)),
245 TestScenario(kManyCalls_Mixed4
, arraysize(kManyCalls_Mixed4
)),
246 TestScenario(kManyCalls_Mixed5
, arraysize(kManyCalls_Mixed5
)),
247 TestScenario(kOneBigUnderrun
, arraysize(kOneBigUnderrun
)),
248 TestScenario(kTwoBigUnderruns
, arraysize(kTwoBigUnderruns
)),
249 TestScenario(kMixedUnderruns
, arraysize(kMixedUnderruns
))));