webrtc_local_audio_track_unittest.cc revision 3551c9c881056c480085172ff9840cab31610854
1fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// Copyright 2013 The Chromium Authors. All rights reserved. 2fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// Use of this source code is governed by a BSD-style license that can be 3d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville// found in the LICENSE file. 4d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville 5d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville#include "base/synchronization/waitable_event.h" 6fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#include "base/test/test_timeouts.h" 7fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#include "content/renderer/media/webrtc_audio_capturer.h" 8fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#include "content/renderer/media/webrtc_local_audio_track.h" 9fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#include "media/audio/audio_parameters.h" 10fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#include "media/base/audio_bus.h" 11fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#include "media/base/audio_capturer_source.h" 12d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville#include "testing/gmock/include/gmock/gmock.h" 13d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville#include "testing/gtest/include/gtest/gtest.h" 14d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville#include "third_party/libjingle/source/talk/app/webrtc/mediastreaminterface.h" 15fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 16fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Savilleusing ::testing::_; 17fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Savilleusing ::testing::AnyNumber; 18fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Savilleusing ::testing::AtLeast; 19fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Savilleusing ::testing::Return; 20fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 21fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Savillenamespace content { 22fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 23fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Savillenamespace { 24fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 25fbaaef999ba563838ebd00874ed8a1c01fbf286dWink SavilleACTION_P(SignalEvent, event) { 26fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville event->Signal(); 27fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville} 28fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 29fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// A simple thread that we use to fake the audio thread which provides data to 30fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// the |WebRtcAudioCapturer|. 31fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Savilleclass FakeAudioThread : public base::PlatformThread::Delegate { 32fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville public: 33fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville explicit FakeAudioThread(const scoped_refptr<WebRtcAudioCapturer>& capturer) 34fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville : capturer_(capturer), 35fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville thread_(), 36fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville closure_(false, false) { 37fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville DCHECK(capturer.get()); 38fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville audio_bus_ = media::AudioBus::Create(capturer_->audio_parameters()); 39fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 40fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 41fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville virtual ~FakeAudioThread() { DCHECK(thread_.is_null()); } 42fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 43fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville // base::PlatformThread::Delegate: 44fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville virtual void ThreadMain() OVERRIDE { 45fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville while (true) { 46fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville if (closure_.IsSignaled()) 47fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville return; 48fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 49fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville media::AudioCapturerSource::CaptureCallback* callback = 50fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville static_cast<media::AudioCapturerSource::CaptureCallback*>( 51fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville capturer_.get()); 52fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville audio_bus_->Zero(); 53fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville callback->Capture(audio_bus_.get(), 0, 0, false); 54fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 55fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville // Sleep 1ms to yield the resource for the main thread. 56fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(1)); 57fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 58fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 59fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 60fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville void Start() { 61fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville base::PlatformThread::CreateWithPriority( 62fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 0, this, &thread_, base::kThreadPriority_RealtimeAudio); 63fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville CHECK(!thread_.is_null()); 64fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 65fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 66fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville void Stop() { 67fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville closure_.Signal(); 68fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville base::PlatformThread::Join(thread_); 69fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville thread_ = base::PlatformThreadHandle(); 70fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 71fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 72fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville private: 73fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville scoped_ptr<media::AudioBus> audio_bus_; 74fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville scoped_refptr<WebRtcAudioCapturer> capturer_; 75fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville base::PlatformThreadHandle thread_; 76fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville base::WaitableEvent closure_; 77fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville DISALLOW_COPY_AND_ASSIGN(FakeAudioThread); 78fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville}; 79fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 80fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Savilleclass MockCapturerSource : public media::AudioCapturerSource { 81fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville public: 82fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville MockCapturerSource() {} 83fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville MOCK_METHOD3(Initialize, void(const media::AudioParameters& params, 84fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville CaptureCallback* callback, 85fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville int session_id)); 86fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville MOCK_METHOD0(Start, void()); 87fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville MOCK_METHOD0(Stop, void()); 88fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville MOCK_METHOD1(SetVolume, void(double volume)); 89fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville MOCK_METHOD1(SetAutomaticGainControl, void(bool enable)); 90fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 91fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville protected: 92fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville virtual ~MockCapturerSource() {} 93fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville}; 94fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 95fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Savilleclass MockWebRtcAudioCapturerSink : public WebRtcAudioCapturerSink { 96fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville public: 97fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville MockWebRtcAudioCapturerSink() {} 98fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville ~MockWebRtcAudioCapturerSink() {} 99fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville int CaptureData(const std::vector<int>& channels, 100fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville const int16* audio_data, 101fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville int sample_rate, 102fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville int number_of_channels, 10364d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci int number_of_frames, 10464d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci int audio_delay_milliseconds, 10564d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci int current_volume, 106fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville bool need_audio_processing, 107fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville bool key_pressed) OVERRIDE { 108fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville CaptureData(channels.size(), 109fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville sample_rate, 110fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville number_of_channels, 111fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville number_of_frames, 112fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville audio_delay_milliseconds, 113fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville current_volume, 114fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville need_audio_processing, 115fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville key_pressed); 11664d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci return 0; 117fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 118fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville MOCK_METHOD8(CaptureData, 119fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville void(int number_of_network_channels, 120fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville int sample_rate, 121fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville int number_of_channels, 122fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville int number_of_frames, 123fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville int audio_delay_milliseconds, 12464d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci int current_volume, 12564d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci bool need_audio_processing, 12664d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci bool key_pressed)); 12764d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci MOCK_METHOD1(SetCaptureFormat, void(const media::AudioParameters& params)); 12864d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci}; 12964d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci 13064d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci} // namespace 13164d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci 13264d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazciclass WebRtcLocalAudioTrackTest : public ::testing::Test { 13364d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci protected: 13464d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci virtual void SetUp() OVERRIDE { 13564d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci capturer_ = WebRtcAudioCapturer::CreateCapturer(); 13664d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci capturer_source_ = new MockCapturerSource(); 13764d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci EXPECT_CALL(*capturer_source_.get(), Initialize(_, capturer_.get(), 0)) 13864d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci .WillOnce(Return()); 13964d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci capturer_->SetCapturerSource(capturer_source_, 140fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville media::CHANNEL_LAYOUT_STEREO, 141fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 48000); 142fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 143fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville EXPECT_CALL(*capturer_source_.get(), SetAutomaticGainControl(false)) 144fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville .WillOnce(Return()); 145fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 146fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville // Start the audio thread used by the |capturer_source_|. 147fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville audio_thread_.reset(new FakeAudioThread(capturer_)); 148fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville audio_thread_->Start(); 149fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 150 151 virtual void TearDown() { 152 audio_thread_->Stop(); 153 audio_thread_.reset(); 154 } 155 156 scoped_refptr<MockCapturerSource> capturer_source_; 157 scoped_refptr<WebRtcAudioCapturer> capturer_; 158 scoped_ptr<FakeAudioThread> audio_thread_; 159}; 160 161// Creates a capturer and audio track, fakes its audio thread, and 162// connect/disconnect the sink to the audio track on the fly, the sink should 163// get data callback when the track is connected to the capturer but not when 164// the track is disconnected from the capturer. 165TEST_F(WebRtcLocalAudioTrackTest, ConnectAndDisconnectOneSink) { 166 EXPECT_CALL(*capturer_source_.get(), Start()).WillOnce(Return()); 167 scoped_refptr<WebRtcLocalAudioTrack> track = 168 WebRtcLocalAudioTrack::Create(std::string(), capturer_, NULL); 169 track->Start(); 170 EXPECT_TRUE(track->enabled()); 171 172 // Connect a number of network channels to the audio track. 173 static const int kNumberOfNetworkChannels = 4; 174 for (int i = 0; i < kNumberOfNetworkChannels; ++i) { 175 static_cast<webrtc::AudioTrackInterface*>(track.get())-> 176 GetRenderer()->AddChannel(i); 177 } 178 scoped_ptr<MockWebRtcAudioCapturerSink> sink( 179 new MockWebRtcAudioCapturerSink()); 180 const media::AudioParameters params = capturer_->audio_parameters(); 181 base::WaitableEvent event(false, false); 182 EXPECT_CALL(*sink, SetCaptureFormat(_)).WillOnce(Return()); 183 EXPECT_CALL(*sink, 184 CaptureData(kNumberOfNetworkChannels, 185 params.sample_rate(), 186 params.channels(), 187 params.frames_per_buffer(), 188 0, 189 0, 190 false, 191 false)).Times(AtLeast(1)) 192 .WillRepeatedly(SignalEvent(&event)); 193 track->AddSink(sink.get()); 194 195 EXPECT_TRUE(event.TimedWait(TestTimeouts::tiny_timeout())); 196 track->RemoveSink(sink.get()); 197 198 EXPECT_CALL(*capturer_source_.get(), Stop()).WillOnce(Return()); 199 track->Stop(); 200 track = NULL; 201} 202 203// The same setup as ConnectAndDisconnectOneSink, but enable and disable the 204// audio track on the fly. When the audio track is disabled, there is no data 205// callback to the sink; when the audio track is enabled, there comes data 206// callback. 207// TODO(xians): Enable this test after resolving the racing issue that TSAN 208// reports on MediaStreamTrack::enabled(); 209TEST_F(WebRtcLocalAudioTrackTest, DISABLED_DisableEnableAudioTrack) { 210 EXPECT_CALL(*capturer_source_.get(), Start()).WillOnce(Return()); 211 scoped_refptr<WebRtcLocalAudioTrack> track = 212 WebRtcLocalAudioTrack::Create(std::string(), capturer_, NULL); 213 track->Start(); 214 static_cast<webrtc::AudioTrackInterface*>(track.get())-> 215 GetRenderer()->AddChannel(0); 216 EXPECT_TRUE(track->enabled()); 217 EXPECT_TRUE(track->set_enabled(false)); 218 scoped_ptr<MockWebRtcAudioCapturerSink> sink( 219 new MockWebRtcAudioCapturerSink()); 220 const media::AudioParameters params = capturer_->audio_parameters(); 221 base::WaitableEvent event(false, false); 222 EXPECT_CALL(*sink, SetCaptureFormat(_)).WillOnce(Return()); 223 EXPECT_CALL(*sink, 224 CaptureData(1, 225 params.sample_rate(), 226 params.channels(), 227 params.frames_per_buffer(), 228 0, 229 0, 230 false, 231 false)).Times(0); 232 track->AddSink(sink.get()); 233 EXPECT_FALSE(event.TimedWait(TestTimeouts::tiny_timeout())); 234 235 event.Reset(); 236 EXPECT_CALL(*sink, 237 CaptureData(1, 238 params.sample_rate(), 239 params.channels(), 240 params.frames_per_buffer(), 241 0, 242 0, 243 false, 244 false)).Times(AtLeast(1)) 245 .WillRepeatedly(SignalEvent(&event)); 246 EXPECT_TRUE(track->set_enabled(true)); 247 EXPECT_TRUE(event.TimedWait(TestTimeouts::tiny_timeout())); 248 track->RemoveSink(sink.get()); 249 250 EXPECT_CALL(*capturer_source_.get(), Stop()).WillOnce(Return()); 251 track->Stop(); 252 track = NULL; 253} 254 255// Create multiple audio tracks and enable/disable them, verify that the audio 256// callbacks appear/disappear. 257TEST_F(WebRtcLocalAudioTrackTest, MultipleAudioTracks) { 258 EXPECT_CALL(*capturer_source_.get(), Start()).WillOnce(Return()); 259 scoped_refptr<WebRtcLocalAudioTrack> track_1 = 260 WebRtcLocalAudioTrack::Create(std::string(), capturer_, NULL); 261 track_1->Start(); 262 static_cast<webrtc::AudioTrackInterface*>(track_1.get())-> 263 GetRenderer()->AddChannel(0); 264 EXPECT_TRUE(track_1->enabled()); 265 scoped_ptr<MockWebRtcAudioCapturerSink> sink_1( 266 new MockWebRtcAudioCapturerSink()); 267 const media::AudioParameters params = capturer_->audio_parameters(); 268 base::WaitableEvent event_1(false, false); 269 EXPECT_CALL(*sink_1, SetCaptureFormat(_)).WillOnce(Return()); 270 EXPECT_CALL(*sink_1, 271 CaptureData(1, 272 params.sample_rate(), 273 params.channels(), 274 params.frames_per_buffer(), 275 0, 276 0, 277 false, 278 false)).Times(AtLeast(1)) 279 .WillRepeatedly(SignalEvent(&event_1)); 280 track_1->AddSink(sink_1.get()); 281 EXPECT_TRUE(event_1.TimedWait(TestTimeouts::tiny_timeout())); 282 283 scoped_refptr<WebRtcLocalAudioTrack> track_2 = 284 WebRtcLocalAudioTrack::Create(std::string(), capturer_, NULL); 285 track_2->Start(); 286 static_cast<webrtc::AudioTrackInterface*>(track_2.get())-> 287 GetRenderer()->AddChannel(1); 288 EXPECT_TRUE(track_2->enabled()); 289 290 // Verify both |sink_1| and |sink_2| get data. 291 event_1.Reset(); 292 base::WaitableEvent event_2(false, false); 293 294 scoped_ptr<MockWebRtcAudioCapturerSink> sink_2( 295 new MockWebRtcAudioCapturerSink()); 296 EXPECT_CALL(*sink_2, SetCaptureFormat(_)).WillOnce(Return()); 297 EXPECT_CALL(*sink_1, 298 CaptureData(1, 299 params.sample_rate(), 300 params.channels(), 301 params.frames_per_buffer(), 302 0, 303 0, 304 false, 305 false)).Times(AtLeast(1)) 306 .WillRepeatedly(SignalEvent(&event_1)); 307 EXPECT_CALL(*sink_2, 308 CaptureData(1, 309 params.sample_rate(), 310 params.channels(), 311 params.frames_per_buffer(), 312 0, 313 0, 314 false, 315 false)).Times(AtLeast(1)) 316 .WillRepeatedly(SignalEvent(&event_2)); 317 track_2->AddSink(sink_2.get()); 318 EXPECT_TRUE(event_1.TimedWait(TestTimeouts::tiny_timeout())); 319 EXPECT_TRUE(event_2.TimedWait(TestTimeouts::tiny_timeout())); 320 321 track_1->RemoveSink(sink_1.get()); 322 track_1->Stop(); 323 track_1 = NULL; 324 325 EXPECT_CALL(*capturer_source_.get(), Stop()).WillOnce(Return()); 326 track_2->RemoveSink(sink_2.get()); 327 track_2->Stop(); 328 track_2 = NULL; 329} 330 331 332// Start one track and verify the capturer is correctly starting its source. 333// And it should be fine to not to call Stop() explicitly. 334TEST_F(WebRtcLocalAudioTrackTest, StartOneAudioTrack) { 335 EXPECT_CALL(*capturer_source_.get(), Start()).Times(1); 336 scoped_refptr<WebRtcLocalAudioTrack> track = 337 WebRtcLocalAudioTrack::Create(std::string(), capturer_, NULL); 338 track->Start(); 339 340 // When the track goes away, it will automatically stop the 341 // |capturer_source_|. 342 EXPECT_CALL(*capturer_source_.get(), Stop()); 343 track->Stop(); 344 track = NULL; 345} 346 347// Start/Stop tracks and verify the capturer is correctly starting/stopping 348// its source. 349TEST_F(WebRtcLocalAudioTrackTest, StartAndStopAudioTracks) { 350 // Starting the first audio track will start the |capturer_source_|. 351 base::WaitableEvent event(false, false); 352 EXPECT_CALL(*capturer_source_.get(), Start()).WillOnce(SignalEvent(&event)); 353 scoped_refptr<WebRtcLocalAudioTrack> track_1 = 354 WebRtcLocalAudioTrack::Create(std::string(), capturer_, NULL); 355 static_cast<webrtc::AudioTrackInterface*>(track_1.get())-> 356 GetRenderer()->AddChannel(0); 357 track_1->Start(); 358 EXPECT_TRUE(event.TimedWait(TestTimeouts::tiny_timeout())); 359 360 // Verify the data flow by connecting the sink to |track_1|. 361 scoped_ptr<MockWebRtcAudioCapturerSink> sink( 362 new MockWebRtcAudioCapturerSink()); 363 event.Reset(); 364 EXPECT_CALL(*sink, CaptureData(_, _, _, _, 0, 0, false, false)) 365 .Times(AnyNumber()).WillRepeatedly(Return()); 366 EXPECT_CALL(*sink, SetCaptureFormat(_)).Times(1); 367 track_1->AddSink(sink.get()); 368 369 // Start the second audio track will not start the |capturer_source_| 370 // since it has been started. 371 EXPECT_CALL(*capturer_source_.get(), Start()).Times(0); 372 scoped_refptr<WebRtcLocalAudioTrack> track_2 = 373 WebRtcLocalAudioTrack::Create(std::string(), capturer_, NULL); 374 track_2->Start(); 375 static_cast<webrtc::AudioTrackInterface*>(track_2.get())-> 376 GetRenderer()->AddChannel(1); 377 378 // Stop the first audio track will not stop the |capturer_source_|. 379 EXPECT_CALL(*capturer_source_.get(), Stop()).Times(0); 380 track_1->RemoveSink(sink.get()); 381 track_1->Stop(); 382 track_1 = NULL; 383 384 EXPECT_CALL(*sink, CaptureData(_, _, _, _, 0, 0, false, false)) 385 .Times(AnyNumber()).WillRepeatedly(Return()); 386 EXPECT_CALL(*sink, SetCaptureFormat(_)).Times(1); 387 track_2->AddSink(sink.get()); 388 389 // Stop the last audio track will stop the |capturer_source_|. 390 event.Reset(); 391 EXPECT_CALL(*capturer_source_.get(), Stop()) 392 .Times(1).WillOnce(SignalEvent(&event)); 393 track_2->Stop(); 394 track_2->RemoveSink(sink.get()); 395 track_2 = NULL; 396 EXPECT_TRUE(event.TimedWait(TestTimeouts::tiny_timeout())); 397} 398 399// Set new source to the existing capturer. 400TEST_F(WebRtcLocalAudioTrackTest, SetNewSourceForCapturerAfterStartTrack) { 401 // Setup the audio track and start the track. 402 EXPECT_CALL(*capturer_source_.get(), Start()).Times(1); 403 scoped_refptr<WebRtcLocalAudioTrack> track = 404 WebRtcLocalAudioTrack::Create(std::string(), capturer_, NULL); 405 track->Start(); 406 407 // Setting new source to the capturer and the track should still get packets. 408 scoped_refptr<MockCapturerSource> new_source(new MockCapturerSource()); 409 EXPECT_CALL(*capturer_source_.get(), Stop()); 410 EXPECT_CALL(*new_source.get(), SetAutomaticGainControl(false)); 411 EXPECT_CALL(*new_source.get(), Initialize(_, capturer_.get(), 0)) 412 .WillOnce(Return()); 413 EXPECT_CALL(*new_source.get(), Start()).WillOnce(Return()); 414 capturer_->SetCapturerSource(new_source, 415 media::CHANNEL_LAYOUT_STEREO, 416 48000); 417 418 // Stop the track. 419 EXPECT_CALL(*new_source.get(), Stop()); 420 track->Stop(); 421 track = NULL; 422} 423 424// Create a new capturer with new source, connect it to a new audio track. 425TEST_F(WebRtcLocalAudioTrackTest, ConnectTracksToDifferentCapturers) { 426 // Setup the first audio track and start it. 427 EXPECT_CALL(*capturer_source_.get(), Start()).Times(1); 428 scoped_refptr<WebRtcLocalAudioTrack> track_1 = 429 WebRtcLocalAudioTrack::Create(std::string(), capturer_, NULL); 430 track_1->Start(); 431 432 // Connect a number of network channels to the |track_1|. 433 static const int kNumberOfNetworkChannelsForTrack1 = 2; 434 for (int i = 0; i < kNumberOfNetworkChannelsForTrack1; ++i) { 435 static_cast<webrtc::AudioTrackInterface*>(track_1.get())-> 436 GetRenderer()->AddChannel(i); 437 } 438 // Verify the data flow by connecting the |sink_1| to |track_1|. 439 scoped_ptr<MockWebRtcAudioCapturerSink> sink_1( 440 new MockWebRtcAudioCapturerSink()); 441 EXPECT_CALL( 442 *sink_1.get(), 443 CaptureData( 444 kNumberOfNetworkChannelsForTrack1, 48000, 2, _, 0, 0, false, false)) 445 .Times(AnyNumber()).WillRepeatedly(Return()); 446 EXPECT_CALL(*sink_1.get(), SetCaptureFormat(_)).Times(1); 447 track_1->AddSink(sink_1.get()); 448 449 // Create a new capturer with new source with different audio format. 450 scoped_refptr<WebRtcAudioCapturer> new_capturer( 451 WebRtcAudioCapturer::CreateCapturer()); 452 scoped_refptr<MockCapturerSource> new_source(new MockCapturerSource()); 453 EXPECT_CALL(*new_source.get(), Initialize(_, new_capturer.get(), 0)) 454 .WillOnce(Return()); 455 EXPECT_CALL(*new_source.get(), SetAutomaticGainControl(false)) 456 .WillOnce(Return()); 457 new_capturer->SetCapturerSource(new_source, 458 media::CHANNEL_LAYOUT_MONO, 459 44100); 460 461 // Start the audio thread used by the new source. 462 scoped_ptr<FakeAudioThread> audio_thread(new FakeAudioThread(new_capturer)); 463 audio_thread->Start(); 464 465 // Setup the second audio track, connect it to the new capturer and start it. 466 EXPECT_CALL(*new_source.get(), Start()).Times(1); 467 scoped_refptr<WebRtcLocalAudioTrack> track_2 = 468 WebRtcLocalAudioTrack::Create(std::string(), new_capturer, NULL); 469 track_2->Start(); 470 471 // Connect a number of network channels to the |track_2|. 472 static const int kNumberOfNetworkChannelsForTrack2 = 3; 473 for (int i = 0; i < kNumberOfNetworkChannelsForTrack2; ++i) { 474 static_cast<webrtc::AudioTrackInterface*>(track_2.get())-> 475 GetRenderer()->AddChannel(i); 476 } 477 // Verify the data flow by connecting the |sink_2| to |track_2|. 478 scoped_ptr<MockWebRtcAudioCapturerSink> sink_2( 479 new MockWebRtcAudioCapturerSink()); 480 EXPECT_CALL( 481 *sink_2, 482 CaptureData( 483 kNumberOfNetworkChannelsForTrack2, 44100, 1, _, 0, 0, false, false)) 484 .Times(AnyNumber()).WillRepeatedly(Return()); 485 EXPECT_CALL(*sink_2, SetCaptureFormat(_)).Times(1); 486 track_2->AddSink(sink_2.get()); 487 488 // Stop the second audio track will stop the new source. 489 base::WaitableEvent event(false, false); 490 EXPECT_CALL(*new_source.get(), Stop()).Times(1).WillOnce(SignalEvent(&event)); 491 track_2->Stop(); 492 track_2->RemoveSink(sink_2.get()); 493 track_2 = NULL; 494 EXPECT_TRUE(event.TimedWait(TestTimeouts::tiny_timeout())); 495 audio_thread->Stop(); 496 audio_thread.reset(); 497 498 // Stop the first audio track. 499 EXPECT_CALL(*capturer_source_.get(), Stop()); 500 track_1->Stop(); 501 track_1 = NULL; 502} 503 504} // namespace content 505