Home | History | Annotate | Download | only in media
      1 // Copyright 2013 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include "base/command_line.h"
      6 #include "base/logging.h"
      7 #include "content/public/common/content_switches.h"
      8 #include "content/renderer/media/mock_media_constraint_factory.h"
      9 #include "content/renderer/media/webrtc/webrtc_local_audio_track_adapter.h"
     10 #include "content/renderer/media/webrtc_audio_capturer.h"
     11 #include "content/renderer/media/webrtc_local_audio_track.h"
     12 #include "media/audio/audio_parameters.h"
     13 #include "media/base/audio_bus.h"
     14 #include "testing/gmock/include/gmock/gmock.h"
     15 #include "testing/gtest/include/gtest/gtest.h"
     16 #include "third_party/WebKit/public/platform/WebMediaConstraints.h"
     17 
     18 using ::testing::_;
     19 using ::testing::AtLeast;
     20 
     21 namespace content {
     22 
     23 namespace {
     24 
     25 class MockCapturerSource : public media::AudioCapturerSource {
     26  public:
     27   MockCapturerSource() {}
     28   MOCK_METHOD3(Initialize, void(const media::AudioParameters& params,
     29                                 CaptureCallback* callback,
     30                                 int session_id));
     31   MOCK_METHOD0(Start, void());
     32   MOCK_METHOD0(Stop, void());
     33   MOCK_METHOD1(SetVolume, void(double volume));
     34   MOCK_METHOD1(SetAutomaticGainControl, void(bool enable));
     35 
     36  protected:
     37   virtual ~MockCapturerSource() {}
     38 };
     39 
     40 class MockPeerConnectionAudioSink : public PeerConnectionAudioSink {
     41  public:
     42   MockPeerConnectionAudioSink() {}
     43   ~MockPeerConnectionAudioSink() {}
     44   virtual int OnData(const int16* audio_data, int sample_rate,
     45                      int number_of_channels, int number_of_frames,
     46                      const std::vector<int>& channels,
     47                      int audio_delay_milliseconds, int current_volume,
     48                      bool need_audio_processing, bool key_pressed) OVERRIDE {
     49     EXPECT_EQ(sample_rate, params_.sample_rate());
     50     EXPECT_EQ(number_of_channels, params_.channels());
     51     EXPECT_EQ(number_of_frames, params_.frames_per_buffer());
     52     OnDataCallback(audio_data, channels, audio_delay_milliseconds,
     53                    current_volume, need_audio_processing, key_pressed);
     54     return 0;
     55   }
     56   MOCK_METHOD6(OnDataCallback, void(const int16* audio_data,
     57                                     const std::vector<int>& channels,
     58                                     int audio_delay_milliseconds,
     59                                     int current_volume,
     60                                     bool need_audio_processing,
     61                                     bool key_pressed));
     62   virtual void OnSetFormat(const media::AudioParameters& params) OVERRIDE {
     63     params_ = params;
     64     FormatIsSet();
     65   }
     66   MOCK_METHOD0(FormatIsSet, void());
     67 
     68  private:
     69   media::AudioParameters params_;
     70 };
     71 
     72 }  // namespace
     73 
     74 class WebRtcAudioCapturerTest : public testing::Test {
     75  protected:
     76   WebRtcAudioCapturerTest()
     77 #if defined(OS_ANDROID)
     78       : params_(media::AudioParameters::AUDIO_PCM_LOW_LATENCY,
     79                 media::CHANNEL_LAYOUT_STEREO, 48000, 16, 960) {
     80     // Android works with a buffer size bigger than 20ms.
     81 #else
     82       : params_(media::AudioParameters::AUDIO_PCM_LOW_LATENCY,
     83                 media::CHANNEL_LAYOUT_STEREO, 48000, 16, 128) {
     84 #endif
     85   }
     86 
     87   void DisableAudioTrackProcessing() {
     88     CommandLine::ForCurrentProcess()->AppendSwitch(
     89         switches::kDisableAudioTrackProcessing);
     90   }
     91 
     92   void VerifyAudioParams(const blink::WebMediaConstraints& constraints,
     93                          bool need_audio_processing) {
     94     capturer_ = WebRtcAudioCapturer::CreateCapturer(
     95         -1, StreamDeviceInfo(MEDIA_DEVICE_AUDIO_CAPTURE,
     96                              "", "", params_.sample_rate(),
     97                              params_.channel_layout(),
     98                              params_.frames_per_buffer()),
     99         constraints, NULL, NULL);
    100     capturer_source_ = new MockCapturerSource();
    101     EXPECT_CALL(*capturer_source_.get(), Initialize(_, capturer_.get(), -1));
    102     EXPECT_CALL(*capturer_source_.get(), SetAutomaticGainControl(true));
    103     EXPECT_CALL(*capturer_source_.get(), Start());
    104     capturer_->SetCapturerSourceForTesting(capturer_source_, params_);
    105 
    106     scoped_refptr<WebRtcLocalAudioTrackAdapter> adapter(
    107         WebRtcLocalAudioTrackAdapter::Create(std::string(), NULL));
    108     track_.reset(new WebRtcLocalAudioTrack(adapter.get(), capturer_, NULL));
    109     track_->Start();
    110 
    111     // Connect a mock sink to the track.
    112     scoped_ptr<MockPeerConnectionAudioSink> sink(
    113         new MockPeerConnectionAudioSink());
    114     track_->AddSink(sink.get());
    115 
    116     int delay_ms = 65;
    117     bool key_pressed = true;
    118     double volume = 0.9;
    119 
    120     // MaxVolume() in WebRtcAudioCapturer is hard-coded to return 255, we add
    121     // 0.5 to do the correct truncation like the production code does.
    122     int expected_volume_value = volume * capturer_->MaxVolume() + 0.5;
    123     scoped_ptr<media::AudioBus> audio_bus = media::AudioBus::Create(params_);
    124     audio_bus->Zero();
    125 
    126     media::AudioCapturerSource::CaptureCallback* callback =
    127         static_cast<media::AudioCapturerSource::CaptureCallback*>(
    128             capturer_.get());
    129 
    130     // Verify the sink is getting the correct values.
    131     EXPECT_CALL(*sink, FormatIsSet());
    132     EXPECT_CALL(*sink,
    133                 OnDataCallback(_, _, delay_ms, expected_volume_value,
    134                                need_audio_processing, key_pressed))
    135         .Times(AtLeast(1));
    136     callback->Capture(audio_bus.get(), delay_ms, volume, key_pressed);
    137 
    138     // Verify the cached values in the capturer fits what we expect.
    139     base::TimeDelta cached_delay;
    140     int cached_volume = !expected_volume_value;
    141     bool cached_key_pressed = !key_pressed;
    142     capturer_->GetAudioProcessingParams(&cached_delay, &cached_volume,
    143                                         &cached_key_pressed);
    144     EXPECT_EQ(cached_delay.InMilliseconds(), delay_ms);
    145     EXPECT_EQ(cached_volume, expected_volume_value);
    146     EXPECT_EQ(cached_key_pressed, key_pressed);
    147 
    148     track_->RemoveSink(sink.get());
    149     EXPECT_CALL(*capturer_source_.get(), Stop());
    150     capturer_->Stop();
    151   }
    152 
    153   media::AudioParameters params_;
    154   scoped_refptr<MockCapturerSource> capturer_source_;
    155   scoped_refptr<WebRtcAudioCapturer> capturer_;
    156   scoped_ptr<WebRtcLocalAudioTrack> track_;
    157 };
    158 
    159 // Pass the delay value, volume and key_pressed info via capture callback, and
    160 // those values should be correctly stored and passed to the track.
    161 TEST_F(WebRtcAudioCapturerTest, VerifyAudioParamsWithoutAudioProcessing) {
    162   DisableAudioTrackProcessing();
    163   // Use constraints with default settings.
    164   MockMediaConstraintFactory constraint_factory;
    165   VerifyAudioParams(constraint_factory.CreateWebMediaConstraints(), true);
    166 }
    167 
    168 TEST_F(WebRtcAudioCapturerTest, VerifyAudioParamsWithAudioProcessing) {
    169   // Turn off the default constraints to verify that the sink will get packets
    170   // with a buffer size smaller than 10ms.
    171   MockMediaConstraintFactory constraint_factory;
    172   constraint_factory.DisableDefaultAudioConstraints();
    173   VerifyAudioParams(constraint_factory.CreateWebMediaConstraints(), false);
    174 }
    175 
    176 TEST_F(WebRtcAudioCapturerTest, FailToCreateCapturerWithWrongConstraints) {
    177   MockMediaConstraintFactory constraint_factory;
    178   const std::string dummy_constraint = "dummy";
    179   constraint_factory.AddMandatory(dummy_constraint, true);
    180 
    181   scoped_refptr<WebRtcAudioCapturer> capturer(
    182       WebRtcAudioCapturer::CreateCapturer(
    183           0, StreamDeviceInfo(MEDIA_DEVICE_AUDIO_CAPTURE,
    184                                "", "", params_.sample_rate(),
    185                                params_.channel_layout(),
    186                                params_.frames_per_buffer()),
    187           constraint_factory.CreateWebMediaConstraints(), NULL, NULL)
    188   );
    189   EXPECT_TRUE(capturer.get() == NULL);
    190 }
    191 
    192 
    193 }  // namespace content
    194