/* * Copyright (c) 2017 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 "api/audio_codecs/builtin_audio_encoder_factory.h" #include #include #include #include "rtc_base/numerics/safe_conversions.h" #include "test/gmock.h" #include "test/gtest.h" namespace webrtc { class AudioEncoderFactoryTest : public ::testing::TestWithParam> { }; TEST_P(AudioEncoderFactoryTest, SupportsAtLeastOneFormat) { auto factory = GetParam(); auto supported_encoders = factory->GetSupportedEncoders(); EXPECT_FALSE(supported_encoders.empty()); } TEST_P(AudioEncoderFactoryTest, CanQueryAllSupportedFormats) { auto factory = GetParam(); auto supported_encoders = factory->GetSupportedEncoders(); for (const auto& spec : supported_encoders) { auto info = factory->QueryAudioEncoder(spec.format); EXPECT_TRUE(info); } } TEST_P(AudioEncoderFactoryTest, CanConstructAllSupportedEncoders) { auto factory = GetParam(); auto supported_encoders = factory->GetSupportedEncoders(); for (const auto& spec : supported_encoders) { auto info = factory->QueryAudioEncoder(spec.format); auto encoder = factory->MakeAudioEncoder(127, spec.format, absl::nullopt); EXPECT_TRUE(encoder); EXPECT_EQ(encoder->SampleRateHz(), info->sample_rate_hz); EXPECT_EQ(encoder->NumChannels(), info->num_channels); EXPECT_EQ(encoder->RtpTimestampRateHz(), spec.format.clockrate_hz); } } TEST_P(AudioEncoderFactoryTest, CanRunAllSupportedEncoders) { constexpr int kTestPayloadType = 127; auto factory = GetParam(); auto supported_encoders = factory->GetSupportedEncoders(); for (const auto& spec : supported_encoders) { auto encoder = factory->MakeAudioEncoder(kTestPayloadType, spec.format, absl::nullopt); EXPECT_TRUE(encoder); encoder->Reset(); const int num_samples = rtc::checked_cast( encoder->SampleRateHz() * encoder->NumChannels() / 100); rtc::Buffer out; rtc::BufferT audio; audio.SetData(num_samples, [](rtc::ArrayView audio) { for (size_t i = 0; i != audio.size(); ++i) { // Just put some numbers in there, ensure they're within range. audio[i] = static_cast(i & std::numeric_limits::max()); } return audio.size(); }); // This is here to stop the test going forever with a broken encoder. constexpr int kMaxEncodeCalls = 100; int blocks = 0; for (; blocks < kMaxEncodeCalls; ++blocks) { AudioEncoder::EncodedInfo info = encoder->Encode( blocks * encoder->RtpTimestampRateHz() / 100, audio, &out); EXPECT_EQ(info.encoded_bytes, out.size()); if (info.encoded_bytes > 0) { EXPECT_EQ(0u, info.encoded_timestamp); EXPECT_EQ(kTestPayloadType, info.payload_type); break; } } ASSERT_LT(blocks, kMaxEncodeCalls); const unsigned int next_timestamp = blocks * encoder->RtpTimestampRateHz() / 100; out.Clear(); for (; blocks < kMaxEncodeCalls; ++blocks) { AudioEncoder::EncodedInfo info = encoder->Encode( blocks * encoder->RtpTimestampRateHz() / 100, audio, &out); EXPECT_EQ(info.encoded_bytes, out.size()); if (info.encoded_bytes > 0) { EXPECT_EQ(next_timestamp, info.encoded_timestamp); EXPECT_EQ(kTestPayloadType, info.payload_type); break; } } ASSERT_LT(blocks, kMaxEncodeCalls); } } INSTANTIATE_TEST_SUITE_P(BuiltinAudioEncoderFactoryTest, AudioEncoderFactoryTest, ::testing::Values(CreateBuiltinAudioEncoderFactory())); TEST(BuiltinAudioEncoderFactoryTest, SupportsTheExpectedFormats) { using ::testing::ElementsAreArray; // Check that we claim to support the formats we expect from build flags, and // we've ordered them correctly. auto factory = CreateBuiltinAudioEncoderFactory(); auto specs = factory->GetSupportedEncoders(); const std::vector supported_formats = [&specs] { std::vector formats; formats.reserve(specs.size()); for (const auto& spec : specs) { formats.push_back(spec.format); } return formats; }(); const std::vector expected_formats = { #ifdef WEBRTC_CODEC_OPUS {"opus", 48000, 2, {{"minptime", "10"}, {"useinbandfec", "1"}}}, #endif #if defined(WEBRTC_CODEC_ISAC) || defined(WEBRTC_CODEC_ISACFX) {"isac", 16000, 1}, #endif #ifdef WEBRTC_CODEC_ISAC {"isac", 32000, 1}, #endif {"G722", 8000, 1}, #ifdef WEBRTC_CODEC_ILBC {"ilbc", 8000, 1}, #endif {"pcmu", 8000, 1}, {"pcma", 8000, 1} }; ASSERT_THAT(supported_formats, ElementsAreArray(expected_formats)); } // Tests that using more channels than the maximum does not work. TEST(BuiltinAudioEncoderFactoryTest, MaxNrOfChannels) { rtc::scoped_refptr aef = CreateBuiltinAudioEncoderFactory(); std::vector codecs = { #ifdef WEBRTC_CODEC_OPUS "opus", #endif #if defined(WEBRTC_CODEC_ISAC) || defined(WEBRTC_CODEC_ISACFX) "isac", #endif #ifdef WEBRTC_CODEC_ILBC "ilbc", #endif "pcmu", "pcma", "l16", "G722", "G711", }; for (auto codec : codecs) { EXPECT_FALSE(aef->MakeAudioEncoder( /*payload_type=*/111, /*format=*/ SdpAudioFormat(codec, 32000, AudioEncoder::kMaxNumberOfChannels + 1), /*codec_pair_id=*/absl::nullopt)); } } } // namespace webrtc