avpacket.c 16.4 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
/*
 * AVPacket functions for libavcodec
 * Copyright (c) 2000, 2001, 2002 Fabrice Bellard
 *
 * This file is part of FFmpeg.
 *
 * FFmpeg is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * FFmpeg is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with FFmpeg; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 */

22 23
#include <string.h>

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 31
#include "bytestream.h"
#include "internal.h"
32

33
#if FF_API_DESTRUCT_PACKET
34

35 36
void av_destruct_packet(AVPacket *pkt)
{
37
    av_freep(&pkt->data);
38
    pkt->size = 0;
39 40
}

41 42 43 44 45 46 47 48
/* a dummy destruct callback for the callers that assume AVPacket.destruct ==
 * NULL => static data */
static void dummy_destruct_packet(AVPacket *pkt)
{
    av_assert0(0);
}
#endif

49 50
void av_init_packet(AVPacket *pkt)
{
51 52 53 54
    pkt->pts                  = AV_NOPTS_VALUE;
    pkt->dts                  = AV_NOPTS_VALUE;
    pkt->pos                  = -1;
    pkt->duration             = 0;
55
    pkt->convergence_duration = 0;
56 57
    pkt->flags                = 0;
    pkt->stream_index         = 0;
58
#if FF_API_DESTRUCT_PACKET
59
FF_DISABLE_DEPRECATION_WARNINGS
60
    pkt->destruct             = NULL;
61
FF_ENABLE_DEPRECATION_WARNINGS
62 63
#endif
    pkt->buf                  = NULL;
64 65
    pkt->side_data            = NULL;
    pkt->side_data_elems      = 0;
66 67
}

68
static int packet_alloc(AVBufferRef **buf, int size)
69
{
70
    int ret;
71 72 73
    if ((unsigned)size >= (unsigned)size + FF_INPUT_BUFFER_PADDING_SIZE)
        return AVERROR(EINVAL);

74 75 76
    ret = av_buffer_realloc(buf, size + FF_INPUT_BUFFER_PADDING_SIZE);
    if (ret < 0)
        return ret;
77

78 79 80 81 82 83 84 85 86 87 88
    memset((*buf)->data + size, 0, FF_INPUT_BUFFER_PADDING_SIZE);

    return 0;
}

int av_new_packet(AVPacket *pkt, int size)
{
    AVBufferRef *buf = NULL;
    int ret = packet_alloc(&buf, size);
    if (ret < 0)
        return ret;
89 90

    av_init_packet(pkt);
91 92
    pkt->buf      = buf;
    pkt->data     = buf->data;
93
    pkt->size     = size;
94
#if FF_API_DESTRUCT_PACKET
95
FF_DISABLE_DEPRECATION_WARNINGS
96
    pkt->destruct = dummy_destruct_packet;
97
FF_ENABLE_DEPRECATION_WARNINGS
98 99
#endif

100 101 102
    return 0;
}

103 104
void av_shrink_packet(AVPacket *pkt, int size)
{
105 106
    if (pkt->size <= size)
        return;
107 108 109 110
    pkt->size = size;
    memset(pkt->data + size, 0, FF_INPUT_BUFFER_PADDING_SIZE);
}

111 112
int av_grow_packet(AVPacket *pkt, int grow_by)
{
113
    int new_size;
114 115 116
    av_assert0((unsigned)pkt->size <= INT_MAX - FF_INPUT_BUFFER_PADDING_SIZE);
    if (!pkt->size)
        return av_new_packet(pkt, grow_by);
117 118
    if ((unsigned)grow_by >
        INT_MAX - (pkt->size + FF_INPUT_BUFFER_PADDING_SIZE))
119
        return -1;
120 121 122 123 124 125 126 127 128 129 130 131

    new_size = pkt->size + grow_by + FF_INPUT_BUFFER_PADDING_SIZE;
    if (pkt->buf) {
        int ret = av_buffer_realloc(&pkt->buf, new_size);
        if (ret < 0)
            return ret;
    } else {
        pkt->buf = av_buffer_alloc(new_size);
        if (!pkt->buf)
            return AVERROR(ENOMEM);
        memcpy(pkt->buf->data, pkt->data, FFMIN(pkt->size, pkt->size + grow_by));
#if FF_API_DESTRUCT_PACKET
132
FF_DISABLE_DEPRECATION_WARNINGS
133
        pkt->destruct = dummy_destruct_packet;
134
FF_ENABLE_DEPRECATION_WARNINGS
135 136 137
#endif
    }
    pkt->data  = pkt->buf->data;
138 139
    pkt->size += grow_by;
    memset(pkt->data + pkt->size, 0, FF_INPUT_BUFFER_PADDING_SIZE);
140

141 142 143
    return 0;
}

