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