| Index: content/renderer/media/webrtc_audio_processor_unittest.cc | 
| diff --git a/content/renderer/media/webrtc_audio_processor_unittest.cc b/content/renderer/media/webrtc_audio_processor_unittest.cc | 
| new file mode 100644 | 
| index 0000000000000000000000000000000000000000..3d4e6cc4ac26473129e3e0f2d40da5b3cc41cd8f | 
| --- /dev/null | 
| +++ b/content/renderer/media/webrtc_audio_processor_unittest.cc | 
| @@ -0,0 +1,166 @@ | 
| +// 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/command_line.h" | 
| +#include "base/file_util.h" | 
| +#include "base/files/file_path.h" | 
| +#include "base/path_service.h" | 
| +#include "base/time/time.h" | 
| +#include "content/public/common/content_switches.h" | 
| +#include "content/renderer/media/rtc_media_constraints.h" | 
| +#include "content/renderer/media/webrtc_audio_processor.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" | 
| +#include "third_party/libjingle/source/talk/app/webrtc/mediastreaminterface.h" | 
| + | 
| +using ::testing::_; | 
| +using ::testing::AnyNumber; | 
| +using ::testing::AtLeast; | 
| +using ::testing::Return; | 
| + | 
| +namespace content { | 
| + | 
| +namespace { | 
| + | 
| +#if defined(ANDROID) | 
| +const int kAudioProcessingSampleRate = 16000; | 
| +#else | 
| +const int kAudioProcessingSampleRate = 32000; | 
| +#endif | 
| +const int kAudioProcessingNumberOfChannel = 1; | 
| + | 
| +// The number of packers used for testing. | 
| +const int kNumberOfPacketsForTest = 100; | 
| + | 
| +void ReadDataFromSpeechFile(char* data, int length) { | 
| +  base::FilePath file; | 
| +  CHECK(PathService::Get(base::DIR_SOURCE_ROOT, &file)); | 
| +  file = file.Append(FILE_PATH_LITERAL("media")) | 
| +             .Append(FILE_PATH_LITERAL("test")) | 
| +             .Append(FILE_PATH_LITERAL("data")) | 
| +             .Append(FILE_PATH_LITERAL("speech_16b_stereo_48kHz.raw")); | 
| +  DCHECK(base::PathExists(file)); | 
| +  int64 data_file_size64 = 0; | 
| +  DCHECK(file_util::GetFileSize(file, &data_file_size64)); | 
| +  EXPECT_EQ(length, file_util::ReadFile(file, data, length)); | 
| +  DCHECK(data_file_size64 > length); | 
| +} | 
| + | 
| +// Constant constraint keys which enables default audio constraints on | 
| +// mediastreams with audio. | 
| +struct { | 
| +  const char* key; | 
| +  const char* value; | 
| +} 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 }, | 
| +}; | 
| + | 
| +void ApplyFixedAudioConstraints(RTCMediaConstraints* constraints) { | 
| +  for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kDefaultAudioConstraints); ++i) { | 
| +    constraints->AddMandatory(kDefaultAudioConstraints[i].key, | 
| +                              kDefaultAudioConstraints[i].value, false); | 
| +  } | 
| +} | 
| + | 
| +}  // namespace | 
| + | 
| +class WebRtcAudioProcessorTest : public ::testing::Test { | 
| + public: | 
| +  WebRtcAudioProcessorTest() | 
| +      : params_(media::AudioParameters::AUDIO_PCM_LOW_LATENCY, | 
| +                media::CHANNEL_LAYOUT_STEREO, 48000, 16, 512) { | 
| +    CommandLine::ForCurrentProcess()->AppendSwitch( | 
| +        switches::kEnableAudioTrackProcessing); | 
| +  } | 
| + | 
| + protected: | 
| +  // Helper method to save duplicated code. | 
| +  void ProcessDataAndVerifyFormat(WebRtcAudioProcessor* audio_processor, | 
| +                                  int expected_output_sample_rate, | 
| +                                  int expected_output_channels, | 
| +                                  int expected_output_buffer_size) { | 
| +    // Read the audio data from a file. | 
| +    const int packet_size = | 
| +        params_.frames_per_buffer() * 2 * params_.channels(); | 
| +    const size_t length = packet_size * kNumberOfPacketsForTest; | 
| +    scoped_ptr<char[]> capture_data(new char[length]); | 
| +    ReadDataFromSpeechFile(capture_data.get(), length); | 
| +    const int16* data_ptr = reinterpret_cast<const int16*>(capture_data.get()); | 
| +    scoped_ptr<media::AudioBus> data_bus = media::AudioBus::Create( | 
| +        params_.channels(), params_.frames_per_buffer()); | 
| +    for (int i = 0; i < kNumberOfPacketsForTest; ++i) { | 
| +      data_bus->FromInterleaved(data_ptr, data_bus->frames(), 2); | 
| +      audio_processor->PushCaptureData(data_bus.get()); | 
| + | 
| +      // Feed data as render data to the processor, this does not cost anything | 
| +      // when the audio processing is off in the processor. | 
| +      audio_processor->PushRenderData( | 
| +          data_ptr, | 
| +          params_.sample_rate(), params_.channels(), | 
| +          params_.frames_per_buffer(), base::TimeDelta::FromMilliseconds(10)); | 
| + | 
| +      // Process and consume the data in the processor. | 
| +      int16* output = NULL; | 
| +      while(audio_processor->ProcessAndConsumeData( | 
| +          base::TimeDelta::FromMilliseconds(10), 255, false, &output)) { | 
| +        EXPECT_TRUE(output != NULL); | 
| +        EXPECT_EQ(audio_processor->OutputFormat().sample_rate(), | 
| +                  expected_output_sample_rate); | 
| +        EXPECT_EQ(audio_processor->OutputFormat().channels(), | 
| +                  expected_output_channels); | 
| +        EXPECT_EQ(audio_processor->OutputFormat().frames_per_buffer(), | 
| +                  expected_output_buffer_size); | 
| +      } | 
| + | 
| +      data_ptr += params_.frames_per_buffer() * params_.channels(); | 
| +    } | 
| +  } | 
| + | 
| +  media::AudioParameters params_; | 
| +}; | 
| + | 
| +TEST_F(WebRtcAudioProcessorTest, WithoutAudioProcessing) { | 
| +  // Setup the audio processor with empty constraint. | 
| +  RTCMediaConstraints constraints; | 
| +  WebRtcAudioProcessor audio_processor(&constraints); | 
| +  audio_processor.SetCaptureFormat(params_); | 
| +  EXPECT_FALSE(audio_processor.has_audio_processing()); | 
| + | 
| +  ProcessDataAndVerifyFormat(&audio_processor, | 
| +                             params_.sample_rate(), | 
| +                             params_.channels(), | 
| +                             params_.sample_rate() / 100); | 
| +} | 
| + | 
| +TEST_F(WebRtcAudioProcessorTest, WithAudioProcessing) { | 
| +  // Setup the audio processor with default constraint. | 
| +  RTCMediaConstraints constraints; | 
| +  ApplyFixedAudioConstraints(&constraints); | 
| +  WebRtcAudioProcessor audio_processor(&constraints); | 
| +  audio_processor.SetCaptureFormat(params_); | 
| +  EXPECT_TRUE(audio_processor.has_audio_processing()); | 
| + | 
| +  ProcessDataAndVerifyFormat(&audio_processor, | 
| +                             kAudioProcessingSampleRate, | 
| +                             kAudioProcessingNumberOfChannel, | 
| +                             kAudioProcessingSampleRate / 100); | 
| +} | 
| + | 
| +}  // namespace content | 
|  |