144 145 146 147 148 149 150 151 152 153 154 155 156
int av_packet_from_data(AVPacket *pkt, uint8_t *data, int size)
{
    if (size >= INT_MAX - FF_INPUT_BUFFER_PADDING_SIZE)
        return AVERROR(EINVAL);

    pkt->buf = av_buffer_create(data, size + FF_INPUT_BUFFER_PADDING_SIZE,
                                av_buffer_default_free, NULL, 0);
    if (!pkt->buf)
        return AVERROR(ENOMEM);

    pkt->data = data;
    pkt->size = size;
#if FF_API_DESTRUCT_PACKET
157
FF_DISABLE_DEPRECATION_WARNINGS
158
    pkt->destruct = dummy_destruct_packet;
159
FF_ENABLE_DEPRECATION_WARNINGS
160 161
#endif

162 163 164
    return 0;
}

165 166 167 168 169 170 171 172
#define ALLOC_MALLOC(data, size) data = av_malloc(size)
#define ALLOC_BUF(data, size)                \
do {                                         \
    av_buffer_realloc(&pkt->buf, size);      \
    data = pkt->buf ? pkt->buf->data : NULL; \
} while (0)

#define DUP_DATA(dst, src, size, padding, ALLOC)                        \
173 174 175 176 177 178
    do {                                                                \
        void *data;                                                     \
        if (padding) {                                                  \
            if ((unsigned)(size) >                                      \
                (unsigned)(size) + FF_INPUT_BUFFER_PADDING_SIZE)        \
                goto failed_alloc;                                      \
179
            ALLOC(data, size + FF_INPUT_BUFFER_PADDING_SIZE);           \
180
        } else {                                                        \
181
            ALLOC(data, size);                                          \
182 183 184 185 186 187 188 189 190
        }                                                               \
        if (!data)                                                      \
            goto failed_alloc;                                          \
        memcpy(data, src, size);                                        \
        if (padding)                                                    \
            memset((uint8_t *)data + size, 0,                           \
                   FF_INPUT_BUFFER_PADDING_SIZE);                       \
        dst = data;                                                     \
    } while (0)
191

192
/* Makes duplicates of data, side_data, but does not copy any other fields */
193
static int copy_packet_data(AVPacket *pkt, const AVPacket *src, int dup)
194
{
195 196
    pkt->data      = NULL;
    pkt->side_data = NULL;
197 198 199 200 201 202 203 204 205
    if (pkt->buf) {
        AVBufferRef *ref = av_buffer_ref(src->buf);
        if (!ref)
            return AVERROR(ENOMEM);
        pkt->buf  = ref;
        pkt->data = ref->data;
    } else {
        DUP_DATA(pkt->data, src->data, pkt->size, 1, ALLOC_BUF);
    }
206
#if FF_API_DESTRUCT_PACKET
207
FF_DISABLE_DEPRECATION_WARNINGS
208
    pkt->destruct = dummy_destruct_packet;
209
FF_ENABLE_DEPRECATION_WARNINGS
210
#endif
211 212 213
    if (pkt->side_data_elems && dup)
        pkt->side_data = src->side_data;
    if (pkt->side_data_elems && !dup) {
214 215 216 217 218
        return av_copy_packet_side_data(pkt, src);
    }
    return 0;

failed_alloc:
219
    av_free_packet(pkt);
220 221
    return AVERROR(ENOMEM);
}
222

