webrtc_local_audio_track_unittest.cc revision 7d4cd473f85ac64c3747c96c277f9e506a0d2246
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::_;
167d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)using ::testing::AnyNumber;
17c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)using ::testing::AtLeast;
18c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)using ::testing::Return;
19c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
20c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)namespace content {
21c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
22c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)namespace {
23c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
24c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)ACTION_P(SignalEvent, event) {
25c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  event->Signal();
26c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
27c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
28c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// A simple thread that we use to fake the audio thread which provides data to
29c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// the |WebRtcAudioCapturer|.
30c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)class FakeAudioThread : public base::PlatformThread::Delegate {
31c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) public:
32c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  explicit FakeAudioThread(const scoped_refptr<WebRtcAudioCapturer>& capturer)
33c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    : capturer_(capturer),
3490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      thread_(),
35c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      closure_(false, false) {
36868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    DCHECK(capturer.get());
37c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    audio_bus_ = media::AudioBus::Create(capturer_->audio_parameters());
38c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
39c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
4090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  virtual ~FakeAudioThread() { DCHECK(thread_.is_null()); }
41c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
42c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // base::PlatformThread::Delegate:
43c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  virtual void ThreadMain() OVERRIDE {
44c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    while (true) {
45c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      if (closure_.IsSignaled())
46c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        return;
47c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
48c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      media::AudioCapturerSource::CaptureCallback* callback =
49868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)          static_cast<media::AudioCapturerSource::CaptureCallback*>(
50868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)              capturer_.get());
51c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      audio_bus_->Zero();
52c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      callback->Capture(audio_bus_.get(), 0, 0);
53c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
54c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      // Sleep 1ms to yield the resource for the main thread.
55c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(1));
56c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    }
57c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
58c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
59c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  void Start() {
60c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    base::PlatformThread::CreateWithPriority(
61c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        0, this, &thread_, base::kThreadPriority_RealtimeAudio);
6290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    CHECK(!thread_.is_null());
63c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
64c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
65c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  void Stop() {
66c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    closure_.Signal();
67c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    base::PlatformThread::Join(thread_);
6890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    thread_ = base::PlatformThreadHandle();
69c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
70c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
71c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) private:
72c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  scoped_ptr<media::AudioBus> audio_bus_;
73c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  scoped_refptr<WebRtcAudioCapturer> capturer_;
74c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  base::PlatformThreadHandle thread_;
75c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  base::WaitableEvent closure_;
76c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(FakeAudioThread);
77c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)};
78c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
79c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)class MockCapturerSource : public media::AudioCapturerSource {
80c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) public:
81c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  MockCapturerSource() {}
82c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  MOCK_METHOD3(Initialize, void(const media::AudioParameters& params,
83c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                CaptureCallback* callback,
84c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                int session_id));
85c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  MOCK_METHOD0(Start, void());
86c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  MOCK_METHOD0(Stop, void());
87c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  MOCK_METHOD1(SetVolume, void(double volume));
88c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  MOCK_METHOD1(SetAutomaticGainControl, void(bool enable));
89c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
90c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) protected:
91c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  virtual ~MockCapturerSource() {}
92c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)};
93c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
94c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)class MockWebRtcAudioCapturerSink : public WebRtcAudioCapturerSink {
95c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) public:
96c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  MockWebRtcAudioCapturerSink() {}
97c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ~MockWebRtcAudioCapturerSink() {}
98c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  MOCK_METHOD5(CaptureData, void(const int16* audio_data,
99c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                 int number_of_channels,
100c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                 int number_of_frames,
101c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                 int audio_delay_milliseconds,
102c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                 double volume));
103c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  MOCK_METHOD1(SetCaptureFormat, void(const media::AudioParameters& params));
104c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)};
105c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
106c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}  // namespace
107c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
108c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)class WebRtcLocalAudioTrackTest : public ::testing::Test {
109c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) protected:
110c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  virtual void SetUp() OVERRIDE {
111c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    capturer_ = WebRtcAudioCapturer::CreateCapturer();
112c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    capturer_source_ = new MockCapturerSource();
113868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    EXPECT_CALL(*capturer_source_.get(), Initialize(_, capturer_.get(), 0))
114c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        .WillOnce(Return());
115c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    capturer_->SetCapturerSource(capturer_source_,
116c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                 media::CHANNEL_LAYOUT_STEREO,
117c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                 48000);
118c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
119868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    EXPECT_CALL(*capturer_source_.get(), SetAutomaticGainControl(false))
120c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        .WillOnce(Return());
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)  }
129c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
130c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  scoped_refptr<MockCapturerSource> capturer_source_;
131c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  scoped_refptr<WebRtcAudioCapturer> capturer_;
132c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  scoped_ptr<FakeAudioThread> audio_thread_;
133c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)};
134c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
135c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Creates a capturer and audio track, fakes its audio thread, and
136c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// connect/disconnect the sink to the audio track on the fly, the sink should
137c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// get data callback when the track is connected to the capturer but not when
138c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// the track is disconnected from the capturer.
139c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)TEST_F(WebRtcLocalAudioTrackTest, ConnectAndDisconnectOneSink) {
1407d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  EXPECT_CALL(*capturer_source_.get(), Start()).WillOnce(Return());
141c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  scoped_refptr<WebRtcLocalAudioTrack> track =
142c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      WebRtcLocalAudioTrack::Create(std::string(), capturer_, NULL);
1437d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  track->Start();
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());
1577d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
1587d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  EXPECT_CALL(*capturer_source_.get(), Stop()).WillOnce(Return());
1597d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  track->Stop();
160c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  track = NULL;
161c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
162c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
163c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// The same setup as ConnectAndDisconnectOneSink, but enable and disable the
164c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// audio track on the fly. When the audio track is disabled, there is no data
165c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// callback to the sink; when the audio track is enabled, there comes data
166c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// callback.
167c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// TODO(xians): Enable this test after resolving the racing issue that TSAN
168c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// reports on MediaStreamTrack::enabled();
169c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)TEST_F(WebRtcLocalAudioTrackTest, DISABLED_DisableEnableAudioTrack) {
1707d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  EXPECT_CALL(*capturer_source_.get(), Start()).WillOnce(Return());
171c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  scoped_refptr<WebRtcLocalAudioTrack> track =
172c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    WebRtcLocalAudioTrack::Create(std::string(), capturer_, NULL);
1737d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  track->Start();
174c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_TRUE(track->enabled());
175c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_TRUE(track->set_enabled(false));
176c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  scoped_ptr<MockWebRtcAudioCapturerSink> sink(
177c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      new MockWebRtcAudioCapturerSink());
178c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  const media::AudioParameters params = capturer_->audio_parameters();
179c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  base::WaitableEvent event(false, false);
180c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_CALL(*sink, SetCaptureFormat(_)).WillOnce(Return());
181c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_CALL(*sink, CaptureData(
182c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      _, params.channels(), params.frames_per_buffer(), 0, 0))
183c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      .Times(0);
184c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  track->AddSink(sink.get());
185c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_FALSE(event.TimedWait(TestTimeouts::tiny_timeout()));
186c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
187c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  event.Reset();
188c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_CALL(*sink, CaptureData(
189c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      _, params.channels(), params.frames_per_buffer(), 0, 0))
190c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      .Times(AtLeast(1)).WillRepeatedly(SignalEvent(&event));
191c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_TRUE(track->set_enabled(true));
192c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_TRUE(event.TimedWait(TestTimeouts::tiny_timeout()));
193c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  track->RemoveSink(sink.get());
1947d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
1957d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  EXPECT_CALL(*capturer_source_.get(), Stop()).WillOnce(Return());
1967d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  track->Stop();
197c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  track = NULL;
198c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
199c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
200c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Create multiple audio tracks and enable/disable them, verify that the audio
201c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// callbacks appear/disappear.
2027d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)TEST_F(WebRtcLocalAudioTrackTest, MultipleAudioTracks) {
2037d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  EXPECT_CALL(*capturer_source_.get(), Start()).WillOnce(Return());
204c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  scoped_refptr<WebRtcLocalAudioTrack> track_1 =
205c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    WebRtcLocalAudioTrack::Create(std::string(), capturer_, NULL);
2067d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  track_1->Start();
207c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_TRUE(track_1->enabled());
208c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  scoped_ptr<MockWebRtcAudioCapturerSink> sink_1(
209c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      new MockWebRtcAudioCapturerSink());
210c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  const media::AudioParameters params = capturer_->audio_parameters();
211c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  base::WaitableEvent event_1(false, false);
212c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_CALL(*sink_1, SetCaptureFormat(_)).WillOnce(Return());
213c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_CALL(*sink_1, CaptureData(
214c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      _, params.channels(), params.frames_per_buffer(), 0, 0))
215c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      .Times(AtLeast(1)).WillRepeatedly(SignalEvent(&event_1));
216c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  track_1->AddSink(sink_1.get());
2177d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  EXPECT_TRUE(event_1.TimedWait(TestTimeouts::tiny_timeout()));
218c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
219c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  scoped_refptr<WebRtcLocalAudioTrack> track_2 =
220c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    WebRtcLocalAudioTrack::Create(std::string(), capturer_, NULL);
2217d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  track_2->Start();
2227d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  EXPECT_TRUE(track_2->enabled());
223c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
2247d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  // Verify both |sink_1| and |sink_2| get data.
225c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  event_1.Reset();
226c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  base::WaitableEvent event_2(false, false);
2277d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
2287d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  scoped_ptr<MockWebRtcAudioCapturerSink> sink_2(
2297d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)        new MockWebRtcAudioCapturerSink());
2307d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  EXPECT_CALL(*sink_2, SetCaptureFormat(_)).WillOnce(Return());
231c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_CALL(*sink_1, CaptureData(
232c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      _, params.channels(), params.frames_per_buffer(), 0, 0))
233c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      .Times(AtLeast(1)).WillRepeatedly(SignalEvent(&event_1));
234c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_CALL(*sink_2, CaptureData(
235c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      _, params.channels(), params.frames_per_buffer(), 0, 0))
236c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      .Times(AtLeast(1)).WillRepeatedly(SignalEvent(&event_2));
2377d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  track_2->AddSink(sink_2.get());
238c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_TRUE(event_1.TimedWait(TestTimeouts::tiny_timeout()));
239c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_TRUE(event_2.TimedWait(TestTimeouts::tiny_timeout()));
240c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
241c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  track_1->RemoveSink(sink_1.get());
2427d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  track_1->Stop();
2437d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  track_1 = NULL;
2447d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
2457d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  EXPECT_CALL(*capturer_source_.get(), Stop()).WillOnce(Return());
246c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  track_2->RemoveSink(sink_2.get());
2477d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  track_2->Stop();
2487d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  track_2 = NULL;
2497d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)}
2507d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
2517d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
2527d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)// Start one track and verify the capturer is correctly starting its source.
2537d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)// And it should be fine to not to call Stop() explicitly.
2547d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)TEST_F(WebRtcLocalAudioTrackTest, StartOneAudioTrack) {
2557d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  EXPECT_CALL(*capturer_source_.get(), Start()).Times(1);
2567d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  scoped_refptr<WebRtcLocalAudioTrack> track =
2577d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      WebRtcLocalAudioTrack::Create(std::string(), capturer_, NULL);
2587d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  track->Start();
2597d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
2607d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  // When the track goes away, it will automatically stop the
2617d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  // |capturer_source_|.
2627d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  EXPECT_CALL(*capturer_source_.get(), Stop());
2637d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  track = NULL;
2647d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)}
2657d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
2667d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)// Start/Stop tracks and verify the capturer is correctly starting/stopping
2677d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)// its source.
2687d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)TEST_F(WebRtcLocalAudioTrackTest, StartAndStopAudioTracks) {
2697d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  // SetDefaultSink() should not trigger the Start() on |capturer_source_|.
2707d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  base::WaitableEvent event(false, false);
2717d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  scoped_ptr<MockWebRtcAudioCapturerSink> default_sink(
2727d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      new MockWebRtcAudioCapturerSink());
2737d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  EXPECT_CALL(*default_sink, SetCaptureFormat(_)).WillOnce(Return());
2747d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  EXPECT_CALL(*default_sink, CaptureData(_, _, _, 0, 0))
2757d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      .Times(AnyNumber()).WillRepeatedly(Return());
2767d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  capturer_->SetDefaultSink(default_sink.get());
2777d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  EXPECT_CALL(*capturer_source_.get(), Start()).Times(0);
2787d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  EXPECT_FALSE(event.TimedWait(TestTimeouts::tiny_timeout()));
2797d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
2807d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  // Starting the first audio track will start the |capturer_source_|.
2817d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  event.Reset();
2827d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  EXPECT_CALL(*capturer_source_.get(), Start()).WillOnce(SignalEvent(&event));
2837d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  scoped_refptr<WebRtcLocalAudioTrack> track_1 =
2847d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      WebRtcLocalAudioTrack::Create(std::string(), capturer_, NULL);
2857d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  track_1->Start();
2867d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  EXPECT_TRUE(event.TimedWait(TestTimeouts::tiny_timeout()));
2877d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
2887d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  // Start the second audio track will not start the |capturer_source_|
2897d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  // since it has been started.
2907d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  EXPECT_CALL(*capturer_source_.get(), Start()).Times(0);
2917d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  scoped_refptr<WebRtcLocalAudioTrack> track_2 =
2927d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      WebRtcLocalAudioTrack::Create(std::string(), capturer_, NULL);
2937d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  track_2->Start();
2947d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
2957d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  // Stop the first audio track will not stop the |capturer_source_|.
2967d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  EXPECT_CALL(*capturer_source_.get(), Stop()).Times(0);
2977d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  track_1->Stop();
298c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  track_1 = NULL;
2997d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
3007d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  // Stop the last audio track will stop the |capturer_source_|.
3017d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  event.Reset();
3027d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  EXPECT_CALL(*capturer_source_.get(), Stop())
3037d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      .Times(1).WillOnce(SignalEvent(&event));
3047d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  track_2->Stop();
305c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  track_2 = NULL;
3067d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  EXPECT_TRUE(event.TimedWait(TestTimeouts::tiny_timeout()));
3077d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
3087d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  capturer_->SetDefaultSink(NULL);
3097d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)}
3107d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
3117d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)// Set new source to the capturer.
3127d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)TEST_F(WebRtcLocalAudioTrackTest, SetNewSourceForCapturerAfterStartTrack) {
3137d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  // Setup the audio track and start the track.
3147d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  EXPECT_CALL(*capturer_source_.get(), Start()).Times(1);
3157d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  scoped_refptr<WebRtcLocalAudioTrack> track =
3167d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      WebRtcLocalAudioTrack::Create(std::string(), capturer_, NULL);
3177d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  track->Start();
3187d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
3197d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  // Setting new source to the capturer and the track should still get packets.
3207d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  scoped_refptr<MockCapturerSource> new_source(new MockCapturerSource());
3217d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  EXPECT_CALL(*capturer_source_.get(), Stop());
3227d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  EXPECT_CALL(*new_source.get(), SetAutomaticGainControl(false));
3237d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  EXPECT_CALL(*new_source.get(), Initialize(_, capturer_.get(), 0))
3247d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      .WillOnce(Return());
3257d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  EXPECT_CALL(*new_source.get(), Start()).WillOnce(Return());
3267d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  capturer_->SetCapturerSource(new_source,
3277d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)                               media::CHANNEL_LAYOUT_STEREO,
3287d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)                               48000);
3297d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
3307d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  // Stop the track.
3317d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  EXPECT_CALL(*new_source.get(), Stop());
3327d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  track->Stop();
3337d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  track = NULL;
334c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
335c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
336c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}  // namespace content
337