Add a av_grow_packet function, to be used by code that merges
[ffmpeg.git] / libavcodec / avpacket.c
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 "avcodec.h"
23 #include "libavutil/avassert.h"
24
25
26 void av_destruct_packet_nofree(AVPacket *pkt)
27 {
28     pkt->data = NULL; pkt->size = 0;
29 }
30
31 void av_destruct_packet(AVPacket *pkt)
32 {
33     av_free(pkt->data);
34     pkt->data = NULL; pkt->size = 0;
35 }
36
37 void av_init_packet(AVPacket *pkt)
38 {
39     pkt->pts   = AV_NOPTS_VALUE;
40     pkt->dts   = AV_NOPTS_VALUE;
41     pkt->pos   = -1;
42     pkt->duration = 0;
43     pkt->convergence_duration = 0;
44     pkt->flags = 0;
45     pkt->stream_index = 0;
46     pkt->destruct= NULL;
47 }
48
49 int av_new_packet(AVPacket *pkt, int size)
50 {
51     uint8_t *data= NULL;
52     if((unsigned)size < (unsigned)size + FF_INPUT_BUFFER_PADDING_SIZE)
53         data = av_malloc(size + FF_INPUT_BUFFER_PADDING_SIZE);
54     if (data){
55         memset(data + size, 0, FF_INPUT_BUFFER_PADDING_SIZE);
56     }else
57         size=0;
58
59     av_init_packet(pkt);
60     pkt->data = data;
61     pkt->size = size;
62     pkt->destruct = av_destruct_packet;
63     if(!data)
64         return AVERROR(ENOMEM);
65     return 0;
66 }
67
68 void av_shrink_packet(AVPacket *pkt, int size)
69 {
70     if (pkt->size <= size) return;
71     pkt->size = size;
72     memset(pkt->data + size, 0, FF_INPUT_BUFFER_PADDING_SIZE);
73 }
74
75 int av_grow_packet(AVPacket *pkt, int grow_by)
76 {
77     void *new_ptr;
78     av_assert0((unsigned)pkt->size <= INT_MAX - FF_INPUT_BUFFER_PADDING_SIZE);
79     if (!pkt->size)
80         return av_new_packet(pkt, grow_by);
81     if ((unsigned)grow_by > INT_MAX - (pkt->size + FF_INPUT_BUFFER_PADDING_SIZE))
82         return -1;
83     new_ptr = av_realloc(pkt->data, pkt->size + grow_by + FF_INPUT_BUFFER_PADDING_SIZE);
84     if (!new_ptr)
85         return AVERROR(ENOMEM);
86     pkt->data = new_ptr;
87     pkt->size += grow_by;
88     memset(pkt->data + pkt->size, 0, FF_INPUT_BUFFER_PADDING_SIZE);
89     return 0;
90 }
91
92 int av_dup_packet(AVPacket *pkt)
93 {
94     if (((pkt->destruct == av_destruct_packet_nofree) || (pkt->destruct == NULL)) && pkt->data) {
95         uint8_t *data;
96         /* We duplicate the packet and don't forget to add the padding again. */
97         if((unsigned)pkt->size > (unsigned)pkt->size + FF_INPUT_BUFFER_PADDING_SIZE)
98             return AVERROR(ENOMEM);
99         data = av_malloc(pkt->size + FF_INPUT_BUFFER_PADDING_SIZE);
100         if (!data) {
101             return AVERROR(ENOMEM);
102         }
103         memcpy(data, pkt->data, pkt->size);
104         memset(data + pkt->size, 0, FF_INPUT_BUFFER_PADDING_SIZE);
105         pkt->data = data;
106         pkt->destruct = av_destruct_packet;
107     }
108     return 0;
109 }
110
111 void av_free_packet(AVPacket *pkt)
112 {
113     if (pkt) {
114         if (pkt->destruct) pkt->destruct(pkt);
115         pkt->data = NULL; pkt->size = 0;
116     }
117 }