blob: 400035353b18e7c98ec9f759137923124a296c96 [file] [log] [blame]
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:211/*
2 * Copyright (c) 2012 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
Philipp Hanckec4fe8252025-05-06 22:39:5411#include "api/audio_codecs/audio_decoder.h"
12
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:2113#include <stdlib.h>
14
Alessio Bazzicab28e57e2020-02-13 08:18:2415#include <array>
Philipp Hanckec4fe8252025-05-06 22:39:5416#include <cstdint>
kwiberg2d0c3322016-02-14 17:28:3317#include <memory>
Philipp Hanckec4fe8252025-05-06 22:39:5418#include <optional>
19#include <tuple>
20#include <utility>
henrik.lundin@webrtc.orga37f1dd2014-10-27 12:58:1821#include <vector>
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:2122
Philipp Hanckec4fe8252025-05-06 22:39:5423#include "api/array_view.h"
24#include "api/audio_codecs/audio_encoder.h"
25#include "api/audio_codecs/g722/audio_encoder_g722_config.h"
Mirko Bonadei92ea95e2017-09-15 04:47:3126#include "api/audio_codecs/opus/audio_encoder_opus.h"
Philipp Hanckec4fe8252025-05-06 22:39:5427#include "api/audio_codecs/opus/audio_encoder_opus_config.h"
Danil Chapovalov1932b442024-07-29 15:59:1928#include "api/environment/environment_factory.h"
Mirko Bonadei92ea95e2017-09-15 04:47:3129#include "modules/audio_coding/codecs/g711/audio_decoder_pcm.h"
30#include "modules/audio_coding/codecs/g711/audio_encoder_pcm.h"
31#include "modules/audio_coding/codecs/g722/audio_decoder_g722.h"
32#include "modules/audio_coding/codecs/g722/audio_encoder_g722.h"
Mirko Bonadei92ea95e2017-09-15 04:47:3133#include "modules/audio_coding/codecs/opus/audio_decoder_opus.h"
34#include "modules/audio_coding/codecs/pcm16b/audio_decoder_pcm16b.h"
35#include "modules/audio_coding/codecs/pcm16b/audio_encoder_pcm16b.h"
Philipp Hanckec4fe8252025-05-06 22:39:5436#include "modules/audio_coding/neteq/tools/input_audio_file.h"
Mirko Bonadei92ea95e2017-09-15 04:47:3137#include "modules/audio_coding/neteq/tools/resample_input_audio_file.h"
Philipp Hanckec4fe8252025-05-06 22:39:5438#include "rtc_base/buffer.h"
39#include "rtc_base/checks.h"
Danil Chapovalov24823c52024-08-16 12:27:4340#include "test/explicit_key_value_config.h"
Mirko Bonadei92ea95e2017-09-15 04:47:3141#include "test/gtest.h"
Steve Anton10542f22019-01-11 17:11:0042#include "test/testsupport/file_utils.h"
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:2143
44namespace webrtc {
45
henrik.lundin@webrtc.orga37f1dd2014-10-27 12:58:1846namespace {
Jakob Ivarsson36274f92020-10-22 11:01:0747
Danil Chapovalov24823c52024-08-16 12:27:4348using test::ExplicitKeyValueConfig;
49
Jakob Ivarsson36274f92020-10-22 11:01:0750constexpr int kOverheadBytesPerPacket = 50;
51
henrik.lundin@webrtc.orga37f1dd2014-10-27 12:58:1852// The absolute difference between the input and output (the first channel) is
Artem Titovd00ce742021-07-28 18:00:1753// compared vs `tolerance`. The parameter `delay` is used to correct for codec
henrik.lundin@webrtc.orga37f1dd2014-10-27 12:58:1854// delays.
55void CompareInputOutput(const std::vector<int16_t>& input,
56 const std::vector<int16_t>& output,
57 size_t num_samples,
58 size_t channels,
59 int tolerance,
60 int delay) {
61 ASSERT_LE(num_samples, input.size());
62 ASSERT_LE(num_samples * channels, output.size());
63 for (unsigned int n = 0; n < num_samples - delay; ++n) {
64 ASSERT_NEAR(input[n], output[channels * n + delay], tolerance)
65 << "Exit test on first diff; n = " << n;
henrik.lundin@webrtc.orga37f1dd2014-10-27 12:58:1866 }
67}
68
Artem Titovd00ce742021-07-28 18:00:1769// The absolute difference between the first two channels in `output` is
70// compared vs `tolerance`.
henrik.lundin@webrtc.orga37f1dd2014-10-27 12:58:1871void CompareTwoChannels(const std::vector<int16_t>& output,
72 size_t samples_per_channel,
73 size_t channels,
74 int tolerance) {
75 ASSERT_GE(channels, 2u);
76 ASSERT_LE(samples_per_channel * channels, output.size());
77 for (unsigned int n = 0; n < samples_per_channel; ++n)
78 ASSERT_NEAR(output[channels * n], output[channels * n + 1], tolerance)
79 << "Stereo samples differ.";
80}
81
82// Calculates mean-squared error between input and output (the first channel).
Artem Titovd00ce742021-07-28 18:00:1783// The parameter `delay` is used to correct for codec delays.
henrik.lundin@webrtc.orga37f1dd2014-10-27 12:58:1884double MseInputOutput(const std::vector<int16_t>& input,
85 const std::vector<int16_t>& output,
86 size_t num_samples,
87 size_t channels,
88 int delay) {
Mirko Bonadei25ab3222021-07-08 18:08:2089 RTC_DCHECK_LT(delay, static_cast<int>(num_samples));
90 RTC_DCHECK_LE(num_samples, input.size());
91 RTC_DCHECK_LE(num_samples * channels, output.size());
henrik.lundin@webrtc.orga37f1dd2014-10-27 12:58:1892 if (num_samples == 0)
93 return 0.0;
94 double squared_sum = 0.0;
95 for (unsigned int n = 0; n < num_samples - delay; ++n) {
96 squared_sum += (input[n] - output[channels * n + delay]) *
97 (input[n] - output[channels * n + delay]);
98 }
99 return squared_sum / (num_samples - delay);
100}
101} // namespace
102
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21103class AudioDecoderTest : public ::testing::Test {
104 protected:
105 AudioDecoderTest()
Evan Shrubsolebbb7c2e2025-05-09 10:36:25106 : input_audio_(test::ResourcePath("audio_coding/testfile32kHz", "pcm"),
107 32000),
henrik.lundin@webrtc.orga37f1dd2014-10-27 12:58:18108 codec_input_rate_hz_(32000), // Legacy default value.
henrik.lundin@webrtc.orgdef1e972014-10-21 12:48:29109 frame_size_(0),
110 data_length_(0),
henrik.lundin@webrtc.orgdef1e972014-10-21 12:48:29111 channels_(1),
henrik.lundin@webrtc.org7f1dfa52014-12-02 12:08:39112 payload_type_(17),
henrik.lundin@webrtc.orga37f1dd2014-10-27 12:58:18113 decoder_(NULL) {}
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21114
Mirko Bonadei682aac512018-07-20 11:59:20115 ~AudioDecoderTest() override {}
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21116
Mirko Bonadei682aac512018-07-20 11:59:20117 void SetUp() override {
henrik.lundin@webrtc.orga37f1dd2014-10-27 12:58:18118 if (audio_encoder_)
kwiberg@webrtc.org05211272015-02-18 12:00:32119 codec_input_rate_hz_ = audio_encoder_->SampleRateHz();
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21120 // Create arrays.
121 ASSERT_GT(data_length_, 0u) << "The test must set data_length_ > 0";
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21122 }
123
Mirko Bonadei682aac512018-07-20 11:59:20124 void TearDown() override {
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21125 delete decoder_;
126 decoder_ = NULL;
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21127 }
128
Yves Gerey665174f2018-06-19 13:03:05129 virtual void InitEncoder() {}
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21130
henrik.lundin@webrtc.orgdef1e972014-10-21 12:48:29131 // TODO(henrik.lundin) Change return type to size_t once most/all overriding
132 // implementations are gone.
133 virtual int EncodeFrame(const int16_t* input,
134 size_t input_len_samples,
Evan Shrubsolea0ea43e2025-04-15 14:52:55135 Buffer* output) {
ossu10a029e2016-03-01 08:41:31136 AudioEncoder::EncodedInfo encoded_info;
kwiberg@webrtc.org05211272015-02-18 12:00:32137 const size_t samples_per_10ms = audio_encoder_->SampleRateHz() / 100;
henrikg91d6ede2015-09-17 07:24:34138 RTC_CHECK_EQ(samples_per_10ms * audio_encoder_->Num10MsFramesInNextPacket(),
139 input_len_samples);
kwiberg2d0c3322016-02-14 17:28:33140 std::unique_ptr<int16_t[]> interleaved_input(
henrik.lundin@webrtc.org130fef82014-12-08 21:07:59141 new int16_t[channels_ * samples_per_10ms]);
Peter Kastingdce40cf2015-08-24 21:52:23142 for (size_t i = 0; i < audio_encoder_->Num10MsFramesInNextPacket(); ++i) {
ossu10a029e2016-03-01 08:41:31143 EXPECT_EQ(0u, encoded_info.encoded_bytes);
kwiberg@webrtc.org663fdd02014-10-29 07:28:36144
145 // Duplicate the mono input signal to however many channels the test
146 // wants.
henrik.lundin@webrtc.org130fef82014-12-08 21:07:59147 test::InputAudioFile::DuplicateInterleaved(input + i * samples_per_10ms,
148 samples_per_10ms, channels_,
149 interleaved_input.get());
kwiberg@webrtc.org663fdd02014-10-29 07:28:36150
Evan Shrubsolea0ea43e2025-04-15 14:52:55151 encoded_info = audio_encoder_->Encode(
152 0,
153 ArrayView<const int16_t>(interleaved_input.get(),
154 audio_encoder_->NumChannels() *
155 audio_encoder_->SampleRateHz() / 100),
156 output);
henrik.lundin@webrtc.orgdef1e972014-10-21 12:48:29157 }
ossu10a029e2016-03-01 08:41:31158 EXPECT_EQ(payload_type_, encoded_info.payload_type);
159 return static_cast<int>(encoded_info.encoded_bytes);
henrik.lundin@webrtc.orgdef1e972014-10-21 12:48:29160 }
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21161
162 // Encodes and decodes audio. The absolute difference between the input and
Artem Titovd00ce742021-07-28 18:00:17163 // output is compared vs `tolerance`, and the mean-squared error is compared
164 // with `mse`. The encoded stream should contain `expected_bytes`. For stereo
minyue@webrtc.orgecbe0aa2013-08-12 06:48:09165 // audio, the absolute difference between the two channels is compared vs
Artem Titovd00ce742021-07-28 18:00:17166 // `channel_diff_tolerance`.
Yves Gerey665174f2018-06-19 13:03:05167 void EncodeDecodeTest(size_t expected_bytes,
168 int tolerance,
169 double mse,
170 int delay = 0,
171 int channel_diff_tolerance = 0) {
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21172 ASSERT_GE(tolerance, 0) << "Test must define a tolerance >= 0";
Yves Gerey665174f2018-06-19 13:03:05173 ASSERT_GE(channel_diff_tolerance, 0)
174 << "Test must define a channel_diff_tolerance >= 0";
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21175 size_t processed_samples = 0u;
ossu10a029e2016-03-01 08:41:31176 size_t encoded_bytes = 0u;
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21177 InitEncoder();
henrik.lundin@webrtc.orga37f1dd2014-10-27 12:58:18178 std::vector<int16_t> input;
179 std::vector<int16_t> decoded;
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21180 while (processed_samples + frame_size_ <= data_length_) {
Artem Titovd00ce742021-07-28 18:00:17181 // Extend input vector with `frame_size_`.
henrik.lundin@webrtc.orga37f1dd2014-10-27 12:58:18182 input.resize(input.size() + frame_size_, 0);
183 // Read from input file.
184 ASSERT_GE(input.size() - processed_samples, frame_size_);
Yves Gerey665174f2018-06-19 13:03:05185 ASSERT_TRUE(input_audio_.Read(frame_size_, codec_input_rate_hz_,
186 &input[processed_samples]));
Evan Shrubsolea0ea43e2025-04-15 14:52:55187 Buffer encoded;
Yves Gerey665174f2018-06-19 13:03:05188 size_t enc_len =
189 EncodeFrame(&input[processed_samples], frame_size_, &encoded);
henrik.lundin@webrtc.orga37f1dd2014-10-27 12:58:18190 // Make sure that frame_size_ * channels_ samples are allocated and free.
191 decoded.resize((processed_samples + frame_size_) * channels_, 0);
Alessio Bazzicab28e57e2020-02-13 08:18:24192
193 const std::vector<AudioDecoder::ParseResult> parse_result =
194 decoder_->ParsePayload(std::move(encoded), /*timestamp=*/0);
195 RTC_CHECK_EQ(parse_result.size(), size_t{1});
196 auto decode_result = parse_result[0].frame->Decode(
Evan Shrubsolea0ea43e2025-04-15 14:52:55197 ArrayView<int16_t>(&decoded[processed_samples * channels_],
198 frame_size_ * channels_ * sizeof(int16_t)));
Alessio Bazzicab28e57e2020-02-13 08:18:24199 RTC_CHECK(decode_result.has_value());
200 EXPECT_EQ(frame_size_ * channels_, decode_result->num_decoded_samples);
ossu10a029e2016-03-01 08:41:31201 encoded_bytes += enc_len;
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21202 processed_samples += frame_size_;
203 }
tina.legrand@webrtc.org8418e962013-11-29 09:30:43204 // For some codecs it doesn't make sense to check expected number of bytes,
Alessio Bazzica17887eb2022-11-11 15:52:46205 // since the number can vary for different platforms. Opus is such a codec.
206 // In this case expected_bytes is set to 0.
tina.legrand@webrtc.org8418e962013-11-29 09:30:43207 if (expected_bytes) {
ossu10a029e2016-03-01 08:41:31208 EXPECT_EQ(expected_bytes, encoded_bytes);
tina.legrand@webrtc.org8418e962013-11-29 09:30:43209 }
Yves Gerey665174f2018-06-19 13:03:05210 CompareInputOutput(input, decoded, processed_samples, channels_, tolerance,
211 delay);
minyue@webrtc.orgecbe0aa2013-08-12 06:48:09212 if (channels_ == 2)
Yves Gerey665174f2018-06-19 13:03:05213 CompareTwoChannels(decoded, processed_samples, channels_,
214 channel_diff_tolerance);
henrik.lundin@webrtc.orga37f1dd2014-10-27 12:58:18215 EXPECT_LE(
216 MseInputOutput(input, decoded, processed_samples, channels_, delay),
217 mse);
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21218 }
219
220 // Encodes a payload and decodes it twice with decoder re-init before each
221 // decode. Verifies that the decoded result is the same.
222 void ReInitTest() {
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21223 InitEncoder();
kwiberg2d0c3322016-02-14 17:28:33224 std::unique_ptr<int16_t[]> input(new int16_t[frame_size_]);
henrik.lundin@webrtc.orga37f1dd2014-10-27 12:58:18225 ASSERT_TRUE(
226 input_audio_.Read(frame_size_, codec_input_rate_hz_, input.get()));
Evan Shrubsolea0ea43e2025-04-15 14:52:55227 std::array<Buffer, 2> encoded;
Alessio Bazzicab28e57e2020-02-13 08:18:24228 EncodeFrame(input.get(), frame_size_, &encoded[0]);
229 // Make a copy.
230 encoded[1].SetData(encoded[0].data(), encoded[0].size());
231
232 std::array<std::vector<int16_t>, 2> outputs;
233 for (size_t i = 0; i < outputs.size(); ++i) {
234 outputs[i].resize(frame_size_ * channels_);
235 decoder_->Reset();
236 const std::vector<AudioDecoder::ParseResult> parse_result =
237 decoder_->ParsePayload(std::move(encoded[i]), /*timestamp=*/0);
238 RTC_CHECK_EQ(parse_result.size(), size_t{1});
239 auto decode_result = parse_result[0].frame->Decode(outputs[i]);
240 RTC_CHECK(decode_result.has_value());
241 EXPECT_EQ(frame_size_ * channels_, decode_result->num_decoded_samples);
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21242 }
Alessio Bazzicab28e57e2020-02-13 08:18:24243 EXPECT_EQ(outputs[0], outputs[1]);
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21244 }
245
246 // Call DecodePlc and verify that the correct number of samples is produced.
247 void DecodePlcTest() {
248 InitEncoder();
kwiberg2d0c3322016-02-14 17:28:33249 std::unique_ptr<int16_t[]> input(new int16_t[frame_size_]);
henrik.lundin@webrtc.orga37f1dd2014-10-27 12:58:18250 ASSERT_TRUE(
251 input_audio_.Read(frame_size_, codec_input_rate_hz_, input.get()));
Evan Shrubsolea0ea43e2025-04-15 14:52:55252 Buffer encoded;
Alessio Bazzicab28e57e2020-02-13 08:18:24253 EncodeFrame(input.get(), frame_size_, &encoded);
Karl Wiberg43766482015-08-27 13:22:11254 decoder_->Reset();
Alessio Bazzicab28e57e2020-02-13 08:18:24255 std::vector<int16_t> output(frame_size_ * channels_);
256 const std::vector<AudioDecoder::ParseResult> parse_result =
257 decoder_->ParsePayload(std::move(encoded), /*timestamp=*/0);
258 RTC_CHECK_EQ(parse_result.size(), size_t{1});
259 auto decode_result = parse_result[0].frame->Decode(output);
260 RTC_CHECK(decode_result.has_value());
261 EXPECT_EQ(frame_size_ * channels_, decode_result->num_decoded_samples);
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21262 // Call DecodePlc and verify that we get one frame of data.
263 // (Overwrite the output from the above Decode call, but that does not
264 // matter.)
Alessio Bazzicab28e57e2020-02-13 08:18:24265 size_t dec_len =
266 decoder_->DecodePlc(/*num_frames=*/1, /*decoded=*/output.data());
turaj@webrtc.org6ad6a072013-09-30 20:07:39267 EXPECT_EQ(frame_size_ * channels_, dec_len);
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21268 }
269
henrik.lundin@webrtc.orga37f1dd2014-10-27 12:58:18270 test::ResampleInputAudioFile input_audio_;
271 int codec_input_rate_hz_;
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21272 size_t frame_size_;
273 size_t data_length_;
henrik.lundin@webrtc.orgaaad6132013-02-01 11:49:28274 size_t channels_;
henrik.lundin@webrtc.org7f1dfa52014-12-02 12:08:39275 const int payload_type_;
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21276 AudioDecoder* decoder_;
kwiberg2d0c3322016-02-14 17:28:33277 std::unique_ptr<AudioEncoder> audio_encoder_;
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21278};
279
280class AudioDecoderPcmUTest : public AudioDecoderTest {
281 protected:
282 AudioDecoderPcmUTest() : AudioDecoderTest() {
283 frame_size_ = 160;
284 data_length_ = 10 * frame_size_;
kwiberg89671832015-09-22 21:06:29285 decoder_ = new AudioDecoderPcmU(1);
henrik.lundin@webrtc.orgdef1e972014-10-21 12:48:29286 AudioEncoderPcmU::Config config;
287 config.frame_size_ms = static_cast<int>(frame_size_ / 8);
henrik.lundin@webrtc.org7f1dfa52014-12-02 12:08:39288 config.payload_type = payload_type_;
henrik.lundin@webrtc.orgdef1e972014-10-21 12:48:29289 audio_encoder_.reset(new AudioEncoderPcmU(config));
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21290 }
291};
292
293class AudioDecoderPcmATest : public AudioDecoderTest {
294 protected:
295 AudioDecoderPcmATest() : AudioDecoderTest() {
296 frame_size_ = 160;
297 data_length_ = 10 * frame_size_;
kwiberg89671832015-09-22 21:06:29298 decoder_ = new AudioDecoderPcmA(1);
henrik.lundin@webrtc.orgdef1e972014-10-21 12:48:29299 AudioEncoderPcmA::Config config;
300 config.frame_size_ms = static_cast<int>(frame_size_ / 8);
henrik.lundin@webrtc.org7f1dfa52014-12-02 12:08:39301 config.payload_type = payload_type_;
henrik.lundin@webrtc.orgdef1e972014-10-21 12:48:29302 audio_encoder_.reset(new AudioEncoderPcmA(config));
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21303 }
304};
305
306class AudioDecoderPcm16BTest : public AudioDecoderTest {
307 protected:
308 AudioDecoderPcm16BTest() : AudioDecoderTest() {
henrik.lundin@webrtc.org817e50d2014-12-11 10:47:19309 codec_input_rate_hz_ = 16000;
310 frame_size_ = 20 * codec_input_rate_hz_ / 1000;
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21311 data_length_ = 10 * frame_size_;
kwiberg6c2eab32016-05-31 09:46:20312 decoder_ = new AudioDecoderPcm16B(codec_input_rate_hz_, 1);
Mirko Bonadei25ab3222021-07-08 18:08:20313 RTC_DCHECK(decoder_);
henrik.lundin@webrtc.org817e50d2014-12-11 10:47:19314 AudioEncoderPcm16B::Config config;
315 config.sample_rate_hz = codec_input_rate_hz_;
316 config.frame_size_ms =
317 static_cast<int>(frame_size_ / (config.sample_rate_hz / 1000));
318 config.payload_type = payload_type_;
319 audio_encoder_.reset(new AudioEncoderPcm16B(config));
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21320 }
321};
322
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21323class AudioDecoderG722Test : public AudioDecoderTest {
324 protected:
325 AudioDecoderG722Test() : AudioDecoderTest() {
henrik.lundin@webrtc.orga37f1dd2014-10-27 12:58:18326 codec_input_rate_hz_ = 16000;
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21327 frame_size_ = 160;
328 data_length_ = 10 * frame_size_;
kwibergb1ed7f02017-06-18 00:30:09329 decoder_ = new AudioDecoderG722Impl;
Mirko Bonadei25ab3222021-07-08 18:08:20330 RTC_DCHECK(decoder_);
kwibergb8727ae2017-06-18 00:41:59331 AudioEncoderG722Config config;
kwiberg@webrtc.org0cd55582014-12-02 11:45:51332 config.frame_size_ms = 10;
333 config.num_channels = 1;
kwibergb8727ae2017-06-18 00:41:59334 audio_encoder_.reset(new AudioEncoderG722Impl(config, payload_type_));
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21335 }
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21336};
337
kwiberg@webrtc.org0cd55582014-12-02 11:45:51338class AudioDecoderG722StereoTest : public AudioDecoderTest {
henrik.lundin@webrtc.orgaaad6132013-02-01 11:49:28339 protected:
kwiberg@webrtc.org0cd55582014-12-02 11:45:51340 AudioDecoderG722StereoTest() : AudioDecoderTest() {
henrik.lundin@webrtc.orgaaad6132013-02-01 11:49:28341 channels_ = 2;
kwiberg@webrtc.org0cd55582014-12-02 11:45:51342 codec_input_rate_hz_ = 16000;
343 frame_size_ = 160;
344 data_length_ = 10 * frame_size_;
kwiberg1b97e262017-06-26 11:19:43345 decoder_ = new AudioDecoderG722StereoImpl;
Mirko Bonadei25ab3222021-07-08 18:08:20346 RTC_DCHECK(decoder_);
kwibergb8727ae2017-06-18 00:41:59347 AudioEncoderG722Config config;
kwiberg@webrtc.org0cd55582014-12-02 11:45:51348 config.frame_size_ms = 10;
349 config.num_channels = 2;
kwibergb8727ae2017-06-18 00:41:59350 audio_encoder_.reset(new AudioEncoderG722Impl(config, payload_type_));
henrik.lundin@webrtc.orgaaad6132013-02-01 11:49:28351 }
352};
353
Karl Wiberg7eb0a5e2019-05-29 11:46:09354class AudioDecoderOpusTest
355 : public AudioDecoderTest,
356 public testing::WithParamInterface<std::tuple<int, int>> {
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21357 protected:
358 AudioDecoderOpusTest() : AudioDecoderTest() {
Karl Wiberg7eb0a5e2019-05-29 11:46:09359 channels_ = opus_num_channels_;
360 codec_input_rate_hz_ = opus_sample_rate_hz_;
Evan Shrubsolea0ea43e2025-04-15 14:52:55361 frame_size_ = CheckedDivExact(opus_sample_rate_hz_, 100);
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21362 data_length_ = 10 * frame_size_;
Danil Chapovalov24823c52024-08-16 12:27:43363 decoder_ = new AudioDecoderOpusImpl(
364 ExplicitKeyValueConfig(""), opus_num_channels_, opus_sample_rate_hz_);
kwiberg96da0112017-06-30 11:23:22365 AudioEncoderOpusConfig config;
Karl Wiberg7eb0a5e2019-05-29 11:46:09366 config.frame_size_ms = 10;
367 config.sample_rate_hz = opus_sample_rate_hz_;
368 config.num_channels = opus_num_channels_;
369 config.application = opus_num_channels_ == 1
370 ? AudioEncoderOpusConfig::ApplicationMode::kVoip
371 : AudioEncoderOpusConfig::ApplicationMode::kAudio;
Danil Chapovalov1932b442024-07-29 15:59:19372 audio_encoder_ = AudioEncoderOpus::MakeAudioEncoder(
373 CreateEnvironment(), config, {.payload_type = payload_type_});
Jakob Ivarsson36274f92020-10-22 11:01:07374 audio_encoder_->OnReceivedOverhead(kOverheadBytesPerPacket);
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21375 }
Karl Wiberg7eb0a5e2019-05-29 11:46:09376 const int opus_sample_rate_hz_{std::get<0>(GetParam())};
377 const int opus_num_channels_{std::get<1>(GetParam())};
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21378};
379
Karl Wiberg7eb0a5e2019-05-29 11:46:09380INSTANTIATE_TEST_SUITE_P(Param,
381 AudioDecoderOpusTest,
382 testing::Combine(testing::Values(16000, 48000),
383 testing::Values(1, 2)));
minyue@webrtc.orgecbe0aa2013-08-12 06:48:09384
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21385TEST_F(AudioDecoderPcmUTest, EncodeDecode) {
386 int tolerance = 251;
387 double mse = 1734.0;
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21388 EncodeDecodeTest(data_length_, tolerance, mse);
389 ReInitTest();
390 EXPECT_FALSE(decoder_->HasDecodePlc());
391}
392
Henrik Lundin3e89dbf2015-06-18 12:58:34393namespace {
394int SetAndGetTargetBitrate(AudioEncoder* audio_encoder, int rate) {
Florent Castelli8037fc62024-08-29 13:00:40395 audio_encoder->OnReceivedUplinkBandwidth(rate, std::nullopt);
Henrik Lundin3e89dbf2015-06-18 12:58:34396 return audio_encoder->GetTargetBitrate();
397}
398void TestSetAndGetTargetBitratesWithFixedCodec(AudioEncoder* audio_encoder,
399 int fixed_rate) {
400 EXPECT_EQ(fixed_rate, SetAndGetTargetBitrate(audio_encoder, 32000));
401 EXPECT_EQ(fixed_rate, SetAndGetTargetBitrate(audio_encoder, fixed_rate - 1));
402 EXPECT_EQ(fixed_rate, SetAndGetTargetBitrate(audio_encoder, fixed_rate));
403 EXPECT_EQ(fixed_rate, SetAndGetTargetBitrate(audio_encoder, fixed_rate + 1));
404}
405} // namespace
406
407TEST_F(AudioDecoderPcmUTest, SetTargetBitrate) {
408 TestSetAndGetTargetBitratesWithFixedCodec(audio_encoder_.get(), 64000);
409}
410
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21411TEST_F(AudioDecoderPcmATest, EncodeDecode) {
412 int tolerance = 308;
413 double mse = 1931.0;
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21414 EncodeDecodeTest(data_length_, tolerance, mse);
415 ReInitTest();
416 EXPECT_FALSE(decoder_->HasDecodePlc());
417}
418
Henrik Lundin3e89dbf2015-06-18 12:58:34419TEST_F(AudioDecoderPcmATest, SetTargetBitrate) {
420 TestSetAndGetTargetBitratesWithFixedCodec(audio_encoder_.get(), 64000);
421}
422
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21423TEST_F(AudioDecoderPcm16BTest, EncodeDecode) {
424 int tolerance = 0;
425 double mse = 0.0;
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21426 EncodeDecodeTest(2 * data_length_, tolerance, mse);
427 ReInitTest();
428 EXPECT_FALSE(decoder_->HasDecodePlc());
429}
430
Henrik Lundin3e89dbf2015-06-18 12:58:34431TEST_F(AudioDecoderPcm16BTest, SetTargetBitrate) {
432 TestSetAndGetTargetBitratesWithFixedCodec(audio_encoder_.get(),
433 codec_input_rate_hz_ * 16);
434}
435
Mirko Bonadei32fdb042024-06-07 08:09:28436// TODO(bugs.webrtc.org/345525069): Either fix/enable or remove G722.
437#if defined(__has_feature) && __has_feature(undefined_behavior_sanitizer)
438TEST_F(AudioDecoderG722Test, DISABLED_EncodeDecode) {
439#else
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21440TEST_F(AudioDecoderG722Test, EncodeDecode) {
Mirko Bonadei32fdb042024-06-07 08:09:28441#endif
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21442 int tolerance = 6176;
443 double mse = 238630.0;
444 int delay = 22; // Delay from input to output.
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21445 EncodeDecodeTest(data_length_ / 2, tolerance, mse, delay);
446 ReInitTest();
447 EXPECT_FALSE(decoder_->HasDecodePlc());
448}
449
Henrik Lundin3e89dbf2015-06-18 12:58:34450TEST_F(AudioDecoderG722Test, SetTargetBitrate) {
451 TestSetAndGetTargetBitratesWithFixedCodec(audio_encoder_.get(), 64000);
452}
453
Mirko Bonadei32fdb042024-06-07 08:09:28454// TODO(bugs.webrtc.org/345525069): Either fix/enable or remove G722.
455#if defined(__has_feature) && __has_feature(undefined_behavior_sanitizer)
Mirko Bonadei32fdb042024-06-07 08:09:28456TEST_F(AudioDecoderG722StereoTest, DISABLED_EncodeDecode) {
Mirko Bonadei33e6e802024-06-07 14:06:51457#else
458TEST_F(AudioDecoderG722StereoTest, EncodeDecode) {
Mirko Bonadei32fdb042024-06-07 08:09:28459#endif
henrik.lundin@webrtc.orgaaad6132013-02-01 11:49:28460 int tolerance = 6176;
minyue@webrtc.orgecbe0aa2013-08-12 06:48:09461 int channel_diff_tolerance = 0;
henrik.lundin@webrtc.orgaaad6132013-02-01 11:49:28462 double mse = 238630.0;
463 int delay = 22; // Delay from input to output.
minyue@webrtc.orgecbe0aa2013-08-12 06:48:09464 EncodeDecodeTest(data_length_, tolerance, mse, delay, channel_diff_tolerance);
henrik.lundin@webrtc.orgaaad6132013-02-01 11:49:28465 ReInitTest();
466 EXPECT_FALSE(decoder_->HasDecodePlc());
467}
468
Henrik Lundin3e89dbf2015-06-18 12:58:34469TEST_F(AudioDecoderG722StereoTest, SetTargetBitrate) {
470 TestSetAndGetTargetBitratesWithFixedCodec(audio_encoder_.get(), 128000);
471}
472
Jakob Ivarsson213dc2c2021-03-10 11:38:34473// TODO(http://bugs.webrtc.org/12518): Enable the test after Opus has been
474// updated.
475TEST_P(AudioDecoderOpusTest, DISABLED_EncodeDecode) {
Karl Wiberg7eb0a5e2019-05-29 11:46:09476 constexpr int tolerance = 6176;
Ivo Creusen16ddae92020-03-04 16:16:59477 constexpr int channel_diff_tolerance = 6;
Karl Wiberg7eb0a5e2019-05-29 11:46:09478 constexpr double mse = 238630.0;
479 constexpr int delay = 22; // Delay from input to output.
tina.legrand@webrtc.org8418e962013-11-29 09:30:43480 EncodeDecodeTest(0, tolerance, mse, delay, channel_diff_tolerance);
minyue@webrtc.orgecbe0aa2013-08-12 06:48:09481 ReInitTest();
482 EXPECT_FALSE(decoder_->HasDecodePlc());
483}
484
Karl Wiberg7eb0a5e2019-05-29 11:46:09485TEST_P(AudioDecoderOpusTest, SetTargetBitrate) {
Jakob Ivarsson36274f92020-10-22 11:01:07486 const int overhead_rate =
487 8 * kOverheadBytesPerPacket * codec_input_rate_hz_ / frame_size_;
488 EXPECT_EQ(6000,
489 SetAndGetTargetBitrate(audio_encoder_.get(), 5999 + overhead_rate));
490 EXPECT_EQ(6000,
491 SetAndGetTargetBitrate(audio_encoder_.get(), 6000 + overhead_rate));
492 EXPECT_EQ(32000, SetAndGetTargetBitrate(audio_encoder_.get(),
493 32000 + overhead_rate));
494 EXPECT_EQ(510000, SetAndGetTargetBitrate(audio_encoder_.get(),
495 510000 + overhead_rate));
496 EXPECT_EQ(510000, SetAndGetTargetBitrate(audio_encoder_.get(),
497 511000 + overhead_rate));
Henrik Lundin3e89dbf2015-06-18 12:58:34498}
499
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21500} // namespace webrtc