webrtc_local_audio_track_unittest.cc revision d0247b1b59f9c528cb6df88b4f2b9afaf80d181e
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" 758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#include "content/renderer/media/rtc_media_constraints.h" 8c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "content/renderer/media/webrtc_audio_capturer.h" 9d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)#include "content/renderer/media/webrtc_local_audio_source_provider.h" 10c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "content/renderer/media/webrtc_local_audio_track.h" 11c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "media/audio/audio_parameters.h" 12c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "media/base/audio_bus.h" 13c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "media/base/audio_capturer_source.h" 14c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "testing/gmock/include/gmock/gmock.h" 15c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "testing/gtest/include/gtest/gtest.h" 16bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch#include "third_party/libjingle/source/talk/app/webrtc/mediastreaminterface.h" 17c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 18c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)using ::testing::_; 197d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)using ::testing::AnyNumber; 20c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)using ::testing::AtLeast; 21c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)using ::testing::Return; 22c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 23c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)namespace content { 24c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 25c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)namespace { 26c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 27c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)ACTION_P(SignalEvent, event) { 28c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) event->Signal(); 29c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 30c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 31c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// A simple thread that we use to fake the audio thread which provides data to 32c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// the |WebRtcAudioCapturer|. 33c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)class FakeAudioThread : public base::PlatformThread::Delegate { 34c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) public: 35c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) explicit FakeAudioThread(const scoped_refptr<WebRtcAudioCapturer>& capturer) 36c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) : capturer_(capturer), 3790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) thread_(), 38c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) closure_(false, false) { 39868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) DCHECK(capturer.get()); 40c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) audio_bus_ = media::AudioBus::Create(capturer_->audio_parameters()); 41c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 42c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 4390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) virtual ~FakeAudioThread() { DCHECK(thread_.is_null()); } 44c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 45c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // base::PlatformThread::Delegate: 46c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) virtual void ThreadMain() OVERRIDE { 47c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) while (true) { 48c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (closure_.IsSignaled()) 49c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return; 50c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 51c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) media::AudioCapturerSource::CaptureCallback* callback = 52868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) static_cast<media::AudioCapturerSource::CaptureCallback*>( 53868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) capturer_.get()); 54c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) audio_bus_->Zero(); 553551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) callback->Capture(audio_bus_.get(), 0, 0, false); 56c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 57c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Sleep 1ms to yield the resource for the main thread. 58c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(1)); 59c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 60c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 61c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 62c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) void Start() { 63c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base::PlatformThread::CreateWithPriority( 64c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 0, this, &thread_, base::kThreadPriority_RealtimeAudio); 6590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) CHECK(!thread_.is_null()); 66c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 67c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 68c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) void Stop() { 69c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) closure_.Signal(); 70c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base::PlatformThread::Join(thread_); 7190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) thread_ = base::PlatformThreadHandle(); 72c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 73c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 74c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) private: 75c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) scoped_ptr<media::AudioBus> audio_bus_; 76c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) scoped_refptr<WebRtcAudioCapturer> capturer_; 77c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base::PlatformThreadHandle thread_; 78c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base::WaitableEvent closure_; 79c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DISALLOW_COPY_AND_ASSIGN(FakeAudioThread); 80c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}; 81c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 82c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)class MockCapturerSource : public media::AudioCapturerSource { 83c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) public: 84c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) MockCapturerSource() {} 85c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) MOCK_METHOD3(Initialize, void(const media::AudioParameters& params, 86c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) CaptureCallback* callback, 87c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) int session_id)); 88c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) MOCK_METHOD0(Start, void()); 89c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) MOCK_METHOD0(Stop, void()); 90c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) MOCK_METHOD1(SetVolume, void(double volume)); 91c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) MOCK_METHOD1(SetAutomaticGainControl, void(bool enable)); 92c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 93c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) protected: 94c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) virtual ~MockCapturerSource() {} 95c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}; 96c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 97c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)class MockWebRtcAudioCapturerSink : public WebRtcAudioCapturerSink { 98c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) public: 99c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) MockWebRtcAudioCapturerSink() {} 100c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) ~MockWebRtcAudioCapturerSink() {} 101bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch int CaptureData(const std::vector<int>& channels, 102bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch const int16* audio_data, 103bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch int sample_rate, 104bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch int number_of_channels, 105bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch int number_of_frames, 106bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch int audio_delay_milliseconds, 107bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch int current_volume, 1083551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) bool need_audio_processing, 1093551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) bool key_pressed) OVERRIDE { 1103551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) CaptureData(channels.size(), 1113551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) sample_rate, 1123551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) number_of_channels, 1133551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) number_of_frames, 1143551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) audio_delay_milliseconds, 1153551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) current_volume, 1163551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) need_audio_processing, 1173551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) key_pressed); 118bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch return 0; 119bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch } 1203551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) MOCK_METHOD8(CaptureData, 1213551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) void(int number_of_network_channels, 1223551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) int sample_rate, 1233551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) int number_of_channels, 1243551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) int number_of_frames, 1253551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) int audio_delay_milliseconds, 1263551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) int current_volume, 1273551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) bool need_audio_processing, 1283551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) bool key_pressed)); 129c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) MOCK_METHOD1(SetCaptureFormat, void(const media::AudioParameters& params)); 130c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}; 131c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 132c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} // namespace 133c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 134c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)class WebRtcLocalAudioTrackTest : public ::testing::Test { 135c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) protected: 136c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) virtual void SetUp() OVERRIDE { 137d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) params_.Reset(media::AudioParameters::AUDIO_PCM_LOW_LATENCY, 138d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) media::CHANNEL_LAYOUT_STEREO, 2, 0, 48000, 16, 480); 139c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) capturer_ = WebRtcAudioCapturer::CreateCapturer(); 140d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) WebRtcLocalAudioSourceProvider* source_provider = 141d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) static_cast<WebRtcLocalAudioSourceProvider*>( 142d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) capturer_->audio_source_provider()); 143d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) source_provider->SetSinkParamsForTesting(params_); 144c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) capturer_source_ = new MockCapturerSource(); 145868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) EXPECT_CALL(*capturer_source_.get(), Initialize(_, capturer_.get(), 0)) 146c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) .WillOnce(Return()); 147c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) capturer_->SetCapturerSource(capturer_source_, 148d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) params_.channel_layout(), 149d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) params_.sample_rate()); 150c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 151868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) EXPECT_CALL(*capturer_source_.get(), SetAutomaticGainControl(false)) 152c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) .WillOnce(Return()); 153bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch 154bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch // Start the audio thread used by the |capturer_source_|. 155c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) audio_thread_.reset(new FakeAudioThread(capturer_)); 156c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) audio_thread_->Start(); 157c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 158c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 159c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) virtual void TearDown() { 160c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) audio_thread_->Stop(); 161c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) audio_thread_.reset(); 162c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 163c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 164d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) media::AudioParameters params_; 165c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) scoped_refptr<MockCapturerSource> capturer_source_; 166c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) scoped_refptr<WebRtcAudioCapturer> capturer_; 167c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) scoped_ptr<FakeAudioThread> audio_thread_; 168c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}; 169c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 170c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Creates a capturer and audio track, fakes its audio thread, and 171c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// connect/disconnect the sink to the audio track on the fly, the sink should 172c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// get data callback when the track is connected to the capturer but not when 173c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// the track is disconnected from the capturer. 174c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)TEST_F(WebRtcLocalAudioTrackTest, ConnectAndDisconnectOneSink) { 1757d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) EXPECT_CALL(*capturer_source_.get(), Start()).WillOnce(Return()); 17658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) RTCMediaConstraints constraints; 177c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) scoped_refptr<WebRtcLocalAudioTrack> track = 178d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) WebRtcLocalAudioTrack::Create(std::string(), capturer_, NULL, NULL, 17958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) &constraints); 1807d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) track->Start(); 181c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) EXPECT_TRUE(track->enabled()); 182bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch 183bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch // Connect a number of network channels to the audio track. 184bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch static const int kNumberOfNetworkChannels = 4; 185bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch for (int i = 0; i < kNumberOfNetworkChannels; ++i) { 186bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch static_cast<webrtc::AudioTrackInterface*>(track.get())-> 187bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch GetRenderer()->AddChannel(i); 188bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch } 189c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) scoped_ptr<MockWebRtcAudioCapturerSink> sink( 190c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) new MockWebRtcAudioCapturerSink()); 191c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const media::AudioParameters params = capturer_->audio_parameters(); 192c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base::WaitableEvent event(false, false); 193c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) EXPECT_CALL(*sink, SetCaptureFormat(_)).WillOnce(Return()); 1943551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) EXPECT_CALL(*sink, 19558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) CaptureData(kNumberOfNetworkChannels, 19658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) params.sample_rate(), 19758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) params.channels(), 198d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) params.sample_rate() / 100, 19958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 0, 20058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 0, 20158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) false, 20258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) false)).Times(AtLeast(1)) 2033551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) .WillRepeatedly(SignalEvent(&event)); 204c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) track->AddSink(sink.get()); 205c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 206c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) EXPECT_TRUE(event.TimedWait(TestTimeouts::tiny_timeout())); 207c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) track->RemoveSink(sink.get()); 2087d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) 2097d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) EXPECT_CALL(*capturer_source_.get(), Stop()).WillOnce(Return()); 2107d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) track->Stop(); 211c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) track = NULL; 212c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 213c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 214c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// The same setup as ConnectAndDisconnectOneSink, but enable and disable the 215c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// audio track on the fly. When the audio track is disabled, there is no data 216c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// callback to the sink; when the audio track is enabled, there comes data 217c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// callback. 218c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// TODO(xians): Enable this test after resolving the racing issue that TSAN 219c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// reports on MediaStreamTrack::enabled(); 220c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)TEST_F(WebRtcLocalAudioTrackTest, DISABLED_DisableEnableAudioTrack) { 2217d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) EXPECT_CALL(*capturer_source_.get(), Start()).WillOnce(Return()); 22258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) RTCMediaConstraints constraints; 223c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) scoped_refptr<WebRtcLocalAudioTrack> track = 224d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) WebRtcLocalAudioTrack::Create(std::string(), capturer_, NULL, NULL, 22558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) &constraints); 2267d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) track->Start(); 227bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch static_cast<webrtc::AudioTrackInterface*>(track.get())-> 228bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch GetRenderer()->AddChannel(0); 229c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) EXPECT_TRUE(track->enabled()); 230c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) EXPECT_TRUE(track->set_enabled(false)); 231c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) scoped_ptr<MockWebRtcAudioCapturerSink> sink( 232c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) new MockWebRtcAudioCapturerSink()); 233c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const media::AudioParameters params = capturer_->audio_parameters(); 234c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base::WaitableEvent event(false, false); 235c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) EXPECT_CALL(*sink, SetCaptureFormat(_)).WillOnce(Return()); 2363551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) EXPECT_CALL(*sink, 2373551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) CaptureData(1, 2383551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) params.sample_rate(), 2393551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) params.channels(), 240d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) params.sample_rate() / 100, 2413551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 0, 2423551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 0, 2433551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) false, 2443551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) false)).Times(0); 245c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) track->AddSink(sink.get()); 246c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) EXPECT_FALSE(event.TimedWait(TestTimeouts::tiny_timeout())); 247c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 248c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) event.Reset(); 2493551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) EXPECT_CALL(*sink, 2503551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) CaptureData(1, 2513551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) params.sample_rate(), 2523551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) params.channels(), 253d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) params.sample_rate() / 100, 2543551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 0, 2553551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 0, 2563551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) false, 2573551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) false)).Times(AtLeast(1)) 2583551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) .WillRepeatedly(SignalEvent(&event)); 259c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) EXPECT_TRUE(track->set_enabled(true)); 260c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) EXPECT_TRUE(event.TimedWait(TestTimeouts::tiny_timeout())); 261c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) track->RemoveSink(sink.get()); 2627d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) 2637d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) EXPECT_CALL(*capturer_source_.get(), Stop()).WillOnce(Return()); 2647d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) track->Stop(); 265c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) track = NULL; 266c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 267c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 268c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Create multiple audio tracks and enable/disable them, verify that the audio 269c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// callbacks appear/disappear. 2707d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)TEST_F(WebRtcLocalAudioTrackTest, MultipleAudioTracks) { 2717d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) EXPECT_CALL(*capturer_source_.get(), Start()).WillOnce(Return()); 27258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) RTCMediaConstraints constraints; 273c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) scoped_refptr<WebRtcLocalAudioTrack> track_1 = 274d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) WebRtcLocalAudioTrack::Create(std::string(), capturer_, NULL, NULL, 27558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) &constraints); 2767d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) track_1->Start(); 277bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch static_cast<webrtc::AudioTrackInterface*>(track_1.get())-> 278bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch GetRenderer()->AddChannel(0); 279c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) EXPECT_TRUE(track_1->enabled()); 280c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) scoped_ptr<MockWebRtcAudioCapturerSink> sink_1( 281c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) new MockWebRtcAudioCapturerSink()); 282c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const media::AudioParameters params = capturer_->audio_parameters(); 283c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base::WaitableEvent event_1(false, false); 284c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) EXPECT_CALL(*sink_1, SetCaptureFormat(_)).WillOnce(Return()); 2853551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) EXPECT_CALL(*sink_1, 28658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) CaptureData(1, 28758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) params.sample_rate(), 28858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) params.channels(), 289d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) params.sample_rate() / 100, 29058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 0, 29158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 0, 29258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) false, 29358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) false)).Times(AtLeast(1)) 2943551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) .WillRepeatedly(SignalEvent(&event_1)); 295c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) track_1->AddSink(sink_1.get()); 2967d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) EXPECT_TRUE(event_1.TimedWait(TestTimeouts::tiny_timeout())); 297c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 298c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) scoped_refptr<WebRtcLocalAudioTrack> track_2 = 299d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) WebRtcLocalAudioTrack::Create(std::string(), capturer_, NULL, NULL, 30058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) &constraints); 3017d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) track_2->Start(); 302bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch static_cast<webrtc::AudioTrackInterface*>(track_2.get())-> 303bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch GetRenderer()->AddChannel(1); 3047d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) EXPECT_TRUE(track_2->enabled()); 305c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 3067d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) // Verify both |sink_1| and |sink_2| get data. 307c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) event_1.Reset(); 308c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base::WaitableEvent event_2(false, false); 3097d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) 3107d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) scoped_ptr<MockWebRtcAudioCapturerSink> sink_2( 3117d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) new MockWebRtcAudioCapturerSink()); 3127d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) EXPECT_CALL(*sink_2, SetCaptureFormat(_)).WillOnce(Return()); 3133551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) EXPECT_CALL(*sink_1, 31458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) CaptureData(1, 31558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) params.sample_rate(), 31658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) params.channels(), 317d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) params.sample_rate() / 100, 31858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 0, 31958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 0, 32058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) false, 32158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) false)).Times(AtLeast(1)) 3223551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) .WillRepeatedly(SignalEvent(&event_1)); 3233551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) EXPECT_CALL(*sink_2, 32458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) CaptureData(1, 32558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) params.sample_rate(), 32658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) params.channels(), 327d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) params.sample_rate() / 100, 32858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 0, 32958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 0, 33058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) false, 33158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) false)).Times(AtLeast(1)) 3323551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) .WillRepeatedly(SignalEvent(&event_2)); 3337d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) track_2->AddSink(sink_2.get()); 334c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) EXPECT_TRUE(event_1.TimedWait(TestTimeouts::tiny_timeout())); 335c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) EXPECT_TRUE(event_2.TimedWait(TestTimeouts::tiny_timeout())); 336c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 337c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) track_1->RemoveSink(sink_1.get()); 3387d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) track_1->Stop(); 3397d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) track_1 = NULL; 3407d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) 3417d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) EXPECT_CALL(*capturer_source_.get(), Stop()).WillOnce(Return()); 342c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) track_2->RemoveSink(sink_2.get()); 3437d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) track_2->Stop(); 3447d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) track_2 = NULL; 3457d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)} 3467d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) 3477d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) 3487d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)// Start one track and verify the capturer is correctly starting its source. 3497d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)// And it should be fine to not to call Stop() explicitly. 3507d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)TEST_F(WebRtcLocalAudioTrackTest, StartOneAudioTrack) { 3517d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) EXPECT_CALL(*capturer_source_.get(), Start()).Times(1); 35258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) RTCMediaConstraints constraints; 3537d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) scoped_refptr<WebRtcLocalAudioTrack> track = 354d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) WebRtcLocalAudioTrack::Create(std::string(), capturer_, NULL, NULL, 35558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) &constraints); 3567d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) track->Start(); 3577d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) 3587d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) // When the track goes away, it will automatically stop the 3597d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) // |capturer_source_|. 3607d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) EXPECT_CALL(*capturer_source_.get(), Stop()); 361bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch track->Stop(); 3627d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) track = NULL; 3637d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)} 3647d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) 3657d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)// Start/Stop tracks and verify the capturer is correctly starting/stopping 3667d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)// its source. 3677d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)TEST_F(WebRtcLocalAudioTrackTest, StartAndStopAudioTracks) { 3687d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) // Starting the first audio track will start the |capturer_source_|. 369bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch base::WaitableEvent event(false, false); 3707d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) EXPECT_CALL(*capturer_source_.get(), Start()).WillOnce(SignalEvent(&event)); 37158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) RTCMediaConstraints constraints; 3727d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) scoped_refptr<WebRtcLocalAudioTrack> track_1 = 373d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) WebRtcLocalAudioTrack::Create(std::string(), capturer_, NULL, NULL, 37458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) &constraints); 375bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch static_cast<webrtc::AudioTrackInterface*>(track_1.get())-> 376bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch GetRenderer()->AddChannel(0); 3777d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) track_1->Start(); 3787d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) EXPECT_TRUE(event.TimedWait(TestTimeouts::tiny_timeout())); 3797d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) 380bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch // Verify the data flow by connecting the sink to |track_1|. 381bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch scoped_ptr<MockWebRtcAudioCapturerSink> sink( 382bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch new MockWebRtcAudioCapturerSink()); 383bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch event.Reset(); 3843551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) EXPECT_CALL(*sink, CaptureData(_, _, _, _, 0, 0, false, false)) 385bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch .Times(AnyNumber()).WillRepeatedly(Return()); 386bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch EXPECT_CALL(*sink, SetCaptureFormat(_)).Times(1); 387bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch track_1->AddSink(sink.get()); 388bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch 3897d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) // Start the second audio track will not start the |capturer_source_| 3907d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) // since it has been started. 3917d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) EXPECT_CALL(*capturer_source_.get(), Start()).Times(0); 3927d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) scoped_refptr<WebRtcLocalAudioTrack> track_2 = 393d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) WebRtcLocalAudioTrack::Create(std::string(), capturer_, NULL, NULL, 39458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) &constraints); 3957d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) track_2->Start(); 396bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch static_cast<webrtc::AudioTrackInterface*>(track_2.get())-> 397bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch GetRenderer()->AddChannel(1); 3987d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) 3997d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) // Stop the first audio track will not stop the |capturer_source_|. 4007d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) EXPECT_CALL(*capturer_source_.get(), Stop()).Times(0); 401bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch track_1->RemoveSink(sink.get()); 4027d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) track_1->Stop(); 403c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) track_1 = NULL; 4047d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) 4053551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) EXPECT_CALL(*sink, CaptureData(_, _, _, _, 0, 0, false, false)) 406bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch .Times(AnyNumber()).WillRepeatedly(Return()); 407bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch EXPECT_CALL(*sink, SetCaptureFormat(_)).Times(1); 408bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch track_2->AddSink(sink.get()); 409bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch 4107d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) // Stop the last audio track will stop the |capturer_source_|. 4117d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) event.Reset(); 4127d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) EXPECT_CALL(*capturer_source_.get(), Stop()) 4137d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) .Times(1).WillOnce(SignalEvent(&event)); 4147d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) track_2->Stop(); 415bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch track_2->RemoveSink(sink.get()); 416c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) track_2 = NULL; 4177d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) EXPECT_TRUE(event.TimedWait(TestTimeouts::tiny_timeout())); 4187d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)} 4197d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) 420bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch// Set new source to the existing capturer. 4217d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)TEST_F(WebRtcLocalAudioTrackTest, SetNewSourceForCapturerAfterStartTrack) { 4227d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) // Setup the audio track and start the track. 4237d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) EXPECT_CALL(*capturer_source_.get(), Start()).Times(1); 42458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) RTCMediaConstraints constraints; 4257d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) scoped_refptr<WebRtcLocalAudioTrack> track = 426d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) WebRtcLocalAudioTrack::Create(std::string(), capturer_, NULL, NULL, 42758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) &constraints); 4287d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) track->Start(); 4297d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) 4307d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) // Setting new source to the capturer and the track should still get packets. 4317d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) scoped_refptr<MockCapturerSource> new_source(new MockCapturerSource()); 4327d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) EXPECT_CALL(*capturer_source_.get(), Stop()); 4337d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) EXPECT_CALL(*new_source.get(), SetAutomaticGainControl(false)); 4347d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) EXPECT_CALL(*new_source.get(), Initialize(_, capturer_.get(), 0)) 4357d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) .WillOnce(Return()); 4367d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) EXPECT_CALL(*new_source.get(), Start()).WillOnce(Return()); 4377d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) capturer_->SetCapturerSource(new_source, 438d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) params_.channel_layout(), 439d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) params_.sample_rate()); 4407d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) 4417d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) // Stop the track. 4427d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) EXPECT_CALL(*new_source.get(), Stop()); 4437d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) track->Stop(); 4447d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) track = NULL; 445c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 446c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 447bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch// Create a new capturer with new source, connect it to a new audio track. 448bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben MurdochTEST_F(WebRtcLocalAudioTrackTest, ConnectTracksToDifferentCapturers) { 449bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch // Setup the first audio track and start it. 450bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch EXPECT_CALL(*capturer_source_.get(), Start()).Times(1); 45158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) RTCMediaConstraints constraints; 452bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch scoped_refptr<WebRtcLocalAudioTrack> track_1 = 453d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) WebRtcLocalAudioTrack::Create(std::string(), capturer_, NULL, NULL, 45458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) &constraints); 455bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch track_1->Start(); 456bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch 457bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch // Connect a number of network channels to the |track_1|. 458bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch static const int kNumberOfNetworkChannelsForTrack1 = 2; 459bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch for (int i = 0; i < kNumberOfNetworkChannelsForTrack1; ++i) { 460bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch static_cast<webrtc::AudioTrackInterface*>(track_1.get())-> 461bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch GetRenderer()->AddChannel(i); 462bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch } 463bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch // Verify the data flow by connecting the |sink_1| to |track_1|. 464bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch scoped_ptr<MockWebRtcAudioCapturerSink> sink_1( 465bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch new MockWebRtcAudioCapturerSink()); 4663551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) EXPECT_CALL( 4673551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) *sink_1.get(), 4683551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) CaptureData( 4693551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) kNumberOfNetworkChannelsForTrack1, 48000, 2, _, 0, 0, false, false)) 470bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch .Times(AnyNumber()).WillRepeatedly(Return()); 471bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch EXPECT_CALL(*sink_1.get(), SetCaptureFormat(_)).Times(1); 472bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch track_1->AddSink(sink_1.get()); 473bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch 474bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch // Create a new capturer with new source with different audio format. 475bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch scoped_refptr<WebRtcAudioCapturer> new_capturer( 476bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch WebRtcAudioCapturer::CreateCapturer()); 477d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) WebRtcLocalAudioSourceProvider* source_provider = 478d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) static_cast<WebRtcLocalAudioSourceProvider*>( 479d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) new_capturer->audio_source_provider()); 480d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) source_provider->SetSinkParamsForTesting(params_); 481bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch scoped_refptr<MockCapturerSource> new_source(new MockCapturerSource()); 482bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch EXPECT_CALL(*new_source.get(), Initialize(_, new_capturer.get(), 0)) 483bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch .WillOnce(Return()); 484bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch EXPECT_CALL(*new_source.get(), SetAutomaticGainControl(false)) 485bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch .WillOnce(Return()); 486bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch new_capturer->SetCapturerSource(new_source, 487bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch media::CHANNEL_LAYOUT_MONO, 488bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch 44100); 489bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch 490bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch // Start the audio thread used by the new source. 491bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch scoped_ptr<FakeAudioThread> audio_thread(new FakeAudioThread(new_capturer)); 492bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch audio_thread->Start(); 493bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch 494bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch // Setup the second audio track, connect it to the new capturer and start it. 495bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch EXPECT_CALL(*new_source.get(), Start()).Times(1); 496bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch scoped_refptr<WebRtcLocalAudioTrack> track_2 = 497d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) WebRtcLocalAudioTrack::Create(std::string(), new_capturer, NULL, NULL, 49858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) &constraints); 499bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch track_2->Start(); 500bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch 501bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch // Connect a number of network channels to the |track_2|. 502bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch static const int kNumberOfNetworkChannelsForTrack2 = 3; 503bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch for (int i = 0; i < kNumberOfNetworkChannelsForTrack2; ++i) { 504bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch static_cast<webrtc::AudioTrackInterface*>(track_2.get())-> 505bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch GetRenderer()->AddChannel(i); 506bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch } 507bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch // Verify the data flow by connecting the |sink_2| to |track_2|. 508bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch scoped_ptr<MockWebRtcAudioCapturerSink> sink_2( 509bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch new MockWebRtcAudioCapturerSink()); 5103551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) EXPECT_CALL( 5113551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) *sink_2, 5123551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) CaptureData( 5133551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) kNumberOfNetworkChannelsForTrack2, 44100, 1, _, 0, 0, false, false)) 514bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch .Times(AnyNumber()).WillRepeatedly(Return()); 515bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch EXPECT_CALL(*sink_2, SetCaptureFormat(_)).Times(1); 516bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch track_2->AddSink(sink_2.get()); 517bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch 518bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch // Stop the second audio track will stop the new source. 519bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch base::WaitableEvent event(false, false); 520bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch EXPECT_CALL(*new_source.get(), Stop()).Times(1).WillOnce(SignalEvent(&event)); 521bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch track_2->Stop(); 522bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch track_2->RemoveSink(sink_2.get()); 523bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch track_2 = NULL; 524bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch EXPECT_TRUE(event.TimedWait(TestTimeouts::tiny_timeout())); 525bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch audio_thread->Stop(); 526bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch audio_thread.reset(); 527bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch 528bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch // Stop the first audio track. 529bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch EXPECT_CALL(*capturer_source_.get(), Stop()); 530bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch track_1->Stop(); 531bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch track_1 = NULL; 532bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch} 533bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch 534c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} // namespace content 535