1/* 2 * filter layer 3 * copyright (c) 2007 Bobby Bingham 4 * 5 * This file is part of FFmpeg. 6 * 7 * FFmpeg is free software; you can redistribute it and/or 8 * modify it under the terms of the GNU Lesser General Public 9 * License as published by the Free Software Foundation; either 10 * version 2.1 of the License, or (at your option) any later version. 11 * 12 * FFmpeg is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 * Lesser General Public License for more details. 16 * 17 * You should have received a copy of the GNU Lesser General Public 18 * License along with FFmpeg; if not, write to the Free Software 19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 20 */ 21 22/* #define DEBUG */ 23 24#include "libavcodec/imgconvert.h" 25#include "libavutil/pixdesc.h" 26#include "avfilter.h" 27 28unsigned avfilter_version(void) { 29 return LIBAVFILTER_VERSION_INT; 30} 31 32const char *avfilter_configuration(void) 33{ 34 return FFMPEG_CONFIGURATION; 35} 36 37const char *avfilter_license(void) 38{ 39#define LICENSE_PREFIX "libavfilter license: " 40 return LICENSE_PREFIX FFMPEG_LICENSE + sizeof(LICENSE_PREFIX) - 1; 41} 42 43/** helper macros to get the in/out pad on the dst/src filter */ 44#define link_dpad(link) link->dst-> input_pads[link->dstpad] 45#define link_spad(link) link->src->output_pads[link->srcpad] 46 47AVFilterPicRef *avfilter_ref_pic(AVFilterPicRef *ref, int pmask) 48{ 49 AVFilterPicRef *ret = av_malloc(sizeof(AVFilterPicRef)); 50 *ret = *ref; 51 ret->perms &= pmask; 52 ret->pic->refcount ++; 53 return ret; 54} 55 56void avfilter_unref_pic(AVFilterPicRef *ref) 57{ 58 if(!(--ref->pic->refcount)) 59 ref->pic->free(ref->pic); 60 av_free(ref); 61} 62 63void avfilter_insert_pad(unsigned idx, unsigned *count, size_t padidx_off, 64 AVFilterPad **pads, AVFilterLink ***links, 65 AVFilterPad *newpad) 66{ 67 unsigned i; 68 69 idx = FFMIN(idx, *count); 70 71 *pads = av_realloc(*pads, sizeof(AVFilterPad) * (*count + 1)); 72 *links = av_realloc(*links, sizeof(AVFilterLink*) * (*count + 1)); 73 memmove(*pads +idx+1, *pads +idx, sizeof(AVFilterPad) * (*count-idx)); 74 memmove(*links+idx+1, *links+idx, sizeof(AVFilterLink*) * (*count-idx)); 75 memcpy(*pads+idx, newpad, sizeof(AVFilterPad)); 76 (*links)[idx] = NULL; 77 78 (*count) ++; 79 for(i = idx+1; i < *count; i ++) 80 if(*links[i]) 81 (*(unsigned *)((uint8_t *) *links[i] + padidx_off)) ++; 82} 83 84int avfilter_link(AVFilterContext *src, unsigned srcpad, 85 AVFilterContext *dst, unsigned dstpad) 86{ 87 AVFilterLink *link; 88 89 if(src->output_count <= srcpad || dst->input_count <= dstpad || 90 src->outputs[srcpad] || dst->inputs[dstpad]) 91 return -1; 92 93 src->outputs[srcpad] = 94 dst-> inputs[dstpad] = link = av_mallocz(sizeof(AVFilterLink)); 95 96 link->src = src; 97 link->dst = dst; 98 link->srcpad = srcpad; 99 link->dstpad = dstpad; 100 link->format = PIX_FMT_NONE; 101 102 return 0; 103} 104 105int avfilter_insert_filter(AVFilterLink *link, AVFilterContext *filt, 106 unsigned in, unsigned out) 107{ 108 av_log(link->dst, AV_LOG_INFO, "auto-inserting filter '%s' " 109 "between the filter '%s' and the filter '%s'\n", 110 filt->name, link->src->name, link->dst->name); 111 112 link->dst->inputs[link->dstpad] = NULL; 113 if(avfilter_link(filt, out, link->dst, link->dstpad)) { 114 /* failed to link output filter to new filter */ 115 link->dst->inputs[link->dstpad] = link; 116 return -1; 117 } 118 119 /* re-hookup the link to the new destination filter we inserted */ 120 link->dst = filt; 121 link->dstpad = in; 122 filt->inputs[in] = link; 123 124 /* if any information on supported colorspaces already exists on the 125 * link, we need to preserve that */ 126 if(link->out_formats) 127 avfilter_formats_changeref(&link->out_formats, 128 &filt->outputs[out]->out_formats); 129 130 return 0; 131} 132 133int avfilter_config_links(AVFilterContext *filter) 134{ 135 int (*config_link)(AVFilterLink *); 136 unsigned i; 137 138 for(i = 0; i < filter->input_count; i ++) { 139 AVFilterLink *link = filter->inputs[i]; 140 141 if(!link) continue; 142 143 switch(link->init_state) { 144 case AVLINK_INIT: 145 continue; 146 case AVLINK_STARTINIT: 147 av_log(filter, AV_LOG_INFO, "circular filter chain detected\n"); 148 return 0; 149 case AVLINK_UNINIT: 150 link->init_state = AVLINK_STARTINIT; 151 152 if(avfilter_config_links(link->src)) 153 return -1; 154 155 if(!(config_link = link_spad(link).config_props)) 156 config_link = avfilter_default_config_output_link; 157 if(config_link(link)) 158 return -1; 159 160 if((config_link = link_dpad(link).config_props)) 161 if(config_link(link)) 162 return -1; 163 164 link->init_state = AVLINK_INIT; 165 } 166 } 167 168 return 0; 169} 170 171static void dprintf_picref(void *ctx, AVFilterPicRef *picref, int end) 172{ 173 dprintf(ctx, 174 "picref[%p data[%p, %p, %p, %p] linesize[%d, %d, %d, %d] pts:%"PRId64" pos:%"PRId64" a:%d/%d s:%dx%d]%s", 175 picref, 176 picref->data [0], picref->data [1], picref->data [2], picref->data [3], 177 picref->linesize[0], picref->linesize[1], picref->linesize[2], picref->linesize[3], 178 picref->pts, picref->pos, 179 picref->pixel_aspect.num, picref->pixel_aspect.den, picref->w, picref->h, 180 end ? "\n" : ""); 181} 182 183static void dprintf_link(void *ctx, AVFilterLink *link, int end) 184{ 185 dprintf(ctx, 186 "link[%p s:%dx%d fmt:%-16s %-16s->%-16s]%s", 187 link, link->w, link->h, 188 av_pix_fmt_descriptors[link->format].name, 189 link->src ? link->src->filter->name : "", 190 link->dst ? link->dst->filter->name : "", 191 end ? "\n" : ""); 192} 193 194#define DPRINTF_START(ctx, func) dprintf(NULL, "%-16s: ", #func) 195 196AVFilterPicRef *avfilter_get_video_buffer(AVFilterLink *link, int perms, int w, int h) 197{ 198 AVFilterPicRef *ret = NULL; 199 200 DPRINTF_START(NULL, get_video_buffer); dprintf_link(NULL, link, 0); dprintf(NULL, " perms:%d w:%d h:%d\n", perms, w, h); 201 202 if(link_dpad(link).get_video_buffer) 203 ret = link_dpad(link).get_video_buffer(link, perms, w, h); 204 205 if(!ret) 206 ret = avfilter_default_get_video_buffer(link, perms, w, h); 207 208 DPRINTF_START(NULL, get_video_buffer); dprintf_link(NULL, link, 0); dprintf(NULL, " returning "); dprintf_picref(NULL, ret, 1); 209 210 return ret; 211} 212 213int avfilter_request_frame(AVFilterLink *link) 214{ 215 DPRINTF_START(NULL, request_frame); dprintf_link(NULL, link, 1); 216 217 if(link_spad(link).request_frame) 218 return link_spad(link).request_frame(link); 219 else if(link->src->inputs[0]) 220 return avfilter_request_frame(link->src->inputs[0]); 221 else return -1; 222} 223 224int avfilter_poll_frame(AVFilterLink *link) 225{ 226 int i, min=INT_MAX; 227 228 if(link_spad(link).poll_frame) 229 return link_spad(link).poll_frame(link); 230 231 for (i=0; i<link->src->input_count; i++) { 232 int val; 233 if(!link->src->inputs[i]) 234 return -1; 235 val = avfilter_poll_frame(link->src->inputs[i]); 236 min = FFMIN(min, val); 237 } 238 239 return min; 240} 241 242/* XXX: should we do the duplicating of the picture ref here, instead of 243 * forcing the source filter to do it? */ 244void avfilter_start_frame(AVFilterLink *link, AVFilterPicRef *picref) 245{ 246 void (*start_frame)(AVFilterLink *, AVFilterPicRef *); 247 AVFilterPad *dst = &link_dpad(link); 248 249 DPRINTF_START(NULL, start_frame); dprintf_link(NULL, link, 0); dprintf(NULL, " "); dprintf_picref(NULL, picref, 1); 250 251 if(!(start_frame = dst->start_frame)) 252 start_frame = avfilter_default_start_frame; 253 254 /* prepare to copy the picture if it has insufficient permissions */ 255 if((dst->min_perms & picref->perms) != dst->min_perms || 256 dst->rej_perms & picref->perms) { 257 /* 258 av_log(link->dst, AV_LOG_INFO, 259 "frame copy needed (have perms %x, need %x, reject %x)\n", 260 picref->perms, 261 link_dpad(link).min_perms, link_dpad(link).rej_perms); 262 */ 263 264 link->cur_pic = avfilter_default_get_video_buffer(link, dst->min_perms, link->w, link->h); 265 link->srcpic = picref; 266 link->cur_pic->pts = link->srcpic->pts; 267 link->cur_pic->pos = link->srcpic->pos; 268 link->cur_pic->pixel_aspect = link->srcpic->pixel_aspect; 269 } 270 else 271 link->cur_pic = picref; 272 273 start_frame(link, link->cur_pic); 274} 275 276void avfilter_end_frame(AVFilterLink *link) 277{ 278 void (*end_frame)(AVFilterLink *); 279 280 if(!(end_frame = link_dpad(link).end_frame)) 281 end_frame = avfilter_default_end_frame; 282 283 end_frame(link); 284 285 /* unreference the source picture if we're feeding the destination filter 286 * a copied version dues to permission issues */ 287 if(link->srcpic) { 288 avfilter_unref_pic(link->srcpic); 289 link->srcpic = NULL; 290 } 291 292} 293 294void avfilter_draw_slice(AVFilterLink *link, int y, int h, int slice_dir) 295{ 296 uint8_t *src[4], *dst[4]; 297 int i, j, vsub; 298 void (*draw_slice)(AVFilterLink *, int, int, int); 299 300 DPRINTF_START(NULL, draw_slice); dprintf_link(NULL, link, 0); dprintf(NULL, " y:%d h:%d dir:%d\n", y, h, slice_dir); 301 302 /* copy the slice if needed for permission reasons */ 303 if(link->srcpic) { 304 vsub = av_pix_fmt_descriptors[link->format].log2_chroma_h; 305 306 for(i = 0; i < 4; i ++) { 307 if(link->srcpic->data[i]) { 308 src[i] = link->srcpic-> data[i] + 309 (y >> (i==0 ? 0 : vsub)) * link->srcpic-> linesize[i]; 310 dst[i] = link->cur_pic->data[i] + 311 (y >> (i==0 ? 0 : vsub)) * link->cur_pic->linesize[i]; 312 } else 313 src[i] = dst[i] = NULL; 314 } 315 316 for(i = 0; i < 4; i ++) { 317 int planew = 318 ff_get_plane_bytewidth(link->format, link->cur_pic->w, i); 319 320 if(!src[i]) continue; 321 322 for(j = 0; j < h >> (i==0 ? 0 : vsub); j ++) { 323 memcpy(dst[i], src[i], planew); 324 src[i] += link->srcpic ->linesize[i]; 325 dst[i] += link->cur_pic->linesize[i]; 326 } 327 } 328 } 329 330 if(!(draw_slice = link_dpad(link).draw_slice)) 331 draw_slice = avfilter_default_draw_slice; 332 draw_slice(link, y, h, slice_dir); 333} 334 335#define MAX_REGISTERED_AVFILTERS_NB 64 336 337static AVFilter *registered_avfilters[MAX_REGISTERED_AVFILTERS_NB + 1]; 338 339static int next_registered_avfilter_idx = 0; 340 341AVFilter *avfilter_get_by_name(const char *name) 342{ 343 int i; 344 345 for (i = 0; registered_avfilters[i]; i++) 346 if (!strcmp(registered_avfilters[i]->name, name)) 347 return registered_avfilters[i]; 348 349 return NULL; 350} 351 352int avfilter_register(AVFilter *filter) 353{ 354 if (next_registered_avfilter_idx == MAX_REGISTERED_AVFILTERS_NB) 355 return -1; 356 357 registered_avfilters[next_registered_avfilter_idx++] = filter; 358 return 0; 359} 360 361AVFilter **av_filter_next(AVFilter **filter) 362{ 363 return filter ? ++filter : ®istered_avfilters[0]; 364} 365 366void avfilter_uninit(void) 367{ 368 memset(registered_avfilters, 0, sizeof(registered_avfilters)); 369 next_registered_avfilter_idx = 0; 370} 371 372static int pad_count(const AVFilterPad *pads) 373{ 374 int count; 375 376 for(count = 0; pads->name; count ++) pads ++; 377 return count; 378} 379 380static const char *filter_name(void *p) 381{ 382 AVFilterContext *filter = p; 383 return filter->filter->name; 384} 385 386static const AVClass avfilter_class = { 387 "AVFilter", 388 filter_name, 389 NULL, 390 LIBAVUTIL_VERSION_INT, 391}; 392 393AVFilterContext *avfilter_open(AVFilter *filter, const char *inst_name) 394{ 395 AVFilterContext *ret; 396 397 if (!filter) 398 return 0; 399 400 ret = av_mallocz(sizeof(AVFilterContext)); 401 402 ret->av_class = &avfilter_class; 403 ret->filter = filter; 404 ret->name = inst_name ? av_strdup(inst_name) : NULL; 405 ret->priv = av_mallocz(filter->priv_size); 406 407 ret->input_count = pad_count(filter->inputs); 408 if (ret->input_count) { 409 ret->input_pads = av_malloc(sizeof(AVFilterPad) * ret->input_count); 410 memcpy(ret->input_pads, filter->inputs, sizeof(AVFilterPad) * ret->input_count); 411 ret->inputs = av_mallocz(sizeof(AVFilterLink*) * ret->input_count); 412 } 413 414 ret->output_count = pad_count(filter->outputs); 415 if (ret->output_count) { 416 ret->output_pads = av_malloc(sizeof(AVFilterPad) * ret->output_count); 417 memcpy(ret->output_pads, filter->outputs, sizeof(AVFilterPad) * ret->output_count); 418 ret->outputs = av_mallocz(sizeof(AVFilterLink*) * ret->output_count); 419 } 420 421 return ret; 422} 423 424void avfilter_destroy(AVFilterContext *filter) 425{ 426 int i; 427 428 if(filter->filter->uninit) 429 filter->filter->uninit(filter); 430 431 for(i = 0; i < filter->input_count; i ++) { 432 if(filter->inputs[i]) 433 filter->inputs[i]->src->outputs[filter->inputs[i]->srcpad] = NULL; 434 av_freep(&filter->inputs[i]); 435 } 436 for(i = 0; i < filter->output_count; i ++) { 437 if(filter->outputs[i]) 438 filter->outputs[i]->dst->inputs[filter->outputs[i]->dstpad] = NULL; 439 av_freep(&filter->outputs[i]); 440 } 441 442 av_freep(&filter->name); 443 av_freep(&filter->input_pads); 444 av_freep(&filter->output_pads); 445 av_freep(&filter->inputs); 446 av_freep(&filter->outputs); 447 av_freep(&filter->priv); 448 av_free(filter); 449} 450 451int avfilter_init_filter(AVFilterContext *filter, const char *args, void *opaque) 452{ 453 int ret=0; 454 455 if(filter->filter->init) 456 ret = filter->filter->init(filter, args, opaque); 457 return ret; 458} 459 460