diff options
author | xians@chromium.org <xians@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-11-29 01:54:23 +0000 |
---|---|---|
committer | xians@chromium.org <xians@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-11-29 01:54:23 +0000 |
commit | 2af5bbebd8959d78999460cb58b91364e83caf06 (patch) | |
tree | fc9c4d6de1e6374a4a6720ccf1589eacc11dac4c /content | |
parent | e11e3b040c3fb5d62e937eb55cd41dcbc00412d4 (diff) | |
download | chromium_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.gypi | 1 | ||||
-rw-r--r-- | content/renderer/media/webrtc_audio_capturer.cc | 2 | ||||
-rw-r--r-- | content/renderer/media/webrtc_audio_capturer_unittest.cc | 171 |
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 |