223
int av_copy_packet_side_data(AVPacket *pkt, const AVPacket *src)
224 225 226
{
    if (src->side_data_elems) {
        int i;
227
        DUP_DATA(pkt->side_data, src->side_data,
228
                src->side_data_elems * sizeof(*src->side_data), 0, ALLOC_MALLOC);
229 230 231 232
        if (src != pkt) {
            memset(pkt->side_data, 0,
                   src->side_data_elems * sizeof(*src->side_data));
        }
233
        for (i = 0; i < src->side_data_elems; i++) {
234 235 236 237
            DUP_DATA(pkt->side_data[i].data, src->side_data[i].data,
                    src->side_data[i].size, 1, ALLOC_MALLOC);
            pkt->side_data[i].size = src->side_data[i].size;
            pkt->side_data[i].type = src->side_data[i].type;
238 239
        }
    }
240
    pkt->side_data_elems = src->side_data_elems;
241 242 243
    return 0;

failed_alloc:
244
    av_free_packet(pkt);
245 246 247
    return AVERROR(ENOMEM);
}

248 249
int av_dup_packet(AVPacket *pkt)
{
250 251
    AVPacket tmp_pkt;

252
FF_DISABLE_DEPRECATION_WARNINGS
253 254 255 256 257
    if (!pkt->buf && pkt->data
#if FF_API_DESTRUCT_PACKET
        && !pkt->destruct
#endif
        ) {
258
FF_ENABLE_DEPRECATION_WARNINGS
259
        tmp_pkt = *pkt;
260
        return copy_packet_data(pkt, &tmp_pkt, 1);
261 262 263
    }
    return 0;
}
Ramiro Polla's avatar
Ramiro Polla committed
264

265
int av_copy_packet(AVPacket *dst, const AVPacket *src)
Andrey Utkin's avatar
Andrey Utkin committed
266 267
{
    *dst = *src;
268
    return copy_packet_data(dst, src, 0);
Andrey Utkin's avatar
Andrey Utkin committed
269 270
}

271 272 273 274
void av_packet_free_side_data(AVPacket *pkt)
{
    int i;
    for (i = 0; i < pkt->side_data_elems; i++)
275
        av_freep(&pkt->side_data[i].data);
276 277 278 279
    av_freep(&pkt->side_data);
    pkt->side_data_elems = 0;
}

Ramiro Polla's avatar
Ramiro Polla committed
280 281 282
void av_free_packet(AVPacket *pkt)
{
    if (pkt) {
283
FF_DISABLE_DEPRECATION_WARNINGS
284 285 286 287
        if (pkt->buf)
            av_buffer_unref(&pkt->buf);
#if FF_API_DESTRUCT_PACKET
        else if (pkt->destruct)
288
            pkt->destruct(pkt);
289 290
        pkt->destruct = NULL;
#endif
291
FF_ENABLE_DEPRECATION_WARNINGS
292 293
        pkt->data            = NULL;
        pkt->size            = 0;
294

295
        av_packet_free_side_data(pkt);
296 297 298
    }
}

299
uint8_t *av_packet_new_side_data(AVPacket *pkt, enum AVPacketSideDataType type,
300 301 302 303 304 305 306 307 308
                                 int size)
{
    int elems = pkt->side_data_elems;

    if ((unsigned)elems + 1 > INT_MAX / sizeof(*pkt->side_data))
        return NULL;
    if ((unsigned)size > INT_MAX - FF_INPUT_BUFFER_PADDING_SIZE)
        return NULL;

309 310
    pkt->side_data = av_realloc(pkt->side_data,
                                (elems + 1) * sizeof(*pkt->side_data));
311 312 313
    if (!pkt->side_data)
        return NULL;

314
    pkt->side_data[elems].data = av_mallocz(size + FF_INPUT_BUFFER_PADDING_SIZE);
315 316 317 318 319 320 321 322 323
    if (!pkt->side_data[elems].data)
        return NULL;
    pkt->side_data[elems].size = size;
    pkt->side_data[elems].type = type;
    pkt->side_data_elems++;

    return pkt->side_data[elems].data;
}

324
uint8_t *av_packet_get_side_data(AVPacket *pkt, enum AVPacketSideDataType type,
325 326 327 328 329 330 331 332 333 334
                                 int *size)
{
    int i;

    for (i = 0; i < pkt->side_data_elems; i++) {
        if (pkt->side_data[i].type == type) {
            if (size)
                *size = pkt->side_data[i].size;
            return pkt->side_data[i].data;
        }
Ramiro Polla's avatar
Ramiro Polla committed
335
    }
336
    return NULL;
Ramiro Polla's avatar
Ramiro Polla committed
337
}
338 339 340 341 342

