1 /*
2 * Copyright (c) 2017 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 "api/audio_codecs/builtin_audio_encoder_factory.h"
12
13 #include <limits>
14 #include <memory>
15 #include <vector>
16
17 #include "rtc_base/numerics/safe_conversions.h"
18 #include "test/gmock.h"
19 #include "test/gtest.h"
20
21 namespace webrtc {
22
23 class AudioEncoderFactoryTest
24 : public ::testing::TestWithParam<rtc::scoped_refptr<AudioEncoderFactory>> {
25 };
26
TEST_P(AudioEncoderFactoryTest,SupportsAtLeastOneFormat)27 TEST_P(AudioEncoderFactoryTest, SupportsAtLeastOneFormat) {
28 auto factory = GetParam();
29 auto supported_encoders = factory->GetSupportedEncoders();
30 EXPECT_FALSE(supported_encoders.empty());
31 }
32
TEST_P(AudioEncoderFactoryTest,CanQueryAllSupportedFormats)33 TEST_P(AudioEncoderFactoryTest, CanQueryAllSupportedFormats) {
34 auto factory = GetParam();
35 auto supported_encoders = factory->GetSupportedEncoders();
36 for (const auto& spec : supported_encoders) {
37 auto info = factory->QueryAudioEncoder(spec.format);
38 EXPECT_TRUE(info);
39 }
40 }
41
TEST_P(AudioEncoderFactoryTest,CanConstructAllSupportedEncoders)42 TEST_P(AudioEncoderFactoryTest, CanConstructAllSupportedEncoders) {
43 auto factory = GetParam();
44 auto supported_encoders = factory->GetSupportedEncoders();
45 for (const auto& spec : supported_encoders) {
46 auto info = factory->QueryAudioEncoder(spec.format);
47 auto encoder = factory->MakeAudioEncoder(127, spec.format, absl::nullopt);
48 EXPECT_TRUE(encoder);
49 EXPECT_EQ(encoder->SampleRateHz(), info->sample_rate_hz);
50 EXPECT_EQ(encoder->NumChannels(), info->num_channels);
51 EXPECT_EQ(encoder->RtpTimestampRateHz(), spec.format.clockrate_hz);
52 }
53 }
54
TEST_P(AudioEncoderFactoryTest,CanRunAllSupportedEncoders)55 TEST_P(AudioEncoderFactoryTest, CanRunAllSupportedEncoders) {
56 constexpr int kTestPayloadType = 127;
57 auto factory = GetParam();
58 auto supported_encoders = factory->GetSupportedEncoders();
59 for (const auto& spec : supported_encoders) {
60 auto encoder =
61 factory->MakeAudioEncoder(kTestPayloadType, spec.format, absl::nullopt);
62 EXPECT_TRUE(encoder);
63 encoder->Reset();
64 const int num_samples = rtc::checked_cast<int>(
65 encoder->SampleRateHz() * encoder->NumChannels() / 100);
66 rtc::Buffer out;
67 rtc::BufferT<int16_t> audio;
68 audio.SetData(num_samples, [](rtc::ArrayView<int16_t> audio) {
69 for (size_t i = 0; i != audio.size(); ++i) {
70 // Just put some numbers in there, ensure they're within range.
71 audio[i] =
72 static_cast<int16_t>(i & std::numeric_limits<int16_t>::max());
73 }
74 return audio.size();
75 });
76 // This is here to stop the test going forever with a broken encoder.
77 constexpr int kMaxEncodeCalls = 100;
78 int blocks = 0;
79 for (; blocks < kMaxEncodeCalls; ++blocks) {
80 AudioEncoder::EncodedInfo info = encoder->Encode(
81 blocks * encoder->RtpTimestampRateHz() / 100, audio, &out);
82 EXPECT_EQ(info.encoded_bytes, out.size());
83 if (info.encoded_bytes > 0) {
84 EXPECT_EQ(0u, info.encoded_timestamp);
85 EXPECT_EQ(kTestPayloadType, info.payload_type);
86 break;
87 }
88 }
89 ASSERT_LT(blocks, kMaxEncodeCalls);
90 const unsigned int next_timestamp =
91 blocks * encoder->RtpTimestampRateHz() / 100;
92 out.Clear();
93 for (; blocks < kMaxEncodeCalls; ++blocks) {
94 AudioEncoder::EncodedInfo info = encoder->Encode(
95 blocks * encoder->RtpTimestampRateHz() / 100, audio, &out);
96 EXPECT_EQ(info.encoded_bytes, out.size());
97 if (info.encoded_bytes > 0) {
98 EXPECT_EQ(next_timestamp, info.encoded_timestamp);
99 EXPECT_EQ(kTestPayloadType, info.payload_type);
100 break;
101 }
102 }
103 ASSERT_LT(blocks, kMaxEncodeCalls);
104 }
105 }
106
107 INSTANTIATE_TEST_SUITE_P(BuiltinAudioEncoderFactoryTest,
108 AudioEncoderFactoryTest,
109 ::testing::Values(CreateBuiltinAudioEncoderFactory()));
110
TEST(BuiltinAudioEncoderFactoryTest,SupportsTheExpectedFormats)111 TEST(BuiltinAudioEncoderFactoryTest, SupportsTheExpectedFormats) {
112 using ::testing::ElementsAreArray;
113 // Check that we claim to support the formats we expect from build flags, and
114 // we've ordered them correctly.
115 auto factory = CreateBuiltinAudioEncoderFactory();
116 auto specs = factory->GetSupportedEncoders();
117
118 const std::vector<SdpAudioFormat> supported_formats = [&specs] {
119 std::vector<SdpAudioFormat> formats;
120 formats.reserve(specs.size());
121 for (const auto& spec : specs) {
122 formats.push_back(spec.format);
123 }
124 return formats;
125 }();
126
127 const std::vector<SdpAudioFormat> expected_formats = {
128 #ifdef WEBRTC_CODEC_OPUS
129 {"opus", 48000, 2, {{"minptime", "10"}, {"useinbandfec", "1"}}},
130 #endif
131 #if defined(WEBRTC_CODEC_ISAC) || defined(WEBRTC_CODEC_ISACFX)
132 {"isac", 16000, 1},
133 #endif
134 #ifdef WEBRTC_CODEC_ISAC
135 {"isac", 32000, 1},
136 #endif
137 {"G722", 8000, 1},
138 #ifdef WEBRTC_CODEC_ILBC
139 {"ilbc", 8000, 1},
140 #endif
141 {"pcmu", 8000, 1},
142 {"pcma", 8000, 1}
143 };
144
145 ASSERT_THAT(supported_formats, ElementsAreArray(expected_formats));
146 }
147 } // namespace webrtc
148