webrtc_local_audio_track_unittest.cc revision 58537e28ecd584eab876aee8be7156509866d23a
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" 9c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "content/renderer/media/webrtc_local_audio_track.h" 10c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "media/audio/audio_parameters.h" 11c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "media/base/audio_bus.h" 12c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "media/base/audio_capturer_source.h" 13c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "testing/gmock/include/gmock/gmock.h" 14c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "testing/gtest/include/gtest/gtest.h" 15bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch#include "third_party/libjingle/source/talk/app/webrtc/mediastreaminterface.h" 16c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 17c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)using ::testing::_; 187d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)using ::testing::AnyNumber; 19c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)using ::testing::AtLeast; 20c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)using ::testing::Return; 21c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 22c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)namespace content { 23c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 24c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)namespace { 25c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 26c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)ACTION_P(SignalEvent, event) { 27c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) event->Signal(); 28c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 29c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 30c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// A simple thread that we use to fake the audio thread which provides data to 31c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// the |WebRtcAudioCapturer|. 32c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)class FakeAudioThread : public base::PlatformThread::Delegate { 33c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) public: 34c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) explicit FakeAudioThread(const scoped_refptr<WebRtcAudioCapturer>& capturer) 35c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) : capturer_(capturer), 3690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) thread_(), 37c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) closure_(false, false) { 38868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) DCHECK(capturer.get()); 39c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) audio_bus_ = media::AudioBus::Create(capturer_->audio_parameters()); 40c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 41c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 4290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) virtual ~FakeAudioThread() { DCHECK(thread_.is_null()); } 43c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 44c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // base::PlatformThread::Delegate: 45c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) virtual void ThreadMain() OVERRIDE { 46c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) while (true) { 47c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (closure_.IsSignaled()) 48c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return; 49c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 50c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) media::AudioCapturerSource::CaptureCallback* callback = 51868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) static_cast<media::AudioCapturerSource::CaptureCallback*>( 52868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) capturer_.get()); 53c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) audio_bus_->Zero(); 543551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) callback->Capture(audio_bus_.get(), 0, 0, false); 55c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 56c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Sleep 1ms to yield the resource for the main thread. 57c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(1)); 58c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 59c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 60c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 61c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) void Start() { 62c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base::PlatformThread::CreateWithPriority( 63c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 0, this, &thread_, base::kThreadPriority_RealtimeAudio); 6490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) CHECK(!thread_.is_null()); 65c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 66c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 67c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) void Stop() { 68c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) closure_.Signal(); 69c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base::PlatformThread::Join(thread_); 7090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) thread_ = base::PlatformThreadHandle(); 71c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 72c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 73c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) private: 74c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) scoped_ptr<media::AudioBus> audio_bus_; 75c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) scoped_refptr<WebRtcAudioCapturer> capturer_; 76c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base::PlatformThreadHandle thread_; 77c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base::WaitableEvent closure_; 78c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DISALLOW_COPY_AND_ASSIGN(FakeAudioThread); 79c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}; 80c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 81c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)class MockCapturerSource : public media::AudioCapturerSource { 82c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) public: 83c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) MockCapturerSource() {} 84c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) MOCK_METHOD3(Initialize, void(const media::AudioParameters& params, 85c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) CaptureCallback* callback, 86c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) int session_id)); 87c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) MOCK_METHOD0(Start, void()); 88c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) MOCK_METHOD0(Stop, void()); 89c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) MOCK_METHOD1(SetVolume, void(double volume)); 90c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) MOCK_METHOD1(SetAutomaticGainControl, void(bool enable)); 91c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 92c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) protected: 93c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) virtual ~MockCapturerSource() {} 94c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}; 95c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 96c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)class MockWebRtcAudioCapturerSink : public WebRtcAudioCapturerSink { 97c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) public: 98c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) MockWebRtcAudioCapturerSink() {} 99c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) ~MockWebRtcAudioCapturerSink() {} 100bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch int CaptureData(const std::vector<int>& channels, 101bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch const int16* audio_data, 102bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch int sample_rate, 103bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch int number_of_channels, 104bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch int number_of_frames, 105bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch int audio_delay_milliseconds, 106bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch int current_volume, 1073551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) bool need_audio_processing, 1083551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) bool key_pressed) OVERRIDE { 1093551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) CaptureData(channels.size(), 1103551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) sample_rate, 1113551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) number_of_channels, 1123551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) number_of_frames, 1133551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) audio_delay_milliseconds, 1143551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) current_volume, 1153551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) need_audio_processing, 1163551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) key_pressed); 117bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch return 0; 118bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch } 1193551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) MOCK_METHOD8(CaptureData, 1203551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) void(int number_of_network_channels, 1213551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) int sample_rate, 1223551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) int number_of_channels, 1233551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) int number_of_frames, 1243551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) int audio_delay_milliseconds, 1253551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) int current_volume, 1263551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) bool need_audio_processing, 1273551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) bool key_pressed)); 128c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) MOCK_METHOD1(SetCaptureFormat, void(const media::AudioParameters& params)); 129c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}; 130c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 131c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} // namespace 132c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 133c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)class WebRtcLocalAudioTrackTest : public ::testing::Test { 134c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) protected: 135c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) virtual void SetUp() OVERRIDE { 136c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) capturer_ = WebRtcAudioCapturer::CreateCapturer(); 137c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) capturer_source_ = new MockCapturerSource(); 138868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) EXPECT_CALL(*capturer_source_.get(), Initialize(_, capturer_.get(), 0)) 139c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) .WillOnce(Return()); 140c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) capturer_->SetCapturerSource(capturer_source_, 141c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) media::CHANNEL_LAYOUT_STEREO, 142c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 48000); 143c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 144868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) EXPECT_CALL(*capturer_source_.get(), SetAutomaticGainControl(false)) 145c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) .WillOnce(Return()); 146bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch 147bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch // Start the audio thread used by the |capturer_source_|. 148c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) audio_thread_.reset(new FakeAudioThread(capturer_)); 149c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) audio_thread_->Start(); 150c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 151c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 152c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) virtual void TearDown() { 153c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) audio_thread_->Stop(); 154c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) audio_thread_.reset(); 155c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 156c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 157c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) scoped_refptr<MockCapturerSource> capturer_source_; 158c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) scoped_refptr<WebRtcAudioCapturer> capturer_; 159c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) scoped_ptr<FakeAudioThread> audio_thread_; 160c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}; 161c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 162c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Creates a capturer and audio track, fakes its audio thread, and 163c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// connect/disconnect the sink to the audio track on the fly, the sink should 164c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// get data callback when the track is connected to the capturer but not when 165c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// the track is disconnected from the capturer. 166c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)TEST_F(WebRtcLocalAudioTrackTest, ConnectAndDisconnectOneSink) { 1677d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) EXPECT_CALL(*capturer_source_.get(), Start()).WillOnce(Return()); 16858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) RTCMediaConstraints constraints; 169c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) scoped_refptr<WebRtcLocalAudioTrack> track = 17058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) WebRtcLocalAudioTrack::Create(std::string(), capturer_, NULL, 17158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) &constraints); 1727d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) track->Start(); 173c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) EXPECT_TRUE(track->enabled()); 174bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch 175bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch // Connect a number of network channels to the audio track. 176bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch static const int kNumberOfNetworkChannels = 4; 177bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch for (int i = 0; i < kNumberOfNetworkChannels; ++i) { 178bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch static_cast<webrtc::AudioTrackInterface*>(track.get())-> 179bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch GetRenderer()->AddChannel(i); 180bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch } 181c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) scoped_ptr<MockWebRtcAudioCapturerSink> sink( 182c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) new MockWebRtcAudioCapturerSink()); 183c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const media::AudioParameters params = capturer_->audio_parameters(); 184c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base::WaitableEvent event(false, false); 185c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) EXPECT_CALL(*sink, SetCaptureFormat(_)).WillOnce(Return()); 1863551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) EXPECT_CALL(*sink, 18758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) CaptureData(kNumberOfNetworkChannels, 18858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) params.sample_rate(), 18958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) params.channels(), 19058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) params.frames_per_buffer(), 19158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 0, 19258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 0, 19358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) false, 19458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) false)).Times(AtLeast(1)) 1953551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) .WillRepeatedly(SignalEvent(&event)); 196c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) track->AddSink(sink.get()); 197c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 198c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) EXPECT_TRUE(event.TimedWait(TestTimeouts::tiny_timeout())); 199c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) track->RemoveSink(sink.get()); 2007d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) 2017d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) EXPECT_CALL(*capturer_source_.get(), Stop()).WillOnce(Return()); 2027d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) track->Stop(); 203c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) track = NULL; 204c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 205c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 206c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// The same setup as ConnectAndDisconnectOneSink, but enable and disable the 207c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// audio track on the fly. When the audio track is disabled, there is no data 208c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// callback to the sink; when the audio track is enabled, there comes data 209c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// callback. 210c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// TODO(xians): Enable this test after resolving the racing issue that TSAN 211c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// reports on MediaStreamTrack::enabled(); 212c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)TEST_F(WebRtcLocalAudioTrackTest, DISABLED_DisableEnableAudioTrack) { 2137d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) EXPECT_CALL(*capturer_source_.get(), Start()).WillOnce(Return()); 21458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) RTCMediaConstraints constraints; 215c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) scoped_refptr<WebRtcLocalAudioTrack> track = 21658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) WebRtcLocalAudioTrack::Create(std::string(), capturer_, NULL, 21758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) &constraints); 2187d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) track->Start(); 219bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch static_cast<webrtc::AudioTrackInterface*>(track.get())-> 220bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch GetRenderer()->AddChannel(0); 221c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) EXPECT_TRUE(track->enabled()); 222c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) EXPECT_TRUE(track->set_enabled(false)); 223c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) scoped_ptr<MockWebRtcAudioCapturerSink> sink( 224c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) new MockWebRtcAudioCapturerSink()); 225c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const media::AudioParameters params = capturer_->audio_parameters(); 226c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base::WaitableEvent event(false, false); 227c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) EXPECT_CALL(*sink, SetCaptureFormat(_)).WillOnce(Return()); 2283551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) EXPECT_CALL(*sink, 2293551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) CaptureData(1, 2303551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) params.sample_rate(), 2313551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) params.channels(), 2323551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) params.frames_per_buffer(), 2333551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 0, 2343551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 0, 2353551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) false, 2363551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) false)).Times(0); 237c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) track->AddSink(sink.get()); 238c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) EXPECT_FALSE(event.TimedWait(TestTimeouts::tiny_timeout())); 239c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 240c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) event.Reset(); 2413551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) EXPECT_CALL(*sink, 2423551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) CaptureData(1, 2433551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) params.sample_rate(), 2443551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) params.channels(), 2453551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) params.frames_per_buffer(), 2463551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 0, 2473551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 0, 2483551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) false, 2493551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) false)).Times(AtLeast(1)) 2503551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) .WillRepeatedly(SignalEvent(&event)); 251c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) EXPECT_TRUE(track->set_enabled(true)); 252c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) EXPECT_TRUE(event.TimedWait(TestTimeouts::tiny_timeout())); 253c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) track->RemoveSink(sink.get()); 2547d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) 2557d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) EXPECT_CALL(*capturer_source_.get(), Stop()).WillOnce(Return()); 2567d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) track->Stop(); 257c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) track = NULL; 258c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 259c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 260c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Create multiple audio tracks and enable/disable them, verify that the audio 261c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// callbacks appear/disappear. 2627d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)TEST_F(WebRtcLocalAudioTrackTest, MultipleAudioTracks) { 2637d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) EXPECT_CALL(*capturer_source_.get(), Start()).WillOnce(Return()); 26458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) RTCMediaConstraints constraints; 265c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) scoped_refptr<WebRtcLocalAudioTrack> track_1 = 26658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) WebRtcLocalAudioTrack::Create(std::string(), capturer_, NULL, 26758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) &constraints); 2687d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) track_1->Start(); 269bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch static_cast<webrtc::AudioTrackInterface*>(track_1.get())-> 270bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch GetRenderer()->AddChannel(0); 271c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) EXPECT_TRUE(track_1->enabled()); 272c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) scoped_ptr<MockWebRtcAudioCapturerSink> sink_1( 273c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) new MockWebRtcAudioCapturerSink()); 274c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const media::AudioParameters params = capturer_->audio_parameters(); 275c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base::WaitableEvent event_1(false, false); 276c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) EXPECT_CALL(*sink_1, SetCaptureFormat(_)).WillOnce(Return()); 2773551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) EXPECT_CALL(*sink_1, 27858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) CaptureData(1, 27958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) params.sample_rate(), 28058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) params.channels(), 28158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) params.frames_per_buffer(), 28258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 0, 28358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 0, 28458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) false, 28558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) false)).Times(AtLeast(1)) 2863551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) .WillRepeatedly(SignalEvent(&event_1)); 287c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) track_1->AddSink(sink_1.get()); 2887d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) EXPECT_TRUE(event_1.TimedWait(TestTimeouts::tiny_timeout())); 289c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 290c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) scoped_refptr<WebRtcLocalAudioTrack> track_2 = 29158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) WebRtcLocalAudioTrack::Create(std::string(), capturer_, NULL, 29258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) &constraints); 2937d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) track_2->Start(); 294bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch static_cast<webrtc::AudioTrackInterface*>(track_2.get())-> 295bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch GetRenderer()->AddChannel(1); 2967d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) EXPECT_TRUE(track_2->enabled()); 297c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 2987d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) // Verify both |sink_1| and |sink_2| get data. 299c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) event_1.Reset(); 300c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base::WaitableEvent event_2(false, false); 3017d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) 3027d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) scoped_ptr<MockWebRtcAudioCapturerSink> sink_2( 3037d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) new MockWebRtcAudioCapturerSink()); 3047d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) EXPECT_CALL(*sink_2, SetCaptureFormat(_)).WillOnce(Return()); 3053551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) EXPECT_CALL(*sink_1, 30658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) CaptureData(1, 30758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) params.sample_rate(), 30858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) params.channels(), 30958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) params.frames_per_buffer(), 31058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 0, 31158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 0, 31258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) false, 31358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) false)).Times(AtLeast(1)) 3143551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) .WillRepeatedly(SignalEvent(&event_1)); 3153551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) EXPECT_CALL(*sink_2, 31658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) CaptureData(1, 31758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) params.sample_rate(), 31858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) params.channels(), 31958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) params.frames_per_buffer(), 32058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 0, 32158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 0, 32258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) false, 32358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) false)).Times(AtLeast(1)) 3243551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) .WillRepeatedly(SignalEvent(&event_2)); 3257d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) track_2->AddSink(sink_2.get()); 326c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) EXPECT_TRUE(event_1.TimedWait(TestTimeouts::tiny_timeout())); 327c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) EXPECT_TRUE(event_2.TimedWait(TestTimeouts::tiny_timeout())); 328c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 329c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) track_1->RemoveSink(sink_1.get()); 3307d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) track_1->Stop(); 3317d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) track_1 = NULL; 3327d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) 3337d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) EXPECT_CALL(*capturer_source_.get(), Stop()).WillOnce(Return()); 334c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) track_2->RemoveSink(sink_2.get()); 3357d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) track_2->Stop(); 3367d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) track_2 = NULL; 3377d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)} 3387d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) 3397d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) 3407d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)// Start one track and verify the capturer is correctly starting its source. 3417d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)// And it should be fine to not to call Stop() explicitly. 3427d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)TEST_F(WebRtcLocalAudioTrackTest, StartOneAudioTrack) { 3437d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) EXPECT_CALL(*capturer_source_.get(), Start()).Times(1); 34458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) RTCMediaConstraints constraints; 3457d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) scoped_refptr<WebRtcLocalAudioTrack> track = 34658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) WebRtcLocalAudioTrack::Create(std::string(), capturer_, NULL, 34758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) &constraints); 3487d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) track->Start(); 3497d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) 3507d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) // When the track goes away, it will automatically stop the 3517d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) // |capturer_source_|. 3527d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) EXPECT_CALL(*capturer_source_.get(), Stop()); 353bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch track->Stop(); 3547d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) track = NULL; 3557d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)} 3567d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) 3577d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)// Start/Stop tracks and verify the capturer is correctly starting/stopping 3587d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)// its source. 3597d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)TEST_F(WebRtcLocalAudioTrackTest, StartAndStopAudioTracks) { 3607d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) // Starting the first audio track will start the |capturer_source_|. 361bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch base::WaitableEvent event(false, false); 3627d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) EXPECT_CALL(*capturer_source_.get(), Start()).WillOnce(SignalEvent(&event)); 36358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) RTCMediaConstraints constraints; 3647d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) scoped_refptr<WebRtcLocalAudioTrack> track_1 = 36558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) WebRtcLocalAudioTrack::Create(std::string(), capturer_, NULL, 36658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) &constraints); 367bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch static_cast<webrtc::AudioTrackInterface*>(track_1.get())-> 368bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch GetRenderer()->AddChannel(0); 3697d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) track_1->Start(); 3707d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) EXPECT_TRUE(event.TimedWait(TestTimeouts::tiny_timeout())); 3717d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) 372bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch // Verify the data flow by connecting the sink to |track_1|. 373bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch scoped_ptr<MockWebRtcAudioCapturerSink> sink( 374bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch new MockWebRtcAudioCapturerSink()); 375bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch event.Reset(); 3763551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) EXPECT_CALL(*sink, CaptureData(_, _, _, _, 0, 0, false, false)) 377bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch .Times(AnyNumber()).WillRepeatedly(Return()); 378bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch EXPECT_CALL(*sink, SetCaptureFormat(_)).Times(1); 379bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch track_1->AddSink(sink.get()); 380bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch 3817d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) // Start the second audio track will not start the |capturer_source_| 3827d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) // since it has been started. 3837d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) EXPECT_CALL(*capturer_source_.get(), Start()).Times(0); 3847d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) scoped_refptr<WebRtcLocalAudioTrack> track_2 = 38558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) WebRtcLocalAudioTrack::Create(std::string(), capturer_, NULL, 38658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) &constraints); 3877d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) track_2->Start(); 388bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch static_cast<webrtc::AudioTrackInterface*>(track_2.get())-> 389bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch GetRenderer()->AddChannel(1); 3907d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) 3917d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) // Stop the first audio track will not stop the |capturer_source_|. 3927d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) EXPECT_CALL(*capturer_source_.get(), Stop()).Times(0); 393bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch track_1->RemoveSink(sink.get()); 3947d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) track_1->Stop(); 395c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) track_1 = NULL; 3967d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) 3973551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) EXPECT_CALL(*sink, CaptureData(_, _, _, _, 0, 0, false, false)) 398bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch .Times(AnyNumber()).WillRepeatedly(Return()); 399bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch EXPECT_CALL(*sink, SetCaptureFormat(_)).Times(1); 400bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch track_2->AddSink(sink.get()); 401bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch 4027d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) // Stop the last audio track will stop the |capturer_source_|. 4037d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) event.Reset(); 4047d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) EXPECT_CALL(*capturer_source_.get(), Stop()) 4057d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) .Times(1).WillOnce(SignalEvent(&event)); 4067d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) track_2->Stop(); 407bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch track_2->RemoveSink(sink.get()); 408c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) track_2 = NULL; 4097d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) EXPECT_TRUE(event.TimedWait(TestTimeouts::tiny_timeout())); 4107d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)} 4117d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) 412bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch// Set new source to the existing capturer. 4137d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)TEST_F(WebRtcLocalAudioTrackTest, SetNewSourceForCapturerAfterStartTrack) { 4147d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) // Setup the audio track and start the track. 4157d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) EXPECT_CALL(*capturer_source_.get(), Start()).Times(1); 41658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) RTCMediaConstraints constraints; 4177d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) scoped_refptr<WebRtcLocalAudioTrack> track = 41858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) WebRtcLocalAudioTrack::Create(std::string(), capturer_, NULL, 41958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) &constraints); 4207d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) track->Start(); 4217d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) 4227d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) // Setting new source to the capturer and the track should still get packets. 4237d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) scoped_refptr<MockCapturerSource> new_source(new MockCapturerSource()); 4247d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) EXPECT_CALL(*capturer_source_.get(), Stop()); 4257d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) EXPECT_CALL(*new_source.get(), SetAutomaticGainControl(false)); 4267d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) EXPECT_CALL(*new_source.get(), Initialize(_, capturer_.get(), 0)) 4277d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) .WillOnce(Return()); 4287d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) EXPECT_CALL(*new_source.get(), Start()).WillOnce(Return()); 4297d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) capturer_->SetCapturerSource(new_source, 4307d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) media::CHANNEL_LAYOUT_STEREO, 4317d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) 48000); 4327d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) 4337d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) // Stop the track. 4347d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) EXPECT_CALL(*new_source.get(), Stop()); 4357d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) track->Stop(); 4367d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) track = NULL; 437c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 438c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 439bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch// Create a new capturer with new source, connect it to a new audio track. 440bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben MurdochTEST_F(WebRtcLocalAudioTrackTest, ConnectTracksToDifferentCapturers) { 441bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch // Setup the first audio track and start it. 442bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch EXPECT_CALL(*capturer_source_.get(), Start()).Times(1); 44358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) RTCMediaConstraints constraints; 444bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch scoped_refptr<WebRtcLocalAudioTrack> track_1 = 44558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) WebRtcLocalAudioTrack::Create(std::string(), capturer_, NULL, 44658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) &constraints); 447bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch track_1->Start(); 448bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch 449bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch // Connect a number of network channels to the |track_1|. 450bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch static const int kNumberOfNetworkChannelsForTrack1 = 2; 451bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch for (int i = 0; i < kNumberOfNetworkChannelsForTrack1; ++i) { 452bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch static_cast<webrtc::AudioTrackInterface*>(track_1.get())-> 453bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch GetRenderer()->AddChannel(i); 454bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch } 455bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch // Verify the data flow by connecting the |sink_1| to |track_1|. 456bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch scoped_ptr<MockWebRtcAudioCapturerSink> sink_1( 457bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch new MockWebRtcAudioCapturerSink()); 4583551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) EXPECT_CALL( 4593551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) *sink_1.get(), 4603551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) CaptureData( 4613551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) kNumberOfNetworkChannelsForTrack1, 48000, 2, _, 0, 0, false, false)) 462bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch .Times(AnyNumber()).WillRepeatedly(Return()); 463bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch EXPECT_CALL(*sink_1.get(), SetCaptureFormat(_)).Times(1); 464bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch track_1->AddSink(sink_1.get()); 465bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch 466bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch // Create a new capturer with new source with different audio format. 467bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch scoped_refptr<WebRtcAudioCapturer> new_capturer( 468bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch WebRtcAudioCapturer::CreateCapturer()); 469bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch scoped_refptr<MockCapturerSource> new_source(new MockCapturerSource()); 470bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch EXPECT_CALL(*new_source.get(), Initialize(_, new_capturer.get(), 0)) 471bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch .WillOnce(Return()); 472bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch EXPECT_CALL(*new_source.get(), SetAutomaticGainControl(false)) 473bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch .WillOnce(Return()); 474bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch new_capturer->SetCapturerSource(new_source, 475bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch media::CHANNEL_LAYOUT_MONO, 476bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch 44100); 477bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch 478bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch // Start the audio thread used by the new source. 479bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch scoped_ptr<FakeAudioThread> audio_thread(new FakeAudioThread(new_capturer)); 480bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch audio_thread->Start(); 481bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch 482bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch // Setup the second audio track, connect it to the new capturer and start it. 483bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch EXPECT_CALL(*new_source.get(), Start()).Times(1); 484bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch scoped_refptr<WebRtcLocalAudioTrack> track_2 = 48558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) WebRtcLocalAudioTrack::Create(std::string(), new_capturer, NULL, 48658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) &constraints); 487bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch track_2->Start(); 488bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch 489bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch // Connect a number of network channels to the |track_2|. 490bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch static const int kNumberOfNetworkChannelsForTrack2 = 3; 491bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch for (int i = 0; i < kNumberOfNetworkChannelsForTrack2; ++i) { 492bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch static_cast<webrtc::AudioTrackInterface*>(track_2.get())-> 493bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch GetRenderer()->AddChannel(i); 494bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch } 495bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch // Verify the data flow by connecting the |sink_2| to |track_2|. 496bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch scoped_ptr<MockWebRtcAudioCapturerSink> sink_2( 497bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch new MockWebRtcAudioCapturerSink()); 4983551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) EXPECT_CALL( 4993551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) *sink_2, 5003551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) CaptureData( 5013551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) kNumberOfNetworkChannelsForTrack2, 44100, 1, _, 0, 0, false, false)) 502bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch .Times(AnyNumber()).WillRepeatedly(Return()); 503bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch EXPECT_CALL(*sink_2, SetCaptureFormat(_)).Times(1); 504bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch track_2->AddSink(sink_2.get()); 505bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch 506bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch // Stop the second audio track will stop the new source. 507bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch base::WaitableEvent event(false, false); 508bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch EXPECT_CALL(*new_source.get(), Stop()).Times(1).WillOnce(SignalEvent(&event)); 509bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch track_2->Stop(); 510bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch track_2->RemoveSink(sink_2.get()); 511bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch track_2 = NULL; 512bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch EXPECT_TRUE(event.TimedWait(TestTimeouts::tiny_timeout())); 513bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch audio_thread->Stop(); 514bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch audio_thread.reset(); 515bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch 516bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch // Stop the first audio track. 517bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch EXPECT_CALL(*capturer_source_.get(), Stop()); 518bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch track_1->Stop(); 519bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch track_1 = NULL; 520bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch} 521bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch 522c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} // namespace content 523