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