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 24#include "config.h" 25 26#include "libavutil/avstring.h" 27#include "libavutil/bprint.h" 28#include "libavutil/internal.h" 29#include "libavutil/thread.h" 30#include "libavutil/time.h" 31 32#include "libavcodec/internal.h" 33 34#include "avformat.h" 35#include "avio_internal.h" 36#include "internal.h" 37#if CONFIG_NETWORK 38#include "network.h" 39#endif 40 41static AVMutex avformat_mutex = AV_MUTEX_INITIALIZER; 42 43/** 44 * @file 45 * various utility functions for use within FFmpeg 46 */ 47 48int ff_lock_avformat(void) 49{ 50 return ff_mutex_lock(&avformat_mutex) ? -1 : 0; 51} 52 53int ff_unlock_avformat(void) 54{ 55 return ff_mutex_unlock(&avformat_mutex) ? -1 : 0; 56} 57 58/* an arbitrarily chosen "sane" max packet size -- 50M */ 59#define SANE_CHUNK_SIZE (50000000) 60 61/* Read the data in sane-sized chunks and append to pkt. 62 * Return the number of bytes read or an error. */ 63static int append_packet_chunked(AVIOContext *s, AVPacket *pkt, int size) 64{ 65 int orig_size = pkt->size; 66 int ret; 67 68 do { 69 int prev_size = pkt->size; 70 int read_size; 71 72 /* When the caller requests a lot of data, limit it to the amount 73 * left in file or SANE_CHUNK_SIZE when it is not known. */ 74 read_size = size; 75 if (read_size > SANE_CHUNK_SIZE/10) { 76 read_size = ffio_limit(s, read_size); 77 // If filesize/maxsize is unknown, limit to SANE_CHUNK_SIZE 78 if (ffiocontext(s)->maxsize < 0) 79 read_size = FFMIN(read_size, SANE_CHUNK_SIZE); 80 } 81 82 ret = av_grow_packet(pkt, read_size); 83 if (ret < 0) 84 break; 85 86 ret = avio_read(s, pkt->data + prev_size, read_size); 87 if (ret != read_size) { 88 av_shrink_packet(pkt, prev_size + FFMAX(ret, 0)); 89 break; 90 } 91 92 size -= read_size; 93 } while (size > 0); 94 if (size > 0) 95 pkt->flags |= AV_PKT_FLAG_CORRUPT; 96 97 if (!pkt->size) 98 av_packet_unref(pkt); 99 return pkt->size > orig_size ? pkt->size - orig_size : ret; 100} 101 102int av_get_packet(AVIOContext *s, AVPacket *pkt, int size) 103{ 104#if FF_API_INIT_PACKET 105FF_DISABLE_DEPRECATION_WARNINGS 106 av_init_packet(pkt); 107 pkt->data = NULL; 108 pkt->size = 0; 109FF_ENABLE_DEPRECATION_WARNINGS 110#else 111 av_packet_unref(pkt); 112#endif 113 pkt->pos = avio_tell(s); 114 115 return append_packet_chunked(s, pkt, size); 116} 117 118int av_append_packet(AVIOContext *s, AVPacket *pkt, int size) 119{ 120 if (!pkt->size) 121 return av_get_packet(s, pkt, size); 122 return append_packet_chunked(s, pkt, size); 123} 124 125int av_filename_number_test(const char *filename) 126{ 127 char buf[1024]; 128 return filename && 129 (av_get_frame_filename(buf, sizeof(buf), filename, 1) >= 0); 130} 131 132/**********************************************************/ 133 134unsigned int ff_codec_get_tag(const AVCodecTag *tags, enum AVCodecID id) 135{ 136 while (tags->id != AV_CODEC_ID_NONE) { 137 if (tags->id == id) 138 return tags->tag; 139 tags++; 140 } 141 return 0; 142} 143 144enum AVCodecID ff_codec_get_id(const AVCodecTag *tags, unsigned int tag) 145{ 146 for (int i = 0; tags[i].id != AV_CODEC_ID_NONE; i++) 147 if (tag == tags[i].tag) 148 return tags[i].id; 149 for (int i = 0; tags[i].id != AV_CODEC_ID_NONE; i++) 150 if (ff_toupper4(tag) == ff_toupper4(tags[i].tag)) 151 return tags[i].id; 152 return AV_CODEC_ID_NONE; 153} 154 155enum AVCodecID ff_get_pcm_codec_id(int bps, int flt, int be, int sflags) 156{ 157 if (bps <= 0 || bps > 64) 158 return AV_CODEC_ID_NONE; 159 160 if (flt) { 161 switch (bps) { 162 case 32: 163 return be ? AV_CODEC_ID_PCM_F32BE : AV_CODEC_ID_PCM_F32LE; 164 case 64: 165 return be ? AV_CODEC_ID_PCM_F64BE : AV_CODEC_ID_PCM_F64LE; 166 default: 167 return AV_CODEC_ID_NONE; 168 } 169 } else { 170 bps += 7; 171 bps >>= 3; 172 if (sflags & (1 << (bps - 1))) { 173 switch (bps) { 174 case 1: 175 return AV_CODEC_ID_PCM_S8; 176 case 2: 177 return be ? AV_CODEC_ID_PCM_S16BE : AV_CODEC_ID_PCM_S16LE; 178 case 3: 179 return be ? AV_CODEC_ID_PCM_S24BE : AV_CODEC_ID_PCM_S24LE; 180 case 4: 181 return be ? AV_CODEC_ID_PCM_S32BE : AV_CODEC_ID_PCM_S32LE; 182 case 8: 183 return be ? AV_CODEC_ID_PCM_S64BE : AV_CODEC_ID_PCM_S64LE; 184 default: 185 return AV_CODEC_ID_NONE; 186 } 187 } else { 188 switch (bps) { 189 case 1: 190 return AV_CODEC_ID_PCM_U8; 191 case 2: 192 return be ? AV_CODEC_ID_PCM_U16BE : AV_CODEC_ID_PCM_U16LE; 193 case 3: 194 return be ? AV_CODEC_ID_PCM_U24BE : AV_CODEC_ID_PCM_U24LE; 195 case 4: 196 return be ? AV_CODEC_ID_PCM_U32BE : AV_CODEC_ID_PCM_U32LE; 197 default: 198 return AV_CODEC_ID_NONE; 199 } 200 } 201 } 202} 203 204unsigned int av_codec_get_tag(const AVCodecTag *const *tags, enum AVCodecID id) 205{ 206 unsigned int tag; 207 if (!av_codec_get_tag2(tags, id, &tag)) 208 return 0; 209 return tag; 210} 211 212int av_codec_get_tag2(const AVCodecTag * const *tags, enum AVCodecID id, 213 unsigned int *tag) 214{ 215 for (int i = 0; tags && tags[i]; i++) { 216 const AVCodecTag *codec_tags = tags[i]; 217 while (codec_tags->id != AV_CODEC_ID_NONE) { 218 if (codec_tags->id == id) { 219 *tag = codec_tags->tag; 220 return 1; 221 } 222 codec_tags++; 223 } 224 } 225 return 0; 226} 227 228enum AVCodecID av_codec_get_id(const AVCodecTag *const *tags, unsigned int tag) 229{ 230 for (int i = 0; tags && tags[i]; i++) { 231 enum AVCodecID id = ff_codec_get_id(tags[i], tag); 232 if (id != AV_CODEC_ID_NONE) 233 return id; 234 } 235 return AV_CODEC_ID_NONE; 236} 237 238int ff_alloc_extradata(AVCodecParameters *par, int size) 239{ 240 av_freep(&par->extradata); 241 par->extradata_size = 0; 242 243 if (size < 0 || size >= INT32_MAX - AV_INPUT_BUFFER_PADDING_SIZE) 244 return AVERROR(EINVAL); 245 246 par->extradata = av_malloc(size + AV_INPUT_BUFFER_PADDING_SIZE); 247 if (!par->extradata) 248 return AVERROR(ENOMEM); 249 250 memset(par->extradata + size, 0, AV_INPUT_BUFFER_PADDING_SIZE); 251 par->extradata_size = size; 252 253 return 0; 254} 255 256/*******************************************************/ 257 258uint64_t ff_ntp_time(void) 259{ 260 return (av_gettime() / 1000) * 1000 + NTP_OFFSET_US; 261} 262 263uint64_t ff_get_formatted_ntp_time(uint64_t ntp_time_us) 264{ 265 uint64_t ntp_ts, frac_part, sec; 266 uint32_t usec; 267 268 //current ntp time in seconds and micro seconds 269 sec = ntp_time_us / 1000000; 270 usec = ntp_time_us % 1000000; 271 272 //encoding in ntp timestamp format 273 frac_part = usec * 0xFFFFFFFFULL; 274 frac_part /= 1000000; 275 276 if (sec > 0xFFFFFFFFULL) 277 av_log(NULL, AV_LOG_WARNING, "NTP time format roll over detected\n"); 278 279 ntp_ts = sec << 32; 280 ntp_ts |= frac_part; 281 282 return ntp_ts; 283} 284 285uint64_t ff_parse_ntp_time(uint64_t ntp_ts) 286{ 287 uint64_t sec = ntp_ts >> 32; 288 uint64_t frac_part = ntp_ts & 0xFFFFFFFFULL; 289 uint64_t usec = (frac_part * 1000000) / 0xFFFFFFFFULL; 290 291 return (sec * 1000000) + usec; 292} 293 294int av_get_frame_filename2(char *buf, int buf_size, const char *path, int number, int flags) 295{ 296 const char *p; 297 char *q, buf1[20], c; 298 int nd, len, percentd_found; 299 300 q = buf; 301 p = path; 302 percentd_found = 0; 303 for (;;) { 304 c = *p++; 305 if (c == '\0') 306 break; 307 if (c == '%') { 308 do { 309 nd = 0; 310 while (av_isdigit(*p)) { 311 if (nd >= INT_MAX / 10 - 255) 312 goto fail; 313 nd = nd * 10 + *p++ - '0'; 314 } 315 c = *p++; 316 } while (av_isdigit(c)); 317 318 switch (c) { 319 case '%': 320 goto addchar; 321 case 'd': 322 if (!(flags & AV_FRAME_FILENAME_FLAGS_MULTIPLE) && percentd_found) 323 goto fail; 324 percentd_found = 1; 325 if (number < 0) 326 nd += 1; 327 snprintf(buf1, sizeof(buf1), "%0*d", nd, number); 328 len = strlen(buf1); 329 if ((q - buf + len) > buf_size - 1) 330 goto fail; 331 memcpy(q, buf1, len); 332 q += len; 333 break; 334 default: 335 goto fail; 336 } 337 } else { 338addchar: 339 if ((q - buf) < buf_size - 1) 340 *q++ = c; 341 } 342 } 343 if (!percentd_found) 344 goto fail; 345 *q = '\0'; 346 return 0; 347fail: 348 *q = '\0'; 349 return -1; 350} 351 352int av_get_frame_filename(char *buf, int buf_size, const char *path, int number) 353{ 354 return av_get_frame_filename2(buf, buf_size, path, number, 0); 355} 356 357void av_url_split(char *proto, int proto_size, 358 char *authorization, int authorization_size, 359 char *hostname, int hostname_size, 360 int *port_ptr, char *path, int path_size, const char *url) 361{ 362 const char *p, *ls, *at, *at2, *col, *brk; 363 364 if (port_ptr) 365 *port_ptr = -1; 366 if (proto_size > 0) 367 proto[0] = 0; 368 if (authorization_size > 0) 369 authorization[0] = 0; 370 if (hostname_size > 0) 371 hostname[0] = 0; 372 if (path_size > 0) 373 path[0] = 0; 374 375 /* parse protocol */ 376 if ((p = strchr(url, ':'))) { 377 av_strlcpy(proto, url, FFMIN(proto_size, p + 1 - url)); 378 p++; /* skip ':' */ 379 if (*p == '/') 380 p++; 381 if (*p == '/') 382 p++; 383 } else { 384 /* no protocol means plain filename */ 385 av_strlcpy(path, url, path_size); 386 return; 387 } 388 389 /* separate path from hostname */ 390 ls = p + strcspn(p, "/?#"); 391 av_strlcpy(path, ls, path_size); 392 393 /* the rest is hostname, use that to parse auth/port */ 394 if (ls != p) { 395 /* authorization (user[:pass]@hostname) */ 396 at2 = p; 397 while ((at = strchr(p, '@')) && at < ls) { 398 av_strlcpy(authorization, at2, 399 FFMIN(authorization_size, at + 1 - at2)); 400 p = at + 1; /* skip '@' */ 401 } 402 403 if (*p == '[' && (brk = strchr(p, ']')) && brk < ls) { 404 /* [host]:port */ 405 av_strlcpy(hostname, p + 1, 406 FFMIN(hostname_size, brk - p)); 407 if (brk[1] == ':' && port_ptr) 408 *port_ptr = atoi(brk + 2); 409 } else if ((col = strchr(p, ':')) && col < ls) { 410 av_strlcpy(hostname, p, 411 FFMIN(col + 1 - p, hostname_size)); 412 if (port_ptr) 413 *port_ptr = atoi(col + 1); 414 } else 415 av_strlcpy(hostname, p, 416 FFMIN(ls + 1 - p, hostname_size)); 417 } 418} 419 420int ff_mkdir_p(const char *path) 421{ 422 int ret = 0; 423 char *temp = av_strdup(path); 424 char *pos = temp; 425 char tmp_ch = '\0'; 426 427 if (!path || !temp) { 428 return -1; 429 } 430 431 if (!av_strncasecmp(temp, "/", 1) || !av_strncasecmp(temp, "\\", 1)) { 432 pos++; 433 } else if (!av_strncasecmp(temp, "./", 2) || !av_strncasecmp(temp, ".\\", 2)) { 434 pos += 2; 435 } 436 437 for ( ; *pos != '\0'; ++pos) { 438 if (*pos == '/' || *pos == '\\') { 439 tmp_ch = *pos; 440 *pos = '\0'; 441 ret = mkdir(temp, 0755); 442 *pos = tmp_ch; 443 } 444 } 445 446 if ((*(pos - 1) != '/') && (*(pos - 1) != '\\')) { 447 ret = mkdir(temp, 0755); 448 } 449 450 av_free(temp); 451 return ret; 452} 453 454char *ff_data_to_hex(char *buff, const uint8_t *src, int s, int lowercase) 455{ 456 static const char hex_table_uc[16] = { '0', '1', '2', '3', 457 '4', '5', '6', '7', 458 '8', '9', 'A', 'B', 459 'C', 'D', 'E', 'F' }; 460 static const char hex_table_lc[16] = { '0', '1', '2', '3', 461 '4', '5', '6', '7', 462 '8', '9', 'a', 'b', 463 'c', 'd', 'e', 'f' }; 464 const char *hex_table = lowercase ? hex_table_lc : hex_table_uc; 465 466 for (int i = 0; i < s; i++) { 467 buff[i * 2] = hex_table[src[i] >> 4]; 468 buff[i * 2 + 1] = hex_table[src[i] & 0xF]; 469 } 470 buff[2 * s] = '\0'; 471 472 return buff; 473} 474 475int ff_hex_to_data(uint8_t *data, const char *p) 476{ 477 int c, len, v; 478 479 len = 0; 480 v = 1; 481 for (;;) { 482 p += strspn(p, SPACE_CHARS); 483 if (*p == '\0') 484 break; 485 c = av_toupper((unsigned char) *p++); 486 if (c >= '0' && c <= '9') 487 c = c - '0'; 488 else if (c >= 'A' && c <= 'F') 489 c = c - 'A' + 10; 490 else 491 break; 492 v = (v << 4) | c; 493 if (v & 0x100) { 494 if (data) 495 data[len] = v; 496 len++; 497 v = 1; 498 } 499 } 500 return len; 501} 502 503void ff_parse_key_value(const char *str, ff_parse_key_val_cb callback_get_buf, 504 void *context) 505{ 506 const char *ptr = str; 507 508 /* Parse key=value pairs. */ 509 for (;;) { 510 const char *key; 511 char *dest = NULL, *dest_end; 512 int key_len, dest_len = 0; 513 514 /* Skip whitespace and potential commas. */ 515 while (*ptr && (av_isspace(*ptr) || *ptr == ',')) 516 ptr++; 517 if (!*ptr) 518 break; 519 520 key = ptr; 521 522 if (!(ptr = strchr(key, '='))) 523 break; 524 ptr++; 525 key_len = ptr - key; 526 527 callback_get_buf(context, key, key_len, &dest, &dest_len); 528 dest_end = dest ? dest + dest_len - 1 : NULL; 529 530 if (*ptr == '\"') { 531 ptr++; 532 while (*ptr && *ptr != '\"') { 533 if (*ptr == '\\') { 534 if (!ptr[1]) 535 break; 536 if (dest && dest < dest_end) 537 *dest++ = ptr[1]; 538 ptr += 2; 539 } else { 540 if (dest && dest < dest_end) 541 *dest++ = *ptr; 542 ptr++; 543 } 544 } 545 if (*ptr == '\"') 546 ptr++; 547 } else { 548 for (; *ptr && !(av_isspace(*ptr) || *ptr == ','); ptr++) 549 if (dest && dest < dest_end) 550 *dest++ = *ptr; 551 } 552 if (dest) 553 *dest = 0; 554 } 555} 556 557int avformat_network_init(void) 558{ 559#if CONFIG_NETWORK 560 int ret; 561 if ((ret = ff_network_init()) < 0) 562 return ret; 563 if ((ret = ff_tls_init()) < 0) 564 return ret; 565#endif 566 return 0; 567} 568 569int avformat_network_deinit(void) 570{ 571#if CONFIG_NETWORK 572 ff_network_close(); 573 ff_tls_deinit(); 574#endif 575 return 0; 576} 577 578int ff_is_http_proto(const char *filename) { 579 const char *proto = avio_find_protocol_name(filename); 580 return proto ? (!av_strcasecmp(proto, "http") || !av_strcasecmp(proto, "https")) : 0; 581} 582 583int ff_bprint_to_codecpar_extradata(AVCodecParameters *par, struct AVBPrint *buf) 584{ 585 int ret; 586 char *str; 587 588 ret = av_bprint_finalize(buf, &str); 589 if (ret < 0) 590 return ret; 591 if (!av_bprint_is_complete(buf)) { 592 av_free(str); 593 return AVERROR(ENOMEM); 594 } 595 596 par->extradata = str; 597 /* Note: the string is NUL terminated (so extradata can be read as a 598 * string), but the ending character is not accounted in the size (in 599 * binary formats you are likely not supposed to mux that character). When 600 * extradata is copied, it is also padded with AV_INPUT_BUFFER_PADDING_SIZE 601 * zeros. */ 602 par->extradata_size = buf->len; 603 return 0; 604} 605