Merge remote-tracking branch 'qatar/master'
[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 <string.h>
23
24 #include "libavutil/avassert.h"
25 #include "libavutil/mem.h"
26 #include "avcodec.h"
27 #include "bytestream.h"
28 #include "internal.h"
29
30 void ff_packet_free_side_data(AVPacket *pkt)
31 {
32     int i;
33     for (i = 0; i < pkt->side_data_elems; i++)
34         av_free(pkt->side_data[i].data);
35     av_freep(&pkt->side_data);
36     pkt->side_data_elems = 0;
37 }
38
39 void av_destruct_packet(AVPacket *pkt)
40 {
41     av_free(pkt->data);
42     pkt->data = NULL;
43     pkt->size = 0;
44
45     ff_packet_free_side_data(pkt);
46 }
47
48 void av_init_packet(AVPacket *pkt)
49 {
50     pkt->pts                  = AV_NOPTS_VALUE;
51     pkt->dts                  = AV_NOPTS_VALUE;
52     pkt->pos                  = -1;
53     pkt->duration             = 0;
54     pkt->convergence_duration = 0;
55     pkt->flags                = 0;
56     pkt->stream_index         = 0;
57     pkt->destruct             = NULL;
58     pkt->side_data            = NULL;
59     pkt->side_data_elems      = 0;
60 }
61
62 int av_new_packet(AVPacket *pkt, int size)
63 {
64     uint8_t *data = NULL;
65     if ((unsigned)size < (unsigned)size + FF_INPUT_BUFFER_PADDING_SIZE)
66         data = av_malloc(size + FF_INPUT_BUFFER_PADDING_SIZE);
67     if (data) {
68         memset(data + size, 0, FF_INPUT_BUFFER_PADDING_SIZE);
69     } else
70         size = 0;
71
72     av_init_packet(pkt);
73     pkt->data     = data;
74     pkt->size     = size;
75     pkt->destruct = av_destruct_packet;
76     if (!data)
77         return AVERROR(ENOMEM);
78     return 0;
79 }
80
81 void av_shrink_packet(AVPacket *pkt, int size)
82 {
83     if (pkt->size <= size)
84         return;
85     pkt->size = size;
86     memset(pkt->data + size, 0, FF_INPUT_BUFFER_PADDING_SIZE);
87 }
88
89 int av_grow_packet(AVPacket *pkt, int grow_by)
90 {
91     void *new_ptr;
92     av_assert0((unsigned)pkt->size <= INT_MAX - FF_INPUT_BUFFER_PADDING_SIZE);
93     if (!pkt->size)
94         return av_new_packet(pkt, grow_by);
95     if ((unsigned)grow_by >
96         INT_MAX - (pkt->size + FF_INPUT_BUFFER_PADDING_SIZE))
97         return -1;
98     new_ptr = av_realloc(pkt->data,
99                          pkt->size + grow_by + FF_INPUT_BUFFER_PADDING_SIZE);
100     if (!new_ptr)
101         return AVERROR(ENOMEM);
102     pkt->data  = new_ptr;
103     pkt->size += grow_by;
104     memset(pkt->data + pkt->size, 0, FF_INPUT_BUFFER_PADDING_SIZE);
105     return 0;
106 }
107
108 #define DUP_DATA(dst, src, size, padding)                               \
109     do {                                                                \
110         void *data;                                                     \
111         if (padding) {                                                  \
112             if ((unsigned)(size) >                                      \
113                 (unsigned)(size) + FF_INPUT_BUFFER_PADDING_SIZE)        \
114                 goto failed_alloc;                                      \
115             data = av_malloc(size + FF_INPUT_BUFFER_PADDING_SIZE);      \
116         } else {                                                        \
117             data = av_malloc(size);                                     \
118         }                                                               \
119         if (!data)                                                      \
120             goto failed_alloc;                                          \
121         memcpy(data, src, size);                                        \
122         if (padding)                                                    \
123             memset((uint8_t *)data + size, 0,                           \
124                    FF_INPUT_BUFFER_PADDING_SIZE);                       \
125         dst = data;                                                     \
126     } while (0)
127
128 /* Makes duplicates of data, side_data, but does not copy any other fields */
129 static int copy_packet_data(AVPacket *dst, AVPacket *src)
130 {
131     dst->data      = NULL;
132     dst->side_data = NULL;
133     DUP_DATA(dst->data, src->data, dst->size, 1);
134     dst->destruct = av_destruct_packet;
135
136     if (dst->side_data_elems) {
137         int i;
138
139         DUP_DATA(dst->side_data, src->side_data,
140                 dst->side_data_elems * sizeof(*dst->side_data), 0);
141         memset(dst->side_data, 0,
142                 dst->side_data_elems * sizeof(*dst->side_data));
143         for (i = 0; i < dst->side_data_elems; i++) {
144             DUP_DATA(dst->side_data[i].data, src->side_data[i].data,
145                     src->side_data[i].size, 1);
146             dst->side_data[i].size = src->side_data[i].size;
147             dst->side_data[i].type = src->side_data[i].type;
148         }
149     }
150     return 0;
151
152 failed_alloc:
153     av_destruct_packet(dst);
154     return AVERROR(ENOMEM);
155 }
156
157 int av_dup_packet(AVPacket *pkt)
158 {
159     AVPacket tmp_pkt;
160
161     if (pkt->destruct == NULL && pkt->data) {
162         tmp_pkt = *pkt;
163         return copy_packet_data(pkt, &tmp_pkt);
164     }
165     return 0;
166 }
167
168 int av_copy_packet(AVPacket *dst, AVPacket *src)
169 {
170     *dst = *src;
171     return copy_packet_data(dst, src);
172 }
173
174 void av_free_packet(AVPacket *pkt)
175 {
176     if (pkt) {
177         if (pkt->destruct)
178             pkt->destruct(pkt);
179         pkt->data            = NULL;
180         pkt->size            = 0;
181         pkt->side_data       = NULL;
182         pkt->side_data_elems = 0;
183     }
184 }
185
186 uint8_t *av_packet_new_side_data(AVPacket *pkt, enum AVPacketSideDataType type,
187                                  int size)
188 {
189     int elems = pkt->side_data_elems;
190
191     if ((unsigned)elems + 1 > INT_MAX / sizeof(*pkt->side_data))
192         return NULL;
193     if ((unsigned)size > INT_MAX - FF_INPUT_BUFFER_PADDING_SIZE)
194         return NULL;
195
196     pkt->side_data = av_realloc(pkt->side_data,
197                                 (elems + 1) * sizeof(*pkt->side_data));
198     if (!pkt->side_data)
199         return NULL;
200
201     pkt->side_data[elems].data = av_malloc(size + FF_INPUT_BUFFER_PADDING_SIZE);
202     if (!pkt->side_data[elems].data)
203         return NULL;
204     pkt->side_data[elems].size = size;
205     pkt->side_data[elems].type = type;
206     pkt->side_data_elems++;
207
208     return pkt->side_data[elems].data;
209 }
210
211 uint8_t *av_packet_get_side_data(AVPacket *pkt, enum AVPacketSideDataType type,
212                                  int *size)
213 {
214     int i;
215
216     for (i = 0; i < pkt->side_data_elems; i++) {
217         if (pkt->side_data[i].type == type) {
218             if (size)
219                 *size = pkt->side_data[i].size;
220             return pkt->side_data[i].data;
221         }
222     }
223     return NULL;
224 }
225
226 #define FF_MERGE_MARKER 0x8c4d9d108e25e9feULL
227
228 int av_packet_merge_side_data(AVPacket *pkt){
229     if(pkt->side_data_elems){
230         int i;
231         uint8_t *p;
232         uint64_t size= pkt->size + 8LL + FF_INPUT_BUFFER_PADDING_SIZE;
233         AVPacket old= *pkt;
234         for (i=0; i<old.side_data_elems; i++) {
235             size += old.side_data[i].size + 5LL;
236         }
237         if (size > INT_MAX)
238             return AVERROR(EINVAL);
239         p = av_malloc(size);
240         if (!p)
241             return AVERROR(ENOMEM);
242         pkt->data = p;
243         pkt->destruct = av_destruct_packet;
244         pkt->size = size - FF_INPUT_BUFFER_PADDING_SIZE;
245         bytestream_put_buffer(&p, old.data, old.size);
246         for (i=old.side_data_elems-1; i>=0; i--) {
247             bytestream_put_buffer(&p, old.side_data[i].data, old.side_data[i].size);
248             bytestream_put_be32(&p, old.side_data[i].size);
249             *p++ = old.side_data[i].type | ((i==old.side_data_elems-1)*128);
250         }
251         bytestream_put_be64(&p, FF_MERGE_MARKER);
252         av_assert0(p-pkt->data == pkt->size);
253         memset(p, 0, FF_INPUT_BUFFER_PADDING_SIZE);
254         av_free_packet(&old);
255         pkt->side_data_elems = 0;
256         pkt->side_data = NULL;
257         return 1;
258     }
259     return 0;
260 }
261
262 int av_packet_split_side_data(AVPacket *pkt){
263     if (!pkt->side_data_elems && pkt->size >12 && AV_RB64(pkt->data + pkt->size - 8) == FF_MERGE_MARKER){
264         int i;
265         unsigned int size;
266         uint8_t *p;
267
268         p = pkt->data + pkt->size - 8 - 5;
269         for (i=1; ; i++){
270             size = AV_RB32(p);
271             if (size>INT_MAX || p - pkt->data < size)
272                 return 0;
273             if (p[4]&128)
274                 break;
275             p-= size+5;
276         }
277
278         pkt->side_data = av_malloc(i * sizeof(*pkt->side_data));
279         if (!pkt->side_data)
280             return AVERROR(ENOMEM);
281
282         p= pkt->data + pkt->size - 8 - 5;
283         for (i=0; ; i++){
284             size= AV_RB32(p);
285             av_assert0(size<=INT_MAX && p - pkt->data >= size);
286             pkt->side_data[i].data = av_malloc(size + FF_INPUT_BUFFER_PADDING_SIZE);
287             pkt->side_data[i].size = size;
288             pkt->side_data[i].type = p[4]&127;
289             if (!pkt->side_data[i].data)
290                 return AVERROR(ENOMEM);
291             memcpy(pkt->side_data[i].data, p-size, size);
292             pkt->size -= size + 5;
293             if(p[4]&128)
294                 break;
295             p-= size+5;
296         }
297         pkt->size -= 8;
298         pkt->side_data_elems = i+1;
299         return 1;
300     }
301     return 0;
302 }
303
304 int av_packet_shrink_side_data(AVPacket *pkt, enum AVPacketSideDataType type,
305                                int size)
306 {
307     int i;
308
309     for (i = 0; i < pkt->side_data_elems; i++) {
310         if (pkt->side_data[i].type == type) {
311             if (size > pkt->side_data[i].size)
312                 return AVERROR(ENOMEM);
313             pkt->side_data[i].size = size;
314             return 0;
315         }
316     }
317     return AVERROR(ENOENT);
318 }