mirror of
https://github.com/mollyim/webrtc.git
synced 2025-05-12 21:30:45 +01:00
iSAC API wrapper unit test fix
Use speech content instead of white noise and enable target vs measured bitrate tests. Bug: webrtc:11360 Change-Id: If8c8e73f943eda14efeb22ba406c7a1bed7d32b4 Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/168660 Commit-Queue: Alessio Bazzica <alessiob@webrtc.org> Reviewed-by: Karl Wiberg <kwiberg@webrtc.org> Cr-Commit-Position: refs/heads/master@{#30630}
This commit is contained in:
parent
4a6f81829b
commit
a7382f7879
6 changed files with 53 additions and 39 deletions
|
@ -57,6 +57,7 @@ rtc_source_set("module_fec_api") {
|
|||
|
||||
if (rtc_include_tests) {
|
||||
modules_tests_resources = [
|
||||
"../resources/audio_coding/testfile16kHz.pcm",
|
||||
"../resources/audio_coding/testfile32kHz.pcm",
|
||||
"../resources/audio_coding/teststereo32kHz.pcm",
|
||||
"../resources/foreman_cif.yuv",
|
||||
|
@ -111,6 +112,7 @@ if (rtc_include_tests) {
|
|||
"../resources/audio_coding/speech_4_channels_48k_one_second.wav",
|
||||
"../resources/audio_coding/speech_mono_16kHz.pcm",
|
||||
"../resources/audio_coding/speech_mono_32_48kHz.pcm",
|
||||
"../resources/audio_coding/testfile16kHz.pcm",
|
||||
"../resources/audio_coding/testfile32kHz.pcm",
|
||||
"../resources/audio_coding/testfile_fake_stereo_32kHz.pcm",
|
||||
"../resources/audio_coding/teststereo32kHz.pcm",
|
||||
|
|
|
@ -28,7 +28,6 @@ class AudioEncoderIsacT final : public AudioEncoder {
|
|||
// - 32000 Hz, 30 ms, 10000-56000 bps (if T has super-wideband support)
|
||||
struct Config {
|
||||
bool IsOk() const;
|
||||
|
||||
int payload_type = 103;
|
||||
int sample_rate_hz = 16000;
|
||||
int frame_size_ms = 30;
|
||||
|
|
|
@ -126,7 +126,7 @@ void AudioEncoderIsacT<T>::RecreateEncoderInstance(const Config& config) {
|
|||
if (isac_state_)
|
||||
RTC_CHECK_EQ(0, T::Free(isac_state_));
|
||||
RTC_CHECK_EQ(0, T::Create(&isac_state_));
|
||||
RTC_CHECK_EQ(0, T::EncoderInit(isac_state_, 1));
|
||||
RTC_CHECK_EQ(0, T::EncoderInit(isac_state_, /*coding_mode=*/1));
|
||||
RTC_CHECK_EQ(0, T::SetEncSampRate(isac_state_, config.sample_rate_hz));
|
||||
const int bit_rate = config.bit_rate == 0 ? kDefaultBitRate : config.bit_rate;
|
||||
RTC_CHECK_EQ(0, T::Control(isac_state_, bit_rate, config.frame_size_ms));
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
*/
|
||||
|
||||
#include <array>
|
||||
#include <limits>
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
#include "absl/strings/string_view.h"
|
||||
|
@ -18,9 +18,11 @@
|
|||
#include "api/audio_codecs/isac/audio_decoder_isac_float.h"
|
||||
#include "api/audio_codecs/isac/audio_encoder_isac_fix.h"
|
||||
#include "api/audio_codecs/isac/audio_encoder_isac_float.h"
|
||||
#include "rtc_base/random.h"
|
||||
#include "modules/audio_coding/test/PCMFile.h"
|
||||
#include "rtc_base/checks.h"
|
||||
#include "rtc_base/strings/string_builder.h"
|
||||
#include "test/gtest.h"
|
||||
#include "test/testsupport/file_utils.h"
|
||||
|
||||
namespace webrtc {
|
||||
namespace {
|
||||
|
@ -38,15 +40,31 @@ absl::string_view IsacImplToString(IsacImpl impl) {
|
|||
}
|
||||
}
|
||||
|
||||
std::vector<int16_t> GetRandomSamplesVector(size_t size) {
|
||||
constexpr int32_t kMin = std::numeric_limits<int16_t>::min();
|
||||
constexpr int32_t kMax = std::numeric_limits<int16_t>::max();
|
||||
std::vector<int16_t> v(size);
|
||||
Random gen(/*seed=*/42);
|
||||
for (auto& x : v) {
|
||||
x = static_cast<int16_t>(gen.Rand(kMin, kMax));
|
||||
std::unique_ptr<PCMFile> GetPcmTestFileReader(int sample_rate_hz) {
|
||||
std::string filename;
|
||||
switch (sample_rate_hz) {
|
||||
case 16000:
|
||||
filename = test::ResourcePath("audio_coding/testfile16kHz", "pcm");
|
||||
break;
|
||||
case 32000:
|
||||
filename = test::ResourcePath("audio_coding/testfile32kHz", "pcm");
|
||||
break;
|
||||
default:
|
||||
RTC_NOTREACHED() << "No test file available for " << sample_rate_hz
|
||||
<< " Hz.";
|
||||
}
|
||||
return v;
|
||||
auto pcm_file = std::make_unique<PCMFile>();
|
||||
pcm_file->ReadStereo(false);
|
||||
pcm_file->Open(filename, sample_rate_hz, "rb", /*auto_rewind=*/true);
|
||||
pcm_file->FastForward(/*num_10ms_blocks=*/100); // Skip initial silence.
|
||||
RTC_CHECK(!pcm_file->EndOfFile());
|
||||
return pcm_file;
|
||||
}
|
||||
|
||||
// Returns a view to the interleaved samples of an AudioFrame object.
|
||||
rtc::ArrayView<const int16_t> AudioFrameToView(const AudioFrame& audio_frame) {
|
||||
return {audio_frame.data(),
|
||||
audio_frame.samples_per_channel() * audio_frame.num_channels()};
|
||||
}
|
||||
|
||||
std::unique_ptr<AudioEncoder> CreateEncoder(IsacImpl impl,
|
||||
|
@ -119,6 +137,7 @@ TEST_P(EncoderTest, TestConfig) {
|
|||
// checks that the number of produces bytes in the first case is less than that
|
||||
// of the second case.
|
||||
TEST_P(EncoderTest, TestDifferentBitrates) {
|
||||
auto pcm_file = GetPcmTestFileReader(GetSampleRateHz());
|
||||
constexpr int kLowBps = 20000;
|
||||
constexpr int kHighBps = 25000;
|
||||
auto encoder_low = CreateEncoder(GetIsacImpl(), GetSampleRateHz(),
|
||||
|
@ -127,39 +146,39 @@ TEST_P(EncoderTest, TestDifferentBitrates) {
|
|||
GetFrameSizeMs(), kHighBps);
|
||||
int num_bytes_low = 0;
|
||||
int num_bytes_high = 0;
|
||||
const auto in = GetRandomSamplesVector(
|
||||
/*size=*/rtc::CheckedDivExact(GetSampleRateHz(), 100));
|
||||
constexpr int kNumFrames = 12;
|
||||
for (int i = 0; i < kNumFrames; ++i) {
|
||||
AudioFrame in;
|
||||
pcm_file->Read10MsData(in);
|
||||
rtc::Buffer low, high;
|
||||
encoder_low->Encode(/*rtp_timestamp=*/0, in, &low);
|
||||
encoder_high->Encode(/*rtp_timestamp=*/0, in, &high);
|
||||
encoder_low->Encode(/*rtp_timestamp=*/0, AudioFrameToView(in), &low);
|
||||
encoder_high->Encode(/*rtp_timestamp=*/0, AudioFrameToView(in), &high);
|
||||
num_bytes_low += low.size();
|
||||
num_bytes_high += high.size();
|
||||
}
|
||||
EXPECT_LT(num_bytes_low, num_bytes_high);
|
||||
}
|
||||
|
||||
// Checks that the target and the measured bitrates are within tolerance.
|
||||
// TODO(webrtc:11360): Add CBR flag to the config and re-enable test with CBR.
|
||||
TEST_P(EncoderTest, DISABLED_TestBitrateNearTarget) {
|
||||
const auto in = GetRandomSamplesVector(
|
||||
/*size=*/rtc::CheckedDivExact(GetSampleRateHz(), 100)); // 10 ms.
|
||||
// Checks that, given a target bitrate, the encoder does not overshoot too much.
|
||||
TEST_P(EncoderTest, DoNotOvershootTargetBitrate) {
|
||||
for (int bitrate_bps : {10000, 15000, 20000, 26000, 32000}) {
|
||||
SCOPED_TRACE(bitrate_bps);
|
||||
auto pcm_file = GetPcmTestFileReader(GetSampleRateHz());
|
||||
auto e = CreateEncoder(GetIsacImpl(), GetSampleRateHz(), GetFrameSizeMs(),
|
||||
bitrate_bps);
|
||||
int num_bytes = 0;
|
||||
constexpr int kNumFrames = 60;
|
||||
constexpr int kNumFrames = 200; // 2 seconds.
|
||||
for (int i = 0; i < kNumFrames; ++i) {
|
||||
AudioFrame in;
|
||||
pcm_file->Read10MsData(in);
|
||||
rtc::Buffer encoded;
|
||||
e->Encode(/*rtp_timestamp=*/0, in, &encoded);
|
||||
e->Encode(/*rtp_timestamp=*/0, AudioFrameToView(in), &encoded);
|
||||
num_bytes += encoded.size();
|
||||
}
|
||||
// Inverse of the duration of |kNumFrames| 10 ms frames (unit: seconds^-1).
|
||||
constexpr float kAudioDurationInv = 100.f / kNumFrames;
|
||||
const int measured_bitrate_bps = 8 * num_bytes * kAudioDurationInv;
|
||||
EXPECT_NEAR(bitrate_bps, measured_bitrate_bps, 1000); // Max 1 kbps.
|
||||
EXPECT_LT(measured_bitrate_bps, bitrate_bps + 2000); // Max 2 kbps extra.
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -227,27 +246,19 @@ struct EncoderDecoderPairTestParams {
|
|||
class EncoderDecoderPairTest
|
||||
: public testing::TestWithParam<EncoderDecoderPairTestParams> {
|
||||
protected:
|
||||
EncoderDecoderPairTest()
|
||||
: input_frame_(GetRandomSamplesVector(GetInputFrameSize())) {}
|
||||
rtc::ArrayView<const int16_t> GetInputFrame() { return input_frame_; }
|
||||
EncoderDecoderPairTest() = default;
|
||||
int GetSampleRateHz() const { return GetParam().sample_rate_hz; }
|
||||
int GetEncoderFrameSizeMs() const { return GetParam().frame_size_ms; }
|
||||
IsacImpl GetEncoderIsacImpl() const { return GetParam().encoder_impl; }
|
||||
IsacImpl GetDecoderIsacImpl() const { return GetParam().decoder_impl; }
|
||||
|
||||
int GetEncoderFrameSize() const {
|
||||
return GetEncoderFrameSizeMs() * GetSampleRateHz() / 1000;
|
||||
}
|
||||
|
||||
private:
|
||||
const std::vector<int16_t> input_frame_;
|
||||
int GetInputFrameSize() const {
|
||||
return rtc::CheckedDivExact(GetParam().sample_rate_hz, 100); // 10 ms.
|
||||
}
|
||||
};
|
||||
|
||||
// Checks that the number of encoded and decoded samples match.
|
||||
TEST_P(EncoderDecoderPairTest, EncodeDecode) {
|
||||
auto pcm_file = GetPcmTestFileReader(GetSampleRateHz());
|
||||
auto encoder = CreateEncoder(GetEncoderIsacImpl(), GetSampleRateHz(),
|
||||
GetEncoderFrameSizeMs(), /*bitrate_bps=*/20000);
|
||||
auto decoder = CreateDecoder(GetDecoderIsacImpl(), GetSampleRateHz());
|
||||
|
@ -257,10 +268,11 @@ TEST_P(EncoderDecoderPairTest, EncodeDecode) {
|
|||
size_t num_decoded_samples = 0;
|
||||
constexpr int kNumFrames = 12;
|
||||
for (int i = 0; i < kNumFrames; ++i) {
|
||||
AudioFrame in;
|
||||
pcm_file->Read10MsData(in);
|
||||
rtc::Buffer encoded;
|
||||
auto in = GetInputFrame();
|
||||
encoder->Encode(/*rtp_timestamp=*/0, in, &encoded);
|
||||
num_encoded_samples += in.size();
|
||||
encoder->Encode(/*rtp_timestamp=*/0, AudioFrameToView(in), &encoded);
|
||||
num_encoded_samples += in.samples_per_channel();
|
||||
if (encoded.empty()) {
|
||||
continue;
|
||||
}
|
||||
|
|
|
@ -304,7 +304,7 @@ typedef struct {
|
|||
int16_t maxRateInBytes;
|
||||
|
||||
/*---
|
||||
If set to 1 iSAC will not addapt the frame-size, if used in
|
||||
If set to 1 iSAC will not adapt the frame-size, if used in
|
||||
channel-adaptive mode. The initial value will be used for all rates.
|
||||
---*/
|
||||
int16_t enforceFrameSize;
|
||||
|
@ -312,7 +312,7 @@ typedef struct {
|
|||
/*-----
|
||||
This records the BWE index the encoder injected into the bit-stream.
|
||||
It will be used in RCU. The same BWE index of main payload will be in
|
||||
the redundant payload. We can not retrive it from BWE because it is
|
||||
the redundant payload. We can not retrieve it from BWE because it is
|
||||
a recursive procedure (WebRtcIsac_GetDownlinkBwJitIndexImpl) and has to be
|
||||
called only once per each encode.
|
||||
-----*/
|
||||
|
|
1
resources/audio_coding/testfile16kHz.pcm.sha1
Normal file
1
resources/audio_coding/testfile16kHz.pcm.sha1
Normal file
|
@ -0,0 +1 @@
|
|||
0d2702e5c350c2a4ad3a641c4d96271e8aa12e6c
|
Loading…
Reference in a new issue