12a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 22a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 32a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// found in the LICENSE file. 42a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 52a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include <list> 62a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 72a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/bind.h" 82a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/bind_helpers.h" 92a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/rand_util.h" 102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/synchronization/waitable_event.h" 112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/threading/thread.h" 122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "media/audio/audio_io.h" 132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "media/audio/simple_sources.h" 142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "media/audio/virtual_audio_input_stream.h" 152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "media/audio/virtual_audio_output_stream.h" 162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "testing/gmock/include/gmock/gmock.h" 172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "testing/gtest/include/gtest/gtest.h" 182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)using ::testing::_; 202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)using ::testing::AtLeast; 212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)using ::testing::InvokeWithoutArgs; 222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)using ::testing::NotNull; 232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace media { 252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace { 272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const AudioParameters kParams( 292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) AudioParameters::AUDIO_PCM_LOW_LATENCY, CHANNEL_LAYOUT_STEREO, 8000, 8, 10); 302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)class MockInputCallback : public AudioInputStream::AudioInputCallback { 322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) public: 332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) MockInputCallback() 342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) : data_pushed_(false, false) { 356d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) ON_CALL(*this, OnData(_, _, _, _)).WillByDefault( 366d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) InvokeWithoutArgs(&data_pushed_, &base::WaitableEvent::Signal)); 372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) virtual ~MockInputCallback() {} 402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 416d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) MOCK_METHOD4(OnData, 426d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) void(AudioInputStream* stream, 436d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) const AudioBus* source, 446d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) uint32 hardware_delay_bytes, 456d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) double volume)); 462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) MOCK_METHOD1(OnError, void(AudioInputStream* stream)); 472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) void WaitForDataPushes() { 492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for (int i = 0; i < 3; ++i) { 502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) data_pushed_.Wait(); 512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) private: 552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::WaitableEvent data_pushed_; 562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DISALLOW_COPY_AND_ASSIGN(MockInputCallback); 582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}; 592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)class TestAudioSource : public SineWaveAudioSource { 612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) public: 622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) TestAudioSource() 632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) : SineWaveAudioSource( 642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) kParams.channel_layout(), 200.0, kParams.sample_rate()), 652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) data_pulled_(false, false) {} 662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) virtual ~TestAudioSource() {} 682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) virtual int OnMoreData(AudioBus* audio_bus, 702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) AudioBuffersState audio_buffers) OVERRIDE { 712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const int ret = SineWaveAudioSource::OnMoreData(audio_bus, audio_buffers); 722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) data_pulled_.Signal(); 732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return ret; 742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) void WaitForDataPulls() { 772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for (int i = 0; i < 3; ++i) { 782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) data_pulled_.Wait(); 792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) private: 832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::WaitableEvent data_pulled_; 842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DISALLOW_COPY_AND_ASSIGN(TestAudioSource); 862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}; 872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} // namespace 892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 90eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochclass VirtualAudioInputStreamTest : public testing::TestWithParam<bool> { 912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) public: 922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) VirtualAudioInputStreamTest() 932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) : audio_thread_(new base::Thread("AudioThread")), 94eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch worker_thread_(new base::Thread("AudioWorkerThread")), 952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) stream_(NULL), 962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) closed_stream_(false, false) { 972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) audio_thread_->Start(); 985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) audio_task_runner_ = audio_thread_->message_loop_proxy(); 992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) virtual ~VirtualAudioInputStreamTest() { 1022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SyncWithAudioThread(); 1032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(output_streams_.empty()); 1052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(stopped_output_streams_.empty()); 1062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) void Create() { 109eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch const bool worker_is_separate_thread = GetParam(); 1102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) stream_ = new VirtualAudioInputStream( 1115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) kParams, GetWorkerTaskRunner(worker_is_separate_thread), 1122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::Bind(&base::DeletePointer<VirtualAudioInputStream>)); 1132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) stream_->Open(); 1142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) void Start() { 1176d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) EXPECT_CALL(input_callback_, OnData(_, NotNull(), _, _)).Times(AtLeast(1)); 1182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ASSERT_TRUE(!!stream_); 1202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) stream_->Start(&input_callback_); 1212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) void CreateAndStartOneOutputStream() { 1242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ASSERT_TRUE(!!stream_); 125868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) AudioOutputStream* const output_stream = new VirtualAudioOutputStream( 126868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) kParams, 127868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) stream_, 128868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) base::Bind(&base::DeletePointer<VirtualAudioOutputStream>)); 1292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) output_streams_.push_back(output_stream); 1302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) output_stream->Open(); 1322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) output_stream->Start(&source_); 1332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) void Stop() { 1362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ASSERT_TRUE(!!stream_); 1372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) stream_->Stop(); 1382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) void Close() { 1412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ASSERT_TRUE(!!stream_); 1422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) stream_->Close(); 1432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) stream_ = NULL; 1442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) closed_stream_.Signal(); 1452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) void WaitForDataToFlow() { 1482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Wait until audio thread is idle before calling output_streams_.size(). 1492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SyncWithAudioThread(); 1502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const int count = output_streams_.size(); 1522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for (int i = 0; i < count; ++i) { 1532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) source_.WaitForDataPulls(); 1542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) input_callback_.WaitForDataPushes(); 1572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) void WaitUntilClosed() { 1602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) closed_stream_.Wait(); 1612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) void StopAndCloseOneOutputStream() { 1642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ASSERT_TRUE(!output_streams_.empty()); 1652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) AudioOutputStream* const output_stream = output_streams_.front(); 1662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ASSERT_TRUE(!!output_stream); 1672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) output_streams_.pop_front(); 1682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) output_stream->Stop(); 1702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) output_stream->Close(); 1712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) void StopFirstOutputStream() { 1742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ASSERT_TRUE(!output_streams_.empty()); 1752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) AudioOutputStream* const output_stream = output_streams_.front(); 1762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ASSERT_TRUE(!!output_stream); 1772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) output_streams_.pop_front(); 1782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) output_stream->Stop(); 1792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) stopped_output_streams_.push_back(output_stream); 1802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) void StopSomeOutputStreams() { 1832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ASSERT_LE(2, static_cast<int>(output_streams_.size())); 1842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for (int remaning = base::RandInt(1, output_streams_.size() - 1); 1852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) remaning > 0; --remaning) { 1862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) StopFirstOutputStream(); 1872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) void RestartAllStoppedOutputStreams() { 1912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) typedef std::list<AudioOutputStream*>::const_iterator ConstIter; 1922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for (ConstIter it = stopped_output_streams_.begin(); 1932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) it != stopped_output_streams_.end(); ++it) { 1942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) (*it)->Start(&source_); 1952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) output_streams_.push_back(*it); 1962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) stopped_output_streams_.clear(); 1982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const scoped_refptr<base::SingleThreadTaskRunner>& audio_task_runner() const { 2015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return audio_task_runner_; 2022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 2032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const scoped_refptr<base::SingleThreadTaskRunner>& GetWorkerTaskRunner( 205eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch bool worker_is_separate_thread) { 206eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch if (worker_is_separate_thread) { 207eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch if (!worker_thread_->IsRunning()) { 208eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch worker_thread_->Start(); 2095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) worker_task_runner_ = worker_thread_->message_loop_proxy(); 210eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch } 2115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return worker_task_runner_; 212eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch } else { 2135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return audio_task_runner_; 214eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch } 215eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch } 216eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 2172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) private: 2182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) void SyncWithAudioThread() { 2192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::WaitableEvent done(false, false); 2205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) audio_task_runner_->PostTask( 2212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) FROM_HERE, 2222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::Bind(&base::WaitableEvent::Signal, base::Unretained(&done))); 2232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) done.Wait(); 2242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 2252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) scoped_ptr<base::Thread> audio_thread_; 2275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) scoped_refptr<base::SingleThreadTaskRunner> audio_task_runner_; 228eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch scoped_ptr<base::Thread> worker_thread_; 2295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) scoped_refptr<base::SingleThreadTaskRunner> worker_task_runner_; 2302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) VirtualAudioInputStream* stream_; 2322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) MockInputCallback input_callback_; 2332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::WaitableEvent closed_stream_; 2342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) std::list<AudioOutputStream*> output_streams_; 2362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) std::list<AudioOutputStream*> stopped_output_streams_; 2372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) TestAudioSource source_; 2382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DISALLOW_COPY_AND_ASSIGN(VirtualAudioInputStreamTest); 2402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}; 2412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#define RUN_ON_AUDIO_THREAD(method) \ 2435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) audio_task_runner()->PostTask( \ 2442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) FROM_HERE, base::Bind(&VirtualAudioInputStreamTest::method, \ 2452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::Unretained(this))) 2462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 247eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochTEST_P(VirtualAudioInputStreamTest, CreateAndClose) { 2482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) RUN_ON_AUDIO_THREAD(Create); 2492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) RUN_ON_AUDIO_THREAD(Close); 2502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) WaitUntilClosed(); 2512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 2522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 253eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochTEST_P(VirtualAudioInputStreamTest, NoOutputs) { 2542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) RUN_ON_AUDIO_THREAD(Create); 2552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) RUN_ON_AUDIO_THREAD(Start); 2562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) WaitForDataToFlow(); 2572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) RUN_ON_AUDIO_THREAD(Stop); 2582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) RUN_ON_AUDIO_THREAD(Close); 2592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) WaitUntilClosed(); 2602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 2612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 262eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochTEST_P(VirtualAudioInputStreamTest, SingleOutput) { 2632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) RUN_ON_AUDIO_THREAD(Create); 2642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) RUN_ON_AUDIO_THREAD(Start); 2652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) RUN_ON_AUDIO_THREAD(CreateAndStartOneOutputStream); 2662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) WaitForDataToFlow(); 2672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) RUN_ON_AUDIO_THREAD(StopAndCloseOneOutputStream); 2682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) RUN_ON_AUDIO_THREAD(Stop); 2692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) RUN_ON_AUDIO_THREAD(Close); 2702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) WaitUntilClosed(); 2712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 2722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 273eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochTEST_P(VirtualAudioInputStreamTest, SingleOutputPausedAndRestarted) { 2742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) RUN_ON_AUDIO_THREAD(Create); 2752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) RUN_ON_AUDIO_THREAD(Start); 2762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) RUN_ON_AUDIO_THREAD(CreateAndStartOneOutputStream); 2772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) WaitForDataToFlow(); 2782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) RUN_ON_AUDIO_THREAD(StopFirstOutputStream); 2792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) RUN_ON_AUDIO_THREAD(RestartAllStoppedOutputStreams); 2802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) WaitForDataToFlow(); 2812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) RUN_ON_AUDIO_THREAD(StopAndCloseOneOutputStream); 2822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) RUN_ON_AUDIO_THREAD(Stop); 2832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) RUN_ON_AUDIO_THREAD(Close); 2842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) WaitUntilClosed(); 2852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 2862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 287eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochTEST_P(VirtualAudioInputStreamTest, MultipleOutputs) { 2882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) RUN_ON_AUDIO_THREAD(Create); 2892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) RUN_ON_AUDIO_THREAD(Start); 2902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) RUN_ON_AUDIO_THREAD(CreateAndStartOneOutputStream); 2912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) WaitForDataToFlow(); 2922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) RUN_ON_AUDIO_THREAD(CreateAndStartOneOutputStream); 2932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) RUN_ON_AUDIO_THREAD(CreateAndStartOneOutputStream); 2942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) WaitForDataToFlow(); 2952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) RUN_ON_AUDIO_THREAD(StopFirstOutputStream); 2962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) RUN_ON_AUDIO_THREAD(StopFirstOutputStream); 2972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) WaitForDataToFlow(); 2982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) RUN_ON_AUDIO_THREAD(StopFirstOutputStream); 2992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) RUN_ON_AUDIO_THREAD(RestartAllStoppedOutputStreams); 3002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) WaitForDataToFlow(); 3012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) RUN_ON_AUDIO_THREAD(StopAndCloseOneOutputStream); 3022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) RUN_ON_AUDIO_THREAD(StopAndCloseOneOutputStream); 3032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) RUN_ON_AUDIO_THREAD(Stop); 3042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) RUN_ON_AUDIO_THREAD(StopAndCloseOneOutputStream); 3052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) RUN_ON_AUDIO_THREAD(Close); 3062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) WaitUntilClosed(); 3072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 3082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// A combination of all of the above tests with many output streams. 310eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochTEST_P(VirtualAudioInputStreamTest, ComprehensiveTest) { 3112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) static const int kNumOutputs = 8; 3122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) static const int kHalfNumOutputs = kNumOutputs / 2; 3132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) static const int kPauseIterations = 5; 3142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) RUN_ON_AUDIO_THREAD(Create); 3162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for (int i = 0; i < kHalfNumOutputs; ++i) { 3172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) RUN_ON_AUDIO_THREAD(CreateAndStartOneOutputStream); 3182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 3192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) RUN_ON_AUDIO_THREAD(Start); 3202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) WaitForDataToFlow(); 3212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for (int i = 0; i < kHalfNumOutputs; ++i) { 3222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) RUN_ON_AUDIO_THREAD(CreateAndStartOneOutputStream); 3232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 3242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) WaitForDataToFlow(); 3252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for (int i = 0; i < kPauseIterations; ++i) { 3262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) RUN_ON_AUDIO_THREAD(StopSomeOutputStreams); 3272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) WaitForDataToFlow(); 3282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) RUN_ON_AUDIO_THREAD(RestartAllStoppedOutputStreams); 3292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) WaitForDataToFlow(); 3302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 3312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for (int i = 0; i < kHalfNumOutputs; ++i) { 3322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) RUN_ON_AUDIO_THREAD(StopAndCloseOneOutputStream); 3332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 3342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) RUN_ON_AUDIO_THREAD(Stop); 3352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for (int i = 0; i < kHalfNumOutputs; ++i) { 3362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) RUN_ON_AUDIO_THREAD(StopAndCloseOneOutputStream); 3372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 3382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) RUN_ON_AUDIO_THREAD(Close); 3392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) WaitUntilClosed(); 3402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 3412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 342eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochINSTANTIATE_TEST_CASE_P(SingleVersusMultithreaded, 343eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch VirtualAudioInputStreamTest, 344eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch ::testing::Values(false, true)); 345eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 3462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} // namespace media 347