PageRenderTime 80ms CodeModel.GetById 14ms app.highlight 60ms RepoModel.GetById 1ms app.codeStats 1ms

/libavcodec/avpacket.c

http://github.com/FFmpeg/FFmpeg
C | 772 lines | 637 code | 114 blank | 21 comment | 128 complexity | 375fc9d2ea83e06fe67b9798afb88d65 MD5 | raw file
  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
 30#include "bytestream.h"
 31#include "internal.h"
 32#include "packet.h"
 33
 34void av_init_packet(AVPacket *pkt)
 35{
 36    pkt->pts                  = AV_NOPTS_VALUE;
 37    pkt->dts                  = AV_NOPTS_VALUE;
 38    pkt->pos                  = -1;
 39    pkt->duration             = 0;
 40#if FF_API_CONVERGENCE_DURATION
 41FF_DISABLE_DEPRECATION_WARNINGS
 42    pkt->convergence_duration = 0;
 43FF_ENABLE_DEPRECATION_WARNINGS
 44#endif
 45    pkt->flags                = 0;
 46    pkt->stream_index         = 0;
 47    pkt->buf                  = NULL;
 48    pkt->side_data            = NULL;
 49    pkt->side_data_elems      = 0;
 50}
 51
 52AVPacket *av_packet_alloc(void)
 53{
 54    AVPacket *pkt = av_mallocz(sizeof(AVPacket));
 55    if (!pkt)
 56        return pkt;
 57
 58    av_init_packet(pkt);
 59
 60    return pkt;
 61}
 62
 63void av_packet_free(AVPacket **pkt)
 64{
 65    if (!pkt || !*pkt)
 66        return;
 67
 68    av_packet_unref(*pkt);
 69    av_freep(pkt);
 70}
 71
 72static int packet_alloc(AVBufferRef **buf, int size)
 73{
 74    int ret;
 75    if (size < 0 || size >= INT_MAX - AV_INPUT_BUFFER_PADDING_SIZE)
 76        return AVERROR(EINVAL);
 77
 78    ret = av_buffer_realloc(buf, size + AV_INPUT_BUFFER_PADDING_SIZE);
 79    if (ret < 0)
 80        return ret;
 81
 82    memset((*buf)->data + size, 0, AV_INPUT_BUFFER_PADDING_SIZE);
 83
 84    return 0;
 85}
 86
 87int av_new_packet(AVPacket *pkt, int size)
 88{
 89    AVBufferRef *buf = NULL;
 90    int ret = packet_alloc(&buf, size);
 91    if (ret < 0)
 92        return ret;
 93
 94    av_init_packet(pkt);
 95    pkt->buf      = buf;
 96    pkt->data     = buf->data;
 97    pkt->size     = size;
 98
 99    return 0;
100}
101
102void av_shrink_packet(AVPacket *pkt, int size)
103{
104    if (pkt->size <= size)
105        return;
106    pkt->size = size;
107    memset(pkt->data + size, 0, AV_INPUT_BUFFER_PADDING_SIZE);
108}
109
110int av_grow_packet(AVPacket *pkt, int grow_by)
111{
112    int new_size;
113    av_assert0((unsigned)pkt->size <= INT_MAX - AV_INPUT_BUFFER_PADDING_SIZE);
114    if ((unsigned)grow_by >
115        INT_MAX - (pkt->size + AV_INPUT_BUFFER_PADDING_SIZE))
116        return AVERROR(ENOMEM);
117
118    new_size = pkt->size + grow_by + AV_INPUT_BUFFER_PADDING_SIZE;
119    if (pkt->buf) {
120        size_t data_offset;
121        uint8_t *old_data = pkt->data;
122        if (pkt->data == NULL) {
123            data_offset = 0;
124            pkt->data = pkt->buf->data;
125        } else {
126            data_offset = pkt->data - pkt->buf->data;
127            if (data_offset > INT_MAX - new_size)
128                return AVERROR(ENOMEM);
129        }
130
131        if (new_size + data_offset > pkt->buf->size ||
132            !av_buffer_is_writable(pkt->buf)) {
133            int ret = av_buffer_realloc(&pkt->buf, new_size + data_offset);
134            if (ret < 0) {
135                pkt->data = old_data;
136                return ret;
137            }
138            pkt->data = pkt->buf->data + data_offset;
139        }
140    } else {
141        pkt->buf = av_buffer_alloc(new_size);
142        if (!pkt->buf)
143            return AVERROR(ENOMEM);
144        if (pkt->size > 0)
145            memcpy(pkt->buf->data, pkt->data, pkt->size);
146        pkt->data = pkt->buf->data;
147    }
148    pkt->size += grow_by;
149    memset(pkt->data + pkt->size, 0, AV_INPUT_BUFFER_PADDING_SIZE);
150
151    return 0;
152}
153
154int av_packet_from_data(AVPacket *pkt, uint8_t *data, int size)
155{
156    if (size >= INT_MAX - AV_INPUT_BUFFER_PADDING_SIZE)
157        return AVERROR(EINVAL);
158
159    pkt->buf = av_buffer_create(data, size + AV_INPUT_BUFFER_PADDING_SIZE,
160                                av_buffer_default_free, NULL, 0);
161    if (!pkt->buf)
162        return AVERROR(ENOMEM);
163
164    pkt->data = data;
165    pkt->size = size;
166
167    return 0;
168}
169
170#if FF_API_AVPACKET_OLD_API
171FF_DISABLE_DEPRECATION_WARNINGS
172#define ALLOC_MALLOC(data, size) data = av_malloc(size)
173#define ALLOC_BUF(data, size)                \
174do {                                         \
175    av_buffer_realloc(&pkt->buf, size);      \
176    data = pkt->buf ? pkt->buf->data : NULL; \
177} while (0)
178
179#define DUP_DATA(dst, src, size, padding, ALLOC)                        \
180    do {                                                                \
181        void *data;                                                     \
182        if (padding) {                                                  \
183            if ((unsigned)(size) >                                      \
184                (unsigned)(size) + AV_INPUT_BUFFER_PADDING_SIZE)        \
185                goto failed_alloc;                                      \
186            ALLOC(data, size + AV_INPUT_BUFFER_PADDING_SIZE);           \
187        } else {                                                        \
188            ALLOC(data, size);                                          \
189        }                                                               \
190        if (!data)                                                      \
191            goto failed_alloc;                                          \
192        memcpy(data, src, size);                                        \
193        if (padding)                                                    \
194            memset((uint8_t *)data + size, 0,                           \
195                   AV_INPUT_BUFFER_PADDING_SIZE);                       \
196        dst = data;                                                     \
197    } while (0)
198
199/* Makes duplicates of data, side_data, but does not copy any other fields */
200static int copy_packet_data(AVPacket *pkt, const AVPacket *src, int dup)
201{
202    pkt->data      = NULL;
203    pkt->side_data = NULL;
204    pkt->side_data_elems = 0;
205    if (pkt->buf) {
206        AVBufferRef *ref = av_buffer_ref(src->buf);
207        if (!ref)
208            return AVERROR(ENOMEM);
209        pkt->buf  = ref;
210        pkt->data = ref->data;
211    } else {
212        DUP_DATA(pkt->data, src->data, pkt->size, 1, ALLOC_BUF);
213    }
214    if (src->side_data_elems && dup) {
215        pkt->side_data = src->side_data;
216        pkt->side_data_elems = src->side_data_elems;
217    }
218    if (src->side_data_elems && !dup) {
219        return av_copy_packet_side_data(pkt, src);
220    }
221    return 0;
222
223failed_alloc:
224    av_packet_unref(pkt);
225    return AVERROR(ENOMEM);
226}
227
228int av_copy_packet_side_data(AVPacket *pkt, const AVPacket *src)
229{
230    if (src->side_data_elems) {
231        int i;
232        DUP_DATA(pkt->side_data, src->side_data,
233                src->side_data_elems * sizeof(*src->side_data), 0, ALLOC_MALLOC);
234        if (src != pkt) {
235            memset(pkt->side_data, 0,
236                   src->side_data_elems * sizeof(*src->side_data));
237        }
238        for (i = 0; i < src->side_data_elems; i++) {
239            DUP_DATA(pkt->side_data[i].data, src->side_data[i].data,
240                    src->side_data[i].size, 1, ALLOC_MALLOC);
241            pkt->side_data[i].size = src->side_data[i].size;
242            pkt->side_data[i].type = src->side_data[i].type;
243        }
244    }
245    pkt->side_data_elems = src->side_data_elems;
246    return 0;
247
248failed_alloc:
249    av_packet_unref(pkt);
250    return AVERROR(ENOMEM);
251}
252
253int av_dup_packet(AVPacket *pkt)
254{
255    AVPacket tmp_pkt;
256
257    if (!pkt->buf && pkt->data) {
258        tmp_pkt = *pkt;
259        return copy_packet_data(pkt, &tmp_pkt, 1);
260    }
261    return 0;
262}
263
264int av_copy_packet(AVPacket *dst, const AVPacket *src)
265{
266    *dst = *src;
267    return copy_packet_data(dst, src, 0);
268}
269FF_ENABLE_DEPRECATION_WARNINGS
270#endif
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_freep(&pkt->side_data[i].data);
277    av_freep(&pkt->side_data);
278    pkt->side_data_elems = 0;
279}
280
281#if FF_API_AVPACKET_OLD_API
282FF_DISABLE_DEPRECATION_WARNINGS
283void av_free_packet(AVPacket *pkt)
284{
285    if (pkt) {
286        if (pkt->buf)
287            av_buffer_unref(&pkt->buf);
288        pkt->data            = NULL;
289        pkt->size            = 0;
290
291        av_packet_free_side_data(pkt);
292    }
293}
294FF_ENABLE_DEPRECATION_WARNINGS
295#endif
296
297int av_packet_add_side_data(AVPacket *pkt, enum AVPacketSideDataType type,
298                            uint8_t *data, size_t size)
299{
300    AVPacketSideData *tmp;
301    int i, elems = pkt->side_data_elems;
302
303    for (i = 0; i < elems; i++) {
304        AVPacketSideData *sd = &pkt->side_data[i];
305
306        if (sd->type == type) {
307            av_free(sd->data);
308            sd->data = data;
309            sd->size = size;
310            return 0;
311        }
312    }
313
314    if ((unsigned)elems + 1 > AV_PKT_DATA_NB)
315        return AVERROR(ERANGE);
316
317    tmp = av_realloc(pkt->side_data, (elems + 1) * sizeof(*tmp));
318    if (!tmp)
319        return AVERROR(ENOMEM);
320
321    pkt->side_data = tmp;
322    pkt->side_data[elems].data = data;
323    pkt->side_data[elems].size = size;
324    pkt->side_data[elems].type = type;
325    pkt->side_data_elems++;
326
327    return 0;
328}
329
330
331uint8_t *av_packet_new_side_data(AVPacket *pkt, enum AVPacketSideDataType type,
332                                 int size)
333{
334    int ret;
335    uint8_t *data;
336
337    if ((unsigned)size > INT_MAX - AV_INPUT_BUFFER_PADDING_SIZE)
338        return NULL;
339    data = av_mallocz(size + AV_INPUT_BUFFER_PADDING_SIZE);
340    if (!data)
341        return NULL;
342
343    ret = av_packet_add_side_data(pkt, type, data, size);
344    if (ret < 0) {
345        av_freep(&data);
346        return NULL;
347    }
348
349    return data;
350}
351
352uint8_t *av_packet_get_side_data(const AVPacket *pkt, enum AVPacketSideDataType type,
353                                 int *size)
354{
355    int i;
356
357    for (i = 0; i < pkt->side_data_elems; i++) {
358        if (pkt->side_data[i].type == type) {
359            if (size)
360                *size = pkt->side_data[i].size;
361            return pkt->side_data[i].data;
362        }
363    }
364    if (size)
365        *size = 0;
366    return NULL;
367}
368
369const char *av_packet_side_data_name(enum AVPacketSideDataType type)
370{
371    switch(type) {
372    case AV_PKT_DATA_PALETTE:                    return "Palette";
373    case AV_PKT_DATA_NEW_EXTRADATA:              return "New Extradata";
374    case AV_PKT_DATA_PARAM_CHANGE:               return "Param Change";
375    case AV_PKT_DATA_H263_MB_INFO:               return "H263 MB Info";
376    case AV_PKT_DATA_REPLAYGAIN:                 return "Replay Gain";
377    case AV_PKT_DATA_DISPLAYMATRIX:              return "Display Matrix";
378    case AV_PKT_DATA_STEREO3D:                   return "Stereo 3D";
379    case AV_PKT_DATA_AUDIO_SERVICE_TYPE:         return "Audio Service Type";
380    case AV_PKT_DATA_QUALITY_STATS:              return "Quality stats";
381    case AV_PKT_DATA_FALLBACK_TRACK:             return "Fallback track";
382    case AV_PKT_DATA_CPB_PROPERTIES:             return "CPB properties";
383    case AV_PKT_DATA_SKIP_SAMPLES:               return "Skip Samples";
384    case AV_PKT_DATA_JP_DUALMONO:                return "JP Dual Mono";
385    case AV_PKT_DATA_STRINGS_METADATA:           return "Strings Metadata";
386    case AV_PKT_DATA_SUBTITLE_POSITION:          return "Subtitle Position";
387    case AV_PKT_DATA_MATROSKA_BLOCKADDITIONAL:   return "Matroska BlockAdditional";
388    case AV_PKT_DATA_WEBVTT_IDENTIFIER:          return "WebVTT ID";
389    case AV_PKT_DATA_WEBVTT_SETTINGS:            return "WebVTT Settings";
390    case AV_PKT_DATA_METADATA_UPDATE:            return "Metadata Update";
391    case AV_PKT_DATA_MPEGTS_STREAM_ID:           return "MPEGTS Stream ID";
392    case AV_PKT_DATA_MASTERING_DISPLAY_METADATA: return "Mastering display metadata";
393    case AV_PKT_DATA_CONTENT_LIGHT_LEVEL:        return "Content light level metadata";
394    case AV_PKT_DATA_SPHERICAL:                  return "Spherical Mapping";
395    case AV_PKT_DATA_A53_CC:                     return "A53 Closed Captions";
396    case AV_PKT_DATA_ENCRYPTION_INIT_INFO:       return "Encryption initialization data";
397    case AV_PKT_DATA_ENCRYPTION_INFO:            return "Encryption info";
398    case AV_PKT_DATA_AFD:                        return "Active Format Description data";
399    case AV_PKT_DATA_PRFT:                       return "Producer Reference Time";
400    case AV_PKT_DATA_ICC_PROFILE:                return "ICC Profile";
401    case AV_PKT_DATA_DOVI_CONF:                  return "DOVI configuration record";
402    }
403    return NULL;
404}
405
406#if FF_API_MERGE_SD_API
407
408#define FF_MERGE_MARKER 0x8c4d9d108e25e9feULL
409
410int av_packet_merge_side_data(AVPacket *pkt){
411    if(pkt->side_data_elems){
412        AVBufferRef *buf;
413        int i;
414        uint8_t *p;
415        uint64_t size= pkt->size + 8LL + AV_INPUT_BUFFER_PADDING_SIZE;
416        AVPacket old= *pkt;
417        for (i=0; i<old.side_data_elems; i++) {
418            size += old.side_data[i].size + 5LL;
419        }
420        if (size > INT_MAX)
421            return AVERROR(EINVAL);
422        buf = av_buffer_alloc(size);
423        if (!buf)
424            return AVERROR(ENOMEM);
425        pkt->buf = buf;
426        pkt->data = p = buf->data;
427        pkt->size = size - AV_INPUT_BUFFER_PADDING_SIZE;
428        bytestream_put_buffer(&p, old.data, old.size);
429        for (i=old.side_data_elems-1; i>=0; i--) {
430            bytestream_put_buffer(&p, old.side_data[i].data, old.side_data[i].size);
431            bytestream_put_be32(&p, old.side_data[i].size);
432            *p++ = old.side_data[i].type | ((i==old.side_data_elems-1)*128);
433        }
434        bytestream_put_be64(&p, FF_MERGE_MARKER);
435        av_assert0(p-pkt->data == pkt->size);
436        memset(p, 0, AV_INPUT_BUFFER_PADDING_SIZE);
437        av_packet_unref(&old);
438        pkt->side_data_elems = 0;
439        pkt->side_data = NULL;
440        return 1;
441    }
442    return 0;
443}
444
445int av_packet_split_side_data(AVPacket *pkt){
446    if (!pkt->side_data_elems && pkt->size >12 && AV_RB64(pkt->data + pkt->size - 8) == FF_MERGE_MARKER){
447        int i;
448        unsigned int size;
449        uint8_t *p;
450
451        p = pkt->data + pkt->size - 8 - 5;
452        for (i=1; ; i++){
453            size = AV_RB32(p);
454            if (size>INT_MAX - 5 || p - pkt->data < size)
455                return 0;
456            if (p[4]&128)
457                break;
458            if (p - pkt->data < size + 5)
459                return 0;
460            p-= size+5;
461        }
462
463        if (i > AV_PKT_DATA_NB)
464            return AVERROR(ERANGE);
465
466        pkt->side_data = av_malloc_array(i, sizeof(*pkt->side_data));
467        if (!pkt->side_data)
468            return AVERROR(ENOMEM);
469
470        p= pkt->data + pkt->size - 8 - 5;
471        for (i=0; ; i++){
472            size= AV_RB32(p);
473            av_assert0(size<=INT_MAX - 5 && p - pkt->data >= size);
474            pkt->side_data[i].data = av_mallocz(size + AV_INPUT_BUFFER_PADDING_SIZE);
475            pkt->side_data[i].size = size;
476            pkt->side_data[i].type = p[4]&127;
477            if (!pkt->side_data[i].data)
478                return AVERROR(ENOMEM);
479            memcpy(pkt->side_data[i].data, p-size, size);
480            pkt->size -= size + 5;
481            if(p[4]&128)
482                break;
483            p-= size+5;
484        }
485        pkt->size -= 8;
486        pkt->side_data_elems = i+1;
487        return 1;
488    }
489    return 0;
490}
491#endif
492
493uint8_t *av_packet_pack_dictionary(AVDictionary *dict, int *size)
494{
495    AVDictionaryEntry *t = NULL;
496    uint8_t *data = NULL;
497    *size = 0;
498
499    if (!dict)
500        return NULL;
501
502    while ((t = av_dict_get(dict, "", t, AV_DICT_IGNORE_SUFFIX))) {
503        const size_t keylen   = strlen(t->key);
504        const size_t valuelen = strlen(t->value);
505        const size_t new_size = *size + keylen + 1 + valuelen + 1;
506        uint8_t *const new_data = av_realloc(data, new_size);
507
508        if (!new_data)
509            goto fail;
510        data = new_data;
511        if (new_size > INT_MAX)
512            goto fail;
513
514        memcpy(data + *size, t->key, keylen + 1);
515        memcpy(data + *size + keylen + 1, t->value, valuelen + 1);
516
517        *size = new_size;
518    }
519
520    return data;
521
522fail:
523    av_freep(&data);
524    *size = 0;
525    return NULL;
526}
527
528int av_packet_unpack_dictionary(const uint8_t *data, int size, AVDictionary **dict)
529{
530    const uint8_t *end;
531    int ret;
532
533    if (!dict || !data || !size)
534        return 0;
535    end = data + size;
536    if (size && end[-1])
537        return AVERROR_INVALIDDATA;
538    while (data < end) {
539        const uint8_t *key = data;
540        const uint8_t *val = data + strlen(key) + 1;
541
542        if (val >= end || !*key)
543            return AVERROR_INVALIDDATA;
544
545        ret = av_dict_set(dict, key, val, 0);
546        if (ret < 0)
547            return ret;
548        data = val + strlen(val) + 1;
549    }
550
551    return 0;
552}
553
554int av_packet_shrink_side_data(AVPacket *pkt, enum AVPacketSideDataType type,
555                               int size)
556{
557    int i;
558
559    for (i = 0; i < pkt->side_data_elems; i++) {
560        if (pkt->side_data[i].type == type) {
561            if (size > pkt->side_data[i].size)
562                return AVERROR(ENOMEM);
563            pkt->side_data[i].size = size;
564            return 0;
565        }
566    }
567    return AVERROR(ENOENT);
568}
569
570int av_packet_copy_props(AVPacket *dst, const AVPacket *src)
571{
572    int i;
573
574    dst->pts                  = src->pts;
575    dst->dts                  = src->dts;
576    dst->pos                  = src->pos;
577    dst->duration             = src->duration;
578#if FF_API_CONVERGENCE_DURATION
579FF_DISABLE_DEPRECATION_WARNINGS
580    dst->convergence_duration = src->convergence_duration;
581FF_ENABLE_DEPRECATION_WARNINGS
582#endif
583    dst->flags                = src->flags;
584    dst->stream_index         = src->stream_index;
585
586    dst->side_data            = NULL;
587    dst->side_data_elems      = 0;
588    for (i = 0; i < src->side_data_elems; i++) {
589        enum AVPacketSideDataType type = src->side_data[i].type;
590        int size          = src->side_data[i].size;
591        uint8_t *src_data = src->side_data[i].data;
592        uint8_t *dst_data = av_packet_new_side_data(dst, type, size);
593
594        if (!dst_data) {
595            av_packet_free_side_data(dst);
596            return AVERROR(ENOMEM);
597        }
598        memcpy(dst_data, src_data, size);
599    }
600
601    return 0;
602}
603
604void av_packet_unref(AVPacket *pkt)
605{
606    av_packet_free_side_data(pkt);
607    av_buffer_unref(&pkt->buf);
608    av_init_packet(pkt);
609    pkt->data = NULL;
610    pkt->size = 0;
611}
612
613int av_packet_ref(AVPacket *dst, const AVPacket *src)
614{
615    int ret;
616
617    dst->buf = NULL;
618
619    ret = av_packet_copy_props(dst, src);
620    if (ret < 0)
621        goto fail;
622
623    if (!src->buf) {
624        ret = packet_alloc(&dst->buf, src->size);
625        if (ret < 0)
626            goto fail;
627        av_assert1(!src->size || src->data);
628        if (src->size)
629            memcpy(dst->buf->data, src->data, src->size);
630
631        dst->data = dst->buf->data;
632    } else {
633        dst->buf = av_buffer_ref(src->buf);
634        if (!dst->buf) {
635            ret = AVERROR(ENOMEM);
636            goto fail;
637        }
638        dst->data = src->data;
639    }
640
641    dst->size = src->size;
642
643    return 0;
644fail:
645    av_packet_unref(dst);
646    return ret;
647}
648
649AVPacket *av_packet_clone(const AVPacket *src)
650{
651    AVPacket *ret = av_packet_alloc();
652
653    if (!ret)
654        return ret;
655
656    if (av_packet_ref(ret, src))
657        av_packet_free(&ret);
658
659    return ret;
660}
661
662void av_packet_move_ref(AVPacket *dst, AVPacket *src)
663{
664    *dst = *src;
665    av_init_packet(src);
666    src->data = NULL;
667    src->size = 0;
668}
669
670int av_packet_make_refcounted(AVPacket *pkt)
671{
672    int ret;
673
674    if (pkt->buf)
675        return 0;
676
677    ret = packet_alloc(&pkt->buf, pkt->size);
678    if (ret < 0)
679        return ret;
680    av_assert1(!pkt->size || pkt->data);
681    if (pkt->size)
682        memcpy(pkt->buf->data, pkt->data, pkt->size);
683
684    pkt->data = pkt->buf->data;
685
686    return 0;
687}
688
689int av_packet_make_writable(AVPacket *pkt)
690{
691    AVBufferRef *buf = NULL;
692    int ret;
693
694    if (pkt->buf && av_buffer_is_writable(pkt->buf))
695        return 0;
696
697    ret = packet_alloc(&buf, pkt->size);
698    if (ret < 0)
699        return ret;
700    av_assert1(!pkt->size || pkt->data);
701    if (pkt->size)
702        memcpy(buf->data, pkt->data, pkt->size);
703
704    av_buffer_unref(&pkt->buf);
705    pkt->buf  = buf;
706    pkt->data = buf->data;
707
708    return 0;
709}
710
711void av_packet_rescale_ts(AVPacket *pkt, AVRational src_tb, AVRational dst_tb)
712{
713    if (pkt->pts != AV_NOPTS_VALUE)
714        pkt->pts = av_rescale_q(pkt->pts, src_tb, dst_tb);
715    if (pkt->dts != AV_NOPTS_VALUE)
716        pkt->dts = av_rescale_q(pkt->dts, src_tb, dst_tb);
717    if (pkt->duration > 0)
718        pkt->duration = av_rescale_q(pkt->duration, src_tb, dst_tb);
719#if FF_API_CONVERGENCE_DURATION
720FF_DISABLE_DEPRECATION_WARNINGS
721    if (pkt->convergence_duration > 0)
722        pkt->convergence_duration = av_rescale_q(pkt->convergence_duration, src_tb, dst_tb);
723FF_ENABLE_DEPRECATION_WARNINGS
724#endif
725}
726
727int ff_side_data_set_encoder_stats(AVPacket *pkt, int quality, int64_t *error, int error_count, int pict_type)
728{
729    uint8_t *side_data;
730    int side_data_size;
731    int i;
732
733    side_data = av_packet_get_side_data(pkt, AV_PKT_DATA_QUALITY_STATS, &side_data_size);
734    if (!side_data) {
735        side_data_size = 4+4+8*error_count;
736        side_data = av_packet_new_side_data(pkt, AV_PKT_DATA_QUALITY_STATS,
737                                            side_data_size);
738    }
739
740    if (!side_data || side_data_size < 4+4+8*error_count)
741        return AVERROR(ENOMEM);
742
743    AV_WL32(side_data   , quality  );
744    side_data[4] = pict_type;
745    side_data[5] = error_count;
746    for (i = 0; i<error_count; i++)
747        AV_WL64(side_data+8 + 8*i , error[i]);
748
749    return 0;
750}
751
752int ff_side_data_set_prft(AVPacket *pkt, int64_t timestamp)
753{
754    AVProducerReferenceTime *prft;
755    uint8_t *side_data;
756    int side_data_size;
757
758    side_data = av_packet_get_side_data(pkt, AV_PKT_DATA_PRFT, &side_data_size);
759    if (!side_data) {
760        side_data_size = sizeof(AVProducerReferenceTime);
761        side_data = av_packet_new_side_data(pkt, AV_PKT_DATA_PRFT, side_data_size);
762    }
763
764    if (!side_data || side_data_size < sizeof(AVProducerReferenceTime))
765        return AVERROR(ENOMEM);
766
767    prft = (AVProducerReferenceTime *)side_data;
768    prft->wallclock = timestamp;
769    prft->flags = 0;
770
771    return 0;
772}