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