OLD | NEW |
---|---|
1 /* | 1 /* |
2 * Copyright (c) 2015 The WebRTC project authors. All Rights Reserved. | 2 * Copyright (c) 2015 The WebRTC project authors. All Rights Reserved. |
3 * | 3 * |
4 * Use of this source code is governed by a BSD-style license | 4 * Use of this source code is governed by a BSD-style license |
5 * that can be found in the LICENSE file in the root of the source | 5 * that can be found in the LICENSE file in the root of the source |
6 * tree. An additional intellectual property rights grant can be found | 6 * tree. An additional intellectual property rights grant can be found |
7 * in the file PATENTS. All contributing project authors may | 7 * in the file PATENTS. All contributing project authors may |
8 * be found in the AUTHORS file in the root of the source tree. | 8 * be found in the AUTHORS file in the root of the source tree. |
9 */ | 9 */ |
10 | 10 |
11 #include <memory> | 11 #include <memory> |
12 | 12 |
13 #include "webrtc/base/checks.h" | 13 #include "webrtc/base/checks.h" |
14 #include "webrtc/common_types.h" | 14 #include "webrtc/common_types.h" |
15 #include "webrtc/modules/audio_coding/audio_network_adaptor/mock/mock_audio_netw ork_adaptor.h" | |
15 #include "webrtc/modules/audio_coding/codecs/opus/audio_encoder_opus.h" | 16 #include "webrtc/modules/audio_coding/codecs/opus/audio_encoder_opus.h" |
16 #include "webrtc/test/gtest.h" | 17 #include "webrtc/test/gtest.h" |
17 | 18 |
18 namespace webrtc { | 19 namespace webrtc { |
20 using ::testing::NiceMock; | |
21 using ::testing::Return; | |
19 | 22 |
20 namespace { | 23 namespace { |
21 const CodecInst kOpusSettings = {105, "opus", 48000, 960, 1, 32000}; | 24 |
25 const CodecInst kDefaultOpusSettings = {105, "opus", 48000, 960, 1, 32000}; | |
26 | |
27 AudioEncoderOpus::Config CreateConfig(const CodecInst& codec_inst) { | |
28 AudioEncoderOpus::Config config; | |
29 config.frame_size_ms = rtc::CheckedDivExact(codec_inst.pacsize, 48); | |
30 config.num_channels = codec_inst.channels; | |
31 config.bitrate_bps = rtc::Optional<int>(codec_inst.rate); | |
32 config.payload_type = codec_inst.pltype; | |
33 config.application = config.num_channels == 1 ? AudioEncoderOpus::kVoip | |
34 : AudioEncoderOpus::kAudio; | |
35 return config; | |
36 } | |
37 | |
38 struct AudioEncoderOpusStates { | |
39 std::shared_ptr<MockAudioNetworkAdaptor*> mock_audio_network_adaptor; | |
40 std::unique_ptr<AudioEncoderOpus> encoder; | |
41 }; | |
42 | |
43 AudioEncoderOpusStates CreateCodec(size_t num_channels) { | |
44 AudioEncoderOpusStates states; | |
45 states.mock_audio_network_adaptor = std::shared_ptr<MockAudioNetworkAdaptor*>( | |
46 new MockAudioNetworkAdaptor*(nullptr)); | |
minyue-webrtc
2016/10/05 14:18:24
This is different from your suggestion. We have to
kwiberg-webrtc
2016/10/06 08:51:10
Yes, of course. I tried to to that in my suggestio
minyue-webrtc
2016/10/06 09:57:06
yes, that reads better.
| |
47 | |
48 std::weak_ptr<MockAudioNetworkAdaptor*> mock_ptr( | |
49 states.mock_audio_network_adaptor); | |
50 AudioEncoderOpus::AudioNetworkAdaptorCreator creator = [mock_ptr]( | |
minyue-webrtc
2016/10/05 14:18:24
I see the point now. We don't use reference, we us
kwiberg-webrtc
2016/10/06 08:51:10
Yes---we copy the weak_ptr. And the thing that it
| |
51 const std::string&, const Clock*) { | |
52 std::unique_ptr<MockAudioNetworkAdaptor> adaptor( | |
53 new NiceMock<MockAudioNetworkAdaptor>()); | |
54 EXPECT_CALL(*adaptor, Die()); | |
55 *mock_ptr.lock() = adaptor.get(); | |
kwiberg-webrtc
2016/10/06 08:51:10
If all shared_ptrs (just one in this test) that po
minyue-webrtc
2016/10/06 09:57:06
FAIL() does not work since it is only allowed in v
| |
56 return adaptor; | |
57 }; | |
58 | |
59 CodecInst codec_inst = kDefaultOpusSettings; | |
60 codec_inst.channels = num_channels; | |
61 auto config = CreateConfig(codec_inst); | |
62 states.encoder.reset(new AudioEncoderOpus(config, std::move(creator))); | |
63 return states; | |
64 } | |
65 | |
66 AudioNetworkAdaptor::EncoderRuntimeConfig CreateEncoderRuntimeConfig() { | |
67 constexpr int kBitrate = 40000; | |
68 constexpr int kFrameLength = 60; | |
69 constexpr bool kEnableFec = true; | |
70 constexpr bool kEnableDtx = false; | |
71 constexpr size_t kNumChannels = 1; | |
72 constexpr float kPacketLossFraction = 0.1f; | |
73 AudioNetworkAdaptor::EncoderRuntimeConfig config; | |
74 config.bitrate_bps = rtc::Optional<int>(kBitrate); | |
75 config.frame_length_ms = rtc::Optional<int>(kFrameLength); | |
76 config.enable_fec = rtc::Optional<bool>(kEnableFec); | |
77 config.enable_dtx = rtc::Optional<bool>(kEnableDtx); | |
78 config.num_channels = rtc::Optional<size_t>(kNumChannels); | |
79 config.uplink_packet_loss_fraction = | |
80 rtc::Optional<float>(kPacketLossFraction); | |
81 return config; | |
82 } | |
83 | |
84 void CheckEncoderRuntimeConfig( | |
85 const AudioEncoderOpus* encoder, | |
86 const AudioNetworkAdaptor::EncoderRuntimeConfig& config) { | |
87 EXPECT_EQ(*config.bitrate_bps, encoder->GetTargetBitrate()); | |
88 EXPECT_EQ(*config.frame_length_ms, encoder->next_frame_length_ms()); | |
89 EXPECT_EQ(*config.enable_fec, encoder->fec_enabled()); | |
90 EXPECT_EQ(*config.enable_dtx, encoder->GetDtx()); | |
91 EXPECT_EQ(*config.num_channels, encoder->num_channels_to_encode()); | |
92 } | |
93 | |
22 } // namespace | 94 } // namespace |
23 | 95 |
24 class AudioEncoderOpusTest : public ::testing::Test { | 96 TEST(AudioEncoderOpusTest, DefaultApplicationModeMono) { |
25 protected: | 97 auto states = CreateCodec(1); |
26 void CreateCodec(int num_channels) { | 98 EXPECT_EQ(AudioEncoderOpus::kVoip, states.encoder->application()); |
27 codec_inst_.channels = num_channels; | |
28 encoder_.reset(new AudioEncoderOpus(codec_inst_)); | |
29 auto expected_app = | |
30 num_channels == 1 ? AudioEncoderOpus::kVoip : AudioEncoderOpus::kAudio; | |
31 EXPECT_EQ(expected_app, encoder_->application()); | |
32 } | |
33 | |
34 CodecInst codec_inst_ = kOpusSettings; | |
35 std::unique_ptr<AudioEncoderOpus> encoder_; | |
36 }; | |
37 | |
38 TEST_F(AudioEncoderOpusTest, DefaultApplicationModeMono) { | |
39 CreateCodec(1); | |
40 } | 99 } |
41 | 100 |
42 TEST_F(AudioEncoderOpusTest, DefaultApplicationModeStereo) { | 101 TEST(AudioEncoderOpusTest, DefaultApplicationModeStereo) { |
43 CreateCodec(2); | 102 auto states = CreateCodec(2); |
103 EXPECT_EQ(AudioEncoderOpus::kAudio, states.encoder->application()); | |
44 } | 104 } |
45 | 105 |
46 TEST_F(AudioEncoderOpusTest, ChangeApplicationMode) { | 106 TEST(AudioEncoderOpusTest, ChangeApplicationMode) { |
47 CreateCodec(2); | 107 auto states = CreateCodec(2); |
48 EXPECT_TRUE(encoder_->SetApplication(AudioEncoder::Application::kSpeech)); | 108 EXPECT_TRUE( |
49 EXPECT_EQ(AudioEncoderOpus::kVoip, encoder_->application()); | 109 states.encoder->SetApplication(AudioEncoder::Application::kSpeech)); |
110 EXPECT_EQ(AudioEncoderOpus::kVoip, states.encoder->application()); | |
50 } | 111 } |
51 | 112 |
52 TEST_F(AudioEncoderOpusTest, ResetWontChangeApplicationMode) { | 113 TEST(AudioEncoderOpusTest, ResetWontChangeApplicationMode) { |
53 CreateCodec(2); | 114 auto states = CreateCodec(2); |
54 | 115 |
55 // Trigger a reset. | 116 // Trigger a reset. |
56 encoder_->Reset(); | 117 states.encoder->Reset(); |
57 // Verify that the mode is still kAudio. | 118 // Verify that the mode is still kAudio. |
58 EXPECT_EQ(AudioEncoderOpus::kAudio, encoder_->application()); | 119 EXPECT_EQ(AudioEncoderOpus::kAudio, states.encoder->application()); |
59 | 120 |
60 // Now change to kVoip. | 121 // Now change to kVoip. |
61 EXPECT_TRUE(encoder_->SetApplication(AudioEncoder::Application::kSpeech)); | 122 EXPECT_TRUE( |
62 EXPECT_EQ(AudioEncoderOpus::kVoip, encoder_->application()); | 123 states.encoder->SetApplication(AudioEncoder::Application::kSpeech)); |
124 EXPECT_EQ(AudioEncoderOpus::kVoip, states.encoder->application()); | |
63 | 125 |
64 // Trigger a reset again. | 126 // Trigger a reset again. |
65 encoder_->Reset(); | 127 states.encoder->Reset(); |
66 // Verify that the mode is still kVoip. | 128 // Verify that the mode is still kVoip. |
67 EXPECT_EQ(AudioEncoderOpus::kVoip, encoder_->application()); | 129 EXPECT_EQ(AudioEncoderOpus::kVoip, states.encoder->application()); |
68 } | 130 } |
69 | 131 |
70 TEST_F(AudioEncoderOpusTest, ToggleDtx) { | 132 TEST(AudioEncoderOpusTest, ToggleDtx) { |
71 CreateCodec(2); | 133 auto states = CreateCodec(2); |
72 // Enable DTX | 134 // Enable DTX |
73 EXPECT_TRUE(encoder_->SetDtx(true)); | 135 EXPECT_TRUE(states.encoder->SetDtx(true)); |
74 // Verify that the mode is still kAudio. | 136 // Verify that the mode is still kAudio. |
75 EXPECT_EQ(AudioEncoderOpus::kAudio, encoder_->application()); | 137 EXPECT_EQ(AudioEncoderOpus::kAudio, states.encoder->application()); |
76 // Turn off DTX. | 138 // Turn off DTX. |
77 EXPECT_TRUE(encoder_->SetDtx(false)); | 139 EXPECT_TRUE(states.encoder->SetDtx(false)); |
78 } | 140 } |
79 | 141 |
80 TEST_F(AudioEncoderOpusTest, SetBitrate) { | 142 TEST(AudioEncoderOpusTest, SetBitrate) { |
81 CreateCodec(1); | 143 auto states = CreateCodec(1); |
82 // Constants are replicated from audio_encoder_opus.cc. | 144 // Constants are replicated from audio_states.encoderopus.cc. |
83 const int kMinBitrateBps = 500; | 145 const int kMinBitrateBps = 500; |
84 const int kMaxBitrateBps = 512000; | 146 const int kMaxBitrateBps = 512000; |
85 // Set a too low bitrate. | 147 // Set a too low bitrate. |
86 encoder_->SetTargetBitrate(kMinBitrateBps - 1); | 148 states.encoder->SetTargetBitrate(kMinBitrateBps - 1); |
87 EXPECT_EQ(kMinBitrateBps, encoder_->GetTargetBitrate()); | 149 EXPECT_EQ(kMinBitrateBps, states.encoder->GetTargetBitrate()); |
88 // Set a too high bitrate. | 150 // Set a too high bitrate. |
89 encoder_->SetTargetBitrate(kMaxBitrateBps + 1); | 151 states.encoder->SetTargetBitrate(kMaxBitrateBps + 1); |
90 EXPECT_EQ(kMaxBitrateBps, encoder_->GetTargetBitrate()); | 152 EXPECT_EQ(kMaxBitrateBps, states.encoder->GetTargetBitrate()); |
91 // Set the minimum rate. | 153 // Set the minimum rate. |
92 encoder_->SetTargetBitrate(kMinBitrateBps); | 154 states.encoder->SetTargetBitrate(kMinBitrateBps); |
93 EXPECT_EQ(kMinBitrateBps, encoder_->GetTargetBitrate()); | 155 EXPECT_EQ(kMinBitrateBps, states.encoder->GetTargetBitrate()); |
94 // Set the maximum rate. | 156 // Set the maximum rate. |
95 encoder_->SetTargetBitrate(kMaxBitrateBps); | 157 states.encoder->SetTargetBitrate(kMaxBitrateBps); |
96 EXPECT_EQ(kMaxBitrateBps, encoder_->GetTargetBitrate()); | 158 EXPECT_EQ(kMaxBitrateBps, states.encoder->GetTargetBitrate()); |
97 // Set rates from 1000 up to 32000 bps. | 159 // Set rates from 1000 up to 32000 bps. |
98 for (int rate = 1000; rate <= 32000; rate += 1000) { | 160 for (int rate = 1000; rate <= 32000; rate += 1000) { |
99 encoder_->SetTargetBitrate(rate); | 161 states.encoder->SetTargetBitrate(rate); |
100 EXPECT_EQ(rate, encoder_->GetTargetBitrate()); | 162 EXPECT_EQ(rate, states.encoder->GetTargetBitrate()); |
101 } | 163 } |
102 } | 164 } |
103 | 165 |
104 namespace { | 166 namespace { |
105 | 167 |
106 // Returns a vector with the n evenly-spaced numbers a, a + (b - a)/(n - 1), | 168 // Returns a vector with the n evenly-spaced numbers a, a + (b - a)/(n - 1), |
107 // ..., b. | 169 // ..., b. |
108 std::vector<double> IntervalSteps(double a, double b, size_t n) { | 170 std::vector<double> IntervalSteps(double a, double b, size_t n) { |
109 RTC_DCHECK_GT(n, 1u); | 171 RTC_DCHECK_GT(n, 1u); |
110 const double step = (b - a) / (n - 1); | 172 const double step = (b - a) / (n - 1); |
(...skipping 10 matching lines...) Expand all Loading... | |
121 const std::vector<double>& losses, | 183 const std::vector<double>& losses, |
122 double expected_return) { | 184 double expected_return) { |
123 for (double loss : losses) { | 185 for (double loss : losses) { |
124 encoder->SetProjectedPacketLossRate(loss); | 186 encoder->SetProjectedPacketLossRate(loss); |
125 EXPECT_DOUBLE_EQ(expected_return, encoder->packet_loss_rate()); | 187 EXPECT_DOUBLE_EQ(expected_return, encoder->packet_loss_rate()); |
126 } | 188 } |
127 } | 189 } |
128 | 190 |
129 } // namespace | 191 } // namespace |
130 | 192 |
131 TEST_F(AudioEncoderOpusTest, PacketLossRateOptimized) { | 193 TEST(AudioEncoderOpusTest, PacketLossRateOptimized) { |
132 CreateCodec(1); | 194 auto states = CreateCodec(1); |
133 auto I = [](double a, double b) { return IntervalSteps(a, b, 10); }; | 195 auto I = [](double a, double b) { return IntervalSteps(a, b, 10); }; |
134 const double eps = 1e-15; | 196 const double eps = 1e-15; |
135 | 197 |
136 // Note that the order of the following calls is critical. | 198 // Note that the order of the following calls is critical. |
137 | 199 |
138 // clang-format off | 200 // clang-format off |
139 TestSetPacketLossRate(encoder_.get(), I(0.00 , 0.01 - eps), 0.00); | 201 TestSetPacketLossRate(states.encoder.get(), I(0.00 , 0.01 - eps), 0.00); |
140 TestSetPacketLossRate(encoder_.get(), I(0.01 + eps, 0.06 - eps), 0.01); | 202 TestSetPacketLossRate(states.encoder.get(), I(0.01 + eps, 0.06 - eps), 0.01); |
141 TestSetPacketLossRate(encoder_.get(), I(0.06 + eps, 0.11 - eps), 0.05); | 203 TestSetPacketLossRate(states.encoder.get(), I(0.06 + eps, 0.11 - eps), 0.05); |
142 TestSetPacketLossRate(encoder_.get(), I(0.11 + eps, 0.22 - eps), 0.10); | 204 TestSetPacketLossRate(states.encoder.get(), I(0.11 + eps, 0.22 - eps), 0.10); |
143 TestSetPacketLossRate(encoder_.get(), I(0.22 + eps, 1.00 ), 0.20); | 205 TestSetPacketLossRate(states.encoder.get(), I(0.22 + eps, 1.00 ), 0.20); |
144 | 206 |
145 TestSetPacketLossRate(encoder_.get(), I(1.00 , 0.18 + eps), 0.20); | 207 TestSetPacketLossRate(states.encoder.get(), I(1.00 , 0.18 + eps), 0.20); |
146 TestSetPacketLossRate(encoder_.get(), I(0.18 - eps, 0.09 + eps), 0.10); | 208 TestSetPacketLossRate(states.encoder.get(), I(0.18 - eps, 0.09 + eps), 0.10); |
147 TestSetPacketLossRate(encoder_.get(), I(0.09 - eps, 0.04 + eps), 0.05); | 209 TestSetPacketLossRate(states.encoder.get(), I(0.09 - eps, 0.04 + eps), 0.05); |
148 TestSetPacketLossRate(encoder_.get(), I(0.04 - eps, 0.01 + eps), 0.01); | 210 TestSetPacketLossRate(states.encoder.get(), I(0.04 - eps, 0.01 + eps), 0.01); |
149 TestSetPacketLossRate(encoder_.get(), I(0.01 - eps, 0.00 ), 0.00); | 211 TestSetPacketLossRate(states.encoder.get(), I(0.01 - eps, 0.00 ), 0.00); |
150 // clang-format on | 212 // clang-format on |
151 } | 213 } |
152 | 214 |
215 TEST(AudioEncoderOpusTest, InvokeAudioNetworkAdaptorOnSetUplinkBandwidth) { | |
216 auto states = CreateCodec(2); | |
217 printf("passed!\n"); | |
218 states.encoder->EnableAudioNetworkAdaptor("", nullptr); | |
219 | |
220 auto config = CreateEncoderRuntimeConfig(); | |
221 EXPECT_CALL(**states.mock_audio_network_adaptor, GetEncoderRuntimeConfig()) | |
222 .WillOnce(Return(config)); | |
223 | |
224 // Since using mock audio network adaptor, any bandwidth value is fine. | |
225 constexpr int kUplinkBandwidth = 50000; | |
226 EXPECT_CALL(**states.mock_audio_network_adaptor, | |
227 SetUplinkBandwidth(kUplinkBandwidth)); | |
228 states.encoder->OnReceivedUplinkBandwidth(kUplinkBandwidth); | |
229 | |
230 CheckEncoderRuntimeConfig(states.encoder.get(), config); | |
231 } | |
232 | |
233 TEST(AudioEncoderOpusTest, | |
234 InvokeAudioNetworkAdaptorOnSetUplinkPacketLossFraction) { | |
235 auto states = CreateCodec(2); | |
236 states.encoder->EnableAudioNetworkAdaptor("", nullptr); | |
237 | |
238 auto config = CreateEncoderRuntimeConfig(); | |
239 EXPECT_CALL(**states.mock_audio_network_adaptor, GetEncoderRuntimeConfig()) | |
240 .WillOnce(Return(config)); | |
241 | |
242 // Since using mock audio network adaptor, any packet loss fraction is fine. | |
243 constexpr float kUplinkPacketLoss = 0.1f; | |
244 EXPECT_CALL(**states.mock_audio_network_adaptor, | |
245 SetUplinkPacketLossFraction(kUplinkPacketLoss)); | |
246 states.encoder->OnReceivedUplinkPacketLossFraction(kUplinkPacketLoss); | |
247 | |
248 CheckEncoderRuntimeConfig(states.encoder.get(), config); | |
249 } | |
250 | |
251 TEST(AudioEncoderOpusTest, InvokeAudioNetworkAdaptorOnSetTargetAudioBitrate) { | |
252 auto states = CreateCodec(2); | |
253 states.encoder->EnableAudioNetworkAdaptor("", nullptr); | |
254 | |
255 auto config = CreateEncoderRuntimeConfig(); | |
256 EXPECT_CALL(**states.mock_audio_network_adaptor, GetEncoderRuntimeConfig()) | |
257 .WillOnce(Return(config)); | |
258 | |
259 // Since using mock audio network adaptor, any target audio bitrate is fine. | |
260 constexpr int kTargetAudioBitrate = 30000; | |
261 EXPECT_CALL(**states.mock_audio_network_adaptor, | |
262 SetTargetAudioBitrate(kTargetAudioBitrate)); | |
263 states.encoder->OnReceivedTargetAudioBitrate(kTargetAudioBitrate); | |
264 | |
265 CheckEncoderRuntimeConfig(states.encoder.get(), config); | |
266 } | |
267 | |
268 TEST(AudioEncoderOpusTest, InvokeAudioNetworkAdaptorOnSetRtt) { | |
269 auto states = CreateCodec(2); | |
270 states.encoder->EnableAudioNetworkAdaptor("", nullptr); | |
271 | |
272 auto config = CreateEncoderRuntimeConfig(); | |
273 EXPECT_CALL(**states.mock_audio_network_adaptor, GetEncoderRuntimeConfig()) | |
274 .WillOnce(Return(config)); | |
275 | |
276 // Since using mock audio network adaptor, any rtt is fine. | |
277 constexpr int kRtt = 30; | |
278 EXPECT_CALL(**states.mock_audio_network_adaptor, SetRtt(kRtt)); | |
279 states.encoder->OnReceivedRtt(kRtt); | |
280 | |
281 CheckEncoderRuntimeConfig(states.encoder.get(), config); | |
282 } | |
283 | |
284 TEST(AudioEncoderOpusTest, | |
285 InvokeAudioNetworkAdaptorOnSetReceiverFrameLengthRange) { | |
286 auto states = CreateCodec(2); | |
287 states.encoder->EnableAudioNetworkAdaptor("", nullptr); | |
288 | |
289 auto config = CreateEncoderRuntimeConfig(); | |
290 EXPECT_CALL(**states.mock_audio_network_adaptor, GetEncoderRuntimeConfig()) | |
291 .WillOnce(Return(config)); | |
292 | |
293 constexpr int kMinFrameLength = 10; | |
294 constexpr int kMaxFrameLength = 60; | |
295 EXPECT_CALL(**states.mock_audio_network_adaptor, | |
296 SetReceiverFrameLengthRange(kMinFrameLength, kMaxFrameLength)); | |
297 states.encoder->SetReceiverFrameLengthRange(kMinFrameLength, kMaxFrameLength); | |
298 | |
299 CheckEncoderRuntimeConfig(states.encoder.get(), config); | |
300 } | |
301 | |
153 } // namespace webrtc | 302 } // namespace webrtc |
OLD | NEW |