Line data Source code
1 : /*
2 : * Copyright (C) 2004-2024 Savoir-faire Linux Inc.
3 : *
4 : * Author: Tristan Matthews <tristan.matthews@savoirfairelinux.com>
5 : * Author: Luca Barbato <lu_zero@gentoo.org>
6 : * Author: Guillaume Roguez <Guillaume.Roguez@savoirfairelinux.com>
7 : * Author: Philippe Gorley <philippe.gorley@savoirfairelinux.com>
8 : *
9 : * This program is free software; you can redistribute it and/or modify
10 : * it under the terms of the GNU General Public License as published by
11 : * the Free Software Foundation; either version 3 of the License, or
12 : * (at your option) any later version.
13 : *
14 : * This program is distributed in the hope that it will be useful,
15 : * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 : * GNU General Public License for more details.
18 : *
19 : * You should have received a copy of the GNU General Public License
20 : * along with this program; if not, write to the Free Software
21 : * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
22 : */
23 :
24 : #include "libav_deps.h" // MUST BE INCLUDED FIRST
25 :
26 : #ifdef HAVE_CONFIG_H
27 : #include "config.h"
28 : #endif
29 : #include "video/video_base.h"
30 : #include "logger.h"
31 :
32 : #include <vector>
33 : #include <algorithm>
34 : #include <string>
35 : #include <iostream>
36 : #include <thread>
37 : #include <mutex>
38 : #include <exception>
39 : #include <ciso646> // fix windows compiler bug
40 :
41 : extern "C" {
42 : #if LIBAVUTIL_VERSION_MAJOR < 56
43 : AVFrameSideData*
44 : av_frame_new_side_data_from_buf(AVFrame* frame, enum AVFrameSideDataType type, AVBufferRef* buf)
45 : {
46 : auto side_data = av_frame_new_side_data(frame, type, 0);
47 : av_buffer_unref(&side_data->buf);
48 : side_data->buf = buf;
49 : side_data->data = side_data->buf->data;
50 : side_data->size = side_data->buf->size;
51 : return side_data;
52 : }
53 : #endif
54 : }
55 :
56 : namespace jami {
57 : namespace libav_utils {
58 :
59 : AVSampleFormat
60 196 : choose_sample_fmt(const AVCodec* codec,
61 : const AVSampleFormat* preferred_formats,
62 : int preferred_formats_count)
63 : {
64 196 : if (codec->sample_fmts)
65 196 : for (int i = 0; i < preferred_formats_count; ++i) {
66 391 : for (auto it = codec->sample_fmts; *it != -1; ++it) {
67 391 : if (*it == preferred_formats[i])
68 196 : return preferred_formats[i];
69 : }
70 : }
71 0 : return AV_SAMPLE_FMT_NONE;
72 : }
73 :
74 : AVSampleFormat
75 196 : choose_sample_fmt_default(const AVCodec* codec, AVSampleFormat defaultFormat)
76 : {
77 : // List of supported formats, current default first
78 196 : const AVSampleFormat preferred_formats[] = {defaultFormat,
79 : AV_SAMPLE_FMT_FLTP,
80 : AV_SAMPLE_FMT_FLT,
81 : AV_SAMPLE_FMT_S16P,
82 : AV_SAMPLE_FMT_S16,
83 : AV_SAMPLE_FMT_DBLP,
84 : AV_SAMPLE_FMT_DBL,
85 : AV_SAMPLE_FMT_S32P,
86 196 : AV_SAMPLE_FMT_S32};
87 196 : return choose_sample_fmt(codec,
88 : preferred_formats,
89 196 : sizeof(preferred_formats) / sizeof(preferred_formats[0]));
90 : }
91 :
92 : #if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(58, 9, 100)
93 : // protect libav/ffmpeg access
94 : static int
95 : avcodecManageMutex(void** data, enum AVLockOp op)
96 : {
97 : auto mutex = reinterpret_cast<std::mutex**>(data);
98 : int ret = 0;
99 : switch (op) {
100 : case AV_LOCK_CREATE:
101 : try {
102 : *mutex = new std::mutex;
103 : } catch (const std::bad_alloc& e) {
104 : return AVERROR(ENOMEM);
105 : }
106 : break;
107 : case AV_LOCK_OBTAIN:
108 : (*mutex)->lock();
109 : break;
110 : case AV_LOCK_RELEASE:
111 : (*mutex)->unlock();
112 : break;
113 : case AV_LOCK_DESTROY:
114 : delete *mutex;
115 : *mutex = nullptr;
116 : break;
117 : default:
118 : #ifdef AVERROR_BUG
119 : return AVERROR_BUG;
120 : #else
121 : break;
122 : #endif
123 : }
124 : return AVERROR(ret);
125 : }
126 : #endif
127 :
128 : static constexpr const char* AVLOGLEVEL = "AVLOGLEVEL";
129 :
130 : static void
131 38 : setAvLogLevel()
132 : {
133 38 : char* envvar = getenv(AVLOGLEVEL);
134 38 : signed level = AV_LOG_WARNING;
135 :
136 38 : if (envvar != nullptr) {
137 0 : level = to_int<int>(envvar, AV_LOG_ERROR);
138 0 : level = std::max(AV_LOG_QUIET, std::min(level, AV_LOG_DEBUG));
139 : }
140 38 : av_log_set_level(level);
141 38 : }
142 :
143 : #ifdef __ANDROID__
144 : static void
145 : androidAvLogCb(void* ptr, int level, const char* fmt, va_list vl)
146 : {
147 : if (level > av_log_get_level())
148 : return;
149 :
150 : char line[1024];
151 : int print_prefix = 1;
152 : int android_level;
153 : va_list vl2;
154 : va_copy(vl2, vl);
155 : av_log_format_line(ptr, level, fmt, vl2, line, sizeof(line), &print_prefix);
156 : va_end(vl2);
157 :
158 : // replace unprintable characters with '?'
159 : int idx = 0;
160 : while (line[idx]) {
161 : if (line[idx] < 0x08 || (line[idx] > 0x0D && line[idx] < 0x20))
162 : line[idx] = '?';
163 : ++idx;
164 : }
165 :
166 : switch (level) {
167 : case AV_LOG_QUIET:
168 : android_level = ANDROID_LOG_SILENT;
169 : break;
170 : case AV_LOG_PANIC:
171 : android_level = ANDROID_LOG_FATAL;
172 : break;
173 : case AV_LOG_FATAL:
174 : android_level = ANDROID_LOG_FATAL;
175 : break;
176 : case AV_LOG_ERROR:
177 : android_level = ANDROID_LOG_ERROR;
178 : break;
179 : case AV_LOG_WARNING:
180 : android_level = ANDROID_LOG_WARN;
181 : break;
182 : case AV_LOG_INFO:
183 : android_level = ANDROID_LOG_INFO;
184 : break;
185 : case AV_LOG_VERBOSE:
186 : android_level = ANDROID_LOG_INFO;
187 : break;
188 : case AV_LOG_DEBUG:
189 : android_level = ANDROID_LOG_DEBUG;
190 : break;
191 : case AV_LOG_TRACE:
192 : android_level = ANDROID_LOG_VERBOSE;
193 : break;
194 : default:
195 : android_level = ANDROID_LOG_DEFAULT;
196 : break;
197 : }
198 : __android_log_print(android_level, "FFmpeg", "%s", line);
199 : }
200 : #endif
201 :
202 : static void
203 38 : init_once()
204 : {
205 : #if LIBAVFORMAT_VERSION_INT < AV_VERSION_INT(58, 9, 100)
206 : av_register_all();
207 : #endif
208 38 : avdevice_register_all();
209 38 : avformat_network_init();
210 : #if LIBAVFILTER_VERSION_INT < AV_VERSION_INT(7, 13, 100)
211 : avfilter_register_all();
212 : #endif
213 :
214 : #if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(58, 9, 100)
215 : av_lockmgr_register(avcodecManageMutex);
216 : #endif
217 :
218 38 : setAvLogLevel();
219 :
220 : #ifdef __ANDROID__
221 : // android doesn't like stdout and stderr :(
222 : av_log_set_callback(androidAvLogCb);
223 : #endif
224 38 : }
225 :
226 : static std::once_flag already_called;
227 :
228 : void
229 45 : av_init()
230 : {
231 45 : std::call_once(already_called, init_once);
232 45 : }
233 :
234 : bool
235 0 : is_yuv_planar(const AVPixFmtDescriptor& desc)
236 : {
237 0 : if (not(desc.flags & AV_PIX_FMT_FLAG_PLANAR) or desc.flags & AV_PIX_FMT_FLAG_RGB)
238 0 : return false;
239 :
240 : /* handle formats that do not use all planes */
241 0 : unsigned used_bit_mask = (1u << desc.nb_components) - 1;
242 0 : for (unsigned i = 0; i < desc.nb_components; ++i)
243 0 : used_bit_mask &= ~(1u << desc.comp[i].plane);
244 :
245 0 : return not used_bit_mask;
246 : }
247 :
248 : std::string
249 61 : getError(int err)
250 : {
251 61 : std::string ret(AV_ERROR_MAX_STRING_SIZE, '\0');
252 61 : av_strerror(err, (char*) ret.data(), ret.size());
253 61 : return ret;
254 0 : }
255 :
256 : const char*
257 48 : getDictValue(const AVDictionary* d, const std::string& key, int flags)
258 : {
259 48 : auto kv = av_dict_get(d, key.c_str(), nullptr, flags);
260 48 : if (kv)
261 48 : return kv->value;
262 : else
263 0 : return "";
264 : }
265 :
266 : void
267 173 : setDictValue(AVDictionary** d, const std::string& key, const std::string& value, int flags)
268 : {
269 173 : av_dict_set(d, key.c_str(), value.c_str(), flags);
270 173 : }
271 :
272 : void
273 8966 : fillWithBlack(AVFrame* frame)
274 : {
275 8966 : const AVPixelFormat format = static_cast<AVPixelFormat>(frame->format);
276 8966 : const int planes = av_pix_fmt_count_planes(format);
277 : // workaround for casting pointers to different sizes
278 : // on 64 bit machines: sizeof(ptrdiff_t) != sizeof(int)
279 : ptrdiff_t linesizes[4];
280 35864 : for (int i = 0; i < planes; ++i)
281 26898 : linesizes[i] = frame->linesize[i];
282 8966 : int ret = av_image_fill_black(frame->data,
283 : linesizes,
284 : format,
285 : frame->color_range,
286 : frame->width,
287 : frame->height);
288 8966 : if (ret < 0) {
289 0 : JAMI_ERR() << "Failed to blacken frame";
290 : }
291 8966 : }
292 :
293 : void
294 0 : fillWithSilence(AVFrame* frame)
295 : {
296 0 : int ret = av_samples_set_silence(frame->extended_data,
297 : 0,
298 : frame->nb_samples,
299 : frame->ch_layout.nb_channels,
300 0 : (AVSampleFormat) frame->format);
301 0 : if (ret < 0)
302 0 : JAMI_ERR() << "Failed to fill frame with silence";
303 0 : }
304 :
305 : } // namespace libav_utils
306 : } // namespace jami
|