FFmpeg coverage


Directory: ../../../ffmpeg/
File: src/libavformat/utils.c
Date: 2026-09-16 07:09:49
Exec Total Coverage
Lines: 272 394 69.0%
Functions: 24 31 77.4%
Branches: 170 309 55.0%

Line Branch Exec Source
1 /*
2 * various utility functions for use within FFmpeg
3 * Copyright (c) 2000, 2001, 2002 Fabrice Bellard
4 *
5 * This file is part of FFmpeg.
6 *
7 * FFmpeg is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
11 *
12 * FFmpeg is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with FFmpeg; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20 */
21
22 #include <stdint.h>
23 #include <time.h>
24
25 #include "config.h"
26
27 #include "libavutil/avassert.h"
28 #include "libavutil/avstring.h"
29 #include "libavutil/bprint.h"
30 #include "libavutil/dict.h"
31 #include "libavutil/internal.h"
32 #include "libavutil/mem.h"
33 #include "libavutil/opt.h"
34 #include "libavutil/parseutils.h"
35 #include "libavutil/time.h"
36 #include "libavutil/time_internal.h"
37
38 #include "libavcodec/internal.h"
39
40 #include "avformat.h"
41 #include "avio_internal.h"
42 #include "internal.h"
43 #if CONFIG_NETWORK
44 #include "network.h"
45 #endif
46 #include "os_support.h"
47 #include "urldecode.h"
48
49 /**
50 * @file
51 * various utility functions for use within FFmpeg
52 */
53
54 /* an arbitrarily chosen "sane" max packet size -- 50M */
55 #define SANE_CHUNK_SIZE (50000000)
56
57 /* Read the data in sane-sized chunks and append to pkt.
58 * Return the number of bytes read or an error. */
59 288195 static int append_packet_chunked(AVIOContext *s, AVPacket *pkt, int size)
60 {
61 288195 int orig_size = pkt->size;
62 int ret;
63
64 do {
65 288195 int prev_size = pkt->size;
66 int read_size;
67
68 /* When the caller requests a lot of data, limit it to the amount
69 * left in file or SANE_CHUNK_SIZE when it is not known. */
70 288195 read_size = size;
71
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 288194 times.
288195 if (read_size > SANE_CHUNK_SIZE/10) {
72 1 read_size = ffio_limit(s, read_size);
73 // If filesize/maxsize is unknown, limit to SANE_CHUNK_SIZE
74
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 if (ffiocontext(s)->maxsize < 0)
75 1 read_size = FFMIN(read_size, SANE_CHUNK_SIZE);
76 }
77
78 288195 ret = av_grow_packet(pkt, read_size);
79
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 288195 times.
288195 if (ret < 0)
80 break;
81
82 288195 ret = avio_read(s, pkt->data + prev_size, read_size);
83
2/2
✓ Branch 0 taken 1010 times.
✓ Branch 1 taken 287185 times.
288195 if (ret != read_size) {
84 1010 av_shrink_packet(pkt, prev_size + FFMAX(ret, 0));
85 1010 break;
86 }
87
88 287185 size -= read_size;
89
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 287185 times.
287185 } while (size > 0);
90
2/2
✓ Branch 0 taken 964 times.
✓ Branch 1 taken 287231 times.
288195 if (size > 0)
91 964 pkt->flags |= AV_PKT_FLAG_CORRUPT;
92
93
2/2
✓ Branch 0 taken 2338 times.
✓ Branch 1 taken 285857 times.
288195 if (!pkt->size)
94 2338 av_packet_unref(pkt);
95
2/2
✓ Branch 0 taken 285852 times.
✓ Branch 1 taken 2343 times.
288195 return pkt->size > orig_size ? pkt->size - orig_size : ret;
96 }
97
98 280536 int av_get_packet(AVIOContext *s, AVPacket *pkt, int size)
99 {
100 #if FF_API_INIT_PACKET
101 FF_DISABLE_DEPRECATION_WARNINGS
102 280536 av_init_packet(pkt);
103 280536 pkt->data = NULL;
104 280536 pkt->size = 0;
105 FF_ENABLE_DEPRECATION_WARNINGS
106 #else
107 av_packet_unref(pkt);
108 #endif
109 280536 pkt->pos = avio_tell(s);
110
111 280536 return append_packet_chunked(s, pkt, size);
112 }
113
114 8249 int av_append_packet(AVIOContext *s, AVPacket *pkt, int size)
115 {
116
2/2
✓ Branch 0 taken 590 times.
✓ Branch 1 taken 7659 times.
8249 if (!pkt->size)
117 590 return av_get_packet(s, pkt, size);
118 7659 return append_packet_chunked(s, pkt, size);
119 }
120
121 1050 int av_filename_number_test(const char *filename)
122 {
123 AVBPrint bp;
124
125
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1050 times.
1050 if (!filename)
126 return 0;
127 1050 av_bprint_init(&bp, 0, AV_BPRINT_SIZE_COUNT_ONLY);
128 1050 return (ff_bprint_get_frame_filename(&bp, filename, 1, AV_FRAME_FILENAME_FLAGS_IGNORE_TRUNCATION) >= 0);
129 }
130
131 /**********************************************************/
132
133 1368 unsigned int ff_codec_get_tag(const AVCodecTag *tags, enum AVCodecID id)
134 {
135
2/2
✓ Branch 0 taken 10497 times.
✓ Branch 1 taken 2 times.
10499 while (tags->id != AV_CODEC_ID_NONE) {
136
2/2
✓ Branch 0 taken 1366 times.
✓ Branch 1 taken 9131 times.
10497 if (tags->id == id)
137 1366 return tags->tag;
138 9131 tags++;
139 }
140 2 return 0;
141 }
142
143 3581 enum AVCodecID ff_codec_get_id(const AVCodecTag *tags, unsigned int tag)
144 {
145
2/2
✓ Branch 0 taken 298596 times.
✓ Branch 1 taken 1134 times.
299730 for (int i = 0; tags[i].id != AV_CODEC_ID_NONE; i++)
146
2/2
✓ Branch 0 taken 2447 times.
✓ Branch 1 taken 296149 times.
298596 if (tag == tags[i].tag)
147 2447 return tags[i].id;
148
2/2
✓ Branch 0 taken 103155 times.
✓ Branch 1 taken 1128 times.
104283 for (int i = 0; tags[i].id != AV_CODEC_ID_NONE; i++)
149
2/2
✓ Branch 2 taken 6 times.
✓ Branch 3 taken 103149 times.
103155 if (ff_toupper4(tag) == ff_toupper4(tags[i].tag))
150 6 return tags[i].id;
151 1128 return AV_CODEC_ID_NONE;
152 }
153
154 617 enum AVCodecID ff_get_pcm_codec_id(int bps, int flt, int be, int sflags)
155 {
156
2/4
✓ Branch 0 taken 617 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 617 times.
617 if (bps <= 0 || bps > 64)
157 return AV_CODEC_ID_NONE;
158
159
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 613 times.
617 if (flt) {
160
2/3
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
4 switch (bps) {
161 2 case 32:
162
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 return be ? AV_CODEC_ID_PCM_F32BE : AV_CODEC_ID_PCM_F32LE;
163 2 case 64:
164
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 return be ? AV_CODEC_ID_PCM_F64BE : AV_CODEC_ID_PCM_F64LE;
165 default:
166 return AV_CODEC_ID_NONE;
167 }
168 } else {
169 613 bps += 7;
170 613 bps >>= 3;
171
2/2
✓ Branch 0 taken 593 times.
✓ Branch 1 taken 20 times.
613 if (sflags & (1 << (bps - 1))) {
172
3/6
✗ Branch 0 not taken.
✓ Branch 1 taken 575 times.
✓ Branch 2 taken 15 times.
✓ Branch 3 taken 3 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
593 switch (bps) {
173 case 1:
174 return AV_CODEC_ID_PCM_S8;
175 575 case 2:
176
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 573 times.
575 return be ? AV_CODEC_ID_PCM_S16BE : AV_CODEC_ID_PCM_S16LE;
177 15 case 3:
178
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 14 times.
15 return be ? AV_CODEC_ID_PCM_S24BE : AV_CODEC_ID_PCM_S24LE;
179 3 case 4:
180
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 return be ? AV_CODEC_ID_PCM_S32BE : AV_CODEC_ID_PCM_S32LE;
181 case 8:
182 return be ? AV_CODEC_ID_PCM_S64BE : AV_CODEC_ID_PCM_S64LE;
183 default:
184 return AV_CODEC_ID_NONE;
185 }
186 } else {
187
1/5
✓ Branch 0 taken 20 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
20 switch (bps) {
188 20 case 1:
189 20 return AV_CODEC_ID_PCM_U8;
190 case 2:
191 return be ? AV_CODEC_ID_PCM_U16BE : AV_CODEC_ID_PCM_U16LE;
192 case 3:
193 return be ? AV_CODEC_ID_PCM_U24BE : AV_CODEC_ID_PCM_U24LE;
194 case 4:
195 return be ? AV_CODEC_ID_PCM_U32BE : AV_CODEC_ID_PCM_U32LE;
196 default:
197 return AV_CODEC_ID_NONE;
198 }
199 }
200 }
201 }
202
203 6279 unsigned int av_codec_get_tag(const AVCodecTag *const *tags, enum AVCodecID id)
204 {
205 unsigned int tag;
206
2/2
✓ Branch 1 taken 14 times.
✓ Branch 2 taken 6265 times.
6279 if (!av_codec_get_tag2(tags, id, &tag))
207 14 return 0;
208 6265 return tag;
209 }
210
211 9735 int av_codec_get_tag2(const AVCodecTag * const *tags, enum AVCodecID id,
212 unsigned int *tag)
213 {
214
3/4
✓ Branch 0 taken 18436 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 18402 times.
✓ Branch 3 taken 34 times.
18436 for (int i = 0; tags && tags[i]; i++) {
215 18402 const AVCodecTag *codec_tags = tags[i];
216
2/2
✓ Branch 0 taken 802185 times.
✓ Branch 1 taken 8701 times.
810886 while (codec_tags->id != AV_CODEC_ID_NONE) {
217
2/2
✓ Branch 0 taken 9701 times.
✓ Branch 1 taken 792484 times.
802185 if (codec_tags->id == id) {
218 9701 *tag = codec_tags->tag;
219 9701 return 1;
220 }
221 792484 codec_tags++;
222 }
223 }
224 34 return 0;
225 }
226
227 262 enum AVCodecID av_codec_get_id(const AVCodecTag *const *tags, unsigned int tag)
228 {
229
3/4
✓ Branch 0 taken 500 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 421 times.
✓ Branch 3 taken 79 times.
500 for (int i = 0; tags && tags[i]; i++) {
230 421 enum AVCodecID id = ff_codec_get_id(tags[i], tag);
231
2/2
✓ Branch 0 taken 183 times.
✓ Branch 1 taken 238 times.
421 if (id != AV_CODEC_ID_NONE)
232 183 return id;
233 }
234 79 return AV_CODEC_ID_NONE;
235 }
236
237 1133 int ff_alloc_extradata(AVCodecParameters *par, int size)
238 {
239 1133 av_freep(&par->extradata);
240 1133 par->extradata_size = 0;
241
242
2/4
✓ Branch 0 taken 1133 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 1133 times.
1133 if (size < 0 || size >= INT32_MAX - AV_INPUT_BUFFER_PADDING_SIZE)
243 return AVERROR(EINVAL);
244
245 1133 par->extradata = av_malloc(size + AV_INPUT_BUFFER_PADDING_SIZE);
246
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1133 times.
1133 if (!par->extradata)
247 return AVERROR(ENOMEM);
248
249 1133 memset(par->extradata + size, 0, AV_INPUT_BUFFER_PADDING_SIZE);
250 1133 par->extradata_size = size;
251
252 1133 return 0;
253 }
254
255 /*******************************************************/
256
257 37 uint64_t ff_ntp_time(void)
258 {
259 37 return (av_gettime() / 1000) * 1000 + NTP_OFFSET_US;
260 }
261
262 uint64_t ff_get_formatted_ntp_time(uint64_t ntp_time_us)
263 {
264 uint64_t ntp_ts, frac_part, sec;
265 uint32_t usec;
266
267 //current ntp time in seconds and microseconds
268 sec = ntp_time_us / 1000000;
269 usec = ntp_time_us % 1000000;
270
271 //encoding in ntp timestamp format
272 frac_part = usec * 0xFFFFFFFFULL;
273 frac_part /= 1000000;
274
275 if (sec > 0xFFFFFFFFULL)
276 av_log(NULL, AV_LOG_WARNING, "NTP time format roll over detected\n");
277
278 ntp_ts = sec << 32;
279 ntp_ts |= frac_part;
280
281 return ntp_ts;
282 }
283
284 uint64_t ff_parse_ntp_time(uint64_t ntp_ts)
285 {
286 uint64_t sec = ntp_ts >> 32;
287 uint64_t frac_part = ntp_ts & 0xFFFFFFFFULL;
288 uint64_t usec = (frac_part * 1000000) / 0xFFFFFFFFULL;
289
290 return (sec * 1000000) + usec;
291 }
292
293 156804 int ff_bprint_get_frame_filename(struct AVBPrint *buf, const char *path, int64_t number, int flags)
294 {
295 const char *p;
296 char c;
297 int nd, percentd_found;
298
299 156804 p = path;
300 156804 percentd_found = 0;
301 for (;;) {
302 11950116 c = *p++;
303
2/2
✓ Branch 0 taken 156804 times.
✓ Branch 1 taken 11793312 times.
11950116 if (c == '\0')
304 156804 break;
305
2/2
✓ Branch 0 taken 156047 times.
✓ Branch 1 taken 11637265 times.
11793312 if (c == '%') {
306 do {
307 156047 nd = 0;
308
2/2
✓ Branch 0 taken 311982 times.
✓ Branch 1 taken 156047 times.
468029 while (av_isdigit(*p)) {
309
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 311982 times.
311982 if (nd >= INT_MAX / 10 - 255)
310 goto fail;
311 311982 nd = nd * 10 + *p++ - '0';
312 }
313 156047 c = *p++;
314
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 156047 times.
156047 } while (av_isdigit(c));
315
316
1/3
✗ Branch 0 not taken.
✓ Branch 1 taken 156047 times.
✗ Branch 2 not taken.
156047 switch (c) {
317 case '%':
318 goto addchar;
319 156047 case 'd':
320
3/4
✓ Branch 0 taken 155381 times.
✓ Branch 1 taken 666 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 155381 times.
156047 if (!(flags & AV_FRAME_FILENAME_FLAGS_MULTIPLE) && percentd_found)
321 goto fail;
322 156047 percentd_found = 1;
323
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 156047 times.
156047 if (number < 0)
324 nd += 1;
325 156047 av_bprintf(buf, "%0*" PRId64, nd, number);
326 156047 break;
327 default:
328 goto fail;
329 }
330 } else {
331 11637265 addchar:
332 11637265 av_bprint_chars(buf, c, 1);
333 }
334 }
335
2/2
✓ Branch 0 taken 757 times.
✓ Branch 1 taken 156047 times.
156804 if (!percentd_found)
336 757 goto fail;
337
3/4
✓ Branch 0 taken 155739 times.
✓ Branch 1 taken 308 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 155739 times.
156047 if (!(flags & AV_FRAME_FILENAME_FLAGS_IGNORE_TRUNCATION) && !av_bprint_is_complete(buf))
338 return AVERROR(ENOMEM);
339 156047 return 0;
340 757 fail:
341 757 return AVERROR(EINVAL);
342 }
343
344 static int get_frame_filename(char *buf, int buf_size, const char *path, int64_t number, int flags)
345 {
346 AVBPrint bp;
347 av_bprint_init_for_buffer(&bp, buf, buf_size);
348 return ff_bprint_get_frame_filename(&bp, path, number, flags) < 0 ? -1 : 0;
349 }
350
351 int av_get_frame_filename2(char *buf, int buf_size, const char *path, int number, int flags)
352 {
353 return get_frame_filename(buf, buf_size, path, number, flags);
354 }
355
356 int av_get_frame_filename(char *buf, int buf_size, const char *path, int number)
357 {
358 return get_frame_filename(buf, buf_size, path, number, 0);
359 }
360
361 9 void av_url_split(char *proto, int proto_size,
362 char *authorization, int authorization_size,
363 char *hostname, int hostname_size,
364 int *port_ptr, char *path, int path_size, const char *url)
365 {
366 const char *p, *ls, *at, *at2, *col, *brk;
367
368
1/2
✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
9 if (port_ptr)
369 9 *port_ptr = -1;
370
1/2
✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
9 if (proto_size > 0)
371 9 proto[0] = 0;
372
1/2
✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
9 if (authorization_size > 0)
373 9 authorization[0] = 0;
374
1/2
✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
9 if (hostname_size > 0)
375 9 hostname[0] = 0;
376
1/2
✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
9 if (path_size > 0)
377 9 path[0] = 0;
378
379 /* parse protocol */
380
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 1 times.
9 if ((p = strchr(url, ':'))) {
381 8 av_strlcpy(proto, url, FFMIN(proto_size, p + 1 - url));
382 8 p++; /* skip ':' */
383
1/2
✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
8 if (*p == '/')
384 8 p++;
385
1/2
✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
8 if (*p == '/')
386 8 p++;
387 } else {
388 /* no protocol means plain filename */
389 1 av_strlcpy(path, url, path_size);
390 1 return;
391 }
392
393 /* separate path from hostname */
394 8 ls = p + strcspn(p, "/?#");
395 8 av_strlcpy(path, ls, path_size);
396
397 /* the rest is hostname, use that to parse auth/port */
398
1/2
✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
8 if (ls != p) {
399 /* authorization (user[:pass]@hostname) */
400 8 at2 = p;
401
4/4
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 7 times.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 1 times.
10 while ((at = strchr(p, '@')) && at < ls) {
402 2 av_strlcpy(authorization, at2,
403 2 FFMIN(authorization_size, at + 1 - at2));
404 2 p = at + 1; /* skip '@' */
405 }
406
407
1/6
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
8 if (*p == '[' && (brk = strchr(p, ']')) && brk < ls) {
408 /* [host]:port */
409 av_strlcpy(hostname, p + 1,
410 FFMIN(hostname_size, brk - p));
411 if (brk[1] == ':' && port_ptr)
412 *port_ptr = atoi(brk + 2);
413
3/4
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 7 times.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
8 } else if ((col = strchr(p, ':')) && col < ls) {
414 1 av_strlcpy(hostname, p,
415 1 FFMIN(col + 1 - p, hostname_size));
416
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (port_ptr)
417 1 *port_ptr = atoi(col + 1);
418 } else
419 7 av_strlcpy(hostname, p,
420 7 FFMIN(ls + 1 - p, hostname_size));
421 }
422 }
423
424 1 int ff_mkdir_p(const char *path)
425 {
426 1 int ret = 0;
427 1 char *temp = av_strdup(path);
428 1 char *pos = temp;
429 1 char tmp_ch = '\0';
430
431
2/4
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
1 if (!path || !temp) {
432 return -1;
433 }
434
435
2/4
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 1 times.
1 if (!av_strncasecmp(temp, "/", 1) || !av_strncasecmp(temp, "\\", 1)) {
436 pos++;
437
2/4
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 1 times.
1 } else if (!av_strncasecmp(temp, "./", 2) || !av_strncasecmp(temp, ".\\", 2)) {
438 pos += 2;
439
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
1 } else if (is_dos_path(temp)) {
440 /* Skip Windows drive letter (e.g. "C:") and the separator(s) after it.
441 * Otherwise the loop below calls mkdir("C:"), which on Windows is a
442 * drive-relative path. When the process CWD is on a different drive,
443 * "C:" resolves to the drive root (C:\), and mkdir on the root
444 * returns EACCES, causing spurious "Permission denied" errors. */
445 pos += 2;
446 while (*pos == '/' || *pos == '\\')
447 pos++;
448 }
449
450
2/2
✓ Branch 0 taken 28 times.
✓ Branch 1 taken 1 times.
29 for ( ; *pos != '\0'; ++pos) {
451
3/4
✓ Branch 0 taken 27 times.
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 27 times.
28 if (*pos == '/' || *pos == '\\') {
452 1 tmp_ch = *pos;
453 1 *pos = '\0';
454 1 ret = mkdir(temp, 0755);
455
2/4
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
1 if (ret < 0 && errno != EEXIST) {
456 int err = errno;
457 av_free(temp);
458 errno = err;
459 return ret;
460 }
461 1 *pos = tmp_ch;
462 }
463 }
464
465
2/4
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
1 if ((*(pos - 1) != '/') && (*(pos - 1) != '\\')) {
466 1 ret = mkdir(temp, 0755);
467 }
468
469 1 av_free(temp);
470 1 return ret;
471 }
472
473 3506 char *ff_data_to_hex(char *buff, const uint8_t *src, int s, int lowercase)
474 {
475 static const char hex_table_uc[16] = { '0', '1', '2', '3',
476 '4', '5', '6', '7',
477 '8', '9', 'A', 'B',
478 'C', 'D', 'E', 'F' };
479 static const char hex_table_lc[16] = { '0', '1', '2', '3',
480 '4', '5', '6', '7',
481 '8', '9', 'a', 'b',
482 'c', 'd', 'e', 'f' };
483
2/2
✓ Branch 0 taken 2809 times.
✓ Branch 1 taken 697 times.
3506 const char *hex_table = lowercase ? hex_table_lc : hex_table_uc;
484
485
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3506 times.
3506 av_assume(s >= 0);
486
2/2
✓ Branch 0 taken 56110 times.
✓ Branch 1 taken 3506 times.
59616 for (unsigned i = 0; i < s; i++) {
487 56110 buff[i * 2] = hex_table[src[i] >> 4];
488 56110 buff[i * 2 + 1] = hex_table[src[i] & 0xF];
489 }
490 3506 buff[2U * s] = '\0';
491
492 3506 return buff;
493 }
494
495 3 int ff_hex_to_data(uint8_t *data, const char *p)
496 {
497 int c, len, v;
498
499 3 len = 0;
500 3 v = 1;
501 for (;;) {
502 96 p += strspn(p, SPACE_CHARS);
503
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 96 times.
99 if (*p == '\0')
504 3 break;
505 96 c = av_toupper((unsigned char) *p++);
506
2/4
✓ Branch 0 taken 96 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 96 times.
✗ Branch 3 not taken.
96 if (c >= '0' && c <= '9')
507 96 c = c - '0';
508 else if (c >= 'A' && c <= 'F')
509 c = c - 'A' + 10;
510 else
511 break;
512 96 v = (v << 4) | c;
513
2/2
✓ Branch 0 taken 48 times.
✓ Branch 1 taken 48 times.
96 if (v & 0x100) {
514
1/2
✓ Branch 0 taken 48 times.
✗ Branch 1 not taken.
48 if (data)
515 48 data[len] = v;
516 48 len++;
517 48 v = 1;
518 }
519 }
520 3 return len;
521 }
522
523 3 void ff_parse_key_value(const char *str, ff_parse_key_val_cb callback_get_buf,
524 void *context)
525 {
526 3 const char *ptr = str;
527
528 /* Parse key=value pairs. */
529 11 for (;;) {
530 const char *key;
531 14 char *dest = NULL, *dest_end;
532 14 int key_len, dest_len = 0;
533
534 /* Skip whitespace and potential commas. */
535
5/6
✓ Branch 0 taken 19 times.
✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 19 times.
✓ Branch 4 taken 8 times.
✓ Branch 5 taken 11 times.
22 while (*ptr && (av_isspace(*ptr) || *ptr == ','))
536 8 ptr++;
537
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 11 times.
14 if (!*ptr)
538 3 break;
539
540 11 key = ptr;
541
542
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 if (!(ptr = strchr(key, '=')))
543 break;
544 11 ptr++;
545 11 key_len = ptr - key;
546
547 11 callback_get_buf(context, key, key_len, &dest, &dest_len);
548
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 3 times.
11 dest_end = dest ? dest + dest_len - 1 : NULL;
549
550
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 5 times.
11 if (*ptr == '\"') {
551 6 ptr++;
552
3/4
✓ Branch 0 taken 52 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 46 times.
✓ Branch 3 taken 6 times.
52 while (*ptr && *ptr != '\"') {
553
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 46 times.
46 if (*ptr == '\\') {
554 if (!ptr[1])
555 break;
556 if (dest && dest < dest_end)
557 *dest++ = ptr[1];
558 ptr += 2;
559 } else {
560
3/4
✓ Branch 0 taken 45 times.
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 45 times.
✗ Branch 3 not taken.
46 if (dest && dest < dest_end)
561 45 *dest++ = *ptr;
562 46 ptr++;
563 }
564 }
565
1/2
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
6 if (*ptr == '\"')
566 6 ptr++;
567 } else {
568
4/6
✓ Branch 0 taken 31 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 31 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 26 times.
✓ Branch 5 taken 5 times.
31 for (; *ptr && !(av_isspace(*ptr) || *ptr == ','); ptr++)
569
3/4
✓ Branch 0 taken 14 times.
✓ Branch 1 taken 12 times.
✓ Branch 2 taken 14 times.
✗ Branch 3 not taken.
26 if (dest && dest < dest_end)
570 14 *dest++ = *ptr;
571 }
572
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 3 times.
11 if (dest)
573 8 *dest = 0;
574 }
575 3 }
576
577 9114 int avformat_network_init(void)
578 {
579 #if CONFIG_NETWORK
580 int ret;
581
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 9114 times.
9114 if ((ret = ff_network_init()) < 0)
582 return ret;
583
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 9114 times.
9114 if ((ret = ff_tls_init()) < 0)
584 return ret;
585 #endif
586 9114 return 0;
587 }
588
589 9114 int avformat_network_deinit(void)
590 {
591 #if CONFIG_NETWORK
592 9114 ff_network_close();
593 9114 ff_tls_deinit();
594 #endif
595 9114 return 0;
596 }
597
598 609 int ff_is_http_proto(const char *filename) {
599 609 const char *proto = avio_find_protocol_name(filename);
600
3/6
✓ Branch 0 taken 609 times.
✗ Branch 1 not taken.
✓ Branch 3 taken 609 times.
✗ Branch 4 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 609 times.
609 return proto ? (!av_strcasecmp(proto, "http") || !av_strcasecmp(proto, "https")) : 0;
601 }
602
603 9 int ff_bprint_to_codecpar_extradata(AVCodecParameters *par, struct AVBPrint *buf)
604 {
605 int ret;
606 char *str;
607
608 9 ret = av_bprint_finalize(buf, &str);
609
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
9 if (ret < 0)
610 return ret;
611
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 9 times.
9 if (!av_bprint_is_complete(buf)) {
612 av_free(str);
613 return AVERROR(ENOMEM);
614 }
615
616 9 par->extradata = str;
617 /* Note: the string is NUL terminated (so extradata can be read as a
618 * string), but the ending character is not accounted in the size (in
619 * binary formats you are likely not supposed to mux that character). When
620 * extradata is copied, it is also padded with AV_INPUT_BUFFER_PADDING_SIZE
621 * zeros. */
622 9 par->extradata_size = buf->len;
623 9 return 0;
624 }
625
626 729 int ff_dict_set_timestamp(AVDictionary **dict, const char *key, int64_t timestamp)
627 {
628 729 int microsecs = timestamp % 1000000;
629 729 time_t seconds = timestamp / 1000000 - (microsecs < 0);
630 struct tm *ptm, tmbuf;
631 729 ptm = gmtime_r(&seconds, &tmbuf);
632
1/2
✓ Branch 0 taken 729 times.
✗ Branch 1 not taken.
729 if (ptm) {
633 char buf[32];
634
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 729 times.
729 if (!strftime(buf, sizeof(buf), "%Y-%m-%dT%H:%M:%S", ptm))
635 return AVERROR_EXTERNAL;
636
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 729 times.
729 av_strlcatf(buf, sizeof(buf), ".%06dZ", microsecs + (microsecs < 0) * 1000000);
637 729 return av_dict_set(dict, key, buf, 0);
638 } else {
639 return AVERROR_EXTERNAL;
640 }
641 }
642
643 static const AVOption* find_opt(void *obj, const char *name, size_t len)
644 {
645 char decoded_name[128];
646
647 if (ff_urldecode_len(decoded_name, sizeof(decoded_name), name, len, 1) < 0)
648 return NULL;
649
650 return av_opt_find(obj, decoded_name, NULL, 0, 0);
651 }
652
653 int ff_parse_opts_from_query_string(void *obj, const char *str, int allow_unknown)
654 {
655 const AVOption *opt;
656 char optval[512];
657 int ret;
658
659 if (*str == '?')
660 str++;
661 while (*str) {
662 size_t len = strcspn(str, "=&");
663 opt = find_opt(obj, str, len);
664 if (!opt) {
665 if (!allow_unknown) {
666 av_log(obj, AV_LOG_ERROR, "Query string option '%.*s' does not exist\n", (int)len, str);
667 return AVERROR_OPTION_NOT_FOUND;
668 }
669 av_log(obj, AV_LOG_VERBOSE, "Ignoring unknown query string option '%.*s'\n", (int)len, str);
670 }
671 str += len;
672 if (!opt) {
673 len = strcspn(str, "&");
674 str += len;
675 } else if (*str == '&' || *str == '\0') {
676 /* Check for bool options without value, e.g. "?verify".
677 * Unfortunately "listen" is a tri-state INT for some protocols so
678 * we also have to allow that for backward compatibility. */
679 if (opt->type != AV_OPT_TYPE_BOOL && strcmp(opt->name, "listen")) {
680 av_log(obj, AV_LOG_ERROR, "Non-bool query string option '%s' has no value\n", opt->name);
681 return AVERROR(EINVAL);
682 }
683 ret = av_opt_set_int(obj, opt->name, 1, 0);
684 if (ret < 0)
685 return ret;
686 } else {
687 av_assert2(*str == '=');
688 str++;
689 len = strcspn(str, "&");
690 if (ff_urldecode_len(optval, sizeof(optval), str, len, 1) < 0) {
691 av_log(obj, AV_LOG_ERROR, "Query string option '%s' value is too long\n", opt->name);
692 return AVERROR(EINVAL);
693 }
694 ret = av_opt_set(obj, opt->name, optval, 0);
695 if (ret < 0)
696 return ret;
697 str += len;
698 }
699 if (*str)
700 str++;
701 }
702 return 0;
703 }
704
705 106 void *ff_bprint_finalize_as_fam(struct AVBPrint *bp, const void *struct_ptr, size_t fam_offset)
706 {
707
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 106 times.
106 if (!av_bprint_is_complete(bp)) {
708 av_bprint_finalize(bp, NULL);
709 return NULL;
710 }
711
712 106 uint8_t *p = av_malloc(fam_offset + bp->len);
713
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 106 times.
106 if (!p) {
714 av_bprint_finalize(bp, NULL);
715 return NULL;
716 }
717 106 memcpy(p, struct_ptr, fam_offset);
718 106 memcpy(p + fam_offset, bp->str, bp->len);
719 106 av_bprint_finalize(bp, NULL);
720
721 106 return p;
722 }
723