webrtc_local_audio_track_unittest.cc revision d0247b1b59f9c528cb6df88b4f2b9afaf80d181e
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"
758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#include "content/renderer/media/rtc_media_constraints.h"
8c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "content/renderer/media/webrtc_audio_capturer.h"
9d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)#include "content/renderer/media/webrtc_local_audio_source_provider.h"
10c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "content/renderer/media/webrtc_local_audio_track.h"
11c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "media/audio/audio_parameters.h"
12c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "media/base/audio_bus.h"
13c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "media/base/audio_capturer_source.h"
14c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "testing/gmock/include/gmock/gmock.h"
15c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "testing/gtest/include/gtest/gtest.h"
16bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch#include "third_party/libjingle/source/talk/app/webrtc/mediastreaminterface.h"
17c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
18c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)using ::testing::_;
197d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)using ::testing::AnyNumber;
20c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)using ::testing::AtLeast;
21c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)using ::testing::Return;
22c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
23c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)namespace content {
24c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
25c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)namespace {
26c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
27c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)ACTION_P(SignalEvent, event) {
28c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  event->Signal();
29c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
30c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
31c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// A simple thread that we use to fake the audio thread which provides data to
32c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// the |WebRtcAudioCapturer|.
33c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)class FakeAudioThread : public base::PlatformThread::Delegate {
34c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) public:
35c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  explicit FakeAudioThread(const scoped_refptr<WebRtcAudioCapturer>& capturer)
36c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    : capturer_(capturer),
3790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      thread_(),
38c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      closure_(false, false) {
39868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    DCHECK(capturer.get());
40c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    audio_bus_ = media::AudioBus::Create(capturer_->audio_parameters());
41c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
42c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
4390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  virtual ~FakeAudioThread() { DCHECK(thread_.is_null()); }
44c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
45c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // base::PlatformThread::Delegate:
46c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  virtual void ThreadMain() OVERRIDE {
47c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    while (true) {
48c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      if (closure_.IsSignaled())
49c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        return;
50c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
51c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      media::AudioCapturerSource::CaptureCallback* callback =
52868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)          static_cast<media::AudioCapturerSource::CaptureCallback*>(
53868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)              capturer_.get());
54c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      audio_bus_->Zero();
553551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      callback->Capture(audio_bus_.get(), 0, 0, false);
56c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
57c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      // Sleep 1ms to yield the resource for the main thread.
58c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(1));
59c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    }
60c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
61c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
62c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  void Start() {
63c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    base::PlatformThread::CreateWithPriority(
64c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        0, this, &thread_, base::kThreadPriority_RealtimeAudio);
6590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    CHECK(!thread_.is_null());
66c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
67c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
68c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  void Stop() {
69c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    closure_.Signal();
70c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    base::PlatformThread::Join(thread_);
7190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    thread_ = base::PlatformThreadHandle();
72c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
73c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
74c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) private:
75c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  scoped_ptr<media::AudioBus> audio_bus_;
76c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  scoped_refptr<WebRtcAudioCapturer> capturer_;
77c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  base::PlatformThreadHandle thread_;
78c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  base::WaitableEvent closure_;
79c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(FakeAudioThread);
80c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)};
81c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
82c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)class MockCapturerSource : public media::AudioCapturerSource {
83c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) public:
84c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  MockCapturerSource() {}
85c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  MOCK_METHOD3(Initialize, void(const media::AudioParameters& params,
86c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                CaptureCallback* callback,
87c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                int session_id));
88c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  MOCK_METHOD0(Start, void());
89c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  MOCK_METHOD0(Stop, void());
90c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  MOCK_METHOD1(SetVolume, void(double volume));
91c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  MOCK_METHOD1(SetAutomaticGainControl, void(bool enable));
92c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
93c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) protected:
94c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  virtual ~MockCapturerSource() {}
95c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)};
96c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
97c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)class MockWebRtcAudioCapturerSink : public WebRtcAudioCapturerSink {
98c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) public:
99c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  MockWebRtcAudioCapturerSink() {}
100c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ~MockWebRtcAudioCapturerSink() {}
101bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  int CaptureData(const std::vector<int>& channels,
102bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch                  const int16* audio_data,
103bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch                  int sample_rate,
104bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch                  int number_of_channels,
105bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch                  int number_of_frames,
106bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch                  int audio_delay_milliseconds,
107bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch                  int current_volume,
1083551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                  bool need_audio_processing,
1093551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                  bool key_pressed) OVERRIDE {
1103551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    CaptureData(channels.size(),
1113551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                sample_rate,
1123551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                number_of_channels,
1133551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                number_of_frames,
1143551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                audio_delay_milliseconds,
1153551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                current_volume,
1163551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                need_audio_processing,
1173551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                key_pressed);
118bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch    return 0;
119bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  }
1203551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  MOCK_METHOD8(CaptureData,
1213551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)               void(int number_of_network_channels,
1223551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                    int sample_rate,
1233551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                    int number_of_channels,
1243551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                    int number_of_frames,
1253551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                    int audio_delay_milliseconds,
1263551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                    int current_volume,
1273551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                    bool need_audio_processing,
1283551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                    bool key_pressed));
129c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  MOCK_METHOD1(SetCaptureFormat, void(const media::AudioParameters& params));
130c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)};
131c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
132c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}  // namespace
133c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
134c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)class WebRtcLocalAudioTrackTest : public ::testing::Test {
135c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) protected:
136c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  virtual void SetUp() OVERRIDE {
137d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    params_.Reset(media::AudioParameters::AUDIO_PCM_LOW_LATENCY,
138d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)                  media::CHANNEL_LAYOUT_STEREO, 2, 0, 48000, 16, 480);
139c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    capturer_ = WebRtcAudioCapturer::CreateCapturer();
140d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    WebRtcLocalAudioSourceProvider* source_provider =
141d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)        static_cast<WebRtcLocalAudioSourceProvider*>(
142d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)            capturer_->audio_source_provider());
143d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    source_provider->SetSinkParamsForTesting(params_);
144c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    capturer_source_ = new MockCapturerSource();
145868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    EXPECT_CALL(*capturer_source_.get(), Initialize(_, capturer_.get(), 0))
146c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        .WillOnce(Return());
147c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    capturer_->SetCapturerSource(capturer_source_,
148d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)                                 params_.channel_layout(),
149d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)                                 params_.sample_rate());
150c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
151868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    EXPECT_CALL(*capturer_source_.get(), SetAutomaticGainControl(false))
152c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        .WillOnce(Return());
153bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch
154bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch    // Start the audio thread used by the |capturer_source_|.
155c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    audio_thread_.reset(new FakeAudioThread(capturer_));
156c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    audio_thread_->Start();
157c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
158c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
159c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  virtual void TearDown() {
160c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    audio_thread_->Stop();
161c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    audio_thread_.reset();
162c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
163c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
164d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  media::AudioParameters params_;
165c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  scoped_refptr<MockCapturerSource> capturer_source_;
166c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  scoped_refptr<WebRtcAudioCapturer> capturer_;
167c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  scoped_ptr<FakeAudioThread> audio_thread_;
168c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)};
169c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
170c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Creates a capturer and audio track, fakes its audio thread, and
171c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// connect/disconnect the sink to the audio track on the fly, the sink should
172c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// get data callback when the track is connected to the capturer but not when
173c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// the track is disconnected from the capturer.
174c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)TEST_F(WebRtcLocalAudioTrackTest, ConnectAndDisconnectOneSink) {
1757d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  EXPECT_CALL(*capturer_source_.get(), Start()).WillOnce(Return());
17658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  RTCMediaConstraints constraints;
177c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  scoped_refptr<WebRtcLocalAudioTrack> track =
178d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      WebRtcLocalAudioTrack::Create(std::string(), capturer_, NULL, NULL,
17958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)          &constraints);
1807d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  track->Start();
181c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_TRUE(track->enabled());
182bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch
183bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  // Connect a number of network channels to the audio track.
184bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  static const int kNumberOfNetworkChannels = 4;
185bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  for (int i = 0; i < kNumberOfNetworkChannels; ++i) {
186bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch    static_cast<webrtc::AudioTrackInterface*>(track.get())->
187bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch        GetRenderer()->AddChannel(i);
188bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  }
189c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  scoped_ptr<MockWebRtcAudioCapturerSink> sink(
190c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      new MockWebRtcAudioCapturerSink());
191c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  const media::AudioParameters params = capturer_->audio_parameters();
192c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  base::WaitableEvent event(false, false);
193c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_CALL(*sink, SetCaptureFormat(_)).WillOnce(Return());
1943551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  EXPECT_CALL(*sink,
19558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      CaptureData(kNumberOfNetworkChannels,
19658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                  params.sample_rate(),
19758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                  params.channels(),
198d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)                  params.sample_rate() / 100,
19958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                  0,
20058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                  0,
20158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                  false,
20258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                  false)).Times(AtLeast(1))
2033551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      .WillRepeatedly(SignalEvent(&event));
204c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  track->AddSink(sink.get());
205c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
206c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_TRUE(event.TimedWait(TestTimeouts::tiny_timeout()));
207c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  track->RemoveSink(sink.get());
2087d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
2097d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  EXPECT_CALL(*capturer_source_.get(), Stop()).WillOnce(Return());
2107d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  track->Stop();
211c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  track = NULL;
212c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
213c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
214c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// The same setup as ConnectAndDisconnectOneSink, but enable and disable the
215c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// audio track on the fly. When the audio track is disabled, there is no data
216c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// callback to the sink; when the audio track is enabled, there comes data
217c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// callback.
218c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// TODO(xians): Enable this test after resolving the racing issue that TSAN
219c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// reports on MediaStreamTrack::enabled();
220c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)TEST_F(WebRtcLocalAudioTrackTest, DISABLED_DisableEnableAudioTrack) {
2217d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  EXPECT_CALL(*capturer_source_.get(), Start()).WillOnce(Return());
22258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  RTCMediaConstraints constraints;
223c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  scoped_refptr<WebRtcLocalAudioTrack> track =
224d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    WebRtcLocalAudioTrack::Create(std::string(), capturer_, NULL, NULL,
22558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)        &constraints);
2267d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  track->Start();
227bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  static_cast<webrtc::AudioTrackInterface*>(track.get())->
228bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch      GetRenderer()->AddChannel(0);
229c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_TRUE(track->enabled());
230c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_TRUE(track->set_enabled(false));
231c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  scoped_ptr<MockWebRtcAudioCapturerSink> sink(
232c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      new MockWebRtcAudioCapturerSink());
233c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  const media::AudioParameters params = capturer_->audio_parameters();
234c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  base::WaitableEvent event(false, false);
235c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_CALL(*sink, SetCaptureFormat(_)).WillOnce(Return());
2363551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  EXPECT_CALL(*sink,
2373551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)              CaptureData(1,
2383551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                          params.sample_rate(),
2393551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                          params.channels(),
240d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)                          params.sample_rate() / 100,
2413551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                          0,
2423551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                          0,
2433551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                          false,
2443551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                          false)).Times(0);
245c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  track->AddSink(sink.get());
246c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_FALSE(event.TimedWait(TestTimeouts::tiny_timeout()));
247c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
248c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  event.Reset();
2493551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  EXPECT_CALL(*sink,
2503551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)              CaptureData(1,
2513551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                          params.sample_rate(),
2523551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                          params.channels(),
253d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)                          params.sample_rate() / 100,
2543551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                          0,
2553551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                          0,
2563551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                          false,
2573551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                          false)).Times(AtLeast(1))
2583551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      .WillRepeatedly(SignalEvent(&event));
259c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_TRUE(track->set_enabled(true));
260c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_TRUE(event.TimedWait(TestTimeouts::tiny_timeout()));
261c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  track->RemoveSink(sink.get());
2627d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
2637d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  EXPECT_CALL(*capturer_source_.get(), Stop()).WillOnce(Return());
2647d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  track->Stop();
265c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  track = NULL;
266c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
267c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
268c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Create multiple audio tracks and enable/disable them, verify that the audio
269c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// callbacks appear/disappear.
2707d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)TEST_F(WebRtcLocalAudioTrackTest, MultipleAudioTracks) {
2717d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  EXPECT_CALL(*capturer_source_.get(), Start()).WillOnce(Return());
27258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  RTCMediaConstraints constraints;
273c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  scoped_refptr<WebRtcLocalAudioTrack> track_1 =
274d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    WebRtcLocalAudioTrack::Create(std::string(), capturer_, NULL, NULL,
27558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)        &constraints);
2767d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  track_1->Start();
277bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  static_cast<webrtc::AudioTrackInterface*>(track_1.get())->
278bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch      GetRenderer()->AddChannel(0);
279c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_TRUE(track_1->enabled());
280c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  scoped_ptr<MockWebRtcAudioCapturerSink> sink_1(
281c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      new MockWebRtcAudioCapturerSink());
282c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  const media::AudioParameters params = capturer_->audio_parameters();
283c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  base::WaitableEvent event_1(false, false);
284c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_CALL(*sink_1, SetCaptureFormat(_)).WillOnce(Return());
2853551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  EXPECT_CALL(*sink_1,
28658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      CaptureData(1,
28758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                  params.sample_rate(),
28858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                  params.channels(),
289d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)                  params.sample_rate() / 100,
29058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                  0,
29158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                  0,
29258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                  false,
29358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                  false)).Times(AtLeast(1))
2943551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      .WillRepeatedly(SignalEvent(&event_1));
295c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  track_1->AddSink(sink_1.get());
2967d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  EXPECT_TRUE(event_1.TimedWait(TestTimeouts::tiny_timeout()));
297c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
298c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  scoped_refptr<WebRtcLocalAudioTrack> track_2 =
299d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    WebRtcLocalAudioTrack::Create(std::string(), capturer_, NULL, NULL,
30058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)        &constraints);
3017d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  track_2->Start();
302bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  static_cast<webrtc::AudioTrackInterface*>(track_2.get())->
303bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch      GetRenderer()->AddChannel(1);
3047d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  EXPECT_TRUE(track_2->enabled());
305c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
3067d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  // Verify both |sink_1| and |sink_2| get data.
307c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  event_1.Reset();
308c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  base::WaitableEvent event_2(false, false);
3097d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
3107d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  scoped_ptr<MockWebRtcAudioCapturerSink> sink_2(
3117d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)        new MockWebRtcAudioCapturerSink());
3127d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  EXPECT_CALL(*sink_2, SetCaptureFormat(_)).WillOnce(Return());
3133551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  EXPECT_CALL(*sink_1,
31458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      CaptureData(1,
31558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                  params.sample_rate(),
31658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                  params.channels(),
317d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)                  params.sample_rate() / 100,
31858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                  0,
31958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                  0,
32058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                  false,
32158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                  false)).Times(AtLeast(1))
3223551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      .WillRepeatedly(SignalEvent(&event_1));
3233551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  EXPECT_CALL(*sink_2,
32458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      CaptureData(1,
32558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                  params.sample_rate(),
32658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                  params.channels(),
327d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)                  params.sample_rate() / 100,
32858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                  0,
32958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                  0,
33058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                  false,
33158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                  false)).Times(AtLeast(1))
3323551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      .WillRepeatedly(SignalEvent(&event_2));
3337d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  track_2->AddSink(sink_2.get());
334c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_TRUE(event_1.TimedWait(TestTimeouts::tiny_timeout()));
335c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_TRUE(event_2.TimedWait(TestTimeouts::tiny_timeout()));
336c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
337c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  track_1->RemoveSink(sink_1.get());
3387d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  track_1->Stop();
3397d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  track_1 = NULL;
3407d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
3417d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  EXPECT_CALL(*capturer_source_.get(), Stop()).WillOnce(Return());
342c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  track_2->RemoveSink(sink_2.get());
3437d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  track_2->Stop();
3447d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  track_2 = NULL;
3457d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)}
3467d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
3477d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
3487d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)// Start one track and verify the capturer is correctly starting its source.
3497d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)// And it should be fine to not to call Stop() explicitly.
3507d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)TEST_F(WebRtcLocalAudioTrackTest, StartOneAudioTrack) {
3517d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  EXPECT_CALL(*capturer_source_.get(), Start()).Times(1);
35258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  RTCMediaConstraints constraints;
3537d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  scoped_refptr<WebRtcLocalAudioTrack> track =
354d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      WebRtcLocalAudioTrack::Create(std::string(), capturer_, NULL, NULL,
35558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)          &constraints);
3567d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  track->Start();
3577d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
3587d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  // When the track goes away, it will automatically stop the
3597d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  // |capturer_source_|.
3607d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  EXPECT_CALL(*capturer_source_.get(), Stop());
361bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  track->Stop();
3627d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  track = NULL;
3637d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)}
3647d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
3657d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)// Start/Stop tracks and verify the capturer is correctly starting/stopping
3667d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)// its source.
3677d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)TEST_F(WebRtcLocalAudioTrackTest, StartAndStopAudioTracks) {
3687d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  // Starting the first audio track will start the |capturer_source_|.
369bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  base::WaitableEvent event(false, false);
3707d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  EXPECT_CALL(*capturer_source_.get(), Start()).WillOnce(SignalEvent(&event));
37158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  RTCMediaConstraints constraints;
3727d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  scoped_refptr<WebRtcLocalAudioTrack> track_1 =
373d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      WebRtcLocalAudioTrack::Create(std::string(), capturer_, NULL, NULL,
37458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)          &constraints);
375bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  static_cast<webrtc::AudioTrackInterface*>(track_1.get())->
376bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch      GetRenderer()->AddChannel(0);
3777d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  track_1->Start();
3787d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  EXPECT_TRUE(event.TimedWait(TestTimeouts::tiny_timeout()));
3797d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
380bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  // Verify the data flow by connecting the sink to |track_1|.
381bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  scoped_ptr<MockWebRtcAudioCapturerSink> sink(
382bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch      new MockWebRtcAudioCapturerSink());
383bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  event.Reset();
3843551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  EXPECT_CALL(*sink, CaptureData(_, _, _, _, 0, 0, false, false))
385bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch      .Times(AnyNumber()).WillRepeatedly(Return());
386bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  EXPECT_CALL(*sink, SetCaptureFormat(_)).Times(1);
387bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  track_1->AddSink(sink.get());
388bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch
3897d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  // Start the second audio track will not start the |capturer_source_|
3907d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  // since it has been started.
3917d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  EXPECT_CALL(*capturer_source_.get(), Start()).Times(0);
3927d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  scoped_refptr<WebRtcLocalAudioTrack> track_2 =
393d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      WebRtcLocalAudioTrack::Create(std::string(), capturer_, NULL, NULL,
39458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)          &constraints);
3957d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  track_2->Start();
396bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  static_cast<webrtc::AudioTrackInterface*>(track_2.get())->
397bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch      GetRenderer()->AddChannel(1);
3987d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
3997d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  // Stop the first audio track will not stop the |capturer_source_|.
4007d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  EXPECT_CALL(*capturer_source_.get(), Stop()).Times(0);
401bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  track_1->RemoveSink(sink.get());
4027d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  track_1->Stop();
403c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  track_1 = NULL;
4047d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
4053551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  EXPECT_CALL(*sink, CaptureData(_, _, _, _, 0, 0, false, false))
406bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch      .Times(AnyNumber()).WillRepeatedly(Return());
407bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  EXPECT_CALL(*sink, SetCaptureFormat(_)).Times(1);
408bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  track_2->AddSink(sink.get());
409bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch
4107d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  // Stop the last audio track will stop the |capturer_source_|.
4117d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  event.Reset();
4127d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  EXPECT_CALL(*capturer_source_.get(), Stop())
4137d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      .Times(1).WillOnce(SignalEvent(&event));
4147d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  track_2->Stop();
415bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  track_2->RemoveSink(sink.get());
416c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  track_2 = NULL;
4177d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  EXPECT_TRUE(event.TimedWait(TestTimeouts::tiny_timeout()));
4187d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)}
4197d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
420bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch// Set new source to the existing capturer.
4217d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)TEST_F(WebRtcLocalAudioTrackTest, SetNewSourceForCapturerAfterStartTrack) {
4227d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  // Setup the audio track and start the track.
4237d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  EXPECT_CALL(*capturer_source_.get(), Start()).Times(1);
42458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  RTCMediaConstraints constraints;
4257d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  scoped_refptr<WebRtcLocalAudioTrack> track =
426d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      WebRtcLocalAudioTrack::Create(std::string(), capturer_, NULL, NULL,
42758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)          &constraints);
4287d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  track->Start();
4297d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
4307d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  // Setting new source to the capturer and the track should still get packets.
4317d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  scoped_refptr<MockCapturerSource> new_source(new MockCapturerSource());
4327d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  EXPECT_CALL(*capturer_source_.get(), Stop());
4337d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  EXPECT_CALL(*new_source.get(), SetAutomaticGainControl(false));
4347d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  EXPECT_CALL(*new_source.get(), Initialize(_, capturer_.get(), 0))
4357d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      .WillOnce(Return());
4367d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  EXPECT_CALL(*new_source.get(), Start()).WillOnce(Return());
4377d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  capturer_->SetCapturerSource(new_source,
438d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)                               params_.channel_layout(),
439d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)                               params_.sample_rate());
4407d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
4417d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  // Stop the track.
4427d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  EXPECT_CALL(*new_source.get(), Stop());
4437d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  track->Stop();
4447d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  track = NULL;
445c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
446c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
447bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch// Create a new capturer with new source, connect it to a new audio track.
448bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben MurdochTEST_F(WebRtcLocalAudioTrackTest, ConnectTracksToDifferentCapturers) {
449bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  // Setup the first audio track and start it.
450bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  EXPECT_CALL(*capturer_source_.get(), Start()).Times(1);
45158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  RTCMediaConstraints constraints;
452bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  scoped_refptr<WebRtcLocalAudioTrack> track_1 =
453d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      WebRtcLocalAudioTrack::Create(std::string(), capturer_, NULL, NULL,
45458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)          &constraints);
455bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  track_1->Start();
456bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch
457bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  // Connect a number of network channels to the |track_1|.
458bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  static const int kNumberOfNetworkChannelsForTrack1 = 2;
459bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  for (int i = 0; i < kNumberOfNetworkChannelsForTrack1; ++i) {
460bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch    static_cast<webrtc::AudioTrackInterface*>(track_1.get())->
461bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch        GetRenderer()->AddChannel(i);
462bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  }
463bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  // Verify the data flow by connecting the |sink_1| to |track_1|.
464bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  scoped_ptr<MockWebRtcAudioCapturerSink> sink_1(
465bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch      new MockWebRtcAudioCapturerSink());
4663551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  EXPECT_CALL(
4673551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      *sink_1.get(),
4683551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      CaptureData(
4693551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)          kNumberOfNetworkChannelsForTrack1, 48000, 2, _, 0, 0, false, false))
470bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch      .Times(AnyNumber()).WillRepeatedly(Return());
471bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  EXPECT_CALL(*sink_1.get(), SetCaptureFormat(_)).Times(1);
472bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  track_1->AddSink(sink_1.get());
473bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch
474bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  // Create a new capturer with new source with different audio format.
475bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  scoped_refptr<WebRtcAudioCapturer> new_capturer(
476bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch      WebRtcAudioCapturer::CreateCapturer());
477d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  WebRtcLocalAudioSourceProvider* source_provider =
478d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      static_cast<WebRtcLocalAudioSourceProvider*>(
479d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)          new_capturer->audio_source_provider());
480d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  source_provider->SetSinkParamsForTesting(params_);
481bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  scoped_refptr<MockCapturerSource> new_source(new MockCapturerSource());
482bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  EXPECT_CALL(*new_source.get(), Initialize(_, new_capturer.get(), 0))
483bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch      .WillOnce(Return());
484bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  EXPECT_CALL(*new_source.get(), SetAutomaticGainControl(false))
485bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch      .WillOnce(Return());
486bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  new_capturer->SetCapturerSource(new_source,
487bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch                                  media::CHANNEL_LAYOUT_MONO,
488bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch                                  44100);
489bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch
490bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  // Start the audio thread used by the new source.
491bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  scoped_ptr<FakeAudioThread> audio_thread(new FakeAudioThread(new_capturer));
492bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  audio_thread->Start();
493bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch
494bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  // Setup the second audio track, connect it to the new capturer and start it.
495bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  EXPECT_CALL(*new_source.get(), Start()).Times(1);
496bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  scoped_refptr<WebRtcLocalAudioTrack> track_2 =
497d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      WebRtcLocalAudioTrack::Create(std::string(), new_capturer, NULL, NULL,
49858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)          &constraints);
499bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  track_2->Start();
500bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch
501bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  // Connect a number of network channels to the |track_2|.
502bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  static const int kNumberOfNetworkChannelsForTrack2 = 3;
503bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  for (int i = 0; i < kNumberOfNetworkChannelsForTrack2; ++i) {
504bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch    static_cast<webrtc::AudioTrackInterface*>(track_2.get())->
505bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch        GetRenderer()->AddChannel(i);
506bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  }
507bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  // Verify the data flow by connecting the |sink_2| to |track_2|.
508bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  scoped_ptr<MockWebRtcAudioCapturerSink> sink_2(
509bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch      new MockWebRtcAudioCapturerSink());
5103551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  EXPECT_CALL(
5113551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      *sink_2,
5123551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      CaptureData(
5133551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)          kNumberOfNetworkChannelsForTrack2, 44100, 1, _, 0, 0, false, false))
514bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch      .Times(AnyNumber()).WillRepeatedly(Return());
515bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  EXPECT_CALL(*sink_2, SetCaptureFormat(_)).Times(1);
516bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  track_2->AddSink(sink_2.get());
517bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch
518bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  // Stop the second audio track will stop the new source.
519bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  base::WaitableEvent event(false, false);
520bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  EXPECT_CALL(*new_source.get(), Stop()).Times(1).WillOnce(SignalEvent(&event));
521bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  track_2->Stop();
522bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  track_2->RemoveSink(sink_2.get());
523bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  track_2 = NULL;
524bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  EXPECT_TRUE(event.TimedWait(TestTimeouts::tiny_timeout()));
525bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  audio_thread->Stop();
526bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  audio_thread.reset();
527bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch
528bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  // Stop the first audio track.
529bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  EXPECT_CALL(*capturer_source_.get(), Stop());
530bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  track_1->Stop();
531bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  track_1 = NULL;
532bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch}
533bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch
534c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}  // namespace content
535