diff options
author | miu@chromium.org <miu@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-01-15 23:24:26 +0000 |
---|---|---|
committer | miu@chromium.org <miu@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-01-15 23:24:26 +0000 |
commit | 4451e7a22d8264f53fd2d2f62a6c5dbacbe1e69f (patch) | |
tree | 901ee492ff8b6a97f2fdfffc397d2f50835710e5 /media/audio/virtual_audio_input_stream_unittest.cc | |
parent | 5a8bb129afab85ae5f0922fccadfbe8bee0eebcf (diff) | |
download | chromium_src-4451e7a22d8264f53fd2d2f62a6c5dbacbe1e69f.zip chromium_src-4451e7a22d8264f53fd2d2f62a6c5dbacbe1e69f.tar.gz chromium_src-4451e7a22d8264f53fd2d2f62a6c5dbacbe1e69f.tar.bz2 |
Bug fix: Bypass dispatcher output stream caching scheme for virtual output streams in AudioManagerBase.
Reworked unit tests in virtual_audio_input_stream_unittest.cc, and confirmed the VirtualAudioInputStreamTest.PausedOutputStreamReconnectsToRealDevice test crashes without the bug fix in audio_manager_base.cc.
BUG=167920
TEST=Run media_unittests --gtest_filter='VirtualAudioInputStreamTest.*'
Review URL: https://chromiumcodereview.appspot.com/11778085
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@177008 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'media/audio/virtual_audio_input_stream_unittest.cc')
-rw-r--r-- | media/audio/virtual_audio_input_stream_unittest.cc | 557 |
1 files changed, 314 insertions, 243 deletions
diff --git a/media/audio/virtual_audio_input_stream_unittest.cc b/media/audio/virtual_audio_input_stream_unittest.cc index b47b814..93b4b01 100644 --- a/media/audio/virtual_audio_input_stream_unittest.cc +++ b/media/audio/virtual_audio_input_stream_unittest.cc @@ -2,321 +2,392 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include <vector> +#include <list> #include "base/message_loop.h" +#include "base/rand_util.h" #include "base/synchronization/waitable_event.h" +#include "media/audio/audio_io.h" #include "media/audio/audio_manager.h" #include "media/audio/simple_sources.h" #include "media/audio/virtual_audio_input_stream.h" +#include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" +using ::testing::_; +using ::testing::AtLeast; +using ::testing::InvokeWithoutArgs; +using ::testing::NotNull; + namespace media { +namespace { + class MockInputCallback : public AudioInputStream::AudioInputCallback { public: - MockInputCallback() {} - virtual void OnData(AudioInputStream* stream, const uint8* data, - uint32 size, uint32 hardware_delay_bytes, - double volume) {} - virtual void OnClose(AudioInputStream* stream) {} - virtual void OnError(AudioInputStream* stream, int code) {} + MockInputCallback() + : data_pushed_(false, false) { + ON_CALL(*this, OnData(_, _, _, _, _)) + .WillByDefault(InvokeWithoutArgs(&data_pushed_, + &base::WaitableEvent::Signal)); + } + + virtual ~MockInputCallback() {} + + MOCK_METHOD5(OnData, void(AudioInputStream* stream, const uint8* data, + uint32 size, uint32 hardware_delay_bytes, + double volume)); + MOCK_METHOD1(OnClose, void(AudioInputStream* stream)); + MOCK_METHOD2(OnError, void(AudioInputStream* stream, int code)); + + void WaitForDataPushes() { + for (int i = 0; i < 3; ++i) { + data_pushed_.Wait(); + } + } private: + base::WaitableEvent data_pushed_; + DISALLOW_COPY_AND_ASSIGN(MockInputCallback); }; -class VirtualAudioInputStreamTest : public testing::Test { +class TestAudioSource : public SineWaveAudioSource { + public: + TestAudioSource() + : SineWaveAudioSource(CHANNEL_LAYOUT_STEREO, 200.0, 8000.0), + data_pulled_(false, false) {} + + virtual ~TestAudioSource() {} + + virtual int OnMoreData(AudioBus* audio_bus, + AudioBuffersState audio_buffers) OVERRIDE { + const int ret = SineWaveAudioSource::OnMoreData(audio_bus, audio_buffers); + data_pulled_.Signal(); + return ret; + } + + virtual int OnMoreIOData(AudioBus* source, + AudioBus* dest, + AudioBuffersState audio_buffers) OVERRIDE { + const int ret = + SineWaveAudioSource::OnMoreIOData(source, dest, audio_buffers); + data_pulled_.Signal(); + return ret; + } + + void WaitForDataPulls() { + for (int i = 0; i < 3; ++i) { + data_pulled_.Wait(); + } + } + + private: + base::WaitableEvent data_pulled_; + + DISALLOW_COPY_AND_ASSIGN(TestAudioSource); +}; + +} // namespace + +class VirtualAudioInputStreamTest + : public testing::Test, + public AudioManager::AudioDeviceListener { public: VirtualAudioInputStreamTest() : audio_manager_(AudioManager::Create()), - params_( - AudioParameters::AUDIO_VIRTUAL,CHANNEL_LAYOUT_MONO, 8000, 8, 128), - output_params_( - AudioParameters::AUDIO_FAKE, CHANNEL_LAYOUT_MONO, 8000, 8, 128), + params_(AudioParameters::AUDIO_VIRTUAL, CHANNEL_LAYOUT_STEREO, 8000, 8, + 10), + output_params_(AudioParameters::AUDIO_FAKE, CHANNEL_LAYOUT_STEREO, 8000, + 8, 10), stream_(NULL), - source_(CHANNEL_LAYOUT_STEREO, 200.0, 128), - done_(false, false) { + closed_stream_(false, false) { + audio_manager_->GetMessageLoop()->PostTask( + FROM_HERE, + base::Bind(&AudioManager::AddOutputDeviceChangeListener, + base::Unretained(audio_manager_.get()), + this)); + } + + ~VirtualAudioInputStreamTest() { + audio_manager_->GetMessageLoop()->PostTask( + FROM_HERE, + base::Bind(&AudioManager::RemoveOutputDeviceChangeListener, + base::Unretained(audio_manager_.get()), + this)); + + SyncWithAudioThread(); + + DCHECK(output_streams_.empty()); + DCHECK(stopped_output_streams_.empty()); } - void CreateAndOpenVirtualAudioInputStream() { + void Create() { stream_ = static_cast<VirtualAudioInputStream*>( audio_manager_->MakeAudioInputStream(params_, "1")); ASSERT_TRUE(!!stream_); stream_->Open(); } - void StartStreamAndRunTestsOnAudioThread(int num_output_streams, - int num_callback_iterations, - int num_streams_removed_per_round, - int num_expected_source_callbacks) { - ASSERT_TRUE(audio_manager_->GetMessageLoop()->BelongsToCurrentThread()); - CreateAndOpenVirtualAudioInputStream(); + void Start() { + EXPECT_CALL(input_callback_, OnClose(_)); + EXPECT_CALL(input_callback_, OnData(_, NotNull(), _, _, _)) + .Times(AtLeast(1)); + + ASSERT_TRUE(!!stream_); stream_->Start(&input_callback_); - AddStreamsAndDoCallbacks(num_output_streams, - num_callback_iterations, - num_streams_removed_per_round, - num_expected_source_callbacks); } - void AddStreamsAndDoCallbacks(int num_output_streams, - int num_callback_iterations, - int num_streams_removed_per_round, - int num_expected_source_callbacks) { - ASSERT_TRUE(audio_manager_->GetMessageLoop()->BelongsToCurrentThread()); + void CreateAndStartOneOutputStream() { + AudioOutputStream* const output_stream = + audio_manager_->MakeAudioOutputStreamProxy(output_params_); + ASSERT_TRUE(!!output_stream); + output_streams_.push_back(output_stream); - for (int i = 0; i < num_output_streams; ++i) { - AudioOutputStream* output_stream = - audio_manager_->MakeAudioOutputStream(output_params_); - DCHECK(output_stream); - output_streams_.push_back(output_stream); + output_stream->Open(); + output_stream->Start(&source_); + } - output_stream->Open(); - output_stream->Start(&source_); - } + void Stop() { + ASSERT_TRUE(!!stream_); + stream_->Stop(); + } - if (num_output_streams == 0 && num_streams_removed_per_round > 0) { - AudioOutputStream* output_stream = output_streams_.back(); - output_streams_.pop_back(); - output_stream->Stop(); - output_stream->Close(); - } + void Close() { + ASSERT_TRUE(!!stream_); + stream_->Close(); + stream_ = NULL; + closed_stream_.Signal(); + } - if (num_callback_iterations > 0) { - // Force the next callback to be immediate. - stream_->buffer_duration_ms_ = base::TimeDelta(); - audio_manager_->GetMessageLoop()->PostTask( - FROM_HERE, base::Bind( - &VirtualAudioInputStreamTest::AddStreamsAndDoCallbacks, - base::Unretained(this), - 0, - --num_callback_iterations, - num_streams_removed_per_round, - num_expected_source_callbacks)); - } else { - // Finish the test. - EXPECT_EQ(num_expected_source_callbacks, source_.callbacks()); - EXPECT_EQ(0, source_.errors()); - - for (std::vector<AudioOutputStream*>::iterator it = - output_streams_.begin(); it != output_streams_.end(); ++it) - (*it)->Stop(); - - stream_->Stop(); - - audio_manager_->GetMessageLoop()->PostTask( - FROM_HERE, base::Bind(&VirtualAudioInputStreamTest::EndTest, - base::Unretained(this))); + void WaitForDataPulls() { + const int count = output_streams_.size(); + for (int i = 0; i < count; ++i) { + source_.WaitForDataPulls(); } } - void OpenAndCloseOnAudioThread() { - ASSERT_TRUE(audio_manager_->GetMessageLoop()->BelongsToCurrentThread()); - CreateAndOpenVirtualAudioInputStream(); - - // Create 2 output streams, which we just open and close without starting. - const int num_output_stream = 2; + void WaitForDataPushes() { + input_callback_.WaitForDataPushes(); + } - for (int i = 0; i < num_output_stream; ++i) { - AudioOutputStream* output_stream = - audio_manager_->MakeAudioOutputStream(output_params_); - DCHECK(output_stream); - output_streams_.push_back(output_stream); + void WaitUntilClosed() { + closed_stream_.Wait(); + } - output_stream->Open(); - } + void StopAndCloseOneOutputStream() { + ASSERT_TRUE(!output_streams_.empty()); + AudioOutputStream* const output_stream = output_streams_.front(); + ASSERT_TRUE(!!output_stream); + output_streams_.pop_front(); - audio_manager_->GetMessageLoop()->PostTask( - FROM_HERE, base::Bind(&VirtualAudioInputStreamTest::EndTest, - base::Unretained(this))); + output_stream->Stop(); + output_stream->Close(); } - void StartStopOnAudioThread(int num_output_streams, - int num_callback_iterations, - int num_expected_source_callbacks) { - ASSERT_TRUE(audio_manager_->GetMessageLoop()->BelongsToCurrentThread()); - CreateAndOpenVirtualAudioInputStream(); - stream_->Start(&input_callback_); - StartStopCallback(true, num_output_streams, num_callback_iterations, - num_expected_source_callbacks); + void StopFirstOutputStream() { + ASSERT_TRUE(!output_streams_.empty()); + AudioOutputStream* const output_stream = output_streams_.front(); + ASSERT_TRUE(!!output_stream); + output_streams_.pop_front(); + output_stream->Stop(); + stopped_output_streams_.push_back(output_stream); } - void StartStopCallback(bool init, - int num_output_streams, - int num_callback_iterations, - int num_expected_source_callbacks) { - ASSERT_TRUE(audio_manager_->GetMessageLoop()->BelongsToCurrentThread()); - - if (init) { - for (int i = 0; i < num_output_streams; ++i) { - AudioOutputStream* output_stream = - audio_manager_->MakeAudioOutputStream(output_params_); - DCHECK(output_stream); - output_streams_.push_back(output_stream); - - output_stream->Open(); - output_stream->Start(&source_); - } - - // Start with an odd iteration number so we call Stop() first below. - DCHECK_NE(0, num_callback_iterations % 2); - } - - // Start or stop half the streams. - for (int i = 0; i < num_output_streams / 2; ++i) { - if (num_callback_iterations % 2 != 0) - output_streams_[i]->Stop(); - else - output_streams_[i]->Start(&source_); + void StopSomeOutputStreams() { + ASSERT_LE(1, static_cast<int>(output_streams_.size())); + for (int remaning = base::RandInt(1, output_streams_.size() - 1); + remaning > 0; --remaning) { + StopFirstOutputStream(); } + } - if (num_callback_iterations > 0) { - // Force the next callback to be immediate. - stream_->buffer_duration_ms_ = base::TimeDelta::FromMilliseconds(0); - audio_manager_->GetMessageLoop()->PostTask( - FROM_HERE, base::Bind( - &VirtualAudioInputStreamTest::StartStopCallback, - base::Unretained(this), - false, - num_output_streams, - --num_callback_iterations, - num_expected_source_callbacks)); - } else { - // Finish the test. - EXPECT_EQ(num_expected_source_callbacks, source_.callbacks()); - EXPECT_EQ(0, source_.errors()); - - for (std::vector<AudioOutputStream*>::iterator it = - output_streams_.begin(); it != output_streams_.end(); ++it) - (*it)->Stop(); - - stream_->Stop(); - - audio_manager_->GetMessageLoop()->PostTask(FROM_HERE, - base::Bind(&VirtualAudioInputStreamTest::EndTest, - base::Unretained(this))); + void RestartAllStoppedOutputStreams() { + typedef std::list<AudioOutputStream*>::const_iterator ConstIter; + for (ConstIter it = stopped_output_streams_.begin(); + it != stopped_output_streams_.end(); ++it) { + (*it)->Start(&source_); + output_streams_.push_back(*it); } + stopped_output_streams_.clear(); } - void EndTest() { - for (std::vector<AudioOutputStream*>::iterator it = - output_streams_.begin(); it != output_streams_.end(); ++it) - (*it)->Close(); + AudioManager* audio_manager() const { return audio_manager_.get(); } - stream_->Close(); + private: + virtual void OnDeviceChange() OVERRIDE { + audio_manager_->RemoveOutputDeviceChangeListener(this); + + // Simulate each AudioOutputController closing and re-opening a stream, in + // turn. + for (int remaining = output_streams_.size(); remaining > 0; --remaining) { + StopAndCloseOneOutputStream(); + CreateAndStartOneOutputStream(); + } + for (int remaining = stopped_output_streams_.size(); remaining > 0; + --remaining) { + AudioOutputStream* stream = stopped_output_streams_.front(); + stopped_output_streams_.pop_front(); + stream->Close(); + + stream = audio_manager_->MakeAudioOutputStreamProxy(output_params_); + ASSERT_TRUE(!!stream); + stopped_output_streams_.push_back(stream); + stream->Open(); + } + + audio_manager_->AddOutputDeviceChangeListener(this); + } - done_.Signal(); + void SyncWithAudioThread() { + base::WaitableEvent done(false, false); + audio_manager_->GetMessageLoop()->PostTask( + FROM_HERE, + base::Bind(&base::WaitableEvent::Signal, base::Unretained(&done))); + done.Wait(); } - protected: - scoped_ptr<AudioManager> audio_manager_; - AudioParameters params_; - AudioParameters output_params_; + const scoped_ptr<AudioManager> audio_manager_; + const AudioParameters params_; + const AudioParameters output_params_; + VirtualAudioInputStream* stream_; MockInputCallback input_callback_; - std::vector<AudioOutputStream*> output_streams_; - SineWaveAudioSource source_; - base::WaitableEvent done_; + base::WaitableEvent closed_stream_; + + std::list<AudioOutputStream*> output_streams_; + std::list<AudioOutputStream*> stopped_output_streams_; + TestAudioSource source_; - private: DISALLOW_COPY_AND_ASSIGN(VirtualAudioInputStreamTest); }; -TEST_F(VirtualAudioInputStreamTest, AttachAndDriveSingleStream) { - const int num_output_streams = 1; - const int num_callback_iterations = 1; - const int num_streams_removed_per_round = 0; - const int num_expected_source_callbacks = 1; - - audio_manager_->GetMessageLoop()->PostTask( - FROM_HERE, base::Bind( - &VirtualAudioInputStreamTest::StartStreamAndRunTestsOnAudioThread, - base::Unretained(this), - num_output_streams, - num_callback_iterations, - num_streams_removed_per_round, - num_expected_source_callbacks)); - - done_.Wait(); -} +#define RUN_ON_AUDIO_THREAD(method) \ + audio_manager()->GetMessageLoop()->PostTask( \ + FROM_HERE, base::Bind(&VirtualAudioInputStreamTest::method, \ + base::Unretained(this))) -TEST_F(VirtualAudioInputStreamTest, AttachAndDriveMultipleStreams) { - const int num_output_streams = 5; - const int num_callback_iterations = 5; - const int num_streams_removed_per_round = 0; - const int num_expected_source_callbacks = 25; - - audio_manager_->GetMessageLoop()->PostTask( - FROM_HERE, base::Bind( - &VirtualAudioInputStreamTest::StartStreamAndRunTestsOnAudioThread, - base::Unretained(this), - num_output_streams, - num_callback_iterations, - num_streams_removed_per_round, - num_expected_source_callbacks)); - - done_.Wait(); +// Creates and closes and VirtualAudioInputStream. +TEST_F(VirtualAudioInputStreamTest, CreateAndClose) { + RUN_ON_AUDIO_THREAD(Create); + RUN_ON_AUDIO_THREAD(Close); + WaitUntilClosed(); } -TEST_F(VirtualAudioInputStreamTest, AttachAndRemoveStreams) { - const int num_output_streams = 8; - const int num_callback_iterations = 5; - const int num_streams_removed_per_round = 1; - const int num_expected_source_callbacks = 8 + 7 + 6 + 5 + 4; - - audio_manager_->GetMessageLoop()->PostTask( - FROM_HERE, base::Bind( - &VirtualAudioInputStreamTest::StartStreamAndRunTestsOnAudioThread, - base::Unretained(this), - num_output_streams, - num_callback_iterations, - num_streams_removed_per_round, - num_expected_source_callbacks)); - - done_.Wait(); +// Tests a session where one output is created and destroyed within. +TEST_F(VirtualAudioInputStreamTest, SingleOutputWithinSession) { + RUN_ON_AUDIO_THREAD(Create); + RUN_ON_AUDIO_THREAD(Start); + RUN_ON_AUDIO_THREAD(CreateAndStartOneOutputStream); + WaitForDataPulls(); // Confirm data is being pulled (rendered). + WaitForDataPushes(); // Confirm mirrored data is being pushed. + RUN_ON_AUDIO_THREAD(StopAndCloseOneOutputStream); + RUN_ON_AUDIO_THREAD(Stop); + RUN_ON_AUDIO_THREAD(Close); + WaitUntilClosed(); } -// Opens/closes a VirtualAudioInputStream and a number of attached -// VirtualAudioOutputStreams without calling Start()/Stop(). -TEST_F(VirtualAudioInputStreamTest, OpenAndClose) { - audio_manager_->GetMessageLoop()->PostTask( - FROM_HERE, base::Bind( - &VirtualAudioInputStreamTest::OpenAndCloseOnAudioThread, - base::Unretained(this))); - - done_.Wait(); +// Tests a session where one output existed before and afterwards. +TEST_F(VirtualAudioInputStreamTest, SingleLongLivedOutput) { + RUN_ON_AUDIO_THREAD(CreateAndStartOneOutputStream); + WaitForDataPulls(); // Confirm data is flowing out before the session. + RUN_ON_AUDIO_THREAD(Create); + RUN_ON_AUDIO_THREAD(Start); + WaitForDataPushes(); + RUN_ON_AUDIO_THREAD(Stop); + RUN_ON_AUDIO_THREAD(Close); + WaitUntilClosed(); + WaitForDataPulls(); // Confirm data is still flowing out. + RUN_ON_AUDIO_THREAD(StopAndCloseOneOutputStream); } -// Creates and closes and VirtualAudioInputStream. -TEST_F(VirtualAudioInputStreamTest, CreateAndClose) { - audio_manager_->GetMessageLoop()->PostTask( - FROM_HERE, base::Bind( - &VirtualAudioInputStreamTest::CreateAndOpenVirtualAudioInputStream, - base::Unretained(this))); +TEST_F(VirtualAudioInputStreamTest, SingleOutputPausedWithinSession) { + RUN_ON_AUDIO_THREAD(Create); + RUN_ON_AUDIO_THREAD(Start); + RUN_ON_AUDIO_THREAD(CreateAndStartOneOutputStream); + WaitForDataPulls(); + WaitForDataPushes(); + RUN_ON_AUDIO_THREAD(StopFirstOutputStream); + RUN_ON_AUDIO_THREAD(RestartAllStoppedOutputStreams); + WaitForDataPulls(); + WaitForDataPushes(); + RUN_ON_AUDIO_THREAD(StopAndCloseOneOutputStream); + RUN_ON_AUDIO_THREAD(Stop); + RUN_ON_AUDIO_THREAD(Close); + WaitUntilClosed(); +} - audio_manager_->GetMessageLoop()->PostTask( - FROM_HERE, base::Bind(&VirtualAudioInputStreamTest::EndTest, - base::Unretained(this))); +TEST_F(VirtualAudioInputStreamTest, OutputStreamsReconnectToRealDevices) { + RUN_ON_AUDIO_THREAD(CreateAndStartOneOutputStream); + WaitForDataPulls(); + RUN_ON_AUDIO_THREAD(Create); + RUN_ON_AUDIO_THREAD(Start); + WaitForDataPushes(); + RUN_ON_AUDIO_THREAD(CreateAndStartOneOutputStream); + WaitForDataPulls(); + WaitForDataPushes(); + RUN_ON_AUDIO_THREAD(Stop); + RUN_ON_AUDIO_THREAD(Close); + WaitUntilClosed(); + WaitForDataPulls(); + RUN_ON_AUDIO_THREAD(StopAndCloseOneOutputStream); + RUN_ON_AUDIO_THREAD(StopAndCloseOneOutputStream); +} - done_.Wait(); +TEST_F(VirtualAudioInputStreamTest, PausedOutputStreamReconnectsToRealDevice) { + RUN_ON_AUDIO_THREAD(CreateAndStartOneOutputStream); + WaitForDataPulls(); + RUN_ON_AUDIO_THREAD(Create); + RUN_ON_AUDIO_THREAD(Start); + WaitForDataPushes(); + RUN_ON_AUDIO_THREAD(CreateAndStartOneOutputStream); + WaitForDataPulls(); + WaitForDataPushes(); + RUN_ON_AUDIO_THREAD(StopFirstOutputStream); + WaitForDataPulls(); + WaitForDataPushes(); + RUN_ON_AUDIO_THREAD(Stop); + RUN_ON_AUDIO_THREAD(Close); + WaitUntilClosed(); + WaitForDataPulls(); + RUN_ON_AUDIO_THREAD(RestartAllStoppedOutputStreams); + WaitForDataPulls(); + RUN_ON_AUDIO_THREAD(StopAndCloseOneOutputStream); + RUN_ON_AUDIO_THREAD(StopAndCloseOneOutputStream); } -// Starts and stops VirtualAudioOutputStreams while attached to a -// VirtualAudioInputStream. -TEST_F(VirtualAudioInputStreamTest, AttachAndStartStopStreams) { - const int num_output_streams = 4; - const int num_callback_iterations = 5; - const int num_expected_source_callbacks = 2 + 4 + 2 + 4 + 2; - - audio_manager_->GetMessageLoop()->PostTask( - FROM_HERE, base::Bind( - &VirtualAudioInputStreamTest::StartStopOnAudioThread, - base::Unretained(this), - num_output_streams, - num_callback_iterations, - num_expected_source_callbacks)); - - done_.Wait(); +// A combination of all of the above tests with many output streams. +TEST_F(VirtualAudioInputStreamTest, ComprehensiveTest) { + static const int kNumOutputs = 8; + static const int kPauseIterations = 5; + + for (int i = 0; i < kNumOutputs / 2; ++i) { + RUN_ON_AUDIO_THREAD(CreateAndStartOneOutputStream); + } + WaitForDataPulls(); + RUN_ON_AUDIO_THREAD(Create); + RUN_ON_AUDIO_THREAD(Start); + WaitForDataPushes(); + for (int i = 0; i < kNumOutputs / 2; ++i) { + RUN_ON_AUDIO_THREAD(CreateAndStartOneOutputStream); + } + WaitForDataPulls(); + WaitForDataPushes(); + for (int i = 0; i < kPauseIterations; ++i) { + RUN_ON_AUDIO_THREAD(StopSomeOutputStreams); + WaitForDataPulls(); + WaitForDataPushes(); + RUN_ON_AUDIO_THREAD(RestartAllStoppedOutputStreams); + WaitForDataPulls(); + WaitForDataPushes(); + } + RUN_ON_AUDIO_THREAD(Stop); + RUN_ON_AUDIO_THREAD(Close); + WaitUntilClosed(); + WaitForDataPulls(); + for (int i = 0; i < kNumOutputs; ++i) { + RUN_ON_AUDIO_THREAD(StopAndCloseOneOutputStream); + } } } // namespace media |