#define FF_MERGE_MARKER 0x8c4d9d108e25e9feULL

int av_packet_merge_side_data(AVPacket *pkt){
    if(pkt->side_data_elems){
343
        AVBufferRef *buf;
344 345 346 347 348 349 350 351 352
        int i;
        uint8_t *p;
        uint64_t size= pkt->size + 8LL + FF_INPUT_BUFFER_PADDING_SIZE;
        AVPacket old= *pkt;
        for (i=0; i<old.side_data_elems; i++) {
            size += old.side_data[i].size + 5LL;
        }
        if (size > INT_MAX)
            return AVERROR(EINVAL);
353 354
        buf = av_buffer_alloc(size);
        if (!buf)
355
            return AVERROR(ENOMEM);
356 357 358
        pkt->buf = buf;
        pkt->data = p = buf->data;
#if FF_API_DESTRUCT_PACKET
359
FF_DISABLE_DEPRECATION_WARNINGS
360
        pkt->destruct = dummy_destruct_packet;
361
FF_ENABLE_DEPRECATION_WARNINGS
362
#endif
363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383
        pkt->size = size - FF_INPUT_BUFFER_PADDING_SIZE;
        bytestream_put_buffer(&p, old.data, old.size);
        for (i=old.side_data_elems-1; i>=0; i--) {
            bytestream_put_buffer(&p, old.side_data[i].data, old.side_data[i].size);
            bytestream_put_be32(&p, old.side_data[i].size);
            *p++ = old.side_data[i].type | ((i==old.side_data_elems-1)*128);
        }
        bytestream_put_be64(&p, FF_MERGE_MARKER);
        av_assert0(p-pkt->data == pkt->size);
        memset(p, 0, FF_INPUT_BUFFER_PADDING_SIZE);
        av_free_packet(&old);
        pkt->side_data_elems = 0;
        pkt->side_data = NULL;
        return 1;
    }
    return 0;
}

int av_packet_split_side_data(AVPacket *pkt){
    if (!pkt->side_data_elems && pkt->size >12 && AV_RB64(pkt->data + pkt->size - 8) == FF_MERGE_MARKER){
        int i;
384
        unsigned int size;
385
        uint8_t *p;
386

387
        p = pkt->data + pkt->size - 8 - 5;
388 389
        for (i=1; ; i++){
            size = AV_RB32(p);
390
            if (size>INT_MAX || p - pkt->data < size)
391 392 393 394 395 396
                return 0;
            if (p[4]&128)
                break;
            p-= size+5;
        }

397
        pkt->side_data = av_malloc_array(i, sizeof(*pkt->side_data));
398 399 400 401 402 403
        if (!pkt->side_data)
            return AVERROR(ENOMEM);

        p= pkt->data + pkt->size - 8 - 5;
        for (i=0; ; i++){
            size= AV_RB32(p);
404
            av_assert0(size<=INT_MAX && p - pkt->data >= size);
405
            pkt->side_data[i].data = av_mallocz(size + FF_INPUT_BUFFER_PADDING_SIZE);
406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421
            pkt->side_data[i].size = size;
            pkt->side_data[i].type = p[4]&127;
            if (!pkt->side_data[i].data)
                return AVERROR(ENOMEM);
            memcpy(pkt->side_data[i].data, p-size, size);
            pkt->size -= size + 5;
            if(p[4]&128)
                break;
            p-= size+5;
        }
        pkt->size -= 8;
        pkt->side_data_elems = i+1;
        return 1;
    }
    return 0;
}
422

423 424 425 426 427 428 429 430 431 432
uint8_t *av_packet_pack_dictionary(AVDictionary *dict, int *size)
{
    AVDictionaryEntry *t = NULL;
    uint8_t *data = NULL;
    *size = 0;

    if (!dict)
        return NULL;

    while ((t = av_dict_get(dict, "", t, AV_DICT_IGNORE_SUFFIX))) {
433 434
        const size_t keylen   = strlen(t->key);
        const size_t valuelen = strlen(t->value);
435 436 437
        const size_t new_size = *size + keylen + 1 + valuelen + 1;
        uint8_t *const new_data = av_realloc(data, new_size);

438
        if (!new_data)
439 440
            goto fail;
        data = new_data;
441 442
        if (new_size > INT_MAX)
            goto fail;
443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482

        memcpy(data + *size, t->key, keylen + 1);
        memcpy(data + *size + keylen + 1, t->value, valuelen + 1);

        *size = new_size;
    }

    return data;

fail:
    av_freep(&data);
    *size = 0;
    return NULL;
}

