Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(528)

Side by Side Diff: webrtc/modules/audio_coding/codecs/opus/audio_encoder_opus_unittest.cc

Issue 2362703002: Adding audio network adaptor to AudioEncoderOpus. (Closed)
Patch Set: fixing Created 4 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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
OLDNEW
« no previous file with comments | « webrtc/modules/audio_coding/codecs/opus/audio_encoder_opus.cc ('k') | webrtc/modules/audio_coding/codecs/opus/opus.gypi » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698