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