15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch#include <vector>
6bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/environment.h"
890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "base/file_util.h"
990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "base/files/file_path.h"
1090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "base/path_service.h"
11868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/stringprintf.h"
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/test/test_timeouts.h"
132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "content/renderer/media/webrtc_audio_capturer.h"
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/renderer/media/webrtc_audio_device_impl.h"
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/renderer/media/webrtc_audio_renderer.h"
167d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#include "content/renderer/media/webrtc_local_audio_track.h"
172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "content/renderer/render_thread_impl.h"
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/test/webrtc_audio_device_test.h"
192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "media/audio/audio_manager_base.h"
202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "media/base/audio_hardware_config.h"
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "testing/gmock/include/gmock/gmock.h"
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "third_party/webrtc/voice_engine/include/voe_audio_processing.h"
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "third_party/webrtc/voice_engine/include/voe_base.h"
2490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "third_party/webrtc/voice_engine/include/voe_codec.h"
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "third_party/webrtc/voice_engine/include/voe_external_media.h"
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "third_party/webrtc/voice_engine/include/voe_file.h"
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "third_party/webrtc/voice_engine/include/voe_network.h"
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
29c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#if defined(OS_WIN)
30c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "base/win/windows_version.h"
31c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#endif
32c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)using media::AudioParameters;
3490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)using media::CHANNEL_LAYOUT_STEREO;
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using testing::_;
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using testing::AnyNumber;
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using testing::InvokeWithoutArgs;
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using testing::Return;
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using testing::StrEq;
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace content {
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const int kRenderViewId = 1;
462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// The number of packers that RunWebRtcLoopbackTimeTest() uses for measurement.
4890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)const int kNumberOfPacketsForLoopbackTest = 100;
4990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
5090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// The hardware latency we feed to WebRtc.
5190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)const int kHardwareLatencyInMs = 50;
5290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)scoped_ptr<media::AudioHardwareConfig> CreateRealHardwareConfig(
542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    media::AudioManager* manager) {
552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const AudioParameters output_parameters =
562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      manager->GetDefaultOutputStreamParameters();
572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const AudioParameters input_parameters =
582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      manager->GetInputStreamParameters(
592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          media::AudioManagerBase::kDefaultDeviceId);
6090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return make_scoped_ptr(new media::AudioHardwareConfig(
622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      input_parameters, output_parameters));
632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Return true if at least one element in the array matches |value|.
662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool FindElementInArray(const int* array, int size, int value) {
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return (std::find(&array[0], &array[0] + size, value) != &array[size]);
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This method returns false if a non-supported rate is detected on the
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// input or output side.
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// TODO(henrika): add support for automatic fallback to Windows Wave audio
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// if a non-supported rate is detected. It is probably better to detect
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// invalid audio settings by actually trying to open the audio streams instead
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// of relying on hard coded conditions.
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool HardwareSampleRatesAreValid() {
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // These are the currently supported hardware sample rates in both directions.
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The actual WebRTC client can limit these ranges further depending on
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // platform but this is the maximum range we support today.
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int valid_input_rates[] = {16000, 32000, 44100, 48000, 96000};
812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int valid_output_rates[] = {16000, 32000, 44100, 48000, 96000};
822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  media::AudioHardwareConfig* hardware_config =
842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      RenderThreadImpl::current()->GetAudioHardwareConfig();
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Verify the input sample rate.
872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int input_sample_rate = hardware_config->GetInputSampleRate();
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!FindElementInArray(valid_input_rates, arraysize(valid_input_rates),
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                          input_sample_rate)) {
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(WARNING) << "Non-supported input sample rate detected.";
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Given that the input rate was OK, verify the output rate as well.
962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int output_sample_rate = hardware_config->GetOutputSampleRate();
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!FindElementInArray(valid_output_rates, arraysize(valid_output_rates),
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                          output_sample_rate)) {
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(WARNING) << "Non-supported output sample rate detected.";
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
106bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch// Utility method which creates and initializes the audio capturer and adds it
107bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch// to WebRTC audio device. This method should be used in tests where
1082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// HardwareSampleRatesAreValid() has been called and returned true.
109bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdochbool CreateAndInitializeCapturer(WebRtcAudioDeviceImpl* webrtc_audio_device) {
110bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  DCHECK(webrtc_audio_device);
111bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  scoped_refptr<WebRtcAudioCapturer> capturer(
112bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch      WebRtcAudioCapturer::CreateCapturer());
1132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  media::AudioHardwareConfig* hardware_config =
1152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      RenderThreadImpl::current()->GetAudioHardwareConfig();
1162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Use native capture sample rate and channel configuration to get some
1182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // action in this test.
1192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int sample_rate = hardware_config->GetInputSampleRate();
1202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  media::ChannelLayout channel_layout =
1212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      hardware_config->GetInputChannelLayout();
122d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  if (!capturer->Initialize(kRenderViewId, channel_layout, sample_rate, 0, 1,
123d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)                            media::AudioManagerBase::kDefaultDeviceId, 0, 0,
124d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)                            media::AudioParameters::NO_EFFECTS)) {
1252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return false;
126bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  }
127bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch
128bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  // Add the capturer to the WebRtcAudioDeviceImpl.
129bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  webrtc_audio_device->AddAudioCapturer(capturer);
1302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return true;
1322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
134bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch// Create and start a local audio track. Starting the audio track will connect
135bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch// the audio track to the capturer and also start the source of the capturer.
136bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch// Also, connect the sink to the audio track.
137bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdochscoped_refptr<WebRtcLocalAudioTrack>
138bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben MurdochCreateAndStartLocalAudioTrack(WebRtcAudioCapturer* capturer,
139a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                              PeerConnectionAudioSink* sink) {
140bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  scoped_refptr<WebRtcLocalAudioTrack> local_audio_track(
141d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      WebRtcLocalAudioTrack::Create(std::string(), capturer, NULL, NULL, NULL));
142bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  local_audio_track->AddSink(sink);
143bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  local_audio_track->Start();
144bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  return local_audio_track;
145bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch}
146bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class WebRTCMediaProcessImpl : public webrtc::VoEMediaProcess {
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  explicit WebRTCMediaProcessImpl(base::WaitableEvent* event)
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      : event_(event),
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        channel_id_(-1),
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        type_(webrtc::kPlaybackPerChannel),
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        packet_size_(0),
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        sample_rate_(0),
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        channels_(0) {
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual ~WebRTCMediaProcessImpl() {}
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // TODO(henrika): Refactor in WebRTC and convert to Chrome coding style.
16090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  virtual void Process(int channel,
16190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                       webrtc::ProcessingTypes type,
162c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                       int16_t audio_10ms[],
16390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                       int length,
16490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                       int sampling_freq,
16590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                       bool is_stereo) OVERRIDE {
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    base::AutoLock auto_lock(lock_);
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    channel_id_ = channel;
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    type_ = type;
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    packet_size_ = length;
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    sample_rate_ = sampling_freq;
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    channels_ = (is_stereo ? 2 : 1);
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (event_) {
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Signal that a new callback has been received.
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      event_->Signal();
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int channel_id() const {
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    base::AutoLock auto_lock(lock_);
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return channel_id_;
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int type() const {
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    base::AutoLock auto_lock(lock_);
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return type_;
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int packet_size() const {
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    base::AutoLock auto_lock(lock_);
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return packet_size_;
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int sample_rate() const {
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    base::AutoLock auto_lock(lock_);
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return sample_rate_;
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::WaitableEvent* event_;
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int channel_id_;
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  webrtc::ProcessingTypes type_;
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int packet_size_;
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int sample_rate_;
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int channels_;
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  mutable base::Lock lock_;
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(WebRTCMediaProcessImpl);
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
209a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// TODO(xians): Use MediaStreamAudioSink.
210a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)class MockMediaStreamAudioSink : public PeerConnectionAudioSink {
21190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) public:
212a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  explicit MockMediaStreamAudioSink(base::WaitableEvent* event)
21390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      : event_(event) {
21490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    DCHECK(event_);
21590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  }
216a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  virtual ~MockMediaStreamAudioSink() {}
217a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
218a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // PeerConnectionAudioSink implementation.
219a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  virtual int OnData(const int16* audio_data,
220a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                     int sample_rate,
221a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                     int number_of_channels,
222a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                     int number_of_frames,
223a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                     const std::vector<int>& channels,
224a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                     int audio_delay_milliseconds,
225a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                     int current_volume,
226a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                     bool need_audio_processing,
227a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                     bool key_pressed) OVERRIDE {
22890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    // Signal that a callback has been received.
22990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    event_->Signal();
230bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch    return 0;
23190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  }
23290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
23390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // Set the format for the capture audio parameters.
234a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  virtual void OnSetFormat(
23590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      const media::AudioParameters& params) OVERRIDE {}
23690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
23790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) private:
23890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)   base::WaitableEvent* event_;
23990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
240a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)   DISALLOW_COPY_AND_ASSIGN(MockMediaStreamAudioSink);
24190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)};
24290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
24390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)class MockWebRtcAudioRendererSource : public WebRtcAudioRendererSource {
24490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) public:
24590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  explicit MockWebRtcAudioRendererSource(base::WaitableEvent* event)
24690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      : event_(event) {
24790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    DCHECK(event_);
24890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  }
24990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  virtual ~MockWebRtcAudioRendererSource() {}
25090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
25190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // WebRtcAudioRendererSource implementation.
25290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  virtual void RenderData(uint8* audio_data,
25390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                          int number_of_channels,
25490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                          int number_of_frames,
25590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                          int audio_delay_milliseconds) OVERRIDE {
25690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    // Signal that a callback has been received.
257868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    // Initialize the memory to zero to avoid uninitialized warning from
258868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    // Valgrind.
259868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    memset(audio_data, 0,
260868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)           sizeof(int16) * number_of_channels * number_of_frames);
26190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    event_->Signal();
26290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  }
26390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
26490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  virtual void SetRenderFormat(const media::AudioParameters& params) OVERRIDE {
26590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  }
26690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
26790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  virtual void RemoveAudioRenderer(WebRtcAudioRenderer* renderer) OVERRIDE {};
26890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
26990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) private:
27090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)   base::WaitableEvent* event_;
27190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
27290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)   DISALLOW_COPY_AND_ASSIGN(MockWebRtcAudioRendererSource);
27390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)};
27490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
27590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// Prints numerical information to stdout in a controlled format so we can plot
27690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// the result.
27790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void PrintPerfResultMs(const char* graph, const char* trace, float time_ms) {
27890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  std::string times;
27990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  base::StringAppendF(&times, "%.2f,", time_ms);
28090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  std::string result = base::StringPrintf(
28190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      "%sRESULT %s%s: %s= %s%s%s %s\n", "*", graph, "",
28290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      trace,  "[", times.c_str(), "]", "ms");
28390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
28490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  fflush(stdout);
28590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  printf("%s", result.c_str());
28690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  fflush(stdout);
28790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
28890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
28990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void ReadDataFromSpeechFile(char* data, int length) {
29090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  base::FilePath data_file;
29190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  CHECK(PathService::Get(base::DIR_SOURCE_ROOT, &data_file));
29290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  data_file =
29390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      data_file.Append(FILE_PATH_LITERAL("media"))
29490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)               .Append(FILE_PATH_LITERAL("test"))
29590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)               .Append(FILE_PATH_LITERAL("data"))
29690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)               .Append(FILE_PATH_LITERAL("speech_16b_stereo_48kHz.raw"));
2977dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  DCHECK(base::PathExists(data_file));
29890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  int64 data_file_size64 = 0;
299a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  DCHECK(base::GetFileSize(data_file, &data_file_size64));
300a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  EXPECT_EQ(length, base::ReadFile(data_file, data, length));
30190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  DCHECK(data_file_size64 > length);
30290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
30390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
30490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void SetChannelCodec(webrtc::VoiceEngine* engine, int channel) {
30590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // TODO(xians): move the codec as an input param to this function, and add
30690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // tests for different codecs, also add support to Android and IOS.
30790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#if !defined(OS_ANDROID) && !defined(OS_IOS)
30890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  webrtc::CodecInst isac;
30990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  strcpy(isac.plname, "ISAC");
31090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  isac.pltype = 104;
31190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  isac.pacsize = 960;
31290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  isac.plfreq = 32000;
31390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  isac.channels = 1;
31490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  isac.rate = -1;
31590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  ScopedWebRTCPtr<webrtc::VoECodec> codec(engine);
31690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  EXPECT_EQ(0, codec->SetRecPayloadType(channel, isac));
31790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  EXPECT_EQ(0, codec->SetSendCodec(channel, isac));
31890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#endif
31990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
32090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
32190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// Returns the time in millisecond for sending packets to WebRtc for encoding,
32290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// signal processing, decoding and receiving them back.
32390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)int RunWebRtcLoopbackTimeTest(media::AudioManager* manager,
32490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                              bool enable_apm) {
32590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  scoped_refptr<WebRtcAudioDeviceImpl> webrtc_audio_device(
32690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      new WebRtcAudioDeviceImpl());
32790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  WebRTCAutoDelete<webrtc::VoiceEngine> engine(webrtc::VoiceEngine::Create());
32890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  EXPECT_TRUE(engine.valid());
32990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  ScopedWebRTCPtr<webrtc::VoEBase> base(engine.get());
33090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  EXPECT_TRUE(base.valid());
331868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  int err = base->Init(webrtc_audio_device.get());
33290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  EXPECT_EQ(0, err);
33390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
334a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // We use OnSetFormat() and SetRenderFormat() to configure the audio
33590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // parameters so that this test can run on machine without hardware device.
33690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  const media::AudioParameters params = media::AudioParameters(
33790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      media::AudioParameters::AUDIO_PCM_LOW_LATENCY, CHANNEL_LAYOUT_STEREO,
33890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      48000, 2, 480);
339a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  PeerConnectionAudioSink* capturer_sink =
340a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      static_cast<PeerConnectionAudioSink*>(webrtc_audio_device.get());
34190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  WebRtcAudioRendererSource* renderer_source =
34290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      static_cast<WebRtcAudioRendererSource*>(webrtc_audio_device.get());
34390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  renderer_source->SetRenderFormat(params);
34490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
34590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // Turn on/off all the signal processing components like AGC, AEC and NS.
34690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  ScopedWebRTCPtr<webrtc::VoEAudioProcessing> audio_processing(engine.get());
34790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  EXPECT_TRUE(audio_processing.valid());
34890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  audio_processing->SetAgcStatus(enable_apm);
34990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  audio_processing->SetNsStatus(enable_apm);
35090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  audio_processing->SetEcStatus(enable_apm);
35190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
35290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // Create a voice channel for the WebRtc.
35390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  int channel = base->CreateChannel();
35490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  EXPECT_NE(-1, channel);
35590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  SetChannelCodec(engine.get(), channel);
35690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
35790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // Use our fake network transmission and start playout and recording.
35890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  ScopedWebRTCPtr<webrtc::VoENetwork> network(engine.get());
35990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  EXPECT_TRUE(network.valid());
36090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  scoped_ptr<WebRTCTransportImpl> transport(
36190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      new WebRTCTransportImpl(network.get()));
36290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  EXPECT_EQ(0, network->RegisterExternalTransport(channel, *transport.get()));
36390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  EXPECT_EQ(0, base->StartPlayout(channel));
36490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  EXPECT_EQ(0, base->StartSend(channel));
36590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
36690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // Read speech data from a speech test file.
367bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  const int input_packet_size =
368bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch      params.frames_per_buffer() * 2 * params.channels();
36990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  const int num_output_channels = webrtc_audio_device->output_channels();
37090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  const int output_packet_size = webrtc_audio_device->output_buffer_size() * 2 *
37190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      num_output_channels;
37290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  const size_t length = input_packet_size * kNumberOfPacketsForLoopbackTest;
37390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  scoped_ptr<char[]> capture_data(new char[length]);
37490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  ReadDataFromSpeechFile(capture_data.get(), length);
37590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
37690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // Start the timer.
37790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  scoped_ptr<uint8[]> buffer(new uint8[output_packet_size]);
37890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  base::Time start_time = base::Time::Now();
37990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  int delay = 0;
380bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  std::vector<int> voe_channels;
381bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  voe_channels.push_back(channel);
38290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  for (int j = 0; j < kNumberOfPacketsForLoopbackTest; ++j) {
38390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    // Sending fake capture data to WebRtc.
384a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    capturer_sink->OnData(
38590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        reinterpret_cast<int16*>(capture_data.get() + input_packet_size * j),
3863551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)        params.sample_rate(),
3873551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)        params.channels(),
3883551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)        params.frames_per_buffer(),
389a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        voe_channels,
3903551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)        kHardwareLatencyInMs,
3913551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)        1.0,
3923551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)        enable_apm,
3933551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)        false);
39490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
39590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    // Receiving data from WebRtc.
39690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    renderer_source->RenderData(
39790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        reinterpret_cast<uint8*>(buffer.get()),
39890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        num_output_channels, webrtc_audio_device->output_buffer_size(),
39990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        kHardwareLatencyInMs + delay);
40090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    delay = (base::Time::Now() - start_time).InMilliseconds();
40190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  }
40290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
40390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  int latency = (base::Time::Now() - start_time).InMilliseconds();
40490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
40590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  EXPECT_EQ(0, base->StopSend(channel));
40690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  EXPECT_EQ(0, base->StopPlayout(channel));
40790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  EXPECT_EQ(0, base->DeleteChannel(channel));
40890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  EXPECT_EQ(0, base->Terminate());
40990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
41090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  return latency;
41190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
41290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
41390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}  // namespace
4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Trivial test which verifies that one part of the test harness
4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// (HardwareSampleRatesAreValid()) works as intended for all supported
4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// hardware input sample rates.
418a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)TEST_F(MAYBE_WebRTCAudioDeviceTest, TestValidInputRates) {
4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int valid_rates[] = {16000, 32000, 44100, 48000, 96000};
4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Verify that we will approve all rates listed in |valid_rates|.
4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (size_t i = 0; i < arraysize(valid_rates); ++i) {
4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_TRUE(FindElementInArray(valid_rates, arraysize(valid_rates),
4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        valid_rates[i]));
4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Verify that any value outside the valid range results in negative
4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // find results.
4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int invalid_rates[] = {-1, 0, 8000, 11025, 22050, 192000};
4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (size_t i = 0; i < arraysize(invalid_rates); ++i) {
4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_FALSE(FindElementInArray(valid_rates, arraysize(valid_rates),
4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        invalid_rates[i]));
4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Trivial test which verifies that one part of the test harness
4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// (HardwareSampleRatesAreValid()) works as intended for all supported
4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// hardware output sample rates.
439a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)TEST_F(MAYBE_WebRTCAudioDeviceTest, TestValidOutputRates) {
4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int valid_rates[] = {44100, 48000, 96000};
4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Verify that we will approve all rates listed in |valid_rates|.
4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (size_t i = 0; i < arraysize(valid_rates); ++i) {
4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_TRUE(FindElementInArray(valid_rates, arraysize(valid_rates),
4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        valid_rates[i]));
4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Verify that any value outside the valid range results in negative
4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // find results.
4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int invalid_rates[] = {-1, 0, 8000, 11025, 22050, 32000, 192000};
4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (size_t i = 0; i < arraysize(invalid_rates); ++i) {
4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_FALSE(FindElementInArray(valid_rates, arraysize(valid_rates),
4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        invalid_rates[i]));
4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Basic test that instantiates and initializes an instance of
4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// WebRtcAudioDeviceImpl.
459a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)TEST_F(MAYBE_WebRTCAudioDeviceTest, Construct) {
460c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#if defined(OS_WIN)
461c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // This test crashes on Win XP bots.
462c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (base::win::GetVersion() <= base::win::VERSION_XP)
463c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return;
464c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#endif
465c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
4662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  AudioParameters input_params(
4672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      AudioParameters::AUDIO_PCM_LOW_LATENCY,
4682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      media::CHANNEL_LAYOUT_MONO,
4692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      48000,
4702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      16,
4712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      480);
4722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  AudioParameters output_params(
4742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      AudioParameters::AUDIO_PCM_LOW_LATENCY,
4752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      media::CHANNEL_LAYOUT_STEREO,
4762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      48000,
4772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      16,
4782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      480);
4792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  media::AudioHardwareConfig audio_config(input_params, output_params);
4812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SetAudioHardwareConfig(&audio_config);
4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_refptr<WebRtcAudioDeviceImpl> webrtc_audio_device(
4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      new WebRtcAudioDeviceImpl());
4852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WebRTCAutoDelete<webrtc::VoiceEngine> engine(webrtc::VoiceEngine::Create());
4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_TRUE(engine.valid());
4885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ScopedWebRTCPtr<webrtc::VoEBase> base(engine.get());
490868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  int err = base->Init(webrtc_audio_device.get());
491bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  EXPECT_TRUE(CreateAndInitializeCapturer(webrtc_audio_device.get()));
4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(0, err);
4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(0, base->Terminate());
4945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Verify that a call to webrtc::VoEBase::StartPlayout() starts audio output
4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// with the correct set of parameters. A WebRtcAudioDeviceImpl instance will
4985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// be utilized to implement the actual audio path. The test registers a
4995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// webrtc::VoEExternalMedia implementation to hijack the output audio and
5005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// verify that streaming starts correctly.
50158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// TODO(henrika): include on Android as well as soon as alla race conditions
50258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// in OpenSLES are resolved.
50358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#if defined(OS_ANDROID)
50458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#define MAYBE_StartPlayout DISABLED_StartPlayout
50558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#else
50658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#define MAYBE_StartPlayout StartPlayout
50758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#endif
50858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)TEST_F(MAYBE_WebRTCAudioDeviceTest, MAYBE_StartPlayout) {
5095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!has_output_devices_) {
5105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(WARNING) << "No output device detected.";
5115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
5125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<media::AudioHardwareConfig> config =
5152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      CreateRealHardwareConfig(audio_manager_.get());
5162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SetAudioHardwareConfig(config.get());
5175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!HardwareSampleRatesAreValid())
5195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
5205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WebRTCAutoDelete<webrtc::VoiceEngine> engine(webrtc::VoiceEngine::Create());
5225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_TRUE(engine.valid());
5235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ScopedWebRTCPtr<webrtc::VoEBase> base(engine.get());
5245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_TRUE(base.valid());
52558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
52658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  scoped_refptr<WebRtcAudioDeviceImpl> webrtc_audio_device(
52758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      new WebRtcAudioDeviceImpl());
528868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  int err = base->Init(webrtc_audio_device.get());
5295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(0, err);
5305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ScopedWebRTCPtr<webrtc::VoEExternalMedia> external_media(engine.get());
5325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_TRUE(external_media.valid());
5335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::WaitableEvent event(false, false);
5345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<WebRTCMediaProcessImpl> media_process(
5355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      new WebRTCMediaProcessImpl(&event));
53658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  int ch = base->CreateChannel();
53758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  EXPECT_NE(-1, ch);
5385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(0, external_media->RegisterExternalMediaProcessing(
5395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ch, webrtc::kPlaybackPerChannel, *media_process.get()));
5405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(0, base->StartPlayout(ch));
54258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  scoped_refptr<WebRtcAudioRenderer> renderer(
54358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      CreateDefaultWebRtcAudioRenderer(kRenderViewId));
54458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  scoped_refptr<MediaStreamAudioRenderer> proxy(
54558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      renderer->CreateSharedAudioRendererProxy());
54658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  EXPECT_TRUE(webrtc_audio_device->SetAudioRenderer(renderer.get()));
54758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  proxy->Start();
54858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  proxy->Play();
5495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(event.TimedWait(TestTimeouts::action_timeout()));
5515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WaitForIOThreadCompletion();
5525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_TRUE(webrtc_audio_device->Playing());
5542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_FALSE(webrtc_audio_device->Recording());
5555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(ch, media_process->channel_id());
5565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(webrtc::kPlaybackPerChannel, media_process->type());
5575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(80, media_process->packet_size());
5585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(8000, media_process->sample_rate());
5595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(0, external_media->DeRegisterExternalMediaProcessing(
5615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ch, webrtc::kPlaybackPerChannel));
5625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(0, base->StopPlayout(ch));
56358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  proxy->Stop();
5645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(0, base->DeleteChannel(ch));
5655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(0, base->Terminate());
5665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Verify that a call to webrtc::VoEBase::StartRecording() starts audio input
5695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// with the correct set of parameters. A WebRtcAudioDeviceImpl instance will
5705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// be utilized to implement the actual audio path. The test registers a
5715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// webrtc::VoEExternalMedia implementation to hijack the input audio and
5725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// verify that streaming starts correctly. An external transport implementation
5735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// is also required to ensure that "sending" can start without actually trying
5745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// to send encoded packets to the network. Our main interest here is to ensure
5755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// that the audio capturing starts as it should.
5765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Disabled when running headless since the bots don't have the required config.
5772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// TODO(leozwang): Because ExternalMediaProcessing is disabled in webrtc,
5792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// disable this unit test on Android for now.
5802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#if defined(OS_ANDROID)
5812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#define MAYBE_StartRecording DISABLED_StartRecording
582eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#elif defined(OS_LINUX) && !defined(OS_CHROMEOS) && defined(ARCH_CPU_ARM_FAMILY)
583eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// This test is failing on ARM linux: http://crbug.com/238490
584eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#define MAYBE_StartRecording DISABLED_StartRecording
5852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#else
5862385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch// Flakily hangs on all other platforms as well: crbug.com/268376.
5872385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch// When the flakiness has been fixed, you probably want to leave it disabled
5882385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch// on the above platforms.
5892385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch#define MAYBE_StartRecording DISABLED_StartRecording
5902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#endif
5912385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch
592a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)TEST_F(MAYBE_WebRTCAudioDeviceTest, MAYBE_StartRecording) {
5935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!has_input_devices_ || !has_output_devices_) {
5945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(WARNING) << "Missing audio devices.";
5955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
5965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<media::AudioHardwareConfig> config =
5992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      CreateRealHardwareConfig(audio_manager_.get());
6002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SetAudioHardwareConfig(config.get());
6015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!HardwareSampleRatesAreValid())
6035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
6045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // TODO(tommi): extend MediaObserver and MockMediaObserver with support
6065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // for new interfaces, like OnSetAudioStreamRecording(). When done, add
6075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // EXPECT_CALL() macros here.
6085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_refptr<WebRtcAudioDeviceImpl> webrtc_audio_device(
6095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      new WebRtcAudioDeviceImpl());
6105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WebRTCAutoDelete<webrtc::VoiceEngine> engine(webrtc::VoiceEngine::Create());
6125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_TRUE(engine.valid());
6135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ScopedWebRTCPtr<webrtc::VoEBase> base(engine.get());
6155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_TRUE(base.valid());
616868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  int err = base->Init(webrtc_audio_device.get());
6175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(0, err);
6185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int ch = base->CreateChannel();
6205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_NE(-1, ch);
6215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ScopedWebRTCPtr<webrtc::VoEExternalMedia> external_media(engine.get());
6235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_TRUE(external_media.valid());
6245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::WaitableEvent event(false, false);
6265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<WebRTCMediaProcessImpl> media_process(
6275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      new WebRTCMediaProcessImpl(&event));
6285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(0, external_media->RegisterExternalMediaProcessing(
6295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ch, webrtc::kRecordingPerChannel, *media_process.get()));
6305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We must add an external transport implementation to be able to start
6325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // recording without actually sending encoded packets to the network. All
6335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // we want to do here is to verify that audio capturing starts as it should.
6345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ScopedWebRTCPtr<webrtc::VoENetwork> network(engine.get());
6355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<WebRTCTransportImpl> transport(
6365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      new WebRTCTransportImpl(network.get()));
6375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(0, network->RegisterExternalTransport(ch, *transport.get()));
6385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(0, base->StartSend(ch));
6395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
640bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  // Create and initialize the capturer which starts the source of the data
641bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  // flow.
642bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  EXPECT_TRUE(CreateAndInitializeCapturer(webrtc_audio_device.get()));
643bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch
644bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  // Create and start a local audio track which is bridging the data flow
645bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  // between the capturer and WebRtcAudioDeviceImpl.
646bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  scoped_refptr<WebRtcLocalAudioTrack> local_audio_track(
647bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch      CreateAndStartLocalAudioTrack(webrtc_audio_device->GetDefaultCapturer(),
648bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch                                    webrtc_audio_device));
649bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  // connect the VoE voice channel to the audio track
650bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  static_cast<webrtc::AudioTrackInterface*>(local_audio_track.get())->
651bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch      GetRenderer()->AddChannel(ch);
652bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch
653bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  // Verify we get the data flow.
6545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(event.TimedWait(TestTimeouts::action_timeout()));
6555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WaitForIOThreadCompletion();
6565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_FALSE(webrtc_audio_device->Playing());
6582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_TRUE(webrtc_audio_device->Recording());
6595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(ch, media_process->channel_id());
6605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(webrtc::kRecordingPerChannel, media_process->type());
6615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(80, media_process->packet_size());
6625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(8000, media_process->sample_rate());
6635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(0, external_media->DeRegisterExternalMediaProcessing(
6655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ch, webrtc::kRecordingPerChannel));
6665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(0, base->StopSend(ch));
6675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
668f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  webrtc_audio_device->GetDefaultCapturer()->Stop();
6695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(0, base->DeleteChannel(ch));
6705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(0, base->Terminate());
6715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Uses WebRtcAudioDeviceImpl to play a local wave file.
67458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// TODO(henrika): include on Android as well as soon as alla race conditions
67558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// in OpenSLES are resolved.
67658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#if defined(OS_ANDROID)
67758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#define MAYBE_PlayLocalFile DISABLED_PlayLocalFile
67858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#else
67958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#define MAYBE_PlayLocalFile PlayLocalFile
68058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#endif
68158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)TEST_F(MAYBE_WebRTCAudioDeviceTest, MAYBE_PlayLocalFile) {
6825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!has_output_devices_) {
6835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(WARNING) << "No output device detected.";
6845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
6855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string file_path(
6885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      GetTestDataPath(FILE_PATH_LITERAL("speechmusic_mono_16kHz.pcm")));
6895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<media::AudioHardwareConfig> config =
6912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      CreateRealHardwareConfig(audio_manager_.get());
6922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SetAudioHardwareConfig(config.get());
6935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!HardwareSampleRatesAreValid())
6955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
6965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WebRTCAutoDelete<webrtc::VoiceEngine> engine(webrtc::VoiceEngine::Create());
6985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_TRUE(engine.valid());
6995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ScopedWebRTCPtr<webrtc::VoEBase> base(engine.get());
7005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_TRUE(base.valid());
70158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
70258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  scoped_refptr<WebRtcAudioDeviceImpl> webrtc_audio_device(
70358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      new WebRtcAudioDeviceImpl());
704868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  int err = base->Init(webrtc_audio_device.get());
7055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(0, err);
7065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int ch = base->CreateChannel();
7075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_NE(-1, ch);
7085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(0, base->StartPlayout(ch));
70958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  scoped_refptr<WebRtcAudioRenderer> renderer(
71058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      CreateDefaultWebRtcAudioRenderer(kRenderViewId));
71158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  scoped_refptr<MediaStreamAudioRenderer> proxy(
71258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      renderer->CreateSharedAudioRendererProxy());
71358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  EXPECT_TRUE(webrtc_audio_device->SetAudioRenderer(renderer.get()));
71458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  proxy->Start();
71558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  proxy->Play();
7165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ScopedWebRTCPtr<webrtc::VoEFile> file(engine.get());
7185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_TRUE(file.valid());
7195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int duration = 0;
7205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(0, file->GetFileDuration(file_path.c_str(), duration,
7215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                     webrtc::kFileFormatPcm16kHzFile));
7225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_NE(0, duration);
7235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(0, file->StartPlayingFileLocally(ch, file_path.c_str(), false,
7255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                             webrtc::kFileFormatPcm16kHzFile));
7265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Play 2 seconds worth of audio and then quit.
7285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  message_loop_.PostDelayedTask(FROM_HERE,
729c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                base::MessageLoop::QuitClosure(),
73058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                                base::TimeDelta::FromSeconds(2));
7315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  message_loop_.Run();
7325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
73358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  proxy->Stop();
7345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(0, base->StopSend(ch));
7355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(0, base->StopPlayout(ch));
7365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(0, base->DeleteChannel(ch));
7375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(0, base->Terminate());
7385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Uses WebRtcAudioDeviceImpl to play out recorded audio in loopback.
7415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// An external transport implementation is utilized to feed back RTP packets
7425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// which are recorded, encoded, packetized into RTP packets and finally
7435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// "transmitted". The RTP packets are then fed back into the VoiceEngine
7445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// where they are decoded and played out on the default audio output device.
7455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Disabled when running headless since the bots don't have the required config.
7465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// TODO(henrika): improve quality by using a wideband codec, enabling noise-
7475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// suppressions etc.
7482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// FullDuplexAudioWithAGC is flaky on Android, disable it for now.
749bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch// Also flakily hangs on Windows: crbug.com/269348.
750bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch#if defined(OS_ANDROID) || defined(OS_WIN)
7512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#define MAYBE_FullDuplexAudioWithAGC DISABLED_FullDuplexAudioWithAGC
7522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#else
7532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#define MAYBE_FullDuplexAudioWithAGC FullDuplexAudioWithAGC
7542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#endif
755a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)TEST_F(MAYBE_WebRTCAudioDeviceTest, MAYBE_FullDuplexAudioWithAGC) {
7565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!has_output_devices_ || !has_input_devices_) {
7575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(WARNING) << "Missing audio devices.";
7585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
7595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<media::AudioHardwareConfig> config =
7622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      CreateRealHardwareConfig(audio_manager_.get());
7632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SetAudioHardwareConfig(config.get());
7645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!HardwareSampleRatesAreValid())
7665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
7675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WebRTCAutoDelete<webrtc::VoiceEngine> engine(webrtc::VoiceEngine::Create());
7695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_TRUE(engine.valid());
7705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ScopedWebRTCPtr<webrtc::VoEBase> base(engine.get());
7715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_TRUE(base.valid());
77258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
77358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  scoped_refptr<WebRtcAudioDeviceImpl> webrtc_audio_device(
77458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      new WebRtcAudioDeviceImpl());
775868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  int err = base->Init(webrtc_audio_device.get());
7765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(0, err);
7775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ScopedWebRTCPtr<webrtc::VoEAudioProcessing> audio_processing(engine.get());
7795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_TRUE(audio_processing.valid());
7802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#if defined(OS_ANDROID)
7812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // On Android, by default AGC is off.
7822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  bool enabled = true;
7832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  webrtc::AgcModes agc_mode = webrtc::kAgcDefault;
7842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(0, audio_processing->GetAgcStatus(enabled, agc_mode));
7852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_FALSE(enabled);
7862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#else
7875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool enabled = false;
7882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  webrtc::AgcModes agc_mode = webrtc::kAgcDefault;
7895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(0, audio_processing->GetAgcStatus(enabled, agc_mode));
7905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(enabled);
7915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(agc_mode, webrtc::kAgcAdaptiveAnalog);
7922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#endif
7935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int ch = base->CreateChannel();
7955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_NE(-1, ch);
7965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
797bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  EXPECT_TRUE(CreateAndInitializeCapturer(webrtc_audio_device.get()));
798bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  scoped_refptr<WebRtcLocalAudioTrack> local_audio_track(
799bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch      CreateAndStartLocalAudioTrack(webrtc_audio_device->GetDefaultCapturer(),
800bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch                                    webrtc_audio_device));
801bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  // connect the VoE voice channel to the audio track
802bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  static_cast<webrtc::AudioTrackInterface*>(local_audio_track.get())->
803bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch      GetRenderer()->AddChannel(ch);
804bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch
8055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ScopedWebRTCPtr<webrtc::VoENetwork> network(engine.get());
8065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_TRUE(network.valid());
8075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<WebRTCTransportImpl> transport(
8085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      new WebRTCTransportImpl(network.get()));
8095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(0, network->RegisterExternalTransport(ch, *transport.get()));
8105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(0, base->StartPlayout(ch));
8115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(0, base->StartSend(ch));
81258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  scoped_refptr<WebRtcAudioRenderer> renderer(
81358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      CreateDefaultWebRtcAudioRenderer(kRenderViewId));
81458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  scoped_refptr<MediaStreamAudioRenderer> proxy(
81558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      renderer->CreateSharedAudioRendererProxy());
81658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  EXPECT_TRUE(webrtc_audio_device->SetAudioRenderer(renderer.get()));
81758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  proxy->Start();
81858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  proxy->Play();
8195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
820f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  VLOG(0) << ">> You should now be able to hear yourself in loopback...";
8215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  message_loop_.PostDelayedTask(FROM_HERE,
822c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                base::MessageLoop::QuitClosure(),
8235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                base::TimeDelta::FromSeconds(2));
8245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  message_loop_.Run();
8255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
826f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  webrtc_audio_device->GetDefaultCapturer()->Stop();
82758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  proxy->Stop();
8285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(0, base->StopSend(ch));
8295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(0, base->StopPlayout(ch));
8305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(0, base->DeleteChannel(ch));
8325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(0, base->Terminate());
8335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8357d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)// Test times out on bots, see http://crbug.com/247447
836a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)TEST_F(MAYBE_WebRTCAudioDeviceTest, DISABLED_WebRtcRecordingSetupTime) {
83790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (!has_input_devices_) {
83890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    LOG(WARNING) << "Missing audio capture devices.";
83990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    return;
84090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  }
84190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
84290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  scoped_ptr<media::AudioHardwareConfig> config =
84390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      CreateRealHardwareConfig(audio_manager_.get());
84490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  SetAudioHardwareConfig(config.get());
84590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
84690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (!HardwareSampleRatesAreValid())
84790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    return;
84890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
84990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  scoped_refptr<WebRtcAudioDeviceImpl> webrtc_audio_device(
85090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      new WebRtcAudioDeviceImpl());
85190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
85290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  WebRTCAutoDelete<webrtc::VoiceEngine> engine(webrtc::VoiceEngine::Create());
85390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  ASSERT_TRUE(engine.valid());
85490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
85590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  ScopedWebRTCPtr<webrtc::VoEBase> base(engine.get());
85690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  ASSERT_TRUE(base.valid());
857868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  int err = base->Init(webrtc_audio_device.get());
85890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  ASSERT_EQ(0, err);
85990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
860bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  int ch = base->CreateChannel();
861bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  EXPECT_NE(-1, ch);
86290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
863bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  EXPECT_TRUE(CreateAndInitializeCapturer(webrtc_audio_device.get()));
86490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  base::WaitableEvent event(false, false);
865a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  scoped_ptr<MockMediaStreamAudioSink> sink(
866a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      new MockMediaStreamAudioSink(&event));
86790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
868bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  // Create and start a local audio track. Starting the audio track will connect
869bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  // the audio track to the capturer and also start the source of the capturer.
870bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  scoped_refptr<WebRtcLocalAudioTrack> local_audio_track(
871bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch      CreateAndStartLocalAudioTrack(
872bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch          webrtc_audio_device->GetDefaultCapturer().get(), sink.get()));
873bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch
874bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  // connect the VoE voice channel to the audio track.
875bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  static_cast<webrtc::AudioTrackInterface*>(local_audio_track.get())->
876bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch      GetRenderer()->AddChannel(ch);
87790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
87890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  base::Time start_time = base::Time::Now();
87990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  EXPECT_EQ(0, base->StartSend(ch));
88090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
88190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  EXPECT_TRUE(event.TimedWait(TestTimeouts::action_timeout()));
88290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  int delay = (base::Time::Now() - start_time).InMilliseconds();
88390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  PrintPerfResultMs("webrtc_recording_setup_c", "t", delay);
88490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
885f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  webrtc_audio_device->GetDefaultCapturer()->Stop();
88690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  EXPECT_EQ(0, base->StopSend(ch));
88790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  EXPECT_EQ(0, base->DeleteChannel(ch));
88890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  EXPECT_EQ(0, base->Terminate());
88990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
89090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
89158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
89258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// TODO(henrika): include on Android as well as soon as alla race conditions
89358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// in OpenSLES are resolved.
89458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#if defined(OS_ANDROID)
89558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#define MAYBE_WebRtcPlayoutSetupTime DISABLED_WebRtcPlayoutSetupTime
89658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#else
89758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#define MAYBE_WebRtcPlayoutSetupTime WebRtcPlayoutSetupTime
89858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#endif
89958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)TEST_F(MAYBE_WebRTCAudioDeviceTest, MAYBE_WebRtcPlayoutSetupTime) {
90090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (!has_output_devices_) {
90190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    LOG(WARNING) << "No output device detected.";
90290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    return;
90390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  }
90490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
90590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  scoped_ptr<media::AudioHardwareConfig> config =
90690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      CreateRealHardwareConfig(audio_manager_.get());
90790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  SetAudioHardwareConfig(config.get());
90890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
90990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (!HardwareSampleRatesAreValid())
91090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    return;
91190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
91290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  base::WaitableEvent event(false, false);
91390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  scoped_ptr<MockWebRtcAudioRendererSource> renderer_source(
91490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      new MockWebRtcAudioRendererSource(&event));
91558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
91658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  scoped_refptr<WebRtcAudioRenderer> renderer(
91758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      CreateDefaultWebRtcAudioRenderer(kRenderViewId));
91890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  renderer->Initialize(renderer_source.get());
91958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  scoped_refptr<MediaStreamAudioRenderer> proxy(
92058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      renderer->CreateSharedAudioRendererProxy());
92158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  proxy->Start();
92290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
92390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // Start the timer and playout.
92490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  base::Time start_time = base::Time::Now();
92558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  proxy->Play();
92690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  EXPECT_TRUE(event.TimedWait(TestTimeouts::action_timeout()));
92790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  int delay = (base::Time::Now() - start_time).InMilliseconds();
92890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  PrintPerfResultMs("webrtc_playout_setup_c", "t", delay);
92990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
93058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  proxy->Stop();
93190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
93290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
933868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#if defined(OS_LINUX) && !defined(OS_CHROMEOS) && defined(ARCH_CPU_ARM_FAMILY)
934868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// Timing out on ARM linux bot: http://crbug.com/238490
935868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#define MAYBE_WebRtcLoopbackTimeWithoutSignalProcessing \
936868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        DISABLED_WebRtcLoopbackTimeWithoutSignalProcessing
937868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#else
938868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#define MAYBE_WebRtcLoopbackTimeWithoutSignalProcessing \
939868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        WebRtcLoopbackTimeWithoutSignalProcessing
940868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#endif
941868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
942a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)TEST_F(MAYBE_WebRTCAudioDeviceTest,
943a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)       MAYBE_WebRtcLoopbackTimeWithoutSignalProcessing) {
944f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#if defined(OS_WIN)
945f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // This test hangs on WinXP: see http://crbug.com/318189.
946f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  if (base::win::GetVersion() <= base::win::VERSION_XP) {
947f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    LOG(WARNING) << "Test disabled due to the test hangs on WinXP.";
948f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    return;
949f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  }
950f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#endif
95190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  int latency = RunWebRtcLoopbackTimeTest(audio_manager_.get(), false);
95290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  PrintPerfResultMs("webrtc_loopback_without_sigal_processing (100 packets)",
95390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                    "t", latency);
95490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
95590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
956868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#if defined(OS_LINUX) && !defined(OS_CHROMEOS) && defined(ARCH_CPU_ARM_FAMILY)
957868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// Timing out on ARM linux bot: http://crbug.com/238490
958868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#define MAYBE_WebRtcLoopbackTimeWithSignalProcessing \
959868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        DISABLED_WebRtcLoopbackTimeWithSignalProcessing
960868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#else
961868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#define MAYBE_WebRtcLoopbackTimeWithSignalProcessing \
962868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        WebRtcLoopbackTimeWithSignalProcessing
963868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#endif
964868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
965a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)TEST_F(MAYBE_WebRTCAudioDeviceTest,
966a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)       MAYBE_WebRtcLoopbackTimeWithSignalProcessing) {
967f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#if defined(OS_WIN)
968f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // This test hangs on WinXP: see http://crbug.com/318189.
969f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  if (base::win::GetVersion() <= base::win::VERSION_XP) {
970f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    LOG(WARNING) << "Test disabled due to the test hangs on WinXP.";
971f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    return;
972f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  }
973f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#endif
97490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  int latency = RunWebRtcLoopbackTimeTest(audio_manager_.get(), true);
97590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  PrintPerfResultMs("webrtc_loopback_with_signal_processing (100 packets)",
97690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                    "t", latency);
97790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
97890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
9795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace content
980