root/content/renderer/media/webrtc_audio_capturer_unittest.cc

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. OnData
  2. OnSetFormat
  3. params_
  4. EnableAudioTrackProcessing
  5. VerifyAudioParams
  6. TEST_F
  7. TEST_F

// Copyright 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "base/command_line.h"
#include "base/logging.h"
#include "content/public/common/content_switches.h"
#include "content/renderer/media/mock_media_constraint_factory.h"
#include "content/renderer/media/webrtc/webrtc_local_audio_track_adapter.h"
#include "content/renderer/media/webrtc_audio_capturer.h"
#include "content/renderer/media/webrtc_local_audio_track.h"
#include "media/audio/audio_parameters.h"
#include "media/base/audio_bus.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/WebKit/public/platform/WebMediaConstraints.h"

using ::testing::_;
using ::testing::AtLeast;

namespace content {

namespace {

class MockCapturerSource : public media::AudioCapturerSource {
 public:
  MockCapturerSource() {}
  MOCK_METHOD3(Initialize, void(const media::AudioParameters& params,
                                CaptureCallback* callback,
                                int session_id));
  MOCK_METHOD0(Start, void());
  MOCK_METHOD0(Stop, void());
  MOCK_METHOD1(SetVolume, void(double volume));
  MOCK_METHOD1(SetAutomaticGainControl, void(bool enable));

 protected:
  virtual ~MockCapturerSource() {}
};

class MockPeerConnectionAudioSink : public PeerConnectionAudioSink {
 public:
  MockPeerConnectionAudioSink() {}
  ~MockPeerConnectionAudioSink() {}
  virtual int OnData(const int16* audio_data, int sample_rate,
                     int number_of_channels, int number_of_frames,
                     const std::vector<int>& channels,
                     int audio_delay_milliseconds, int current_volume,
                     bool need_audio_processing, bool key_pressed) OVERRIDE {
    EXPECT_EQ(sample_rate, params_.sample_rate());
    EXPECT_EQ(number_of_channels, params_.channels());
    EXPECT_EQ(number_of_frames, params_.frames_per_buffer());
    OnDataCallback(audio_data, channels, audio_delay_milliseconds,
                   current_volume, need_audio_processing, key_pressed);
    return 0;
  }
  MOCK_METHOD6(OnDataCallback, void(const int16* audio_data,
                                    const std::vector<int>& channels,
                                    int audio_delay_milliseconds,
                                    int current_volume,
                                    bool need_audio_processing,
                                    bool key_pressed));
  virtual void OnSetFormat(const media::AudioParameters& params) OVERRIDE {
    params_ = params;
    FormatIsSet();
  }
  MOCK_METHOD0(FormatIsSet, void());

 private:
  media::AudioParameters params_;
};

}  // namespace

class WebRtcAudioCapturerTest : public testing::Test {
 protected:
  WebRtcAudioCapturerTest()
#if defined(OS_ANDROID)
      : params_(media::AudioParameters::AUDIO_PCM_LOW_LATENCY,
                media::CHANNEL_LAYOUT_STEREO, 48000, 16, 960) {
    // Android works with a buffer size bigger than 20ms.
#else
      : params_(media::AudioParameters::AUDIO_PCM_LOW_LATENCY,
                media::CHANNEL_LAYOUT_STEREO, 48000, 16, 128) {
#endif
  }

  void EnableAudioTrackProcessing() {
    CommandLine::ForCurrentProcess()->AppendSwitch(
        switches::kEnableAudioTrackProcessing);
  }

  void VerifyAudioParams(const blink::WebMediaConstraints& constraints,
                         bool need_audio_processing) {
    capturer_ = WebRtcAudioCapturer::CreateCapturer(
        -1, StreamDeviceInfo(MEDIA_DEVICE_AUDIO_CAPTURE,
                             "", "", params_.sample_rate(),
                             params_.channel_layout(),
                             params_.frames_per_buffer()),
        constraints, NULL);
    capturer_source_ = new MockCapturerSource();
    EXPECT_CALL(*capturer_source_.get(), Initialize(_, capturer_.get(), -1));
    capturer_->SetCapturerSourceForTesting(capturer_source_, params_);

    EXPECT_CALL(*capturer_source_.get(), SetAutomaticGainControl(true));
    EXPECT_CALL(*capturer_source_.get(), Start());
    scoped_refptr<WebRtcLocalAudioTrackAdapter> adapter(
        WebRtcLocalAudioTrackAdapter::Create(std::string(), NULL));
    track_.reset(new WebRtcLocalAudioTrack(adapter, capturer_, NULL));
    track_->Start();

    // Connect a mock sink to the track.
    scoped_ptr<MockPeerConnectionAudioSink> sink(
        new MockPeerConnectionAudioSink());
    track_->AddSink(sink.get());

    int delay_ms = 65;
    bool key_pressed = true;
    double volume = 0.9;

    // MaxVolume() in WebRtcAudioCapturer is hard-coded to return 255, we add
    // 0.5 to do the correct truncation like the production code does.
    int expected_volume_value = volume * capturer_->MaxVolume() + 0.5;
    scoped_ptr<media::AudioBus> audio_bus = media::AudioBus::Create(params_);
    audio_bus->Zero();

    media::AudioCapturerSource::CaptureCallback* callback =
        static_cast<media::AudioCapturerSource::CaptureCallback*>(capturer_);

    // Verify the sink is getting the correct values.
    EXPECT_CALL(*sink, FormatIsSet());
    EXPECT_CALL(*sink,
                OnDataCallback(_, _, delay_ms, expected_volume_value,
                               need_audio_processing, key_pressed));
    callback->Capture(audio_bus.get(), delay_ms, volume, key_pressed);

    // Verify the cached values in the capturer fits what we expect.
    base::TimeDelta cached_delay;
    int cached_volume = !expected_volume_value;
    bool cached_key_pressed = !key_pressed;
    capturer_->GetAudioProcessingParams(&cached_delay, &cached_volume,
                                        &cached_key_pressed);
    EXPECT_EQ(cached_delay.InMilliseconds(), delay_ms);
    EXPECT_EQ(cached_volume, expected_volume_value);
    EXPECT_EQ(cached_key_pressed, key_pressed);

    track_->RemoveSink(sink.get());
    EXPECT_CALL(*capturer_source_.get(), Stop());
    capturer_->Stop();
  }

  media::AudioParameters params_;
  scoped_refptr<MockCapturerSource> capturer_source_;
  scoped_refptr<WebRtcAudioCapturer> capturer_;
  scoped_ptr<WebRtcLocalAudioTrack> track_;
};

// Pass the delay value, volume and key_pressed info via capture callback, and
// those values should be correctly stored and passed to the track.
TEST_F(WebRtcAudioCapturerTest, VerifyAudioParams) {
  // Use constraints with default settings.
  blink::WebMediaConstraints constraints;
  VerifyAudioParams(constraints, true);
}

TEST_F(WebRtcAudioCapturerTest, VerifyAudioParamsWithAudioProcessing) {
  EnableAudioTrackProcessing();
  // Turn off the default constraints to verify that the sink will get packets
  // with a buffer size smaller than 10ms.
  MockMediaConstraintFactory constraint_factory;
  constraint_factory.DisableDefaultAudioConstraints();
  VerifyAudioParams(constraint_factory.CreateWebMediaConstraints(), false);
}

}  // namespace content

/* [<][>][^][v][top][bottom][index][help] */