Libav 0.7.1
|
00001 /* 00002 * AVPacket functions for libavcodec 00003 * Copyright (c) 2000, 2001, 2002 Fabrice Bellard 00004 * 00005 * This file is part of Libav. 00006 * 00007 * Libav is free software; you can redistribute it and/or 00008 * modify it under the terms of the GNU Lesser General Public 00009 * License as published by the Free Software Foundation; either 00010 * version 2.1 of the License, or (at your option) any later version. 00011 * 00012 * Libav is distributed in the hope that it will be useful, 00013 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00015 * Lesser General Public License for more details. 00016 * 00017 * You should have received a copy of the GNU Lesser General Public 00018 * License along with Libav; if not, write to the Free Software 00019 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 00020 */ 00021 00022 #include "avcodec.h" 00023 #include "libavutil/avassert.h" 00024 00025 00026 void av_destruct_packet_nofree(AVPacket *pkt) 00027 { 00028 pkt->data = NULL; pkt->size = 0; 00029 pkt->side_data = NULL; 00030 pkt->side_data_elems = 0; 00031 } 00032 00033 void av_destruct_packet(AVPacket *pkt) 00034 { 00035 int i; 00036 00037 av_free(pkt->data); 00038 pkt->data = NULL; pkt->size = 0; 00039 00040 for (i = 0; i < pkt->side_data_elems; i++) 00041 av_free(pkt->side_data[i].data); 00042 av_freep(&pkt->side_data); 00043 pkt->side_data_elems = 0; 00044 } 00045 00046 void av_init_packet(AVPacket *pkt) 00047 { 00048 pkt->pts = AV_NOPTS_VALUE; 00049 pkt->dts = AV_NOPTS_VALUE; 00050 pkt->pos = -1; 00051 pkt->duration = 0; 00052 pkt->convergence_duration = 0; 00053 pkt->flags = 0; 00054 pkt->stream_index = 0; 00055 pkt->destruct= NULL; 00056 pkt->side_data = NULL; 00057 pkt->side_data_elems = 0; 00058 } 00059 00060 int av_new_packet(AVPacket *pkt, int size) 00061 { 00062 uint8_t *data= NULL; 00063 if((unsigned)size < (unsigned)size + FF_INPUT_BUFFER_PADDING_SIZE) 00064 data = av_malloc(size + FF_INPUT_BUFFER_PADDING_SIZE); 00065 if (data){ 00066 memset(data + size, 0, FF_INPUT_BUFFER_PADDING_SIZE); 00067 }else 00068 size=0; 00069 00070 av_init_packet(pkt); 00071 pkt->data = data; 00072 pkt->size = size; 00073 pkt->destruct = av_destruct_packet; 00074 if(!data) 00075 return AVERROR(ENOMEM); 00076 return 0; 00077 } 00078 00079 void av_shrink_packet(AVPacket *pkt, int size) 00080 { 00081 if (pkt->size <= size) return; 00082 pkt->size = size; 00083 memset(pkt->data + size, 0, FF_INPUT_BUFFER_PADDING_SIZE); 00084 } 00085 00086 int av_grow_packet(AVPacket *pkt, int grow_by) 00087 { 00088 void *new_ptr; 00089 av_assert0((unsigned)pkt->size <= INT_MAX - FF_INPUT_BUFFER_PADDING_SIZE); 00090 if (!pkt->size) 00091 return av_new_packet(pkt, grow_by); 00092 if ((unsigned)grow_by > INT_MAX - (pkt->size + FF_INPUT_BUFFER_PADDING_SIZE)) 00093 return -1; 00094 new_ptr = av_realloc(pkt->data, pkt->size + grow_by + FF_INPUT_BUFFER_PADDING_SIZE); 00095 if (!new_ptr) 00096 return AVERROR(ENOMEM); 00097 pkt->data = new_ptr; 00098 pkt->size += grow_by; 00099 memset(pkt->data + pkt->size, 0, FF_INPUT_BUFFER_PADDING_SIZE); 00100 return 0; 00101 } 00102 00103 #define DUP_DATA(dst, src, size, padding) \ 00104 do { \ 00105 void *data; \ 00106 if (padding) { \ 00107 if ((unsigned)(size) > (unsigned)(size) + FF_INPUT_BUFFER_PADDING_SIZE) \ 00108 goto failed_alloc; \ 00109 data = av_malloc(size + FF_INPUT_BUFFER_PADDING_SIZE); \ 00110 } else { \ 00111 data = av_malloc(size); \ 00112 } \ 00113 if (!data) \ 00114 goto failed_alloc; \ 00115 memcpy(data, src, size); \ 00116 if (padding) \ 00117 memset((uint8_t*)data + size, 0, FF_INPUT_BUFFER_PADDING_SIZE); \ 00118 dst = data; \ 00119 } while(0) 00120 00121 int av_dup_packet(AVPacket *pkt) 00122 { 00123 AVPacket tmp_pkt; 00124 00125 if (((pkt->destruct == av_destruct_packet_nofree) || (pkt->destruct == NULL)) && pkt->data) { 00126 tmp_pkt = *pkt; 00127 00128 pkt->data = NULL; 00129 pkt->side_data = NULL; 00130 DUP_DATA(pkt->data, tmp_pkt.data, pkt->size, 1); 00131 pkt->destruct = av_destruct_packet; 00132 00133 if (pkt->side_data_elems) { 00134 int i; 00135 00136 DUP_DATA(pkt->side_data, tmp_pkt.side_data, 00137 pkt->side_data_elems * sizeof(*pkt->side_data), 0); 00138 memset(pkt->side_data, 0, pkt->side_data_elems * sizeof(*pkt->side_data)); 00139 for (i = 0; i < pkt->side_data_elems; i++) { 00140 DUP_DATA(pkt->side_data[i].data, tmp_pkt.side_data[i].data, 00141 pkt->side_data[i].size, 1); 00142 } 00143 } 00144 } 00145 return 0; 00146 failed_alloc: 00147 av_destruct_packet(pkt); 00148 return AVERROR(ENOMEM); 00149 } 00150 00151 void av_free_packet(AVPacket *pkt) 00152 { 00153 if (pkt) { 00154 if (pkt->destruct) pkt->destruct(pkt); 00155 pkt->data = NULL; pkt->size = 0; 00156 pkt->side_data = NULL; 00157 pkt->side_data_elems = 0; 00158 } 00159 } 00160 00161 uint8_t* av_packet_new_side_data(AVPacket *pkt, enum AVPacketSideDataType type, 00162 int size) 00163 { 00164 int elems = pkt->side_data_elems; 00165 00166 if ((unsigned)elems + 1 > INT_MAX / sizeof(*pkt->side_data)) 00167 return NULL; 00168 if ((unsigned)size > INT_MAX - FF_INPUT_BUFFER_PADDING_SIZE) 00169 return NULL; 00170 00171 pkt->side_data = av_realloc(pkt->side_data, (elems + 1) * sizeof(*pkt->side_data)); 00172 if (!pkt->side_data) 00173 return NULL; 00174 00175 pkt->side_data[elems].data = av_malloc(size + FF_INPUT_BUFFER_PADDING_SIZE); 00176 if (!pkt->side_data[elems].data) 00177 return NULL; 00178 pkt->side_data[elems].size = size; 00179 pkt->side_data[elems].type = type; 00180 pkt->side_data_elems++; 00181 00182 return pkt->side_data[elems].data; 00183 } 00184 00185 uint8_t* av_packet_get_side_data(AVPacket *pkt, enum AVPacketSideDataType type, 00186 int *size) 00187 { 00188 int i; 00189 00190 for (i = 0; i < pkt->side_data_elems; i++) { 00191 if (pkt->side_data[i].type == type) { 00192 if (size) 00193 *size = pkt->side_data[i].size; 00194 return pkt->side_data[i].data; 00195 } 00196 } 00197 return NULL; 00198 }