webrtc_local_audio_track_unittest.cc revision 7d4cd473f85ac64c3747c96c277f9e506a0d2246
1c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Copyright 2013 The Chromium Authors. All rights reserved. 2c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 3c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// found in the LICENSE file. 4c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 5c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "base/synchronization/waitable_event.h" 6c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "base/test/test_timeouts.h" 7c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "content/renderer/media/webrtc_audio_capturer.h" 8c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "content/renderer/media/webrtc_local_audio_track.h" 9c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "media/audio/audio_parameters.h" 10c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "media/base/audio_bus.h" 11c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "media/base/audio_capturer_source.h" 12c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "testing/gmock/include/gmock/gmock.h" 13c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "testing/gtest/include/gtest/gtest.h" 14c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 15c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)using ::testing::_; 167d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)using ::testing::AnyNumber; 17c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)using ::testing::AtLeast; 18c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)using ::testing::Return; 19c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 20c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)namespace content { 21c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 22c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)namespace { 23c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 24c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)ACTION_P(SignalEvent, event) { 25c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) event->Signal(); 26c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 27c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 28c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// A simple thread that we use to fake the audio thread which provides data to 29c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// the |WebRtcAudioCapturer|. 30c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)class FakeAudioThread : public base::PlatformThread::Delegate { 31c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) public: 32c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) explicit FakeAudioThread(const scoped_refptr<WebRtcAudioCapturer>& capturer) 33c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) : capturer_(capturer), 3490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) thread_(), 35c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) closure_(false, false) { 36868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) DCHECK(capturer.get()); 37c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) audio_bus_ = media::AudioBus::Create(capturer_->audio_parameters()); 38c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 39c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 4090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) virtual ~FakeAudioThread() { DCHECK(thread_.is_null()); } 41c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 42c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // base::PlatformThread::Delegate: 43c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) virtual void ThreadMain() OVERRIDE { 44c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) while (true) { 45c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (closure_.IsSignaled()) 46c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return; 47c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 48c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) media::AudioCapturerSource::CaptureCallback* callback = 49868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) static_cast<media::AudioCapturerSource::CaptureCallback*>( 50868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) capturer_.get()); 51c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) audio_bus_->Zero(); 52c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) callback->Capture(audio_bus_.get(), 0, 0); 53c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 54c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Sleep 1ms to yield the resource for the main thread. 55c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(1)); 56c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 57c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 58c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 59c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) void Start() { 60c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base::PlatformThread::CreateWithPriority( 61c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 0, this, &thread_, base::kThreadPriority_RealtimeAudio); 6290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) CHECK(!thread_.is_null()); 63c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 64c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 65c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) void Stop() { 66c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) closure_.Signal(); 67c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base::PlatformThread::Join(thread_); 6890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) thread_ = base::PlatformThreadHandle(); 69c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 70c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 71c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) private: 72c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) scoped_ptr<media::AudioBus> audio_bus_; 73c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) scoped_refptr<WebRtcAudioCapturer> capturer_; 74c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base::PlatformThreadHandle thread_; 75c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base::WaitableEvent closure_; 76c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DISALLOW_COPY_AND_ASSIGN(FakeAudioThread); 77c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}; 78c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 79c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)class MockCapturerSource : public media::AudioCapturerSource { 80c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) public: 81c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) MockCapturerSource() {} 82c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) MOCK_METHOD3(Initialize, void(const media::AudioParameters& params, 83c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) CaptureCallback* callback, 84c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) int session_id)); 85c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) MOCK_METHOD0(Start, void()); 86c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) MOCK_METHOD0(Stop, void()); 87c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) MOCK_METHOD1(SetVolume, void(double volume)); 88c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) MOCK_METHOD1(SetAutomaticGainControl, void(bool enable)); 89c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 90c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) protected: 91c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) virtual ~MockCapturerSource() {} 92c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}; 93c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 94c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)class MockWebRtcAudioCapturerSink : public WebRtcAudioCapturerSink { 95c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) public: 96c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) MockWebRtcAudioCapturerSink() {} 97c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) ~MockWebRtcAudioCapturerSink() {} 98c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) MOCK_METHOD5(CaptureData, void(const int16* audio_data, 99c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) int number_of_channels, 100c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) int number_of_frames, 101c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) int audio_delay_milliseconds, 102c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) double volume)); 103c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) MOCK_METHOD1(SetCaptureFormat, void(const media::AudioParameters& params)); 104c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}; 105c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 106c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} // namespace 107c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 108c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)class WebRtcLocalAudioTrackTest : public ::testing::Test { 109c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) protected: 110c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) virtual void SetUp() OVERRIDE { 111c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) capturer_ = WebRtcAudioCapturer::CreateCapturer(); 112c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) capturer_source_ = new MockCapturerSource(); 113868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) EXPECT_CALL(*capturer_source_.get(), Initialize(_, capturer_.get(), 0)) 114c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) .WillOnce(Return()); 115c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) capturer_->SetCapturerSource(capturer_source_, 116c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) media::CHANNEL_LAYOUT_STEREO, 117c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 48000); 118c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 119868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) EXPECT_CALL(*capturer_source_.get(), SetAutomaticGainControl(false)) 120c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) .WillOnce(Return()); 121c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) audio_thread_.reset(new FakeAudioThread(capturer_)); 122c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) audio_thread_->Start(); 123c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 124c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 125c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) virtual void TearDown() { 126c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) audio_thread_->Stop(); 127c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) audio_thread_.reset(); 128c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 129c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 130c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) scoped_refptr<MockCapturerSource> capturer_source_; 131c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) scoped_refptr<WebRtcAudioCapturer> capturer_; 132c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) scoped_ptr<FakeAudioThread> audio_thread_; 133c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}; 134c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 135c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Creates a capturer and audio track, fakes its audio thread, and 136c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// connect/disconnect the sink to the audio track on the fly, the sink should 137c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// get data callback when the track is connected to the capturer but not when 138c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// the track is disconnected from the capturer. 139c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)TEST_F(WebRtcLocalAudioTrackTest, ConnectAndDisconnectOneSink) { 1407d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) EXPECT_CALL(*capturer_source_.get(), Start()).WillOnce(Return()); 141c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) scoped_refptr<WebRtcLocalAudioTrack> track = 142c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) WebRtcLocalAudioTrack::Create(std::string(), capturer_, NULL); 1437d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) track->Start(); 144c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) EXPECT_TRUE(track->enabled()); 145c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) scoped_ptr<MockWebRtcAudioCapturerSink> sink( 146c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) new MockWebRtcAudioCapturerSink()); 147c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const media::AudioParameters params = capturer_->audio_parameters(); 148c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base::WaitableEvent event(false, false); 149c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) EXPECT_CALL(*sink, SetCaptureFormat(_)).WillOnce(Return()); 150c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) EXPECT_CALL(*sink, CaptureData( 151c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) _, params.channels(), params.frames_per_buffer(), 0, 0)) 152c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) .Times(AtLeast(1)).WillRepeatedly(SignalEvent(&event)); 153c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) track->AddSink(sink.get()); 154c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 155c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) EXPECT_TRUE(event.TimedWait(TestTimeouts::tiny_timeout())); 156c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) track->RemoveSink(sink.get()); 1577d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) 1587d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) EXPECT_CALL(*capturer_source_.get(), Stop()).WillOnce(Return()); 1597d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) track->Stop(); 160c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) track = NULL; 161c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 162c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 163c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// The same setup as ConnectAndDisconnectOneSink, but enable and disable the 164c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// audio track on the fly. When the audio track is disabled, there is no data 165c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// callback to the sink; when the audio track is enabled, there comes data 166c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// callback. 167c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// TODO(xians): Enable this test after resolving the racing issue that TSAN 168c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// reports on MediaStreamTrack::enabled(); 169c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)TEST_F(WebRtcLocalAudioTrackTest, DISABLED_DisableEnableAudioTrack) { 1707d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) EXPECT_CALL(*capturer_source_.get(), Start()).WillOnce(Return()); 171c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) scoped_refptr<WebRtcLocalAudioTrack> track = 172c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) WebRtcLocalAudioTrack::Create(std::string(), capturer_, NULL); 1737d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) track->Start(); 174c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) EXPECT_TRUE(track->enabled()); 175c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) EXPECT_TRUE(track->set_enabled(false)); 176c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) scoped_ptr<MockWebRtcAudioCapturerSink> sink( 177c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) new MockWebRtcAudioCapturerSink()); 178c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const media::AudioParameters params = capturer_->audio_parameters(); 179c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base::WaitableEvent event(false, false); 180c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) EXPECT_CALL(*sink, SetCaptureFormat(_)).WillOnce(Return()); 181c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) EXPECT_CALL(*sink, CaptureData( 182c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) _, params.channels(), params.frames_per_buffer(), 0, 0)) 183c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) .Times(0); 184c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) track->AddSink(sink.get()); 185c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) EXPECT_FALSE(event.TimedWait(TestTimeouts::tiny_timeout())); 186c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 187c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) event.Reset(); 188c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) EXPECT_CALL(*sink, CaptureData( 189c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) _, params.channels(), params.frames_per_buffer(), 0, 0)) 190c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) .Times(AtLeast(1)).WillRepeatedly(SignalEvent(&event)); 191c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) EXPECT_TRUE(track->set_enabled(true)); 192c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) EXPECT_TRUE(event.TimedWait(TestTimeouts::tiny_timeout())); 193c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) track->RemoveSink(sink.get()); 1947d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) 1957d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) EXPECT_CALL(*capturer_source_.get(), Stop()).WillOnce(Return()); 1967d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) track->Stop(); 197c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) track = NULL; 198c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 199c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 200c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Create multiple audio tracks and enable/disable them, verify that the audio 201c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// callbacks appear/disappear. 2027d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)TEST_F(WebRtcLocalAudioTrackTest, MultipleAudioTracks) { 2037d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) EXPECT_CALL(*capturer_source_.get(), Start()).WillOnce(Return()); 204c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) scoped_refptr<WebRtcLocalAudioTrack> track_1 = 205c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) WebRtcLocalAudioTrack::Create(std::string(), capturer_, NULL); 2067d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) track_1->Start(); 207c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) EXPECT_TRUE(track_1->enabled()); 208c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) scoped_ptr<MockWebRtcAudioCapturerSink> sink_1( 209c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) new MockWebRtcAudioCapturerSink()); 210c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const media::AudioParameters params = capturer_->audio_parameters(); 211c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base::WaitableEvent event_1(false, false); 212c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) EXPECT_CALL(*sink_1, SetCaptureFormat(_)).WillOnce(Return()); 213c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) EXPECT_CALL(*sink_1, CaptureData( 214c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) _, params.channels(), params.frames_per_buffer(), 0, 0)) 215c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) .Times(AtLeast(1)).WillRepeatedly(SignalEvent(&event_1)); 216c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) track_1->AddSink(sink_1.get()); 2177d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) EXPECT_TRUE(event_1.TimedWait(TestTimeouts::tiny_timeout())); 218c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 219c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) scoped_refptr<WebRtcLocalAudioTrack> track_2 = 220c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) WebRtcLocalAudioTrack::Create(std::string(), capturer_, NULL); 2217d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) track_2->Start(); 2227d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) EXPECT_TRUE(track_2->enabled()); 223c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 2247d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) // Verify both |sink_1| and |sink_2| get data. 225c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) event_1.Reset(); 226c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base::WaitableEvent event_2(false, false); 2277d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) 2287d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) scoped_ptr<MockWebRtcAudioCapturerSink> sink_2( 2297d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) new MockWebRtcAudioCapturerSink()); 2307d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) EXPECT_CALL(*sink_2, SetCaptureFormat(_)).WillOnce(Return()); 231c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) EXPECT_CALL(*sink_1, CaptureData( 232c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) _, params.channels(), params.frames_per_buffer(), 0, 0)) 233c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) .Times(AtLeast(1)).WillRepeatedly(SignalEvent(&event_1)); 234c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) EXPECT_CALL(*sink_2, CaptureData( 235c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) _, params.channels(), params.frames_per_buffer(), 0, 0)) 236c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) .Times(AtLeast(1)).WillRepeatedly(SignalEvent(&event_2)); 2377d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) track_2->AddSink(sink_2.get()); 238c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) EXPECT_TRUE(event_1.TimedWait(TestTimeouts::tiny_timeout())); 239c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) EXPECT_TRUE(event_2.TimedWait(TestTimeouts::tiny_timeout())); 240c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 241c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) track_1->RemoveSink(sink_1.get()); 2427d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) track_1->Stop(); 2437d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) track_1 = NULL; 2447d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) 2457d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) EXPECT_CALL(*capturer_source_.get(), Stop()).WillOnce(Return()); 246c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) track_2->RemoveSink(sink_2.get()); 2477d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) track_2->Stop(); 2487d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) track_2 = NULL; 2497d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)} 2507d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) 2517d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) 2527d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)// Start one track and verify the capturer is correctly starting its source. 2537d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)// And it should be fine to not to call Stop() explicitly. 2547d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)TEST_F(WebRtcLocalAudioTrackTest, StartOneAudioTrack) { 2557d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) EXPECT_CALL(*capturer_source_.get(), Start()).Times(1); 2567d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) scoped_refptr<WebRtcLocalAudioTrack> track = 2577d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) WebRtcLocalAudioTrack::Create(std::string(), capturer_, NULL); 2587d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) track->Start(); 2597d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) 2607d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) // When the track goes away, it will automatically stop the 2617d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) // |capturer_source_|. 2627d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) EXPECT_CALL(*capturer_source_.get(), Stop()); 2637d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) track = NULL; 2647d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)} 2657d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) 2667d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)// Start/Stop tracks and verify the capturer is correctly starting/stopping 2677d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)// its source. 2687d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)TEST_F(WebRtcLocalAudioTrackTest, StartAndStopAudioTracks) { 2697d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) // SetDefaultSink() should not trigger the Start() on |capturer_source_|. 2707d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) base::WaitableEvent event(false, false); 2717d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) scoped_ptr<MockWebRtcAudioCapturerSink> default_sink( 2727d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) new MockWebRtcAudioCapturerSink()); 2737d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) EXPECT_CALL(*default_sink, SetCaptureFormat(_)).WillOnce(Return()); 2747d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) EXPECT_CALL(*default_sink, CaptureData(_, _, _, 0, 0)) 2757d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) .Times(AnyNumber()).WillRepeatedly(Return()); 2767d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) capturer_->SetDefaultSink(default_sink.get()); 2777d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) EXPECT_CALL(*capturer_source_.get(), Start()).Times(0); 2787d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) EXPECT_FALSE(event.TimedWait(TestTimeouts::tiny_timeout())); 2797d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) 2807d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) // Starting the first audio track will start the |capturer_source_|. 2817d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) event.Reset(); 2827d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) EXPECT_CALL(*capturer_source_.get(), Start()).WillOnce(SignalEvent(&event)); 2837d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) scoped_refptr<WebRtcLocalAudioTrack> track_1 = 2847d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) WebRtcLocalAudioTrack::Create(std::string(), capturer_, NULL); 2857d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) track_1->Start(); 2867d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) EXPECT_TRUE(event.TimedWait(TestTimeouts::tiny_timeout())); 2877d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) 2887d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) // Start the second audio track will not start the |capturer_source_| 2897d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) // since it has been started. 2907d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) EXPECT_CALL(*capturer_source_.get(), Start()).Times(0); 2917d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) scoped_refptr<WebRtcLocalAudioTrack> track_2 = 2927d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) WebRtcLocalAudioTrack::Create(std::string(), capturer_, NULL); 2937d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) track_2->Start(); 2947d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) 2957d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) // Stop the first audio track will not stop the |capturer_source_|. 2967d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) EXPECT_CALL(*capturer_source_.get(), Stop()).Times(0); 2977d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) track_1->Stop(); 298c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) track_1 = NULL; 2997d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) 3007d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) // Stop the last audio track will stop the |capturer_source_|. 3017d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) event.Reset(); 3027d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) EXPECT_CALL(*capturer_source_.get(), Stop()) 3037d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) .Times(1).WillOnce(SignalEvent(&event)); 3047d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) track_2->Stop(); 305c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) track_2 = NULL; 3067d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) EXPECT_TRUE(event.TimedWait(TestTimeouts::tiny_timeout())); 3077d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) 3087d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) capturer_->SetDefaultSink(NULL); 3097d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)} 3107d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) 3117d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)// Set new source to the capturer. 3127d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)TEST_F(WebRtcLocalAudioTrackTest, SetNewSourceForCapturerAfterStartTrack) { 3137d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) // Setup the audio track and start the track. 3147d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) EXPECT_CALL(*capturer_source_.get(), Start()).Times(1); 3157d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) scoped_refptr<WebRtcLocalAudioTrack> track = 3167d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) WebRtcLocalAudioTrack::Create(std::string(), capturer_, NULL); 3177d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) track->Start(); 3187d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) 3197d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) // Setting new source to the capturer and the track should still get packets. 3207d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) scoped_refptr<MockCapturerSource> new_source(new MockCapturerSource()); 3217d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) EXPECT_CALL(*capturer_source_.get(), Stop()); 3227d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) EXPECT_CALL(*new_source.get(), SetAutomaticGainControl(false)); 3237d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) EXPECT_CALL(*new_source.get(), Initialize(_, capturer_.get(), 0)) 3247d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) .WillOnce(Return()); 3257d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) EXPECT_CALL(*new_source.get(), Start()).WillOnce(Return()); 3267d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) capturer_->SetCapturerSource(new_source, 3277d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) media::CHANNEL_LAYOUT_STEREO, 3287d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) 48000); 3297d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) 3307d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) // Stop the track. 3317d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) EXPECT_CALL(*new_source.get(), Stop()); 3327d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) track->Stop(); 3337d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) track = NULL; 334c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 335c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 336c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} // namespace content 337