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

Unified Diff: webrtc/modules/audio_coding/codecs/isac/unittest.cc

Issue 1208923002: iSAC: Functions for importing and exporting bandwidth est. info (Closed) Base URL: https://chromium.googlesource.com/external/webrtc.git@master
Patch Set: Created 5 years, 6 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 side-by-side diff with in-line comments
Download patch
Index: webrtc/modules/audio_coding/codecs/isac/unittest.cc
diff --git a/webrtc/modules/audio_coding/codecs/isac/unittest.cc b/webrtc/modules/audio_coding/codecs/isac/unittest.cc
new file mode 100644
index 0000000000000000000000000000000000000000..842c67c56468e96e1c6a4eb69b8fa81619269049
--- /dev/null
+++ b/webrtc/modules/audio_coding/codecs/isac/unittest.cc
@@ -0,0 +1,188 @@
+/*
+ * Copyright (c) 2015 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include <cmath>
+#include <sstream>
+#include <vector>
+
+#include "testing/gtest/include/gtest/gtest.h"
+#include "webrtc/base/buffer.h"
+#include "webrtc/base/checks.h"
+#include "webrtc/modules/audio_coding/codecs/isac/fix/interface/audio_encoder_isacfix.h"
+#include "webrtc/modules/audio_coding/codecs/isac/main/interface/audio_encoder_isac.h"
+#include "webrtc/test/testsupport/fileutils.h"
+
+namespace webrtc {
+
+namespace {
+
+std::vector<int16_t> LoadSpeechData() {
hlundin-webrtc 2015/06/26 10:35:15 Consider using webrtc::test::InputAudioFile instea
kwiberg-webrtc 2015/06/28 03:17:41 Done.
+ static const int kIsacNumberOfSamples = 32 * 60; // 60 ms at 32 kHz
+ const std::string file_name =
+ webrtc::test::ResourcePath("audio_coding/testfile32kHz", "pcm");
+ FILE* input_file = fopen(file_name.c_str(), "rb");
+ CHECK(input_file);
+ std::vector<int16_t> speech_data(kIsacNumberOfSamples);
+ CHECK_EQ(kIsacNumberOfSamples,
+ static_cast<int32_t>(fread(speech_data.data(), sizeof(int16_t),
+ kIsacNumberOfSamples, input_file)));
+ CHECK_EQ(0, fclose(input_file));
+#ifndef WEBRTC_ARCH_LITTLE_ENDIAN
+#error "Need to convert samples from little-endian"
+#endif
+ return speech_data;
+}
+
+template <typename T>
+IsacBandwidthInfo GetBwInfo(typename T::instance_type* inst) {
+ IsacBandwidthInfo bi;
+ T::GetBandwidthInfo(inst, &bi);
+ CHECK(bi.in_use);
+ return bi;
+}
+
+std::string Str(const IsacBandwidthInfo& bi) {
hlundin-webrtc 2015/06/26 10:35:14 The function name is a bit too compact. Consider T
kwiberg-webrtc 2015/06/28 03:17:41 Done.
+ CHECK(bi.in_use);
+ std::ostringstream o;
+ o << "(send_bw_avg: " << bi.send_bw_avg << ", "
+ << "send_max_delay_avg: " << bi.send_max_delay_avg << ", "
+ << "bottleneck_idx: " << bi.bottleneck_idx << ", "
+ << "jitter_info: " << bi.jitter_info << ")";
+ return o.str();
+}
+
+// Is the distance between a and b dist or less, and the relative distance
+// rdist or less?
+bool AlmostEqual(int a, int b, unsigned dist, double rdist) {
+ // d = |a-b|, because casting n-bit signed to n-bit unsigned leaves a value
+ // unchanged mod 2^n.
+ unsigned d = a > b ? static_cast<unsigned>(a) - static_cast<unsigned>(b)
+ : static_cast<unsigned>(b) - static_cast<unsigned>(a);
+ return d <= dist && d <= rdist * std::min(std::abs(a), std::abs(b));
+}
+
+// Returns true if the two arguments are similar enough.
+bool Similar(const IsacBandwidthInfo& a, const IsacBandwidthInfo& b) {
+ return AlmostEqual(a.send_bw_avg, b.send_bw_avg, 1000, 0.07) &&
+ a.send_max_delay_avg == b.send_max_delay_avg &&
+ AlmostEqual(a.bottleneck_idx, b.bottleneck_idx, 1, 0.1) &&
+ a.jitter_info == b.jitter_info;
+}
+
+// Count the number of elements in the range [lower,upper).
+template <typename T>
+int CountRange(std::multiset<T> s, T lower, T upper) {
+ return std::distance(s.lower_bound(lower), s.lower_bound(upper));
+}
+
+template <typename T>
+rtc::Buffer Encode60Ms(typename T::instance_type* inst,
+ const IsacBandwidthInfo* bi,
+ const int16_t* speech_data) {
+ rtc::Buffer output(1000);
+ for (int i = 0;; ++i) {
+ if (bi)
+ T::SetBandwidthInfo(inst, bi);
+ int encoded_bytes = T::Encode(inst, speech_data, output.data());
hlundin-webrtc 2015/06/26 10:35:15 What if encoded_bytes is too large for output?
kwiberg-webrtc 2015/06/28 03:17:41 It shouldn't be. And some sanitizer bot would comp
+ if (i == 5) {
+ output.SetSize(encoded_bytes);
+ return output;
+ }
+ CHECK_EQ(0, encoded_bytes);
hlundin-webrtc 2015/06/26 10:35:14 CHECK is quite aggressive here. Consider using EXP
kwiberg-webrtc 2015/06/28 03:17:41 OK. Although I sort of doubt the rest of the run w
hlundin-webrtc 2015/06/29 08:42:18 Right. But a CHECK will kill the test binary, in t
kwiberg-webrtc 2015/06/29 11:53:48 Mmmm, I didn't think things through enough to real
+ }
+}
+
+template <typename T>
+void TestGetSetBandwidthInfo(const int16_t* speech_data) {
+ // Conjoined encoder/decoder pair:
+ typename T::instance_type* encdec;
+ EXPECT_EQ(0, T::Create(&encdec));
hlundin-webrtc 2015/06/26 10:35:15 All the create and init calls should be ASSERT_EQ
kwiberg-webrtc 2015/06/28 03:17:41 Done.
+ EXPECT_EQ(0, T::EncoderInit(encdec, 0 /* adaptive mode */));
+ EXPECT_EQ(0, T::DecoderInit(encdec));
+
+ // Disjoint encoder/decoder pair:
+ typename T::instance_type* enc;
+ EXPECT_EQ(0, T::Create(&enc));
+ EXPECT_EQ(0, T::EncoderInit(enc, 0 /* adaptive mode */));
+ typename T::instance_type* dec;
+ EXPECT_EQ(0, T::Create(&dec));
+ EXPECT_EQ(0, T::DecoderInit(dec));
+
+ const int kSamplesPerPacket = 960;
+ std::multiset<int> send_bw_avg, bottleneck_idx;
+ for (int i = 0; i < 250; ++i) {
+ std::ostringstream ss;
+ ss << "i = " << i;
+ SCOPED_TRACE(ss.str());
+
+ // 1. Get BW info from decoders, and make sure they're similar enough.
+ auto bi1 = GetBwInfo<T>(encdec);
+ auto bi2 = GetBwInfo<T>(dec);
+ EXPECT_TRUE(Similar(bi1, bi2)) << "Not similar enough:\n " << Str(bi1)
+ << "\n " << Str(bi2);
+ send_bw_avg.insert(bi2.send_bw_avg);
+ bottleneck_idx.insert(bi2.bottleneck_idx);
+
+ // 2. Encode 6 * 10 ms. The separate encoder is given the BW info before
+ // each encode call.
+ auto bitstream1 = Encode60Ms<T>(encdec, nullptr, speech_data);
+ auto bitstream2 = Encode60Ms<T>(enc, &bi2, speech_data);
+
+ // 3. Deliver the encoded data to the decoders (but don't actually ask them
+ // to decode it; that's not necessary).
+ const int send_time = i * kSamplesPerPacket;
+ const int receive_time = send_time + kSamplesPerPacket / 10; // 6 ms delay
+ EXPECT_EQ(
+ 0, T::UpdateBwEstimate(encdec, bitstream1.data(), bitstream1.size(), 1,
+ send_time, receive_time));
+ EXPECT_EQ(0, T::UpdateBwEstimate(dec, bitstream2.data(), bitstream2.size(),
+ 1, send_time, receive_time));
kwiberg-webrtc 2015/06/25 14:52:43 If I've understood correctly, this means that each
hlundin-webrtc 2015/06/26 10:35:15 I'm not so sure. The receive time should just be t
kwiberg-webrtc 2015/06/27 23:43:43 But I do get some action. First it keeps the bitra
hlundin-webrtc 2015/06/29 08:42:18 Hmm. I still think that the BWE should ignore this
+ }
+
+ // Check that we see a good spread of send_bw_avg numbers.
+ EXPECT_EQ(CountRange(send_bw_avg, std::numeric_limits<int>::min(), 10000), 0);
hlundin-webrtc 2015/06/26 10:35:15 EXPECT_EQ should have swapped parameters; expected
kwiberg-webrtc 2015/06/28 03:17:41 Done. For symmetry, I also swapped the EXPECT_GEs.
+ EXPECT_GE(CountRange(send_bw_avg, 10000, 11000), 37);
+ EXPECT_GE(CountRange(send_bw_avg, 11000, 12000), 14);
+ EXPECT_GE(CountRange(send_bw_avg, 12000, 13000), 14);
+ EXPECT_GE(CountRange(send_bw_avg, 13000, 14000), 10);
+ EXPECT_GE(CountRange(send_bw_avg, 14000, 15000), 15);
+ EXPECT_GE(CountRange(send_bw_avg, 15000, 16000), 12);
+ EXPECT_GE(CountRange(send_bw_avg, 16000, 17000), 10);
+ EXPECT_GE(CountRange(send_bw_avg, 17000, 18000), 12);
+ EXPECT_GE(CountRange(send_bw_avg, 18000, 19000), 7);
+ EXPECT_GE(CountRange(send_bw_avg, 19000, 20000), 40);
+ EXPECT_GE(CountRange(send_bw_avg, 20000, 21000), 34);
+ EXPECT_EQ(CountRange(send_bw_avg, 21000, std::numeric_limits<int>::max()), 0);
+
+ // Check that we see a good spread of bottleneck_idx numbers.
+ EXPECT_EQ(bottleneck_idx.count(7), 1u);
+ EXPECT_EQ(CountRange(bottleneck_idx, std::numeric_limits<int>::min(), 12), 1);
+ EXPECT_GE(bottleneck_idx.count(12), 37u);
+ EXPECT_GE(bottleneck_idx.count(13), 18u);
+ EXPECT_GE(bottleneck_idx.count(14), 18u);
+ EXPECT_GE(bottleneck_idx.count(15), 18u);
+ EXPECT_GE(bottleneck_idx.count(16), 20u);
+ EXPECT_GE(bottleneck_idx.count(17), 19u);
+ EXPECT_GE(bottleneck_idx.count(18), 40u);
+ EXPECT_GE(bottleneck_idx.count(19), 32u);
+ EXPECT_EQ(CountRange(bottleneck_idx, 20, std::numeric_limits<int>::max()), 0);
+}
+
+} // namespace
+
+TEST(IsacCommonTest, GetSetBandwidthInfoFloat) {
+ TestGetSetBandwidthInfo<IsacFloat>(LoadSpeechData().data());
+}
+
+TEST(IsacCommonTest, GetSetBandwidthInfoFix) {
+ TestGetSetBandwidthInfo<IsacFix>(LoadSpeechData().data());
+}
+
+} // namespace webrtc

Powered by Google App Engine
This is Rietveld 408576698