1/* 2 * AVPacket functions for libavcodec 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 <string.h> 23 24#include "libavutil/avassert.h" 25#include "libavutil/common.h" 26#include "libavutil/internal.h" 27#include "libavutil/mathematics.h" 28#include "libavutil/mem.h" 29#include "avcodec.h" 30#include "bytestream.h" 31#include "internal.h" 32 33#if FF_API_DESTRUCT_PACKET 34 35void av_destruct_packet(AVPacket *pkt) 36{ 37 av_free(pkt->data); 38 pkt->data = NULL; 39 pkt->size = 0; 40} 41 42/* a dummy destruct callback for the callers that assume AVPacket.destruct == 43 * NULL => static data */ 44static void dummy_destruct_packet(AVPacket *pkt) 45{ 46 av_assert0(0); 47} 48#endif 49 50void av_init_packet(AVPacket *pkt) 51{ 52 pkt->pts = AV_NOPTS_VALUE; 53 pkt->dts = AV_NOPTS_VALUE; 54 pkt->pos = -1; 55 pkt->duration = 0; 56 pkt->convergence_duration = 0; 57 pkt->flags = 0; 58 pkt->stream_index = 0; 59#if FF_API_DESTRUCT_PACKET 60FF_DISABLE_DEPRECATION_WARNINGS 61 pkt->destruct = NULL; 62FF_ENABLE_DEPRECATION_WARNINGS 63#endif 64 pkt->buf = NULL; 65 pkt->side_data = NULL; 66 pkt->side_data_elems = 0; 67} 68 69static int packet_alloc(AVBufferRef **buf, int size) 70{ 71 int ret; 72 if ((unsigned)size >= (unsigned)size + FF_INPUT_BUFFER_PADDING_SIZE) 73 return AVERROR(EINVAL); 74 75 ret = av_buffer_realloc(buf, size + FF_INPUT_BUFFER_PADDING_SIZE); 76 if (ret < 0) 77 return ret; 78 79 memset((*buf)->data + size, 0, FF_INPUT_BUFFER_PADDING_SIZE); 80 81 return 0; 82} 83 84int av_new_packet(AVPacket *pkt, int size) 85{ 86 AVBufferRef *buf = NULL; 87 int ret = packet_alloc(&buf, size); 88 if (ret < 0) 89 return ret; 90 91 av_init_packet(pkt); 92 pkt->buf = buf; 93 pkt->data = buf->data; 94 pkt->size = size; 95#if FF_API_DESTRUCT_PACKET 96FF_DISABLE_DEPRECATION_WARNINGS 97 pkt->destruct = dummy_destruct_packet; 98FF_ENABLE_DEPRECATION_WARNINGS 99#endif 100 101 return 0; 102} 103 104void av_shrink_packet(AVPacket *pkt, int size) 105{ 106 if (pkt->size <= size) 107 return; 108 pkt->size = size; 109 memset(pkt->data + size, 0, FF_INPUT_BUFFER_PADDING_SIZE); 110} 111 112int av_grow_packet(AVPacket *pkt, int grow_by) 113{ 114 int new_size; 115 av_assert0((unsigned)pkt->size <= INT_MAX - FF_INPUT_BUFFER_PADDING_SIZE); 116 if (!pkt->size) 117 return av_new_packet(pkt, grow_by); 118 if ((unsigned)grow_by > 119 INT_MAX - (pkt->size + FF_INPUT_BUFFER_PADDING_SIZE)) 120 return -1; 121 122 new_size = pkt->size + grow_by + FF_INPUT_BUFFER_PADDING_SIZE; 123 if (pkt->buf) { 124 int ret = av_buffer_realloc(&pkt->buf, new_size); 125 if (ret < 0) 126 return ret; 127 } else { 128 pkt->buf = av_buffer_alloc(new_size); 129 if (!pkt->buf) 130 return AVERROR(ENOMEM); 131 memcpy(pkt->buf->data, pkt->data, FFMIN(pkt->size, pkt->size + grow_by)); 132#if FF_API_DESTRUCT_PACKET 133FF_DISABLE_DEPRECATION_WARNINGS 134 pkt->destruct = dummy_destruct_packet; 135FF_ENABLE_DEPRECATION_WARNINGS 136#endif 137 } 138 pkt->data = pkt->buf->data; 139 pkt->size += grow_by; 140 memset(pkt->data + pkt->size, 0, FF_INPUT_BUFFER_PADDING_SIZE); 141 142 return 0; 143} 144 145int av_packet_from_data(AVPacket *pkt, uint8_t *data, int size) 146{ 147 if (size >= INT_MAX - FF_INPUT_BUFFER_PADDING_SIZE) 148 return AVERROR(EINVAL); 149 150 pkt->buf = av_buffer_create(data, size + FF_INPUT_BUFFER_PADDING_SIZE, 151 av_buffer_default_free, NULL, 0); 152 if (!pkt->buf) 153 return AVERROR(ENOMEM); 154 155 pkt->data = data; 156 pkt->size = size; 157#if FF_API_DESTRUCT_PACKET 158FF_DISABLE_DEPRECATION_WARNINGS 159 pkt->destruct = dummy_destruct_packet; 160FF_ENABLE_DEPRECATION_WARNINGS 161#endif 162 163 return 0; 164} 165 166#define ALLOC_MALLOC(data, size) data = av_malloc(size) 167#define ALLOC_BUF(data, size) \ 168do { \ 169 av_buffer_realloc(&pkt->buf, size); \ 170 data = pkt->buf ? pkt->buf->data : NULL; \ 171} while (0) 172 173#define DUP_DATA(dst, src, size, padding, ALLOC) \ 174 do { \ 175 void *data; \ 176 if (padding) { \ 177 if ((unsigned)(size) > \ 178 (unsigned)(size) + FF_INPUT_BUFFER_PADDING_SIZE) \ 179 goto failed_alloc; \ 180 ALLOC(data, size + FF_INPUT_BUFFER_PADDING_SIZE); \ 181 } else { \ 182 ALLOC(data, size); \ 183 } \ 184 if (!data) \ 185 goto failed_alloc; \ 186 memcpy(data, src, size); \ 187 if (padding) \ 188 memset((uint8_t *)data + size, 0, \ 189 FF_INPUT_BUFFER_PADDING_SIZE); \ 190 dst = data; \ 191 } while (0) 192 193/* Makes duplicates of data, side_data, but does not copy any other fields */ 194static int copy_packet_data(AVPacket *pkt, const AVPacket *src, int dup) 195{ 196 pkt->data = NULL; 197 pkt->side_data = NULL; 198 if (pkt->buf) { 199 AVBufferRef *ref = av_buffer_ref(src->buf); 200 if (!ref) 201 return AVERROR(ENOMEM); 202 pkt->buf = ref; 203 pkt->data = ref->data; 204 } else { 205 DUP_DATA(pkt->data, src->data, pkt->size, 1, ALLOC_BUF); 206 } 207#if FF_API_DESTRUCT_PACKET 208FF_DISABLE_DEPRECATION_WARNINGS 209 pkt->destruct = dummy_destruct_packet; 210FF_ENABLE_DEPRECATION_WARNINGS 211#endif 212 if (pkt->side_data_elems && dup) 213 pkt->side_data = src->side_data; 214 if (pkt->side_data_elems && !dup) { 215 return av_copy_packet_side_data(pkt, src); 216 } 217 return 0; 218 219failed_alloc: 220 av_free_packet(pkt); 221 return AVERROR(ENOMEM); 222} 223 224int av_copy_packet_side_data(AVPacket *pkt, const AVPacket *src) 225{ 226 if (src->side_data_elems) { 227 int i; 228 DUP_DATA(pkt->side_data, src->side_data, 229 src->side_data_elems * sizeof(*src->side_data), 0, ALLOC_MALLOC); 230 if (src != pkt) { 231 memset(pkt->side_data, 0, 232 src->side_data_elems * sizeof(*src->side_data)); 233 } 234 for (i = 0; i < src->side_data_elems; i++) { 235 DUP_DATA(pkt->side_data[i].data, src->side_data[i].data, 236 src->side_data[i].size, 1, ALLOC_MALLOC); 237 pkt->side_data[i].size = src->side_data[i].size; 238 pkt->side_data[i].type = src->side_data[i].type; 239 } 240 } 241 pkt->side_data_elems = src->side_data_elems; 242 return 0; 243 244failed_alloc: 245 av_free_packet(pkt); 246 return AVERROR(ENOMEM); 247} 248 249int av_dup_packet(AVPacket *pkt) 250{ 251 AVPacket tmp_pkt; 252 253FF_DISABLE_DEPRECATION_WARNINGS 254 if (!pkt->buf && pkt->data 255#if FF_API_DESTRUCT_PACKET 256 && !pkt->destruct 257#endif 258 ) { 259FF_ENABLE_DEPRECATION_WARNINGS 260 tmp_pkt = *pkt; 261 return copy_packet_data(pkt, &tmp_pkt, 1); 262 } 263 return 0; 264} 265 266int av_copy_packet(AVPacket *dst, const AVPacket *src) 267{ 268 *dst = *src; 269 return copy_packet_data(dst, src, 0); 270} 271 272void av_packet_free_side_data(AVPacket *pkt) 273{ 274 int i; 275 for (i = 0; i < pkt->side_data_elems; i++) 276 av_free(pkt->side_data[i].data); 277 av_freep(&pkt->side_data); 278 pkt->side_data_elems = 0; 279} 280 281void av_free_packet(AVPacket *pkt) 282{ 283 if (pkt) { 284FF_DISABLE_DEPRECATION_WARNINGS 285 if (pkt->buf) 286 av_buffer_unref(&pkt->buf); 287#if FF_API_DESTRUCT_PACKET 288 else if (pkt->destruct) 289 pkt->destruct(pkt); 290 pkt->destruct = NULL; 291#endif 292FF_ENABLE_DEPRECATION_WARNINGS 293 pkt->data = NULL; 294 pkt->size = 0; 295 296 av_packet_free_side_data(pkt); 297 } 298} 299 300uint8_t *av_packet_new_side_data(AVPacket *pkt, enum AVPacketSideDataType type, 301 int size) 302{ 303 int elems = pkt->side_data_elems; 304 305 if ((unsigned)elems + 1 > INT_MAX / sizeof(*pkt->side_data)) 306 return NULL; 307 if ((unsigned)size > INT_MAX - FF_INPUT_BUFFER_PADDING_SIZE) 308 return NULL; 309 310 pkt->side_data = av_realloc(pkt->side_data, 311 (elems + 1) * sizeof(*pkt->side_data)); 312 if (!pkt->side_data) 313 return NULL; 314 315 pkt->side_data[elems].data = av_mallocz(size + FF_INPUT_BUFFER_PADDING_SIZE); 316 if (!pkt->side_data[elems].data) 317 return NULL; 318 pkt->side_data[elems].size = size; 319 pkt->side_data[elems].type = type; 320 pkt->side_data_elems++; 321 322 return pkt->side_data[elems].data; 323} 324 325uint8_t *av_packet_get_side_data(AVPacket *pkt, enum AVPacketSideDataType type, 326 int *size) 327{ 328 int i; 329 330 for (i = 0; i < pkt->side_data_elems; i++) { 331 if (pkt->side_data[i].type == type) { 332 if (size) 333 *size = pkt->side_data[i].size; 334 return pkt->side_data[i].data; 335 } 336 } 337 return NULL; 338} 339 340#define FF_MERGE_MARKER 0x8c4d9d108e25e9feULL 341 342int av_packet_merge_side_data(AVPacket *pkt){ 343 if(pkt->side_data_elems){ 344 AVBufferRef *buf; 345 int i; 346 uint8_t *p; 347 uint64_t size= pkt->size + 8LL + FF_INPUT_BUFFER_PADDING_SIZE; 348 AVPacket old= *pkt; 349 for (i=0; i<old.side_data_elems; i++) { 350 size += old.side_data[i].size + 5LL; 351 } 352 if (size > INT_MAX) 353 return AVERROR(EINVAL); 354 buf = av_buffer_alloc(size); 355 if (!buf) 356 return AVERROR(ENOMEM); 357 pkt->buf = buf; 358 pkt->data = p = buf->data; 359#if FF_API_DESTRUCT_PACKET 360FF_DISABLE_DEPRECATION_WARNINGS 361 pkt->destruct = dummy_destruct_packet; 362FF_ENABLE_DEPRECATION_WARNINGS 363#endif 364 pkt->size = size - FF_INPUT_BUFFER_PADDING_SIZE; 365 bytestream_put_buffer(&p, old.data, old.size); 366 for (i=old.side_data_elems-1; i>=0; i--) { 367 bytestream_put_buffer(&p, old.side_data[i].data, old.side_data[i].size); 368 bytestream_put_be32(&p, old.side_data[i].size); 369 *p++ = old.side_data[i].type | ((i==old.side_data_elems-1)*128); 370 } 371 bytestream_put_be64(&p, FF_MERGE_MARKER); 372 av_assert0(p-pkt->data == pkt->size); 373 memset(p, 0, FF_INPUT_BUFFER_PADDING_SIZE); 374 av_free_packet(&old); 375 pkt->side_data_elems = 0; 376 pkt->side_data = NULL; 377 return 1; 378 } 379 return 0; 380} 381 382int av_packet_split_side_data(AVPacket *pkt){ 383 if (!pkt->side_data_elems && pkt->size >12 && AV_RB64(pkt->data + pkt->size - 8) == FF_MERGE_MARKER){ 384 int i; 385 unsigned int size; 386 uint8_t *p; 387 388 p = pkt->data + pkt->size - 8 - 5; 389 for (i=1; ; i++){ 390 size = AV_RB32(p); 391 if (size>INT_MAX || p - pkt->data < size) 392 return 0; 393 if (p[4]&128) 394 break; 395 p-= size+5; 396 } 397 398 pkt->side_data = av_malloc_array(i, sizeof(*pkt->side_data)); 399 if (!pkt->side_data) 400 return AVERROR(ENOMEM); 401 402 p= pkt->data + pkt->size - 8 - 5; 403 for (i=0; ; i++){ 404 size= AV_RB32(p); 405 av_assert0(size<=INT_MAX && p - pkt->data >= size); 406 pkt->side_data[i].data = av_mallocz(size + FF_INPUT_BUFFER_PADDING_SIZE); 407 pkt->side_data[i].size = size; 408 pkt->side_data[i].type = p[4]&127; 409 if (!pkt->side_data[i].data) 410 return AVERROR(ENOMEM); 411 memcpy(pkt->side_data[i].data, p-size, size); 412 pkt->size -= size + 5; 413 if(p[4]&128) 414 break; 415 p-= size+5; 416 } 417 pkt->size -= 8; 418 pkt->side_data_elems = i+1; 419 return 1; 420 } 421 return 0; 422} 423 424uint8_t *av_packet_pack_dictionary(AVDictionary *dict, int *size) 425{ 426 AVDictionaryEntry *t = NULL; 427 uint8_t *data = NULL; 428 *size = 0; 429 430 if (!dict) 431 return NULL; 432 433 while ((t = av_dict_get(dict, "", t, AV_DICT_IGNORE_SUFFIX))) { 434 const size_t keylen = strlen(t->key); 435 const size_t valuelen = strlen(t->value); 436 const size_t new_size = *size + keylen + 1 + valuelen + 1; 437 uint8_t *const new_data = av_realloc(data, new_size); 438 439 if (!new_data) 440 goto fail; 441 data = new_data; 442 if (new_size > INT_MAX) 443 goto fail; 444 445 memcpy(data + *size, t->key, keylen + 1); 446 memcpy(data + *size + keylen + 1, t->value, valuelen + 1); 447 448 *size = new_size; 449 } 450 451 return data; 452 453fail: 454 av_freep(&data); 455 *size = 0; 456 return NULL; 457} 458 459int av_packet_unpack_dictionary(const uint8_t *data, int size, AVDictionary **dict) 460{ 461 const uint8_t *end = data + size; 462 int ret = 0; 463 464 if (!dict || !data || !size) 465 return ret; 466 if (size && end[-1]) 467 return AVERROR_INVALIDDATA; 468 while (data < end) { 469 const uint8_t *key = data; 470 const uint8_t *val = data + strlen(key) + 1; 471 472 if (val >= end) 473 return AVERROR_INVALIDDATA; 474 475 ret = av_dict_set(dict, key, val, 0); 476 if (ret < 0) 477 break; 478 data = val + strlen(val) + 1; 479 } 480 481 return ret; 482} 483 484int av_packet_shrink_side_data(AVPacket *pkt, enum AVPacketSideDataType type, 485 int size) 486{ 487 int i; 488 489 for (i = 0; i < pkt->side_data_elems; i++) { 490 if (pkt->side_data[i].type == type) { 491 if (size > pkt->side_data[i].size) 492 return AVERROR(ENOMEM); 493 pkt->side_data[i].size = size; 494 return 0; 495 } 496 } 497 return AVERROR(ENOENT); 498} 499 500int av_packet_copy_props(AVPacket *dst, const AVPacket *src) 501{ 502 int i; 503 504 dst->pts = src->pts; 505 dst->dts = src->dts; 506 dst->pos = src->pos; 507 dst->duration = src->duration; 508 dst->convergence_duration = src->convergence_duration; 509 dst->flags = src->flags; 510 dst->stream_index = src->stream_index; 511 512 for (i = 0; i < src->side_data_elems; i++) { 513 enum AVPacketSideDataType type = src->side_data[i].type; 514 int size = src->side_data[i].size; 515 uint8_t *src_data = src->side_data[i].data; 516 uint8_t *dst_data = av_packet_new_side_data(dst, type, size); 517 518 if (!dst_data) { 519 av_packet_free_side_data(dst); 520 return AVERROR(ENOMEM); 521 } 522 memcpy(dst_data, src_data, size); 523 } 524 525 return 0; 526} 527 528void av_packet_unref(AVPacket *pkt) 529{ 530 av_packet_free_side_data(pkt); 531 av_buffer_unref(&pkt->buf); 532 av_init_packet(pkt); 533 pkt->data = NULL; 534 pkt->size = 0; 535} 536 537int av_packet_ref(AVPacket *dst, const AVPacket *src) 538{ 539 int ret; 540 541 ret = av_packet_copy_props(dst, src); 542 if (ret < 0) 543 return ret; 544 545 if (!src->buf) { 546 ret = packet_alloc(&dst->buf, src->size); 547 if (ret < 0) 548 goto fail; 549 memcpy(dst->buf->data, src->data, src->size); 550 } else 551 dst->buf = av_buffer_ref(src->buf); 552 553 dst->size = src->size; 554 dst->data = dst->buf->data; 555 return 0; 556fail: 557 av_packet_free_side_data(dst); 558 return ret; 559} 560 561void av_packet_move_ref(AVPacket *dst, AVPacket *src) 562{ 563 *dst = *src; 564 av_init_packet(src); 565} 566 567void av_packet_rescale_ts(AVPacket *pkt, AVRational src_tb, AVRational dst_tb) 568{ 569 if (pkt->pts != AV_NOPTS_VALUE) 570 pkt->pts = av_rescale_q(pkt->pts, src_tb, dst_tb); 571 if (pkt->dts != AV_NOPTS_VALUE) 572 pkt->dts = av_rescale_q(pkt->dts, src_tb, dst_tb); 573 if (pkt->duration > 0) 574 pkt->duration = av_rescale_q(pkt->duration, src_tb, dst_tb); 575 if (pkt->convergence_duration > 0) 576 pkt->convergence_duration = av_rescale_q(pkt->convergence_duration, src_tb, dst_tb); 577} 578