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