webrtc_local_audio_track_unittest.cc revision 1320f92c476a1ad9d19dba2a48c72b75566198e9
1// Copyright 2013 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "base/synchronization/waitable_event.h"
6#include "base/test/test_timeouts.h"
7#include "content/renderer/media/media_stream_audio_source.h"
8#include "content/renderer/media/mock_media_constraint_factory.h"
9#include "content/renderer/media/webrtc/webrtc_local_audio_track_adapter.h"
10#include "content/renderer/media/webrtc_audio_capturer.h"
11#include "content/renderer/media/webrtc_audio_device_impl.h"
12#include "content/renderer/media/webrtc_local_audio_track.h"
13#include "media/audio/audio_parameters.h"
14#include "media/base/audio_bus.h"
15#include "media/base/audio_capturer_source.h"
16#include "testing/gmock/include/gmock/gmock.h"
17#include "testing/gtest/include/gtest/gtest.h"
18#include "third_party/WebKit/public/platform/WebMediaConstraints.h"
19#include "third_party/WebKit/public/web/WebHeap.h"
20#include "third_party/libjingle/source/talk/app/webrtc/mediastreaminterface.h"
21
22using ::testing::_;
23using ::testing::AnyNumber;
24using ::testing::AtLeast;
25using ::testing::Return;
26
27namespace content {
28
29namespace {
30
31ACTION_P(SignalEvent, event) {
32  event->Signal();
33}
34
35// A simple thread that we use to fake the audio thread which provides data to
36// the |WebRtcAudioCapturer|.
37class FakeAudioThread : public base::PlatformThread::Delegate {
38 public:
39  FakeAudioThread(WebRtcAudioCapturer* capturer,
40                  const media::AudioParameters& params)
41    : capturer_(capturer),
42      thread_(),
43      closure_(false, false) {
44    DCHECK(capturer);
45    audio_bus_ = media::AudioBus::Create(params);
46  }
47
48  virtual ~FakeAudioThread() { DCHECK(thread_.is_null()); }
49
50  // base::PlatformThread::Delegate:
51  virtual void ThreadMain() OVERRIDE {
52    while (true) {
53      if (closure_.IsSignaled())
54        return;
55
56      media::AudioCapturerSource::CaptureCallback* callback =
57          static_cast<media::AudioCapturerSource::CaptureCallback*>(
58              capturer_);
59      audio_bus_->Zero();
60      callback->Capture(audio_bus_.get(), 0, 0, false);
61
62      // Sleep 1ms to yield the resource for the main thread.
63      base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(1));
64    }
65  }
66
67  void Start() {
68    base::PlatformThread::CreateWithPriority(
69        0, this, &thread_, base::kThreadPriority_RealtimeAudio);
70    CHECK(!thread_.is_null());
71  }
72
73  void Stop() {
74    closure_.Signal();
75    base::PlatformThread::Join(thread_);
76    thread_ = base::PlatformThreadHandle();
77  }
78
79 private:
80  scoped_ptr<media::AudioBus> audio_bus_;
81  WebRtcAudioCapturer* capturer_;
82  base::PlatformThreadHandle thread_;
83  base::WaitableEvent closure_;
84  DISALLOW_COPY_AND_ASSIGN(FakeAudioThread);
85};
86
87class MockCapturerSource : public media::AudioCapturerSource {
88 public:
89  explicit MockCapturerSource(WebRtcAudioCapturer* capturer)
90      : capturer_(capturer) {}
91  MOCK_METHOD3(OnInitialize, void(const media::AudioParameters& params,
92                                  CaptureCallback* callback,
93                                  int session_id));
94  MOCK_METHOD0(OnStart, void());
95  MOCK_METHOD0(OnStop, void());
96  MOCK_METHOD1(SetVolume, void(double volume));
97  MOCK_METHOD1(SetAutomaticGainControl, void(bool enable));
98
99  virtual void Initialize(const media::AudioParameters& params,
100                          CaptureCallback* callback,
101                          int session_id) OVERRIDE {
102    DCHECK(params.IsValid());
103    params_ = params;
104    OnInitialize(params, callback, session_id);
105  }
106  virtual void Start() OVERRIDE {
107    audio_thread_.reset(new FakeAudioThread(capturer_, params_));
108    audio_thread_->Start();
109    OnStart();
110  }
111  virtual void Stop() OVERRIDE {
112    audio_thread_->Stop();
113    audio_thread_.reset();
114    OnStop();
115  }
116 protected:
117  virtual ~MockCapturerSource() {}
118
119 private:
120  scoped_ptr<FakeAudioThread> audio_thread_;
121  WebRtcAudioCapturer* capturer_;
122  media::AudioParameters params_;
123};
124
125// TODO(xians): Use MediaStreamAudioSink.
126class MockMediaStreamAudioSink : public PeerConnectionAudioSink {
127 public:
128  MockMediaStreamAudioSink() {}
129  ~MockMediaStreamAudioSink() {}
130  int OnData(const int16* audio_data,
131             int sample_rate,
132             int number_of_channels,
133             int number_of_frames,
134             const std::vector<int>& channels,
135             int audio_delay_milliseconds,
136             int current_volume,
137             bool need_audio_processing,
138             bool key_pressed) OVERRIDE {
139    EXPECT_EQ(params_.sample_rate(), sample_rate);
140    EXPECT_EQ(params_.channels(), number_of_channels);
141    EXPECT_EQ(params_.frames_per_buffer(), number_of_frames);
142    CaptureData(channels.size(),
143                audio_delay_milliseconds,
144                current_volume,
145                need_audio_processing,
146                key_pressed);
147    return 0;
148  }
149  MOCK_METHOD5(CaptureData,
150               void(int number_of_network_channels,
151                    int audio_delay_milliseconds,
152                    int current_volume,
153                    bool need_audio_processing,
154                    bool key_pressed));
155  void OnSetFormat(const media::AudioParameters& params) {
156    params_ = params;
157    FormatIsSet();
158  }
159  MOCK_METHOD0(FormatIsSet, void());
160
161  const media::AudioParameters& audio_params() const { return params_; }
162
163 private:
164  media::AudioParameters params_;
165};
166
167}  // namespace
168
169class WebRtcLocalAudioTrackTest : public ::testing::Test {
170 protected:
171  virtual void SetUp() OVERRIDE {
172    params_.Reset(media::AudioParameters::AUDIO_PCM_LOW_LATENCY,
173                  media::CHANNEL_LAYOUT_STEREO, 2, 48000, 16, 480);
174    MockMediaConstraintFactory constraint_factory;
175    blink_source_.initialize("dummy", blink::WebMediaStreamSource::TypeAudio,
176                             "dummy");
177    MediaStreamAudioSource* audio_source = new MediaStreamAudioSource();
178    blink_source_.setExtraData(audio_source);
179
180    StreamDeviceInfo device(MEDIA_DEVICE_AUDIO_CAPTURE,
181                            std::string(), std::string());
182    capturer_ = WebRtcAudioCapturer::CreateCapturer(
183        -1, device, constraint_factory.CreateWebMediaConstraints(), NULL,
184        audio_source);
185    audio_source->SetAudioCapturer(capturer_.get());
186    capturer_source_ = new MockCapturerSource(capturer_.get());
187    EXPECT_CALL(*capturer_source_.get(), OnInitialize(_, capturer_.get(), -1))
188        .WillOnce(Return());
189    EXPECT_CALL(*capturer_source_.get(), SetAutomaticGainControl(true));
190    EXPECT_CALL(*capturer_source_.get(), OnStart());
191    capturer_->SetCapturerSourceForTesting(capturer_source_, params_);
192  }
193
194  virtual void TearDown() OVERRIDE {
195    blink_source_.reset();
196    blink::WebHeap::collectAllGarbageForTesting();
197  }
198
199  media::AudioParameters params_;
200  blink::WebMediaStreamSource blink_source_;
201  scoped_refptr<MockCapturerSource> capturer_source_;
202  scoped_refptr<WebRtcAudioCapturer> capturer_;
203};
204
205// Creates a capturer and audio track, fakes its audio thread, and
206// connect/disconnect the sink to the audio track on the fly, the sink should
207// get data callback when the track is connected to the capturer but not when
208// the track is disconnected from the capturer.
209TEST_F(WebRtcLocalAudioTrackTest, ConnectAndDisconnectOneSink) {
210  scoped_refptr<WebRtcLocalAudioTrackAdapter> adapter(
211      WebRtcLocalAudioTrackAdapter::Create(std::string(), NULL));
212  scoped_ptr<WebRtcLocalAudioTrack> track(
213      new WebRtcLocalAudioTrack(adapter.get(), capturer_, NULL));
214  track->Start();
215  EXPECT_TRUE(track->GetAudioAdapter()->enabled());
216
217  scoped_ptr<MockMediaStreamAudioSink> sink(new MockMediaStreamAudioSink());
218  base::WaitableEvent event(false, false);
219  EXPECT_CALL(*sink, FormatIsSet());
220  EXPECT_CALL(*sink,
221      CaptureData(0,
222                  0,
223                  0,
224                  _,
225                  false)).Times(AtLeast(1))
226      .WillRepeatedly(SignalEvent(&event));
227  track->AddSink(sink.get());
228  EXPECT_TRUE(event.TimedWait(TestTimeouts::tiny_timeout()));
229  track->RemoveSink(sink.get());
230
231  EXPECT_CALL(*capturer_source_.get(), OnStop()).WillOnce(Return());
232  capturer_->Stop();
233}
234
235// The same setup as ConnectAndDisconnectOneSink, but enable and disable the
236// audio track on the fly. When the audio track is disabled, there is no data
237// callback to the sink; when the audio track is enabled, there comes data
238// callback.
239// TODO(xians): Enable this test after resolving the racing issue that TSAN
240// reports on MediaStreamTrack::enabled();
241TEST_F(WebRtcLocalAudioTrackTest,  DISABLED_DisableEnableAudioTrack) {
242  EXPECT_CALL(*capturer_source_.get(), SetAutomaticGainControl(true));
243  EXPECT_CALL(*capturer_source_.get(), OnStart());
244  scoped_refptr<WebRtcLocalAudioTrackAdapter> adapter(
245      WebRtcLocalAudioTrackAdapter::Create(std::string(), NULL));
246  scoped_ptr<WebRtcLocalAudioTrack> track(
247      new WebRtcLocalAudioTrack(adapter.get(), capturer_, NULL));
248  track->Start();
249  EXPECT_TRUE(track->GetAudioAdapter()->enabled());
250  EXPECT_TRUE(track->GetAudioAdapter()->set_enabled(false));
251  scoped_ptr<MockMediaStreamAudioSink> sink(new MockMediaStreamAudioSink());
252  const media::AudioParameters params = capturer_->source_audio_parameters();
253  base::WaitableEvent event(false, false);
254  EXPECT_CALL(*sink, FormatIsSet()).Times(1);
255  EXPECT_CALL(*sink,
256              CaptureData(0, 0, 0, _, false)).Times(0);
257  EXPECT_EQ(sink->audio_params().frames_per_buffer(),
258            params.sample_rate() / 100);
259  track->AddSink(sink.get());
260  EXPECT_FALSE(event.TimedWait(TestTimeouts::tiny_timeout()));
261
262  event.Reset();
263  EXPECT_CALL(*sink, CaptureData(0, 0, 0, _, false)).Times(AtLeast(1))
264      .WillRepeatedly(SignalEvent(&event));
265  EXPECT_TRUE(track->GetAudioAdapter()->set_enabled(true));
266  EXPECT_TRUE(event.TimedWait(TestTimeouts::tiny_timeout()));
267  track->RemoveSink(sink.get());
268
269  EXPECT_CALL(*capturer_source_.get(), OnStop()).WillOnce(Return());
270  capturer_->Stop();
271  track.reset();
272}
273
274// Create multiple audio tracks and enable/disable them, verify that the audio
275// callbacks appear/disappear.
276// Flaky due to a data race, see http://crbug.com/295418
277TEST_F(WebRtcLocalAudioTrackTest, DISABLED_MultipleAudioTracks) {
278  scoped_refptr<WebRtcLocalAudioTrackAdapter> adapter_1(
279      WebRtcLocalAudioTrackAdapter::Create(std::string(), NULL));
280  scoped_ptr<WebRtcLocalAudioTrack> track_1(
281      new WebRtcLocalAudioTrack(adapter_1.get(), capturer_, NULL));
282  track_1->Start();
283  EXPECT_TRUE(track_1->GetAudioAdapter()->enabled());
284  scoped_ptr<MockMediaStreamAudioSink> sink_1(new MockMediaStreamAudioSink());
285  const media::AudioParameters params = capturer_->source_audio_parameters();
286  base::WaitableEvent event_1(false, false);
287  EXPECT_CALL(*sink_1, FormatIsSet()).WillOnce(Return());
288  EXPECT_CALL(*sink_1,
289      CaptureData(0, 0, 0, _, false)).Times(AtLeast(1))
290      .WillRepeatedly(SignalEvent(&event_1));
291  EXPECT_EQ(sink_1->audio_params().frames_per_buffer(),
292            params.sample_rate() / 100);
293  track_1->AddSink(sink_1.get());
294  EXPECT_TRUE(event_1.TimedWait(TestTimeouts::tiny_timeout()));
295
296  scoped_refptr<WebRtcLocalAudioTrackAdapter> adapter_2(
297      WebRtcLocalAudioTrackAdapter::Create(std::string(), NULL));
298  scoped_ptr<WebRtcLocalAudioTrack> track_2(
299      new WebRtcLocalAudioTrack(adapter_2.get(), capturer_, NULL));
300  track_2->Start();
301  EXPECT_TRUE(track_2->GetAudioAdapter()->enabled());
302
303  // Verify both |sink_1| and |sink_2| get data.
304  event_1.Reset();
305  base::WaitableEvent event_2(false, false);
306
307  scoped_ptr<MockMediaStreamAudioSink> sink_2(new MockMediaStreamAudioSink());
308  EXPECT_CALL(*sink_2, FormatIsSet()).WillOnce(Return());
309  EXPECT_CALL(*sink_1, CaptureData(0, 0, 0, _, false)).Times(AtLeast(1))
310      .WillRepeatedly(SignalEvent(&event_1));
311  EXPECT_EQ(sink_1->audio_params().frames_per_buffer(),
312            params.sample_rate() / 100);
313  EXPECT_CALL(*sink_2, CaptureData(0, 0, 0, _, false)).Times(AtLeast(1))
314      .WillRepeatedly(SignalEvent(&event_2));
315  EXPECT_EQ(sink_2->audio_params().frames_per_buffer(),
316            params.sample_rate() / 100);
317  track_2->AddSink(sink_2.get());
318  EXPECT_TRUE(event_1.TimedWait(TestTimeouts::tiny_timeout()));
319  EXPECT_TRUE(event_2.TimedWait(TestTimeouts::tiny_timeout()));
320
321  track_1->RemoveSink(sink_1.get());
322  track_1->Stop();
323  track_1.reset();
324
325  EXPECT_CALL(*capturer_source_.get(), OnStop()).WillOnce(Return());
326  track_2->RemoveSink(sink_2.get());
327  track_2->Stop();
328  track_2.reset();
329}
330
331
332// Start one track and verify the capturer is correctly starting its source.
333// And it should be fine to not to call Stop() explicitly.
334TEST_F(WebRtcLocalAudioTrackTest, StartOneAudioTrack) {
335  scoped_refptr<WebRtcLocalAudioTrackAdapter> adapter(
336      WebRtcLocalAudioTrackAdapter::Create(std::string(), NULL));
337  scoped_ptr<WebRtcLocalAudioTrack> track(
338      new WebRtcLocalAudioTrack(adapter.get(), capturer_, NULL));
339  track->Start();
340
341  // When the track goes away, it will automatically stop the
342  // |capturer_source_|.
343  EXPECT_CALL(*capturer_source_.get(), OnStop());
344  track.reset();
345}
346
347// Start two tracks and verify the capturer is correctly starting its source.
348// When the last track connected to the capturer is stopped, the source is
349// stopped.
350TEST_F(WebRtcLocalAudioTrackTest, StartTwoAudioTracks) {
351  scoped_refptr<WebRtcLocalAudioTrackAdapter> adapter1(
352      WebRtcLocalAudioTrackAdapter::Create(std::string(), NULL));
353  scoped_ptr<WebRtcLocalAudioTrack> track1(
354      new WebRtcLocalAudioTrack(adapter1.get(), capturer_, NULL));
355  track1->Start();
356
357  scoped_refptr<WebRtcLocalAudioTrackAdapter> adapter2(
358        WebRtcLocalAudioTrackAdapter::Create(std::string(), NULL));
359  scoped_ptr<WebRtcLocalAudioTrack> track2(
360      new WebRtcLocalAudioTrack(adapter2.get(), capturer_, NULL));
361  track2->Start();
362
363  track1->Stop();
364  // When the last track is stopped, it will automatically stop the
365  // |capturer_source_|.
366  EXPECT_CALL(*capturer_source_.get(), OnStop());
367  track2->Stop();
368}
369
370// Start/Stop tracks and verify the capturer is correctly starting/stopping
371// its source.
372TEST_F(WebRtcLocalAudioTrackTest, StartAndStopAudioTracks) {
373  base::WaitableEvent event(false, false);
374  scoped_refptr<WebRtcLocalAudioTrackAdapter> adapter_1(
375      WebRtcLocalAudioTrackAdapter::Create(std::string(), NULL));
376  scoped_ptr<WebRtcLocalAudioTrack> track_1(
377      new WebRtcLocalAudioTrack(adapter_1.get(), capturer_, NULL));
378  track_1->Start();
379
380  // Verify the data flow by connecting the sink to |track_1|.
381  scoped_ptr<MockMediaStreamAudioSink> sink(new MockMediaStreamAudioSink());
382  event.Reset();
383  EXPECT_CALL(*sink, FormatIsSet()).WillOnce(SignalEvent(&event));
384  EXPECT_CALL(*sink, CaptureData(_, 0, 0, _, false))
385      .Times(AnyNumber()).WillRepeatedly(Return());
386  track_1->AddSink(sink.get());
387  EXPECT_TRUE(event.TimedWait(TestTimeouts::tiny_timeout()));
388
389  // Start the second audio track will not start the |capturer_source_|
390  // since it has been started.
391  EXPECT_CALL(*capturer_source_.get(), OnStart()).Times(0);
392  scoped_refptr<WebRtcLocalAudioTrackAdapter> adapter_2(
393      WebRtcLocalAudioTrackAdapter::Create(std::string(), NULL));
394  scoped_ptr<WebRtcLocalAudioTrack> track_2(
395      new WebRtcLocalAudioTrack(adapter_2.get(), capturer_, NULL));
396  track_2->Start();
397
398  // Stop the capturer will clear up the track lists in the capturer.
399  EXPECT_CALL(*capturer_source_.get(), OnStop());
400  capturer_->Stop();
401
402  // Adding a new track to the capturer.
403  track_2->AddSink(sink.get());
404  EXPECT_CALL(*sink, FormatIsSet()).Times(0);
405
406  // Stop the capturer again will not trigger stopping the source of the
407  // capturer again..
408  event.Reset();
409  EXPECT_CALL(*capturer_source_.get(), OnStop()).Times(0);
410  capturer_->Stop();
411}
412
413// Contains data races reported by tsan: crbug.com/404133
414#if defined(THREAD_SANITIZER)
415  #define DISABLE_ON_TSAN(function) DISABLED_##function
416#else
417  #define DISABLE_ON_TSAN(function) function
418#endif
419
420// Create a new capturer with new source, connect it to a new audio track.
421TEST_F(WebRtcLocalAudioTrackTest,
422       DISABLE_ON_TSAN(ConnectTracksToDifferentCapturers)) {
423  // Setup the first audio track and start it.
424  scoped_refptr<WebRtcLocalAudioTrackAdapter> adapter_1(
425      WebRtcLocalAudioTrackAdapter::Create(std::string(), NULL));
426  scoped_ptr<WebRtcLocalAudioTrack> track_1(
427      new WebRtcLocalAudioTrack(adapter_1.get(), capturer_, NULL));
428  track_1->Start();
429
430  // Verify the data flow by connecting the |sink_1| to |track_1|.
431  scoped_ptr<MockMediaStreamAudioSink> sink_1(new MockMediaStreamAudioSink());
432  EXPECT_CALL(*sink_1.get(), CaptureData(0, 0, 0, _, false))
433      .Times(AnyNumber()).WillRepeatedly(Return());
434  EXPECT_CALL(*sink_1.get(), FormatIsSet()).Times(AnyNumber());
435  track_1->AddSink(sink_1.get());
436
437  // Create a new capturer with new source with different audio format.
438  MockMediaConstraintFactory constraint_factory;
439  StreamDeviceInfo device(MEDIA_DEVICE_AUDIO_CAPTURE,
440                          std::string(), std::string());
441  scoped_refptr<WebRtcAudioCapturer> new_capturer(
442      WebRtcAudioCapturer::CreateCapturer(
443          -1, device, constraint_factory.CreateWebMediaConstraints(), NULL,
444          NULL));
445  scoped_refptr<MockCapturerSource> new_source(
446      new MockCapturerSource(new_capturer.get()));
447  EXPECT_CALL(*new_source.get(), OnInitialize(_, new_capturer.get(), -1));
448  EXPECT_CALL(*new_source.get(), SetAutomaticGainControl(true));
449  EXPECT_CALL(*new_source.get(), OnStart());
450
451  media::AudioParameters new_param(
452      media::AudioParameters::AUDIO_PCM_LOW_LATENCY,
453      media::CHANNEL_LAYOUT_MONO, 44100, 16, 441);
454  new_capturer->SetCapturerSourceForTesting(new_source, new_param);
455
456  // Setup the second audio track, connect it to the new capturer and start it.
457  scoped_refptr<WebRtcLocalAudioTrackAdapter> adapter_2(
458      WebRtcLocalAudioTrackAdapter::Create(std::string(), NULL));
459  scoped_ptr<WebRtcLocalAudioTrack> track_2(
460      new WebRtcLocalAudioTrack(adapter_2.get(), new_capturer, NULL));
461  track_2->Start();
462
463  // Verify the data flow by connecting the |sink_2| to |track_2|.
464  scoped_ptr<MockMediaStreamAudioSink> sink_2(new MockMediaStreamAudioSink());
465  base::WaitableEvent event(false, false);
466  EXPECT_CALL(*sink_2, CaptureData(0, 0, 0, _, false))
467      .Times(AnyNumber()).WillRepeatedly(Return());
468  EXPECT_CALL(*sink_2, FormatIsSet()).WillOnce(SignalEvent(&event));
469  track_2->AddSink(sink_2.get());
470  EXPECT_TRUE(event.TimedWait(TestTimeouts::tiny_timeout()));
471
472  // Stopping the new source will stop the second track.
473  event.Reset();
474  EXPECT_CALL(*new_source.get(), OnStop())
475      .Times(1).WillOnce(SignalEvent(&event));
476  new_capturer->Stop();
477  EXPECT_TRUE(event.TimedWait(TestTimeouts::tiny_timeout()));
478
479  // Stop the capturer of the first audio track.
480  EXPECT_CALL(*capturer_source_.get(), OnStop());
481  capturer_->Stop();
482}
483
484// Make sure a audio track can deliver packets with a buffer size smaller than
485// 10ms when it is not connected with a peer connection.
486TEST_F(WebRtcLocalAudioTrackTest, TrackWorkWithSmallBufferSize) {
487  // Setup a capturer which works with a buffer size smaller than 10ms.
488  media::AudioParameters params(media::AudioParameters::AUDIO_PCM_LOW_LATENCY,
489                                media::CHANNEL_LAYOUT_STEREO, 48000, 16, 128);
490
491  // Create a capturer with new source which works with the format above.
492  MockMediaConstraintFactory factory;
493  factory.DisableDefaultAudioConstraints();
494  scoped_refptr<WebRtcAudioCapturer> capturer(
495      WebRtcAudioCapturer::CreateCapturer(
496          -1,
497          StreamDeviceInfo(MEDIA_DEVICE_AUDIO_CAPTURE,
498                           "", "", params.sample_rate(),
499                           params.channel_layout(),
500                           params.frames_per_buffer()),
501          factory.CreateWebMediaConstraints(),
502          NULL, NULL));
503  scoped_refptr<MockCapturerSource> source(
504      new MockCapturerSource(capturer.get()));
505  EXPECT_CALL(*source.get(), OnInitialize(_, capturer.get(), -1));
506  EXPECT_CALL(*source.get(), SetAutomaticGainControl(true));
507  EXPECT_CALL(*source.get(), OnStart());
508  capturer->SetCapturerSourceForTesting(source, params);
509
510  // Setup a audio track, connect it to the capturer and start it.
511  scoped_refptr<WebRtcLocalAudioTrackAdapter> adapter(
512      WebRtcLocalAudioTrackAdapter::Create(std::string(), NULL));
513  scoped_ptr<WebRtcLocalAudioTrack> track(
514      new WebRtcLocalAudioTrack(adapter.get(), capturer, NULL));
515  track->Start();
516
517  // Verify the data flow by connecting the |sink| to |track|.
518  scoped_ptr<MockMediaStreamAudioSink> sink(new MockMediaStreamAudioSink());
519  base::WaitableEvent event(false, false);
520  EXPECT_CALL(*sink, FormatIsSet()).Times(1);
521  // Verify the sinks are getting the packets with an expecting buffer size.
522#if defined(OS_ANDROID)
523  const int expected_buffer_size = params.sample_rate() / 100;
524#else
525  const int expected_buffer_size = params.frames_per_buffer();
526#endif
527  EXPECT_CALL(*sink, CaptureData(
528      0, 0, 0, _, false))
529      .Times(AtLeast(1)).WillRepeatedly(SignalEvent(&event));
530  track->AddSink(sink.get());
531  EXPECT_TRUE(event.TimedWait(TestTimeouts::tiny_timeout()));
532  EXPECT_EQ(expected_buffer_size, sink->audio_params().frames_per_buffer());
533
534  // Stopping the new source will stop the second track.
535  EXPECT_CALL(*source.get(), OnStop()).Times(1);
536  capturer->Stop();
537
538  // Even though this test don't use |capturer_source_| it will be stopped
539  // during teardown of the test harness.
540  EXPECT_CALL(*capturer_source_.get(), OnStop());
541}
542
543}  // namespace content
544