Cast: Stop logging kVideoFrameSentToEncoder and rename a couple events.
[chromium-blink-merge.git] / media / audio / virtual_audio_input_stream_unittest.cc
blob49379524cfd0f0b21a424fb4935fdeb498873b7c
1 // Copyright (c) 2012 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.
5 #include <list>
7 #include "base/bind.h"
8 #include "base/bind_helpers.h"
9 #include "base/rand_util.h"
10 #include "base/synchronization/waitable_event.h"
11 #include "base/threading/thread.h"
12 #include "media/audio/audio_io.h"
13 #include "media/audio/simple_sources.h"
14 #include "media/audio/virtual_audio_input_stream.h"
15 #include "media/audio/virtual_audio_output_stream.h"
16 #include "testing/gmock/include/gmock/gmock.h"
17 #include "testing/gtest/include/gtest/gtest.h"
19 using ::testing::_;
20 using ::testing::AtLeast;
21 using ::testing::InvokeWithoutArgs;
22 using ::testing::NotNull;
24 namespace media {
26 namespace {
28 const AudioParameters kParams(
29 AudioParameters::AUDIO_PCM_LOW_LATENCY, CHANNEL_LAYOUT_STEREO, 8000, 8, 10);
31 class MockInputCallback : public AudioInputStream::AudioInputCallback {
32 public:
33 MockInputCallback()
34 : data_pushed_(false, false) {
35 ON_CALL(*this, OnData(_, _, _, _, _))
36 .WillByDefault(InvokeWithoutArgs(&data_pushed_,
37 &base::WaitableEvent::Signal));
40 virtual ~MockInputCallback() {}
42 MOCK_METHOD5(OnData, void(AudioInputStream* stream, const uint8* data,
43 uint32 size, uint32 hardware_delay_bytes,
44 double volume));
45 MOCK_METHOD1(OnError, void(AudioInputStream* stream));
47 void WaitForDataPushes() {
48 for (int i = 0; i < 3; ++i) {
49 data_pushed_.Wait();
53 private:
54 base::WaitableEvent data_pushed_;
56 DISALLOW_COPY_AND_ASSIGN(MockInputCallback);
59 class TestAudioSource : public SineWaveAudioSource {
60 public:
61 TestAudioSource()
62 : SineWaveAudioSource(
63 kParams.channel_layout(), 200.0, kParams.sample_rate()),
64 data_pulled_(false, false) {}
66 virtual ~TestAudioSource() {}
68 virtual int OnMoreData(AudioBus* audio_bus,
69 AudioBuffersState audio_buffers) OVERRIDE {
70 const int ret = SineWaveAudioSource::OnMoreData(audio_bus, audio_buffers);
71 data_pulled_.Signal();
72 return ret;
75 virtual int OnMoreIOData(AudioBus* source,
76 AudioBus* dest,
77 AudioBuffersState audio_buffers) OVERRIDE {
78 const int ret =
79 SineWaveAudioSource::OnMoreIOData(source, dest, audio_buffers);
80 data_pulled_.Signal();
81 return ret;
84 void WaitForDataPulls() {
85 for (int i = 0; i < 3; ++i) {
86 data_pulled_.Wait();
90 private:
91 base::WaitableEvent data_pulled_;
93 DISALLOW_COPY_AND_ASSIGN(TestAudioSource);
96 } // namespace
98 class VirtualAudioInputStreamTest : public testing::TestWithParam<bool> {
99 public:
100 VirtualAudioInputStreamTest()
101 : audio_thread_(new base::Thread("AudioThread")),
102 worker_thread_(new base::Thread("AudioWorkerThread")),
103 stream_(NULL),
104 closed_stream_(false, false) {
105 audio_thread_->Start();
106 audio_task_runner_ = audio_thread_->message_loop_proxy();
109 virtual ~VirtualAudioInputStreamTest() {
110 SyncWithAudioThread();
112 DCHECK(output_streams_.empty());
113 DCHECK(stopped_output_streams_.empty());
116 void Create() {
117 const bool worker_is_separate_thread = GetParam();
118 stream_ = new VirtualAudioInputStream(
119 kParams, GetWorkerTaskRunner(worker_is_separate_thread),
120 base::Bind(&base::DeletePointer<VirtualAudioInputStream>));
121 stream_->Open();
124 void Start() {
125 EXPECT_CALL(input_callback_, OnData(_, NotNull(), _, _, _))
126 .Times(AtLeast(1));
128 ASSERT_TRUE(!!stream_);
129 stream_->Start(&input_callback_);
132 void CreateAndStartOneOutputStream() {
133 ASSERT_TRUE(!!stream_);
134 AudioOutputStream* const output_stream = new VirtualAudioOutputStream(
135 kParams,
136 stream_,
137 base::Bind(&base::DeletePointer<VirtualAudioOutputStream>));
138 output_streams_.push_back(output_stream);
140 output_stream->Open();
141 output_stream->Start(&source_);
144 void Stop() {
145 ASSERT_TRUE(!!stream_);
146 stream_->Stop();
149 void Close() {
150 ASSERT_TRUE(!!stream_);
151 stream_->Close();
152 stream_ = NULL;
153 closed_stream_.Signal();
156 void WaitForDataToFlow() {
157 // Wait until audio thread is idle before calling output_streams_.size().
158 SyncWithAudioThread();
160 const int count = output_streams_.size();
161 for (int i = 0; i < count; ++i) {
162 source_.WaitForDataPulls();
165 input_callback_.WaitForDataPushes();
168 void WaitUntilClosed() {
169 closed_stream_.Wait();
172 void StopAndCloseOneOutputStream() {
173 ASSERT_TRUE(!output_streams_.empty());
174 AudioOutputStream* const output_stream = output_streams_.front();
175 ASSERT_TRUE(!!output_stream);
176 output_streams_.pop_front();
178 output_stream->Stop();
179 output_stream->Close();
182 void StopFirstOutputStream() {
183 ASSERT_TRUE(!output_streams_.empty());
184 AudioOutputStream* const output_stream = output_streams_.front();
185 ASSERT_TRUE(!!output_stream);
186 output_streams_.pop_front();
187 output_stream->Stop();
188 stopped_output_streams_.push_back(output_stream);
191 void StopSomeOutputStreams() {
192 ASSERT_LE(2, static_cast<int>(output_streams_.size()));
193 for (int remaning = base::RandInt(1, output_streams_.size() - 1);
194 remaning > 0; --remaning) {
195 StopFirstOutputStream();
199 void RestartAllStoppedOutputStreams() {
200 typedef std::list<AudioOutputStream*>::const_iterator ConstIter;
201 for (ConstIter it = stopped_output_streams_.begin();
202 it != stopped_output_streams_.end(); ++it) {
203 (*it)->Start(&source_);
204 output_streams_.push_back(*it);
206 stopped_output_streams_.clear();
209 const scoped_refptr<base::SingleThreadTaskRunner>& audio_task_runner() const {
210 return audio_task_runner_;
213 const scoped_refptr<base::SingleThreadTaskRunner>& GetWorkerTaskRunner(
214 bool worker_is_separate_thread) {
215 if (worker_is_separate_thread) {
216 if (!worker_thread_->IsRunning()) {
217 worker_thread_->Start();
218 worker_task_runner_ = worker_thread_->message_loop_proxy();
220 return worker_task_runner_;
221 } else {
222 return audio_task_runner_;
226 private:
227 void SyncWithAudioThread() {
228 base::WaitableEvent done(false, false);
229 audio_task_runner_->PostTask(
230 FROM_HERE,
231 base::Bind(&base::WaitableEvent::Signal, base::Unretained(&done)));
232 done.Wait();
235 scoped_ptr<base::Thread> audio_thread_;
236 scoped_refptr<base::SingleThreadTaskRunner> audio_task_runner_;
237 scoped_ptr<base::Thread> worker_thread_;
238 scoped_refptr<base::SingleThreadTaskRunner> worker_task_runner_;
240 VirtualAudioInputStream* stream_;
241 MockInputCallback input_callback_;
242 base::WaitableEvent closed_stream_;
244 std::list<AudioOutputStream*> output_streams_;
245 std::list<AudioOutputStream*> stopped_output_streams_;
246 TestAudioSource source_;
248 DISALLOW_COPY_AND_ASSIGN(VirtualAudioInputStreamTest);
251 #define RUN_ON_AUDIO_THREAD(method) \
252 audio_task_runner()->PostTask( \
253 FROM_HERE, base::Bind(&VirtualAudioInputStreamTest::method, \
254 base::Unretained(this)))
256 TEST_P(VirtualAudioInputStreamTest, CreateAndClose) {
257 RUN_ON_AUDIO_THREAD(Create);
258 RUN_ON_AUDIO_THREAD(Close);
259 WaitUntilClosed();
262 TEST_P(VirtualAudioInputStreamTest, NoOutputs) {
263 RUN_ON_AUDIO_THREAD(Create);
264 RUN_ON_AUDIO_THREAD(Start);
265 WaitForDataToFlow();
266 RUN_ON_AUDIO_THREAD(Stop);
267 RUN_ON_AUDIO_THREAD(Close);
268 WaitUntilClosed();
271 TEST_P(VirtualAudioInputStreamTest, SingleOutput) {
272 RUN_ON_AUDIO_THREAD(Create);
273 RUN_ON_AUDIO_THREAD(Start);
274 RUN_ON_AUDIO_THREAD(CreateAndStartOneOutputStream);
275 WaitForDataToFlow();
276 RUN_ON_AUDIO_THREAD(StopAndCloseOneOutputStream);
277 RUN_ON_AUDIO_THREAD(Stop);
278 RUN_ON_AUDIO_THREAD(Close);
279 WaitUntilClosed();
282 TEST_P(VirtualAudioInputStreamTest, SingleOutputPausedAndRestarted) {
283 RUN_ON_AUDIO_THREAD(Create);
284 RUN_ON_AUDIO_THREAD(Start);
285 RUN_ON_AUDIO_THREAD(CreateAndStartOneOutputStream);
286 WaitForDataToFlow();
287 RUN_ON_AUDIO_THREAD(StopFirstOutputStream);
288 RUN_ON_AUDIO_THREAD(RestartAllStoppedOutputStreams);
289 WaitForDataToFlow();
290 RUN_ON_AUDIO_THREAD(StopAndCloseOneOutputStream);
291 RUN_ON_AUDIO_THREAD(Stop);
292 RUN_ON_AUDIO_THREAD(Close);
293 WaitUntilClosed();
296 TEST_P(VirtualAudioInputStreamTest, MultipleOutputs) {
297 RUN_ON_AUDIO_THREAD(Create);
298 RUN_ON_AUDIO_THREAD(Start);
299 RUN_ON_AUDIO_THREAD(CreateAndStartOneOutputStream);
300 WaitForDataToFlow();
301 RUN_ON_AUDIO_THREAD(CreateAndStartOneOutputStream);
302 RUN_ON_AUDIO_THREAD(CreateAndStartOneOutputStream);
303 WaitForDataToFlow();
304 RUN_ON_AUDIO_THREAD(StopFirstOutputStream);
305 RUN_ON_AUDIO_THREAD(StopFirstOutputStream);
306 WaitForDataToFlow();
307 RUN_ON_AUDIO_THREAD(StopFirstOutputStream);
308 RUN_ON_AUDIO_THREAD(RestartAllStoppedOutputStreams);
309 WaitForDataToFlow();
310 RUN_ON_AUDIO_THREAD(StopAndCloseOneOutputStream);
311 RUN_ON_AUDIO_THREAD(StopAndCloseOneOutputStream);
312 RUN_ON_AUDIO_THREAD(Stop);
313 RUN_ON_AUDIO_THREAD(StopAndCloseOneOutputStream);
314 RUN_ON_AUDIO_THREAD(Close);
315 WaitUntilClosed();
318 // A combination of all of the above tests with many output streams.
319 TEST_P(VirtualAudioInputStreamTest, ComprehensiveTest) {
320 static const int kNumOutputs = 8;
321 static const int kHalfNumOutputs = kNumOutputs / 2;
322 static const int kPauseIterations = 5;
324 RUN_ON_AUDIO_THREAD(Create);
325 for (int i = 0; i < kHalfNumOutputs; ++i) {
326 RUN_ON_AUDIO_THREAD(CreateAndStartOneOutputStream);
328 RUN_ON_AUDIO_THREAD(Start);
329 WaitForDataToFlow();
330 for (int i = 0; i < kHalfNumOutputs; ++i) {
331 RUN_ON_AUDIO_THREAD(CreateAndStartOneOutputStream);
333 WaitForDataToFlow();
334 for (int i = 0; i < kPauseIterations; ++i) {
335 RUN_ON_AUDIO_THREAD(StopSomeOutputStreams);
336 WaitForDataToFlow();
337 RUN_ON_AUDIO_THREAD(RestartAllStoppedOutputStreams);
338 WaitForDataToFlow();
340 for (int i = 0; i < kHalfNumOutputs; ++i) {
341 RUN_ON_AUDIO_THREAD(StopAndCloseOneOutputStream);
343 RUN_ON_AUDIO_THREAD(Stop);
344 for (int i = 0; i < kHalfNumOutputs; ++i) {
345 RUN_ON_AUDIO_THREAD(StopAndCloseOneOutputStream);
347 RUN_ON_AUDIO_THREAD(Close);
348 WaitUntilClosed();
351 INSTANTIATE_TEST_CASE_P(SingleVersusMultithreaded,
352 VirtualAudioInputStreamTest,
353 ::testing::Values(false, true));
355 } // namespace media