webrtc_local_audio_track_unittest.cc revision c2e0dbddbe15c98d52c4786dac06cb8952a8ae6d
1c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Copyright 2013 The Chromium Authors. All rights reserved. 2c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 3c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// found in the LICENSE file. 4c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 5c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "base/synchronization/waitable_event.h" 6c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "base/test/test_timeouts.h" 7c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "content/renderer/media/webrtc_audio_capturer.h" 8c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "content/renderer/media/webrtc_local_audio_track.h" 9c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "media/audio/audio_parameters.h" 10c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "media/base/audio_bus.h" 11c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "media/base/audio_capturer_source.h" 12c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "testing/gmock/include/gmock/gmock.h" 13c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "testing/gtest/include/gtest/gtest.h" 14c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 15c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)using ::testing::_; 16c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)using ::testing::AtLeast; 17c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)using ::testing::Return; 18c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 19c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)namespace content { 20c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 21c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)namespace { 22c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 23c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)ACTION_P(SignalEvent, event) { 24c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) event->Signal(); 25c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 26c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 27c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// A simple thread that we use to fake the audio thread which provides data to 28c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// the |WebRtcAudioCapturer|. 29c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)class FakeAudioThread : public base::PlatformThread::Delegate { 30c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) public: 31c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) explicit FakeAudioThread(const scoped_refptr<WebRtcAudioCapturer>& capturer) 32c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) : capturer_(capturer), 33c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) thread_(base::kNullThreadHandle), 34c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) closure_(false, false) { 35c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DCHECK(capturer); 36c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) audio_bus_ = media::AudioBus::Create(capturer_->audio_parameters()); 37c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 38c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 39c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) virtual ~FakeAudioThread() { DCHECK(!thread_); } 40c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 41c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // base::PlatformThread::Delegate: 42c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) virtual void ThreadMain() OVERRIDE { 43c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) while (true) { 44c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (closure_.IsSignaled()) 45c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return; 46c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 47c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) media::AudioCapturerSource::CaptureCallback* callback = 48c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) static_cast<media::AudioCapturerSource::CaptureCallback*>(capturer_); 49c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) audio_bus_->Zero(); 50c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) callback->Capture(audio_bus_.get(), 0, 0); 51c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 52c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Sleep 1ms to yield the resource for the main thread. 53c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(1)); 54c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 55c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 56c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 57c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) void Start() { 58c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base::PlatformThread::CreateWithPriority( 59c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 0, this, &thread_, base::kThreadPriority_RealtimeAudio); 60c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) CHECK(thread_ != base::kNullThreadHandle); 61c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 62c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 63c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) void Stop() { 64c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) closure_.Signal(); 65c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base::PlatformThread::Join(thread_); 66c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) thread_ = base::kNullThreadHandle; 67c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 68c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 69c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) private: 70c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) scoped_ptr<media::AudioBus> audio_bus_; 71c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) scoped_refptr<WebRtcAudioCapturer> capturer_; 72c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base::PlatformThreadHandle thread_; 73c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base::WaitableEvent closure_; 74c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DISALLOW_COPY_AND_ASSIGN(FakeAudioThread); 75c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}; 76c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 77c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)class MockCapturerSource : public media::AudioCapturerSource { 78c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) public: 79c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) MockCapturerSource() {} 80c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) MOCK_METHOD3(Initialize, void(const media::AudioParameters& params, 81c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) CaptureCallback* callback, 82c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) int session_id)); 83c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) MOCK_METHOD0(Start, void()); 84c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) MOCK_METHOD0(Stop, void()); 85c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) MOCK_METHOD1(SetVolume, void(double volume)); 86c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) MOCK_METHOD1(SetAutomaticGainControl, void(bool enable)); 87c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 88c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) protected: 89c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) virtual ~MockCapturerSource() {} 90c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}; 91c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 92c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)class MockWebRtcAudioCapturerSink : public WebRtcAudioCapturerSink { 93c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) public: 94c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) MockWebRtcAudioCapturerSink() {} 95c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) ~MockWebRtcAudioCapturerSink() {} 96c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) MOCK_METHOD5(CaptureData, void(const int16* audio_data, 97c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) int number_of_channels, 98c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) int number_of_frames, 99c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) int audio_delay_milliseconds, 100c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) double volume)); 101c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) MOCK_METHOD1(SetCaptureFormat, void(const media::AudioParameters& params)); 102c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}; 103c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 104c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} // namespace 105c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 106c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)class WebRtcLocalAudioTrackTest : public ::testing::Test { 107c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) protected: 108c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) virtual void SetUp() OVERRIDE { 109c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) capturer_ = WebRtcAudioCapturer::CreateCapturer(); 110c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) capturer_source_ = new MockCapturerSource(); 111c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) EXPECT_CALL(*capturer_source_, Initialize(_, capturer_.get(), 0)) 112c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) .WillOnce(Return()); 113c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) capturer_->SetCapturerSource(capturer_source_, 114c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) media::CHANNEL_LAYOUT_STEREO, 115c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 48000); 116c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 117c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) EXPECT_CALL(*capturer_source_, Start()).WillOnce(Return()); 118c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) EXPECT_CALL(*capturer_source_, SetAutomaticGainControl(false)) 119c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) .WillOnce(Return()); 120c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) capturer_->Start(); 121c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) audio_thread_.reset(new FakeAudioThread(capturer_)); 122c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) audio_thread_->Start(); 123c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 124c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 125c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) virtual void TearDown() { 126c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) audio_thread_->Stop(); 127c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) audio_thread_.reset(); 128c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) EXPECT_CALL(*capturer_source_, Stop()).WillOnce(Return()); 129c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) capturer_->Stop(); 130c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 131c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 132c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) scoped_refptr<MockCapturerSource> capturer_source_; 133c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) scoped_refptr<WebRtcAudioCapturer> capturer_; 134c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) scoped_ptr<FakeAudioThread> audio_thread_; 135c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}; 136c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 137c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Creates a capturer and audio track, fakes its audio thread, and 138c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// connect/disconnect the sink to the audio track on the fly, the sink should 139c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// get data callback when the track is connected to the capturer but not when 140c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// the track is disconnected from the capturer. 141c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)TEST_F(WebRtcLocalAudioTrackTest, ConnectAndDisconnectOneSink) { 142c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) scoped_refptr<WebRtcLocalAudioTrack> track = 143c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) WebRtcLocalAudioTrack::Create(std::string(), capturer_, NULL); 144c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) EXPECT_TRUE(track->enabled()); 145c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) scoped_ptr<MockWebRtcAudioCapturerSink> sink( 146c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) new MockWebRtcAudioCapturerSink()); 147c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const media::AudioParameters params = capturer_->audio_parameters(); 148c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base::WaitableEvent event(false, false); 149c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) EXPECT_CALL(*sink, SetCaptureFormat(_)).WillOnce(Return()); 150c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) EXPECT_CALL(*sink, CaptureData( 151c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) _, params.channels(), params.frames_per_buffer(), 0, 0)) 152c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) .Times(AtLeast(1)).WillRepeatedly(SignalEvent(&event)); 153c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) track->AddSink(sink.get()); 154c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 155c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) EXPECT_TRUE(event.TimedWait(TestTimeouts::tiny_timeout())); 156c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) track->RemoveSink(sink.get()); 157c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) track = NULL; 158c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 159c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 160c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// The same setup as ConnectAndDisconnectOneSink, but enable and disable the 161c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// audio track on the fly. When the audio track is disabled, there is no data 162c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// callback to the sink; when the audio track is enabled, there comes data 163c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// callback. 164c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// TODO(xians): Enable this test after resolving the racing issue that TSAN 165c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// reports on MediaStreamTrack::enabled(); 166c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)TEST_F(WebRtcLocalAudioTrackTest, DISABLED_DisableEnableAudioTrack) { 167c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) scoped_refptr<WebRtcLocalAudioTrack> track = 168c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) WebRtcLocalAudioTrack::Create(std::string(), capturer_, NULL); 169c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) EXPECT_TRUE(track->enabled()); 170c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) EXPECT_TRUE(track->set_enabled(false)); 171c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) scoped_ptr<MockWebRtcAudioCapturerSink> sink( 172c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) new MockWebRtcAudioCapturerSink()); 173c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const media::AudioParameters params = capturer_->audio_parameters(); 174c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base::WaitableEvent event(false, false); 175c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) EXPECT_CALL(*sink, SetCaptureFormat(_)).WillOnce(Return()); 176c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) EXPECT_CALL(*sink, CaptureData( 177c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) _, params.channels(), params.frames_per_buffer(), 0, 0)) 178c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) .Times(0); 179c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) track->AddSink(sink.get()); 180c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) EXPECT_FALSE(event.TimedWait(TestTimeouts::tiny_timeout())); 181c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 182c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) event.Reset(); 183c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) EXPECT_CALL(*sink, CaptureData( 184c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) _, params.channels(), params.frames_per_buffer(), 0, 0)) 185c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) .Times(AtLeast(1)).WillRepeatedly(SignalEvent(&event)); 186c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) EXPECT_TRUE(track->set_enabled(true)); 187c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) EXPECT_TRUE(event.TimedWait(TestTimeouts::tiny_timeout())); 188c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) track->RemoveSink(sink.get()); 189c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) track = NULL; 190c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 191c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 192c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Create multiple audio tracks and enable/disable them, verify that the audio 193c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// callbacks appear/disappear. 194c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// TODO(xians): Enable the test after the racing problem is resolved. 195c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)TEST_F(WebRtcLocalAudioTrackTest, DISABLED_MultipleAudioTracks) { 196c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) scoped_refptr<WebRtcLocalAudioTrack> track_1 = 197c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) WebRtcLocalAudioTrack::Create(std::string(), capturer_, NULL); 198c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) EXPECT_TRUE(track_1->enabled()); 199c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) scoped_ptr<MockWebRtcAudioCapturerSink> sink_1( 200c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) new MockWebRtcAudioCapturerSink()); 201c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const media::AudioParameters params = capturer_->audio_parameters(); 202c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base::WaitableEvent event_1(false, false); 203c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) EXPECT_CALL(*sink_1, SetCaptureFormat(_)).WillOnce(Return()); 204c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) EXPECT_CALL(*sink_1, CaptureData( 205c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) _, params.channels(), params.frames_per_buffer(), 0, 0)) 206c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) .Times(AtLeast(1)).WillRepeatedly(SignalEvent(&event_1)); 207c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) track_1->AddSink(sink_1.get()); 208c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 209c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) scoped_refptr<WebRtcLocalAudioTrack> track_2 = 210c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) WebRtcLocalAudioTrack::Create(std::string(), capturer_, NULL); 211c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) EXPECT_TRUE(track_2->set_enabled(false)); 212c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) scoped_ptr<MockWebRtcAudioCapturerSink> sink_2( 213c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) new MockWebRtcAudioCapturerSink()); 214c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) EXPECT_CALL(*sink_2, SetCaptureFormat(_)).WillOnce(Return()); 215c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) EXPECT_CALL(*sink_2, CaptureData( 216c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) _, params.channels(), params.frames_per_buffer(), 0, 0)) 217c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) .Times(0); 218c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) track_2->AddSink(sink_2.get()); 219c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) EXPECT_TRUE(event_1.TimedWait(TestTimeouts::tiny_timeout())); 220c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 221c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 222c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Enable |track_2|, and verify the data callback comes to |sink_2|; 223c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) event_1.Reset(); 224c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base::WaitableEvent event_2(false, false); 225c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) EXPECT_CALL(*sink_1, CaptureData( 226c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) _, params.channels(), params.frames_per_buffer(), 0, 0)) 227c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) .Times(AtLeast(1)).WillRepeatedly(SignalEvent(&event_1)); 228c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) EXPECT_CALL(*sink_2, CaptureData( 229c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) _, params.channels(), params.frames_per_buffer(), 0, 0)) 230c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) .Times(AtLeast(1)).WillRepeatedly(SignalEvent(&event_2)); 231c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) EXPECT_TRUE(track_2->set_enabled(true)); 232c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) EXPECT_TRUE(event_1.TimedWait(TestTimeouts::tiny_timeout())); 233c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) EXPECT_TRUE(event_2.TimedWait(TestTimeouts::tiny_timeout())); 234c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 235c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) track_1->RemoveSink(sink_1.get()); 236c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) track_2->RemoveSink(sink_2.get()); 237c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) track_1 = NULL; 238c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) track_2 = NULL; 239c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 240c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 241c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} // namespace content 242