Line data Source code
1 : /*
2 : * Copyright (C) 2004-2024 Savoir-faire Linux Inc.
3 : *
4 : * This program is free software: you can redistribute it and/or modify
5 : * it under the terms of the GNU General Public License as published by
6 : * the Free Software Foundation, either version 3 of the License, or
7 : * (at your option) any later version.
8 : *
9 : * This program is distributed in the hope that it will be useful,
10 : * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 : * GNU General Public License for more details.
13 : *
14 : * You should have received a copy of the GNU General Public License
15 : * along with this program. If not, see <https://www.gnu.org/licenses/>.
16 : */
17 :
18 : #include "libav_deps.h" // MUST BE INCLUDED FIRST
19 : #ifdef HAVE_CONFIG_H
20 : #include "config.h"
21 : #endif
22 : #include "logger.h"
23 : #include "system_codec_container.h"
24 : #include "media_encoder.h"
25 :
26 : #include <sstream>
27 :
28 : #ifdef APPLE
29 : #include <TargetConditionals.h>
30 : #endif
31 :
32 : namespace jami {
33 :
34 : decltype(getGlobalInstance<SystemCodecContainer>)& getSystemCodecContainer
35 : = getGlobalInstance<SystemCodecContainer>;
36 :
37 271 : SystemCodecContainer::SystemCodecContainer()
38 : {
39 271 : initCodecConfig();
40 271 : }
41 :
42 271 : SystemCodecContainer::~SystemCodecContainer()
43 : {
44 : // TODO
45 271 : }
46 :
47 : void
48 271 : SystemCodecContainer::initCodecConfig()
49 : {
50 : #ifdef ENABLE_VIDEO
51 271 : auto minH264 = SystemCodecInfo::DEFAULT_H264_MIN_QUALITY;
52 271 : auto maxH264 = SystemCodecInfo::DEFAULT_H264_MAX_QUALITY;
53 271 : auto minH265 = SystemCodecInfo::DEFAULT_H264_MIN_QUALITY;
54 271 : auto maxH265 = SystemCodecInfo::DEFAULT_H264_MAX_QUALITY;
55 271 : auto minVP8 = SystemCodecInfo::DEFAULT_VP8_MIN_QUALITY;
56 271 : auto maxVP8 = SystemCodecInfo::DEFAULT_VP8_MAX_QUALITY;
57 271 : auto defaultBitrate = SystemCodecInfo::DEFAULT_VIDEO_BITRATE;
58 : #endif
59 7317 : availableCodecList_ = {
60 : #ifdef ENABLE_VIDEO
61 : /* Define supported video codec*/
62 0 : std::make_shared<SystemVideoCodecInfo>(AV_CODEC_ID_HEVC,
63 0 : AV_CODEC_ID_HEVC,
64 : "H.265/HEVC",
65 : "H265",
66 : "",
67 271 : CODEC_ENCODER_DECODER,
68 : defaultBitrate,
69 : minH265,
70 : maxH265),
71 :
72 0 : std::make_shared<SystemVideoCodecInfo>(AV_CODEC_ID_H264,
73 0 : AV_CODEC_ID_H264,
74 : "H.264/AVC",
75 : "H264",
76 : "libx264",
77 542 : CODEC_ENCODER_DECODER,
78 : defaultBitrate,
79 : minH264,
80 : maxH264),
81 :
82 0 : std::make_shared<SystemVideoCodecInfo>(AV_CODEC_ID_VP8,
83 0 : AV_CODEC_ID_VP8,
84 : "VP8",
85 : "VP8",
86 : "libvpx",
87 542 : CODEC_ENCODER_DECODER,
88 : defaultBitrate,
89 : minVP8,
90 : maxVP8),
91 : #if !(defined(TARGET_OS_IOS) && TARGET_OS_IOS)
92 0 : std::make_shared<SystemVideoCodecInfo>(AV_CODEC_ID_MPEG4,
93 0 : AV_CODEC_ID_MPEG4,
94 : "MP4V-ES",
95 : "MP4V-ES",
96 : "mpeg4",
97 542 : CODEC_ENCODER_DECODER,
98 : defaultBitrate),
99 :
100 0 : std::make_shared<SystemVideoCodecInfo>(AV_CODEC_ID_H263,
101 0 : AV_CODEC_ID_H263,
102 : "H.263",
103 : "H263-1998",
104 : "h263",
105 542 : CODEC_ENCODER_DECODER,
106 : defaultBitrate),
107 : #endif
108 :
109 : #endif
110 : /* Define supported audio codec*/
111 :
112 0 : std::make_shared<SystemAudioCodecInfo>(AV_CODEC_ID_OPUS,
113 0 : AV_CODEC_ID_OPUS,
114 : "Opus",
115 : "opus",
116 : "libopus",
117 0 : CODEC_ENCODER_DECODER,
118 0 : 0,
119 0 : 48000,
120 0 : 2,
121 0 : 104,
122 542 : AV_SAMPLE_FMT_FLT),
123 :
124 0 : std::make_shared<SystemAudioCodecInfo>(AV_CODEC_ID_ADPCM_G722,
125 0 : AV_CODEC_ID_ADPCM_G722,
126 : "G.722",
127 : "G722",
128 : "g722",
129 0 : CODEC_ENCODER_DECODER,
130 0 : 0,
131 0 : 16000,
132 0 : 1,
133 542 : 9),
134 :
135 0 : std::make_shared<SystemAudioCodecInfo>(AV_CODEC_ID_ADPCM_G726,
136 0 : AV_CODEC_ID_ADPCM_G726,
137 : "G.726",
138 : "G726-32",
139 : "g726",
140 0 : CODEC_ENCODER_DECODER,
141 0 : 0,
142 0 : 8000,
143 0 : 1,
144 542 : 2),
145 :
146 0 : std::make_shared<SystemAudioCodecInfo>(AV_CODEC_ID_SPEEX | 0x20000000,
147 0 : AV_CODEC_ID_SPEEX,
148 : "Speex",
149 : "speex",
150 : "libspeex",
151 0 : CODEC_ENCODER_DECODER,
152 0 : 0,
153 0 : 32000,
154 0 : 1,
155 542 : 112),
156 :
157 0 : std::make_shared<SystemAudioCodecInfo>(AV_CODEC_ID_SPEEX | 0x10000000,
158 0 : AV_CODEC_ID_SPEEX,
159 : "Speex",
160 : "speex",
161 : "libspeex",
162 0 : CODEC_ENCODER_DECODER,
163 0 : 0,
164 0 : 16000,
165 0 : 1,
166 542 : 111),
167 :
168 0 : std::make_shared<SystemAudioCodecInfo>(AV_CODEC_ID_SPEEX,
169 0 : AV_CODEC_ID_SPEEX,
170 : "Speex",
171 : "speex",
172 : "libspeex",
173 0 : CODEC_ENCODER_DECODER,
174 0 : 0,
175 0 : 8000,
176 0 : 1,
177 542 : 110),
178 :
179 0 : std::make_shared<SystemAudioCodecInfo>(AV_CODEC_ID_PCM_ALAW,
180 0 : AV_CODEC_ID_PCM_ALAW,
181 : "G.711a",
182 : "PCMA",
183 : "pcm_alaw",
184 0 : CODEC_ENCODER_DECODER,
185 0 : 64,
186 0 : 8000,
187 0 : 1,
188 542 : 8),
189 :
190 271 : std::make_shared<SystemAudioCodecInfo>(AV_CODEC_ID_PCM_MULAW,
191 0 : AV_CODEC_ID_PCM_MULAW,
192 : "G.711u",
193 : "PCMU",
194 : "pcm_mulaw",
195 0 : CODEC_ENCODER_DECODER,
196 0 : 64,
197 0 : 8000,
198 0 : 1,
199 542 : 0),
200 3794 : };
201 271 : setActiveH265();
202 271 : checkInstalledCodecs();
203 271 : }
204 :
205 : bool
206 271 : SystemCodecContainer::setActiveH265()
207 : {
208 : #if (defined(TARGET_OS_IOS) && TARGET_OS_IOS)
209 : removeCodecByName("H265");
210 : return false;
211 : #endif
212 :
213 271 : auto apiName = MediaEncoder::testH265Accel();
214 271 : if (apiName != "") {
215 0 : JAMI_WARN("Found a usable accelerated H265/HEVC codec: %s, enabling.", apiName.c_str());
216 0 : return true;
217 : } else {
218 271 : JAMI_ERR("Unable to find a usable accelerated H265/HEVC codec, disabling.");
219 271 : removeCodecByName("H265");
220 : }
221 271 : return false;
222 271 : }
223 :
224 : void
225 271 : SystemCodecContainer::checkInstalledCodecs()
226 : {
227 271 : std::ostringstream enc_ss;
228 271 : std::ostringstream dec_ss;
229 :
230 3523 : for (const auto& codecIt : availableCodecList_) {
231 3252 : AVCodecID codecId = (AVCodecID) codecIt->avcodecId;
232 3252 : CodecType codecType = codecIt->codecType;
233 :
234 3252 : if (codecType & CODEC_ENCODER) {
235 3252 : if (avcodec_find_encoder(codecId) != nullptr)
236 3252 : enc_ss << codecIt->name << ' ';
237 : else
238 0 : codecIt->codecType = (CodecType)((unsigned) codecType & ~CODEC_ENCODER);
239 : }
240 :
241 3252 : if (codecType & CODEC_DECODER) {
242 3252 : if (avcodec_find_decoder(codecId) != nullptr)
243 3252 : dec_ss << codecIt->name << ' ';
244 : else
245 0 : codecIt->codecType = (CodecType)((unsigned) codecType & ~CODEC_DECODER);
246 : }
247 : }
248 271 : JAMI_INFO("Encoder(s) found: %s", enc_ss.str().c_str());
249 271 : JAMI_INFO("Decoder(s) found: %s", dec_ss.str().c_str());
250 271 : }
251 :
252 : std::vector<std::shared_ptr<SystemCodecInfo>>
253 808 : SystemCodecContainer::getSystemCodecInfoList(MediaType mediaType)
254 : {
255 808 : if (mediaType & MEDIA_ALL)
256 808 : return availableCodecList_;
257 :
258 : // otherwise we have to instantiate a new list containing filtered objects
259 : // must be destroyed by the caller…
260 0 : std::vector<std::shared_ptr<SystemCodecInfo>> systemCodecList;
261 0 : for (const auto& codecIt : availableCodecList_) {
262 0 : if (codecIt->mediaType & mediaType)
263 0 : systemCodecList.push_back(codecIt);
264 : }
265 0 : return systemCodecList;
266 0 : }
267 :
268 : std::vector<unsigned>
269 0 : SystemCodecContainer::getSystemCodecInfoIdList(MediaType mediaType)
270 : {
271 0 : std::vector<unsigned> idList;
272 0 : for (const auto& codecIt : availableCodecList_) {
273 0 : if (codecIt->mediaType & mediaType)
274 0 : idList.push_back(codecIt->id);
275 : }
276 0 : return idList;
277 0 : }
278 :
279 : std::shared_ptr<SystemCodecInfo>
280 0 : SystemCodecContainer::searchCodecById(unsigned codecId, MediaType mediaType)
281 : {
282 0 : for (const auto& codecIt : availableCodecList_) {
283 0 : if ((codecIt->id == codecId) && (codecIt->mediaType & mediaType))
284 0 : return codecIt;
285 : }
286 0 : return {};
287 : }
288 : std::shared_ptr<SystemCodecInfo>
289 165 : SystemCodecContainer::searchCodecByName(const std::string& name, MediaType mediaType)
290 : {
291 1191 : for (const auto& codecIt : availableCodecList_) {
292 1191 : if (codecIt->name == name && (codecIt->mediaType & mediaType))
293 165 : return codecIt;
294 : }
295 0 : return {};
296 : }
297 : std::shared_ptr<SystemCodecInfo>
298 0 : SystemCodecContainer::searchCodecByPayload(unsigned payload, MediaType mediaType)
299 : {
300 0 : for (const auto& codecIt : availableCodecList_) {
301 0 : if ((codecIt->payloadType == payload) && (codecIt->mediaType & mediaType))
302 0 : return codecIt;
303 : }
304 0 : return {};
305 : }
306 : void
307 271 : SystemCodecContainer::removeCodecByName(const std::string& name, MediaType mediaType)
308 : {
309 271 : for (auto codecIt = availableCodecList_.begin(); codecIt != availableCodecList_.end();
310 0 : ++codecIt) {
311 271 : if ((*codecIt)->mediaType & mediaType and (*codecIt)->name == name) {
312 271 : availableCodecList_.erase(codecIt);
313 271 : break;
314 : }
315 : }
316 271 : }
317 :
318 : } // namespace jami
|