Index: content/renderer/media/webrtc/processed_local_audio_source_unittest.cc |
diff --git a/content/renderer/media/webrtc_audio_capturer_unittest.cc b/content/renderer/media/webrtc/processed_local_audio_source_unittest.cc |
similarity index 20% |
rename from content/renderer/media/webrtc_audio_capturer_unittest.cc |
rename to content/renderer/media/webrtc/processed_local_audio_source_unittest.cc |
index 373b95ba50e17a28e962d3c769253082cb899ab2..3a2516e65d32ecbe8aaa9eb3408c40b0aa340c8b 100644 |
--- a/content/renderer/media/webrtc_audio_capturer_unittest.cc |
+++ b/content/renderer/media/webrtc/processed_local_audio_source_unittest.cc |
@@ -1,46 +1,41 @@ |
-// Copyright 2013 The Chromium Authors. All rights reserved. |
+// Copyright 2016 The Chromium Authors. All rights reserved. |
// Use of this source code is governed by a BSD-style license that can be |
// found in the LICENSE file. |
#include "base/logging.h" |
#include "build/build_config.h" |
#include "content/public/renderer/media_stream_audio_sink.h" |
+#include "content/renderer/media/media_stream_audio_track.h" |
+#include "content/renderer/media/mock_audio_device_factory.h" |
#include "content/renderer/media/mock_constraint_factory.h" |
-#include "content/renderer/media/webrtc/webrtc_local_audio_track_adapter.h" |
-#include "content/renderer/media/webrtc_audio_capturer.h" |
-#include "content/renderer/media/webrtc_local_audio_track.h" |
+#include "content/renderer/media/webrtc/mock_peer_connection_dependency_factory.h" |
+#include "content/renderer/media/webrtc/processed_local_audio_source.h" |
#include "media/base/audio_bus.h" |
#include "media/base/audio_parameters.h" |
#include "testing/gmock/include/gmock/gmock.h" |
#include "testing/gtest/include/gtest/gtest.h" |
#include "third_party/WebKit/public/platform/WebMediaConstraints.h" |
+#include "third_party/WebKit/public/web/WebHeap.h" |
using ::testing::_; |
using ::testing::AtLeast; |
+using ::testing::Invoke; |
namespace content { |
namespace { |
-class MockCapturerSource : public media::AudioCapturerSource { |
- public: |
- MockCapturerSource() {} |
- MOCK_METHOD3(Initialize, void(const media::AudioParameters& params, |
- CaptureCallback* callback, |
- int session_id)); |
- MOCK_METHOD0(Start, void()); |
- MOCK_METHOD0(Stop, void()); |
- MOCK_METHOD1(SetVolume, void(double volume)); |
- MOCK_METHOD1(SetAutomaticGainControl, void(bool enable)); |
- |
- protected: |
- ~MockCapturerSource() override {} |
-}; |
+#if defined(OS_ANDROID) |
+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!
|
+#else |
+constexpr int kBufferSize = 128; |
+#endif |
class MockMediaStreamAudioSink : public MediaStreamAudioSink { |
public: |
MockMediaStreamAudioSink() {} |
~MockMediaStreamAudioSink() override {} |
+ |
void OnData(const media::AudioBus& audio_bus, |
base::TimeTicks estimated_capture_time) override { |
EXPECT_EQ(audio_bus.channels(), params_.channels()); |
@@ -49,11 +44,12 @@ class MockMediaStreamAudioSink : public MediaStreamAudioSink { |
OnDataCallback(); |
} |
MOCK_METHOD0(OnDataCallback, void()); |
+ |
void OnSetFormat(const media::AudioParameters& params) override { |
params_ = params; |
- FormatIsSet(); |
+ FormatIsSet(params_); |
} |
- MOCK_METHOD0(FormatIsSet, void()); |
+ MOCK_METHOD1(FormatIsSet, void(const media::AudioParameters& params)); |
private: |
media::AudioParameters params_; |
@@ -61,92 +57,152 @@ class MockMediaStreamAudioSink : public MediaStreamAudioSink { |
} // namespace |
-class WebRtcAudioCapturerTest : public testing::Test { |
+class ProcessedLocalAudioSourceTest : public testing::Test { |
protected: |
- WebRtcAudioCapturerTest() |
-#if defined(OS_ANDROID) |
- : params_(media::AudioParameters::AUDIO_PCM_LOW_LATENCY, |
- media::CHANNEL_LAYOUT_STEREO, 48000, 16, 960) { |
- // Android works with a buffer size bigger than 20ms. |
-#else |
+ ProcessedLocalAudioSourceTest() |
: params_(media::AudioParameters::AUDIO_PCM_LOW_LATENCY, |
- media::CHANNEL_LAYOUT_STEREO, 48000, 16, 128) { |
-#endif |
+ media::CHANNEL_LAYOUT_STEREO, 48000, 16, kBufferSize) {} |
+ |
+ ~ProcessedLocalAudioSourceTest() override {} |
+ |
+ void SetUp() override { |
+ blink_audio_source_.initialize(blink::WebString::fromUTF8("audio_label"), |
+ blink::WebMediaStreamSource::TypeAudio, |
+ blink::WebString::fromUTF8("audio_track"), |
+ false /* remote */, true /* readonly */); |
+ blink_audio_track_.initialize(blink_audio_source_.id(), |
+ blink_audio_source_); |
} |
- void VerifyAudioParams(const blink::WebMediaConstraints& constraints, |
- bool need_audio_processing) { |
- const std::unique_ptr<WebRtcAudioCapturer> capturer = |
- WebRtcAudioCapturer::CreateCapturer( |
- -1, StreamDeviceInfo( |
- MEDIA_DEVICE_AUDIO_CAPTURE, "", "", params_.sample_rate(), |
- params_.channel_layout(), params_.frames_per_buffer()), |
- constraints, nullptr, nullptr); |
- const scoped_refptr<MockCapturerSource> capturer_source( |
- new MockCapturerSource()); |
- EXPECT_CALL(*capturer_source.get(), Initialize(_, capturer.get(), -1)); |
- EXPECT_CALL(*capturer_source.get(), SetAutomaticGainControl(true)); |
- EXPECT_CALL(*capturer_source.get(), Start()); |
- capturer->SetCapturerSource(capturer_source, params_); |
- |
- scoped_refptr<WebRtcLocalAudioTrackAdapter> adapter( |
- WebRtcLocalAudioTrackAdapter::Create(std::string(), NULL)); |
- const std::unique_ptr<WebRtcLocalAudioTrack> track( |
- new WebRtcLocalAudioTrack(adapter.get())); |
- capturer->AddTrack(track.get()); |
- |
- // Connect a mock sink to the track. |
- std::unique_ptr<MockMediaStreamAudioSink> sink( |
- new MockMediaStreamAudioSink()); |
- track->AddSink(sink.get()); |
- |
- int delay_ms = 65; |
- bool key_pressed = true; |
- double volume = 0.9; |
- |
- std::unique_ptr<media::AudioBus> audio_bus = |
- media::AudioBus::Create(params_); |
- audio_bus->Zero(); |
- |
- media::AudioCapturerSource::CaptureCallback* callback = |
- static_cast<media::AudioCapturerSource::CaptureCallback*>( |
- capturer.get()); |
- |
- // Verify the sink is getting the correct values. |
- EXPECT_CALL(*sink, FormatIsSet()); |
- EXPECT_CALL(*sink, OnDataCallback()).Times(AtLeast(1)); |
- callback->Capture(audio_bus.get(), delay_ms, volume, key_pressed); |
- |
- track->RemoveSink(sink.get()); |
- EXPECT_CALL(*capturer_source.get(), Stop()); |
- capturer->Stop(); |
+ void TearDown() override { |
+ blink_audio_track_.reset(); |
+ blink_audio_source_.reset(); |
+ blink::WebHeap::collectAllGarbageForTesting(); |
} |
- media::AudioParameters params_; |
+ void CreateProcessedLocalAudioSource( |
+ const blink::WebMediaConstraints& constraints) { |
+ ProcessedLocalAudioSource* const source = |
+ new ProcessedLocalAudioSource( |
+ -1 /* consumer_render_frame_id is N/A for non-browser tests */, |
+ StreamDeviceInfo(MEDIA_DEVICE_AUDIO_CAPTURE, "Mock audio device", |
+ "mock_audio_device_id", params_.sample_rate(), |
+ params_.channel_layout(), |
+ params_.frames_per_buffer()), |
+ &mock_dependency_factory_); |
+ source->SetAllowInvalidRenderFrameIdForTesting(true); |
+ source->SetSourceConstraints(constraints); |
+ blink_audio_source_.setExtraData(source); // Takes ownership. |
+ } |
+ |
+ void CheckAudioParametersMatch(const media::AudioParameters& params) { |
+ EXPECT_TRUE(params_.Equals(params)); |
+ } |
+ |
+ MockAudioDeviceFactory* mock_audio_device_factory() { |
+ return &mock_audio_device_factory_; |
+ } |
+ |
+ media::AudioCapturerSource::CaptureCallback* capture_source_callback() const { |
+ return static_cast<media::AudioCapturerSource::CaptureCallback*>( |
+ ProcessedLocalAudioSource::From(audio_source())); |
+ } |
+ |
+ MediaStreamAudioSource* audio_source() const { |
+ return MediaStreamAudioSource::From(blink_audio_source_); |
+ } |
+ |
+ const blink::WebMediaStreamTrack& blink_audio_track() { |
+ return blink_audio_track_; |
+ } |
+ |
+ private: |
+ MockAudioDeviceFactory mock_audio_device_factory_; |
+ const media::AudioParameters params_; |
+ MockPeerConnectionDependencyFactory mock_dependency_factory_; |
+ blink::WebMediaStreamSource blink_audio_source_; |
+ blink::WebMediaStreamTrack blink_audio_track_; |
}; |
-TEST_F(WebRtcAudioCapturerTest, VerifyAudioParamsWithAudioProcessing) { |
- // Turn off the default constraints to verify that the sink will get packets |
- // with a buffer size smaller than 10ms. |
+// Tests a basic end-to-end start-up, track+sink connections, audio flow, and |
+// shut-down. The unit tests in media_stream_audio_unittest.cc provide more |
+// comprehensive testing of the object graph connections and multi-threading |
+// concerns. |
+TEST_F(ProcessedLocalAudioSourceTest, VerifyAudioFlowWithoutAudioProcessing) { |
+ // Turn off the default constraints so the sink will get audio in chunks of |
+ // the native buffer size. |
MockConstraintFactory constraint_factory; |
constraint_factory.DisableDefaultAudioConstraints(); |
- VerifyAudioParams(constraint_factory.CreateWebMediaConstraints(), false); |
+ |
+ CreateProcessedLocalAudioSource( |
+ constraint_factory.CreateWebMediaConstraints()); |
+ |
+ // Connect the track, and expect the MockCapturerSource to be initialized and |
+ // started by ProcessedLocalAudioSource. |
+ EXPECT_CALL(*mock_audio_device_factory()->mock_capturer_source(), |
+ Initialize(_, capture_source_callback(), -1)); |
+ EXPECT_CALL(*mock_audio_device_factory()->mock_capturer_source(), |
+ SetAutomaticGainControl(true)); |
+ EXPECT_CALL(*mock_audio_device_factory()->mock_capturer_source(), Start()); |
+ ASSERT_TRUE(audio_source()->ConnectToTrack(blink_audio_track())); |
+ CheckAudioParametersMatch(audio_source()->GetAudioParameters()); |
+ |
+ // Connect a sink to the track. |
+ std::unique_ptr<MockMediaStreamAudioSink> sink( |
+ new MockMediaStreamAudioSink()); |
+ using ThisTest = |
+ ProcessedLocalAudioSourceTest_VerifyAudioFlowWithoutAudioProcessing_Test; |
+ EXPECT_CALL(*sink, FormatIsSet(_)) |
+ .WillOnce(Invoke(this, &ThisTest::CheckAudioParametersMatch)); |
+ MediaStreamAudioTrack::From(blink_audio_track())->AddSink(sink.get()); |
+ |
+ // Feed audio data into the ProcessedLocalAudioSource and expect it to reach |
+ // the sink. |
+ int delay_ms = 65; |
+ bool key_pressed = true; |
+ double volume = 0.9; |
+ std::unique_ptr<media::AudioBus> audio_bus = |
+ media::AudioBus::Create(audio_source()->GetAudioParameters()); |
+ audio_bus->Zero(); |
+ EXPECT_CALL(*sink, OnDataCallback()).Times(AtLeast(1)); |
+ capture_source_callback()->Capture(audio_bus.get(), delay_ms, volume, |
+ key_pressed); |
+ |
+ // Expect the ProcessedLocalAudioSource to auto-stop the MockCapturerSource |
+ // when the track is stopped. |
+ EXPECT_CALL(*mock_audio_device_factory()->mock_capturer_source(), Stop()); |
+ MediaStreamAudioTrack::From(blink_audio_track())->Stop(); |
} |
-TEST_F(WebRtcAudioCapturerTest, FailToCreateCapturerWithWrongConstraints) { |
+// Tests that the source is not started when invalid audio constraints are |
+// present. |
+TEST_F(ProcessedLocalAudioSourceTest, FailToStartWithWrongConstraints) { |
MockConstraintFactory constraint_factory; |
const std::string dummy_constraint = "dummy"; |
// Set a non-audio constraint. |
constraint_factory.basic().width.setExact(240); |
- std::unique_ptr<WebRtcAudioCapturer> capturer( |
- WebRtcAudioCapturer::CreateCapturer( |
- 0, StreamDeviceInfo(MEDIA_DEVICE_AUDIO_CAPTURE, "", "", |
- params_.sample_rate(), params_.channel_layout(), |
- params_.frames_per_buffer()), |
- constraint_factory.CreateWebMediaConstraints(), NULL, NULL)); |
- EXPECT_TRUE(capturer.get() == NULL); |
+ CreateProcessedLocalAudioSource( |
+ constraint_factory.CreateWebMediaConstraints()); |
+ |
+ // Expect the MockCapturerSource is never initialized/started and the |
+ // ConnectToTrack() operation fails due to the invalid constraint. |
+ EXPECT_CALL(*mock_audio_device_factory()->mock_capturer_source(), |
+ Initialize(_, capture_source_callback(), -1)) |
+ .Times(0); |
+ EXPECT_CALL(*mock_audio_device_factory()->mock_capturer_source(), |
+ SetAutomaticGainControl(true)).Times(0); |
+ EXPECT_CALL(*mock_audio_device_factory()->mock_capturer_source(), Start()) |
+ .Times(0); |
+ EXPECT_FALSE(audio_source()->ConnectToTrack(blink_audio_track())); |
+ |
+ // Even though ConnectToTrack() failed, there should still have been a new |
+ // MediaStreamAudioTrack instance created, owned by the |
+ // blink::WebMediaStreamTrack. |
+ EXPECT_TRUE(MediaStreamAudioTrack::From(blink_audio_track())); |
} |
+// TODO(miu): There's a lot of logic in ProcessedLocalAudioSource around |
+// constraints processing and validation that should have unit testing. |
} // namespace content |