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/media_stream_audio_processor.h" 13#include "content/renderer/media/rtc_media_constraints.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 20using ::testing::_; 21using ::testing::AnyNumber; 22using ::testing::AtLeast; 23using ::testing::Return; 24 25namespace content { 26 27namespace { 28 29#if defined(ANDROID) 30const int kAudioProcessingSampleRate = 16000; 31#else 32const int kAudioProcessingSampleRate = 32000; 33#endif 34const int kAudioProcessingNumberOfChannel = 1; 35 36// The number of packers used for testing. 37const int kNumberOfPacketsForTest = 100; 38 39void 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(base::GetFileSize(file, &data_file_size64)); 49 EXPECT_EQ(length, base::ReadFile(file, data, length)); 50 DCHECK(data_file_size64 > length); 51} 52 53void 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 85class MediaStreamAudioProcessorTest : public ::testing::Test { 86 public: 87 MediaStreamAudioProcessorTest() 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(MediaStreamAudioProcessor* 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 139TEST_F(MediaStreamAudioProcessorTest, WithoutAudioProcessing) { 140 // Setup the audio processor with empty constraint. 141 RTCMediaConstraints constraints; 142 MediaStreamAudioProcessor 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 152TEST_F(MediaStreamAudioProcessorTest, WithAudioProcessing) { 153 // Setup the audio processor with default constraint. 154 RTCMediaConstraints constraints; 155 ApplyFixedAudioConstraints(&constraints); 156 MediaStreamAudioProcessor 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 167