Line data Source code
1 : /*
2 : * Copyright (C) 2004-2026 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 : #include "string_utils.h"
20 :
21 : #ifdef HAVE_CONFIG_H
22 : #include "config.h"
23 : #endif
24 : #include "logger.h"
25 :
26 : #include <algorithm>
27 : #include <string>
28 : #include <mutex>
29 :
30 : extern "C" {
31 : #if LIBAVUTIL_VERSION_MAJOR < 56
32 : AVFrameSideData*
33 : av_frame_new_side_data_from_buf(AVFrame* frame, enum AVFrameSideDataType type, AVBufferRef* buf)
34 : {
35 : auto side_data = av_frame_new_side_data(frame, type, 0);
36 : av_buffer_unref(&side_data->buf);
37 : side_data->buf = buf;
38 : side_data->data = side_data->buf->data;
39 : side_data->size = side_data->buf->size;
40 : return side_data;
41 : }
42 : #endif
43 : }
44 :
45 : namespace jami {
46 : namespace libav_utils {
47 :
48 : AVSampleFormat
49 181 : choose_sample_fmt(const AVCodec* codec, const AVSampleFormat* preferred_formats, int preferred_formats_count)
50 : {
51 181 : if (codec->sample_fmts)
52 181 : for (int i = 0; i < preferred_formats_count; ++i) {
53 361 : for (const auto* it = codec->sample_fmts; *it != -1; ++it) {
54 361 : if (*it == preferred_formats[i])
55 181 : return preferred_formats[i];
56 : }
57 : }
58 0 : return AV_SAMPLE_FMT_NONE;
59 : }
60 :
61 : AVSampleFormat
62 181 : choose_sample_fmt_default(const AVCodec* codec, AVSampleFormat defaultFormat)
63 : {
64 : // List of supported formats, current default first
65 181 : const AVSampleFormat preferred_formats[] = {defaultFormat,
66 : AV_SAMPLE_FMT_FLTP,
67 : AV_SAMPLE_FMT_FLT,
68 : AV_SAMPLE_FMT_S16P,
69 : AV_SAMPLE_FMT_S16,
70 : AV_SAMPLE_FMT_DBLP,
71 : AV_SAMPLE_FMT_DBL,
72 : AV_SAMPLE_FMT_S32P,
73 181 : AV_SAMPLE_FMT_S32};
74 181 : return choose_sample_fmt(codec, preferred_formats, sizeof(preferred_formats) / sizeof(preferred_formats[0]));
75 : }
76 :
77 : #if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(58, 9, 100)
78 : // protect libav/ffmpeg access
79 : static int
80 : avcodecManageMutex(void** data, enum AVLockOp op)
81 : {
82 : auto mutex = reinterpret_cast<std::mutex**>(data);
83 : int ret = 0;
84 : switch (op) {
85 : case AV_LOCK_CREATE:
86 : try {
87 : *mutex = new std::mutex;
88 : } catch (const std::bad_alloc& e) {
89 : return AVERROR(ENOMEM);
90 : }
91 : break;
92 : case AV_LOCK_OBTAIN:
93 : (*mutex)->lock();
94 : break;
95 : case AV_LOCK_RELEASE:
96 : (*mutex)->unlock();
97 : break;
98 : case AV_LOCK_DESTROY:
99 : delete *mutex;
100 : *mutex = nullptr;
101 : break;
102 : default:
103 : #ifdef AVERROR_BUG
104 : return AVERROR_BUG;
105 : #else
106 : break;
107 : #endif
108 : }
109 : return AVERROR(ret);
110 : }
111 : #endif
112 :
113 : static constexpr const char* AVLOGLEVEL = "AVLOGLEVEL";
114 :
115 : static void
116 38 : setAvLogLevel()
117 : {
118 38 : char* envvar = getenv(AVLOGLEVEL);
119 38 : signed level = AV_LOG_WARNING;
120 :
121 38 : if (envvar != nullptr) {
122 0 : level = to_int<int>(envvar, AV_LOG_ERROR);
123 0 : level = std::max(AV_LOG_QUIET, std::min(level, AV_LOG_DEBUG));
124 : }
125 38 : av_log_set_level(level);
126 38 : }
127 :
128 : #ifdef __ANDROID__
129 : static void
130 : androidAvLogCb(void* ptr, int level, const char* fmt, va_list vl)
131 : {
132 : if (level > av_log_get_level())
133 : return;
134 :
135 : char line[1024];
136 : int print_prefix = 1;
137 : int android_level;
138 : va_list vl2;
139 : va_copy(vl2, vl);
140 : av_log_format_line(ptr, level, fmt, vl2, line, sizeof(line), &print_prefix);
141 : va_end(vl2);
142 :
143 : // replace unprintable characters with '?'
144 : int idx = 0;
145 : while (line[idx]) {
146 : if (line[idx] < 0x08 || (line[idx] > 0x0D && line[idx] < 0x20))
147 : line[idx] = '?';
148 : ++idx;
149 : }
150 :
151 : switch (level) {
152 : case AV_LOG_QUIET:
153 : android_level = ANDROID_LOG_SILENT;
154 : break;
155 : case AV_LOG_PANIC:
156 : android_level = ANDROID_LOG_FATAL;
157 : break;
158 : case AV_LOG_FATAL:
159 : android_level = ANDROID_LOG_FATAL;
160 : break;
161 : case AV_LOG_ERROR:
162 : android_level = ANDROID_LOG_ERROR;
163 : break;
164 : case AV_LOG_WARNING:
165 : android_level = ANDROID_LOG_WARN;
166 : break;
167 : case AV_LOG_INFO:
168 : android_level = ANDROID_LOG_INFO;
169 : break;
170 : case AV_LOG_VERBOSE:
171 : android_level = ANDROID_LOG_INFO;
172 : break;
173 : case AV_LOG_DEBUG:
174 : android_level = ANDROID_LOG_DEBUG;
175 : break;
176 : case AV_LOG_TRACE:
177 : android_level = ANDROID_LOG_VERBOSE;
178 : break;
179 : default:
180 : android_level = ANDROID_LOG_DEFAULT;
181 : break;
182 : }
183 : __android_log_print(android_level, "FFmpeg", "%s", line);
184 : }
185 : #endif
186 :
187 : static void
188 38 : init_once()
189 : {
190 : #if LIBAVFORMAT_VERSION_INT < AV_VERSION_INT(58, 9, 100)
191 : av_register_all();
192 : #endif
193 38 : avdevice_register_all();
194 38 : avformat_network_init();
195 : #if LIBAVFILTER_VERSION_INT < AV_VERSION_INT(7, 13, 100)
196 : avfilter_register_all();
197 : #endif
198 :
199 : #if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(58, 9, 100)
200 : av_lockmgr_register(avcodecManageMutex);
201 : #endif
202 :
203 38 : setAvLogLevel();
204 :
205 : #ifdef __ANDROID__
206 : // android doesn't like stdout and stderr :(
207 : av_log_set_callback(androidAvLogCb);
208 : #endif
209 38 : }
210 :
211 : static std::once_flag already_called;
212 :
213 : void
214 45 : av_init()
215 : {
216 45 : std::call_once(already_called, init_once);
217 45 : }
218 :
219 : bool
220 0 : is_yuv_planar(const AVPixFmtDescriptor& desc)
221 : {
222 0 : if (not(desc.flags & AV_PIX_FMT_FLAG_PLANAR) or desc.flags & AV_PIX_FMT_FLAG_RGB)
223 0 : return false;
224 :
225 : /* handle formats that do not use all planes */
226 0 : unsigned used_bit_mask = (1u << desc.nb_components) - 1;
227 0 : for (unsigned i = 0; i < desc.nb_components; ++i)
228 0 : used_bit_mask &= ~(1u << desc.comp[i].plane);
229 :
230 0 : return not used_bit_mask;
231 : }
232 :
233 : std::string
234 58 : getError(int err)
235 : {
236 58 : std::string ret(AV_ERROR_MAX_STRING_SIZE, '\0');
237 58 : av_strerror(err, (char*) ret.data(), ret.size());
238 58 : return ret;
239 0 : }
240 :
241 : const char*
242 47 : getDictValue(const AVDictionary* d, const std::string& key, int flags)
243 : {
244 47 : auto* kv = av_dict_get(d, key.c_str(), nullptr, flags);
245 47 : if (kv)
246 47 : return kv->value;
247 : else
248 0 : return "";
249 : }
250 :
251 : void
252 143 : setDictValue(AVDictionary** d, const std::string& key, const std::string& value, int flags)
253 : {
254 143 : av_dict_set(d, key.c_str(), value.c_str(), flags);
255 143 : }
256 :
257 : void
258 8908 : fillWithBlack(AVFrame* frame)
259 : {
260 8908 : const AVPixelFormat format = static_cast<AVPixelFormat>(frame->format);
261 8908 : const int planes = av_pix_fmt_count_planes(format);
262 : // workaround for casting pointers to different sizes
263 : // on 64 bit machines: sizeof(ptrdiff_t) != sizeof(int)
264 : ptrdiff_t linesizes[4];
265 35632 : for (int i = 0; i < planes; ++i)
266 26724 : linesizes[i] = frame->linesize[i];
267 8908 : int ret = av_image_fill_black(frame->data, linesizes, format, frame->color_range, frame->width, frame->height);
268 8908 : if (ret < 0) {
269 0 : JAMI_ERR() << "Failed to blacken frame";
270 : }
271 8908 : }
272 :
273 : void
274 0 : fillWithSilence(AVFrame* frame)
275 : {
276 0 : int ret = av_samples_set_silence(frame->extended_data,
277 : 0,
278 : frame->nb_samples,
279 : frame->ch_layout.nb_channels,
280 0 : (AVSampleFormat) frame->format);
281 0 : if (ret < 0)
282 0 : JAMI_ERR() << "Failed to fill frame with silence";
283 0 : }
284 :
285 : AudioFormat
286 6 : getFormat(const AVFrame* frame)
287 : {
288 12 : return AudioFormat {static_cast<unsigned>(frame->sample_rate),
289 6 : static_cast<unsigned>(frame->ch_layout.nb_channels),
290 6 : static_cast<AVSampleFormat>(frame->format)};
291 : }
292 :
293 : } // namespace libav_utils
294 : } // namespace jami
|