00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include "internal.h"
00023 #include "libavutil/avassert.h"
00024 #include "bytestream.h"
00025 #include "avcodec.h"
00026
00027 void av_destruct_packet_nofree(AVPacket *pkt)
00028 {
00029 pkt->data = NULL;
00030 pkt->size = 0;
00031 pkt->side_data = NULL;
00032 pkt->side_data_elems = 0;
00033 }
00034
00035 void ff_packet_free_side_data(AVPacket *pkt)
00036 {
00037 int i;
00038 for (i = 0; i < pkt->side_data_elems; i++)
00039 av_free(pkt->side_data[i].data);
00040 av_freep(&pkt->side_data);
00041 pkt->side_data_elems = 0;
00042 }
00043
00044 void av_destruct_packet(AVPacket *pkt)
00045 {
00046 av_free(pkt->data);
00047 pkt->data = NULL;
00048 pkt->size = 0;
00049
00050 ff_packet_free_side_data(pkt);
00051 }
00052
00053 void av_init_packet(AVPacket *pkt)
00054 {
00055 pkt->pts = AV_NOPTS_VALUE;
00056 pkt->dts = AV_NOPTS_VALUE;
00057 pkt->pos = -1;
00058 pkt->duration = 0;
00059 pkt->convergence_duration = 0;
00060 pkt->flags = 0;
00061 pkt->stream_index = 0;
00062 pkt->destruct = NULL;
00063 pkt->side_data = NULL;
00064 pkt->side_data_elems = 0;
00065 }
00066
00067 int av_new_packet(AVPacket *pkt, int size)
00068 {
00069 uint8_t *data = NULL;
00070 if ((unsigned)size < (unsigned)size + FF_INPUT_BUFFER_PADDING_SIZE)
00071 data = av_malloc(size + FF_INPUT_BUFFER_PADDING_SIZE);
00072 if (data) {
00073 memset(data + size, 0, FF_INPUT_BUFFER_PADDING_SIZE);
00074 } else
00075 size = 0;
00076
00077 av_init_packet(pkt);
00078 pkt->data = data;
00079 pkt->size = size;
00080 pkt->destruct = av_destruct_packet;
00081 if (!data)
00082 return AVERROR(ENOMEM);
00083 return 0;
00084 }
00085
00086 void av_shrink_packet(AVPacket *pkt, int size)
00087 {
00088 if (pkt->size <= size)
00089 return;
00090 pkt->size = size;
00091 memset(pkt->data + size, 0, FF_INPUT_BUFFER_PADDING_SIZE);
00092 }
00093
00094 int av_grow_packet(AVPacket *pkt, int grow_by)
00095 {
00096 void *new_ptr;
00097 av_assert0((unsigned)pkt->size <= INT_MAX - FF_INPUT_BUFFER_PADDING_SIZE);
00098 if (!pkt->size)
00099 return av_new_packet(pkt, grow_by);
00100 if ((unsigned)grow_by >
00101 INT_MAX - (pkt->size + FF_INPUT_BUFFER_PADDING_SIZE))
00102 return -1;
00103 new_ptr = av_realloc(pkt->data,
00104 pkt->size + grow_by + FF_INPUT_BUFFER_PADDING_SIZE);
00105 if (!new_ptr)
00106 return AVERROR(ENOMEM);
00107 pkt->data = new_ptr;
00108 pkt->size += grow_by;
00109 memset(pkt->data + pkt->size, 0, FF_INPUT_BUFFER_PADDING_SIZE);
00110 return 0;
00111 }
00112
00113 #define DUP_DATA(dst, src, size, padding) \
00114 do { \
00115 void *data; \
00116 if (padding) { \
00117 if ((unsigned)(size) > \
00118 (unsigned)(size) + FF_INPUT_BUFFER_PADDING_SIZE) \
00119 goto failed_alloc; \
00120 data = av_malloc(size + FF_INPUT_BUFFER_PADDING_SIZE); \
00121 } else { \
00122 data = av_malloc(size); \
00123 } \
00124 if (!data) \
00125 goto failed_alloc; \
00126 memcpy(data, src, size); \
00127 if (padding) \
00128 memset((uint8_t *)data + size, 0, \
00129 FF_INPUT_BUFFER_PADDING_SIZE); \
00130 dst = data; \
00131 } while (0)
00132
00133 int av_dup_packet(AVPacket *pkt)
00134 {
00135 AVPacket tmp_pkt;
00136
00137 if (((pkt->destruct == av_destruct_packet_nofree) ||
00138 (pkt->destruct == NULL)) && pkt->data) {
00139 tmp_pkt = *pkt;
00140
00141 pkt->data = NULL;
00142 pkt->side_data = NULL;
00143 DUP_DATA(pkt->data, tmp_pkt.data, pkt->size, 1);
00144 pkt->destruct = av_destruct_packet;
00145
00146 if (pkt->side_data_elems) {
00147 int i;
00148
00149 DUP_DATA(pkt->side_data, tmp_pkt.side_data,
00150 pkt->side_data_elems * sizeof(*pkt->side_data), 0);
00151 memset(pkt->side_data, 0,
00152 pkt->side_data_elems * sizeof(*pkt->side_data));
00153 for (i = 0; i < pkt->side_data_elems; i++)
00154 DUP_DATA(pkt->side_data[i].data, tmp_pkt.side_data[i].data,
00155 pkt->side_data[i].size, 1);
00156 }
00157 }
00158 return 0;
00159
00160 failed_alloc:
00161 av_destruct_packet(pkt);
00162 return AVERROR(ENOMEM);
00163 }
00164
00165 void av_free_packet(AVPacket *pkt)
00166 {
00167 if (pkt) {
00168 if (pkt->destruct)
00169 pkt->destruct(pkt);
00170 pkt->data = NULL;
00171 pkt->size = 0;
00172 pkt->side_data = NULL;
00173 pkt->side_data_elems = 0;
00174 }
00175 }
00176
00177 uint8_t *av_packet_new_side_data(AVPacket *pkt, enum AVPacketSideDataType type,
00178 int size)
00179 {
00180 int elems = pkt->side_data_elems;
00181
00182 if ((unsigned)elems + 1 > INT_MAX / sizeof(*pkt->side_data))
00183 return NULL;
00184 if ((unsigned)size > INT_MAX - FF_INPUT_BUFFER_PADDING_SIZE)
00185 return NULL;
00186
00187 pkt->side_data = av_realloc(pkt->side_data,
00188 (elems + 1) * sizeof(*pkt->side_data));
00189 if (!pkt->side_data)
00190 return NULL;
00191
00192 pkt->side_data[elems].data = av_malloc(size + FF_INPUT_BUFFER_PADDING_SIZE);
00193 if (!pkt->side_data[elems].data)
00194 return NULL;
00195 pkt->side_data[elems].size = size;
00196 pkt->side_data[elems].type = type;
00197 pkt->side_data_elems++;
00198
00199 return pkt->side_data[elems].data;
00200 }
00201
00202 uint8_t *av_packet_get_side_data(AVPacket *pkt, enum AVPacketSideDataType type,
00203 int *size)
00204 {
00205 int i;
00206
00207 for (i = 0; i < pkt->side_data_elems; i++) {
00208 if (pkt->side_data[i].type == type) {
00209 if (size)
00210 *size = pkt->side_data[i].size;
00211 return pkt->side_data[i].data;
00212 }
00213 }
00214 return NULL;
00215 }
00216
00217 #define FF_MERGE_MARKER 0x8c4d9d108e25e9feULL
00218
00219 int av_packet_merge_side_data(AVPacket *pkt){
00220 if(pkt->side_data_elems){
00221 int i;
00222 uint8_t *p;
00223 uint64_t size= pkt->size + 8LL + FF_INPUT_BUFFER_PADDING_SIZE;
00224 AVPacket old= *pkt;
00225 for (i=0; i<old.side_data_elems; i++) {
00226 size += old.side_data[i].size + 5LL;
00227 }
00228 if (size > INT_MAX)
00229 return AVERROR(EINVAL);
00230 p = av_malloc(size);
00231 if (!p)
00232 return AVERROR(ENOMEM);
00233 pkt->data = p;
00234 pkt->destruct = av_destruct_packet;
00235 pkt->size = size - FF_INPUT_BUFFER_PADDING_SIZE;
00236 bytestream_put_buffer(&p, old.data, old.size);
00237 for (i=old.side_data_elems-1; i>=0; i--) {
00238 bytestream_put_buffer(&p, old.side_data[i].data, old.side_data[i].size);
00239 bytestream_put_be32(&p, old.side_data[i].size);
00240 *p++ = old.side_data[i].type | ((i==old.side_data_elems-1)*128);
00241 }
00242 bytestream_put_be64(&p, FF_MERGE_MARKER);
00243 av_assert0(p-pkt->data == pkt->size);
00244 memset(p, 0, FF_INPUT_BUFFER_PADDING_SIZE);
00245 av_free_packet(&old);
00246 pkt->side_data_elems = 0;
00247 pkt->side_data = NULL;
00248 return 1;
00249 }
00250 return 0;
00251 }
00252
00253 int av_packet_split_side_data(AVPacket *pkt){
00254 if (!pkt->side_data_elems && pkt->size >12 && AV_RB64(pkt->data + pkt->size - 8) == FF_MERGE_MARKER){
00255 int i;
00256 unsigned int size;
00257 uint8_t *p;
00258
00259 p = pkt->data + pkt->size - 8 - 5;
00260 for (i=1; ; i++){
00261 size = AV_RB32(p);
00262 if (size>INT_MAX || p - pkt->data < size)
00263 return 0;
00264 if (p[4]&128)
00265 break;
00266 p-= size+5;
00267 }
00268
00269 pkt->side_data = av_malloc(i * sizeof(*pkt->side_data));
00270 if (!pkt->side_data)
00271 return AVERROR(ENOMEM);
00272
00273 p= pkt->data + pkt->size - 8 - 5;
00274 for (i=0; ; i++){
00275 size= AV_RB32(p);
00276 av_assert0(size<=INT_MAX && p - pkt->data >= size);
00277 pkt->side_data[i].data = av_malloc(size + FF_INPUT_BUFFER_PADDING_SIZE);
00278 pkt->side_data[i].size = size;
00279 pkt->side_data[i].type = p[4]&127;
00280 if (!pkt->side_data[i].data)
00281 return AVERROR(ENOMEM);
00282 memcpy(pkt->side_data[i].data, p-size, size);
00283 pkt->size -= size + 5;
00284 if(p[4]&128)
00285 break;
00286 p-= size+5;
00287 }
00288 pkt->size -= 8;
00289 pkt->side_data_elems = i+1;
00290 return 1;
00291 }
00292 return 0;
00293 }
00294
00295 int av_packet_shrink_side_data(AVPacket *pkt, enum AVPacketSideDataType type,
00296 int size)
00297 {
00298 int i;
00299
00300 for (i = 0; i < pkt->side_data_elems; i++) {
00301 if (pkt->side_data[i].type == type) {
00302 if (size > pkt->side_data[i].size)
00303 return AVERROR(ENOMEM);
00304 pkt->side_data[i].size = size;
00305 return 0;
00306 }
00307 }
00308 return AVERROR(ENOENT);
00309 }