OLD | NEW |
(Empty) | |
| 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 |
| 3 // found in the LICENSE file. |
| 4 |
| 5 #include "base/command_line.h" |
| 6 #include "base/file_util.h" |
| 7 #include "base/files/file_path.h" |
| 8 #include "base/logging.h" |
| 9 #include "base/path_service.h" |
| 10 #include "base/time/time.h" |
| 11 #include "content/public/common/content_switches.h" |
| 12 #include "content/renderer/media/rtc_media_constraints.h" |
| 13 #include "content/renderer/media/webrtc_audio_processor.h" |
| 14 #include "media/audio/audio_parameters.h" |
| 15 #include "media/base/audio_bus.h" |
| 16 #include "testing/gmock/include/gmock/gmock.h" |
| 17 #include "testing/gtest/include/gtest/gtest.h" |
| 18 #include "third_party/libjingle/source/talk/app/webrtc/mediastreaminterface.h" |
| 19 |
| 20 using ::testing::_; |
| 21 using ::testing::AnyNumber; |
| 22 using ::testing::AtLeast; |
| 23 using ::testing::Return; |
| 24 |
| 25 namespace content { |
| 26 |
| 27 namespace { |
| 28 |
| 29 #if defined(ANDROID) |
| 30 const int kAudioProcessingSampleRate = 16000; |
| 31 #else |
| 32 const int kAudioProcessingSampleRate = 32000; |
| 33 #endif |
| 34 const int kAudioProcessingNumberOfChannel = 1; |
| 35 |
| 36 // The number of packers used for testing. |
| 37 const int kNumberOfPacketsForTest = 100; |
| 38 |
| 39 void ReadDataFromSpeechFile(char* data, int length) { |
| 40 base::FilePath file; |
| 41 CHECK(PathService::Get(base::DIR_SOURCE_ROOT, &file)); |
| 42 file = file.Append(FILE_PATH_LITERAL("media")) |
| 43 .Append(FILE_PATH_LITERAL("test")) |
| 44 .Append(FILE_PATH_LITERAL("data")) |
| 45 .Append(FILE_PATH_LITERAL("speech_16b_stereo_48kHz.raw")); |
| 46 DCHECK(base::PathExists(file)); |
| 47 int64 data_file_size64 = 0; |
| 48 DCHECK(file_util::GetFileSize(file, &data_file_size64)); |
| 49 EXPECT_EQ(length, file_util::ReadFile(file, data, length)); |
| 50 DCHECK(data_file_size64 > length); |
| 51 } |
| 52 |
| 53 void ApplyFixedAudioConstraints(RTCMediaConstraints* constraints) { |
| 54 // Constant constraint keys which enables default audio constraints on |
| 55 // mediastreams with audio. |
| 56 struct { |
| 57 const char* key; |
| 58 const char* value; |
| 59 } static const kDefaultAudioConstraints[] = { |
| 60 { webrtc::MediaConstraintsInterface::kEchoCancellation, |
| 61 webrtc::MediaConstraintsInterface::kValueTrue }, |
| 62 #if defined(OS_CHROMEOS) || defined(OS_MACOSX) |
| 63 // Enable the extended filter mode AEC on platforms with known echo issues. |
| 64 { webrtc::MediaConstraintsInterface::kExperimentalEchoCancellation, |
| 65 webrtc::MediaConstraintsInterface::kValueTrue }, |
| 66 #endif |
| 67 { webrtc::MediaConstraintsInterface::kAutoGainControl, |
| 68 webrtc::MediaConstraintsInterface::kValueTrue }, |
| 69 { webrtc::MediaConstraintsInterface::kExperimentalAutoGainControl, |
| 70 webrtc::MediaConstraintsInterface::kValueTrue }, |
| 71 { webrtc::MediaConstraintsInterface::kNoiseSuppression, |
| 72 webrtc::MediaConstraintsInterface::kValueTrue }, |
| 73 { webrtc::MediaConstraintsInterface::kHighpassFilter, |
| 74 webrtc::MediaConstraintsInterface::kValueTrue }, |
| 75 }; |
| 76 |
| 77 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kDefaultAudioConstraints); ++i) { |
| 78 constraints->AddMandatory(kDefaultAudioConstraints[i].key, |
| 79 kDefaultAudioConstraints[i].value, false); |
| 80 } |
| 81 } |
| 82 |
| 83 } // namespace |
| 84 |
| 85 class WebRtcAudioProcessorTest : public ::testing::Test { |
| 86 public: |
| 87 WebRtcAudioProcessorTest() |
| 88 : params_(media::AudioParameters::AUDIO_PCM_LOW_LATENCY, |
| 89 media::CHANNEL_LAYOUT_STEREO, 48000, 16, 512) { |
| 90 CommandLine::ForCurrentProcess()->AppendSwitch( |
| 91 switches::kEnableAudioTrackProcessing); |
| 92 } |
| 93 |
| 94 protected: |
| 95 // Helper method to save duplicated code. |
| 96 void ProcessDataAndVerifyFormat(WebRtcAudioProcessor* audio_processor, |
| 97 int expected_output_sample_rate, |
| 98 int expected_output_channels, |
| 99 int expected_output_buffer_size) { |
| 100 // Read the audio data from a file. |
| 101 const int packet_size = |
| 102 params_.frames_per_buffer() * 2 * params_.channels(); |
| 103 const size_t length = packet_size * kNumberOfPacketsForTest; |
| 104 scoped_ptr<char[]> capture_data(new char[length]); |
| 105 ReadDataFromSpeechFile(capture_data.get(), length); |
| 106 const int16* data_ptr = reinterpret_cast<const int16*>(capture_data.get()); |
| 107 scoped_ptr<media::AudioBus> data_bus = media::AudioBus::Create( |
| 108 params_.channels(), params_.frames_per_buffer()); |
| 109 for (int i = 0; i < kNumberOfPacketsForTest; ++i) { |
| 110 data_bus->FromInterleaved(data_ptr, data_bus->frames(), 2); |
| 111 audio_processor->PushCaptureData(data_bus.get()); |
| 112 |
| 113 // |audio_processor| does nothing when the audio processing is off in |
| 114 // the processor. |
| 115 audio_processor->PushRenderData( |
| 116 data_ptr, |
| 117 params_.sample_rate(), params_.channels(), |
| 118 params_.frames_per_buffer(), base::TimeDelta::FromMilliseconds(10)); |
| 119 |
| 120 int16* output = NULL; |
| 121 while(audio_processor->ProcessAndConsumeData( |
| 122 base::TimeDelta::FromMilliseconds(10), 255, false, &output)) { |
| 123 EXPECT_TRUE(output != NULL); |
| 124 EXPECT_EQ(audio_processor->OutputFormat().sample_rate(), |
| 125 expected_output_sample_rate); |
| 126 EXPECT_EQ(audio_processor->OutputFormat().channels(), |
| 127 expected_output_channels); |
| 128 EXPECT_EQ(audio_processor->OutputFormat().frames_per_buffer(), |
| 129 expected_output_buffer_size); |
| 130 } |
| 131 |
| 132 data_ptr += params_.frames_per_buffer() * params_.channels(); |
| 133 } |
| 134 } |
| 135 |
| 136 media::AudioParameters params_; |
| 137 }; |
| 138 |
| 139 TEST_F(WebRtcAudioProcessorTest, WithoutAudioProcessing) { |
| 140 // Setup the audio processor with empty constraint. |
| 141 RTCMediaConstraints constraints; |
| 142 WebRtcAudioProcessor audio_processor(&constraints); |
| 143 audio_processor.SetCaptureFormat(params_); |
| 144 EXPECT_FALSE(audio_processor.has_audio_processing()); |
| 145 |
| 146 ProcessDataAndVerifyFormat(&audio_processor, |
| 147 params_.sample_rate(), |
| 148 params_.channels(), |
| 149 params_.sample_rate() / 100); |
| 150 } |
| 151 |
| 152 TEST_F(WebRtcAudioProcessorTest, WithAudioProcessing) { |
| 153 // Setup the audio processor with default constraint. |
| 154 RTCMediaConstraints constraints; |
| 155 ApplyFixedAudioConstraints(&constraints); |
| 156 WebRtcAudioProcessor audio_processor(&constraints); |
| 157 audio_processor.SetCaptureFormat(params_); |
| 158 EXPECT_TRUE(audio_processor.has_audio_processing()); |
| 159 |
| 160 ProcessDataAndVerifyFormat(&audio_processor, |
| 161 kAudioProcessingSampleRate, |
| 162 kAudioProcessingNumberOfChannel, |
| 163 kAudioProcessingSampleRate / 100); |
| 164 } |
| 165 |
| 166 } // namespace content |
OLD | NEW |