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/logging.h"
6#include "base/strings/utf_string_conversions.h"
7#include "content/renderer/media/mock_media_constraint_factory.h"
8#include "content/renderer/media/webrtc/webrtc_local_audio_track_adapter.h"
9#include "content/renderer/media/webrtc_audio_capturer.h"
10#include "content/renderer/media/webrtc_local_audio_source_provider.h"
11#include "content/renderer/media/webrtc_local_audio_track.h"
12#include "media/audio/audio_parameters.h"
13#include "media/base/audio_bus.h"
14#include "testing/gtest/include/gtest/gtest.h"
15#include "third_party/WebKit/public/platform/WebMediaStreamTrack.h"
16#include "third_party/WebKit/public/web/WebHeap.h"
17
18namespace content {
19
20class WebRtcLocalAudioSourceProviderTest : public testing::Test {
21 protected:
22  virtual void SetUp() OVERRIDE {
23    source_params_.Reset(media::AudioParameters::AUDIO_PCM_LOW_LATENCY,
24                         media::CHANNEL_LAYOUT_MONO, 1, 48000, 16, 480);
25    sink_params_.Reset(
26        media::AudioParameters::AUDIO_PCM_LOW_LATENCY,
27        media::CHANNEL_LAYOUT_STEREO, 2, 44100, 16,
28        WebRtcLocalAudioSourceProvider::kWebAudioRenderBufferSize);
29    const int length =
30        source_params_.frames_per_buffer() * source_params_.channels();
31    source_data_.reset(new int16[length]);
32    sink_bus_ = media::AudioBus::Create(sink_params_);
33    MockMediaConstraintFactory constraint_factory;
34      scoped_refptr<WebRtcAudioCapturer> capturer(
35        WebRtcAudioCapturer::CreateCapturer(
36            -1, StreamDeviceInfo(),
37            constraint_factory.CreateWebMediaConstraints(), NULL, NULL));
38    scoped_refptr<WebRtcLocalAudioTrackAdapter> adapter(
39        WebRtcLocalAudioTrackAdapter::Create(std::string(), NULL));
40    scoped_ptr<WebRtcLocalAudioTrack> native_track(
41        new WebRtcLocalAudioTrack(adapter.get(), capturer, NULL));
42    blink::WebMediaStreamSource audio_source;
43    audio_source.initialize(base::UTF8ToUTF16("dummy_source_id"),
44                            blink::WebMediaStreamSource::TypeAudio,
45                            base::UTF8ToUTF16("dummy_source_name"));
46    blink_track_.initialize(blink::WebString::fromUTF8("audio_track"),
47                            audio_source);
48    blink_track_.setExtraData(native_track.release());
49    source_provider_.reset(new WebRtcLocalAudioSourceProvider(blink_track_));
50    source_provider_->SetSinkParamsForTesting(sink_params_);
51    source_provider_->OnSetFormat(source_params_);
52  }
53
54  virtual void TearDown() OVERRIDE {
55    source_provider_.reset();
56    blink_track_.reset();
57    blink::WebHeap::collectAllGarbageForTesting();
58  }
59
60  media::AudioParameters source_params_;
61  scoped_ptr<int16[]> source_data_;
62  media::AudioParameters sink_params_;
63  scoped_ptr<media::AudioBus> sink_bus_;
64  blink::WebMediaStreamTrack blink_track_;
65  scoped_ptr<WebRtcLocalAudioSourceProvider> source_provider_;
66};
67
68TEST_F(WebRtcLocalAudioSourceProviderTest, VerifyDataFlow) {
69  // Point the WebVector into memory owned by |sink_bus_|.
70  blink::WebVector<float*> audio_data(
71      static_cast<size_t>(sink_bus_->channels()));
72  for (size_t i = 0; i < audio_data.size(); ++i)
73    audio_data[i] = sink_bus_->channel(i);
74
75  // Enable the |source_provider_| by asking for data. This will inject
76  // source_params_.frames_per_buffer() of zero into the resampler since there
77  // no available data in the FIFO.
78  source_provider_->provideInput(audio_data, sink_params_.frames_per_buffer());
79  EXPECT_TRUE(sink_bus_->channel(0)[0] == 0);
80
81  // Set the value of source data to be 1.
82  const int length =
83      source_params_.frames_per_buffer() * source_params_.channels();
84  std::fill(source_data_.get(), source_data_.get() + length, 1);
85
86  // Deliver data to |source_provider_|.
87  source_provider_->OnData(source_data_.get(),
88                           source_params_.sample_rate(),
89                           source_params_.channels(),
90                           source_params_.frames_per_buffer());
91
92  // Consume the first packet in the resampler, which contains only zero.
93  // And the consumption of the data will trigger pulling the real packet from
94  // the source provider FIFO into the resampler.
95  // Note that we need to count in the provideInput() call a few lines above.
96  for (int i = sink_params_.frames_per_buffer();
97       i < source_params_.frames_per_buffer();
98       i += sink_params_.frames_per_buffer()) {
99    sink_bus_->Zero();
100    source_provider_->provideInput(audio_data,
101                                   sink_params_.frames_per_buffer());
102    EXPECT_DOUBLE_EQ(0.0, sink_bus_->channel(0)[0]);
103    EXPECT_DOUBLE_EQ(0.0, sink_bus_->channel(1)[0]);
104  }
105
106  // Prepare the second packet for featching.
107  source_provider_->OnData(source_data_.get(),
108                           source_params_.sample_rate(),
109                           source_params_.channels(),
110                           source_params_.frames_per_buffer());
111
112  // Verify the packets.
113  for (int i = 0; i < source_params_.frames_per_buffer();
114       i += sink_params_.frames_per_buffer()) {
115    sink_bus_->Zero();
116    source_provider_->provideInput(audio_data,
117                                   sink_params_.frames_per_buffer());
118    EXPECT_GT(sink_bus_->channel(0)[0], 0);
119    EXPECT_GT(sink_bus_->channel(1)[0], 0);
120    EXPECT_DOUBLE_EQ(sink_bus_->channel(0)[0], sink_bus_->channel(1)[0]);
121  }
122}
123
124TEST_F(WebRtcLocalAudioSourceProviderTest,
125       DeleteSourceProviderBeforeStoppingTrack) {
126  source_provider_.reset();
127
128  // Stop the audio track.
129  WebRtcLocalAudioTrack* native_track = static_cast<WebRtcLocalAudioTrack*>(
130      MediaStreamTrack::GetTrack(blink_track_));
131  native_track->Stop();
132}
133
134TEST_F(WebRtcLocalAudioSourceProviderTest,
135       StopTrackBeforeDeletingSourceProvider) {
136  // Stop the audio track.
137  WebRtcLocalAudioTrack* native_track = static_cast<WebRtcLocalAudioTrack*>(
138      MediaStreamTrack::GetTrack(blink_track_));
139  native_track->Stop();
140
141  // Delete the source provider.
142  source_provider_.reset();
143}
144
145}  // namespace content
146