• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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