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"
70529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch#include "content/renderer/media/media_stream_audio_source.h"
8a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "content/renderer/media/mock_media_constraint_factory.h"
95d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "content/renderer/media/webrtc/webrtc_local_audio_track_adapter.h"
10c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "content/renderer/media/webrtc_audio_capturer.h"
11a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "content/renderer/media/webrtc_audio_device_impl.h"
12c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "content/renderer/media/webrtc_local_audio_track.h"
13c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "media/audio/audio_parameters.h"
14c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "media/base/audio_bus.h"
15c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "media/base/audio_capturer_source.h"
16c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "testing/gmock/include/gmock/gmock.h"
17c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "testing/gtest/include/gtest/gtest.h"
185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "third_party/WebKit/public/platform/WebMediaConstraints.h"
191320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "third_party/WebKit/public/web/WebHeap.h"
20bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch#include "third_party/libjingle/source/talk/app/webrtc/mediastreaminterface.h"
21c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
22c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)using ::testing::_;
237d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)using ::testing::AnyNumber;
24c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)using ::testing::AtLeast;
25c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)using ::testing::Return;
26c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
27c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)namespace content {
28c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
29c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)namespace {
30c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
31c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)ACTION_P(SignalEvent, event) {
32c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  event->Signal();
33c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
34c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
35c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// A simple thread that we use to fake the audio thread which provides data to
36c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// the |WebRtcAudioCapturer|.
37c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)class FakeAudioThread : public base::PlatformThread::Delegate {
38c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) public:
390529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  FakeAudioThread(WebRtcAudioCapturer* capturer,
40f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                  const media::AudioParameters& params)
41c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    : capturer_(capturer),
4290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      thread_(),
43c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      closure_(false, false) {
440529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    DCHECK(capturer);
45f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    audio_bus_ = media::AudioBus::Create(params);
46c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
47c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
4890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  virtual ~FakeAudioThread() { DCHECK(thread_.is_null()); }
49c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
50c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // base::PlatformThread::Delegate:
51c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  virtual void ThreadMain() OVERRIDE {
52c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    while (true) {
53c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      if (closure_.IsSignaled())
54c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        return;
55c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
56c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      media::AudioCapturerSource::CaptureCallback* callback =
57868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)          static_cast<media::AudioCapturerSource::CaptureCallback*>(
580529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch              capturer_);
59c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      audio_bus_->Zero();
603551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      callback->Capture(audio_bus_.get(), 0, 0, false);
61c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
62c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      // Sleep 1ms to yield the resource for the main thread.
63c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(1));
64c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    }
65c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
66c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
67c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  void Start() {
68c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    base::PlatformThread::CreateWithPriority(
69c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        0, this, &thread_, base::kThreadPriority_RealtimeAudio);
7090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    CHECK(!thread_.is_null());
71c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
72c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
73c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  void Stop() {
74c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    closure_.Signal();
75c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    base::PlatformThread::Join(thread_);
7690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    thread_ = base::PlatformThreadHandle();
77c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
78c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
79c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) private:
80c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  scoped_ptr<media::AudioBus> audio_bus_;
810529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  WebRtcAudioCapturer* capturer_;
82c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  base::PlatformThreadHandle thread_;
83c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  base::WaitableEvent closure_;
84c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(FakeAudioThread);
85c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)};
86c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
87c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)class MockCapturerSource : public media::AudioCapturerSource {
88c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) public:
89f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  explicit MockCapturerSource(WebRtcAudioCapturer* capturer)
90f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      : capturer_(capturer) {}
91f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  MOCK_METHOD3(OnInitialize, void(const media::AudioParameters& params,
92f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                                  CaptureCallback* callback,
93f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                                  int session_id));
94f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  MOCK_METHOD0(OnStart, void());
95f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  MOCK_METHOD0(OnStop, void());
96c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  MOCK_METHOD1(SetVolume, void(double volume));
97c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  MOCK_METHOD1(SetAutomaticGainControl, void(bool enable));
98c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
99f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  virtual void Initialize(const media::AudioParameters& params,
100f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                          CaptureCallback* callback,
101f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                          int session_id) OVERRIDE {
102f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    DCHECK(params.IsValid());
103f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    params_ = params;
104f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    OnInitialize(params, callback, session_id);
105f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  }
106f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  virtual void Start() OVERRIDE {
107f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    audio_thread_.reset(new FakeAudioThread(capturer_, params_));
108f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    audio_thread_->Start();
109f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    OnStart();
110f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  }
111f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  virtual void Stop() OVERRIDE {
112f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    audio_thread_->Stop();
113f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    audio_thread_.reset();
114f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    OnStop();
115f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  }
116c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) protected:
117c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  virtual ~MockCapturerSource() {}
118f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
119f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) private:
120f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  scoped_ptr<FakeAudioThread> audio_thread_;
121f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  WebRtcAudioCapturer* capturer_;
122f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  media::AudioParameters params_;
123c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)};
124c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
125a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// TODO(xians): Use MediaStreamAudioSink.
126a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)class MockMediaStreamAudioSink : public PeerConnectionAudioSink {
127c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) public:
128a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  MockMediaStreamAudioSink() {}
129a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  ~MockMediaStreamAudioSink() {}
130a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  int OnData(const int16* audio_data,
131a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)             int sample_rate,
132a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)             int number_of_channels,
133a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)             int number_of_frames,
134a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)             const std::vector<int>& channels,
135a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)             int audio_delay_milliseconds,
136a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)             int current_volume,
137a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)             bool need_audio_processing,
138a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)             bool key_pressed) OVERRIDE {
139a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    EXPECT_EQ(params_.sample_rate(), sample_rate);
140a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    EXPECT_EQ(params_.channels(), number_of_channels);
141a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    EXPECT_EQ(params_.frames_per_buffer(), number_of_frames);
1423551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    CaptureData(channels.size(),
1433551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                audio_delay_milliseconds,
1443551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                current_volume,
1453551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                need_audio_processing,
1463551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                key_pressed);
147bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch    return 0;
148bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  }
149a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  MOCK_METHOD5(CaptureData,
1503551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)               void(int number_of_network_channels,
1513551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                    int audio_delay_milliseconds,
1523551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                    int current_volume,
1533551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                    bool need_audio_processing,
1543551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                    bool key_pressed));
155a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  void OnSetFormat(const media::AudioParameters& params) {
156a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    params_ = params;
157a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    FormatIsSet();
158a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  }
159a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  MOCK_METHOD0(FormatIsSet, void());
160a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
161a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  const media::AudioParameters& audio_params() const { return params_; }
162a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
163a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) private:
164a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  media::AudioParameters params_;
165c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)};
166c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
167c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}  // namespace
168c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
169c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)class WebRtcLocalAudioTrackTest : public ::testing::Test {
170c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) protected:
171c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  virtual void SetUp() OVERRIDE {
172d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    params_.Reset(media::AudioParameters::AUDIO_PCM_LOW_LATENCY,
1731320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                  media::CHANNEL_LAYOUT_STEREO, 2, 48000, 16, 480);
174cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    MockMediaConstraintFactory constraint_factory;
1750529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    blink_source_.initialize("dummy", blink::WebMediaStreamSource::TypeAudio,
1760529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch                             "dummy");
1770529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    MediaStreamAudioSource* audio_source = new MediaStreamAudioSource();
1780529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    blink_source_.setExtraData(audio_source);
1790529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
180a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    StreamDeviceInfo device(MEDIA_DEVICE_AUDIO_CAPTURE,
181a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                            std::string(), std::string());
182cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    capturer_ = WebRtcAudioCapturer::CreateCapturer(
183cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        -1, device, constraint_factory.CreateWebMediaConstraints(), NULL,
184cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        audio_source);
1851320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    audio_source->SetAudioCapturer(capturer_.get());
186f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    capturer_source_ = new MockCapturerSource(capturer_.get());
1875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    EXPECT_CALL(*capturer_source_.get(), OnInitialize(_, capturer_.get(), -1))
188c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        .WillOnce(Return());
1890529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    EXPECT_CALL(*capturer_source_.get(), SetAutomaticGainControl(true));
1900529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    EXPECT_CALL(*capturer_source_.get(), OnStart());
1915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    capturer_->SetCapturerSourceForTesting(capturer_source_, params_);
192c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
193c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1941320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  virtual void TearDown() OVERRIDE {
1951320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    blink_source_.reset();
1961320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    blink::WebHeap::collectAllGarbageForTesting();
1971320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  }
1981320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
199d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  media::AudioParameters params_;
2000529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  blink::WebMediaStreamSource blink_source_;
201c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  scoped_refptr<MockCapturerSource> capturer_source_;
202c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  scoped_refptr<WebRtcAudioCapturer> capturer_;
203c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)};
204c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
205c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Creates a capturer and audio track, fakes its audio thread, and
206c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// connect/disconnect the sink to the audio track on the fly, the sink should
207c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// get data callback when the track is connected to the capturer but not when
208c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// the track is disconnected from the capturer.
209c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)TEST_F(WebRtcLocalAudioTrackTest, ConnectAndDisconnectOneSink) {
2105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  scoped_refptr<WebRtcLocalAudioTrackAdapter> adapter(
2115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      WebRtcLocalAudioTrackAdapter::Create(std::string(), NULL));
2125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  scoped_ptr<WebRtcLocalAudioTrack> track(
2131320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      new WebRtcLocalAudioTrack(adapter.get(), capturer_, NULL));
2147d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  track->Start();
215a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  EXPECT_TRUE(track->GetAudioAdapter()->enabled());
216bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch
217a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  scoped_ptr<MockMediaStreamAudioSink> sink(new MockMediaStreamAudioSink());
218c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  base::WaitableEvent event(false, false);
219a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  EXPECT_CALL(*sink, FormatIsSet());
2203551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  EXPECT_CALL(*sink,
221f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      CaptureData(0,
22258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                  0,
22358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                  0,
224a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                  _,
22558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                  false)).Times(AtLeast(1))
2263551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      .WillRepeatedly(SignalEvent(&event));
227c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  track->AddSink(sink.get());
228c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_TRUE(event.TimedWait(TestTimeouts::tiny_timeout()));
229c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  track->RemoveSink(sink.get());
2307d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
231f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  EXPECT_CALL(*capturer_source_.get(), OnStop()).WillOnce(Return());
232f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  capturer_->Stop();
233c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
234c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
235c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// The same setup as ConnectAndDisconnectOneSink, but enable and disable the
236c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// audio track on the fly. When the audio track is disabled, there is no data
237c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// callback to the sink; when the audio track is enabled, there comes data
238c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// callback.
239c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// TODO(xians): Enable this test after resolving the racing issue that TSAN
240c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// reports on MediaStreamTrack::enabled();
241f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)TEST_F(WebRtcLocalAudioTrackTest,  DISABLED_DisableEnableAudioTrack) {
242f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  EXPECT_CALL(*capturer_source_.get(), SetAutomaticGainControl(true));
243f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  EXPECT_CALL(*capturer_source_.get(), OnStart());
2445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  scoped_refptr<WebRtcLocalAudioTrackAdapter> adapter(
2455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      WebRtcLocalAudioTrackAdapter::Create(std::string(), NULL));
2465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  scoped_ptr<WebRtcLocalAudioTrack> track(
2471320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      new WebRtcLocalAudioTrack(adapter.get(), capturer_, NULL));
2487d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  track->Start();
249a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  EXPECT_TRUE(track->GetAudioAdapter()->enabled());
250a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  EXPECT_TRUE(track->GetAudioAdapter()->set_enabled(false));
251a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  scoped_ptr<MockMediaStreamAudioSink> sink(new MockMediaStreamAudioSink());
2525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  const media::AudioParameters params = capturer_->source_audio_parameters();
253c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  base::WaitableEvent event(false, false);
254a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  EXPECT_CALL(*sink, FormatIsSet()).Times(1);
2553551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  EXPECT_CALL(*sink,
256f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)              CaptureData(0, 0, 0, _, false)).Times(0);
257a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  EXPECT_EQ(sink->audio_params().frames_per_buffer(),
258a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)            params.sample_rate() / 100);
259c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  track->AddSink(sink.get());
260c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_FALSE(event.TimedWait(TestTimeouts::tiny_timeout()));
261c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
262c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  event.Reset();
263f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  EXPECT_CALL(*sink, CaptureData(0, 0, 0, _, false)).Times(AtLeast(1))
2643551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      .WillRepeatedly(SignalEvent(&event));
265a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  EXPECT_TRUE(track->GetAudioAdapter()->set_enabled(true));
266c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_TRUE(event.TimedWait(TestTimeouts::tiny_timeout()));
267c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  track->RemoveSink(sink.get());
2687d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
269f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  EXPECT_CALL(*capturer_source_.get(), OnStop()).WillOnce(Return());
270f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  capturer_->Stop();
2715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  track.reset();
272c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
273c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
274c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Create multiple audio tracks and enable/disable them, verify that the audio
275c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// callbacks appear/disappear.
27668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)// Flaky due to a data race, see http://crbug.com/295418
27768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)TEST_F(WebRtcLocalAudioTrackTest, DISABLED_MultipleAudioTracks) {
2785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  scoped_refptr<WebRtcLocalAudioTrackAdapter> adapter_1(
2795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      WebRtcLocalAudioTrackAdapter::Create(std::string(), NULL));
2805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  scoped_ptr<WebRtcLocalAudioTrack> track_1(
2811320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      new WebRtcLocalAudioTrack(adapter_1.get(), capturer_, NULL));
2827d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  track_1->Start();
283a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  EXPECT_TRUE(track_1->GetAudioAdapter()->enabled());
284a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  scoped_ptr<MockMediaStreamAudioSink> sink_1(new MockMediaStreamAudioSink());
2855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  const media::AudioParameters params = capturer_->source_audio_parameters();
286c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  base::WaitableEvent event_1(false, false);
287a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  EXPECT_CALL(*sink_1, FormatIsSet()).WillOnce(Return());
2883551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  EXPECT_CALL(*sink_1,
289f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      CaptureData(0, 0, 0, _, false)).Times(AtLeast(1))
2903551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      .WillRepeatedly(SignalEvent(&event_1));
291a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  EXPECT_EQ(sink_1->audio_params().frames_per_buffer(),
292a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)            params.sample_rate() / 100);
293c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  track_1->AddSink(sink_1.get());
2947d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  EXPECT_TRUE(event_1.TimedWait(TestTimeouts::tiny_timeout()));
295c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
2965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  scoped_refptr<WebRtcLocalAudioTrackAdapter> adapter_2(
2975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      WebRtcLocalAudioTrackAdapter::Create(std::string(), NULL));
2985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  scoped_ptr<WebRtcLocalAudioTrack> track_2(
2991320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      new WebRtcLocalAudioTrack(adapter_2.get(), capturer_, NULL));
3007d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  track_2->Start();
301a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  EXPECT_TRUE(track_2->GetAudioAdapter()->enabled());
302c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
3037d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  // Verify both |sink_1| and |sink_2| get data.
304c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  event_1.Reset();
305c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  base::WaitableEvent event_2(false, false);
3067d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
307a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  scoped_ptr<MockMediaStreamAudioSink> sink_2(new MockMediaStreamAudioSink());
308a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  EXPECT_CALL(*sink_2, FormatIsSet()).WillOnce(Return());
309f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  EXPECT_CALL(*sink_1, CaptureData(0, 0, 0, _, false)).Times(AtLeast(1))
3103551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      .WillRepeatedly(SignalEvent(&event_1));
311a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  EXPECT_EQ(sink_1->audio_params().frames_per_buffer(),
312a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)            params.sample_rate() / 100);
313f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  EXPECT_CALL(*sink_2, CaptureData(0, 0, 0, _, false)).Times(AtLeast(1))
3143551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      .WillRepeatedly(SignalEvent(&event_2));
315a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  EXPECT_EQ(sink_2->audio_params().frames_per_buffer(),
316a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)            params.sample_rate() / 100);
3177d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  track_2->AddSink(sink_2.get());
318c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_TRUE(event_1.TimedWait(TestTimeouts::tiny_timeout()));
319c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_TRUE(event_2.TimedWait(TestTimeouts::tiny_timeout()));
320c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
321c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  track_1->RemoveSink(sink_1.get());
3227d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  track_1->Stop();
3235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  track_1.reset();
3247d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
325f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  EXPECT_CALL(*capturer_source_.get(), OnStop()).WillOnce(Return());
326c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  track_2->RemoveSink(sink_2.get());
3277d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  track_2->Stop();
3285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  track_2.reset();
3297d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)}
3307d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
3317d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
3327d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)// Start one track and verify the capturer is correctly starting its source.
3337d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)// And it should be fine to not to call Stop() explicitly.
3347d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)TEST_F(WebRtcLocalAudioTrackTest, StartOneAudioTrack) {
3355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  scoped_refptr<WebRtcLocalAudioTrackAdapter> adapter(
3365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      WebRtcLocalAudioTrackAdapter::Create(std::string(), NULL));
3375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  scoped_ptr<WebRtcLocalAudioTrack> track(
3381320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      new WebRtcLocalAudioTrack(adapter.get(), capturer_, NULL));
3397d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  track->Start();
3407d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
3417d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  // When the track goes away, it will automatically stop the
3427d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  // |capturer_source_|.
343f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  EXPECT_CALL(*capturer_source_.get(), OnStop());
3445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  track.reset();
3457d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)}
3467d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
3470529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch// Start two tracks and verify the capturer is correctly starting its source.
3480529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch// When the last track connected to the capturer is stopped, the source is
3490529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch// stopped.
3500529e5d033099cbfc42635f6f6183833b09dff6eBen MurdochTEST_F(WebRtcLocalAudioTrackTest, StartTwoAudioTracks) {
3510529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  scoped_refptr<WebRtcLocalAudioTrackAdapter> adapter1(
3520529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      WebRtcLocalAudioTrackAdapter::Create(std::string(), NULL));
3530529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  scoped_ptr<WebRtcLocalAudioTrack> track1(
3541320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      new WebRtcLocalAudioTrack(adapter1.get(), capturer_, NULL));
3550529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  track1->Start();
3560529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
3570529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  scoped_refptr<WebRtcLocalAudioTrackAdapter> adapter2(
3580529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch        WebRtcLocalAudioTrackAdapter::Create(std::string(), NULL));
3590529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  scoped_ptr<WebRtcLocalAudioTrack> track2(
3601320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      new WebRtcLocalAudioTrack(adapter2.get(), capturer_, NULL));
3610529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  track2->Start();
3620529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
3630529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  track1->Stop();
3640529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  // When the last track is stopped, it will automatically stop the
3650529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  // |capturer_source_|.
3660529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  EXPECT_CALL(*capturer_source_.get(), OnStop());
3670529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  track2->Stop();
3680529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch}
3690529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
3707d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)// Start/Stop tracks and verify the capturer is correctly starting/stopping
3717d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)// its source.
3727d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)TEST_F(WebRtcLocalAudioTrackTest, StartAndStopAudioTracks) {
373bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  base::WaitableEvent event(false, false);
3745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  scoped_refptr<WebRtcLocalAudioTrackAdapter> adapter_1(
3755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      WebRtcLocalAudioTrackAdapter::Create(std::string(), NULL));
3765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  scoped_ptr<WebRtcLocalAudioTrack> track_1(
3771320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      new WebRtcLocalAudioTrack(adapter_1.get(), capturer_, NULL));
3787d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  track_1->Start();
3797d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
380bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  // Verify the data flow by connecting the sink to |track_1|.
381a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  scoped_ptr<MockMediaStreamAudioSink> sink(new MockMediaStreamAudioSink());
382bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  event.Reset();
383a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  EXPECT_CALL(*sink, FormatIsSet()).WillOnce(SignalEvent(&event));
384a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  EXPECT_CALL(*sink, CaptureData(_, 0, 0, _, false))
385bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch      .Times(AnyNumber()).WillRepeatedly(Return());
386bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  track_1->AddSink(sink.get());
387f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  EXPECT_TRUE(event.TimedWait(TestTimeouts::tiny_timeout()));
388bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch
3897d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  // Start the second audio track will not start the |capturer_source_|
3907d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  // since it has been started.
391f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  EXPECT_CALL(*capturer_source_.get(), OnStart()).Times(0);
3925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  scoped_refptr<WebRtcLocalAudioTrackAdapter> adapter_2(
3935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      WebRtcLocalAudioTrackAdapter::Create(std::string(), NULL));
3945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  scoped_ptr<WebRtcLocalAudioTrack> track_2(
3951320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      new WebRtcLocalAudioTrack(adapter_2.get(), capturer_, NULL));
3967d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  track_2->Start();
3977d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
398f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // Stop the capturer will clear up the track lists in the capturer.
399f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  EXPECT_CALL(*capturer_source_.get(), OnStop());
400f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  capturer_->Stop();
4017d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
402f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // Adding a new track to the capturer.
403bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  track_2->AddSink(sink.get());
404a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  EXPECT_CALL(*sink, FormatIsSet()).Times(0);
405bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch
406f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // Stop the capturer again will not trigger stopping the source of the
407f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // capturer again..
4087d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  event.Reset();
409f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  EXPECT_CALL(*capturer_source_.get(), OnStop()).Times(0);
410f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  capturer_->Stop();
4117d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)}
4127d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
4136e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)// Contains data races reported by tsan: crbug.com/404133
4146e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)#if defined(THREAD_SANITIZER)
4156e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  #define DISABLE_ON_TSAN(function) DISABLED_##function
4166e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)#else
4176e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  #define DISABLE_ON_TSAN(function) function
4186e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)#endif
4196e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
420bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch// Create a new capturer with new source, connect it to a new audio track.
4216e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)TEST_F(WebRtcLocalAudioTrackTest,
4226e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)       DISABLE_ON_TSAN(ConnectTracksToDifferentCapturers)) {
423bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  // Setup the first audio track and start it.
4245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  scoped_refptr<WebRtcLocalAudioTrackAdapter> adapter_1(
4255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      WebRtcLocalAudioTrackAdapter::Create(std::string(), NULL));
4265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  scoped_ptr<WebRtcLocalAudioTrack> track_1(
4271320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      new WebRtcLocalAudioTrack(adapter_1.get(), capturer_, NULL));
428bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  track_1->Start();
429bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch
430bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  // Verify the data flow by connecting the |sink_1| to |track_1|.
431a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  scoped_ptr<MockMediaStreamAudioSink> sink_1(new MockMediaStreamAudioSink());
432f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  EXPECT_CALL(*sink_1.get(), CaptureData(0, 0, 0, _, false))
433bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch      .Times(AnyNumber()).WillRepeatedly(Return());
434a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  EXPECT_CALL(*sink_1.get(), FormatIsSet()).Times(AnyNumber());
435bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  track_1->AddSink(sink_1.get());
436bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch
437bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  // Create a new capturer with new source with different audio format.
438cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  MockMediaConstraintFactory constraint_factory;
439a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  StreamDeviceInfo device(MEDIA_DEVICE_AUDIO_CAPTURE,
440a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                          std::string(), std::string());
441bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  scoped_refptr<WebRtcAudioCapturer> new_capturer(
442cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      WebRtcAudioCapturer::CreateCapturer(
443cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)          -1, device, constraint_factory.CreateWebMediaConstraints(), NULL,
444cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)          NULL));
445f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  scoped_refptr<MockCapturerSource> new_source(
446f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      new MockCapturerSource(new_capturer.get()));
4475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  EXPECT_CALL(*new_source.get(), OnInitialize(_, new_capturer.get(), -1));
4480529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  EXPECT_CALL(*new_source.get(), SetAutomaticGainControl(true));
4490529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  EXPECT_CALL(*new_source.get(), OnStart());
4500529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
4515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  media::AudioParameters new_param(
4525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      media::AudioParameters::AUDIO_PCM_LOW_LATENCY,
4535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      media::CHANNEL_LAYOUT_MONO, 44100, 16, 441);
4545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  new_capturer->SetCapturerSourceForTesting(new_source, new_param);
455bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch
456bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  // Setup the second audio track, connect it to the new capturer and start it.
4575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  scoped_refptr<WebRtcLocalAudioTrackAdapter> adapter_2(
4585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      WebRtcLocalAudioTrackAdapter::Create(std::string(), NULL));
4595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  scoped_ptr<WebRtcLocalAudioTrack> track_2(
4601320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      new WebRtcLocalAudioTrack(adapter_2.get(), new_capturer, NULL));
461bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  track_2->Start();
462bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch
463bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  // Verify the data flow by connecting the |sink_2| to |track_2|.
464a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  scoped_ptr<MockMediaStreamAudioSink> sink_2(new MockMediaStreamAudioSink());
465f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  base::WaitableEvent event(false, false);
466f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  EXPECT_CALL(*sink_2, CaptureData(0, 0, 0, _, false))
467bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch      .Times(AnyNumber()).WillRepeatedly(Return());
468a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  EXPECT_CALL(*sink_2, FormatIsSet()).WillOnce(SignalEvent(&event));
469bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  track_2->AddSink(sink_2.get());
470f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  EXPECT_TRUE(event.TimedWait(TestTimeouts::tiny_timeout()));
471f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
472f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // Stopping the new source will stop the second track.
473f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  event.Reset();
474f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  EXPECT_CALL(*new_source.get(), OnStop())
475f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      .Times(1).WillOnce(SignalEvent(&event));
476f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  new_capturer->Stop();
477f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  EXPECT_TRUE(event.TimedWait(TestTimeouts::tiny_timeout()));
478f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
479f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // Stop the capturer of the first audio track.
480f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  EXPECT_CALL(*capturer_source_.get(), OnStop());
481f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  capturer_->Stop();
482f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
483f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
484f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// Make sure a audio track can deliver packets with a buffer size smaller than
485f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// 10ms when it is not connected with a peer connection.
486f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)TEST_F(WebRtcLocalAudioTrackTest, TrackWorkWithSmallBufferSize) {
487f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // Setup a capturer which works with a buffer size smaller than 10ms.
488f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  media::AudioParameters params(media::AudioParameters::AUDIO_PCM_LOW_LATENCY,
489f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                                media::CHANNEL_LAYOUT_STEREO, 48000, 16, 128);
490f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
491f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // Create a capturer with new source which works with the format above.
492a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  MockMediaConstraintFactory factory;
493a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  factory.DisableDefaultAudioConstraints();
494f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  scoped_refptr<WebRtcAudioCapturer> capturer(
4955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      WebRtcAudioCapturer::CreateCapturer(
4965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)          -1,
4975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)          StreamDeviceInfo(MEDIA_DEVICE_AUDIO_CAPTURE,
4985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                           "", "", params.sample_rate(),
4995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                           params.channel_layout(),
5005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                           params.frames_per_buffer()),
501a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)          factory.CreateWebMediaConstraints(),
5020529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch          NULL, NULL));
503f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  scoped_refptr<MockCapturerSource> source(
504f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      new MockCapturerSource(capturer.get()));
5055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  EXPECT_CALL(*source.get(), OnInitialize(_, capturer.get(), -1));
5060529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  EXPECT_CALL(*source.get(), SetAutomaticGainControl(true));
5070529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  EXPECT_CALL(*source.get(), OnStart());
5085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  capturer->SetCapturerSourceForTesting(source, params);
509f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
510f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // Setup a audio track, connect it to the capturer and start it.
5115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  scoped_refptr<WebRtcLocalAudioTrackAdapter> adapter(
5125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      WebRtcLocalAudioTrackAdapter::Create(std::string(), NULL));
5135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  scoped_ptr<WebRtcLocalAudioTrack> track(
5141320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      new WebRtcLocalAudioTrack(adapter.get(), capturer, NULL));
515f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  track->Start();
516f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
517f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // Verify the data flow by connecting the |sink| to |track|.
518a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  scoped_ptr<MockMediaStreamAudioSink> sink(new MockMediaStreamAudioSink());
519bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  base::WaitableEvent event(false, false);
520a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  EXPECT_CALL(*sink, FormatIsSet()).Times(1);
521f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // Verify the sinks are getting the packets with an expecting buffer size.
522f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#if defined(OS_ANDROID)
523f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  const int expected_buffer_size = params.sample_rate() / 100;
524f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#else
525f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  const int expected_buffer_size = params.frames_per_buffer();
526f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#endif
527f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  EXPECT_CALL(*sink, CaptureData(
528a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      0, 0, 0, _, false))
529f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      .Times(AtLeast(1)).WillRepeatedly(SignalEvent(&event));
530f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  track->AddSink(sink.get());
531bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  EXPECT_TRUE(event.TimedWait(TestTimeouts::tiny_timeout()));
532a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  EXPECT_EQ(expected_buffer_size, sink->audio_params().frames_per_buffer());
533bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch
534f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // Stopping the new source will stop the second track.
5351320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  EXPECT_CALL(*source.get(), OnStop()).Times(1);
536f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  capturer->Stop();
5370529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
5380529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  // Even though this test don't use |capturer_source_| it will be stopped
5390529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  // during teardown of the test harness.
5400529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  EXPECT_CALL(*capturer_source_.get(), OnStop());
541bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch}
542bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch
543c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}  // namespace content
544