webrtc_local_audio_track_unittest.cc revision 868fa2fe829687343ffae624259930155e16dbd8
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),
3390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      thread_(),
34c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      closure_(false, false) {
35868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    DCHECK(capturer.get());
36c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    audio_bus_ = media::AudioBus::Create(capturer_->audio_parameters());
37c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
38c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
3990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  virtual ~FakeAudioThread() { DCHECK(thread_.is_null()); }
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 =
48868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)          static_cast<media::AudioCapturerSource::CaptureCallback*>(
49868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)              capturer_.get());
50c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      audio_bus_->Zero();
51c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      callback->Capture(audio_bus_.get(), 0, 0);
52c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
53c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      // Sleep 1ms to yield the resource for the main thread.
54c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(1));
55c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    }
56c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
57c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
58c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  void Start() {
59c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    base::PlatformThread::CreateWithPriority(
60c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        0, this, &thread_, base::kThreadPriority_RealtimeAudio);
6190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    CHECK(!thread_.is_null());
62c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
63c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
64c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  void Stop() {
65c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    closure_.Signal();
66c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    base::PlatformThread::Join(thread_);
6790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    thread_ = base::PlatformThreadHandle();
68c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
69c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
70c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) private:
71c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  scoped_ptr<media::AudioBus> audio_bus_;
72c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  scoped_refptr<WebRtcAudioCapturer> capturer_;
73c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  base::PlatformThreadHandle thread_;
74c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  base::WaitableEvent closure_;
75c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(FakeAudioThread);
76c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)};
77c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
78c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)class MockCapturerSource : public media::AudioCapturerSource {
79c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) public:
80c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  MockCapturerSource() {}
81c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  MOCK_METHOD3(Initialize, void(const media::AudioParameters& params,
82c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                CaptureCallback* callback,
83c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                int session_id));
84c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  MOCK_METHOD0(Start, void());
85c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  MOCK_METHOD0(Stop, void());
86c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  MOCK_METHOD1(SetVolume, void(double volume));
87c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  MOCK_METHOD1(SetAutomaticGainControl, void(bool enable));
88c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
89c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) protected:
90c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  virtual ~MockCapturerSource() {}
91c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)};
92c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
93c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)class MockWebRtcAudioCapturerSink : public WebRtcAudioCapturerSink {
94c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) public:
95c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  MockWebRtcAudioCapturerSink() {}
96c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ~MockWebRtcAudioCapturerSink() {}
97c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  MOCK_METHOD5(CaptureData, void(const int16* audio_data,
98c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                 int number_of_channels,
99c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                 int number_of_frames,
100c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                 int audio_delay_milliseconds,
101c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                 double volume));
102c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  MOCK_METHOD1(SetCaptureFormat, void(const media::AudioParameters& params));
103c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)};
104c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
105c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}  // namespace
106c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
107c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)class WebRtcLocalAudioTrackTest : public ::testing::Test {
108c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) protected:
109c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  virtual void SetUp() OVERRIDE {
110c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    capturer_ = WebRtcAudioCapturer::CreateCapturer();
111c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    capturer_source_ = new MockCapturerSource();
112868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    EXPECT_CALL(*capturer_source_.get(), Initialize(_, capturer_.get(), 0))
113c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        .WillOnce(Return());
114c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    capturer_->SetCapturerSource(capturer_source_,
115c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                 media::CHANNEL_LAYOUT_STEREO,
116c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                 48000);
117c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
118868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    EXPECT_CALL(*capturer_source_.get(), Start()).WillOnce(Return());
119868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    EXPECT_CALL(*capturer_source_.get(), SetAutomaticGainControl(false))
120c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        .WillOnce(Return());
121c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    capturer_->Start();
122c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    audio_thread_.reset(new FakeAudioThread(capturer_));
123c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    audio_thread_->Start();
124c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
125c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
126c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  virtual void TearDown() {
127c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    audio_thread_->Stop();
128c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    audio_thread_.reset();
129868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    EXPECT_CALL(*capturer_source_.get(), Stop()).WillOnce(Return());
130c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    capturer_->Stop();
131c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
132c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
133c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  scoped_refptr<MockCapturerSource> capturer_source_;
134c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  scoped_refptr<WebRtcAudioCapturer> capturer_;
135c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  scoped_ptr<FakeAudioThread> audio_thread_;
136c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)};
137c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
138c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Creates a capturer and audio track, fakes its audio thread, and
139c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// connect/disconnect the sink to the audio track on the fly, the sink should
140c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// get data callback when the track is connected to the capturer but not when
141c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// the track is disconnected from the capturer.
142c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)TEST_F(WebRtcLocalAudioTrackTest, ConnectAndDisconnectOneSink) {
143c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  scoped_refptr<WebRtcLocalAudioTrack> track =
144c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      WebRtcLocalAudioTrack::Create(std::string(), capturer_, NULL);
145c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_TRUE(track->enabled());
146c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  scoped_ptr<MockWebRtcAudioCapturerSink> sink(
147c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      new MockWebRtcAudioCapturerSink());
148c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  const media::AudioParameters params = capturer_->audio_parameters();
149c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  base::WaitableEvent event(false, false);
150c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_CALL(*sink, SetCaptureFormat(_)).WillOnce(Return());
151c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_CALL(*sink, CaptureData(
152c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      _, params.channels(), params.frames_per_buffer(), 0, 0))
153c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      .Times(AtLeast(1)).WillRepeatedly(SignalEvent(&event));
154c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  track->AddSink(sink.get());
155c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
156c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_TRUE(event.TimedWait(TestTimeouts::tiny_timeout()));
157c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  track->RemoveSink(sink.get());
158c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  track = NULL;
159c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
160c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
161c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// The same setup as ConnectAndDisconnectOneSink, but enable and disable the
162c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// audio track on the fly. When the audio track is disabled, there is no data
163c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// callback to the sink; when the audio track is enabled, there comes data
164c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// callback.
165c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// TODO(xians): Enable this test after resolving the racing issue that TSAN
166c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// reports on MediaStreamTrack::enabled();
167c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)TEST_F(WebRtcLocalAudioTrackTest, DISABLED_DisableEnableAudioTrack) {
168c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  scoped_refptr<WebRtcLocalAudioTrack> track =
169c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    WebRtcLocalAudioTrack::Create(std::string(), capturer_, NULL);
170c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_TRUE(track->enabled());
171c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_TRUE(track->set_enabled(false));
172c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  scoped_ptr<MockWebRtcAudioCapturerSink> sink(
173c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      new MockWebRtcAudioCapturerSink());
174c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  const media::AudioParameters params = capturer_->audio_parameters();
175c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  base::WaitableEvent event(false, false);
176c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_CALL(*sink, SetCaptureFormat(_)).WillOnce(Return());
177c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_CALL(*sink, CaptureData(
178c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      _, params.channels(), params.frames_per_buffer(), 0, 0))
179c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      .Times(0);
180c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  track->AddSink(sink.get());
181c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_FALSE(event.TimedWait(TestTimeouts::tiny_timeout()));
182c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
183c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  event.Reset();
184c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_CALL(*sink, CaptureData(
185c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      _, params.channels(), params.frames_per_buffer(), 0, 0))
186c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      .Times(AtLeast(1)).WillRepeatedly(SignalEvent(&event));
187c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_TRUE(track->set_enabled(true));
188c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_TRUE(event.TimedWait(TestTimeouts::tiny_timeout()));
189c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  track->RemoveSink(sink.get());
190c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  track = NULL;
191c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
192c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
193c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Create multiple audio tracks and enable/disable them, verify that the audio
194c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// callbacks appear/disappear.
195c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// TODO(xians): Enable the test after the racing problem is resolved.
196c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)TEST_F(WebRtcLocalAudioTrackTest, DISABLED_MultipleAudioTracks) {
197c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  scoped_refptr<WebRtcLocalAudioTrack> track_1 =
198c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    WebRtcLocalAudioTrack::Create(std::string(), capturer_, NULL);
199c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_TRUE(track_1->enabled());
200c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  scoped_ptr<MockWebRtcAudioCapturerSink> sink_1(
201c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      new MockWebRtcAudioCapturerSink());
202c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  const media::AudioParameters params = capturer_->audio_parameters();
203c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  base::WaitableEvent event_1(false, false);
204c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_CALL(*sink_1, SetCaptureFormat(_)).WillOnce(Return());
205c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_CALL(*sink_1, CaptureData(
206c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      _, params.channels(), params.frames_per_buffer(), 0, 0))
207c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      .Times(AtLeast(1)).WillRepeatedly(SignalEvent(&event_1));
208c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  track_1->AddSink(sink_1.get());
209c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
210c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  scoped_refptr<WebRtcLocalAudioTrack> track_2 =
211c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    WebRtcLocalAudioTrack::Create(std::string(), capturer_, NULL);
212c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_TRUE(track_2->set_enabled(false));
213c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  scoped_ptr<MockWebRtcAudioCapturerSink> sink_2(
214c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      new MockWebRtcAudioCapturerSink());
215c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_CALL(*sink_2, SetCaptureFormat(_)).WillOnce(Return());
216c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_CALL(*sink_2, CaptureData(
217c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      _, params.channels(), params.frames_per_buffer(), 0, 0))
218c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      .Times(0);
219c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  track_2->AddSink(sink_2.get());
220c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_TRUE(event_1.TimedWait(TestTimeouts::tiny_timeout()));
221c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
222c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
223c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Enable |track_2|, and verify the data callback comes to |sink_2|;
224c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  event_1.Reset();
225c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  base::WaitableEvent event_2(false, false);
226c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_CALL(*sink_1, CaptureData(
227c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      _, params.channels(), params.frames_per_buffer(), 0, 0))
228c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      .Times(AtLeast(1)).WillRepeatedly(SignalEvent(&event_1));
229c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_CALL(*sink_2, CaptureData(
230c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      _, params.channels(), params.frames_per_buffer(), 0, 0))
231c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      .Times(AtLeast(1)).WillRepeatedly(SignalEvent(&event_2));
232c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_TRUE(track_2->set_enabled(true));
233c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_TRUE(event_1.TimedWait(TestTimeouts::tiny_timeout()));
234c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_TRUE(event_2.TimedWait(TestTimeouts::tiny_timeout()));
235c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
236c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  track_1->RemoveSink(sink_1.get());
237c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  track_2->RemoveSink(sink_2.get());
238c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  track_1 = NULL;
239c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  track_2 = NULL;
240c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
241c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
242c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}  // namespace content
243