| 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 | 272431 | static int append_packet_chunked(AVIOContext *s, AVPacket *pkt, int size) | |
| 60 | { | ||
| 61 | 272431 | int orig_size = pkt->size; | |
| 62 | int ret; | ||
| 63 | |||
| 64 | do { | ||
| 65 | 272431 | 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 | 272431 | read_size = size; | |
| 71 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 272431 times.
|
272431 | if (read_size > SANE_CHUNK_SIZE/10) { |
| 72 | ✗ | read_size = ffio_limit(s, read_size); | |
| 73 | // If filesize/maxsize is unknown, limit to SANE_CHUNK_SIZE | ||
| 74 | ✗ | if (ffiocontext(s)->maxsize < 0) | |
| 75 | ✗ | read_size = FFMIN(read_size, SANE_CHUNK_SIZE); | |
| 76 | } | ||
| 77 | |||
| 78 | 272431 | ret = av_grow_packet(pkt, read_size); | |
| 79 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 272431 times.
|
272431 | if (ret < 0) |
| 80 | ✗ | break; | |
| 81 | |||
| 82 | 272431 | ret = avio_read(s, pkt->data + prev_size, read_size); | |
| 83 |
2/2✓ Branch 0 taken 928 times.
✓ Branch 1 taken 271503 times.
|
272431 | if (ret != read_size) { |
| 84 | 928 | av_shrink_packet(pkt, prev_size + FFMAX(ret, 0)); | |
| 85 | 928 | break; | |
| 86 | } | ||
| 87 | |||
| 88 | 271503 | size -= read_size; | |
| 89 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 271503 times.
|
271503 | } while (size > 0); |
| 90 |
2/2✓ Branch 0 taken 883 times.
✓ Branch 1 taken 271548 times.
|
272431 | if (size > 0) |
| 91 | 883 | pkt->flags |= AV_PKT_FLAG_CORRUPT; | |
| 92 | |||
| 93 |
2/2✓ Branch 0 taken 2255 times.
✓ Branch 1 taken 270176 times.
|
272431 | if (!pkt->size) |
| 94 | 2255 | av_packet_unref(pkt); | |
| 95 |
2/2✓ Branch 0 taken 270171 times.
✓ Branch 1 taken 2260 times.
|
272431 | return pkt->size > orig_size ? pkt->size - orig_size : ret; |
| 96 | } | ||
| 97 | |||
| 98 | 263001 | int av_get_packet(AVIOContext *s, AVPacket *pkt, int size) | |
| 99 | { | ||
| 100 | #if FF_API_INIT_PACKET | ||
| 101 | FF_DISABLE_DEPRECATION_WARNINGS | ||
| 102 | 263001 | av_init_packet(pkt); | |
| 103 | 263001 | pkt->data = NULL; | |
| 104 | 263001 | pkt->size = 0; | |
| 105 | FF_ENABLE_DEPRECATION_WARNINGS | ||
| 106 | #else | ||
| 107 | av_packet_unref(pkt); | ||
| 108 | #endif | ||
| 109 | 263001 | pkt->pos = avio_tell(s); | |
| 110 | |||
| 111 | 263001 | return append_packet_chunked(s, pkt, size); | |
| 112 | } | ||
| 113 | |||
| 114 | 10020 | int av_append_packet(AVIOContext *s, AVPacket *pkt, int size) | |
| 115 | { | ||
| 116 |
2/2✓ Branch 0 taken 590 times.
✓ Branch 1 taken 9430 times.
|
10020 | if (!pkt->size) |
| 117 | 590 | return av_get_packet(s, pkt, size); | |
| 118 | 9430 | return append_packet_chunked(s, pkt, size); | |
| 119 | } | ||
| 120 | |||
| 121 | 1001 | int av_filename_number_test(const char *filename) | |
| 122 | { | ||
| 123 | AVBPrint bp; | ||
| 124 | |||
| 125 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1001 times.
|
1001 | if (!filename) |
| 126 | ✗ | return 0; | |
| 127 | 1001 | av_bprint_init(&bp, 0, AV_BPRINT_SIZE_COUNT_ONLY); | |
| 128 | 1001 | return (ff_bprint_get_frame_filename(&bp, filename, 1, AV_FRAME_FILENAME_FLAGS_IGNORE_TRUNCATION) >= 0); | |
| 129 | } | ||
| 130 | |||
| 131 | /**********************************************************/ | ||
| 132 | |||
| 133 | 1326 | unsigned int ff_codec_get_tag(const AVCodecTag *tags, enum AVCodecID id) | |
| 134 | { | ||
| 135 |
2/2✓ Branch 0 taken 9923 times.
✓ Branch 1 taken 2 times.
|
9925 | while (tags->id != AV_CODEC_ID_NONE) { |
| 136 |
2/2✓ Branch 0 taken 1324 times.
✓ Branch 1 taken 8599 times.
|
9923 | if (tags->id == id) |
| 137 | 1324 | return tags->tag; | |
| 138 | 8599 | tags++; | |
| 139 | } | ||
| 140 | 2 | return 0; | |
| 141 | } | ||
| 142 | |||
| 143 | 3089 | enum AVCodecID ff_codec_get_id(const AVCodecTag *tags, unsigned int tag) | |
| 144 | { | ||
| 145 |
2/2✓ Branch 0 taken 269605 times.
✓ Branch 1 taken 922 times.
|
270527 | for (int i = 0; tags[i].id != AV_CODEC_ID_NONE; i++) |
| 146 |
2/2✓ Branch 0 taken 2167 times.
✓ Branch 1 taken 267438 times.
|
269605 | if (tag == tags[i].tag) |
| 147 | 2167 | return tags[i].id; | |
| 148 |
2/2✓ Branch 0 taken 83452 times.
✓ Branch 1 taken 917 times.
|
84369 | for (int i = 0; tags[i].id != AV_CODEC_ID_NONE; i++) |
| 149 |
2/2✓ Branch 2 taken 5 times.
✓ Branch 3 taken 83447 times.
|
83452 | if (ff_toupper4(tag) == ff_toupper4(tags[i].tag)) |
| 150 | 5 | return tags[i].id; | |
| 151 | 917 | return AV_CODEC_ID_NONE; | |
| 152 | } | ||
| 153 | |||
| 154 | 556 | enum AVCodecID ff_get_pcm_codec_id(int bps, int flt, int be, int sflags) | |
| 155 | { | ||
| 156 |
2/4✓ Branch 0 taken 556 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 556 times.
|
556 | if (bps <= 0 || bps > 64) |
| 157 | ✗ | return AV_CODEC_ID_NONE; | |
| 158 | |||
| 159 |
2/2✓ Branch 0 taken 4 times.
✓ Branch 1 taken 552 times.
|
556 | 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 | 552 | bps += 7; | |
| 170 | 552 | bps >>= 3; | |
| 171 |
2/2✓ Branch 0 taken 534 times.
✓ Branch 1 taken 18 times.
|
552 | if (sflags & (1 << (bps - 1))) { |
| 172 |
3/6✗ Branch 0 not taken.
✓ Branch 1 taken 519 times.
✓ Branch 2 taken 12 times.
✓ Branch 3 taken 3 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
|
534 | switch (bps) { |
| 173 | ✗ | case 1: | |
| 174 | ✗ | return AV_CODEC_ID_PCM_S8; | |
| 175 | 519 | case 2: | |
| 176 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 517 times.
|
519 | return be ? AV_CODEC_ID_PCM_S16BE : AV_CODEC_ID_PCM_S16LE; |
| 177 | 12 | case 3: | |
| 178 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 11 times.
|
12 | 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 18 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
|
18 | switch (bps) { |
| 188 | 18 | case 1: | |
| 189 | 18 | 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 | 6181 | unsigned int av_codec_get_tag(const AVCodecTag *const *tags, enum AVCodecID id) | |
| 204 | { | ||
| 205 | unsigned int tag; | ||
| 206 |
2/2✓ Branch 1 taken 13 times.
✓ Branch 2 taken 6168 times.
|
6181 | if (!av_codec_get_tag2(tags, id, &tag)) |
| 207 | 13 | return 0; | |
| 208 | 6168 | return tag; | |
| 209 | } | ||
| 210 | |||
| 211 | 9582 | int av_codec_get_tag2(const AVCodecTag * const *tags, enum AVCodecID id, | |
| 212 | unsigned int *tag) | ||
| 213 | { | ||
| 214 |
3/4✓ Branch 0 taken 18160 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 18129 times.
✓ Branch 3 taken 31 times.
|
18160 | for (int i = 0; tags && tags[i]; i++) { |
| 215 | 18129 | const AVCodecTag *codec_tags = tags[i]; | |
| 216 |
2/2✓ Branch 0 taken 785945 times.
✓ Branch 1 taken 8578 times.
|
794523 | while (codec_tags->id != AV_CODEC_ID_NONE) { |
| 217 |
2/2✓ Branch 0 taken 9551 times.
✓ Branch 1 taken 776394 times.
|
785945 | if (codec_tags->id == id) { |
| 218 | 9551 | *tag = codec_tags->tag; | |
| 219 | 9551 | return 1; | |
| 220 | } | ||
| 221 | 776394 | codec_tags++; | |
| 222 | } | ||
| 223 | } | ||
| 224 | 31 | return 0; | |
| 225 | } | ||
| 226 | |||
| 227 | 193 | enum AVCodecID av_codec_get_id(const AVCodecTag *const *tags, unsigned int tag) | |
| 228 | { | ||
| 229 |
3/4✓ Branch 0 taken 357 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 294 times.
✓ Branch 3 taken 63 times.
|
357 | for (int i = 0; tags && tags[i]; i++) { |
| 230 | 294 | enum AVCodecID id = ff_codec_get_id(tags[i], tag); | |
| 231 |
2/2✓ Branch 0 taken 130 times.
✓ Branch 1 taken 164 times.
|
294 | if (id != AV_CODEC_ID_NONE) |
| 232 | 130 | return id; | |
| 233 | } | ||
| 234 | 63 | return AV_CODEC_ID_NONE; | |
| 235 | } | ||
| 236 | |||
| 237 | 949 | int ff_alloc_extradata(AVCodecParameters *par, int size) | |
| 238 | { | ||
| 239 | 949 | av_freep(&par->extradata); | |
| 240 | 949 | par->extradata_size = 0; | |
| 241 | |||
| 242 |
2/4✓ Branch 0 taken 949 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 949 times.
|
949 | if (size < 0 || size >= INT32_MAX - AV_INPUT_BUFFER_PADDING_SIZE) |
| 243 | ✗ | return AVERROR(EINVAL); | |
| 244 | |||
| 245 | 949 | par->extradata = av_malloc(size + AV_INPUT_BUFFER_PADDING_SIZE); | |
| 246 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 949 times.
|
949 | if (!par->extradata) |
| 247 | ✗ | return AVERROR(ENOMEM); | |
| 248 | |||
| 249 | 949 | memset(par->extradata + size, 0, AV_INPUT_BUFFER_PADDING_SIZE); | |
| 250 | 949 | par->extradata_size = size; | |
| 251 | |||
| 252 | 949 | 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 micro seconds | ||
| 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 | 156117 | 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 | 156117 | p = path; | |
| 300 | 156117 | percentd_found = 0; | |
| 301 | for (;;) { | ||
| 302 | 11898955 | c = *p++; | |
| 303 |
2/2✓ Branch 0 taken 156117 times.
✓ Branch 1 taken 11742838 times.
|
11898955 | if (c == '\0') |
| 304 | 156117 | break; | |
| 305 |
2/2✓ Branch 0 taken 155402 times.
✓ Branch 1 taken 11587436 times.
|
11742838 | if (c == '%') { |
| 306 | do { | ||
| 307 | 155402 | nd = 0; | |
| 308 |
2/2✓ Branch 0 taken 310692 times.
✓ Branch 1 taken 155402 times.
|
466094 | while (av_isdigit(*p)) { |
| 309 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 310692 times.
|
310692 | if (nd >= INT_MAX / 10 - 255) |
| 310 | ✗ | goto fail; | |
| 311 | 310692 | nd = nd * 10 + *p++ - '0'; | |
| 312 | } | ||
| 313 | 155402 | c = *p++; | |
| 314 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 155402 times.
|
155402 | } while (av_isdigit(c)); |
| 315 | |||
| 316 |
1/3✗ Branch 0 not taken.
✓ Branch 1 taken 155402 times.
✗ Branch 2 not taken.
|
155402 | switch (c) { |
| 317 | ✗ | case '%': | |
| 318 | ✗ | goto addchar; | |
| 319 | 155402 | case 'd': | |
| 320 |
3/4✓ Branch 0 taken 154739 times.
✓ Branch 1 taken 663 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 154739 times.
|
155402 | if (!(flags & AV_FRAME_FILENAME_FLAGS_MULTIPLE) && percentd_found) |
| 321 | ✗ | goto fail; | |
| 322 | 155402 | percentd_found = 1; | |
| 323 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 155402 times.
|
155402 | if (number < 0) |
| 324 | ✗ | nd += 1; | |
| 325 | 155402 | av_bprintf(buf, "%0*" PRId64, nd, number); | |
| 326 | 155402 | break; | |
| 327 | ✗ | default: | |
| 328 | ✗ | goto fail; | |
| 329 | } | ||
| 330 | } else { | ||
| 331 | 11587436 | addchar: | |
| 332 | 11587436 | av_bprint_chars(buf, c, 1); | |
| 333 | } | ||
| 334 | } | ||
| 335 |
2/2✓ Branch 0 taken 715 times.
✓ Branch 1 taken 155402 times.
|
156117 | if (!percentd_found) |
| 336 | 715 | goto fail; | |
| 337 |
3/4✓ Branch 0 taken 155102 times.
✓ Branch 1 taken 300 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 155102 times.
|
155402 | if (!(flags & AV_FRAME_FILENAME_FLAGS_IGNORE_TRUNCATION) && !av_bprint_is_complete(buf)) |
| 338 | ✗ | return AVERROR(ENOMEM); | |
| 339 | 155402 | return 0; | |
| 340 | 715 | fail: | |
| 341 | 715 | 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 | ✗ | int ff_mkdir_p(const char *path) | |
| 425 | { | ||
| 426 | ✗ | int ret = 0; | |
| 427 | ✗ | char *temp = av_strdup(path); | |
| 428 | ✗ | char *pos = temp; | |
| 429 | ✗ | char tmp_ch = '\0'; | |
| 430 | |||
| 431 | ✗ | if (!path || !temp) { | |
| 432 | ✗ | return -1; | |
| 433 | } | ||
| 434 | |||
| 435 | ✗ | if (!av_strncasecmp(temp, "/", 1) || !av_strncasecmp(temp, "\\", 1)) { | |
| 436 | ✗ | pos++; | |
| 437 | ✗ | } else if (!av_strncasecmp(temp, "./", 2) || !av_strncasecmp(temp, ".\\", 2)) { | |
| 438 | ✗ | pos += 2; | |
| 439 | } | ||
| 440 | |||
| 441 | ✗ | for ( ; *pos != '\0'; ++pos) { | |
| 442 | ✗ | if (*pos == '/' || *pos == '\\') { | |
| 443 | ✗ | tmp_ch = *pos; | |
| 444 | ✗ | *pos = '\0'; | |
| 445 | ✗ | ret = mkdir(temp, 0755); | |
| 446 | ✗ | *pos = tmp_ch; | |
| 447 | } | ||
| 448 | } | ||
| 449 | |||
| 450 | ✗ | if ((*(pos - 1) != '/') && (*(pos - 1) != '\\')) { | |
| 451 | ✗ | ret = mkdir(temp, 0755); | |
| 452 | } | ||
| 453 | |||
| 454 | ✗ | av_free(temp); | |
| 455 | ✗ | return ret; | |
| 456 | } | ||
| 457 | |||
| 458 | 3498 | char *ff_data_to_hex(char *buff, const uint8_t *src, int s, int lowercase) | |
| 459 | { | ||
| 460 | static const char hex_table_uc[16] = { '0', '1', '2', '3', | ||
| 461 | '4', '5', '6', '7', | ||
| 462 | '8', '9', 'A', 'B', | ||
| 463 | 'C', 'D', 'E', 'F' }; | ||
| 464 | static const char hex_table_lc[16] = { '0', '1', '2', '3', | ||
| 465 | '4', '5', '6', '7', | ||
| 466 | '8', '9', 'a', 'b', | ||
| 467 | 'c', 'd', 'e', 'f' }; | ||
| 468 |
2/2✓ Branch 0 taken 2801 times.
✓ Branch 1 taken 697 times.
|
3498 | const char *hex_table = lowercase ? hex_table_lc : hex_table_uc; |
| 469 | |||
| 470 |
2/2✓ Branch 0 taken 55982 times.
✓ Branch 1 taken 3498 times.
|
59480 | for (int i = 0; i < s; i++) { |
| 471 | 55982 | buff[i * 2] = hex_table[src[i] >> 4]; | |
| 472 | 55982 | buff[i * 2 + 1] = hex_table[src[i] & 0xF]; | |
| 473 | } | ||
| 474 | 3498 | buff[2 * s] = '\0'; | |
| 475 | |||
| 476 | 3498 | return buff; | |
| 477 | } | ||
| 478 | |||
| 479 | ✗ | int ff_hex_to_data(uint8_t *data, const char *p) | |
| 480 | { | ||
| 481 | int c, len, v; | ||
| 482 | |||
| 483 | ✗ | len = 0; | |
| 484 | ✗ | v = 1; | |
| 485 | for (;;) { | ||
| 486 | ✗ | p += strspn(p, SPACE_CHARS); | |
| 487 | ✗ | if (*p == '\0') | |
| 488 | ✗ | break; | |
| 489 | ✗ | c = av_toupper((unsigned char) *p++); | |
| 490 | ✗ | if (c >= '0' && c <= '9') | |
| 491 | ✗ | c = c - '0'; | |
| 492 | ✗ | else if (c >= 'A' && c <= 'F') | |
| 493 | ✗ | c = c - 'A' + 10; | |
| 494 | else | ||
| 495 | break; | ||
| 496 | ✗ | v = (v << 4) | c; | |
| 497 | ✗ | if (v & 0x100) { | |
| 498 | ✗ | if (data) | |
| 499 | ✗ | data[len] = v; | |
| 500 | ✗ | len++; | |
| 501 | ✗ | v = 1; | |
| 502 | } | ||
| 503 | } | ||
| 504 | ✗ | return len; | |
| 505 | } | ||
| 506 | |||
| 507 | 1 | void ff_parse_key_value(const char *str, ff_parse_key_val_cb callback_get_buf, | |
| 508 | void *context) | ||
| 509 | { | ||
| 510 | 1 | const char *ptr = str; | |
| 511 | |||
| 512 | /* Parse key=value pairs. */ | ||
| 513 | 1 | for (;;) { | |
| 514 | const char *key; | ||
| 515 | 2 | char *dest = NULL, *dest_end; | |
| 516 | 2 | int key_len, dest_len = 0; | |
| 517 | |||
| 518 | /* Skip whitespace and potential commas. */ | ||
| 519 |
4/6✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 1 times.
|
2 | while (*ptr && (av_isspace(*ptr) || *ptr == ',')) |
| 520 | ✗ | ptr++; | |
| 521 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
|
2 | if (!*ptr) |
| 522 | 1 | break; | |
| 523 | |||
| 524 | 1 | key = ptr; | |
| 525 | |||
| 526 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
|
1 | if (!(ptr = strchr(key, '='))) |
| 527 | ✗ | break; | |
| 528 | 1 | ptr++; | |
| 529 | 1 | key_len = ptr - key; | |
| 530 | |||
| 531 | 1 | callback_get_buf(context, key, key_len, &dest, &dest_len); | |
| 532 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
1 | dest_end = dest ? dest + dest_len - 1 : NULL; |
| 533 | |||
| 534 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
1 | if (*ptr == '\"') { |
| 535 | 1 | ptr++; | |
| 536 |
3/4✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 8 times.
✓ Branch 3 taken 1 times.
|
9 | while (*ptr && *ptr != '\"') { |
| 537 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
|
8 | if (*ptr == '\\') { |
| 538 | ✗ | if (!ptr[1]) | |
| 539 | ✗ | break; | |
| 540 | ✗ | if (dest && dest < dest_end) | |
| 541 | ✗ | *dest++ = ptr[1]; | |
| 542 | ✗ | ptr += 2; | |
| 543 | } else { | ||
| 544 |
2/4✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 8 times.
✗ Branch 3 not taken.
|
8 | if (dest && dest < dest_end) |
| 545 | 8 | *dest++ = *ptr; | |
| 546 | 8 | ptr++; | |
| 547 | } | ||
| 548 | } | ||
| 549 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
1 | if (*ptr == '\"') |
| 550 | 1 | ptr++; | |
| 551 | } else { | ||
| 552 | ✗ | for (; *ptr && !(av_isspace(*ptr) || *ptr == ','); ptr++) | |
| 553 | ✗ | if (dest && dest < dest_end) | |
| 554 | ✗ | *dest++ = *ptr; | |
| 555 | } | ||
| 556 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
1 | if (dest) |
| 557 | 1 | *dest = 0; | |
| 558 | } | ||
| 559 | 1 | } | |
| 560 | |||
| 561 | 8570 | int avformat_network_init(void) | |
| 562 | { | ||
| 563 | #if CONFIG_NETWORK | ||
| 564 | int ret; | ||
| 565 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 8570 times.
|
8570 | if ((ret = ff_network_init()) < 0) |
| 566 | ✗ | return ret; | |
| 567 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 8570 times.
|
8570 | if ((ret = ff_tls_init()) < 0) |
| 568 | ✗ | return ret; | |
| 569 | #endif | ||
| 570 | 8570 | return 0; | |
| 571 | } | ||
| 572 | |||
| 573 | 8570 | int avformat_network_deinit(void) | |
| 574 | { | ||
| 575 | #if CONFIG_NETWORK | ||
| 576 | 8570 | ff_network_close(); | |
| 577 | 8570 | ff_tls_deinit(); | |
| 578 | #endif | ||
| 579 | 8570 | return 0; | |
| 580 | } | ||
| 581 | |||
| 582 | 376 | int ff_is_http_proto(const char *filename) { | |
| 583 | 376 | const char *proto = avio_find_protocol_name(filename); | |
| 584 |
3/6✓ Branch 0 taken 376 times.
✗ Branch 1 not taken.
✓ Branch 3 taken 376 times.
✗ Branch 4 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 376 times.
|
376 | return proto ? (!av_strcasecmp(proto, "http") || !av_strcasecmp(proto, "https")) : 0; |
| 585 | } | ||
| 586 | |||
| 587 | 9 | int ff_bprint_to_codecpar_extradata(AVCodecParameters *par, struct AVBPrint *buf) | |
| 588 | { | ||
| 589 | int ret; | ||
| 590 | char *str; | ||
| 591 | |||
| 592 | 9 | ret = av_bprint_finalize(buf, &str); | |
| 593 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
|
9 | if (ret < 0) |
| 594 | ✗ | return ret; | |
| 595 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 9 times.
|
9 | if (!av_bprint_is_complete(buf)) { |
| 596 | ✗ | av_free(str); | |
| 597 | ✗ | return AVERROR(ENOMEM); | |
| 598 | } | ||
| 599 | |||
| 600 | 9 | par->extradata = str; | |
| 601 | /* Note: the string is NUL terminated (so extradata can be read as a | ||
| 602 | * string), but the ending character is not accounted in the size (in | ||
| 603 | * binary formats you are likely not supposed to mux that character). When | ||
| 604 | * extradata is copied, it is also padded with AV_INPUT_BUFFER_PADDING_SIZE | ||
| 605 | * zeros. */ | ||
| 606 | 9 | par->extradata_size = buf->len; | |
| 607 | 9 | return 0; | |
| 608 | } | ||
| 609 | |||
| 610 | 572 | int ff_dict_set_timestamp(AVDictionary **dict, const char *key, int64_t timestamp) | |
| 611 | { | ||
| 612 | 572 | time_t seconds = timestamp / 1000000; | |
| 613 | struct tm *ptm, tmbuf; | ||
| 614 | 572 | ptm = gmtime_r(&seconds, &tmbuf); | |
| 615 |
1/2✓ Branch 0 taken 572 times.
✗ Branch 1 not taken.
|
572 | if (ptm) { |
| 616 | char buf[32]; | ||
| 617 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 572 times.
|
572 | if (!strftime(buf, sizeof(buf), "%Y-%m-%dT%H:%M:%S", ptm)) |
| 618 | ✗ | return AVERROR_EXTERNAL; | |
| 619 | 572 | av_strlcatf(buf, sizeof(buf), ".%06dZ", (int)(timestamp % 1000000)); | |
| 620 | 572 | return av_dict_set(dict, key, buf, 0); | |
| 621 | } else { | ||
| 622 | ✗ | return AVERROR_EXTERNAL; | |
| 623 | } | ||
| 624 | } | ||
| 625 | |||
| 626 | ✗ | static const AVOption* find_opt(void *obj, const char *name, size_t len) | |
| 627 | { | ||
| 628 | char decoded_name[128]; | ||
| 629 | |||
| 630 | ✗ | if (ff_urldecode_len(decoded_name, sizeof(decoded_name), name, len, 1) < 0) | |
| 631 | ✗ | return NULL; | |
| 632 | |||
| 633 | ✗ | return av_opt_find(obj, decoded_name, NULL, 0, 0); | |
| 634 | } | ||
| 635 | |||
| 636 | ✗ | int ff_parse_opts_from_query_string(void *obj, const char *str, int allow_unknown) | |
| 637 | { | ||
| 638 | const AVOption *opt; | ||
| 639 | char optval[512]; | ||
| 640 | int ret; | ||
| 641 | |||
| 642 | ✗ | if (*str == '?') | |
| 643 | ✗ | str++; | |
| 644 | ✗ | while (*str) { | |
| 645 | ✗ | size_t len = strcspn(str, "=&"); | |
| 646 | ✗ | opt = find_opt(obj, str, len); | |
| 647 | ✗ | if (!opt) { | |
| 648 | ✗ | if (!allow_unknown) { | |
| 649 | ✗ | av_log(obj, AV_LOG_ERROR, "Query string option '%.*s' does not exist\n", (int)len, str); | |
| 650 | ✗ | return AVERROR_OPTION_NOT_FOUND; | |
| 651 | } | ||
| 652 | ✗ | av_log(obj, AV_LOG_VERBOSE, "Ignoring unknown query string option '%.*s'\n", (int)len, str); | |
| 653 | } | ||
| 654 | ✗ | str += len; | |
| 655 | ✗ | if (!opt) { | |
| 656 | ✗ | len = strcspn(str, "&"); | |
| 657 | ✗ | str += len; | |
| 658 | ✗ | } else if (*str == '&' || *str == '\0') { | |
| 659 | /* Check for bool options without value, e.g. "?verify". | ||
| 660 | * Unfortunately "listen" is a tri-state INT for some protocols so | ||
| 661 | * we also have to allow that for backward compatibility. */ | ||
| 662 | ✗ | if (opt->type != AV_OPT_TYPE_BOOL && strcmp(opt->name, "listen")) { | |
| 663 | ✗ | av_log(obj, AV_LOG_ERROR, "Non-bool query string option '%s' has no value\n", opt->name); | |
| 664 | ✗ | return AVERROR(EINVAL); | |
| 665 | } | ||
| 666 | ✗ | ret = av_opt_set_int(obj, opt->name, 1, 0); | |
| 667 | ✗ | if (ret < 0) | |
| 668 | ✗ | return ret; | |
| 669 | } else { | ||
| 670 | av_assert2(*str == '='); | ||
| 671 | ✗ | str++; | |
| 672 | ✗ | len = strcspn(str, "&"); | |
| 673 | ✗ | if (ff_urldecode_len(optval, sizeof(optval), str, len, 1) < 0) { | |
| 674 | ✗ | av_log(obj, AV_LOG_ERROR, "Query string option '%s' value is too long\n", opt->name); | |
| 675 | ✗ | return AVERROR(EINVAL); | |
| 676 | } | ||
| 677 | ✗ | ret = av_opt_set(obj, opt->name, optval, 0); | |
| 678 | ✗ | if (ret < 0) | |
| 679 | ✗ | return ret; | |
| 680 | ✗ | str += len; | |
| 681 | } | ||
| 682 | ✗ | if (*str) | |
| 683 | ✗ | str++; | |
| 684 | } | ||
| 685 | ✗ | return 0; | |
| 686 | } | ||
| 687 |