OLD | NEW |
---|---|
(Empty) | |
1 /* | |
2 * Copyright (c) 2015 The WebRTC project authors. All Rights Reserved. | |
3 * | |
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 | |
6 * tree. An additional intellectual property rights grant can be found | |
7 * in the file PATENTS. All contributing project authors may | |
8 * be found in the AUTHORS file in the root of the source tree. | |
9 */ | |
10 | |
11 #include <algorithm> | |
12 #include <sstream> | |
13 #include <vector> | |
14 | |
15 #include "testing/gtest/include/gtest/gtest.h" | |
16 #include "webrtc/base/buffer.h" | |
17 #include "webrtc/modules/audio_coding/codecs/isac/fix/interface/audio_encoder_is acfix.h" | |
18 #include "webrtc/modules/audio_coding/codecs/isac/main/interface/audio_encoder_i sac.h" | |
19 #include "webrtc/modules/audio_coding/neteq/tools/input_audio_file.h" | |
20 #include "webrtc/test/testsupport/fileutils.h" | |
21 | |
22 namespace webrtc { | |
23 | |
24 namespace { | |
25 | |
26 std::vector<int16_t> LoadSpeechData() { | |
27 webrtc::test::InputAudioFile input_file( | |
28 webrtc::test::ResourcePath("audio_coding/testfile32kHz", "pcm")); | |
29 static const int kIsacNumberOfSamples = 32 * 60; // 60 ms at 32 kHz | |
30 std::vector<int16_t> speech_data(kIsacNumberOfSamples); | |
31 input_file.Read(kIsacNumberOfSamples, speech_data.data()); | |
32 return speech_data; | |
33 } | |
34 | |
35 template <typename T> | |
36 IsacBandwidthInfo GetBwInfo(typename T::instance_type* inst) { | |
37 IsacBandwidthInfo bi; | |
38 T::GetBandwidthInfo(inst, &bi); | |
39 EXPECT_TRUE(bi.in_use); | |
40 return bi; | |
41 } | |
42 | |
43 template <typename T> | |
44 rtc::Buffer EncodePacket(typename T::instance_type* inst, | |
45 const IsacBandwidthInfo* bi, | |
46 const int16_t* speech_data, | |
47 int framesize_ms) { | |
48 rtc::Buffer output(1000); | |
49 for (int i = 0;; ++i) { | |
50 if (bi) | |
51 T::SetBandwidthInfo(inst, bi); | |
52 int encoded_bytes = T::Encode(inst, speech_data, output.data()); | |
53 if (i + 1 == framesize_ms / 10) { | |
54 EXPECT_GT(encoded_bytes, 0); | |
55 EXPECT_LE(static_cast<size_t>(encoded_bytes), output.size()); | |
56 output.SetSize(encoded_bytes); | |
57 return output; | |
58 } | |
59 EXPECT_EQ(0, encoded_bytes); | |
60 } | |
61 } | |
62 | |
63 class BoundedCapacityChannel final { | |
64 public: | |
65 BoundedCapacityChannel(int rate_bps) | |
hlundin-webrtc
2015/07/02 14:04:36
Suggest you call the parameter rate_bits_per_secon
kwiberg-webrtc
2015/07/03 00:27:53
Done, for the whole file.
| |
66 : current_time_rtp_(0), | |
67 channel_rate_bytes_per_sample_(rate_bps / (8.0 * kSamplesPerSecond)) {} | |
68 | |
69 // Simulate sending the given number of bytes at the given RTP time. Returns | |
70 // the | |
hlundin-webrtc
2015/07/02 14:04:36
Re-flow the line breaks.
kwiberg-webrtc
2015/07/03 00:27:53
Done.
| |
71 // new current RTP time after the sending is done. | |
72 int Send(int send_time_rtp, int nbytes) { | |
73 current_time_rtp_ = std::max(current_time_rtp_, send_time_rtp) + | |
74 nbytes / channel_rate_bytes_per_sample_; | |
75 return current_time_rtp_; | |
76 } | |
77 | |
78 private: | |
79 int current_time_rtp_; | |
80 // The somewhat strange unit for channel rate, bytes per sample, is because | |
81 // RTP time is measured in samples: | |
82 const double channel_rate_bytes_per_sample_; | |
83 static const int kSamplesPerSecond = 16000; | |
84 }; | |
85 | |
86 template <typename T, bool adaptive> | |
87 struct TestParam {}; | |
88 | |
89 template <> | |
90 struct TestParam<IsacFloat, true> { | |
91 static const int time_to_settle = 200; | |
92 static int ExpectedRateBps(int rate_bps) { return rate_bps; } | |
93 }; | |
94 | |
95 template <> | |
96 struct TestParam<IsacFix, true> { | |
97 static const int time_to_settle = 350; | |
98 static int ExpectedRateBps(int rate_bps) { | |
99 // For some reason, IsacFix fails to adapt to the channel's actual | |
100 // bandwidth. Instead, it settles on a few hundred packets at 10kbit/s, | |
101 // then a few hundred at 5kbit/s, then a few hundred at 10kbit/s, and so | |
102 // on. The 200 packets starting at 350 are in the middle of the first | |
103 // 10kbit/s run. | |
104 return 10000; | |
105 } | |
106 }; | |
107 | |
108 template <> | |
109 struct TestParam<IsacFloat, false> { | |
110 static const int time_to_settle = 0; | |
111 static int ExpectedRateBps(int rate_bps) { return 16000; } | |
112 }; | |
113 | |
114 template <> | |
115 struct TestParam<IsacFix, false> { | |
116 static const int time_to_settle = 0; | |
117 static int ExpectedRateBps(int rate_bps) { return 8000; } | |
118 }; | |
119 | |
120 // Test that the iSAC encoder produces identical output whether or not we use a | |
121 // conjoined encoder+decoder pair or a separate encoder and decoder that | |
122 // communicate BW estimation info explicitly. | |
123 template <typename T, bool adaptive> | |
124 void TestGetSetBandwidthInfo(const int16_t* speech_data, int rate_bps) { | |
125 using Param = TestParam<T, adaptive>; | |
126 | |
127 // Conjoined encoder/decoder pair: | |
128 typename T::instance_type* encdec; | |
129 ASSERT_EQ(0, T::Create(&encdec)); | |
130 ASSERT_EQ(0, T::EncoderInit(encdec, adaptive ? 0 : 1)); | |
131 ASSERT_EQ(0, T::DecoderInit(encdec)); | |
132 | |
133 // Disjoint encoder/decoder pair: | |
134 typename T::instance_type* enc; | |
135 ASSERT_EQ(0, T::Create(&enc)); | |
136 ASSERT_EQ(0, T::EncoderInit(enc, adaptive ? 0 : 1)); | |
137 typename T::instance_type* dec; | |
138 ASSERT_EQ(0, T::Create(&dec)); | |
139 ASSERT_EQ(0, T::DecoderInit(dec)); | |
140 | |
141 // 0. Get initial BW info from decoder. | |
142 auto bi = GetBwInfo<T>(dec); | |
143 | |
144 BoundedCapacityChannel channel1(rate_bps), channel2(rate_bps); | |
145 std::vector<size_t> packet_sizes; | |
146 for (int i = 0; i < Param::time_to_settle + 200; ++i) { | |
147 std::ostringstream ss; | |
148 ss << " i = " << i; | |
149 SCOPED_TRACE(ss.str()); | |
150 | |
151 // 1. Encode 6 * 10 ms (adaptive) or 3 * 10 ms (nonadaptive). The separate | |
152 // encoder is given the BW info before each encode call. | |
153 const int framesize_ms = adaptive ? 60 : 30; | |
154 auto bitstream1 = | |
155 EncodePacket<T>(encdec, nullptr, speech_data, framesize_ms); | |
156 auto bitstream2 = EncodePacket<T>(enc, &bi, speech_data, framesize_ms); | |
157 EXPECT_EQ(bitstream1, bitstream2); | |
158 if (i > Param::time_to_settle) | |
159 packet_sizes.push_back(bitstream1.size()); | |
160 | |
161 // 2. Deliver the encoded data to the decoders (but don't actually ask them | |
162 // to decode it; that's not necessary). Then get new BW info from the | |
163 // separate decoder. | |
164 const int samples_per_packet = 16 * framesize_ms; | |
165 const int send_time = i * samples_per_packet; | |
166 EXPECT_EQ(0, T::UpdateBwEstimate( | |
167 encdec, bitstream1.data(), bitstream1.size(), i, send_time, | |
168 channel1.Send(send_time, bitstream1.size()))); | |
169 EXPECT_EQ(0, T::UpdateBwEstimate( | |
170 dec, bitstream2.data(), bitstream2.size(), i, send_time, | |
171 channel2.Send(send_time, bitstream2.size()))); | |
172 bi = GetBwInfo<T>(dec); | |
173 } | |
174 | |
175 EXPECT_EQ(0, T::Free(encdec)); | |
176 EXPECT_EQ(0, T::Free(enc)); | |
177 EXPECT_EQ(0, T::Free(dec)); | |
178 | |
179 // The average send bitrate is close to the channel's capacity. | |
180 double avg_size = | |
181 std::accumulate(packet_sizes.begin(), packet_sizes.end(), 0) / | |
182 static_cast<double>(packet_sizes.size()); | |
183 double avg_rate_bps = 8.0 * avg_size / 60e-3; | |
hlundin-webrtc
2015/07/02 14:04:36
Shouldn't 60e-3 be 30e-3 in the non-adaptive case?
kwiberg-webrtc
2015/07/03 00:27:53
Yes. Done.
| |
184 double expected_rate_bps = Param::ExpectedRateBps(rate_bps); | |
185 EXPECT_GT(avg_rate_bps / expected_rate_bps, 0.99); | |
186 EXPECT_LT(avg_rate_bps / expected_rate_bps, 1.06); | |
187 | |
188 // The largest packet isn't that large, and the smallest not that small. | |
189 auto minmax_size = | |
190 std::minmax_element(packet_sizes.begin(), packet_sizes.end()); | |
191 double size_range = *minmax_size.second - *minmax_size.first; | |
192 EXPECT_LE(size_range / avg_size, 0.16); | |
193 } | |
194 | |
195 } // namespace | |
196 | |
197 TEST(IsacCommonTest, GetSetBandwidthInfoFloat12kAdaptive) { | |
198 TestGetSetBandwidthInfo<IsacFloat, true>(LoadSpeechData().data(), 12000); | |
199 } | |
200 | |
201 TEST(IsacCommonTest, GetSetBandwidthInfoFloat15kAdaptive) { | |
202 TestGetSetBandwidthInfo<IsacFloat, true>(LoadSpeechData().data(), 15000); | |
203 } | |
204 | |
205 TEST(IsacCommonTest, GetSetBandwidthInfoFloat19kAdaptive) { | |
206 TestGetSetBandwidthInfo<IsacFloat, true>(LoadSpeechData().data(), 19000); | |
207 } | |
208 | |
209 TEST(IsacCommonTest, GetSetBandwidthInfoFloat22kAdaptive) { | |
210 TestGetSetBandwidthInfo<IsacFloat, true>(LoadSpeechData().data(), 22000); | |
211 } | |
212 | |
213 TEST(IsacCommonTest, GetSetBandwidthInfoFix12kAdaptive) { | |
214 TestGetSetBandwidthInfo<IsacFix, true>(LoadSpeechData().data(), 12000); | |
215 } | |
216 | |
217 TEST(IsacCommonTest, GetSetBandwidthInfoFix15kAdaptive) { | |
218 TestGetSetBandwidthInfo<IsacFix, true>(LoadSpeechData().data(), 15000); | |
219 } | |
220 | |
221 TEST(IsacCommonTest, GetSetBandwidthInfoFix19kAdaptive) { | |
222 TestGetSetBandwidthInfo<IsacFix, true>(LoadSpeechData().data(), 19000); | |
223 } | |
224 | |
225 TEST(IsacCommonTest, GetSetBandwidthInfoFix22kAdaptive) { | |
226 TestGetSetBandwidthInfo<IsacFix, true>(LoadSpeechData().data(), 22000); | |
227 } | |
228 | |
229 TEST(IsacCommonTest, GetSetBandwidthInfoFloat12k) { | |
230 TestGetSetBandwidthInfo<IsacFloat, false>(LoadSpeechData().data(), 12000); | |
231 } | |
232 | |
233 TEST(IsacCommonTest, GetSetBandwidthInfoFloat15k) { | |
234 TestGetSetBandwidthInfo<IsacFloat, false>(LoadSpeechData().data(), 15000); | |
235 } | |
236 | |
237 TEST(IsacCommonTest, GetSetBandwidthInfoFloat19k) { | |
238 TestGetSetBandwidthInfo<IsacFloat, false>(LoadSpeechData().data(), 19000); | |
239 } | |
240 | |
241 TEST(IsacCommonTest, GetSetBandwidthInfoFloat22k) { | |
242 TestGetSetBandwidthInfo<IsacFloat, false>(LoadSpeechData().data(), 22000); | |
243 } | |
244 | |
245 TEST(IsacCommonTest, GetSetBandwidthInfoFix12k) { | |
246 TestGetSetBandwidthInfo<IsacFix, false>(LoadSpeechData().data(), 12000); | |
247 } | |
248 | |
249 TEST(IsacCommonTest, GetSetBandwidthInfoFix15k) { | |
250 TestGetSetBandwidthInfo<IsacFix, false>(LoadSpeechData().data(), 15000); | |
251 } | |
252 | |
253 TEST(IsacCommonTest, GetSetBandwidthInfoFix19k) { | |
254 TestGetSetBandwidthInfo<IsacFix, false>(LoadSpeechData().data(), 19000); | |
255 } | |
256 | |
257 TEST(IsacCommonTest, GetSetBandwidthInfoFix22k) { | |
258 TestGetSetBandwidthInfo<IsacFix, false>(LoadSpeechData().data(), 22000); | |
259 } | |
260 | |
261 } // namespace webrtc | |
OLD | NEW |