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