blob: 50178a9bf97da26694e0798e638d0c4583028a03 [file] [log] [blame]
tina.legrand@webrtc.orgdb11fab2013-04-17 10:39:41 +00001/*
2 * Copyright (c) 2013 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 */
kwiberg91d97562016-02-14 01:10:03 -080010
11#include <memory>
tina.legrand@webrtc.orgdb11fab2013-04-17 10:39:41 +000012#include <string>
13
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020014#include "modules/audio_coding/codecs/opus/opus_inst.h"
15#include "modules/audio_coding/codecs/opus/opus_interface.h"
16#include "modules/audio_coding/neteq/tools/audio_loop.h"
17#include "rtc_base/checks.h"
Karl Wiberge40468b2017-11-22 10:42:26 +010018#include "rtc_base/numerics/safe_conversions.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020019#include "test/gtest.h"
Steve Anton10542f22019-01-11 09:11:00 -080020#include "test/testsupport/file_utils.h"
tina.legrand@webrtc.orgdb11fab2013-04-17 10:39:41 +000021
tina.legrand@webrtc.orgdb11fab2013-04-17 10:39:41 +000022namespace webrtc {
23
minyue@webrtc.org0ca768b2014-12-11 16:09:35 +000024using test::AudioLoop;
minyue@webrtc.org7dba7862015-01-20 16:01:50 +000025using ::testing::TestWithParam;
26using ::testing::Values;
27using ::testing::Combine;
minyue@webrtc.org0ca768b2014-12-11 16:09:35 +000028
tina.legrand@webrtc.orgdb11fab2013-04-17 10:39:41 +000029// Maximum number of bytes in output bitstream.
Alex Loiko83ed89a2019-01-17 12:32:11 +010030const size_t kMaxBytes = 2000;
minyue@webrtc.org0ca768b2014-12-11 16:09:35 +000031// Sample rate of Opus.
Peter Kastingdce40cf2015-08-24 14:52:23 -070032const size_t kOpusRateKhz = 48;
minyue@webrtc.orgf563e852014-07-18 21:11:27 +000033// Number of samples-per-channel in a 20 ms frame, sampled at 48 kHz.
Peter Kastingdce40cf2015-08-24 14:52:23 -070034const size_t kOpus20msFrameSamples = kOpusRateKhz * 20;
minyue@webrtc.orgf563e852014-07-18 21:11:27 +000035// Number of samples-per-channel in a 10 ms frame, sampled at 48 kHz.
Peter Kastingdce40cf2015-08-24 14:52:23 -070036const size_t kOpus10msFrameSamples = kOpusRateKhz * 10;
tina.legrand@webrtc.orgdb11fab2013-04-17 10:39:41 +000037
minyue@webrtc.org7dba7862015-01-20 16:01:50 +000038class OpusTest : public TestWithParam<::testing::tuple<int, int>> {
tina.legrand@webrtc.orgdb11fab2013-04-17 10:39:41 +000039 protected:
40 OpusTest();
tina.legrand@webrtc.orgdb11fab2013-04-17 10:39:41 +000041
minyue3cea2562015-11-10 03:49:26 -080042 void TestDtxEffect(bool dtx, int block_length_ms);
minyue@webrtc.org0ca768b2014-12-11 16:09:35 +000043
soren28dc2852017-04-06 05:48:36 -070044 void TestCbrEffect(bool dtx, int block_length_ms);
45
minyue@webrtc.org0ca768b2014-12-11 16:09:35 +000046 // Prepare |speech_data_| for encoding, read from a hard-coded file.
47 // After preparation, |speech_data_.GetNextBlock()| returns a pointer to a
48 // block of |block_length_ms| milliseconds. The data is looped every
49 // |loop_length_ms| milliseconds.
Peter Kasting69558702016-01-12 16:26:35 -080050 void PrepareSpeechData(size_t channel,
51 int block_length_ms,
52 int loop_length_ms);
minyue@webrtc.org0ca768b2014-12-11 16:09:35 +000053
54 int EncodeDecode(WebRtcOpusEncInst* encoder,
kwiberg288886b2015-11-06 01:21:35 -080055 rtc::ArrayView<const int16_t> input_audio,
minyue@webrtc.org0ca768b2014-12-11 16:09:35 +000056 WebRtcOpusDecInst* decoder,
57 int16_t* output_audio,
58 int16_t* audio_type);
minyue@webrtc.org0040a6e2014-08-04 14:41:57 +000059
minyue@webrtc.org7dba7862015-01-20 16:01:50 +000060 void SetMaxPlaybackRate(WebRtcOpusEncInst* encoder,
Yves Gerey665174f2018-06-19 15:03:05 +020061 opus_int32 expect,
62 int32_t set);
minyue@webrtc.org7dba7862015-01-20 16:01:50 +000063
Yves Gerey665174f2018-06-19 15:03:05 +020064 void CheckAudioBounded(const int16_t* audio,
65 size_t samples,
66 size_t channels,
minyue3cea2562015-11-10 03:49:26 -080067 uint16_t bound) const;
68
minyue@webrtc.org7dba7862015-01-20 16:01:50 +000069 WebRtcOpusEncInst* opus_encoder_;
70 WebRtcOpusDecInst* opus_decoder_;
tina.legrand@webrtc.orgdb11fab2013-04-17 10:39:41 +000071
minyue@webrtc.org0ca768b2014-12-11 16:09:35 +000072 AudioLoop speech_data_;
tina.legrand@webrtc.orgdb11fab2013-04-17 10:39:41 +000073 uint8_t bitstream_[kMaxBytes];
Peter Kastingdce40cf2015-08-24 14:52:23 -070074 size_t encoded_bytes_;
Peter Kasting69558702016-01-12 16:26:35 -080075 size_t channels_;
minyue@webrtc.org7dba7862015-01-20 16:01:50 +000076 int application_;
tina.legrand@webrtc.orgdb11fab2013-04-17 10:39:41 +000077};
78
79OpusTest::OpusTest()
minyue@webrtc.org7dba7862015-01-20 16:01:50 +000080 : opus_encoder_(NULL),
81 opus_decoder_(NULL),
82 encoded_bytes_(0),
Peter Kasting69558702016-01-12 16:26:35 -080083 channels_(static_cast<size_t>(::testing::get<0>(GetParam()))),
Yves Gerey665174f2018-06-19 15:03:05 +020084 application_(::testing::get<1>(GetParam())) {}
tina.legrand@webrtc.orgdb11fab2013-04-17 10:39:41 +000085
Yves Gerey665174f2018-06-19 15:03:05 +020086void OpusTest::PrepareSpeechData(size_t channel,
87 int block_length_ms,
minyue@webrtc.org0ca768b2014-12-11 16:09:35 +000088 int loop_length_ms) {
Alex Loiko83ed89a2019-01-17 12:32:11 +010089 std::map<int, std::string> channel_to_basename = {
90 {1, "audio_coding/testfile32kHz"},
91 {2, "audio_coding/teststereo32kHz"},
92 {4, "audio_coding/speech_4_channels_48k_one_second"}};
93 std::map<int, std::string> channel_to_suffix = {
94 {1, "pcm"}, {2, "pcm"}, {4, "wav"}};
Yves Gerey665174f2018-06-19 15:03:05 +020095 const std::string file_name = webrtc::test::ResourcePath(
Alex Loiko83ed89a2019-01-17 12:32:11 +010096 channel_to_basename[channel], channel_to_suffix[channel]);
minyue@webrtc.org0ca768b2014-12-11 16:09:35 +000097 if (loop_length_ms < block_length_ms) {
98 loop_length_ms = block_length_ms;
99 }
100 EXPECT_TRUE(speech_data_.Init(file_name,
101 loop_length_ms * kOpusRateKhz * channel,
102 block_length_ms * kOpusRateKhz * channel));
tina.legrand@webrtc.orgdb11fab2013-04-17 10:39:41 +0000103}
104
minyue@webrtc.org7dba7862015-01-20 16:01:50 +0000105void OpusTest::SetMaxPlaybackRate(WebRtcOpusEncInst* encoder,
106 opus_int32 expect,
107 int32_t set) {
minyue@webrtc.org0040a6e2014-08-04 14:41:57 +0000108 opus_int32 bandwidth;
minyue@webrtc.org7dba7862015-01-20 16:01:50 +0000109 EXPECT_EQ(0, WebRtcOpus_SetMaxPlaybackRate(opus_encoder_, set));
Alex Loiko83ed89a2019-01-17 12:32:11 +0100110 EXPECT_EQ(0, WebRtcOpus_GetMaxPlaybackRate(opus_encoder_, &bandwidth));
minyue@webrtc.org0040a6e2014-08-04 14:41:57 +0000111 EXPECT_EQ(expect, bandwidth);
112}
113
Yves Gerey665174f2018-06-19 15:03:05 +0200114void OpusTest::CheckAudioBounded(const int16_t* audio,
115 size_t samples,
116 size_t channels,
117 uint16_t bound) const {
minyue3cea2562015-11-10 03:49:26 -0800118 for (size_t i = 0; i < samples; ++i) {
Peter Kasting69558702016-01-12 16:26:35 -0800119 for (size_t c = 0; c < channels; ++c) {
minyue3cea2562015-11-10 03:49:26 -0800120 ASSERT_GE(audio[i * channels + c], -bound);
121 ASSERT_LE(audio[i * channels + c], bound);
122 }
123 }
124}
125
minyue@webrtc.org0ca768b2014-12-11 16:09:35 +0000126int OpusTest::EncodeDecode(WebRtcOpusEncInst* encoder,
kwiberg288886b2015-11-06 01:21:35 -0800127 rtc::ArrayView<const int16_t> input_audio,
minyue@webrtc.org0ca768b2014-12-11 16:09:35 +0000128 WebRtcOpusDecInst* decoder,
129 int16_t* output_audio,
130 int16_t* audio_type) {
Yves Gerey665174f2018-06-19 15:03:05 +0200131 int encoded_bytes_int =
132 WebRtcOpus_Encode(encoder, input_audio.data(),
133 rtc::CheckedDivExact(input_audio.size(), channels_),
134 kMaxBytes, bitstream_);
Peter Kastingdce40cf2015-08-24 14:52:23 -0700135 EXPECT_GE(encoded_bytes_int, 0);
136 encoded_bytes_ = static_cast<size_t>(encoded_bytes_int);
minyuel6d92bf52015-09-23 15:20:39 +0200137 int est_len = WebRtcOpus_DurationEst(decoder, bitstream_, encoded_bytes_);
Yves Gerey665174f2018-06-19 15:03:05 +0200138 int act_len = WebRtcOpus_Decode(decoder, bitstream_, encoded_bytes_,
139 output_audio, audio_type);
minyuel6d92bf52015-09-23 15:20:39 +0200140 EXPECT_EQ(est_len, act_len);
141 return act_len;
minyue@webrtc.org0ca768b2014-12-11 16:09:35 +0000142}
143
144// Test if encoder/decoder can enter DTX mode properly and do not enter DTX when
145// they should not. This test is signal dependent.
minyue3cea2562015-11-10 03:49:26 -0800146void OpusTest::TestDtxEffect(bool dtx, int block_length_ms) {
147 PrepareSpeechData(channels_, block_length_ms, 2000);
148 const size_t samples = kOpusRateKhz * block_length_ms;
minyue@webrtc.org0ca768b2014-12-11 16:09:35 +0000149
150 // Create encoder memory.
Yves Gerey665174f2018-06-19 15:03:05 +0200151 EXPECT_EQ(0,
152 WebRtcOpus_EncoderCreate(&opus_encoder_, channels_, application_));
minyue@webrtc.org7dba7862015-01-20 16:01:50 +0000153 EXPECT_EQ(0, WebRtcOpus_DecoderCreate(&opus_decoder_, channels_));
minyue@webrtc.org0ca768b2014-12-11 16:09:35 +0000154
155 // Set bitrate.
Yves Gerey665174f2018-06-19 15:03:05 +0200156 EXPECT_EQ(
157 0, WebRtcOpus_SetBitRate(opus_encoder_, channels_ == 1 ? 32000 : 64000));
minyue@webrtc.org0ca768b2014-12-11 16:09:35 +0000158
159 // Set input audio as silence.
minyue3cea2562015-11-10 03:49:26 -0800160 std::vector<int16_t> silence(samples * channels_, 0);
minyue@webrtc.org0ca768b2014-12-11 16:09:35 +0000161
162 // Setting DTX.
Yves Gerey665174f2018-06-19 15:03:05 +0200163 EXPECT_EQ(0, dtx ? WebRtcOpus_EnableDtx(opus_encoder_)
164 : WebRtcOpus_DisableDtx(opus_encoder_));
minyue@webrtc.org0ca768b2014-12-11 16:09:35 +0000165
166 int16_t audio_type;
minyue3cea2562015-11-10 03:49:26 -0800167 int16_t* output_data_decode = new int16_t[samples * channels_];
minyue@webrtc.org0ca768b2014-12-11 16:09:35 +0000168
169 for (int i = 0; i < 100; ++i) {
Yves Gerey665174f2018-06-19 15:03:05 +0200170 EXPECT_EQ(samples, static_cast<size_t>(EncodeDecode(
171 opus_encoder_, speech_data_.GetNextBlock(),
172 opus_decoder_, output_data_decode, &audio_type)));
minyue@webrtc.org0ca768b2014-12-11 16:09:35 +0000173 // If not DTX, it should never enter DTX mode. If DTX, we do not care since
174 // whether it enters DTX depends on the signal type.
175 if (!dtx) {
Peter Kastingdce40cf2015-08-24 14:52:23 -0700176 EXPECT_GT(encoded_bytes_, 1U);
minyue@webrtc.org7dba7862015-01-20 16:01:50 +0000177 EXPECT_EQ(0, opus_encoder_->in_dtx_mode);
178 EXPECT_EQ(0, opus_decoder_->in_dtx_mode);
minyue@webrtc.org0ca768b2014-12-11 16:09:35 +0000179 EXPECT_EQ(0, audio_type); // Speech.
180 }
181 }
182
183 // We input some silent segments. In DTX mode, the encoder will stop sending.
184 // However, DTX may happen after a while.
minyue@webrtc.org7dba7862015-01-20 16:01:50 +0000185 for (int i = 0; i < 30; ++i) {
Yves Gerey665174f2018-06-19 15:03:05 +0200186 EXPECT_EQ(samples, static_cast<size_t>(
187 EncodeDecode(opus_encoder_, silence, opus_decoder_,
188 output_data_decode, &audio_type)));
minyue@webrtc.org0ca768b2014-12-11 16:09:35 +0000189 if (!dtx) {
Peter Kastingdce40cf2015-08-24 14:52:23 -0700190 EXPECT_GT(encoded_bytes_, 1U);
minyue@webrtc.org7dba7862015-01-20 16:01:50 +0000191 EXPECT_EQ(0, opus_encoder_->in_dtx_mode);
192 EXPECT_EQ(0, opus_decoder_->in_dtx_mode);
minyue@webrtc.org0ca768b2014-12-11 16:09:35 +0000193 EXPECT_EQ(0, audio_type); // Speech.
Peter Kasting728d9032015-06-11 14:31:38 -0700194 } else if (encoded_bytes_ == 1) {
minyue@webrtc.org7dba7862015-01-20 16:01:50 +0000195 EXPECT_EQ(1, opus_encoder_->in_dtx_mode);
196 EXPECT_EQ(1, opus_decoder_->in_dtx_mode);
minyue@webrtc.org0ca768b2014-12-11 16:09:35 +0000197 EXPECT_EQ(2, audio_type); // Comfort noise.
198 break;
199 }
200 }
201
Minyue Li092041c2015-05-11 12:19:35 +0200202 // When Opus is in DTX, it wakes up in a regular basis. It sends two packets,
203 // one with an arbitrary size and the other of 1-byte, then stops sending for
minyue3cea2562015-11-10 03:49:26 -0800204 // a certain number of frames.
205
206 // |max_dtx_frames| is the maximum number of frames Opus can stay in DTX.
207 const int max_dtx_frames = 400 / block_length_ms + 1;
208
209 // We run |kRunTimeMs| milliseconds of pure silence.
minyue58e08cb2016-02-24 03:49:19 -0800210 const int kRunTimeMs = 4500;
minyue3cea2562015-11-10 03:49:26 -0800211
212 // We check that, after a |kCheckTimeMs| milliseconds (given that the CNG in
213 // Opus needs time to adapt), the absolute values of DTX decoded signal are
214 // bounded by |kOutputValueBound|.
minyue58e08cb2016-02-24 03:49:19 -0800215 const int kCheckTimeMs = 4000;
minyue3cea2562015-11-10 03:49:26 -0800216
217#if defined(OPUS_FIXED_POINT)
minyuel7e937e92016-02-29 10:24:15 +0100218 // Fixed-point Opus generates a random (comfort) noise, which has a less
219 // predictable value bound than its floating-point Opus. This value depends on
220 // input signal, and the time window for checking the output values (between
221 // |kCheckTimeMs| and |kRunTimeMs|).
222 const uint16_t kOutputValueBound = 30;
223
minyue3cea2562015-11-10 03:49:26 -0800224#else
minyue58e08cb2016-02-24 03:49:19 -0800225 const uint16_t kOutputValueBound = 2;
minyue3cea2562015-11-10 03:49:26 -0800226#endif
227
228 int time = 0;
229 while (time < kRunTimeMs) {
230 // DTX mode is maintained for maximum |max_dtx_frames| frames.
231 int i = 0;
232 for (; i < max_dtx_frames; ++i) {
233 time += block_length_ms;
Yves Gerey665174f2018-06-19 15:03:05 +0200234 EXPECT_EQ(samples, static_cast<size_t>(
235 EncodeDecode(opus_encoder_, silence, opus_decoder_,
236 output_data_decode, &audio_type)));
Minyue Li092041c2015-05-11 12:19:35 +0200237 if (dtx) {
minyue3cea2562015-11-10 03:49:26 -0800238 if (encoded_bytes_ > 1)
239 break;
Peter Kastingdce40cf2015-08-24 14:52:23 -0700240 EXPECT_EQ(0U, encoded_bytes_) // Send 0 byte.
Minyue Li092041c2015-05-11 12:19:35 +0200241 << "Opus should have entered DTX mode.";
242 EXPECT_EQ(1, opus_encoder_->in_dtx_mode);
243 EXPECT_EQ(1, opus_decoder_->in_dtx_mode);
244 EXPECT_EQ(2, audio_type); // Comfort noise.
minyue3cea2562015-11-10 03:49:26 -0800245 if (time >= kCheckTimeMs) {
246 CheckAudioBounded(output_data_decode, samples, channels_,
247 kOutputValueBound);
248 }
Minyue Li092041c2015-05-11 12:19:35 +0200249 } else {
Peter Kastingdce40cf2015-08-24 14:52:23 -0700250 EXPECT_GT(encoded_bytes_, 1U);
Minyue Li092041c2015-05-11 12:19:35 +0200251 EXPECT_EQ(0, opus_encoder_->in_dtx_mode);
252 EXPECT_EQ(0, opus_decoder_->in_dtx_mode);
253 EXPECT_EQ(0, audio_type); // Speech.
254 }
255 }
256
minyue3cea2562015-11-10 03:49:26 -0800257 if (dtx) {
258 // With DTX, Opus must stop transmission for some time.
259 EXPECT_GT(i, 1);
260 }
Minyue Li092041c2015-05-11 12:19:35 +0200261
minyue3cea2562015-11-10 03:49:26 -0800262 // We expect a normal payload.
Minyue Li092041c2015-05-11 12:19:35 +0200263 EXPECT_EQ(0, opus_encoder_->in_dtx_mode);
264 EXPECT_EQ(0, opus_decoder_->in_dtx_mode);
265 EXPECT_EQ(0, audio_type); // Speech.
266
267 // Enters DTX again immediately.
minyue3cea2562015-11-10 03:49:26 -0800268 time += block_length_ms;
Yves Gerey665174f2018-06-19 15:03:05 +0200269 EXPECT_EQ(samples, static_cast<size_t>(
270 EncodeDecode(opus_encoder_, silence, opus_decoder_,
271 output_data_decode, &audio_type)));
minyue@webrtc.org0ca768b2014-12-11 16:09:35 +0000272 if (dtx) {
Peter Kastingdce40cf2015-08-24 14:52:23 -0700273 EXPECT_EQ(1U, encoded_bytes_); // Send 1 byte.
minyue@webrtc.org7dba7862015-01-20 16:01:50 +0000274 EXPECT_EQ(1, opus_encoder_->in_dtx_mode);
275 EXPECT_EQ(1, opus_decoder_->in_dtx_mode);
minyue@webrtc.org0ca768b2014-12-11 16:09:35 +0000276 EXPECT_EQ(2, audio_type); // Comfort noise.
minyue3cea2562015-11-10 03:49:26 -0800277 if (time >= kCheckTimeMs) {
278 CheckAudioBounded(output_data_decode, samples, channels_,
279 kOutputValueBound);
280 }
minyue@webrtc.org0ca768b2014-12-11 16:09:35 +0000281 } else {
Peter Kastingdce40cf2015-08-24 14:52:23 -0700282 EXPECT_GT(encoded_bytes_, 1U);
minyue@webrtc.org7dba7862015-01-20 16:01:50 +0000283 EXPECT_EQ(0, opus_encoder_->in_dtx_mode);
284 EXPECT_EQ(0, opus_decoder_->in_dtx_mode);
minyue@webrtc.org0ca768b2014-12-11 16:09:35 +0000285 EXPECT_EQ(0, audio_type); // Speech.
286 }
287 }
288
minyue@webrtc.org0ca768b2014-12-11 16:09:35 +0000289 silence[0] = 10000;
290 if (dtx) {
291 // Verify that encoder/decoder can jump out from DTX mode.
Yves Gerey665174f2018-06-19 15:03:05 +0200292 EXPECT_EQ(samples, static_cast<size_t>(
293 EncodeDecode(opus_encoder_, silence, opus_decoder_,
294 output_data_decode, &audio_type)));
Peter Kastingdce40cf2015-08-24 14:52:23 -0700295 EXPECT_GT(encoded_bytes_, 1U);
minyue@webrtc.org7dba7862015-01-20 16:01:50 +0000296 EXPECT_EQ(0, opus_encoder_->in_dtx_mode);
297 EXPECT_EQ(0, opus_decoder_->in_dtx_mode);
minyue@webrtc.org0ca768b2014-12-11 16:09:35 +0000298 EXPECT_EQ(0, audio_type); // Speech.
299 }
300
301 // Free memory.
minyue@webrtc.org7dba7862015-01-20 16:01:50 +0000302 delete[] output_data_decode;
minyue@webrtc.org7dba7862015-01-20 16:01:50 +0000303 EXPECT_EQ(0, WebRtcOpus_EncoderFree(opus_encoder_));
304 EXPECT_EQ(0, WebRtcOpus_DecoderFree(opus_decoder_));
minyue@webrtc.org0ca768b2014-12-11 16:09:35 +0000305}
306
soren28dc2852017-04-06 05:48:36 -0700307// Test if CBR does what we expect.
308void OpusTest::TestCbrEffect(bool cbr, int block_length_ms) {
309 PrepareSpeechData(channels_, block_length_ms, 2000);
310 const size_t samples = kOpusRateKhz * block_length_ms;
311
312 int32_t max_pkt_size_diff = 0;
313 int32_t prev_pkt_size = 0;
314
315 // Create encoder memory.
316 EXPECT_EQ(0,
317 WebRtcOpus_EncoderCreate(&opus_encoder_, channels_, application_));
318 EXPECT_EQ(0, WebRtcOpus_DecoderCreate(&opus_decoder_, channels_));
319
320 // Set bitrate.
321 EXPECT_EQ(
322 0, WebRtcOpus_SetBitRate(opus_encoder_, channels_ == 1 ? 32000 : 64000));
323
324 // Setting CBR.
325 EXPECT_EQ(0, cbr ? WebRtcOpus_EnableCbr(opus_encoder_)
326 : WebRtcOpus_DisableCbr(opus_encoder_));
327
328 int16_t audio_type;
329 std::vector<int16_t> audio_out(samples * channels_);
330 for (int i = 0; i < 100; ++i) {
331 EXPECT_EQ(samples, static_cast<size_t>(EncodeDecode(
332 opus_encoder_, speech_data_.GetNextBlock(),
333 opus_decoder_, audio_out.data(), &audio_type)));
334
335 if (prev_pkt_size > 0) {
336 int32_t diff = std::abs((int32_t)encoded_bytes_ - prev_pkt_size);
337 max_pkt_size_diff = std::max(max_pkt_size_diff, diff);
338 }
Mirko Bonadei737e0732017-10-19 09:00:17 +0200339 prev_pkt_size = rtc::checked_cast<int32_t>(encoded_bytes_);
soren28dc2852017-04-06 05:48:36 -0700340 }
341
342 if (cbr) {
343 EXPECT_EQ(max_pkt_size_diff, 0);
344 } else {
345 EXPECT_GT(max_pkt_size_diff, 0);
346 }
347
348 // Free memory.
349 EXPECT_EQ(0, WebRtcOpus_EncoderFree(opus_encoder_));
350 EXPECT_EQ(0, WebRtcOpus_DecoderFree(opus_decoder_));
351}
352
tina.legrand@webrtc.orgdb11fab2013-04-17 10:39:41 +0000353// Test failing Create.
henrika1d34fe92015-06-16 10:04:20 +0200354TEST(OpusTest, OpusCreateFail) {
minyue@webrtc.org7dba7862015-01-20 16:01:50 +0000355 WebRtcOpusEncInst* opus_encoder;
356 WebRtcOpusDecInst* opus_decoder;
357
tina.legrand@webrtc.orgdb11fab2013-04-17 10:39:41 +0000358 // Test to see that an invalid pointer is caught.
minyue@webrtc.org7dba7862015-01-20 16:01:50 +0000359 EXPECT_EQ(-1, WebRtcOpus_EncoderCreate(NULL, 1, 0));
360 // Invalid channel number.
Alex Loiko83ed89a2019-01-17 12:32:11 +0100361 EXPECT_EQ(-1, WebRtcOpus_EncoderCreate(&opus_encoder, 257, 0));
minyue@webrtc.org7dba7862015-01-20 16:01:50 +0000362 // Invalid applciation mode.
363 EXPECT_EQ(-1, WebRtcOpus_EncoderCreate(&opus_encoder, 1, 2));
364
tina.legrand@webrtc.orgdb11fab2013-04-17 10:39:41 +0000365 EXPECT_EQ(-1, WebRtcOpus_DecoderCreate(NULL, 1));
minyue@webrtc.org7dba7862015-01-20 16:01:50 +0000366 // Invalid channel number.
Alex Loiko83ed89a2019-01-17 12:32:11 +0100367 EXPECT_EQ(-1, WebRtcOpus_DecoderCreate(&opus_decoder, 257));
tina.legrand@webrtc.orgdb11fab2013-04-17 10:39:41 +0000368}
369
370// Test failing Free.
henrika1d34fe92015-06-16 10:04:20 +0200371TEST(OpusTest, OpusFreeFail) {
tina.legrand@webrtc.orgdb11fab2013-04-17 10:39:41 +0000372 // Test to see that an invalid pointer is caught.
373 EXPECT_EQ(-1, WebRtcOpus_EncoderFree(NULL));
374 EXPECT_EQ(-1, WebRtcOpus_DecoderFree(NULL));
375}
376
377// Test normal Create and Free.
henrika1d34fe92015-06-16 10:04:20 +0200378TEST_P(OpusTest, OpusCreateFree) {
Yves Gerey665174f2018-06-19 15:03:05 +0200379 EXPECT_EQ(0,
380 WebRtcOpus_EncoderCreate(&opus_encoder_, channels_, application_));
minyue@webrtc.org7dba7862015-01-20 16:01:50 +0000381 EXPECT_EQ(0, WebRtcOpus_DecoderCreate(&opus_decoder_, channels_));
382 EXPECT_TRUE(opus_encoder_ != NULL);
383 EXPECT_TRUE(opus_decoder_ != NULL);
tina.legrand@webrtc.orgdb11fab2013-04-17 10:39:41 +0000384 // Free encoder and decoder memory.
minyue@webrtc.org7dba7862015-01-20 16:01:50 +0000385 EXPECT_EQ(0, WebRtcOpus_EncoderFree(opus_encoder_));
386 EXPECT_EQ(0, WebRtcOpus_DecoderFree(opus_decoder_));
tina.legrand@webrtc.orgdb11fab2013-04-17 10:39:41 +0000387}
388
henrika1d34fe92015-06-16 10:04:20 +0200389TEST_P(OpusTest, OpusEncodeDecode) {
minyue@webrtc.org7dba7862015-01-20 16:01:50 +0000390 PrepareSpeechData(channels_, 20, 20);
minyue@webrtc.org0ca768b2014-12-11 16:09:35 +0000391
tina.legrand@webrtc.orgdb11fab2013-04-17 10:39:41 +0000392 // Create encoder memory.
Yves Gerey665174f2018-06-19 15:03:05 +0200393 EXPECT_EQ(0,
394 WebRtcOpus_EncoderCreate(&opus_encoder_, channels_, application_));
395 EXPECT_EQ(0, WebRtcOpus_DecoderCreate(&opus_decoder_, channels_));
tina.legrand@webrtc.orgdb11fab2013-04-17 10:39:41 +0000396
397 // Set bitrate.
Yves Gerey665174f2018-06-19 15:03:05 +0200398 EXPECT_EQ(
399 0, WebRtcOpus_SetBitRate(opus_encoder_, channels_ == 1 ? 32000 : 64000));
tina.legrand@webrtc.orgdb11fab2013-04-17 10:39:41 +0000400
401 // Check number of channels for decoder.
minyue@webrtc.org7dba7862015-01-20 16:01:50 +0000402 EXPECT_EQ(channels_, WebRtcOpus_DecoderChannels(opus_decoder_));
403
404 // Check application mode.
405 opus_int32 app;
Alex Loiko83ed89a2019-01-17 12:32:11 +0100406 opus_multistream_encoder_ctl(opus_encoder_->encoder,
407 OPUS_GET_APPLICATION(&app));
minyue@webrtc.org7dba7862015-01-20 16:01:50 +0000408 EXPECT_EQ(application_ == 0 ? OPUS_APPLICATION_VOIP : OPUS_APPLICATION_AUDIO,
409 app);
tina.legrand@webrtc.orgdb11fab2013-04-17 10:39:41 +0000410
411 // Encode & decode.
tina.legrand@webrtc.orgdb11fab2013-04-17 10:39:41 +0000412 int16_t audio_type;
minyue@webrtc.org7dba7862015-01-20 16:01:50 +0000413 int16_t* output_data_decode = new int16_t[kOpus20msFrameSamples * channels_];
minyue@webrtc.orgf563e852014-07-18 21:11:27 +0000414 EXPECT_EQ(kOpus20msFrameSamples,
kwiberg288886b2015-11-06 01:21:35 -0800415 static_cast<size_t>(
416 EncodeDecode(opus_encoder_, speech_data_.GetNextBlock(),
417 opus_decoder_, output_data_decode, &audio_type)));
tina.legrand@webrtc.orgdb11fab2013-04-17 10:39:41 +0000418
tina.legrand@webrtc.orgdb11fab2013-04-17 10:39:41 +0000419 // Free memory.
minyue@webrtc.org7dba7862015-01-20 16:01:50 +0000420 delete[] output_data_decode;
421 EXPECT_EQ(0, WebRtcOpus_EncoderFree(opus_encoder_));
422 EXPECT_EQ(0, WebRtcOpus_DecoderFree(opus_decoder_));
tina.legrand@webrtc.orgdb11fab2013-04-17 10:39:41 +0000423}
424
henrika1d34fe92015-06-16 10:04:20 +0200425TEST_P(OpusTest, OpusSetBitRate) {
tina.legrand@webrtc.orgdb11fab2013-04-17 10:39:41 +0000426 // Test without creating encoder memory.
minyue@webrtc.org7dba7862015-01-20 16:01:50 +0000427 EXPECT_EQ(-1, WebRtcOpus_SetBitRate(opus_encoder_, 60000));
tina.legrand@webrtc.orgdb11fab2013-04-17 10:39:41 +0000428
429 // Create encoder memory, try with different bitrates.
Yves Gerey665174f2018-06-19 15:03:05 +0200430 EXPECT_EQ(0,
431 WebRtcOpus_EncoderCreate(&opus_encoder_, channels_, application_));
minyue@webrtc.org7dba7862015-01-20 16:01:50 +0000432 EXPECT_EQ(0, WebRtcOpus_SetBitRate(opus_encoder_, 30000));
433 EXPECT_EQ(0, WebRtcOpus_SetBitRate(opus_encoder_, 60000));
434 EXPECT_EQ(0, WebRtcOpus_SetBitRate(opus_encoder_, 300000));
435 EXPECT_EQ(0, WebRtcOpus_SetBitRate(opus_encoder_, 600000));
tina.legrand@webrtc.orgdb11fab2013-04-17 10:39:41 +0000436
437 // Free memory.
minyue@webrtc.org7dba7862015-01-20 16:01:50 +0000438 EXPECT_EQ(0, WebRtcOpus_EncoderFree(opus_encoder_));
tina.legrand@webrtc.orgdb11fab2013-04-17 10:39:41 +0000439}
440
minyue@webrtc.org7dba7862015-01-20 16:01:50 +0000441TEST_P(OpusTest, OpusSetComplexity) {
minyue@webrtc.org04546882014-03-07 08:55:48 +0000442 // Test without creating encoder memory.
minyue@webrtc.org7dba7862015-01-20 16:01:50 +0000443 EXPECT_EQ(-1, WebRtcOpus_SetComplexity(opus_encoder_, 9));
minyue@webrtc.org04546882014-03-07 08:55:48 +0000444
445 // Create encoder memory, try with different complexities.
Yves Gerey665174f2018-06-19 15:03:05 +0200446 EXPECT_EQ(0,
447 WebRtcOpus_EncoderCreate(&opus_encoder_, channels_, application_));
minyue@webrtc.org04546882014-03-07 08:55:48 +0000448
minyue@webrtc.org7dba7862015-01-20 16:01:50 +0000449 EXPECT_EQ(0, WebRtcOpus_SetComplexity(opus_encoder_, 0));
450 EXPECT_EQ(0, WebRtcOpus_SetComplexity(opus_encoder_, 10));
451 EXPECT_EQ(-1, WebRtcOpus_SetComplexity(opus_encoder_, 11));
minyue@webrtc.org04546882014-03-07 08:55:48 +0000452
453 // Free memory.
minyue@webrtc.org7dba7862015-01-20 16:01:50 +0000454 EXPECT_EQ(0, WebRtcOpus_EncoderFree(opus_encoder_));
minyue@webrtc.org04546882014-03-07 08:55:48 +0000455}
456
Alex Luebseeb27652017-11-20 11:13:56 -0800457TEST_P(OpusTest, OpusSetBandwidth) {
Alex Loiko83ed89a2019-01-17 12:32:11 +0100458 if (channels_ > 2) {
459 // TODO(webrtc:10217): investigate why multi-stream Opus reports
460 // narrowband when it's configured with FULLBAND.
461 return;
462 }
Alex Luebseeb27652017-11-20 11:13:56 -0800463 PrepareSpeechData(channels_, 20, 20);
464
465 int16_t audio_type;
466 std::unique_ptr<int16_t[]> output_data_decode(
467 new int16_t[kOpus20msFrameSamples * channels_]());
468
469 // Test without creating encoder memory.
470 EXPECT_EQ(-1,
471 WebRtcOpus_SetBandwidth(opus_encoder_, OPUS_BANDWIDTH_NARROWBAND));
472 EXPECT_EQ(-1, WebRtcOpus_GetBandwidth(opus_encoder_));
473
474 // Create encoder memory, try with different bandwidths.
475 EXPECT_EQ(0,
476 WebRtcOpus_EncoderCreate(&opus_encoder_, channels_, application_));
477 EXPECT_EQ(0, WebRtcOpus_DecoderCreate(&opus_decoder_, channels_));
478
479 EXPECT_EQ(-1, WebRtcOpus_SetBandwidth(opus_encoder_,
480 OPUS_BANDWIDTH_NARROWBAND - 1));
481 EXPECT_EQ(0,
482 WebRtcOpus_SetBandwidth(opus_encoder_, OPUS_BANDWIDTH_NARROWBAND));
483 EncodeDecode(opus_encoder_, speech_data_.GetNextBlock(), opus_decoder_,
484 output_data_decode.get(), &audio_type);
485 EXPECT_EQ(OPUS_BANDWIDTH_NARROWBAND, WebRtcOpus_GetBandwidth(opus_encoder_));
486 EXPECT_EQ(0, WebRtcOpus_SetBandwidth(opus_encoder_, OPUS_BANDWIDTH_FULLBAND));
487 EncodeDecode(opus_encoder_, speech_data_.GetNextBlock(), opus_decoder_,
488 output_data_decode.get(), &audio_type);
489 EXPECT_EQ(OPUS_BANDWIDTH_FULLBAND, WebRtcOpus_GetBandwidth(opus_encoder_));
490 EXPECT_EQ(
491 -1, WebRtcOpus_SetBandwidth(opus_encoder_, OPUS_BANDWIDTH_FULLBAND + 1));
492 EncodeDecode(opus_encoder_, speech_data_.GetNextBlock(), opus_decoder_,
493 output_data_decode.get(), &audio_type);
494 EXPECT_EQ(OPUS_BANDWIDTH_FULLBAND, WebRtcOpus_GetBandwidth(opus_encoder_));
495
496 // Free memory.
497 EXPECT_EQ(0, WebRtcOpus_EncoderFree(opus_encoder_));
498 EXPECT_EQ(0, WebRtcOpus_DecoderFree(opus_decoder_));
499}
500
minyuec8299f92016-09-27 02:08:47 -0700501TEST_P(OpusTest, OpusForceChannels) {
502 // Test without creating encoder memory.
503 EXPECT_EQ(-1, WebRtcOpus_SetForceChannels(opus_encoder_, 1));
504
505 ASSERT_EQ(0,
506 WebRtcOpus_EncoderCreate(&opus_encoder_, channels_, application_));
507
Alex Loiko83ed89a2019-01-17 12:32:11 +0100508 if (channels_ >= 2) {
minyuec8299f92016-09-27 02:08:47 -0700509 EXPECT_EQ(-1, WebRtcOpus_SetForceChannels(opus_encoder_, 3));
510 EXPECT_EQ(0, WebRtcOpus_SetForceChannels(opus_encoder_, 2));
511 EXPECT_EQ(0, WebRtcOpus_SetForceChannels(opus_encoder_, 1));
512 EXPECT_EQ(0, WebRtcOpus_SetForceChannels(opus_encoder_, 0));
513 } else {
514 EXPECT_EQ(-1, WebRtcOpus_SetForceChannels(opus_encoder_, 2));
515 EXPECT_EQ(0, WebRtcOpus_SetForceChannels(opus_encoder_, 1));
516 EXPECT_EQ(0, WebRtcOpus_SetForceChannels(opus_encoder_, 0));
517 }
518
519 EXPECT_EQ(0, WebRtcOpus_EncoderFree(opus_encoder_));
520}
521
minyue@webrtc.org7dba7862015-01-20 16:01:50 +0000522// Encode and decode one frame, initialize the decoder and
tina.legrand@webrtc.orgdb11fab2013-04-17 10:39:41 +0000523// decode once more.
henrika1d34fe92015-06-16 10:04:20 +0200524TEST_P(OpusTest, OpusDecodeInit) {
minyue@webrtc.org7dba7862015-01-20 16:01:50 +0000525 PrepareSpeechData(channels_, 20, 20);
minyue@webrtc.org0ca768b2014-12-11 16:09:35 +0000526
tina.legrand@webrtc.orgdb11fab2013-04-17 10:39:41 +0000527 // Create encoder memory.
Yves Gerey665174f2018-06-19 15:03:05 +0200528 EXPECT_EQ(0,
529 WebRtcOpus_EncoderCreate(&opus_encoder_, channels_, application_));
minyue@webrtc.org7dba7862015-01-20 16:01:50 +0000530 EXPECT_EQ(0, WebRtcOpus_DecoderCreate(&opus_decoder_, channels_));
tina.legrand@webrtc.orgdb11fab2013-04-17 10:39:41 +0000531
532 // Encode & decode.
tina.legrand@webrtc.orgdb11fab2013-04-17 10:39:41 +0000533 int16_t audio_type;
minyue@webrtc.org7dba7862015-01-20 16:01:50 +0000534 int16_t* output_data_decode = new int16_t[kOpus20msFrameSamples * channels_];
minyue@webrtc.orgf563e852014-07-18 21:11:27 +0000535 EXPECT_EQ(kOpus20msFrameSamples,
kwiberg288886b2015-11-06 01:21:35 -0800536 static_cast<size_t>(
537 EncodeDecode(opus_encoder_, speech_data_.GetNextBlock(),
538 opus_decoder_, output_data_decode, &audio_type)));
minyue@webrtc.org52bc4f42014-12-04 11:00:50 +0000539
Karl Wiberg43766482015-08-27 15:22:11 +0200540 WebRtcOpus_DecoderInit(opus_decoder_);
minyue@webrtc.org52bc4f42014-12-04 11:00:50 +0000541
542 EXPECT_EQ(kOpus20msFrameSamples,
Yves Gerey665174f2018-06-19 15:03:05 +0200543 static_cast<size_t>(
544 WebRtcOpus_Decode(opus_decoder_, bitstream_, encoded_bytes_,
545 output_data_decode, &audio_type)));
tina.legrand@webrtc.orgdb11fab2013-04-17 10:39:41 +0000546
547 // Free memory.
minyue@webrtc.org7dba7862015-01-20 16:01:50 +0000548 delete[] output_data_decode;
549 EXPECT_EQ(0, WebRtcOpus_EncoderFree(opus_encoder_));
550 EXPECT_EQ(0, WebRtcOpus_DecoderFree(opus_decoder_));
tina.legrand@webrtc.orgdb11fab2013-04-17 10:39:41 +0000551}
552
henrika1d34fe92015-06-16 10:04:20 +0200553TEST_P(OpusTest, OpusEnableDisableFec) {
minyue@webrtc.org46509c82014-03-07 11:49:11 +0000554 // Test without creating encoder memory.
minyue@webrtc.org7dba7862015-01-20 16:01:50 +0000555 EXPECT_EQ(-1, WebRtcOpus_EnableFec(opus_encoder_));
556 EXPECT_EQ(-1, WebRtcOpus_DisableFec(opus_encoder_));
minyue@webrtc.org46509c82014-03-07 11:49:11 +0000557
minyue@webrtc.org7dba7862015-01-20 16:01:50 +0000558 // Create encoder memory.
Yves Gerey665174f2018-06-19 15:03:05 +0200559 EXPECT_EQ(0,
560 WebRtcOpus_EncoderCreate(&opus_encoder_, channels_, application_));
minyue@webrtc.org46509c82014-03-07 11:49:11 +0000561
minyue@webrtc.org7dba7862015-01-20 16:01:50 +0000562 EXPECT_EQ(0, WebRtcOpus_EnableFec(opus_encoder_));
563 EXPECT_EQ(0, WebRtcOpus_DisableFec(opus_encoder_));
minyue@webrtc.org46509c82014-03-07 11:49:11 +0000564
565 // Free memory.
minyue@webrtc.org7dba7862015-01-20 16:01:50 +0000566 EXPECT_EQ(0, WebRtcOpus_EncoderFree(opus_encoder_));
minyue@webrtc.org46509c82014-03-07 11:49:11 +0000567}
568
henrika1d34fe92015-06-16 10:04:20 +0200569TEST_P(OpusTest, OpusEnableDisableDtx) {
minyue@webrtc.org0ca768b2014-12-11 16:09:35 +0000570 // Test without creating encoder memory.
minyue@webrtc.org7dba7862015-01-20 16:01:50 +0000571 EXPECT_EQ(-1, WebRtcOpus_EnableDtx(opus_encoder_));
572 EXPECT_EQ(-1, WebRtcOpus_DisableDtx(opus_encoder_));
minyue@webrtc.org0ca768b2014-12-11 16:09:35 +0000573
minyue@webrtc.org7dba7862015-01-20 16:01:50 +0000574 // Create encoder memory.
Yves Gerey665174f2018-06-19 15:03:05 +0200575 EXPECT_EQ(0,
576 WebRtcOpus_EncoderCreate(&opus_encoder_, channels_, application_));
minyue@webrtc.org0ca768b2014-12-11 16:09:35 +0000577
578 opus_int32 dtx;
579
580 // DTX is off by default.
Alex Loiko83ed89a2019-01-17 12:32:11 +0100581 opus_multistream_encoder_ctl(opus_encoder_->encoder, OPUS_GET_DTX(&dtx));
minyue@webrtc.org0ca768b2014-12-11 16:09:35 +0000582 EXPECT_EQ(0, dtx);
583
584 // Test to enable DTX.
minyue@webrtc.org7dba7862015-01-20 16:01:50 +0000585 EXPECT_EQ(0, WebRtcOpus_EnableDtx(opus_encoder_));
Alex Loiko83ed89a2019-01-17 12:32:11 +0100586 opus_multistream_encoder_ctl(opus_encoder_->encoder, OPUS_GET_DTX(&dtx));
minyue@webrtc.org0ca768b2014-12-11 16:09:35 +0000587 EXPECT_EQ(1, dtx);
588
589 // Test to disable DTX.
minyue@webrtc.org7dba7862015-01-20 16:01:50 +0000590 EXPECT_EQ(0, WebRtcOpus_DisableDtx(opus_encoder_));
Alex Loiko83ed89a2019-01-17 12:32:11 +0100591 opus_multistream_encoder_ctl(opus_encoder_->encoder, OPUS_GET_DTX(&dtx));
minyue@webrtc.org0ca768b2014-12-11 16:09:35 +0000592 EXPECT_EQ(0, dtx);
593
minyue@webrtc.org0ca768b2014-12-11 16:09:35 +0000594 // Free memory.
minyue@webrtc.org7dba7862015-01-20 16:01:50 +0000595 EXPECT_EQ(0, WebRtcOpus_EncoderFree(opus_encoder_));
minyue@webrtc.org0ca768b2014-12-11 16:09:35 +0000596}
597
henrika1d34fe92015-06-16 10:04:20 +0200598TEST_P(OpusTest, OpusDtxOff) {
minyue3cea2562015-11-10 03:49:26 -0800599 TestDtxEffect(false, 10);
600 TestDtxEffect(false, 20);
601 TestDtxEffect(false, 40);
minyue@webrtc.org0ca768b2014-12-11 16:09:35 +0000602}
603
henrika1d34fe92015-06-16 10:04:20 +0200604TEST_P(OpusTest, OpusDtxOn) {
Alex Loiko83ed89a2019-01-17 12:32:11 +0100605 if (channels_ > 2) {
606 // TODO(webrtc:10218): adapt the test to the sizes and order of multi-stream
607 // DTX packets.
608 return;
609 }
minyue3cea2562015-11-10 03:49:26 -0800610 TestDtxEffect(true, 10);
611 TestDtxEffect(true, 20);
612 TestDtxEffect(true, 40);
minyue@webrtc.org0ca768b2014-12-11 16:09:35 +0000613}
614
soren28dc2852017-04-06 05:48:36 -0700615TEST_P(OpusTest, OpusCbrOff) {
616 TestCbrEffect(false, 10);
617 TestCbrEffect(false, 20);
618 TestCbrEffect(false, 40);
619}
620
621TEST_P(OpusTest, OpusCbrOn) {
622 TestCbrEffect(true, 10);
623 TestCbrEffect(true, 20);
624 TestCbrEffect(true, 40);
625}
626
henrika1d34fe92015-06-16 10:04:20 +0200627TEST_P(OpusTest, OpusSetPacketLossRate) {
minyue@webrtc.org46509c82014-03-07 11:49:11 +0000628 // Test without creating encoder memory.
minyue@webrtc.org7dba7862015-01-20 16:01:50 +0000629 EXPECT_EQ(-1, WebRtcOpus_SetPacketLossRate(opus_encoder_, 50));
minyue@webrtc.org0ca768b2014-12-11 16:09:35 +0000630
tina.legrand@webrtc.orgbd21fb52013-08-08 11:01:07 +0000631 // Create encoder memory.
Yves Gerey665174f2018-06-19 15:03:05 +0200632 EXPECT_EQ(0,
633 WebRtcOpus_EncoderCreate(&opus_encoder_, channels_, application_));
minyue@webrtc.org7dba7862015-01-20 16:01:50 +0000634
635 EXPECT_EQ(0, WebRtcOpus_SetPacketLossRate(opus_encoder_, 50));
636 EXPECT_EQ(-1, WebRtcOpus_SetPacketLossRate(opus_encoder_, -1));
637 EXPECT_EQ(-1, WebRtcOpus_SetPacketLossRate(opus_encoder_, 101));
638
639 // Free memory.
640 EXPECT_EQ(0, WebRtcOpus_EncoderFree(opus_encoder_));
641}
642
henrika1d34fe92015-06-16 10:04:20 +0200643TEST_P(OpusTest, OpusSetMaxPlaybackRate) {
minyue@webrtc.org7dba7862015-01-20 16:01:50 +0000644 // Test without creating encoder memory.
645 EXPECT_EQ(-1, WebRtcOpus_SetMaxPlaybackRate(opus_encoder_, 20000));
646
647 // Create encoder memory.
Yves Gerey665174f2018-06-19 15:03:05 +0200648 EXPECT_EQ(0,
649 WebRtcOpus_EncoderCreate(&opus_encoder_, channels_, application_));
minyue@webrtc.org7dba7862015-01-20 16:01:50 +0000650
651 SetMaxPlaybackRate(opus_encoder_, OPUS_BANDWIDTH_FULLBAND, 48000);
652 SetMaxPlaybackRate(opus_encoder_, OPUS_BANDWIDTH_FULLBAND, 24001);
653 SetMaxPlaybackRate(opus_encoder_, OPUS_BANDWIDTH_SUPERWIDEBAND, 24000);
654 SetMaxPlaybackRate(opus_encoder_, OPUS_BANDWIDTH_SUPERWIDEBAND, 16001);
655 SetMaxPlaybackRate(opus_encoder_, OPUS_BANDWIDTH_WIDEBAND, 16000);
656 SetMaxPlaybackRate(opus_encoder_, OPUS_BANDWIDTH_WIDEBAND, 12001);
657 SetMaxPlaybackRate(opus_encoder_, OPUS_BANDWIDTH_MEDIUMBAND, 12000);
658 SetMaxPlaybackRate(opus_encoder_, OPUS_BANDWIDTH_MEDIUMBAND, 8001);
659 SetMaxPlaybackRate(opus_encoder_, OPUS_BANDWIDTH_NARROWBAND, 8000);
660 SetMaxPlaybackRate(opus_encoder_, OPUS_BANDWIDTH_NARROWBAND, 4000);
661
662 // Free memory.
663 EXPECT_EQ(0, WebRtcOpus_EncoderFree(opus_encoder_));
664}
665
666// Test PLC.
henrika1d34fe92015-06-16 10:04:20 +0200667TEST_P(OpusTest, OpusDecodePlc) {
minyue@webrtc.org7dba7862015-01-20 16:01:50 +0000668 PrepareSpeechData(channels_, 20, 20);
669
670 // Create encoder memory.
Yves Gerey665174f2018-06-19 15:03:05 +0200671 EXPECT_EQ(0,
672 WebRtcOpus_EncoderCreate(&opus_encoder_, channels_, application_));
minyue@webrtc.org7dba7862015-01-20 16:01:50 +0000673 EXPECT_EQ(0, WebRtcOpus_DecoderCreate(&opus_decoder_, channels_));
tina.legrand@webrtc.orgbd21fb52013-08-08 11:01:07 +0000674
675 // Set bitrate.
Yves Gerey665174f2018-06-19 15:03:05 +0200676 EXPECT_EQ(
677 0, WebRtcOpus_SetBitRate(opus_encoder_, channels_ == 1 ? 32000 : 64000));
tina.legrand@webrtc.orgbd21fb52013-08-08 11:01:07 +0000678
679 // Check number of channels for decoder.
minyue@webrtc.org7dba7862015-01-20 16:01:50 +0000680 EXPECT_EQ(channels_, WebRtcOpus_DecoderChannels(opus_decoder_));
tina.legrand@webrtc.orgbd21fb52013-08-08 11:01:07 +0000681
682 // Encode & decode.
tina.legrand@webrtc.orgbd21fb52013-08-08 11:01:07 +0000683 int16_t audio_type;
minyue@webrtc.org7dba7862015-01-20 16:01:50 +0000684 int16_t* output_data_decode = new int16_t[kOpus20msFrameSamples * channels_];
minyue@webrtc.orgf563e852014-07-18 21:11:27 +0000685 EXPECT_EQ(kOpus20msFrameSamples,
kwiberg288886b2015-11-06 01:21:35 -0800686 static_cast<size_t>(
687 EncodeDecode(opus_encoder_, speech_data_.GetNextBlock(),
688 opus_decoder_, output_data_decode, &audio_type)));
tina.legrand@webrtc.orgbd21fb52013-08-08 11:01:07 +0000689
minyue@webrtc.org33ccdfa2014-12-04 12:14:12 +0000690 // Call decoder PLC.
minyue@webrtc.org7dba7862015-01-20 16:01:50 +0000691 int16_t* plc_buffer = new int16_t[kOpus20msFrameSamples * channels_];
Yves Gerey665174f2018-06-19 15:03:05 +0200692 EXPECT_EQ(kOpus20msFrameSamples, static_cast<size_t>(WebRtcOpus_DecodePlc(
693 opus_decoder_, plc_buffer, 1)));
tina.legrand@webrtc.orgbd21fb52013-08-08 11:01:07 +0000694
695 // Free memory.
minyue@webrtc.org7dba7862015-01-20 16:01:50 +0000696 delete[] plc_buffer;
697 delete[] output_data_decode;
698 EXPECT_EQ(0, WebRtcOpus_EncoderFree(opus_encoder_));
699 EXPECT_EQ(0, WebRtcOpus_DecoderFree(opus_decoder_));
tina.legrand@webrtc.orgdb11fab2013-04-17 10:39:41 +0000700}
701
702// Duration estimation.
henrika1d34fe92015-06-16 10:04:20 +0200703TEST_P(OpusTest, OpusDurationEstimation) {
minyue@webrtc.org7dba7862015-01-20 16:01:50 +0000704 PrepareSpeechData(channels_, 20, 20);
minyue@webrtc.org0ca768b2014-12-11 16:09:35 +0000705
tina.legrand@webrtc.orgdb11fab2013-04-17 10:39:41 +0000706 // Create.
Yves Gerey665174f2018-06-19 15:03:05 +0200707 EXPECT_EQ(0,
708 WebRtcOpus_EncoderCreate(&opus_encoder_, channels_, application_));
minyue@webrtc.org7dba7862015-01-20 16:01:50 +0000709 EXPECT_EQ(0, WebRtcOpus_DecoderCreate(&opus_decoder_, channels_));
tina.legrand@webrtc.orgdb11fab2013-04-17 10:39:41 +0000710
minyue@webrtc.org0ca768b2014-12-11 16:09:35 +0000711 // 10 ms. We use only first 10 ms of a 20 ms block.
kwiberg288886b2015-11-06 01:21:35 -0800712 auto speech_block = speech_data_.GetNextBlock();
713 int encoded_bytes_int = WebRtcOpus_Encode(
714 opus_encoder_, speech_block.data(),
Yves Gerey665174f2018-06-19 15:03:05 +0200715 rtc::CheckedDivExact(speech_block.size(), 2 * channels_), kMaxBytes,
716 bitstream_);
Peter Kastingdce40cf2015-08-24 14:52:23 -0700717 EXPECT_GE(encoded_bytes_int, 0);
Yves Gerey665174f2018-06-19 15:03:05 +0200718 EXPECT_EQ(
719 kOpus10msFrameSamples,
720 static_cast<size_t>(WebRtcOpus_DurationEst(
721 opus_decoder_, bitstream_, static_cast<size_t>(encoded_bytes_int))));
tina.legrand@webrtc.orgdb11fab2013-04-17 10:39:41 +0000722
723 // 20 ms
kwiberg288886b2015-11-06 01:21:35 -0800724 speech_block = speech_data_.GetNextBlock();
Yves Gerey665174f2018-06-19 15:03:05 +0200725 encoded_bytes_int =
726 WebRtcOpus_Encode(opus_encoder_, speech_block.data(),
727 rtc::CheckedDivExact(speech_block.size(), channels_),
728 kMaxBytes, bitstream_);
Peter Kastingdce40cf2015-08-24 14:52:23 -0700729 EXPECT_GE(encoded_bytes_int, 0);
Yves Gerey665174f2018-06-19 15:03:05 +0200730 EXPECT_EQ(
731 kOpus20msFrameSamples,
732 static_cast<size_t>(WebRtcOpus_DurationEst(
733 opus_decoder_, bitstream_, static_cast<size_t>(encoded_bytes_int))));
tina.legrand@webrtc.orgdb11fab2013-04-17 10:39:41 +0000734
735 // Free memory.
minyue@webrtc.org7dba7862015-01-20 16:01:50 +0000736 EXPECT_EQ(0, WebRtcOpus_EncoderFree(opus_encoder_));
737 EXPECT_EQ(0, WebRtcOpus_DecoderFree(opus_decoder_));
tina.legrand@webrtc.orgdb11fab2013-04-17 10:39:41 +0000738}
739
henrika1d34fe92015-06-16 10:04:20 +0200740TEST_P(OpusTest, OpusDecodeRepacketized) {
Alex Loiko83ed89a2019-01-17 12:32:11 +0100741 if (channels_ > 2) {
742 // As per the Opus documentation
743 // https://mf4.xiph.org/jenkins/view/opus/job/opus/ws/doc/html/group__opus__repacketizer.html#details,
744 // multiple streams are not supported.
745 return;
746 }
minyuea613eb62017-03-14 14:33:30 -0700747 constexpr size_t kPackets = 6;
minyue@webrtc.org7f7d7e32015-03-16 12:30:37 +0000748
749 PrepareSpeechData(channels_, 20, 20 * kPackets);
750
751 // Create encoder memory.
Yves Gerey665174f2018-06-19 15:03:05 +0200752 ASSERT_EQ(0,
753 WebRtcOpus_EncoderCreate(&opus_encoder_, channels_, application_));
754 ASSERT_EQ(0, WebRtcOpus_DecoderCreate(&opus_decoder_, channels_));
minyue@webrtc.org7f7d7e32015-03-16 12:30:37 +0000755
756 // Set bitrate.
Yves Gerey665174f2018-06-19 15:03:05 +0200757 EXPECT_EQ(
758 0, WebRtcOpus_SetBitRate(opus_encoder_, channels_ == 1 ? 32000 : 64000));
minyue@webrtc.org7f7d7e32015-03-16 12:30:37 +0000759
760 // Check number of channels for decoder.
761 EXPECT_EQ(channels_, WebRtcOpus_DecoderChannels(opus_decoder_));
762
763 // Encode & decode.
764 int16_t audio_type;
kwiberg91d97562016-02-14 01:10:03 -0800765 std::unique_ptr<int16_t[]> output_data_decode(
minyue@webrtc.org7f7d7e32015-03-16 12:30:37 +0000766 new int16_t[kPackets * kOpus20msFrameSamples * channels_]);
767 OpusRepacketizer* rp = opus_repacketizer_create();
768
minyuea613eb62017-03-14 14:33:30 -0700769 size_t num_packets = 0;
770 constexpr size_t kMaxCycles = 100;
771 for (size_t idx = 0; idx < kMaxCycles; ++idx) {
kwiberg288886b2015-11-06 01:21:35 -0800772 auto speech_block = speech_data_.GetNextBlock();
773 encoded_bytes_ =
774 WebRtcOpus_Encode(opus_encoder_, speech_block.data(),
Peter Kasting69558702016-01-12 16:26:35 -0800775 rtc::CheckedDivExact(speech_block.size(), channels_),
kwiberg288886b2015-11-06 01:21:35 -0800776 kMaxBytes, bitstream_);
Yves Gerey665174f2018-06-19 15:03:05 +0200777 if (opus_repacketizer_cat(rp, bitstream_,
778 rtc::checked_cast<opus_int32>(encoded_bytes_)) ==
779 OPUS_OK) {
minyuea613eb62017-03-14 14:33:30 -0700780 ++num_packets;
781 if (num_packets == kPackets) {
782 break;
783 }
784 } else {
785 // Opus repacketizer cannot guarantee a success. We try again if it fails.
786 opus_repacketizer_init(rp);
787 num_packets = 0;
788 }
minyue@webrtc.org7f7d7e32015-03-16 12:30:37 +0000789 }
minyuea613eb62017-03-14 14:33:30 -0700790 EXPECT_EQ(kPackets, num_packets);
minyue@webrtc.org7f7d7e32015-03-16 12:30:37 +0000791
792 encoded_bytes_ = opus_repacketizer_out(rp, bitstream_, kMaxBytes);
793
794 EXPECT_EQ(kOpus20msFrameSamples * kPackets,
Peter Kastingdce40cf2015-08-24 14:52:23 -0700795 static_cast<size_t>(WebRtcOpus_DurationEst(
796 opus_decoder_, bitstream_, encoded_bytes_)));
minyue@webrtc.org7f7d7e32015-03-16 12:30:37 +0000797
798 EXPECT_EQ(kOpus20msFrameSamples * kPackets,
Yves Gerey665174f2018-06-19 15:03:05 +0200799 static_cast<size_t>(
800 WebRtcOpus_Decode(opus_decoder_, bitstream_, encoded_bytes_,
801 output_data_decode.get(), &audio_type)));
minyue@webrtc.org7f7d7e32015-03-16 12:30:37 +0000802
803 // Free memory.
804 opus_repacketizer_destroy(rp);
805 EXPECT_EQ(0, WebRtcOpus_EncoderFree(opus_encoder_));
806 EXPECT_EQ(0, WebRtcOpus_DecoderFree(opus_decoder_));
807}
808
minyue@webrtc.org7dba7862015-01-20 16:01:50 +0000809INSTANTIATE_TEST_CASE_P(VariousMode,
810 OpusTest,
Alex Loiko83ed89a2019-01-17 12:32:11 +0100811 Combine(Values(1, 2, 4), Values(0, 1)));
minyue@webrtc.org7dba7862015-01-20 16:01:50 +0000812
tina.legrand@webrtc.orgdb11fab2013-04-17 10:39:41 +0000813} // namespace webrtc