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