Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(86)

Side by Side Diff: content/renderer/media/webrtc/processed_local_audio_source_unittest.cc

Issue 1834323002: MediaStream audio: Refactor 3 separate "glue" implementations into one. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Reworked unit tests around structural changes, and added exhaustive media_stream_audio_unittest.cc. Created 4 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2013 The Chromium Authors. All rights reserved. 1 // Copyright 2016 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "base/logging.h" 5 #include "base/logging.h"
6 #include "build/build_config.h" 6 #include "build/build_config.h"
7 #include "content/public/renderer/media_stream_audio_sink.h" 7 #include "content/public/renderer/media_stream_audio_sink.h"
8 #include "content/renderer/media/media_stream_audio_track.h"
9 #include "content/renderer/media/mock_audio_device_factory.h"
8 #include "content/renderer/media/mock_constraint_factory.h" 10 #include "content/renderer/media/mock_constraint_factory.h"
9 #include "content/renderer/media/webrtc/webrtc_local_audio_track_adapter.h" 11 #include "content/renderer/media/webrtc/mock_peer_connection_dependency_factory. h"
10 #include "content/renderer/media/webrtc_audio_capturer.h" 12 #include "content/renderer/media/webrtc/processed_local_audio_source.h"
11 #include "content/renderer/media/webrtc_local_audio_track.h"
12 #include "media/base/audio_bus.h" 13 #include "media/base/audio_bus.h"
13 #include "media/base/audio_parameters.h" 14 #include "media/base/audio_parameters.h"
14 #include "testing/gmock/include/gmock/gmock.h" 15 #include "testing/gmock/include/gmock/gmock.h"
15 #include "testing/gtest/include/gtest/gtest.h" 16 #include "testing/gtest/include/gtest/gtest.h"
16 #include "third_party/WebKit/public/platform/WebMediaConstraints.h" 17 #include "third_party/WebKit/public/platform/WebMediaConstraints.h"
18 #include "third_party/WebKit/public/web/WebHeap.h"
17 19
18 using ::testing::_; 20 using ::testing::_;
19 using ::testing::AtLeast; 21 using ::testing::AtLeast;
22 using ::testing::Invoke;
20 23
21 namespace content { 24 namespace content {
22 25
23 namespace { 26 namespace {
24 27
25 class MockCapturerSource : public media::AudioCapturerSource { 28 #if defined(OS_ANDROID)
26 public: 29 constexpr int kBufferSize = 960; // Android works with a 20ms buffer size.
o1ka 2016/05/04 08:49:24 The original comment is "bigger than 20ms" (and th
miu 2016/05/04 22:10:09 Done. Made the audio parameters more explicit with
o1ka 2016/05/06 16:53:57 Thanks!
27 MockCapturerSource() {} 30 #else
28 MOCK_METHOD3(Initialize, void(const media::AudioParameters& params, 31 constexpr int kBufferSize = 128;
29 CaptureCallback* callback, 32 #endif
30 int session_id));
31 MOCK_METHOD0(Start, void());
32 MOCK_METHOD0(Stop, void());
33 MOCK_METHOD1(SetVolume, void(double volume));
34 MOCK_METHOD1(SetAutomaticGainControl, void(bool enable));
35
36 protected:
37 ~MockCapturerSource() override {}
38 };
39 33
40 class MockMediaStreamAudioSink : public MediaStreamAudioSink { 34 class MockMediaStreamAudioSink : public MediaStreamAudioSink {
41 public: 35 public:
42 MockMediaStreamAudioSink() {} 36 MockMediaStreamAudioSink() {}
43 ~MockMediaStreamAudioSink() override {} 37 ~MockMediaStreamAudioSink() override {}
38
44 void OnData(const media::AudioBus& audio_bus, 39 void OnData(const media::AudioBus& audio_bus,
45 base::TimeTicks estimated_capture_time) override { 40 base::TimeTicks estimated_capture_time) override {
46 EXPECT_EQ(audio_bus.channels(), params_.channels()); 41 EXPECT_EQ(audio_bus.channels(), params_.channels());
47 EXPECT_EQ(audio_bus.frames(), params_.frames_per_buffer()); 42 EXPECT_EQ(audio_bus.frames(), params_.frames_per_buffer());
48 EXPECT_FALSE(estimated_capture_time.is_null()); 43 EXPECT_FALSE(estimated_capture_time.is_null());
49 OnDataCallback(); 44 OnDataCallback();
50 } 45 }
51 MOCK_METHOD0(OnDataCallback, void()); 46 MOCK_METHOD0(OnDataCallback, void());
47
52 void OnSetFormat(const media::AudioParameters& params) override { 48 void OnSetFormat(const media::AudioParameters& params) override {
53 params_ = params; 49 params_ = params;
54 FormatIsSet(); 50 FormatIsSet(params_);
55 } 51 }
56 MOCK_METHOD0(FormatIsSet, void()); 52 MOCK_METHOD1(FormatIsSet, void(const media::AudioParameters& params));
57 53
58 private: 54 private:
59 media::AudioParameters params_; 55 media::AudioParameters params_;
60 }; 56 };
61 57
62 } // namespace 58 } // namespace
63 59
64 class WebRtcAudioCapturerTest : public testing::Test { 60 class ProcessedLocalAudioSourceTest : public testing::Test {
65 protected: 61 protected:
66 WebRtcAudioCapturerTest() 62 ProcessedLocalAudioSourceTest()
67 #if defined(OS_ANDROID)
68 : params_(media::AudioParameters::AUDIO_PCM_LOW_LATENCY, 63 : params_(media::AudioParameters::AUDIO_PCM_LOW_LATENCY,
69 media::CHANNEL_LAYOUT_STEREO, 48000, 16, 960) { 64 media::CHANNEL_LAYOUT_STEREO, 48000, 16, kBufferSize) {}
70 // Android works with a buffer size bigger than 20ms. 65
71 #else 66 ~ProcessedLocalAudioSourceTest() override {}
72 : params_(media::AudioParameters::AUDIO_PCM_LOW_LATENCY, 67
73 media::CHANNEL_LAYOUT_STEREO, 48000, 16, 128) { 68 void SetUp() override {
74 #endif 69 blink_audio_source_.initialize(blink::WebString::fromUTF8("audio_label"),
70 blink::WebMediaStreamSource::TypeAudio,
71 blink::WebString::fromUTF8("audio_track"),
72 false /* remote */, true /* readonly */);
73 blink_audio_track_.initialize(blink_audio_source_.id(),
74 blink_audio_source_);
75 } 75 }
76 76
77 void VerifyAudioParams(const blink::WebMediaConstraints& constraints, 77 void TearDown() override {
78 bool need_audio_processing) { 78 blink_audio_track_.reset();
79 const std::unique_ptr<WebRtcAudioCapturer> capturer = 79 blink_audio_source_.reset();
80 WebRtcAudioCapturer::CreateCapturer( 80 blink::WebHeap::collectAllGarbageForTesting();
81 -1, StreamDeviceInfo(
82 MEDIA_DEVICE_AUDIO_CAPTURE, "", "", params_.sample_rate(),
83 params_.channel_layout(), params_.frames_per_buffer()),
84 constraints, nullptr, nullptr);
85 const scoped_refptr<MockCapturerSource> capturer_source(
86 new MockCapturerSource());
87 EXPECT_CALL(*capturer_source.get(), Initialize(_, capturer.get(), -1));
88 EXPECT_CALL(*capturer_source.get(), SetAutomaticGainControl(true));
89 EXPECT_CALL(*capturer_source.get(), Start());
90 capturer->SetCapturerSource(capturer_source, params_);
91
92 scoped_refptr<WebRtcLocalAudioTrackAdapter> adapter(
93 WebRtcLocalAudioTrackAdapter::Create(std::string(), NULL));
94 const std::unique_ptr<WebRtcLocalAudioTrack> track(
95 new WebRtcLocalAudioTrack(adapter.get()));
96 capturer->AddTrack(track.get());
97
98 // Connect a mock sink to the track.
99 std::unique_ptr<MockMediaStreamAudioSink> sink(
100 new MockMediaStreamAudioSink());
101 track->AddSink(sink.get());
102
103 int delay_ms = 65;
104 bool key_pressed = true;
105 double volume = 0.9;
106
107 std::unique_ptr<media::AudioBus> audio_bus =
108 media::AudioBus::Create(params_);
109 audio_bus->Zero();
110
111 media::AudioCapturerSource::CaptureCallback* callback =
112 static_cast<media::AudioCapturerSource::CaptureCallback*>(
113 capturer.get());
114
115 // Verify the sink is getting the correct values.
116 EXPECT_CALL(*sink, FormatIsSet());
117 EXPECT_CALL(*sink, OnDataCallback()).Times(AtLeast(1));
118 callback->Capture(audio_bus.get(), delay_ms, volume, key_pressed);
119
120 track->RemoveSink(sink.get());
121 EXPECT_CALL(*capturer_source.get(), Stop());
122 capturer->Stop();
123 } 81 }
124 82
125 media::AudioParameters params_; 83 void CreateProcessedLocalAudioSource(
84 const blink::WebMediaConstraints& constraints) {
85 ProcessedLocalAudioSource* const source =
86 new ProcessedLocalAudioSource(
87 -1 /* consumer_render_frame_id is N/A for non-browser tests */,
88 StreamDeviceInfo(MEDIA_DEVICE_AUDIO_CAPTURE, "Mock audio device",
89 "mock_audio_device_id", params_.sample_rate(),
90 params_.channel_layout(),
91 params_.frames_per_buffer()),
92 &mock_dependency_factory_);
93 source->SetAllowInvalidRenderFrameIdForTesting(true);
94 source->SetSourceConstraints(constraints);
95 blink_audio_source_.setExtraData(source); // Takes ownership.
96 }
97
98 void CheckAudioParametersMatch(const media::AudioParameters& params) {
99 EXPECT_TRUE(params_.Equals(params));
100 }
101
102 MockAudioDeviceFactory* mock_audio_device_factory() {
103 return &mock_audio_device_factory_;
104 }
105
106 media::AudioCapturerSource::CaptureCallback* capture_source_callback() const {
107 return static_cast<media::AudioCapturerSource::CaptureCallback*>(
108 ProcessedLocalAudioSource::From(audio_source()));
109 }
110
111 MediaStreamAudioSource* audio_source() const {
112 return MediaStreamAudioSource::From(blink_audio_source_);
113 }
114
115 const blink::WebMediaStreamTrack& blink_audio_track() {
116 return blink_audio_track_;
117 }
118
119 private:
120 MockAudioDeviceFactory mock_audio_device_factory_;
121 const media::AudioParameters params_;
122 MockPeerConnectionDependencyFactory mock_dependency_factory_;
123 blink::WebMediaStreamSource blink_audio_source_;
124 blink::WebMediaStreamTrack blink_audio_track_;
126 }; 125 };
127 126
128 TEST_F(WebRtcAudioCapturerTest, VerifyAudioParamsWithAudioProcessing) { 127 // Tests a basic end-to-end start-up, track+sink connections, audio flow, and
129 // Turn off the default constraints to verify that the sink will get packets 128 // shut-down. The unit tests in media_stream_audio_unittest.cc provide more
130 // with a buffer size smaller than 10ms. 129 // comprehensive testing of the object graph connections and multi-threading
130 // concerns.
131 TEST_F(ProcessedLocalAudioSourceTest, VerifyAudioFlowWithoutAudioProcessing) {
132 // Turn off the default constraints so the sink will get audio in chunks of
133 // the native buffer size.
131 MockConstraintFactory constraint_factory; 134 MockConstraintFactory constraint_factory;
132 constraint_factory.DisableDefaultAudioConstraints(); 135 constraint_factory.DisableDefaultAudioConstraints();
133 VerifyAudioParams(constraint_factory.CreateWebMediaConstraints(), false); 136
137 CreateProcessedLocalAudioSource(
138 constraint_factory.CreateWebMediaConstraints());
139
140 // Connect the track, and expect the MockCapturerSource to be initialized and
141 // started by ProcessedLocalAudioSource.
142 EXPECT_CALL(*mock_audio_device_factory()->mock_capturer_source(),
143 Initialize(_, capture_source_callback(), -1));
144 EXPECT_CALL(*mock_audio_device_factory()->mock_capturer_source(),
145 SetAutomaticGainControl(true));
146 EXPECT_CALL(*mock_audio_device_factory()->mock_capturer_source(), Start());
147 ASSERT_TRUE(audio_source()->ConnectToTrack(blink_audio_track()));
148 CheckAudioParametersMatch(audio_source()->GetAudioParameters());
149
150 // Connect a sink to the track.
151 std::unique_ptr<MockMediaStreamAudioSink> sink(
152 new MockMediaStreamAudioSink());
153 using ThisTest =
154 ProcessedLocalAudioSourceTest_VerifyAudioFlowWithoutAudioProcessing_Test;
155 EXPECT_CALL(*sink, FormatIsSet(_))
156 .WillOnce(Invoke(this, &ThisTest::CheckAudioParametersMatch));
157 MediaStreamAudioTrack::From(blink_audio_track())->AddSink(sink.get());
158
159 // Feed audio data into the ProcessedLocalAudioSource and expect it to reach
160 // the sink.
161 int delay_ms = 65;
162 bool key_pressed = true;
163 double volume = 0.9;
164 std::unique_ptr<media::AudioBus> audio_bus =
165 media::AudioBus::Create(audio_source()->GetAudioParameters());
166 audio_bus->Zero();
167 EXPECT_CALL(*sink, OnDataCallback()).Times(AtLeast(1));
168 capture_source_callback()->Capture(audio_bus.get(), delay_ms, volume,
169 key_pressed);
170
171 // Expect the ProcessedLocalAudioSource to auto-stop the MockCapturerSource
172 // when the track is stopped.
173 EXPECT_CALL(*mock_audio_device_factory()->mock_capturer_source(), Stop());
174 MediaStreamAudioTrack::From(blink_audio_track())->Stop();
134 } 175 }
135 176
136 TEST_F(WebRtcAudioCapturerTest, FailToCreateCapturerWithWrongConstraints) { 177 // Tests that the source is not started when invalid audio constraints are
178 // present.
179 TEST_F(ProcessedLocalAudioSourceTest, FailToStartWithWrongConstraints) {
137 MockConstraintFactory constraint_factory; 180 MockConstraintFactory constraint_factory;
138 const std::string dummy_constraint = "dummy"; 181 const std::string dummy_constraint = "dummy";
139 // Set a non-audio constraint. 182 // Set a non-audio constraint.
140 constraint_factory.basic().width.setExact(240); 183 constraint_factory.basic().width.setExact(240);
141 184
142 std::unique_ptr<WebRtcAudioCapturer> capturer( 185 CreateProcessedLocalAudioSource(
143 WebRtcAudioCapturer::CreateCapturer( 186 constraint_factory.CreateWebMediaConstraints());
144 0, StreamDeviceInfo(MEDIA_DEVICE_AUDIO_CAPTURE, "", "", 187
145 params_.sample_rate(), params_.channel_layout(), 188 // Expect the MockCapturerSource is never initialized/started and the
146 params_.frames_per_buffer()), 189 // ConnectToTrack() operation fails due to the invalid constraint.
147 constraint_factory.CreateWebMediaConstraints(), NULL, NULL)); 190 EXPECT_CALL(*mock_audio_device_factory()->mock_capturer_source(),
148 EXPECT_TRUE(capturer.get() == NULL); 191 Initialize(_, capture_source_callback(), -1))
192 .Times(0);
193 EXPECT_CALL(*mock_audio_device_factory()->mock_capturer_source(),
194 SetAutomaticGainControl(true)).Times(0);
195 EXPECT_CALL(*mock_audio_device_factory()->mock_capturer_source(), Start())
196 .Times(0);
197 EXPECT_FALSE(audio_source()->ConnectToTrack(blink_audio_track()));
198
199 // Even though ConnectToTrack() failed, there should still have been a new
200 // MediaStreamAudioTrack instance created, owned by the
201 // blink::WebMediaStreamTrack.
202 EXPECT_TRUE(MediaStreamAudioTrack::From(blink_audio_track()));
149 } 203 }
150 204
205 // TODO(miu): There's a lot of logic in ProcessedLocalAudioSource around
206 // constraints processing and validation that should have unit testing.
151 207
152 } // namespace content 208 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698