| OLD | NEW |
| 1 // Copyright 2013 The Chromium Authors. All rights reserved. | 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 | 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/synchronization/waitable_event.h" | 5 #include "base/synchronization/waitable_event.h" |
| 6 #include "base/test/test_timeouts.h" | 6 #include "base/test/test_timeouts.h" |
| 7 #include "content/renderer/media/webrtc_audio_capturer.h" | 7 #include "content/renderer/media/webrtc_audio_capturer.h" |
| 8 #include "content/renderer/media/webrtc_local_audio_track.h" | 8 #include "content/renderer/media/webrtc_local_audio_track.h" |
| 9 #include "media/audio/audio_parameters.h" | 9 #include "media/audio/audio_parameters.h" |
| 10 #include "media/base/audio_bus.h" | 10 #include "media/base/audio_bus.h" |
| 11 #include "media/base/audio_capturer_source.h" | 11 #include "media/base/audio_capturer_source.h" |
| 12 #include "testing/gmock/include/gmock/gmock.h" | 12 #include "testing/gmock/include/gmock/gmock.h" |
| 13 #include "testing/gtest/include/gtest/gtest.h" | 13 #include "testing/gtest/include/gtest/gtest.h" |
| 14 | 14 |
| 15 using ::testing::_; | 15 using ::testing::_; |
| 16 using ::testing::AnyNumber; |
| 16 using ::testing::AtLeast; | 17 using ::testing::AtLeast; |
| 17 using ::testing::Return; | 18 using ::testing::Return; |
| 18 | 19 |
| 19 namespace content { | 20 namespace content { |
| 20 | 21 |
| 21 namespace { | 22 namespace { |
| 22 | 23 |
| 23 ACTION_P(SignalEvent, event) { | 24 ACTION_P(SignalEvent, event) { |
| 24 event->Signal(); | 25 event->Signal(); |
| 25 } | 26 } |
| (...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 108 protected: | 109 protected: |
| 109 virtual void SetUp() OVERRIDE { | 110 virtual void SetUp() OVERRIDE { |
| 110 capturer_ = WebRtcAudioCapturer::CreateCapturer(); | 111 capturer_ = WebRtcAudioCapturer::CreateCapturer(); |
| 111 capturer_source_ = new MockCapturerSource(); | 112 capturer_source_ = new MockCapturerSource(); |
| 112 EXPECT_CALL(*capturer_source_.get(), Initialize(_, capturer_.get(), 0)) | 113 EXPECT_CALL(*capturer_source_.get(), Initialize(_, capturer_.get(), 0)) |
| 113 .WillOnce(Return()); | 114 .WillOnce(Return()); |
| 114 capturer_->SetCapturerSource(capturer_source_, | 115 capturer_->SetCapturerSource(capturer_source_, |
| 115 media::CHANNEL_LAYOUT_STEREO, | 116 media::CHANNEL_LAYOUT_STEREO, |
| 116 48000); | 117 48000); |
| 117 | 118 |
| 118 EXPECT_CALL(*capturer_source_.get(), Start()).WillOnce(Return()); | |
| 119 EXPECT_CALL(*capturer_source_.get(), SetAutomaticGainControl(false)) | 119 EXPECT_CALL(*capturer_source_.get(), SetAutomaticGainControl(false)) |
| 120 .WillOnce(Return()); | 120 .WillOnce(Return()); |
| 121 capturer_->Start(); | |
| 122 audio_thread_.reset(new FakeAudioThread(capturer_)); | 121 audio_thread_.reset(new FakeAudioThread(capturer_)); |
| 123 audio_thread_->Start(); | 122 audio_thread_->Start(); |
| 124 } | 123 } |
| 125 | 124 |
| 126 virtual void TearDown() { | 125 virtual void TearDown() { |
| 127 audio_thread_->Stop(); | 126 audio_thread_->Stop(); |
| 128 audio_thread_.reset(); | 127 audio_thread_.reset(); |
| 129 EXPECT_CALL(*capturer_source_.get(), Stop()).WillOnce(Return()); | |
| 130 capturer_->Stop(); | |
| 131 } | 128 } |
| 132 | 129 |
| 133 scoped_refptr<MockCapturerSource> capturer_source_; | 130 scoped_refptr<MockCapturerSource> capturer_source_; |
| 134 scoped_refptr<WebRtcAudioCapturer> capturer_; | 131 scoped_refptr<WebRtcAudioCapturer> capturer_; |
| 135 scoped_ptr<FakeAudioThread> audio_thread_; | 132 scoped_ptr<FakeAudioThread> audio_thread_; |
| 136 }; | 133 }; |
| 137 | 134 |
| 138 // Creates a capturer and audio track, fakes its audio thread, and | 135 // Creates a capturer and audio track, fakes its audio thread, and |
| 139 // connect/disconnect the sink to the audio track on the fly, the sink should | 136 // connect/disconnect the sink to the audio track on the fly, the sink should |
| 140 // get data callback when the track is connected to the capturer but not when | 137 // get data callback when the track is connected to the capturer but not when |
| 141 // the track is disconnected from the capturer. | 138 // the track is disconnected from the capturer. |
| 142 TEST_F(WebRtcLocalAudioTrackTest, ConnectAndDisconnectOneSink) { | 139 TEST_F(WebRtcLocalAudioTrackTest, ConnectAndDisconnectOneSink) { |
| 140 EXPECT_CALL(*capturer_source_.get(), Start()).WillOnce(Return()); |
| 143 scoped_refptr<WebRtcLocalAudioTrack> track = | 141 scoped_refptr<WebRtcLocalAudioTrack> track = |
| 144 WebRtcLocalAudioTrack::Create(std::string(), capturer_, NULL); | 142 WebRtcLocalAudioTrack::Create(std::string(), capturer_, NULL); |
| 143 track->Start(); |
| 145 EXPECT_TRUE(track->enabled()); | 144 EXPECT_TRUE(track->enabled()); |
| 146 scoped_ptr<MockWebRtcAudioCapturerSink> sink( | 145 scoped_ptr<MockWebRtcAudioCapturerSink> sink( |
| 147 new MockWebRtcAudioCapturerSink()); | 146 new MockWebRtcAudioCapturerSink()); |
| 148 const media::AudioParameters params = capturer_->audio_parameters(); | 147 const media::AudioParameters params = capturer_->audio_parameters(); |
| 149 base::WaitableEvent event(false, false); | 148 base::WaitableEvent event(false, false); |
| 150 EXPECT_CALL(*sink, SetCaptureFormat(_)).WillOnce(Return()); | 149 EXPECT_CALL(*sink, SetCaptureFormat(_)).WillOnce(Return()); |
| 151 EXPECT_CALL(*sink, CaptureData( | 150 EXPECT_CALL(*sink, CaptureData( |
| 152 _, params.channels(), params.frames_per_buffer(), 0, 0)) | 151 _, params.channels(), params.frames_per_buffer(), 0, 0)) |
| 153 .Times(AtLeast(1)).WillRepeatedly(SignalEvent(&event)); | 152 .Times(AtLeast(1)).WillRepeatedly(SignalEvent(&event)); |
| 154 track->AddSink(sink.get()); | 153 track->AddSink(sink.get()); |
| 155 | 154 |
| 156 EXPECT_TRUE(event.TimedWait(TestTimeouts::tiny_timeout())); | 155 EXPECT_TRUE(event.TimedWait(TestTimeouts::tiny_timeout())); |
| 157 track->RemoveSink(sink.get()); | 156 track->RemoveSink(sink.get()); |
| 157 |
| 158 EXPECT_CALL(*capturer_source_.get(), Stop()).WillOnce(Return()); |
| 159 track->Stop(); |
| 158 track = NULL; | 160 track = NULL; |
| 159 } | 161 } |
| 160 | 162 |
| 161 // The same setup as ConnectAndDisconnectOneSink, but enable and disable the | 163 // The same setup as ConnectAndDisconnectOneSink, but enable and disable the |
| 162 // audio track on the fly. When the audio track is disabled, there is no data | 164 // audio track on the fly. When the audio track is disabled, there is no data |
| 163 // callback to the sink; when the audio track is enabled, there comes data | 165 // callback to the sink; when the audio track is enabled, there comes data |
| 164 // callback. | 166 // callback. |
| 165 // TODO(xians): Enable this test after resolving the racing issue that TSAN | 167 // TODO(xians): Enable this test after resolving the racing issue that TSAN |
| 166 // reports on MediaStreamTrack::enabled(); | 168 // reports on MediaStreamTrack::enabled(); |
| 167 TEST_F(WebRtcLocalAudioTrackTest, DISABLED_DisableEnableAudioTrack) { | 169 TEST_F(WebRtcLocalAudioTrackTest, DISABLED_DisableEnableAudioTrack) { |
| 170 EXPECT_CALL(*capturer_source_.get(), Start()).WillOnce(Return()); |
| 168 scoped_refptr<WebRtcLocalAudioTrack> track = | 171 scoped_refptr<WebRtcLocalAudioTrack> track = |
| 169 WebRtcLocalAudioTrack::Create(std::string(), capturer_, NULL); | 172 WebRtcLocalAudioTrack::Create(std::string(), capturer_, NULL); |
| 173 track->Start(); |
| 170 EXPECT_TRUE(track->enabled()); | 174 EXPECT_TRUE(track->enabled()); |
| 171 EXPECT_TRUE(track->set_enabled(false)); | 175 EXPECT_TRUE(track->set_enabled(false)); |
| 172 scoped_ptr<MockWebRtcAudioCapturerSink> sink( | 176 scoped_ptr<MockWebRtcAudioCapturerSink> sink( |
| 173 new MockWebRtcAudioCapturerSink()); | 177 new MockWebRtcAudioCapturerSink()); |
| 174 const media::AudioParameters params = capturer_->audio_parameters(); | 178 const media::AudioParameters params = capturer_->audio_parameters(); |
| 175 base::WaitableEvent event(false, false); | 179 base::WaitableEvent event(false, false); |
| 176 EXPECT_CALL(*sink, SetCaptureFormat(_)).WillOnce(Return()); | 180 EXPECT_CALL(*sink, SetCaptureFormat(_)).WillOnce(Return()); |
| 177 EXPECT_CALL(*sink, CaptureData( | 181 EXPECT_CALL(*sink, CaptureData( |
| 178 _, params.channels(), params.frames_per_buffer(), 0, 0)) | 182 _, params.channels(), params.frames_per_buffer(), 0, 0)) |
| 179 .Times(0); | 183 .Times(0); |
| 180 track->AddSink(sink.get()); | 184 track->AddSink(sink.get()); |
| 181 EXPECT_FALSE(event.TimedWait(TestTimeouts::tiny_timeout())); | 185 EXPECT_FALSE(event.TimedWait(TestTimeouts::tiny_timeout())); |
| 182 | 186 |
| 183 event.Reset(); | 187 event.Reset(); |
| 184 EXPECT_CALL(*sink, CaptureData( | 188 EXPECT_CALL(*sink, CaptureData( |
| 185 _, params.channels(), params.frames_per_buffer(), 0, 0)) | 189 _, params.channels(), params.frames_per_buffer(), 0, 0)) |
| 186 .Times(AtLeast(1)).WillRepeatedly(SignalEvent(&event)); | 190 .Times(AtLeast(1)).WillRepeatedly(SignalEvent(&event)); |
| 187 EXPECT_TRUE(track->set_enabled(true)); | 191 EXPECT_TRUE(track->set_enabled(true)); |
| 188 EXPECT_TRUE(event.TimedWait(TestTimeouts::tiny_timeout())); | 192 EXPECT_TRUE(event.TimedWait(TestTimeouts::tiny_timeout())); |
| 189 track->RemoveSink(sink.get()); | 193 track->RemoveSink(sink.get()); |
| 194 |
| 195 EXPECT_CALL(*capturer_source_.get(), Stop()).WillOnce(Return()); |
| 196 track->Stop(); |
| 190 track = NULL; | 197 track = NULL; |
| 191 } | 198 } |
| 192 | 199 |
| 193 // Create multiple audio tracks and enable/disable them, verify that the audio | 200 // Create multiple audio tracks and enable/disable them, verify that the audio |
| 194 // callbacks appear/disappear. | 201 // callbacks appear/disappear. |
| 195 // TODO(xians): Enable the test after the racing problem is resolved. | 202 // TODO(xians): Enable the test after the racing problem is resolved. |
| 196 TEST_F(WebRtcLocalAudioTrackTest, DISABLED_MultipleAudioTracks) { | 203 TEST_F(WebRtcLocalAudioTrackTest, DISABLED_MultipleAudioTracks) { |
| 204 EXPECT_CALL(*capturer_source_.get(), Start()).WillOnce(Return()); |
| 197 scoped_refptr<WebRtcLocalAudioTrack> track_1 = | 205 scoped_refptr<WebRtcLocalAudioTrack> track_1 = |
| 198 WebRtcLocalAudioTrack::Create(std::string(), capturer_, NULL); | 206 WebRtcLocalAudioTrack::Create(std::string(), capturer_, NULL); |
| 207 track_1->Start(); |
| 199 EXPECT_TRUE(track_1->enabled()); | 208 EXPECT_TRUE(track_1->enabled()); |
| 200 scoped_ptr<MockWebRtcAudioCapturerSink> sink_1( | 209 scoped_ptr<MockWebRtcAudioCapturerSink> sink_1( |
| 201 new MockWebRtcAudioCapturerSink()); | 210 new MockWebRtcAudioCapturerSink()); |
| 202 const media::AudioParameters params = capturer_->audio_parameters(); | 211 const media::AudioParameters params = capturer_->audio_parameters(); |
| 203 base::WaitableEvent event_1(false, false); | 212 base::WaitableEvent event_1(false, false); |
| 204 EXPECT_CALL(*sink_1, SetCaptureFormat(_)).WillOnce(Return()); | 213 EXPECT_CALL(*sink_1, SetCaptureFormat(_)).WillOnce(Return()); |
| 205 EXPECT_CALL(*sink_1, CaptureData( | 214 EXPECT_CALL(*sink_1, CaptureData( |
| 206 _, params.channels(), params.frames_per_buffer(), 0, 0)) | 215 _, params.channels(), params.frames_per_buffer(), 0, 0)) |
| 207 .Times(AtLeast(1)).WillRepeatedly(SignalEvent(&event_1)); | 216 .Times(AtLeast(1)).WillRepeatedly(SignalEvent(&event_1)); |
| 208 track_1->AddSink(sink_1.get()); | 217 track_1->AddSink(sink_1.get()); |
| 209 | 218 |
| 210 scoped_refptr<WebRtcLocalAudioTrack> track_2 = | 219 scoped_refptr<WebRtcLocalAudioTrack> track_2 = |
| 211 WebRtcLocalAudioTrack::Create(std::string(), capturer_, NULL); | 220 WebRtcLocalAudioTrack::Create(std::string(), capturer_, NULL); |
| 221 track_2->Start(); |
| 212 EXPECT_TRUE(track_2->set_enabled(false)); | 222 EXPECT_TRUE(track_2->set_enabled(false)); |
| 213 scoped_ptr<MockWebRtcAudioCapturerSink> sink_2( | 223 scoped_ptr<MockWebRtcAudioCapturerSink> sink_2( |
| 214 new MockWebRtcAudioCapturerSink()); | 224 new MockWebRtcAudioCapturerSink()); |
| 215 EXPECT_CALL(*sink_2, SetCaptureFormat(_)).WillOnce(Return()); | 225 EXPECT_CALL(*sink_2, SetCaptureFormat(_)).WillOnce(Return()); |
| 216 EXPECT_CALL(*sink_2, CaptureData( | 226 EXPECT_CALL(*sink_2, CaptureData( |
| 217 _, params.channels(), params.frames_per_buffer(), 0, 0)) | 227 _, params.channels(), params.frames_per_buffer(), 0, 0)) |
| 218 .Times(0); | 228 .Times(0); |
| 219 track_2->AddSink(sink_2.get()); | 229 track_2->AddSink(sink_2.get()); |
| 220 EXPECT_TRUE(event_1.TimedWait(TestTimeouts::tiny_timeout())); | 230 EXPECT_TRUE(event_1.TimedWait(TestTimeouts::tiny_timeout())); |
| 221 | 231 |
| 222 | 232 |
| 223 // Enable |track_2|, and verify the data callback comes to |sink_2|; | 233 // Enable |track_2|, and verify the data callback comes to |sink_2|; |
| 224 event_1.Reset(); | 234 event_1.Reset(); |
| 225 base::WaitableEvent event_2(false, false); | 235 base::WaitableEvent event_2(false, false); |
| 226 EXPECT_CALL(*sink_1, CaptureData( | 236 EXPECT_CALL(*sink_1, CaptureData( |
| 227 _, params.channels(), params.frames_per_buffer(), 0, 0)) | 237 _, params.channels(), params.frames_per_buffer(), 0, 0)) |
| 228 .Times(AtLeast(1)).WillRepeatedly(SignalEvent(&event_1)); | 238 .Times(AtLeast(1)).WillRepeatedly(SignalEvent(&event_1)); |
| 229 EXPECT_CALL(*sink_2, CaptureData( | 239 EXPECT_CALL(*sink_2, CaptureData( |
| 230 _, params.channels(), params.frames_per_buffer(), 0, 0)) | 240 _, params.channels(), params.frames_per_buffer(), 0, 0)) |
| 231 .Times(AtLeast(1)).WillRepeatedly(SignalEvent(&event_2)); | 241 .Times(AtLeast(1)).WillRepeatedly(SignalEvent(&event_2)); |
| 232 EXPECT_TRUE(track_2->set_enabled(true)); | 242 EXPECT_TRUE(track_2->set_enabled(true)); |
| 233 EXPECT_TRUE(event_1.TimedWait(TestTimeouts::tiny_timeout())); | 243 EXPECT_TRUE(event_1.TimedWait(TestTimeouts::tiny_timeout())); |
| 234 EXPECT_TRUE(event_2.TimedWait(TestTimeouts::tiny_timeout())); | 244 EXPECT_TRUE(event_2.TimedWait(TestTimeouts::tiny_timeout())); |
| 235 | 245 |
| 236 track_1->RemoveSink(sink_1.get()); | 246 track_1->RemoveSink(sink_1.get()); |
| 247 track_1->Stop(); |
| 248 track_1 = NULL; |
| 249 |
| 250 EXPECT_CALL(*capturer_source_.get(), Stop()).WillOnce(Return()); |
| 237 track_2->RemoveSink(sink_2.get()); | 251 track_2->RemoveSink(sink_2.get()); |
| 238 track_1 = NULL; | 252 track_2->Stop(); |
| 239 track_2 = NULL; | 253 track_2 = NULL; |
| 240 } | 254 } |
| 241 | 255 |
| 256 |
| 257 // Start one track and verify the capturer is correctly starting its source. |
| 258 // And it should be fine to not to call Stop() explicitly. |
| 259 TEST_F(WebRtcLocalAudioTrackTest, StartOneAudioTrack) { |
| 260 EXPECT_CALL(*capturer_source_.get(), Start()).Times(1); |
| 261 scoped_refptr<WebRtcLocalAudioTrack> track = |
| 262 WebRtcLocalAudioTrack::Create(std::string(), capturer_, NULL); |
| 263 track->Start(); |
| 264 } |
| 265 |
| 266 // Start/Stop tracks and verify the capturer is correctly starting/stopping |
| 267 // its source. |
| 268 TEST_F(WebRtcLocalAudioTrackTest, StartAndStopAudioTracks) { |
| 269 // SetDefaultSink() should not trigger the Start() on |capturer_source_|. |
| 270 base::WaitableEvent event(false, false); |
| 271 scoped_ptr<MockWebRtcAudioCapturerSink> default_sink( |
| 272 new MockWebRtcAudioCapturerSink()); |
| 273 EXPECT_CALL(*default_sink, SetCaptureFormat(_)).WillOnce(Return()); |
| 274 EXPECT_CALL(*default_sink, CaptureData( |
| 275 _, _, _, 0, 0)) |
| 276 .Times(AnyNumber()).WillRepeatedly(Return()); |
| 277 capturer_->SetDefaultSink(default_sink.get()); |
| 278 EXPECT_CALL(*capturer_source_.get(), Start()).Times(0); |
| 279 EXPECT_FALSE(event.TimedWait(TestTimeouts::tiny_timeout())); |
| 280 |
| 281 // Starting the first audio track will start the |capturer_source_|. |
| 282 event.Reset(); |
| 283 EXPECT_CALL(*capturer_source_.get(), Start()).WillOnce(SignalEvent(&event)); |
| 284 scoped_refptr<WebRtcLocalAudioTrack> track_1 = |
| 285 WebRtcLocalAudioTrack::Create(std::string(), capturer_, NULL); |
| 286 track_1->Start(); |
| 287 EXPECT_TRUE(event.TimedWait(TestTimeouts::tiny_timeout())); |
| 288 |
| 289 // Start the second audio track will not start the |capturer_source_| |
| 290 // since it has been started. |
| 291 EXPECT_CALL(*capturer_source_.get(), Start()).Times(0); |
| 292 scoped_refptr<WebRtcLocalAudioTrack> track_2 = |
| 293 WebRtcLocalAudioTrack::Create(std::string(), capturer_, NULL); |
| 294 track_2->Start(); |
| 295 |
| 296 // Stop the first audio track will not stop the |capturer_source_|. |
| 297 EXPECT_CALL(*capturer_source_.get(), Stop()).Times(0); |
| 298 track_1->Stop(); |
| 299 track_1 = NULL; |
| 300 |
| 301 // Stop the last audio track will stop the |capturer_source_|. |
| 302 event.Reset(); |
| 303 EXPECT_CALL(*capturer_source_.get(), Stop()) |
| 304 .Times(1).WillOnce(SignalEvent(&event)); |
| 305 track_2->Stop(); |
| 306 track_2 = NULL; |
| 307 EXPECT_TRUE(event.TimedWait(TestTimeouts::tiny_timeout())); |
| 308 |
| 309 capturer_->SetDefaultSink(NULL); |
| 310 } |
| 311 |
| 242 } // namespace content | 312 } // namespace content |
| OLD | NEW |