avpacket.c
Go to the documentation of this file.
1 /*
2  * AVPacket functions for libavcodec
3  * Copyright (c) 2000, 2001, 2002 Fabrice Bellard
4  *
5  * This file is part of Libav.
6  *
7  * Libav 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  * Libav 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 Libav; 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 
29 {
30  int i;
31 
32  av_free(pkt->data);
33  pkt->data = NULL;
34  pkt->size = 0;
35 
36  for (i = 0; i < pkt->side_data_elems; i++)
37  av_free(pkt->side_data[i].data);
38  av_freep(&pkt->side_data);
39  pkt->side_data_elems = 0;
40 }
41 
43 {
44  pkt->pts = AV_NOPTS_VALUE;
45  pkt->dts = AV_NOPTS_VALUE;
46  pkt->pos = -1;
47  pkt->duration = 0;
48  pkt->convergence_duration = 0;
49  pkt->flags = 0;
50  pkt->stream_index = 0;
51  pkt->destruct = NULL;
52  pkt->side_data = NULL;
53  pkt->side_data_elems = 0;
54 }
55 
56 int av_new_packet(AVPacket *pkt, int size)
57 {
58  uint8_t *data = NULL;
59  if ((unsigned)size < (unsigned)size + FF_INPUT_BUFFER_PADDING_SIZE)
61  if (data) {
62  memset(data + size, 0, FF_INPUT_BUFFER_PADDING_SIZE);
63  } else
64  size = 0;
65 
66  av_init_packet(pkt);
67  pkt->data = data;
68  pkt->size = size;
70  if (!data)
71  return AVERROR(ENOMEM);
72  return 0;
73 }
74 
76 {
77  if (pkt->size <= size)
78  return;
79  pkt->size = size;
80  memset(pkt->data + size, 0, FF_INPUT_BUFFER_PADDING_SIZE);
81 }
82 
83 int av_grow_packet(AVPacket *pkt, int grow_by)
84 {
85  void *new_ptr;
86  av_assert0((unsigned)pkt->size <= INT_MAX - FF_INPUT_BUFFER_PADDING_SIZE);
87  if (!pkt->size)
88  return av_new_packet(pkt, grow_by);
89  if ((unsigned)grow_by >
90  INT_MAX - (pkt->size + FF_INPUT_BUFFER_PADDING_SIZE))
91  return -1;
92  new_ptr = av_realloc(pkt->data,
93  pkt->size + grow_by + FF_INPUT_BUFFER_PADDING_SIZE);
94  if (!new_ptr)
95  return AVERROR(ENOMEM);
96  pkt->data = new_ptr;
97  pkt->size += grow_by;
98  memset(pkt->data + pkt->size, 0, FF_INPUT_BUFFER_PADDING_SIZE);
99  return 0;
100 }
101 
102 #define DUP_DATA(dst, src, size, padding) \
103  do { \
104  void *data; \
105  if (padding) { \
106  if ((unsigned)(size) > \
107  (unsigned)(size) + FF_INPUT_BUFFER_PADDING_SIZE) \
108  goto failed_alloc; \
109  data = av_malloc(size + FF_INPUT_BUFFER_PADDING_SIZE); \
110  } else { \
111  data = av_malloc(size); \
112  } \
113  if (!data) \
114  goto failed_alloc; \
115  memcpy(data, src, size); \
116  if (padding) \
117  memset((uint8_t *)data + size, 0, \
118  FF_INPUT_BUFFER_PADDING_SIZE); \
119  dst = data; \
120  } while (0)
121 
123 {
124  AVPacket tmp_pkt;
125 
126  if (pkt->destruct == NULL && pkt->data) {
127  tmp_pkt = *pkt;
128 
129  pkt->data = NULL;
130  pkt->side_data = NULL;
131  DUP_DATA(pkt->data, tmp_pkt.data, pkt->size, 1);
133 
134  if (pkt->side_data_elems) {
135  int i;
136 
137  DUP_DATA(pkt->side_data, tmp_pkt.side_data,
138  pkt->side_data_elems * sizeof(*pkt->side_data), 0);
139  memset(pkt->side_data, 0,
140  pkt->side_data_elems * sizeof(*pkt->side_data));
141  for (i = 0; i < pkt->side_data_elems; i++)
142  DUP_DATA(pkt->side_data[i].data, tmp_pkt.side_data[i].data,
143  tmp_pkt.side_data[i].size, 1);
144  }
145  }
146  return 0;
147 
148 failed_alloc:
149  av_destruct_packet(pkt);
150  return AVERROR(ENOMEM);
151 }
152 
154 {
155  if (pkt) {
156  if (pkt->destruct)
157  pkt->destruct(pkt);
158  pkt->data = NULL;
159  pkt->size = 0;
160  pkt->side_data = NULL;
161  pkt->side_data_elems = 0;
162  }
163 }
164 
166  int size)
167 {
168  int elems = pkt->side_data_elems;
169 
170  if ((unsigned)elems + 1 > INT_MAX / sizeof(*pkt->side_data))
171  return NULL;
172  if ((unsigned)size > INT_MAX - FF_INPUT_BUFFER_PADDING_SIZE)
173  return NULL;
174 
175  pkt->side_data = av_realloc(pkt->side_data,
176  (elems + 1) * sizeof(*pkt->side_data));
177  if (!pkt->side_data)
178  return NULL;
179 
181  if (!pkt->side_data[elems].data)
182  return NULL;
183  pkt->side_data[elems].size = size;
184  pkt->side_data[elems].type = type;
185  pkt->side_data_elems++;
186 
187  return pkt->side_data[elems].data;
188 }
189 
191  int *size)
192 {
193  int i;
194 
195  for (i = 0; i < pkt->side_data_elems; i++) {
196  if (pkt->side_data[i].type == type) {
197  if (size)
198  *size = pkt->side_data[i].size;
199  return pkt->side_data[i].data;
200  }
201  }
202  return NULL;
203 }
204 
206  int size)
207 {
208  int i;
209 
210  for (i = 0; i < pkt->side_data_elems; i++) {
211  if (pkt->side_data[i].type == type) {
212  if (size > pkt->side_data[i].size)
213  return AVERROR(ENOMEM);
214  pkt->side_data[i].size = size;
215  return 0;
216  }
217  }
218  return AVERROR(ENOENT);
219 }