int av_packet_unpack_dictionary(const uint8_t *data, int size, AVDictionary **dict)
{
    const uint8_t *end = data + size;
    int ret = 0;

    if (!dict || !data || !size)
        return ret;
    if (size && end[-1])
        return AVERROR_INVALIDDATA;
    while (data < end) {
        const uint8_t *key = data;
        const uint8_t *val = data + strlen(key) + 1;

        if (val >= end)
            return AVERROR_INVALIDDATA;

        ret = av_dict_set(dict, key, val, 0);
        if (ret < 0)
            break;
        data = val + strlen(val) + 1;
    }

    return ret;
}

483 484 485 486 487 488 489 490 491 492 493 494 495 496 497
int av_packet_shrink_side_data(AVPacket *pkt, enum AVPacketSideDataType type,
                               int size)
{
    int i;

    for (i = 0; i < pkt->side_data_elems; i++) {
        if (pkt->side_data[i].type == type) {
            if (size > pkt->side_data[i].size)
                return AVERROR(ENOMEM);
            pkt->side_data[i].size = size;
            return 0;
        }
    }
    return AVERROR(ENOENT);
}
498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535

int av_packet_copy_props(AVPacket *dst, const AVPacket *src)
{
    int i;

    dst->pts                  = src->pts;
    dst->dts                  = src->dts;
    dst->pos                  = src->pos;
    dst->duration             = src->duration;
    dst->convergence_duration = src->convergence_duration;
    dst->flags                = src->flags;
    dst->stream_index         = src->stream_index;

    for (i = 0; i < src->side_data_elems; i++) {
         enum AVPacketSideDataType type = src->side_data[i].type;
         int size          = src->side_data[i].size;
         uint8_t *src_data = src->side_data[i].data;
         uint8_t *dst_data = av_packet_new_side_data(dst, type, size);

        if (!dst_data) {
            av_packet_free_side_data(dst);
            return AVERROR(ENOMEM);
        }
        memcpy(dst_data, src_data, size);
    }

    return 0;
}

void av_packet_unref(AVPacket *pkt)
{
    av_packet_free_side_data(pkt);
    av_buffer_unref(&pkt->buf);
    av_init_packet(pkt);
    pkt->data = NULL;
    pkt->size = 0;
}

536
int av_packet_ref(AVPacket *dst, const AVPacket *src)
537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564
{
    int ret;

    ret = av_packet_copy_props(dst, src);
    if (ret < 0)
        return ret;

    if (!src->buf) {
        ret = packet_alloc(&dst->buf, src->size);
        if (ret < 0)
            goto fail;
        memcpy(dst->buf->data, src->data, src->size);
    } else
        dst->buf = av_buffer_ref(src->buf);

    dst->size = src->size;
    dst->data = dst->buf->data;
    return 0;
fail:
    av_packet_free_side_data(dst);
    return ret;
}

void av_packet_move_ref(AVPacket *dst, AVPacket *src)
{
    *dst = *src;
    av_init_packet(src);
}
565 566 567 568 569 570 571 572 573 574 575 576

void av_packet_rescale_ts(AVPacket *pkt, AVRational src_tb, AVRational dst_tb)
{
    if (pkt->pts != AV_NOPTS_VALUE)
        pkt->pts = av_rescale_q(pkt->pts, src_tb, dst_tb);
    if (pkt->dts != AV_NOPTS_VALUE)
        pkt->dts = av_rescale_q(pkt->dts, src_tb, dst_tb);
    if (pkt->duration > 0)
        pkt->duration = av_rescale_q(pkt->duration, src_tb, dst_tb);
    if (pkt->convergence_duration > 0)
        pkt->convergence_duration = av_rescale_q(pkt->convergence_duration, src_tb, dst_tb);
}