virtual_audio_input_stream_unittest.cc revision 2a99a7e74a7f215066514fe81d2bfa6639d9eddd
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/message_loop.h" 102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/rand_util.h" 112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/synchronization/waitable_event.h" 122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/threading/thread.h" 132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "media/audio/audio_io.h" 142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "media/audio/simple_sources.h" 152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "media/audio/virtual_audio_input_stream.h" 162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "media/audio/virtual_audio_output_stream.h" 172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "testing/gmock/include/gmock/gmock.h" 182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "testing/gtest/include/gtest/gtest.h" 192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)using ::testing::_; 212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)using ::testing::AtLeast; 222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)using ::testing::InvokeWithoutArgs; 232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)using ::testing::NotNull; 242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace media { 262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace { 282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const AudioParameters kParams( 302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) AudioParameters::AUDIO_PCM_LOW_LATENCY, CHANNEL_LAYOUT_STEREO, 8000, 8, 10); 312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)class MockInputCallback : public AudioInputStream::AudioInputCallback { 332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) public: 342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) MockInputCallback() 352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) : data_pushed_(false, false) { 362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ON_CALL(*this, OnData(_, _, _, _, _)) 372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) .WillByDefault(InvokeWithoutArgs(&data_pushed_, 382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) &base::WaitableEvent::Signal)); 392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) virtual ~MockInputCallback() {} 422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) MOCK_METHOD5(OnData, void(AudioInputStream* stream, const uint8* data, 442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) uint32 size, uint32 hardware_delay_bytes, 452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) double volume)); 462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) MOCK_METHOD1(OnClose, void(AudioInputStream* stream)); 472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) MOCK_METHOD1(OnError, void(AudioInputStream* stream)); 482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) void WaitForDataPushes() { 502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for (int i = 0; i < 3; ++i) { 512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) data_pushed_.Wait(); 522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) private: 562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::WaitableEvent data_pushed_; 572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DISALLOW_COPY_AND_ASSIGN(MockInputCallback); 592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}; 602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)class TestAudioSource : public SineWaveAudioSource { 622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) public: 632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) TestAudioSource() 642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) : SineWaveAudioSource( 652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) kParams.channel_layout(), 200.0, kParams.sample_rate()), 662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) data_pulled_(false, false) {} 672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) virtual ~TestAudioSource() {} 692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) virtual int OnMoreData(AudioBus* audio_bus, 712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) AudioBuffersState audio_buffers) OVERRIDE { 722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const int ret = SineWaveAudioSource::OnMoreData(audio_bus, audio_buffers); 732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) data_pulled_.Signal(); 742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return ret; 752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) virtual int OnMoreIOData(AudioBus* source, 782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) AudioBus* dest, 792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) AudioBuffersState audio_buffers) OVERRIDE { 802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const int ret = 812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SineWaveAudioSource::OnMoreIOData(source, dest, audio_buffers); 822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) data_pulled_.Signal(); 832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return ret; 842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) void WaitForDataPulls() { 872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for (int i = 0; i < 3; ++i) { 882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) data_pulled_.Wait(); 892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) private: 932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::WaitableEvent data_pulled_; 942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DISALLOW_COPY_AND_ASSIGN(TestAudioSource); 962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}; 972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} // namespace 992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)class VirtualAudioInputStreamTest : public testing::Test { 1012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) public: 1022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) VirtualAudioInputStreamTest() 1032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) : audio_thread_(new base::Thread("AudioThread")), 1042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) stream_(NULL), 1052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) closed_stream_(false, false) { 1062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) audio_thread_->Start(); 1072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) audio_message_loop_ = audio_thread_->message_loop_proxy(); 1082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) virtual ~VirtualAudioInputStreamTest() { 1112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SyncWithAudioThread(); 1122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(output_streams_.empty()); 1142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(stopped_output_streams_.empty()); 1152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) void Create() { 1182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) stream_ = new VirtualAudioInputStream( 1192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) kParams, audio_message_loop_, 1202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::Bind(&base::DeletePointer<VirtualAudioInputStream>)); 1212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) stream_->Open(); 1222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) void Start() { 1252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) EXPECT_CALL(input_callback_, OnClose(_)); 1262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) EXPECT_CALL(input_callback_, OnData(_, NotNull(), _, _, _)) 1272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) .Times(AtLeast(1)); 1282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ASSERT_TRUE(!!stream_); 1302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) stream_->Start(&input_callback_); 1312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) void CreateAndStartOneOutputStream() { 1342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ASSERT_TRUE(!!stream_); 1352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) AudioOutputStream* const output_stream = 1362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) new VirtualAudioOutputStream( 1372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) kParams, audio_message_loop_, stream_, 1382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::Bind(&base::DeletePointer<VirtualAudioOutputStream>)); 1392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) output_streams_.push_back(output_stream); 1402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) output_stream->Open(); 1422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) output_stream->Start(&source_); 1432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) void Stop() { 1462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ASSERT_TRUE(!!stream_); 1472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) stream_->Stop(); 1482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) void Close() { 1512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ASSERT_TRUE(!!stream_); 1522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) stream_->Close(); 1532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) stream_ = NULL; 1542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) closed_stream_.Signal(); 1552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) void WaitForDataToFlow() { 1582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Wait until audio thread is idle before calling output_streams_.size(). 1592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SyncWithAudioThread(); 1602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const int count = output_streams_.size(); 1622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for (int i = 0; i < count; ++i) { 1632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) source_.WaitForDataPulls(); 1642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) input_callback_.WaitForDataPushes(); 1672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) void WaitUntilClosed() { 1702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) closed_stream_.Wait(); 1712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) void StopAndCloseOneOutputStream() { 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) 1792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) output_stream->Stop(); 1802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) output_stream->Close(); 1812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) void StopFirstOutputStream() { 1842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ASSERT_TRUE(!output_streams_.empty()); 1852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) AudioOutputStream* const output_stream = output_streams_.front(); 1862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ASSERT_TRUE(!!output_stream); 1872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) output_streams_.pop_front(); 1882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) output_stream->Stop(); 1892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) stopped_output_streams_.push_back(output_stream); 1902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) void StopSomeOutputStreams() { 1932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ASSERT_LE(2, static_cast<int>(output_streams_.size())); 1942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for (int remaning = base::RandInt(1, output_streams_.size() - 1); 1952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) remaning > 0; --remaning) { 1962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) StopFirstOutputStream(); 1972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) void RestartAllStoppedOutputStreams() { 2012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) typedef std::list<AudioOutputStream*>::const_iterator ConstIter; 2022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for (ConstIter it = stopped_output_streams_.begin(); 2032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) it != stopped_output_streams_.end(); ++it) { 2042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) (*it)->Start(&source_); 2052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) output_streams_.push_back(*it); 2062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 2072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) stopped_output_streams_.clear(); 2082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 2092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const scoped_refptr<base::MessageLoopProxy>& audio_message_loop() const { 2112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return audio_message_loop_; 2122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 2132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) private: 2152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) void SyncWithAudioThread() { 2162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::WaitableEvent done(false, false); 2172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) audio_message_loop_->PostTask( 2182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) FROM_HERE, 2192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::Bind(&base::WaitableEvent::Signal, base::Unretained(&done))); 2202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) done.Wait(); 2212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 2222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) scoped_ptr<base::Thread> audio_thread_; 2242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) scoped_refptr<base::MessageLoopProxy> audio_message_loop_; 2252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) VirtualAudioInputStream* stream_; 2272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) MockInputCallback input_callback_; 2282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::WaitableEvent closed_stream_; 2292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) std::list<AudioOutputStream*> output_streams_; 2312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) std::list<AudioOutputStream*> stopped_output_streams_; 2322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) TestAudioSource source_; 2332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DISALLOW_COPY_AND_ASSIGN(VirtualAudioInputStreamTest); 2352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}; 2362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#define RUN_ON_AUDIO_THREAD(method) \ 2382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) audio_message_loop()->PostTask( \ 2392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) FROM_HERE, base::Bind(&VirtualAudioInputStreamTest::method, \ 2402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::Unretained(this))) 2412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TEST_F(VirtualAudioInputStreamTest, CreateAndClose) { 2432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) RUN_ON_AUDIO_THREAD(Create); 2442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) RUN_ON_AUDIO_THREAD(Close); 2452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) WaitUntilClosed(); 2462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 2472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TEST_F(VirtualAudioInputStreamTest, NoOutputs) { 2492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) RUN_ON_AUDIO_THREAD(Create); 2502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) RUN_ON_AUDIO_THREAD(Start); 2512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) WaitForDataToFlow(); 2522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) RUN_ON_AUDIO_THREAD(Stop); 2532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) RUN_ON_AUDIO_THREAD(Close); 2542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) WaitUntilClosed(); 2552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 2562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TEST_F(VirtualAudioInputStreamTest, SingleOutput) { 2582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) RUN_ON_AUDIO_THREAD(Create); 2592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) RUN_ON_AUDIO_THREAD(Start); 2602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) RUN_ON_AUDIO_THREAD(CreateAndStartOneOutputStream); 2612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) WaitForDataToFlow(); 2622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) RUN_ON_AUDIO_THREAD(StopAndCloseOneOutputStream); 2632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) RUN_ON_AUDIO_THREAD(Stop); 2642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) RUN_ON_AUDIO_THREAD(Close); 2652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) WaitUntilClosed(); 2662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 2672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TEST_F(VirtualAudioInputStreamTest, SingleOutputPausedAndRestarted) { 2692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) RUN_ON_AUDIO_THREAD(Create); 2702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) RUN_ON_AUDIO_THREAD(Start); 2712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) RUN_ON_AUDIO_THREAD(CreateAndStartOneOutputStream); 2722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) WaitForDataToFlow(); 2732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) RUN_ON_AUDIO_THREAD(StopFirstOutputStream); 2742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) RUN_ON_AUDIO_THREAD(RestartAllStoppedOutputStreams); 2752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) WaitForDataToFlow(); 2762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) RUN_ON_AUDIO_THREAD(StopAndCloseOneOutputStream); 2772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) RUN_ON_AUDIO_THREAD(Stop); 2782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) RUN_ON_AUDIO_THREAD(Close); 2792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) WaitUntilClosed(); 2802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 2812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TEST_F(VirtualAudioInputStreamTest, MultipleOutputs) { 2832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) RUN_ON_AUDIO_THREAD(Create); 2842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) RUN_ON_AUDIO_THREAD(Start); 2852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) RUN_ON_AUDIO_THREAD(CreateAndStartOneOutputStream); 2862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) WaitForDataToFlow(); 2872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) RUN_ON_AUDIO_THREAD(CreateAndStartOneOutputStream); 2882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) RUN_ON_AUDIO_THREAD(CreateAndStartOneOutputStream); 2892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) WaitForDataToFlow(); 2902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) RUN_ON_AUDIO_THREAD(StopFirstOutputStream); 2912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) RUN_ON_AUDIO_THREAD(StopFirstOutputStream); 2922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) WaitForDataToFlow(); 2932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) RUN_ON_AUDIO_THREAD(StopFirstOutputStream); 2942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) RUN_ON_AUDIO_THREAD(RestartAllStoppedOutputStreams); 2952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) WaitForDataToFlow(); 2962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) RUN_ON_AUDIO_THREAD(StopAndCloseOneOutputStream); 2972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) RUN_ON_AUDIO_THREAD(StopAndCloseOneOutputStream); 2982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) RUN_ON_AUDIO_THREAD(Stop); 2992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) RUN_ON_AUDIO_THREAD(StopAndCloseOneOutputStream); 3002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) RUN_ON_AUDIO_THREAD(Close); 3012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) WaitUntilClosed(); 3022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 3032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// A combination of all of the above tests with many output streams. 3052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TEST_F(VirtualAudioInputStreamTest, ComprehensiveTest) { 3062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) static const int kNumOutputs = 8; 3072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) static const int kHalfNumOutputs = kNumOutputs / 2; 3082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) static const int kPauseIterations = 5; 3092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) RUN_ON_AUDIO_THREAD(Create); 3112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for (int i = 0; i < kHalfNumOutputs; ++i) { 3122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) RUN_ON_AUDIO_THREAD(CreateAndStartOneOutputStream); 3132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 3142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) RUN_ON_AUDIO_THREAD(Start); 3152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) WaitForDataToFlow(); 3162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for (int i = 0; i < kHalfNumOutputs; ++i) { 3172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) RUN_ON_AUDIO_THREAD(CreateAndStartOneOutputStream); 3182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 3192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) WaitForDataToFlow(); 3202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for (int i = 0; i < kPauseIterations; ++i) { 3212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) RUN_ON_AUDIO_THREAD(StopSomeOutputStreams); 3222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) WaitForDataToFlow(); 3232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) RUN_ON_AUDIO_THREAD(RestartAllStoppedOutputStreams); 3242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) WaitForDataToFlow(); 3252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 3262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for (int i = 0; i < kHalfNumOutputs; ++i) { 3272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) RUN_ON_AUDIO_THREAD(StopAndCloseOneOutputStream); 3282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 3292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) RUN_ON_AUDIO_THREAD(Stop); 3302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for (int i = 0; i < kHalfNumOutputs; ++i) { 3312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) RUN_ON_AUDIO_THREAD(StopAndCloseOneOutputStream); 3322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 3332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) RUN_ON_AUDIO_THREAD(Close); 3342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) WaitUntilClosed(); 3352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 3362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} // namespace media 338