OLD | NEW |
| (Empty) |
1 /* | |
2 * Copyright (c) 2016 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 "webrtc/modules/audio_coding/codecs/builtin_audio_decoder_factory_inter
nal.h" | |
12 | |
13 #include <memory> | |
14 #include <vector> | |
15 | |
16 #include "webrtc/common_types.h" | |
17 #include "webrtc/modules/audio_coding/codecs/cng/webrtc_cng.h" | |
18 #include "webrtc/modules/audio_coding/codecs/g711/audio_decoder_pcm.h" | |
19 #include "webrtc/rtc_base/checks.h" | |
20 #include "webrtc/rtc_base/optional.h" | |
21 #ifdef WEBRTC_CODEC_G722 | |
22 #include "webrtc/modules/audio_coding/codecs/g722/audio_decoder_g722.h" | |
23 #endif | |
24 #ifdef WEBRTC_CODEC_ILBC | |
25 #include "webrtc/modules/audio_coding/codecs/ilbc/audio_decoder_ilbc.h" | |
26 #endif | |
27 #ifdef WEBRTC_CODEC_ISACFX | |
28 #include "webrtc/modules/audio_coding/codecs/isac/fix/include/audio_decoder_isac
fix.h" // nogncheck | |
29 #endif | |
30 #ifdef WEBRTC_CODEC_ISAC | |
31 #include "webrtc/modules/audio_coding/codecs/isac/main/include/audio_decoder_isa
c.h" // nogncheck | |
32 #endif | |
33 #ifdef WEBRTC_CODEC_OPUS | |
34 #include "webrtc/modules/audio_coding/codecs/opus/audio_decoder_opus.h" | |
35 #endif | |
36 #include "webrtc/modules/audio_coding/codecs/pcm16b/audio_decoder_pcm16b.h" | |
37 | |
38 namespace webrtc { | |
39 | |
40 namespace { | |
41 | |
42 struct NamedDecoderConstructor { | |
43 const char* name; | |
44 | |
45 // If |format| is good, return true and (if |out| isn't null) reset |*out| to | |
46 // a new decoder object. If the |format| is not good, return false. | |
47 bool (*constructor)(const SdpAudioFormat& format, | |
48 std::unique_ptr<AudioDecoder>* out); | |
49 }; | |
50 | |
51 // TODO(kwiberg): These factory functions should probably be moved to each | |
52 // decoder. | |
53 NamedDecoderConstructor decoder_constructors[] = { | |
54 {"pcmu", | |
55 [](const SdpAudioFormat& format, std::unique_ptr<AudioDecoder>* out) { | |
56 if (format.clockrate_hz == 8000 && format.num_channels >= 1) { | |
57 if (out) { | |
58 out->reset(new AudioDecoderPcmU(format.num_channels)); | |
59 } | |
60 return true; | |
61 } else { | |
62 return false; | |
63 } | |
64 }}, | |
65 {"pcma", | |
66 [](const SdpAudioFormat& format, std::unique_ptr<AudioDecoder>* out) { | |
67 if (format.clockrate_hz == 8000 && format.num_channels >= 1) { | |
68 if (out) { | |
69 out->reset(new AudioDecoderPcmA(format.num_channels)); | |
70 } | |
71 return true; | |
72 } else { | |
73 return false; | |
74 } | |
75 }}, | |
76 #ifdef WEBRTC_CODEC_ILBC | |
77 {"ilbc", | |
78 [](const SdpAudioFormat& format, std::unique_ptr<AudioDecoder>* out) { | |
79 if (format.clockrate_hz == 8000 && format.num_channels == 1) { | |
80 if (out) { | |
81 out->reset(new AudioDecoderIlbcImpl); | |
82 } | |
83 return true; | |
84 } else { | |
85 return false; | |
86 } | |
87 }}, | |
88 #endif | |
89 #if defined(WEBRTC_CODEC_ISACFX) | |
90 {"isac", | |
91 [](const SdpAudioFormat& format, std::unique_ptr<AudioDecoder>* out) { | |
92 if (format.clockrate_hz == 16000 && format.num_channels == 1) { | |
93 if (out) { | |
94 out->reset(new AudioDecoderIsacFixImpl(format.clockrate_hz)); | |
95 } | |
96 return true; | |
97 } else { | |
98 return false; | |
99 } | |
100 }}, | |
101 #elif defined(WEBRTC_CODEC_ISAC) | |
102 {"isac", | |
103 [](const SdpAudioFormat& format, std::unique_ptr<AudioDecoder>* out) { | |
104 if ((format.clockrate_hz == 16000 || format.clockrate_hz == 32000) && | |
105 format.num_channels == 1) { | |
106 if (out) { | |
107 out->reset(new AudioDecoderIsacFloatImpl(format.clockrate_hz)); | |
108 } | |
109 return true; | |
110 } else { | |
111 return false; | |
112 } | |
113 }}, | |
114 #endif | |
115 {"l16", | |
116 [](const SdpAudioFormat& format, std::unique_ptr<AudioDecoder>* out) { | |
117 if (format.num_channels >= 1) { | |
118 if (out) { | |
119 out->reset(new AudioDecoderPcm16B(format.clockrate_hz, | |
120 format.num_channels)); | |
121 } | |
122 return true; | |
123 } else { | |
124 return false; | |
125 } | |
126 }}, | |
127 #ifdef WEBRTC_CODEC_G722 | |
128 {"g722", | |
129 [](const SdpAudioFormat& format, std::unique_ptr<AudioDecoder>* out) { | |
130 if (format.clockrate_hz == 8000) { | |
131 if (format.num_channels == 1) { | |
132 if (out) { | |
133 out->reset(new AudioDecoderG722Impl); | |
134 } | |
135 return true; | |
136 } else if (format.num_channels == 2) { | |
137 if (out) { | |
138 out->reset(new AudioDecoderG722StereoImpl); | |
139 } | |
140 return true; | |
141 } | |
142 } | |
143 return false; | |
144 }}, | |
145 #endif | |
146 #ifdef WEBRTC_CODEC_OPUS | |
147 {"opus", | |
148 [](const SdpAudioFormat& format, std::unique_ptr<AudioDecoder>* out) { | |
149 const rtc::Optional<int> num_channels = [&] { | |
150 auto stereo = format.parameters.find("stereo"); | |
151 if (stereo != format.parameters.end()) { | |
152 if (stereo->second == "0") { | |
153 return rtc::Optional<int>(1); | |
154 } else if (stereo->second == "1") { | |
155 return rtc::Optional<int>(2); | |
156 } else { | |
157 return rtc::Optional<int>(); // Bad stereo parameter. | |
158 } | |
159 } | |
160 return rtc::Optional<int>(1); // Default to mono. | |
161 }(); | |
162 if (format.clockrate_hz == 48000 && format.num_channels == 2 && | |
163 num_channels) { | |
164 if (out) { | |
165 out->reset(new AudioDecoderOpusImpl(*num_channels)); | |
166 } | |
167 return true; | |
168 } else { | |
169 return false; | |
170 } | |
171 }}, | |
172 #endif | |
173 }; | |
174 | |
175 class BuiltinAudioDecoderFactory : public AudioDecoderFactory { | |
176 public: | |
177 std::vector<AudioCodecSpec> GetSupportedDecoders() override { | |
178 // Although this looks a bit strange, it means specs need only be | |
179 // initialized once, and that that initialization is thread-safe. | |
180 static std::vector<AudioCodecSpec> specs = [] { | |
181 std::vector<AudioCodecSpec> specs; | |
182 #ifdef WEBRTC_CODEC_OPUS | |
183 AudioCodecInfo opus_info{48000, 1, 64000, 6000, 510000}; | |
184 opus_info.allow_comfort_noise = false; | |
185 opus_info.supports_network_adaption = true; | |
186 // clang-format off | |
187 SdpAudioFormat opus_format({"opus", 48000, 2, { | |
188 {"minptime", "10"}, | |
189 {"useinbandfec", "1"} | |
190 }}); | |
191 // clang-format on | |
192 specs.push_back({std::move(opus_format), opus_info}); | |
193 #endif | |
194 #if (defined(WEBRTC_CODEC_ISAC) || defined(WEBRTC_CODEC_ISACFX)) | |
195 specs.push_back(AudioCodecSpec{{"ISAC", 16000, 1}, | |
196 {16000, 1, 32000, 10000, 56000}}); | |
197 #endif | |
198 #if (defined(WEBRTC_CODEC_ISAC)) | |
199 specs.push_back(AudioCodecSpec{{"ISAC", 32000, 1}, | |
200 {32000, 1, 56000, 10000, 56000}}); | |
201 #endif | |
202 #ifdef WEBRTC_CODEC_G722 | |
203 specs.push_back(AudioCodecSpec{{"G722", 8000, 1}, | |
204 {16000, 1, 64000}}); | |
205 #endif | |
206 #ifdef WEBRTC_CODEC_ILBC | |
207 specs.push_back(AudioCodecSpec{{"ILBC", 8000, 1}, | |
208 {8000, 1, 13300}}); | |
209 #endif | |
210 specs.push_back(AudioCodecSpec{{"PCMU", 8000, 1}, | |
211 {8000, 1, 64000}}); | |
212 specs.push_back(AudioCodecSpec{{"PCMA", 8000, 1}, | |
213 {8000, 1, 64000}}); | |
214 return specs; | |
215 }(); | |
216 return specs; | |
217 } | |
218 | |
219 bool IsSupportedDecoder(const SdpAudioFormat& format) override { | |
220 for (const auto& dc : decoder_constructors) { | |
221 if (STR_CASE_CMP(format.name.c_str(), dc.name) == 0) { | |
222 return dc.constructor(format, nullptr); | |
223 } | |
224 } | |
225 return false; | |
226 } | |
227 | |
228 std::unique_ptr<AudioDecoder> MakeAudioDecoder( | |
229 const SdpAudioFormat& format) override { | |
230 for (const auto& dc : decoder_constructors) { | |
231 if (STR_CASE_CMP(format.name.c_str(), dc.name) == 0) { | |
232 std::unique_ptr<AudioDecoder> decoder; | |
233 bool ok = dc.constructor(format, &decoder); | |
234 RTC_DCHECK_EQ(ok, decoder != nullptr); | |
235 if (decoder) { | |
236 const int expected_sample_rate_hz = | |
237 STR_CASE_CMP(format.name.c_str(), "g722") == 0 | |
238 ? 2 * format.clockrate_hz | |
239 : format.clockrate_hz; | |
240 RTC_CHECK_EQ(expected_sample_rate_hz, decoder->SampleRateHz()); | |
241 } | |
242 return decoder; | |
243 } | |
244 } | |
245 return nullptr; | |
246 } | |
247 }; | |
248 | |
249 } // namespace | |
250 | |
251 rtc::scoped_refptr<AudioDecoderFactory> | |
252 CreateBuiltinAudioDecoderFactoryInternal() { | |
253 return rtc::scoped_refptr<AudioDecoderFactory>( | |
254 new rtc::RefCountedObject<BuiltinAudioDecoderFactory>); | |
255 } | |
256 | |
257 } // namespace webrtc | |
OLD | NEW |