opus_unittest.cc (38081B)
1 /* 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 */ 10 11 #include "opus.h" 12 13 #include <algorithm> 14 #include <cstddef> 15 #include <cstdint> 16 #include <cstdlib> 17 #include <map> 18 #include <memory> 19 #include <string> 20 #include <tuple> 21 #include <vector> 22 23 #include "api/array_view.h" 24 #include "modules/audio_coding/codecs/opus/opus_interface.h" 25 #include "modules/audio_coding/neteq/tools/audio_loop.h" 26 #include "rtc_base/checks.h" 27 #include "rtc_base/numerics/safe_conversions.h" 28 #include "test/gtest.h" 29 #include "test/testsupport/file_utils.h" 30 31 namespace webrtc { 32 33 namespace { 34 // Equivalent to SDP params 35 // {{"channel_mapping", "0,1,2,3"}, {"coupled_streams", "2"}}. 36 constexpr unsigned char kQuadChannelMapping[] = {0, 1, 2, 3}; 37 constexpr int kQuadTotalStreams = 2; 38 constexpr int kQuadCoupledStreams = 2; 39 40 constexpr unsigned char kStereoChannelMapping[] = {0, 1}; 41 constexpr int kStereoTotalStreams = 1; 42 constexpr int kStereoCoupledStreams = 1; 43 44 constexpr unsigned char kMonoChannelMapping[] = {0}; 45 constexpr int kMonoTotalStreams = 1; 46 constexpr int kMonoCoupledStreams = 0; 47 48 void CreateSingleOrMultiStreamEncoder(WebRtcOpusEncInst** opus_encoder, 49 int channels, 50 int application, 51 bool use_multistream, 52 int encoder_sample_rate_hz) { 53 EXPECT_TRUE(channels == 1 || channels == 2 || use_multistream); 54 if (use_multistream) { 55 EXPECT_EQ(encoder_sample_rate_hz, 48000); 56 if (channels == 1) { 57 EXPECT_EQ(0, WebRtcOpus_MultistreamEncoderCreate( 58 opus_encoder, channels, application, kMonoTotalStreams, 59 kMonoCoupledStreams, kMonoChannelMapping)); 60 } else if (channels == 2) { 61 EXPECT_EQ(0, WebRtcOpus_MultistreamEncoderCreate( 62 opus_encoder, channels, application, kStereoTotalStreams, 63 kStereoCoupledStreams, kStereoChannelMapping)); 64 } else if (channels == 4) { 65 EXPECT_EQ(0, WebRtcOpus_MultistreamEncoderCreate( 66 opus_encoder, channels, application, kQuadTotalStreams, 67 kQuadCoupledStreams, kQuadChannelMapping)); 68 } else { 69 EXPECT_TRUE(false) << channels; 70 } 71 } else { 72 EXPECT_EQ(0, WebRtcOpus_EncoderCreate(opus_encoder, channels, application, 73 encoder_sample_rate_hz)); 74 } 75 } 76 77 void CreateSingleOrMultiStreamDecoder(WebRtcOpusDecInst** opus_decoder, 78 int channels, 79 bool use_multistream, 80 int decoder_sample_rate_hz) { 81 EXPECT_TRUE(channels == 1 || channels == 2 || use_multistream); 82 if (use_multistream) { 83 EXPECT_EQ(decoder_sample_rate_hz, 48000); 84 if (channels == 1) { 85 EXPECT_EQ(0, WebRtcOpus_MultistreamDecoderCreate( 86 opus_decoder, channels, kMonoTotalStreams, 87 kMonoCoupledStreams, kMonoChannelMapping)); 88 } else if (channels == 2) { 89 EXPECT_EQ(0, WebRtcOpus_MultistreamDecoderCreate( 90 opus_decoder, channels, kStereoTotalStreams, 91 kStereoCoupledStreams, kStereoChannelMapping)); 92 } else if (channels == 4) { 93 EXPECT_EQ(0, WebRtcOpus_MultistreamDecoderCreate( 94 opus_decoder, channels, kQuadTotalStreams, 95 kQuadCoupledStreams, kQuadChannelMapping)); 96 } else { 97 EXPECT_TRUE(false) << channels; 98 } 99 } else { 100 EXPECT_EQ(0, WebRtcOpus_DecoderCreate(opus_decoder, channels, 101 decoder_sample_rate_hz)); 102 } 103 } 104 105 int SamplesPerChannel(int sample_rate_hz, int duration_ms) { 106 const int samples_per_ms = CheckedDivExact(sample_rate_hz, 1000); 107 return samples_per_ms * duration_ms; 108 } 109 110 using test::AudioLoop; 111 using ::testing::Combine; 112 using ::testing::TestWithParam; 113 using ::testing::Values; 114 115 // Maximum number of bytes in output bitstream. 116 constexpr size_t kMaxBytes = 2000; 117 118 class OpusTest 119 : public TestWithParam<::testing::tuple<size_t, int, bool, int, int>> { 120 protected: 121 OpusTest() = default; 122 123 void TestDtxEffect(bool dtx, int block_length_ms); 124 125 void TestCbrEffect(bool dtx, int block_length_ms); 126 127 // Prepare `speech_data_` for encoding, read from a hard-coded file. 128 // After preparation, `speech_data_.GetNextBlock()` returns a pointer to a 129 // block of `block_length_ms` milliseconds. The data is looped every 130 // `loop_length_ms` milliseconds. 131 void PrepareSpeechData(int block_length_ms, int loop_length_ms); 132 133 int EncodeDecode(WebRtcOpusEncInst* encoder, 134 ArrayView<const int16_t> input_audio, 135 WebRtcOpusDecInst* decoder, 136 int16_t* output_audio, 137 int16_t* audio_type); 138 139 void SetMaxPlaybackRate(WebRtcOpusEncInst* encoder, 140 opus_int32 expect, 141 int32_t set); 142 143 void CheckAudioBounded(const int16_t* audio, 144 size_t samples, 145 size_t channels, 146 uint16_t bound) const; 147 148 WebRtcOpusEncInst* opus_encoder_ = nullptr; 149 WebRtcOpusDecInst* opus_decoder_ = nullptr; 150 AudioLoop speech_data_; 151 uint8_t bitstream_[kMaxBytes]; 152 size_t encoded_bytes_ = 0; 153 const size_t channels_{std::get<0>(GetParam())}; 154 const int application_{std::get<1>(GetParam())}; 155 const bool use_multistream_{std::get<2>(GetParam())}; 156 const int encoder_sample_rate_hz_{std::get<3>(GetParam())}; 157 const int decoder_sample_rate_hz_{std::get<4>(GetParam())}; 158 }; 159 160 } // namespace 161 162 // Singlestream: Try all combinations. 163 INSTANTIATE_TEST_SUITE_P(Singlestream, 164 OpusTest, 165 testing::Combine(testing::Values(1, 2), 166 testing::Values(0, 1), 167 testing::Values(false), 168 testing::Values(16000, 48000), 169 testing::Values(16000, 48000))); 170 171 // Multistream: Some representative cases (only 48 kHz for now). 172 INSTANTIATE_TEST_SUITE_P( 173 Multistream, 174 OpusTest, 175 testing::Values(std::make_tuple(1, 0, true, 48000, 48000), 176 std::make_tuple(2, 1, true, 48000, 48000), 177 std::make_tuple(4, 0, true, 48000, 48000), 178 std::make_tuple(4, 1, true, 48000, 48000))); 179 180 void OpusTest::PrepareSpeechData(int block_length_ms, int loop_length_ms) { 181 std::map<int, std::string> channel_to_basename = { 182 {1, "audio_coding/testfile32kHz"}, 183 {2, "audio_coding/teststereo32kHz"}, 184 {4, "audio_coding/speech_4_channels_48k_one_second"}}; 185 std::map<int, std::string> channel_to_suffix = { 186 {1, "pcm"}, {2, "pcm"}, {4, "wav"}}; 187 const std::string file_name = test::ResourcePath( 188 channel_to_basename[channels_], channel_to_suffix[channels_]); 189 if (loop_length_ms < block_length_ms) { 190 loop_length_ms = block_length_ms; 191 } 192 const int sample_rate_khz = CheckedDivExact(encoder_sample_rate_hz_, 1000); 193 EXPECT_TRUE(speech_data_.Init(file_name, 194 loop_length_ms * sample_rate_khz * channels_, 195 block_length_ms * sample_rate_khz * channels_)); 196 } 197 198 void OpusTest::SetMaxPlaybackRate(WebRtcOpusEncInst* /* encoder */, 199 opus_int32 expect, 200 int32_t set) { 201 opus_int32 bandwidth; 202 EXPECT_EQ(0, WebRtcOpus_SetMaxPlaybackRate(opus_encoder_, set)); 203 EXPECT_EQ(0, WebRtcOpus_GetMaxPlaybackRate(opus_encoder_, &bandwidth)); 204 EXPECT_EQ(expect, bandwidth); 205 } 206 207 void OpusTest::CheckAudioBounded(const int16_t* audio, 208 size_t samples, 209 size_t channels, 210 uint16_t bound) const { 211 for (size_t i = 0; i < samples; ++i) { 212 for (size_t c = 0; c < channels; ++c) { 213 ASSERT_GE(audio[i * channels + c], -bound); 214 ASSERT_LE(audio[i * channels + c], bound); 215 } 216 } 217 } 218 219 int OpusTest::EncodeDecode(WebRtcOpusEncInst* encoder, 220 ArrayView<const int16_t> input_audio, 221 WebRtcOpusDecInst* decoder, 222 int16_t* output_audio, 223 int16_t* audio_type) { 224 const int input_samples_per_channel = 225 CheckedDivExact(input_audio.size(), channels_); 226 int encoded_bytes_int = 227 WebRtcOpus_Encode(encoder, input_audio.data(), input_samples_per_channel, 228 kMaxBytes, bitstream_); 229 EXPECT_GE(encoded_bytes_int, 0); 230 encoded_bytes_ = static_cast<size_t>(encoded_bytes_int); 231 if (encoded_bytes_ != 0) { 232 int est_len = WebRtcOpus_DurationEst(decoder, bitstream_, encoded_bytes_); 233 int act_len = WebRtcOpus_Decode(decoder, bitstream_, encoded_bytes_, 234 output_audio, audio_type); 235 EXPECT_EQ(est_len, act_len); 236 return act_len; 237 } else { 238 int total_dtx_len = 0; 239 const int output_samples_per_channel = input_samples_per_channel * 240 decoder_sample_rate_hz_ / 241 encoder_sample_rate_hz_; 242 while (total_dtx_len < output_samples_per_channel) { 243 int est_len = WebRtcOpus_DurationEst(decoder, nullptr, 0); 244 int act_len = WebRtcOpus_Decode(decoder, nullptr, 0, 245 &output_audio[total_dtx_len * channels_], 246 audio_type); 247 EXPECT_EQ(est_len, act_len); 248 total_dtx_len += act_len; 249 } 250 return total_dtx_len; 251 } 252 } 253 254 // Test if encoder/decoder can enter DTX mode properly and do not enter DTX when 255 // they should not. This test is signal dependent. 256 void OpusTest::TestDtxEffect(bool dtx, int block_length_ms) { 257 PrepareSpeechData(block_length_ms, 2000); 258 const size_t input_samples = 259 CheckedDivExact(encoder_sample_rate_hz_, 1000) * block_length_ms; 260 const size_t output_samples = 261 CheckedDivExact(decoder_sample_rate_hz_, 1000) * block_length_ms; 262 263 // Create encoder memory. 264 CreateSingleOrMultiStreamEncoder(&opus_encoder_, channels_, application_, 265 use_multistream_, encoder_sample_rate_hz_); 266 CreateSingleOrMultiStreamDecoder(&opus_decoder_, channels_, use_multistream_, 267 decoder_sample_rate_hz_); 268 269 // Set bitrate. 270 EXPECT_EQ( 271 0, WebRtcOpus_SetBitRate(opus_encoder_, channels_ == 1 ? 32000 : 64000)); 272 273 // Set input audio as silence. 274 std::vector<int16_t> silence(input_samples * channels_, 0); 275 276 // Setting DTX. 277 EXPECT_EQ(0, dtx ? WebRtcOpus_EnableDtx(opus_encoder_) 278 : WebRtcOpus_DisableDtx(opus_encoder_)); 279 280 int16_t audio_type; 281 int16_t* output_data_decode = new int16_t[output_samples * channels_]; 282 283 for (int i = 0; i < 100; ++i) { 284 EXPECT_EQ(output_samples, 285 static_cast<size_t>(EncodeDecode( 286 opus_encoder_, speech_data_.GetNextBlock(), opus_decoder_, 287 output_data_decode, &audio_type))); 288 // If not DTX, it should never enter DTX mode. If DTX, we do not care since 289 // whether it enters DTX depends on the signal type. 290 if (!dtx) { 291 EXPECT_GT(encoded_bytes_, 1U); 292 EXPECT_EQ(0, opus_encoder_->in_dtx_mode); 293 EXPECT_EQ(0, opus_decoder_->in_dtx_mode); 294 EXPECT_EQ(0, audio_type); // Speech. 295 } 296 } 297 298 // We input some silent segments. In DTX mode, the encoder will stop sending. 299 // However, DTX may happen after a while. 300 for (int i = 0; i < 30; ++i) { 301 EXPECT_EQ(output_samples, static_cast<size_t>(EncodeDecode( 302 opus_encoder_, silence, opus_decoder_, 303 output_data_decode, &audio_type))); 304 if (!dtx) { 305 EXPECT_GT(encoded_bytes_, 1U); 306 EXPECT_EQ(0, opus_encoder_->in_dtx_mode); 307 EXPECT_EQ(0, opus_decoder_->in_dtx_mode); 308 EXPECT_EQ(0, audio_type); // Speech. 309 } else if (encoded_bytes_ == 1) { 310 EXPECT_EQ(1, opus_encoder_->in_dtx_mode); 311 EXPECT_EQ(1, opus_decoder_->in_dtx_mode); 312 EXPECT_EQ(2, audio_type); // Comfort noise. 313 break; 314 } 315 } 316 317 // When Opus is in DTX, it wakes up in a regular basis. It sends two packets, 318 // one with an arbitrary size and the other of 1-byte, then stops sending for 319 // a certain number of frames. 320 321 // `max_dtx_frames` is the maximum number of frames Opus can stay in DTX. 322 // TODO(kwiberg): Why does this number depend on the encoding sample rate? 323 const int max_dtx_frames = 324 (encoder_sample_rate_hz_ == 16000 ? 800 : 400) / block_length_ms + 1; 325 326 // We run `kRunTimeMs` milliseconds of pure silence. 327 const int kRunTimeMs = 4500; 328 329 // We check that, after a `kCheckTimeMs` milliseconds (given that the CNG in 330 // Opus needs time to adapt), the absolute values of DTX decoded signal are 331 // bounded by `kOutputValueBound`. 332 const int kCheckTimeMs = 4000; 333 334 #if defined(OPUS_FIXED_POINT) 335 // Fixed-point Opus generates a random (comfort) noise, which has a less 336 // predictable value bound than its floating-point Opus. This value depends on 337 // input signal, and the time window for checking the output values (between 338 // `kCheckTimeMs` and `kRunTimeMs`). 339 const uint16_t kOutputValueBound = 30; 340 341 #else 342 const uint16_t kOutputValueBound = 2; 343 #endif 344 345 int time = 0; 346 while (time < kRunTimeMs) { 347 // DTX mode is maintained for maximum `max_dtx_frames` frames. 348 int i = 0; 349 for (; i < max_dtx_frames; ++i) { 350 time += block_length_ms; 351 EXPECT_EQ(output_samples, static_cast<size_t>(EncodeDecode( 352 opus_encoder_, silence, opus_decoder_, 353 output_data_decode, &audio_type))); 354 if (dtx) { 355 if (encoded_bytes_ > 1) 356 break; 357 EXPECT_EQ(0U, encoded_bytes_) // Send 0 byte. 358 << "Opus should have entered DTX mode."; 359 EXPECT_EQ(1, opus_encoder_->in_dtx_mode); 360 EXPECT_EQ(1, opus_decoder_->in_dtx_mode); 361 EXPECT_EQ(2, audio_type); // Comfort noise. 362 if (time >= kCheckTimeMs) { 363 CheckAudioBounded(output_data_decode, output_samples, channels_, 364 kOutputValueBound); 365 } 366 } else { 367 EXPECT_GT(encoded_bytes_, 1U); 368 EXPECT_EQ(0, opus_encoder_->in_dtx_mode); 369 EXPECT_EQ(0, opus_decoder_->in_dtx_mode); 370 EXPECT_EQ(0, audio_type); // Speech. 371 } 372 } 373 374 if (dtx) { 375 // With DTX, Opus must stop transmission for some time. 376 EXPECT_GT(i, 1); 377 } 378 379 // We expect a normal payload. 380 EXPECT_EQ(0, opus_encoder_->in_dtx_mode); 381 EXPECT_EQ(0, opus_decoder_->in_dtx_mode); 382 EXPECT_EQ(0, audio_type); // Speech. 383 384 // Enters DTX again immediately. 385 time += block_length_ms; 386 EXPECT_EQ(output_samples, static_cast<size_t>(EncodeDecode( 387 opus_encoder_, silence, opus_decoder_, 388 output_data_decode, &audio_type))); 389 if (dtx) { 390 EXPECT_EQ(1U, encoded_bytes_); // Send 1 byte. 391 EXPECT_EQ(1, opus_encoder_->in_dtx_mode); 392 EXPECT_EQ(1, opus_decoder_->in_dtx_mode); 393 EXPECT_EQ(2, audio_type); // Comfort noise. 394 if (time >= kCheckTimeMs) { 395 CheckAudioBounded(output_data_decode, output_samples, channels_, 396 kOutputValueBound); 397 } 398 } else { 399 EXPECT_GT(encoded_bytes_, 1U); 400 EXPECT_EQ(0, opus_encoder_->in_dtx_mode); 401 EXPECT_EQ(0, opus_decoder_->in_dtx_mode); 402 EXPECT_EQ(0, audio_type); // Speech. 403 } 404 } 405 406 silence[0] = 10000; 407 if (dtx) { 408 // Verify that encoder/decoder can jump out from DTX mode. 409 EXPECT_EQ(output_samples, static_cast<size_t>(EncodeDecode( 410 opus_encoder_, silence, opus_decoder_, 411 output_data_decode, &audio_type))); 412 EXPECT_GT(encoded_bytes_, 1U); 413 EXPECT_EQ(0, opus_encoder_->in_dtx_mode); 414 EXPECT_EQ(0, opus_decoder_->in_dtx_mode); 415 EXPECT_EQ(0, audio_type); // Speech. 416 } 417 418 // Free memory. 419 delete[] output_data_decode; 420 EXPECT_EQ(0, WebRtcOpus_EncoderFree(opus_encoder_)); 421 EXPECT_EQ(0, WebRtcOpus_DecoderFree(opus_decoder_)); 422 } 423 424 // Test if CBR does what we expect. 425 void OpusTest::TestCbrEffect(bool cbr, int block_length_ms) { 426 PrepareSpeechData(block_length_ms, 2000); 427 const size_t output_samples = 428 CheckedDivExact(decoder_sample_rate_hz_, 1000) * block_length_ms; 429 430 int32_t max_pkt_size_diff = 0; 431 int32_t prev_pkt_size = 0; 432 433 // Create encoder memory. 434 CreateSingleOrMultiStreamEncoder(&opus_encoder_, channels_, application_, 435 use_multistream_, encoder_sample_rate_hz_); 436 CreateSingleOrMultiStreamDecoder(&opus_decoder_, channels_, use_multistream_, 437 decoder_sample_rate_hz_); 438 439 // Set bitrate. 440 EXPECT_EQ( 441 0, WebRtcOpus_SetBitRate(opus_encoder_, channels_ == 1 ? 32000 : 64000)); 442 443 // Setting CBR. 444 EXPECT_EQ(0, cbr ? WebRtcOpus_EnableCbr(opus_encoder_) 445 : WebRtcOpus_DisableCbr(opus_encoder_)); 446 447 int16_t audio_type; 448 std::vector<int16_t> audio_out(output_samples * channels_); 449 for (int i = 0; i < 100; ++i) { 450 EXPECT_EQ(output_samples, 451 static_cast<size_t>( 452 EncodeDecode(opus_encoder_, speech_data_.GetNextBlock(), 453 opus_decoder_, audio_out.data(), &audio_type))); 454 455 if (prev_pkt_size > 0) { 456 int32_t diff = std::abs((int32_t)encoded_bytes_ - prev_pkt_size); 457 max_pkt_size_diff = std::max(max_pkt_size_diff, diff); 458 } 459 prev_pkt_size = checked_cast<int32_t>(encoded_bytes_); 460 } 461 462 if (cbr) { 463 EXPECT_EQ(max_pkt_size_diff, 0); 464 } else { 465 EXPECT_GT(max_pkt_size_diff, 0); 466 } 467 468 // Free memory. 469 EXPECT_EQ(0, WebRtcOpus_EncoderFree(opus_encoder_)); 470 EXPECT_EQ(0, WebRtcOpus_DecoderFree(opus_decoder_)); 471 } 472 473 // Test failing Create. 474 TEST(OpusTest, OpusCreateFail) { 475 WebRtcOpusEncInst* opus_encoder; 476 WebRtcOpusDecInst* opus_decoder; 477 478 // Test to see that an invalid pointer is caught. 479 EXPECT_EQ(-1, WebRtcOpus_EncoderCreate(nullptr, 1, 0, 48000)); 480 // Invalid channel number. 481 EXPECT_EQ(-1, WebRtcOpus_EncoderCreate(&opus_encoder, 257, 0, 48000)); 482 // Invalid applciation mode. 483 EXPECT_EQ(-1, WebRtcOpus_EncoderCreate(&opus_encoder, 1, 2, 48000)); 484 // Invalid sample rate. 485 EXPECT_EQ(-1, WebRtcOpus_EncoderCreate(&opus_encoder, 1, 0, 12345)); 486 487 EXPECT_EQ(-1, WebRtcOpus_DecoderCreate(nullptr, 1, 48000)); 488 // Invalid channel number. 489 EXPECT_EQ(-1, WebRtcOpus_DecoderCreate(&opus_decoder, 257, 48000)); 490 // Invalid sample rate. 491 EXPECT_EQ(-1, WebRtcOpus_DecoderCreate(&opus_decoder, 1, 12345)); 492 } 493 494 // Test failing Free. 495 TEST(OpusTest, OpusFreeFail) { 496 // Test to see that an invalid pointer is caught. 497 EXPECT_EQ(-1, WebRtcOpus_EncoderFree(nullptr)); 498 EXPECT_EQ(-1, WebRtcOpus_DecoderFree(nullptr)); 499 } 500 501 // Test normal Create and Free. 502 TEST_P(OpusTest, OpusCreateFree) { 503 CreateSingleOrMultiStreamEncoder(&opus_encoder_, channels_, application_, 504 use_multistream_, encoder_sample_rate_hz_); 505 CreateSingleOrMultiStreamDecoder(&opus_decoder_, channels_, use_multistream_, 506 decoder_sample_rate_hz_); 507 EXPECT_TRUE(opus_encoder_ != nullptr); 508 EXPECT_TRUE(opus_decoder_ != nullptr); 509 // Free encoder and decoder memory. 510 EXPECT_EQ(0, WebRtcOpus_EncoderFree(opus_encoder_)); 511 EXPECT_EQ(0, WebRtcOpus_DecoderFree(opus_decoder_)); 512 } 513 514 #define ENCODER_CTL(inst, vargs) \ 515 inst->encoder \ 516 ? opus_encoder_ctl(inst->encoder, vargs) \ 517 : opus_multistream_encoder_ctl(inst->multistream_encoder, vargs) 518 519 TEST_P(OpusTest, OpusEncodeDecode) { 520 PrepareSpeechData(20, 20); 521 522 // Create encoder memory. 523 CreateSingleOrMultiStreamEncoder(&opus_encoder_, channels_, application_, 524 use_multistream_, encoder_sample_rate_hz_); 525 CreateSingleOrMultiStreamDecoder(&opus_decoder_, channels_, use_multistream_, 526 decoder_sample_rate_hz_); 527 528 // Set bitrate. 529 EXPECT_EQ( 530 0, WebRtcOpus_SetBitRate(opus_encoder_, channels_ == 1 ? 32000 : 64000)); 531 532 // Check number of channels for decoder. 533 EXPECT_EQ(channels_, WebRtcOpus_DecoderChannels(opus_decoder_)); 534 535 // Check application mode. 536 opus_int32 app; 537 ENCODER_CTL(opus_encoder_, OPUS_GET_APPLICATION(&app)); 538 EXPECT_EQ(application_ == 0 ? OPUS_APPLICATION_VOIP : OPUS_APPLICATION_AUDIO, 539 app); 540 541 // Encode & decode. 542 int16_t audio_type; 543 const int decode_samples_per_channel = 544 SamplesPerChannel(decoder_sample_rate_hz_, /*ms=*/20); 545 int16_t* output_data_decode = 546 new int16_t[decode_samples_per_channel * channels_]; 547 EXPECT_EQ(decode_samples_per_channel, 548 EncodeDecode(opus_encoder_, speech_data_.GetNextBlock(), 549 opus_decoder_, output_data_decode, &audio_type)); 550 551 // Free memory. 552 delete[] output_data_decode; 553 EXPECT_EQ(0, WebRtcOpus_EncoderFree(opus_encoder_)); 554 EXPECT_EQ(0, WebRtcOpus_DecoderFree(opus_decoder_)); 555 } 556 557 TEST_P(OpusTest, OpusSetBitRate) { 558 // Test without creating encoder memory. 559 EXPECT_EQ(-1, WebRtcOpus_SetBitRate(opus_encoder_, 60000)); 560 561 // Create encoder memory, try with different bitrates. 562 CreateSingleOrMultiStreamEncoder(&opus_encoder_, channels_, application_, 563 use_multistream_, encoder_sample_rate_hz_); 564 EXPECT_EQ(0, WebRtcOpus_SetBitRate(opus_encoder_, 30000)); 565 EXPECT_EQ(0, WebRtcOpus_SetBitRate(opus_encoder_, 60000)); 566 EXPECT_EQ(0, WebRtcOpus_SetBitRate(opus_encoder_, 300000)); 567 EXPECT_EQ(0, WebRtcOpus_SetBitRate(opus_encoder_, 600000)); 568 569 // Free memory. 570 EXPECT_EQ(0, WebRtcOpus_EncoderFree(opus_encoder_)); 571 } 572 573 TEST_P(OpusTest, OpusSetComplexity) { 574 // Test without creating encoder memory. 575 EXPECT_EQ(-1, WebRtcOpus_SetComplexity(opus_encoder_, 9)); 576 577 // Create encoder memory, try with different complexities. 578 CreateSingleOrMultiStreamEncoder(&opus_encoder_, channels_, application_, 579 use_multistream_, encoder_sample_rate_hz_); 580 581 EXPECT_EQ(0, WebRtcOpus_SetComplexity(opus_encoder_, 0)); 582 EXPECT_EQ(0, WebRtcOpus_SetComplexity(opus_encoder_, 10)); 583 EXPECT_EQ(-1, WebRtcOpus_SetComplexity(opus_encoder_, 11)); 584 585 // Free memory. 586 EXPECT_EQ(0, WebRtcOpus_EncoderFree(opus_encoder_)); 587 } 588 589 TEST_P(OpusTest, OpusSetBandwidth) { 590 if (channels_ > 2) { 591 // TODO(webrtc:10217): investigate why multi-stream Opus reports 592 // narrowband when it's configured with FULLBAND. 593 return; 594 } 595 PrepareSpeechData(20, 20); 596 597 int16_t audio_type; 598 const int decode_samples_per_channel = 599 SamplesPerChannel(decoder_sample_rate_hz_, /*ms=*/20); 600 std::unique_ptr<int16_t[]> output_data_decode( 601 new int16_t[decode_samples_per_channel * channels_]()); 602 603 // Test without creating encoder memory. 604 EXPECT_EQ(-1, 605 WebRtcOpus_SetBandwidth(opus_encoder_, OPUS_BANDWIDTH_NARROWBAND)); 606 EXPECT_EQ(-1, WebRtcOpus_GetBandwidth(opus_encoder_)); 607 608 // Create encoder memory, try with different bandwidths. 609 CreateSingleOrMultiStreamEncoder(&opus_encoder_, channels_, application_, 610 use_multistream_, encoder_sample_rate_hz_); 611 CreateSingleOrMultiStreamDecoder(&opus_decoder_, channels_, use_multistream_, 612 decoder_sample_rate_hz_); 613 614 EXPECT_EQ(-1, WebRtcOpus_SetBandwidth(opus_encoder_, 615 OPUS_BANDWIDTH_NARROWBAND - 1)); 616 EXPECT_EQ(0, 617 WebRtcOpus_SetBandwidth(opus_encoder_, OPUS_BANDWIDTH_NARROWBAND)); 618 EncodeDecode(opus_encoder_, speech_data_.GetNextBlock(), opus_decoder_, 619 output_data_decode.get(), &audio_type); 620 EXPECT_EQ(OPUS_BANDWIDTH_NARROWBAND, WebRtcOpus_GetBandwidth(opus_encoder_)); 621 EXPECT_EQ(0, WebRtcOpus_SetBandwidth(opus_encoder_, OPUS_BANDWIDTH_FULLBAND)); 622 EncodeDecode(opus_encoder_, speech_data_.GetNextBlock(), opus_decoder_, 623 output_data_decode.get(), &audio_type); 624 EXPECT_EQ(encoder_sample_rate_hz_ == 16000 ? OPUS_BANDWIDTH_WIDEBAND 625 : OPUS_BANDWIDTH_FULLBAND, 626 WebRtcOpus_GetBandwidth(opus_encoder_)); 627 EXPECT_EQ( 628 -1, WebRtcOpus_SetBandwidth(opus_encoder_, OPUS_BANDWIDTH_FULLBAND + 1)); 629 EncodeDecode(opus_encoder_, speech_data_.GetNextBlock(), opus_decoder_, 630 output_data_decode.get(), &audio_type); 631 EXPECT_EQ(encoder_sample_rate_hz_ == 16000 ? OPUS_BANDWIDTH_WIDEBAND 632 : OPUS_BANDWIDTH_FULLBAND, 633 WebRtcOpus_GetBandwidth(opus_encoder_)); 634 635 // Free memory. 636 EXPECT_EQ(0, WebRtcOpus_EncoderFree(opus_encoder_)); 637 EXPECT_EQ(0, WebRtcOpus_DecoderFree(opus_decoder_)); 638 } 639 640 TEST_P(OpusTest, OpusForceChannels) { 641 // Test without creating encoder memory. 642 EXPECT_EQ(-1, WebRtcOpus_SetForceChannels(opus_encoder_, 1)); 643 644 CreateSingleOrMultiStreamEncoder(&opus_encoder_, channels_, application_, 645 use_multistream_, encoder_sample_rate_hz_); 646 ASSERT_NE(nullptr, opus_encoder_); 647 648 if (channels_ >= 2) { 649 EXPECT_EQ(-1, WebRtcOpus_SetForceChannels(opus_encoder_, 3)); 650 EXPECT_EQ(0, WebRtcOpus_SetForceChannels(opus_encoder_, 2)); 651 EXPECT_EQ(0, WebRtcOpus_SetForceChannels(opus_encoder_, 1)); 652 EXPECT_EQ(0, WebRtcOpus_SetForceChannels(opus_encoder_, 0)); 653 } else { 654 EXPECT_EQ(-1, WebRtcOpus_SetForceChannels(opus_encoder_, 2)); 655 EXPECT_EQ(0, WebRtcOpus_SetForceChannels(opus_encoder_, 1)); 656 EXPECT_EQ(0, WebRtcOpus_SetForceChannels(opus_encoder_, 0)); 657 } 658 659 EXPECT_EQ(0, WebRtcOpus_EncoderFree(opus_encoder_)); 660 } 661 662 // Encode and decode one frame, initialize the decoder and 663 // decode once more. 664 TEST_P(OpusTest, OpusDecodeInit) { 665 PrepareSpeechData(20, 20); 666 667 // Create encoder memory. 668 CreateSingleOrMultiStreamEncoder(&opus_encoder_, channels_, application_, 669 use_multistream_, encoder_sample_rate_hz_); 670 CreateSingleOrMultiStreamDecoder(&opus_decoder_, channels_, use_multistream_, 671 decoder_sample_rate_hz_); 672 673 // Encode & decode. 674 int16_t audio_type; 675 const int decode_samples_per_channel = 676 SamplesPerChannel(decoder_sample_rate_hz_, /*ms=*/20); 677 int16_t* output_data_decode = 678 new int16_t[decode_samples_per_channel * channels_]; 679 EXPECT_EQ(decode_samples_per_channel, 680 EncodeDecode(opus_encoder_, speech_data_.GetNextBlock(), 681 opus_decoder_, output_data_decode, &audio_type)); 682 683 WebRtcOpus_DecoderInit(opus_decoder_); 684 685 EXPECT_EQ(decode_samples_per_channel, 686 WebRtcOpus_Decode(opus_decoder_, bitstream_, encoded_bytes_, 687 output_data_decode, &audio_type)); 688 689 // Free memory. 690 delete[] output_data_decode; 691 EXPECT_EQ(0, WebRtcOpus_EncoderFree(opus_encoder_)); 692 EXPECT_EQ(0, WebRtcOpus_DecoderFree(opus_decoder_)); 693 } 694 695 TEST_P(OpusTest, OpusEnableDisableFec) { 696 // Test without creating encoder memory. 697 EXPECT_EQ(-1, WebRtcOpus_EnableFec(opus_encoder_)); 698 EXPECT_EQ(-1, WebRtcOpus_DisableFec(opus_encoder_)); 699 700 // Create encoder memory. 701 CreateSingleOrMultiStreamEncoder(&opus_encoder_, channels_, application_, 702 use_multistream_, encoder_sample_rate_hz_); 703 704 EXPECT_EQ(0, WebRtcOpus_EnableFec(opus_encoder_)); 705 EXPECT_EQ(0, WebRtcOpus_DisableFec(opus_encoder_)); 706 707 // Free memory. 708 EXPECT_EQ(0, WebRtcOpus_EncoderFree(opus_encoder_)); 709 } 710 711 TEST_P(OpusTest, OpusEnableDisableDtx) { 712 // Test without creating encoder memory. 713 EXPECT_EQ(-1, WebRtcOpus_EnableDtx(opus_encoder_)); 714 EXPECT_EQ(-1, WebRtcOpus_DisableDtx(opus_encoder_)); 715 716 // Create encoder memory. 717 CreateSingleOrMultiStreamEncoder(&opus_encoder_, channels_, application_, 718 use_multistream_, encoder_sample_rate_hz_); 719 720 opus_int32 dtx; 721 722 // DTX is off by default. 723 ENCODER_CTL(opus_encoder_, OPUS_GET_DTX(&dtx)); 724 EXPECT_EQ(0, dtx); 725 726 // Test to enable DTX. 727 EXPECT_EQ(0, WebRtcOpus_EnableDtx(opus_encoder_)); 728 ENCODER_CTL(opus_encoder_, OPUS_GET_DTX(&dtx)); 729 EXPECT_EQ(1, dtx); 730 731 // Test to disable DTX. 732 EXPECT_EQ(0, WebRtcOpus_DisableDtx(opus_encoder_)); 733 ENCODER_CTL(opus_encoder_, OPUS_GET_DTX(&dtx)); 734 EXPECT_EQ(0, dtx); 735 736 // Free memory. 737 EXPECT_EQ(0, WebRtcOpus_EncoderFree(opus_encoder_)); 738 } 739 740 TEST_P(OpusTest, OpusDtxOff) { 741 TestDtxEffect(false, 10); 742 TestDtxEffect(false, 20); 743 TestDtxEffect(false, 40); 744 } 745 746 TEST_P(OpusTest, OpusDtxOn) { 747 if (channels_ > 2 || application_ != 0) { 748 // DTX does not work with OPUS_APPLICATION_AUDIO at low complexity settings. 749 // TODO(webrtc:10218): adapt the test to the sizes and order of multi-stream 750 // DTX packets. 751 return; 752 } 753 TestDtxEffect(true, 10); 754 TestDtxEffect(true, 20); 755 TestDtxEffect(true, 40); 756 } 757 758 // TODO: https://issues.webrtc.org/411157363 - reenable test after update. 759 TEST_P(OpusTest, DISABLED_OpusCbrOff) { 760 TestCbrEffect(false, 10); 761 TestCbrEffect(false, 20); 762 TestCbrEffect(false, 40); 763 } 764 765 TEST_P(OpusTest, OpusCbrOn) { 766 TestCbrEffect(true, 10); 767 TestCbrEffect(true, 20); 768 TestCbrEffect(true, 40); 769 } 770 771 TEST_P(OpusTest, OpusSetPacketLossRate) { 772 // Test without creating encoder memory. 773 EXPECT_EQ(-1, WebRtcOpus_SetPacketLossRate(opus_encoder_, 50)); 774 775 // Create encoder memory. 776 CreateSingleOrMultiStreamEncoder(&opus_encoder_, channels_, application_, 777 use_multistream_, encoder_sample_rate_hz_); 778 779 EXPECT_EQ(0, WebRtcOpus_SetPacketLossRate(opus_encoder_, 50)); 780 EXPECT_EQ(-1, WebRtcOpus_SetPacketLossRate(opus_encoder_, -1)); 781 EXPECT_EQ(-1, WebRtcOpus_SetPacketLossRate(opus_encoder_, 101)); 782 783 // Free memory. 784 EXPECT_EQ(0, WebRtcOpus_EncoderFree(opus_encoder_)); 785 } 786 787 TEST_P(OpusTest, OpusSetMaxPlaybackRate) { 788 // Test without creating encoder memory. 789 EXPECT_EQ(-1, WebRtcOpus_SetMaxPlaybackRate(opus_encoder_, 20000)); 790 791 // Create encoder memory. 792 CreateSingleOrMultiStreamEncoder(&opus_encoder_, channels_, application_, 793 use_multistream_, encoder_sample_rate_hz_); 794 795 SetMaxPlaybackRate(opus_encoder_, OPUS_BANDWIDTH_FULLBAND, 48000); 796 SetMaxPlaybackRate(opus_encoder_, OPUS_BANDWIDTH_FULLBAND, 24001); 797 SetMaxPlaybackRate(opus_encoder_, OPUS_BANDWIDTH_SUPERWIDEBAND, 24000); 798 SetMaxPlaybackRate(opus_encoder_, OPUS_BANDWIDTH_SUPERWIDEBAND, 16001); 799 SetMaxPlaybackRate(opus_encoder_, OPUS_BANDWIDTH_WIDEBAND, 16000); 800 SetMaxPlaybackRate(opus_encoder_, OPUS_BANDWIDTH_WIDEBAND, 12001); 801 SetMaxPlaybackRate(opus_encoder_, OPUS_BANDWIDTH_MEDIUMBAND, 12000); 802 SetMaxPlaybackRate(opus_encoder_, OPUS_BANDWIDTH_MEDIUMBAND, 8001); 803 SetMaxPlaybackRate(opus_encoder_, OPUS_BANDWIDTH_NARROWBAND, 8000); 804 SetMaxPlaybackRate(opus_encoder_, OPUS_BANDWIDTH_NARROWBAND, 4000); 805 806 // Free memory. 807 EXPECT_EQ(0, WebRtcOpus_EncoderFree(opus_encoder_)); 808 } 809 810 // Test PLC. 811 TEST_P(OpusTest, OpusDecodePlc) { 812 PrepareSpeechData(20, 20); 813 814 // Create encoder memory. 815 CreateSingleOrMultiStreamEncoder(&opus_encoder_, channels_, application_, 816 use_multistream_, encoder_sample_rate_hz_); 817 CreateSingleOrMultiStreamDecoder(&opus_decoder_, channels_, use_multistream_, 818 decoder_sample_rate_hz_); 819 820 // Set bitrate. 821 EXPECT_EQ( 822 0, WebRtcOpus_SetBitRate(opus_encoder_, channels_ == 1 ? 32000 : 64000)); 823 824 // Check number of channels for decoder. 825 EXPECT_EQ(channels_, WebRtcOpus_DecoderChannels(opus_decoder_)); 826 827 // Encode & decode. 828 int16_t audio_type; 829 const int decode_samples_per_channel = 830 SamplesPerChannel(decoder_sample_rate_hz_, /*ms=*/20); 831 int16_t* output_data_decode = 832 new int16_t[decode_samples_per_channel * channels_]; 833 EXPECT_EQ(decode_samples_per_channel, 834 EncodeDecode(opus_encoder_, speech_data_.GetNextBlock(), 835 opus_decoder_, output_data_decode, &audio_type)); 836 837 // Call decoder PLC. 838 constexpr int kPlcDurationMs = 10; 839 const int plc_samples = decoder_sample_rate_hz_ * kPlcDurationMs / 1000; 840 int16_t* plc_buffer = new int16_t[plc_samples * channels_]; 841 EXPECT_EQ(plc_samples, WebRtcOpus_Decode(opus_decoder_, nullptr, 0, 842 plc_buffer, &audio_type)); 843 844 // Free memory. 845 delete[] plc_buffer; 846 delete[] output_data_decode; 847 EXPECT_EQ(0, WebRtcOpus_EncoderFree(opus_encoder_)); 848 EXPECT_EQ(0, WebRtcOpus_DecoderFree(opus_decoder_)); 849 } 850 851 // Duration estimation. 852 TEST_P(OpusTest, OpusDurationEstimation) { 853 PrepareSpeechData(20, 20); 854 855 // Create. 856 CreateSingleOrMultiStreamEncoder(&opus_encoder_, channels_, application_, 857 use_multistream_, encoder_sample_rate_hz_); 858 CreateSingleOrMultiStreamDecoder(&opus_decoder_, channels_, use_multistream_, 859 decoder_sample_rate_hz_); 860 861 // 10 ms. We use only first 10 ms of a 20 ms block. 862 auto speech_block = speech_data_.GetNextBlock(); 863 int encoded_bytes_int = 864 WebRtcOpus_Encode(opus_encoder_, speech_block.data(), 865 CheckedDivExact(speech_block.size(), 2 * channels_), 866 kMaxBytes, bitstream_); 867 EXPECT_GE(encoded_bytes_int, 0); 868 EXPECT_EQ(SamplesPerChannel(decoder_sample_rate_hz_, /*ms=*/10), 869 WebRtcOpus_DurationEst(opus_decoder_, bitstream_, 870 static_cast<size_t>(encoded_bytes_int))); 871 872 // 20 ms 873 speech_block = speech_data_.GetNextBlock(); 874 encoded_bytes_int = WebRtcOpus_Encode( 875 opus_encoder_, speech_block.data(), 876 CheckedDivExact(speech_block.size(), channels_), kMaxBytes, bitstream_); 877 EXPECT_GE(encoded_bytes_int, 0); 878 EXPECT_EQ(SamplesPerChannel(decoder_sample_rate_hz_, /*ms=*/20), 879 WebRtcOpus_DurationEst(opus_decoder_, bitstream_, 880 static_cast<size_t>(encoded_bytes_int))); 881 882 // Free memory. 883 EXPECT_EQ(0, WebRtcOpus_EncoderFree(opus_encoder_)); 884 EXPECT_EQ(0, WebRtcOpus_DecoderFree(opus_decoder_)); 885 } 886 887 TEST_P(OpusTest, OpusDecodeRepacketized) { 888 if (channels_ > 2) { 889 // As per the Opus documentation 890 // https://mf4.xiph.org/jenkins/view/opus/job/opus/ws/doc/html/group__opus__repacketizer.html#details, 891 // multiple streams are not supported. 892 return; 893 } 894 constexpr size_t kPackets = 6; 895 896 PrepareSpeechData(20, 20 * kPackets); 897 898 // Create encoder memory. 899 CreateSingleOrMultiStreamEncoder(&opus_encoder_, channels_, application_, 900 use_multistream_, encoder_sample_rate_hz_); 901 ASSERT_NE(nullptr, opus_encoder_); 902 CreateSingleOrMultiStreamDecoder(&opus_decoder_, channels_, use_multistream_, 903 decoder_sample_rate_hz_); 904 ASSERT_NE(nullptr, opus_decoder_); 905 906 // Set bitrate. 907 EXPECT_EQ( 908 0, WebRtcOpus_SetBitRate(opus_encoder_, channels_ == 1 ? 32000 : 64000)); 909 910 // Check number of channels for decoder. 911 EXPECT_EQ(channels_, WebRtcOpus_DecoderChannels(opus_decoder_)); 912 913 // Encode & decode. 914 int16_t audio_type; 915 const int decode_samples_per_channel = 916 SamplesPerChannel(decoder_sample_rate_hz_, /*ms=*/20); 917 std::unique_ptr<int16_t[]> output_data_decode( 918 new int16_t[kPackets * decode_samples_per_channel * channels_]); 919 OpusRepacketizer* rp = opus_repacketizer_create(); 920 921 size_t num_packets = 0; 922 constexpr size_t kMaxCycles = 100; 923 for (size_t idx = 0; idx < kMaxCycles; ++idx) { 924 auto speech_block = speech_data_.GetNextBlock(); 925 encoded_bytes_ = WebRtcOpus_Encode( 926 opus_encoder_, speech_block.data(), 927 CheckedDivExact(speech_block.size(), channels_), kMaxBytes, bitstream_); 928 if (opus_repacketizer_cat(rp, bitstream_, 929 checked_cast<opus_int32>(encoded_bytes_)) == 930 OPUS_OK) { 931 ++num_packets; 932 if (num_packets == kPackets) { 933 break; 934 } 935 } else { 936 // Opus repacketizer cannot guarantee a success. We try again if it fails. 937 opus_repacketizer_init(rp); 938 num_packets = 0; 939 } 940 } 941 EXPECT_EQ(kPackets, num_packets); 942 943 encoded_bytes_ = opus_repacketizer_out(rp, bitstream_, kMaxBytes); 944 945 EXPECT_EQ(decode_samples_per_channel * kPackets, 946 static_cast<size_t>(WebRtcOpus_DurationEst( 947 opus_decoder_, bitstream_, encoded_bytes_))); 948 949 EXPECT_EQ(decode_samples_per_channel * kPackets, 950 static_cast<size_t>( 951 WebRtcOpus_Decode(opus_decoder_, bitstream_, encoded_bytes_, 952 output_data_decode.get(), &audio_type))); 953 954 // Free memory. 955 opus_repacketizer_destroy(rp); 956 EXPECT_EQ(0, WebRtcOpus_EncoderFree(opus_encoder_)); 957 EXPECT_EQ(0, WebRtcOpus_DecoderFree(opus_decoder_)); 958 } 959 960 TEST(OpusVadTest, CeltUnknownStatus) { 961 const uint8_t celt[] = {0x80}; 962 EXPECT_EQ(WebRtcOpus_PacketHasVoiceActivity(celt, 1), -1); 963 } 964 965 TEST(OpusVadTest, Mono20msVadSet) { 966 uint8_t silk20msMonoVad[] = {0x78, 0x80}; 967 EXPECT_TRUE(WebRtcOpus_PacketHasVoiceActivity(silk20msMonoVad, 2)); 968 } 969 970 TEST(OpusVadTest, Mono20MsVadUnset) { 971 uint8_t silk20msMonoSilence[] = {0x78, 0x00}; 972 EXPECT_FALSE(WebRtcOpus_PacketHasVoiceActivity(silk20msMonoSilence, 2)); 973 } 974 975 TEST(OpusVadTest, Stereo20MsVadOnSideChannel) { 976 uint8_t silk20msStereoVadSideChannel[] = {0x78 | 0x04, 0x20}; 977 EXPECT_TRUE( 978 WebRtcOpus_PacketHasVoiceActivity(silk20msStereoVadSideChannel, 2)); 979 } 980 981 TEST(OpusVadTest, TwoOpusMonoFramesVadOnSecond) { 982 uint8_t twoMonoFrames[] = {0x78 | 0x1, 0x00, 0x80}; 983 EXPECT_TRUE(WebRtcOpus_PacketHasVoiceActivity(twoMonoFrames, 3)); 984 } 985 986 } // namespace webrtc