/* * Copyright (c) 2014 The WebRTC project authors. All Rights Reserved. * * Use of this source code is governed by a BSD-style license * that can be found in the LICENSE file in the root of the source * tree. An additional intellectual property rights grant can be found * in the file PATENTS. All contributing project authors may * be found in the AUTHORS file in the root of the source tree. */ #include "modules/audio_coding/codecs/opus/opus_interface.h" #include "modules/audio_coding/codecs/tools/audio_codec_speed_test.h" using ::std::string; namespace webrtc { static const int kOpusBlockDurationMs = 20; static const int kOpusSamplingKhz = 48; class OpusSpeedTest : public AudioCodecSpeedTest { protected: OpusSpeedTest(); void SetUp() override; void TearDown() override; float EncodeABlock(int16_t* in_data, uint8_t* bit_stream, size_t max_bytes, size_t* encoded_bytes) override; float DecodeABlock(const uint8_t* bit_stream, size_t encoded_bytes, int16_t* out_data) override; WebRtcOpusEncInst* opus_encoder_; WebRtcOpusDecInst* opus_decoder_; }; OpusSpeedTest::OpusSpeedTest() : AudioCodecSpeedTest(kOpusBlockDurationMs, kOpusSamplingKhz, kOpusSamplingKhz), opus_encoder_(NULL), opus_decoder_(NULL) {} void OpusSpeedTest::SetUp() { AudioCodecSpeedTest::SetUp(); // If channels_ == 1, use Opus VOIP mode, otherwise, audio mode. int app = channels_ == 1 ? 0 : 1; /* Create encoder memory. */ EXPECT_EQ(0, WebRtcOpus_EncoderCreate(&opus_encoder_, channels_, app)); EXPECT_EQ(0, WebRtcOpus_DecoderCreate(&opus_decoder_, channels_)); /* Set bitrate. */ EXPECT_EQ(0, WebRtcOpus_SetBitRate(opus_encoder_, bit_rate_)); } void OpusSpeedTest::TearDown() { AudioCodecSpeedTest::TearDown(); /* Free memory. */ EXPECT_EQ(0, WebRtcOpus_EncoderFree(opus_encoder_)); EXPECT_EQ(0, WebRtcOpus_DecoderFree(opus_decoder_)); } float OpusSpeedTest::EncodeABlock(int16_t* in_data, uint8_t* bit_stream, size_t max_bytes, size_t* encoded_bytes) { clock_t clocks = clock(); int value = WebRtcOpus_Encode(opus_encoder_, in_data, input_length_sample_, max_bytes, bit_stream); clocks = clock() - clocks; EXPECT_GT(value, 0); *encoded_bytes = static_cast(value); return 1000.0 * clocks / CLOCKS_PER_SEC; } float OpusSpeedTest::DecodeABlock(const uint8_t* bit_stream, size_t encoded_bytes, int16_t* out_data) { int value; int16_t audio_type; clock_t clocks = clock(); value = WebRtcOpus_Decode(opus_decoder_, bit_stream, encoded_bytes, out_data, &audio_type); clocks = clock() - clocks; EXPECT_EQ(output_length_sample_, static_cast(value)); return 1000.0 * clocks / CLOCKS_PER_SEC; } /* Test audio length in second. */ constexpr size_t kDurationSec = 400; #define ADD_TEST(complexity) \ TEST_P(OpusSpeedTest, OpusSetComplexityTest##complexity) { \ /* Set complexity. */ \ printf("Setting complexity to %d ...\n", complexity); \ EXPECT_EQ(0, WebRtcOpus_SetComplexity(opus_encoder_, complexity)); \ EncodeDecode(kDurationSec); \ } ADD_TEST(10) ADD_TEST(9) ADD_TEST(8) ADD_TEST(7) ADD_TEST(6) ADD_TEST(5) ADD_TEST(4) ADD_TEST(3) ADD_TEST(2) ADD_TEST(1) ADD_TEST(0) #define ADD_BANDWIDTH_TEST(bandwidth) \ TEST_P(OpusSpeedTest, OpusSetBandwidthTest##bandwidth) { \ /* Set bandwidth. */ \ printf("Setting bandwidth to %d ...\n", bandwidth); \ EXPECT_EQ(0, WebRtcOpus_SetBandwidth(opus_encoder_, bandwidth)); \ EncodeDecode(kDurationSec); \ } ADD_BANDWIDTH_TEST(OPUS_BANDWIDTH_NARROWBAND) ADD_BANDWIDTH_TEST(OPUS_BANDWIDTH_MEDIUMBAND) ADD_BANDWIDTH_TEST(OPUS_BANDWIDTH_WIDEBAND) ADD_BANDWIDTH_TEST(OPUS_BANDWIDTH_SUPERWIDEBAND) ADD_BANDWIDTH_TEST(OPUS_BANDWIDTH_FULLBAND) // List all test cases: (channel, bit rat, filename, extension). const coding_param param_set[] = { std::make_tuple(1, 64000, string("audio_coding/speech_mono_32_48kHz"), string("pcm"), true), std::make_tuple(1, 32000, string("audio_coding/speech_mono_32_48kHz"), string("pcm"), true), std::make_tuple(2, 64000, string("audio_coding/music_stereo_48kHz"), string("pcm"), true)}; INSTANTIATE_TEST_SUITE_P(AllTest, OpusSpeedTest, ::testing::ValuesIn(param_set)); } // namespace webrtc