summaryrefslogtreecommitdiffstats
path: root/content
diff options
context:
space:
mode:
authorxians@chromium.org <xians@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-11-29 01:54:23 +0000
committerxians@chromium.org <xians@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-11-29 01:54:23 +0000
commit2af5bbebd8959d78999460cb58b91364e83caf06 (patch)
treefc9c4d6de1e6374a4a6720ccf1589eacc11dac4c /content
parente11e3b040c3fb5d62e937eb55cd41dcbc00412d4 (diff)
downloadchromium_src-2af5bbebd8959d78999460cb58b91364e83caf06.zip
chromium_src-2af5bbebd8959d78999460cb58b91364e83caf06.tar.gz
chromium_src-2af5bbebd8959d78999460cb58b91364e83caf06.tar.bz2
Fixed the problem where audio processing is disabled when video effect is enabled.
And added unittest to prevent such problems happening again. BUG=324293 TEST=content_unittests --gtest_filter="*WebRtcAudioCapturer*" Review URL: https://codereview.chromium.org/95083002 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@237861 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'content')
-rw-r--r--content/content_tests.gypi1
-rw-r--r--content/renderer/media/webrtc_audio_capturer.cc2
-rw-r--r--content/renderer/media/webrtc_audio_capturer_unittest.cc171
3 files changed, 173 insertions, 1 deletions
diff --git a/content/content_tests.gypi b/content/content_tests.gypi
index eab8945..b8c5678 100644
--- a/content/content_tests.gypi
+++ b/content/content_tests.gypi
@@ -687,6 +687,7 @@
'renderer/media/rtc_peer_connection_handler_unittest.cc',
'renderer/media/rtc_video_decoder_unittest.cc',
'renderer/media/video_source_handler_unittest.cc',
+ 'renderer/media/webrtc_audio_capturer_unittest.cc',
'renderer/media/webrtc_audio_device_unittest.cc',
'renderer/media/webrtc_identity_service_unittest.cc',
'renderer/media/webrtc_local_audio_source_provider_unittest.cc',
diff --git a/content/renderer/media/webrtc_audio_capturer.cc b/content/renderer/media/webrtc_audio_capturer.cc
index 5a6e59d..275290a 100644
--- a/content/renderer/media/webrtc_audio_capturer.cc
+++ b/content/renderer/media/webrtc_audio_capturer.cc
@@ -435,7 +435,7 @@ void WebRtcAudioCapturer::Capture(media::AudioBus* audio_source,
// volume is higher than 255.
volume_ = static_cast<int>((volume * MaxVolume()) + 0.5);
current_volume = volume_;
- audio_delay_ = base::TimeDelta::FromMicroseconds(audio_delay_milliseconds);
+ audio_delay_ = base::TimeDelta::FromMilliseconds(audio_delay_milliseconds);
key_pressed_ = key_pressed;
tracks = tracks_;
std::swap(tracks_to_notify_format_, tracks_to_notify_format);
diff --git a/content/renderer/media/webrtc_audio_capturer_unittest.cc b/content/renderer/media/webrtc_audio_capturer_unittest.cc
new file mode 100644
index 0000000..08a3d9d
--- /dev/null
+++ b/content/renderer/media/webrtc_audio_capturer_unittest.cc
@@ -0,0 +1,171 @@
+// Copyright 2013 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 "content/renderer/media/rtc_media_constraints.h"
+#include "content/renderer/media/webrtc_audio_capturer.h"
+#include "content/renderer/media/webrtc_local_audio_track.h"
+#include "media/audio/audio_parameters.h"
+#include "media/base/audio_bus.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+using ::testing::_;
+using ::testing::AtLeast;
+
+namespace content {
+
+namespace {
+
+// TODO(xians): Consolidate the similar methods in different unittests into
+// one.
+void ApplyFixedAudioConstraints(RTCMediaConstraints* constraints) {
+ // Constant constraint keys which enables default audio constraints on
+ // mediastreams with audio.
+ struct {
+ const char* key;
+ const char* value;
+ } static const kDefaultAudioConstraints[] = {
+ { webrtc::MediaConstraintsInterface::kEchoCancellation,
+ webrtc::MediaConstraintsInterface::kValueTrue },
+ #if defined(OS_CHROMEOS) || defined(OS_MACOSX)
+ // Enable the extended filter mode AEC on platforms with known echo issues.
+ { webrtc::MediaConstraintsInterface::kExperimentalEchoCancellation,
+ webrtc::MediaConstraintsInterface::kValueTrue },
+ #endif
+ { webrtc::MediaConstraintsInterface::kAutoGainControl,
+ webrtc::MediaConstraintsInterface::kValueTrue },
+ { webrtc::MediaConstraintsInterface::kExperimentalAutoGainControl,
+ webrtc::MediaConstraintsInterface::kValueTrue },
+ { webrtc::MediaConstraintsInterface::kNoiseSuppression,
+ webrtc::MediaConstraintsInterface::kValueTrue },
+ { webrtc::MediaConstraintsInterface::kHighpassFilter,
+ webrtc::MediaConstraintsInterface::kValueTrue },
+ };
+
+ for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kDefaultAudioConstraints); ++i) {
+ constraints->AddMandatory(kDefaultAudioConstraints[i].key,
+ kDefaultAudioConstraints[i].value, false);
+ }
+}
+
+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:
+ virtual ~MockCapturerSource() {}
+};
+
+class MockWebRtcAudioCapturerSink : public WebRtcAudioCapturerSink {
+ public:
+ MockWebRtcAudioCapturerSink() {}
+ ~MockWebRtcAudioCapturerSink() {}
+ MOCK_METHOD9(CaptureData, int(const std::vector<int>& channels,
+ const int16* audio_data,
+ int sample_rate,
+ int number_of_channels,
+ int number_of_frames,
+ int audio_delay_milliseconds,
+ int current_volume,
+ bool need_audio_processing,
+ bool key_pressed));
+ MOCK_METHOD1(SetCaptureFormat, void(const media::AudioParameters& params));
+};
+
+} // namespace
+
+class WebRtcAudioCapturerTest : 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
+ : params_(media::AudioParameters::AUDIO_PCM_LOW_LATENCY,
+ media::CHANNEL_LAYOUT_STEREO, 48000, 16, 128) {
+#endif
+ capturer_ = WebRtcAudioCapturer::CreateCapturer();
+ capturer_->Initialize(-1, params_.channel_layout(), params_.sample_rate(),
+ params_.frames_per_buffer(), 0, std::string(), 0, 0);
+ capturer_source_ = new MockCapturerSource();
+ EXPECT_CALL(*capturer_source_.get(), Initialize(_, capturer_.get(), 0));
+ capturer_->SetCapturerSource(capturer_source_,
+ params_.channel_layout(),
+ params_.sample_rate());
+
+ EXPECT_CALL(*capturer_source_.get(), SetAutomaticGainControl(true));
+ EXPECT_CALL(*capturer_source_.get(), Start());
+ RTCMediaConstraints constraints;
+ ApplyFixedAudioConstraints(&constraints);
+ track_ = WebRtcLocalAudioTrack::Create(std::string(), capturer_, NULL,
+ NULL, &constraints);
+ static_cast<WebRtcLocalAudioSourceProvider*>(
+ track_->audio_source_provider())->SetSinkParamsForTesting(params_);
+ track_->Start();
+ EXPECT_TRUE(track_->enabled());
+ }
+
+ media::AudioParameters params_;
+ scoped_refptr<MockCapturerSource> capturer_source_;
+ scoped_refptr<WebRtcAudioCapturer> capturer_;
+ scoped_refptr<WebRtcLocalAudioTrack> track_;
+};
+
+// Pass the delay value, vollume and key_pressed info via capture callback, and
+// those values should be correctly stored and passed to the track.
+TEST_F(WebRtcAudioCapturerTest, VerifyAudioParams) {
+ // Connect a mock sink to the track.
+ scoped_ptr<MockWebRtcAudioCapturerSink> sink(
+ new MockWebRtcAudioCapturerSink());
+ track_->AddSink(sink.get());
+
+ int delay_ms = 65;
+ bool key_pressed = true;
+ double volume = 0.9;
+ // MaxVolume() in WebRtcAudioCapturer is hard-coded to return 255, we add 0.5
+ // to do the correct truncation as how the production code does.
+ int expected_volume_value = volume * capturer_->MaxVolume() + 0.5;
+ scoped_ptr<media::AudioBus> audio_bus = media::AudioBus::Create(params_);
+#if defined(OS_ANDROID)
+ const int expected_buffer_size = params_.sample_rate() / 100;
+#else
+ const int expected_buffer_size = params_.frames_per_buffer();
+#endif
+ bool expected_need_audio_processing = true;
+ media::AudioCapturerSource::CaptureCallback* callback =
+ static_cast<media::AudioCapturerSource::CaptureCallback*>(capturer_);
+ // Verify the sink is getting the correct values.
+ EXPECT_CALL(*sink, SetCaptureFormat(_));
+ EXPECT_CALL(*sink,
+ CaptureData(_, _, params_.sample_rate(), params_.channels(),
+ expected_buffer_size, delay_ms,
+ expected_volume_value, expected_need_audio_processing,
+ key_pressed)).Times(AtLeast(1));
+ callback->Capture(audio_bus.get(), delay_ms, volume, key_pressed);
+
+ // Verify the cached values in the capturer fits what we expect.
+ base::TimeDelta cached_delay;
+ int cached_volume = !expected_volume_value;
+ bool cached_key_pressed = !key_pressed;
+ capturer_->GetAudioProcessingParams(&cached_delay, &cached_volume,
+ &cached_key_pressed);
+ EXPECT_EQ(cached_delay.InMilliseconds(), delay_ms);
+ EXPECT_EQ(cached_volume, expected_volume_value);
+ EXPECT_EQ(cached_key_pressed, key_pressed);
+
+ track_->RemoveSink(sink.get());
+ EXPECT_CALL(*capturer_source_.get(), Stop());
+ capturer_->Stop();
+}
+
+} // namespace content