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/imgutils.h"
00024
00025 #include "avfilter.h"
00026 #include "internal.h"
00027 #include "video.h"
00028
00029 static char *ff_get_ref_perms_string(char *buf, size_t buf_size, int perms)
00030 {
00031 snprintf(buf, buf_size, "%s%s%s%s%s%s",
00032 perms & AV_PERM_READ ? "r" : "",
00033 perms & AV_PERM_WRITE ? "w" : "",
00034 perms & AV_PERM_PRESERVE ? "p" : "",
00035 perms & AV_PERM_REUSE ? "u" : "",
00036 perms & AV_PERM_REUSE2 ? "U" : "",
00037 perms & AV_PERM_NEG_LINESIZES ? "n" : "");
00038 return buf;
00039 }
00040
00041 static void ff_dlog_ref(void *ctx, AVFilterBufferRef *ref, int end)
00042 {
00043 av_unused char buf[16];
00044 av_dlog(ctx,
00045 "ref[%p buf:%p refcount:%d perms:%s data:%p linesize[%d, %d, %d, %d] pts:%"PRId64" pos:%"PRId64,
00046 ref, ref->buf, ref->buf->refcount, ff_get_ref_perms_string(buf, sizeof(buf), ref->perms), ref->data[0],
00047 ref->linesize[0], ref->linesize[1], ref->linesize[2], ref->linesize[3],
00048 ref->pts, ref->pos);
00049
00050 if (ref->video) {
00051 av_dlog(ctx, " a:%d/%d s:%dx%d i:%c iskey:%d type:%c",
00052 ref->video->sample_aspect_ratio.num, ref->video->sample_aspect_ratio.den,
00053 ref->video->w, ref->video->h,
00054 !ref->video->interlaced ? 'P' :
00055 ref->video->top_field_first ? 'T' : 'B',
00056 ref->video->key_frame,
00057 av_get_picture_type_char(ref->video->pict_type));
00058 }
00059 if (ref->audio) {
00060 av_dlog(ctx, " cl:%"PRId64"d n:%d r:%d",
00061 ref->audio->channel_layout,
00062 ref->audio->nb_samples,
00063 ref->audio->sample_rate);
00064 }
00065
00066 av_dlog(ctx, "]%s", end ? "\n" : "");
00067 }
00068
00069 AVFilterBufferRef *ff_null_get_video_buffer(AVFilterLink *link, int perms, int w, int h)
00070 {
00071 return avfilter_get_video_buffer(link->dst->outputs[0], perms, w, h);
00072 }
00073
00074 AVFilterBufferRef *ff_default_get_video_buffer(AVFilterLink *link, int perms, int w, int h)
00075 {
00076 int linesize[4];
00077 uint8_t *data[4];
00078 int i;
00079 AVFilterBufferRef *picref = NULL;
00080 AVFilterPool *pool = link->pool;
00081
00082 if (pool) {
00083 for (i = 0; i < POOL_SIZE; i++) {
00084 picref = pool->pic[i];
00085 if (picref && picref->buf->format == link->format && picref->buf->w == w && picref->buf->h == h) {
00086 AVFilterBuffer *pic = picref->buf;
00087 pool->pic[i] = NULL;
00088 pool->count--;
00089 picref->video->w = w;
00090 picref->video->h = h;
00091 picref->perms = perms | AV_PERM_READ;
00092 picref->format = link->format;
00093 pic->refcount = 1;
00094 memcpy(picref->data, pic->data, sizeof(picref->data));
00095 memcpy(picref->linesize, pic->linesize, sizeof(picref->linesize));
00096 pool->refcount++;
00097 return picref;
00098 }
00099 }
00100 } else {
00101 pool = link->pool = av_mallocz(sizeof(AVFilterPool));
00102 pool->refcount = 1;
00103 }
00104
00105
00106 if ((i = av_image_alloc(data, linesize, w, h, link->format, 32)) < 0)
00107 return NULL;
00108
00109 picref = avfilter_get_video_buffer_ref_from_arrays(data, linesize,
00110 perms, w, h, link->format);
00111 if (!picref) {
00112 av_free(data[0]);
00113 return NULL;
00114 }
00115
00116 memset(data[0], 128, i);
00117
00118 picref->buf->priv = pool;
00119 picref->buf->free = NULL;
00120 pool->refcount++;
00121
00122 return picref;
00123 }
00124
00125 AVFilterBufferRef *
00126 avfilter_get_video_buffer_ref_from_arrays(uint8_t * const data[4], const int linesize[4], int perms,
00127 int w, int h, enum PixelFormat format)
00128 {
00129 AVFilterBuffer *pic = av_mallocz(sizeof(AVFilterBuffer));
00130 AVFilterBufferRef *picref = av_mallocz(sizeof(AVFilterBufferRef));
00131
00132 if (!pic || !picref)
00133 goto fail;
00134
00135 picref->buf = pic;
00136 picref->buf->free = ff_avfilter_default_free_buffer;
00137 if (!(picref->video = av_mallocz(sizeof(AVFilterBufferRefVideoProps))))
00138 goto fail;
00139
00140 pic->w = picref->video->w = w;
00141 pic->h = picref->video->h = h;
00142
00143
00144 picref->perms = perms | AV_PERM_READ;
00145
00146 pic->refcount = 1;
00147 picref->type = AVMEDIA_TYPE_VIDEO;
00148 pic->format = picref->format = format;
00149
00150 memcpy(pic->data, data, 4*sizeof(data[0]));
00151 memcpy(pic->linesize, linesize, 4*sizeof(linesize[0]));
00152 memcpy(picref->data, pic->data, sizeof(picref->data));
00153 memcpy(picref->linesize, pic->linesize, sizeof(picref->linesize));
00154
00155 pic-> extended_data = pic->data;
00156 picref->extended_data = picref->data;
00157
00158 picref->pts = AV_NOPTS_VALUE;
00159
00160 return picref;
00161
00162 fail:
00163 if (picref && picref->video)
00164 av_free(picref->video);
00165 av_free(picref);
00166 av_free(pic);
00167 return NULL;
00168 }
00169
00170 AVFilterBufferRef *avfilter_get_video_buffer(AVFilterLink *link, int perms, int w, int h)
00171 {
00172 AVFilterBufferRef *ret = NULL;
00173
00174 av_unused char buf[16];
00175 FF_DPRINTF_START(NULL, get_video_buffer); ff_dlog_link(NULL, link, 0);
00176 av_dlog(NULL, " perms:%s w:%d h:%d\n", ff_get_ref_perms_string(buf, sizeof(buf), perms), w, h);
00177
00178 if (link->dstpad->get_video_buffer)
00179 ret = link->dstpad->get_video_buffer(link, perms, w, h);
00180
00181 if (!ret)
00182 ret = ff_default_get_video_buffer(link, perms, w, h);
00183
00184 if (ret)
00185 ret->type = AVMEDIA_TYPE_VIDEO;
00186
00187 FF_DPRINTF_START(NULL, get_video_buffer); ff_dlog_link(NULL, link, 0); av_dlog(NULL, " returning "); ff_dlog_ref(NULL, ret, 1);
00188
00189 return ret;
00190 }
00191
00192 void ff_null_start_frame(AVFilterLink *link, AVFilterBufferRef *picref)
00193 {
00194 avfilter_start_frame(link->dst->outputs[0], picref);
00195 }
00196
00197 static void default_start_frame(AVFilterLink *inlink, AVFilterBufferRef *picref)
00198 {
00199 AVFilterLink *outlink = NULL;
00200
00201 if (inlink->dst->output_count)
00202 outlink = inlink->dst->outputs[0];
00203
00204 if (outlink) {
00205 outlink->out_buf = avfilter_get_video_buffer(outlink, AV_PERM_WRITE, outlink->w, outlink->h);
00206 avfilter_copy_buffer_ref_props(outlink->out_buf, picref);
00207 avfilter_start_frame(outlink, avfilter_ref_buffer(outlink->out_buf, ~0));
00208 }
00209 }
00210
00211
00212
00213 void avfilter_start_frame(AVFilterLink *link, AVFilterBufferRef *picref)
00214 {
00215 void (*start_frame)(AVFilterLink *, AVFilterBufferRef *);
00216 AVFilterPad *dst = link->dstpad;
00217 int perms = picref->perms;
00218 AVFilterCommand *cmd= link->dst->command_queue;
00219
00220 FF_DPRINTF_START(NULL, start_frame); ff_dlog_link(NULL, link, 0); av_dlog(NULL, " "); ff_dlog_ref(NULL, picref, 1);
00221
00222 if (!(start_frame = dst->start_frame))
00223 start_frame = default_start_frame;
00224
00225 if (picref->linesize[0] < 0)
00226 perms |= AV_PERM_NEG_LINESIZES;
00227
00228 if ((dst->min_perms & perms) != dst->min_perms || dst->rej_perms & perms) {
00229 av_log(link->dst, AV_LOG_DEBUG,
00230 "frame copy needed (have perms %x, need %x, reject %x)\n",
00231 picref->perms,
00232 link->dstpad->min_perms, link->dstpad->rej_perms);
00233
00234 link->cur_buf = avfilter_get_video_buffer(link, dst->min_perms, link->w, link->h);
00235 link->src_buf = picref;
00236 avfilter_copy_buffer_ref_props(link->cur_buf, link->src_buf);
00237
00238
00239 if (av_pix_fmt_descriptors[link->format].flags & PIX_FMT_PAL)
00240 memcpy(link->cur_buf->data[1], link->src_buf-> data[1], AVPALETTE_SIZE);
00241 }
00242 else
00243 link->cur_buf = picref;
00244
00245 while(cmd && cmd->time <= picref->pts * av_q2d(link->time_base)){
00246 av_log(link->dst, AV_LOG_DEBUG,
00247 "Processing command time:%f command:%s arg:%s\n",
00248 cmd->time, cmd->command, cmd->arg);
00249 avfilter_process_command(link->dst, cmd->command, cmd->arg, 0, 0, cmd->flags);
00250 ff_command_queue_pop(link->dst);
00251 cmd= link->dst->command_queue;
00252 }
00253
00254 start_frame(link, link->cur_buf);
00255 ff_update_link_current_pts(link, link->cur_buf->pts);
00256 }
00257
00258 void ff_null_end_frame(AVFilterLink *link)
00259 {
00260 avfilter_end_frame(link->dst->outputs[0]);
00261 }
00262
00263 static void default_end_frame(AVFilterLink *inlink)
00264 {
00265 AVFilterLink *outlink = NULL;
00266
00267 if (inlink->dst->output_count)
00268 outlink = inlink->dst->outputs[0];
00269
00270 avfilter_unref_buffer(inlink->cur_buf);
00271 inlink->cur_buf = NULL;
00272
00273 if (outlink) {
00274 if (outlink->out_buf) {
00275 avfilter_unref_buffer(outlink->out_buf);
00276 outlink->out_buf = NULL;
00277 }
00278 avfilter_end_frame(outlink);
00279 }
00280 }
00281
00282 void avfilter_end_frame(AVFilterLink *link)
00283 {
00284 void (*end_frame)(AVFilterLink *);
00285
00286 if (!(end_frame = link->dstpad->end_frame))
00287 end_frame = default_end_frame;
00288
00289 end_frame(link);
00290
00291
00292
00293 if (link->src_buf) {
00294 avfilter_unref_buffer(link->src_buf);
00295 link->src_buf = NULL;
00296 }
00297 }
00298
00299 void ff_null_draw_slice(AVFilterLink *link, int y, int h, int slice_dir)
00300 {
00301 avfilter_draw_slice(link->dst->outputs[0], y, h, slice_dir);
00302 }
00303
00304 static void default_draw_slice(AVFilterLink *inlink, int y, int h, int slice_dir)
00305 {
00306 AVFilterLink *outlink = NULL;
00307
00308 if (inlink->dst->output_count)
00309 outlink = inlink->dst->outputs[0];
00310
00311 if (outlink)
00312 avfilter_draw_slice(outlink, y, h, slice_dir);
00313 }
00314
00315 void avfilter_draw_slice(AVFilterLink *link, int y, int h, int slice_dir)
00316 {
00317 uint8_t *src[4], *dst[4];
00318 int i, j, vsub;
00319 void (*draw_slice)(AVFilterLink *, int, int, int);
00320
00321 FF_DPRINTF_START(NULL, draw_slice); ff_dlog_link(NULL, link, 0); av_dlog(NULL, " y:%d h:%d dir:%d\n", y, h, slice_dir);
00322
00323
00324 if (link->src_buf) {
00325 vsub = av_pix_fmt_descriptors[link->format].log2_chroma_h;
00326
00327 for (i = 0; i < 4; i++) {
00328 if (link->src_buf->data[i]) {
00329 src[i] = link->src_buf-> data[i] +
00330 (y >> (i==1 || i==2 ? vsub : 0)) * link->src_buf-> linesize[i];
00331 dst[i] = link->cur_buf->data[i] +
00332 (y >> (i==1 || i==2 ? vsub : 0)) * link->cur_buf->linesize[i];
00333 } else
00334 src[i] = dst[i] = NULL;
00335 }
00336
00337 for (i = 0; i < 4; i++) {
00338 int planew =
00339 av_image_get_linesize(link->format, link->cur_buf->video->w, i);
00340
00341 if (!src[i]) continue;
00342
00343 for (j = 0; j < h >> (i==1 || i==2 ? vsub : 0); j++) {
00344 memcpy(dst[i], src[i], planew);
00345 src[i] += link->src_buf->linesize[i];
00346 dst[i] += link->cur_buf->linesize[i];
00347 }
00348 }
00349 }
00350
00351 if (!(draw_slice = link->dstpad->draw_slice))
00352 draw_slice = default_draw_slice;
00353 draw_slice(link, y, h, slice_dir);
00354 }
00355
00356 #if FF_API_FILTERS_PUBLIC
00357 AVFilterBufferRef *avfilter_default_get_video_buffer(AVFilterLink *link, int perms, int w, int h)
00358 {
00359 return ff_default_get_video_buffer(link, perms, w, h);
00360 }
00361 void avfilter_default_start_frame(AVFilterLink *inlink, AVFilterBufferRef *picref)
00362 {
00363 default_start_frame(inlink, picref);
00364 }
00365 void avfilter_default_end_frame(AVFilterLink *inlink)
00366 {
00367 default_end_frame(inlink);
00368 }
00369 void avfilter_default_draw_slice(AVFilterLink *inlink, int y, int h, int slice_dir)
00370 {
00371 default_draw_slice(inlink, y, h, slice_dir);
00372 }
00373 AVFilterBufferRef *avfilter_null_get_video_buffer(AVFilterLink *link, int perms, int w, int h)
00374 {
00375 return ff_null_get_video_buffer(link, perms, w, h);
00376 }
00377 void avfilter_null_start_frame(AVFilterLink *link, AVFilterBufferRef *picref)
00378 {
00379 ff_null_start_frame(link, picref);
00380 }
00381 void avfilter_null_end_frame(AVFilterLink *link)
00382 {
00383 ff_null_end_frame(link);
00384 }
00385 void avfilter_null_draw_slice(AVFilterLink *link, int y, int h, int slice_dir)
00386 {
00387 ff_null_draw_slice(link, y, h, slice_dir);
00388 }
00389 #endif