00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #include "libavutil/channel_layout.h"
00024 #include "libavutil/avassert.h"
00025 #include "libavutil/common.h"
00026 #include "libavutil/imgutils.h"
00027 #include "libavcodec/avcodec.h"
00028
00029 #include "avfilter.h"
00030 #include "internal.h"
00031 #include "audio.h"
00032 #include "avcodec.h"
00033
00034 void ff_avfilter_default_free_buffer(AVFilterBuffer *ptr)
00035 {
00036 if (ptr->extended_data != ptr->data)
00037 av_freep(&ptr->extended_data);
00038 av_free(ptr->data[0]);
00039 av_free(ptr);
00040 }
00041
00042 static void copy_video_props(AVFilterBufferRefVideoProps *dst, AVFilterBufferRefVideoProps *src) {
00043 *dst = *src;
00044 if (src->qp_table) {
00045 int qsize = src->qp_table_size;
00046 dst->qp_table = av_malloc(qsize);
00047 memcpy(dst->qp_table, src->qp_table, qsize);
00048 }
00049 }
00050
00051 AVFilterBufferRef *avfilter_ref_buffer(AVFilterBufferRef *ref, int pmask)
00052 {
00053 AVFilterBufferRef *ret = av_malloc(sizeof(AVFilterBufferRef));
00054 if (!ret)
00055 return NULL;
00056 *ret = *ref;
00057
00058 ret->metadata = NULL;
00059 av_dict_copy(&ret->metadata, ref->metadata, 0);
00060
00061 if (ref->type == AVMEDIA_TYPE_VIDEO) {
00062 ret->video = av_malloc(sizeof(AVFilterBufferRefVideoProps));
00063 if (!ret->video) {
00064 av_free(ret);
00065 return NULL;
00066 }
00067 copy_video_props(ret->video, ref->video);
00068 ret->extended_data = ret->data;
00069 } else if (ref->type == AVMEDIA_TYPE_AUDIO) {
00070 ret->audio = av_malloc(sizeof(AVFilterBufferRefAudioProps));
00071 if (!ret->audio) {
00072 av_free(ret);
00073 return NULL;
00074 }
00075 *ret->audio = *ref->audio;
00076
00077 if (ref->extended_data && ref->extended_data != ref->data) {
00078 int nb_channels = av_get_channel_layout_nb_channels(ref->audio->channel_layout);
00079 if (!(ret->extended_data = av_malloc(sizeof(*ret->extended_data) *
00080 nb_channels))) {
00081 av_freep(&ret->audio);
00082 av_freep(&ret);
00083 return NULL;
00084 }
00085 memcpy(ret->extended_data, ref->extended_data,
00086 sizeof(*ret->extended_data) * nb_channels);
00087 } else
00088 ret->extended_data = ret->data;
00089 }
00090 ret->perms &= pmask;
00091 ret->buf->refcount ++;
00092 return ret;
00093 }
00094
00095 void ff_free_pool(AVFilterPool *pool)
00096 {
00097 int i;
00098
00099 av_assert0(pool->refcount > 0);
00100
00101 for (i = 0; i < POOL_SIZE; i++) {
00102 if (pool->pic[i]) {
00103 AVFilterBufferRef *picref = pool->pic[i];
00104
00105
00106 av_assert0(!picref->buf->refcount);
00107 av_freep(&picref->buf->data[0]);
00108 av_freep(&picref->buf);
00109
00110 av_freep(&picref->audio);
00111 av_assert0(!picref->video || !picref->video->qp_table);
00112 av_freep(&picref->video);
00113 av_freep(&pool->pic[i]);
00114 pool->count--;
00115 }
00116 }
00117 pool->draining = 1;
00118
00119 if (!--pool->refcount) {
00120 av_assert0(!pool->count);
00121 av_free(pool);
00122 }
00123 }
00124
00125 static void store_in_pool(AVFilterBufferRef *ref)
00126 {
00127 int i;
00128 AVFilterPool *pool= ref->buf->priv;
00129
00130 av_assert0(ref->buf->data[0]);
00131 av_assert0(pool->refcount>0);
00132
00133 if (ref->video)
00134 av_freep(&ref->video->qp_table);
00135
00136 if (pool->count == POOL_SIZE) {
00137 AVFilterBufferRef *ref1 = pool->pic[0];
00138 av_freep(&ref1->video);
00139 av_freep(&ref1->audio);
00140 av_freep(&ref1->buf->data[0]);
00141 av_freep(&ref1->buf);
00142 av_free(ref1);
00143 memmove(&pool->pic[0], &pool->pic[1], sizeof(void*)*(POOL_SIZE-1));
00144 pool->count--;
00145 pool->pic[POOL_SIZE-1] = NULL;
00146 }
00147
00148 for (i = 0; i < POOL_SIZE; i++) {
00149 if (!pool->pic[i]) {
00150 pool->pic[i] = ref;
00151 pool->count++;
00152 break;
00153 }
00154 }
00155 if (pool->draining) {
00156 ff_free_pool(pool);
00157 } else
00158 --pool->refcount;
00159 }
00160
00161 void avfilter_unref_buffer(AVFilterBufferRef *ref)
00162 {
00163 if (!ref)
00164 return;
00165 av_assert0(ref->buf->refcount > 0);
00166 if (!(--ref->buf->refcount)) {
00167 if (!ref->buf->free) {
00168 store_in_pool(ref);
00169 return;
00170 }
00171 ref->buf->free(ref->buf);
00172 }
00173 if (ref->extended_data != ref->data)
00174 av_freep(&ref->extended_data);
00175 if (ref->video)
00176 av_freep(&ref->video->qp_table);
00177 av_freep(&ref->video);
00178 av_freep(&ref->audio);
00179 av_dict_free(&ref->metadata);
00180 av_free(ref);
00181 }
00182
00183 void avfilter_unref_bufferp(AVFilterBufferRef **ref)
00184 {
00185 avfilter_unref_buffer(*ref);
00186 *ref = NULL;
00187 }
00188
00189 void avfilter_copy_buffer_ref_props(AVFilterBufferRef *dst, AVFilterBufferRef *src)
00190 {
00191
00192 dst->pts = src->pts;
00193 dst->pos = src->pos;
00194
00195 switch (src->type) {
00196 case AVMEDIA_TYPE_VIDEO: {
00197 if (dst->video->qp_table)
00198 av_freep(&dst->video->qp_table);
00199 copy_video_props(dst->video, src->video);
00200 break;
00201 }
00202 case AVMEDIA_TYPE_AUDIO: *dst->audio = *src->audio; break;
00203 default: break;
00204 }
00205
00206 av_dict_free(&dst->metadata);
00207 av_dict_copy(&dst->metadata, src->metadata, 0);
00208 }
00209
00210 AVFilterBufferRef *ff_copy_buffer_ref(AVFilterLink *outlink,
00211 AVFilterBufferRef *ref)
00212 {
00213 AVFilterBufferRef *buf;
00214 int channels;
00215
00216 switch (outlink->type) {
00217
00218 case AVMEDIA_TYPE_VIDEO:
00219 buf = ff_get_video_buffer(outlink, AV_PERM_WRITE,
00220 ref->video->w, ref->video->h);
00221 if(!buf)
00222 return NULL;
00223 av_image_copy(buf->data, buf->linesize,
00224 (void*)ref->data, ref->linesize,
00225 ref->format, ref->video->w, ref->video->h);
00226 break;
00227
00228 case AVMEDIA_TYPE_AUDIO:
00229 buf = ff_get_audio_buffer(outlink, AV_PERM_WRITE,
00230 ref->audio->nb_samples);
00231 if(!buf)
00232 return NULL;
00233 channels = ref->audio->channels;
00234 av_samples_copy(buf->extended_data, ref->buf->extended_data,
00235 0, 0, ref->audio->nb_samples,
00236 channels,
00237 ref->format);
00238 break;
00239
00240 default:
00241 return NULL;
00242 }
00243 avfilter_copy_buffer_ref_props(buf, ref);
00244 return buf;
00245 }