Libav
|
00001 /* 00002 * filter layer 00003 * copyright (c) 2007 Bobby Bingham 00004 * 00005 * This file is part of FFmpeg. 00006 * 00007 * FFmpeg 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 * FFmpeg 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 FFmpeg; if not, write to the Free Software 00019 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 00020 */ 00021 00022 /* #define DEBUG */ 00023 00024 #include "libavcodec/imgconvert.h" 00025 #include "libavutil/pixdesc.h" 00026 #include "avfilter.h" 00027 00028 unsigned avfilter_version(void) { 00029 return LIBAVFILTER_VERSION_INT; 00030 } 00031 00032 const char *avfilter_configuration(void) 00033 { 00034 return FFMPEG_CONFIGURATION; 00035 } 00036 00037 const char *avfilter_license(void) 00038 { 00039 #define LICENSE_PREFIX "libavfilter license: " 00040 return LICENSE_PREFIX FFMPEG_LICENSE + sizeof(LICENSE_PREFIX) - 1; 00041 } 00042 00044 #define link_dpad(link) link->dst-> input_pads[link->dstpad] 00045 #define link_spad(link) link->src->output_pads[link->srcpad] 00046 00047 AVFilterPicRef *avfilter_ref_pic(AVFilterPicRef *ref, int pmask) 00048 { 00049 AVFilterPicRef *ret = av_malloc(sizeof(AVFilterPicRef)); 00050 *ret = *ref; 00051 ret->perms &= pmask; 00052 ret->pic->refcount ++; 00053 return ret; 00054 } 00055 00056 void avfilter_unref_pic(AVFilterPicRef *ref) 00057 { 00058 if(!(--ref->pic->refcount)) 00059 ref->pic->free(ref->pic); 00060 av_free(ref); 00061 } 00062 00063 void avfilter_insert_pad(unsigned idx, unsigned *count, size_t padidx_off, 00064 AVFilterPad **pads, AVFilterLink ***links, 00065 AVFilterPad *newpad) 00066 { 00067 unsigned i; 00068 00069 idx = FFMIN(idx, *count); 00070 00071 *pads = av_realloc(*pads, sizeof(AVFilterPad) * (*count + 1)); 00072 *links = av_realloc(*links, sizeof(AVFilterLink*) * (*count + 1)); 00073 memmove(*pads +idx+1, *pads +idx, sizeof(AVFilterPad) * (*count-idx)); 00074 memmove(*links+idx+1, *links+idx, sizeof(AVFilterLink*) * (*count-idx)); 00075 memcpy(*pads+idx, newpad, sizeof(AVFilterPad)); 00076 (*links)[idx] = NULL; 00077 00078 (*count) ++; 00079 for(i = idx+1; i < *count; i ++) 00080 if(*links[i]) 00081 (*(unsigned *)((uint8_t *) *links[i] + padidx_off)) ++; 00082 } 00083 00084 int avfilter_link(AVFilterContext *src, unsigned srcpad, 00085 AVFilterContext *dst, unsigned dstpad) 00086 { 00087 AVFilterLink *link; 00088 00089 if(src->output_count <= srcpad || dst->input_count <= dstpad || 00090 src->outputs[srcpad] || dst->inputs[dstpad]) 00091 return -1; 00092 00093 src->outputs[srcpad] = 00094 dst-> inputs[dstpad] = link = av_mallocz(sizeof(AVFilterLink)); 00095 00096 link->src = src; 00097 link->dst = dst; 00098 link->srcpad = srcpad; 00099 link->dstpad = dstpad; 00100 link->format = PIX_FMT_NONE; 00101 00102 return 0; 00103 } 00104 00105 int avfilter_insert_filter(AVFilterLink *link, AVFilterContext *filt, 00106 unsigned in, unsigned out) 00107 { 00108 av_log(link->dst, AV_LOG_INFO, "auto-inserting filter '%s' " 00109 "between the filter '%s' and the filter '%s'\n", 00110 filt->name, link->src->name, link->dst->name); 00111 00112 link->dst->inputs[link->dstpad] = NULL; 00113 if(avfilter_link(filt, out, link->dst, link->dstpad)) { 00114 /* failed to link output filter to new filter */ 00115 link->dst->inputs[link->dstpad] = link; 00116 return -1; 00117 } 00118 00119 /* re-hookup the link to the new destination filter we inserted */ 00120 link->dst = filt; 00121 link->dstpad = in; 00122 filt->inputs[in] = link; 00123 00124 /* if any information on supported colorspaces already exists on the 00125 * link, we need to preserve that */ 00126 if(link->out_formats) 00127 avfilter_formats_changeref(&link->out_formats, 00128 &filt->outputs[out]->out_formats); 00129 00130 return 0; 00131 } 00132 00133 int avfilter_config_links(AVFilterContext *filter) 00134 { 00135 int (*config_link)(AVFilterLink *); 00136 unsigned i; 00137 00138 for(i = 0; i < filter->input_count; i ++) { 00139 AVFilterLink *link = filter->inputs[i]; 00140 00141 if(!link) continue; 00142 00143 switch(link->init_state) { 00144 case AVLINK_INIT: 00145 continue; 00146 case AVLINK_STARTINIT: 00147 av_log(filter, AV_LOG_INFO, "circular filter chain detected\n"); 00148 return 0; 00149 case AVLINK_UNINIT: 00150 link->init_state = AVLINK_STARTINIT; 00151 00152 if(avfilter_config_links(link->src)) 00153 return -1; 00154 00155 if(!(config_link = link_spad(link).config_props)) 00156 config_link = avfilter_default_config_output_link; 00157 if(config_link(link)) 00158 return -1; 00159 00160 if((config_link = link_dpad(link).config_props)) 00161 if(config_link(link)) 00162 return -1; 00163 00164 link->init_state = AVLINK_INIT; 00165 } 00166 } 00167 00168 return 0; 00169 } 00170 00171 static void dprintf_picref(void *ctx, AVFilterPicRef *picref, int end) 00172 { 00173 dprintf(ctx, 00174 "picref[%p data[%p, %p, %p, %p] linesize[%d, %d, %d, %d] pts:%"PRId64" pos:%"PRId64" a:%d/%d s:%dx%d]%s", 00175 picref, 00176 picref->data [0], picref->data [1], picref->data [2], picref->data [3], 00177 picref->linesize[0], picref->linesize[1], picref->linesize[2], picref->linesize[3], 00178 picref->pts, picref->pos, 00179 picref->pixel_aspect.num, picref->pixel_aspect.den, picref->w, picref->h, 00180 end ? "\n" : ""); 00181 } 00182 00183 static void dprintf_link(void *ctx, AVFilterLink *link, int end) 00184 { 00185 dprintf(ctx, 00186 "link[%p s:%dx%d fmt:%-16s %-16s->%-16s]%s", 00187 link, link->w, link->h, 00188 av_pix_fmt_descriptors[link->format].name, 00189 link->src ? link->src->filter->name : "", 00190 link->dst ? link->dst->filter->name : "", 00191 end ? "\n" : ""); 00192 } 00193 00194 #define DPRINTF_START(ctx, func) dprintf(NULL, "%-16s: ", #func) 00195 00196 AVFilterPicRef *avfilter_get_video_buffer(AVFilterLink *link, int perms, int w, int h) 00197 { 00198 AVFilterPicRef *ret = NULL; 00199 00200 DPRINTF_START(NULL, get_video_buffer); dprintf_link(NULL, link, 0); dprintf(NULL, " perms:%d w:%d h:%d\n", perms, w, h); 00201 00202 if(link_dpad(link).get_video_buffer) 00203 ret = link_dpad(link).get_video_buffer(link, perms, w, h); 00204 00205 if(!ret) 00206 ret = avfilter_default_get_video_buffer(link, perms, w, h); 00207 00208 DPRINTF_START(NULL, get_video_buffer); dprintf_link(NULL, link, 0); dprintf(NULL, " returning "); dprintf_picref(NULL, ret, 1); 00209 00210 return ret; 00211 } 00212 00213 int avfilter_request_frame(AVFilterLink *link) 00214 { 00215 DPRINTF_START(NULL, request_frame); dprintf_link(NULL, link, 1); 00216 00217 if(link_spad(link).request_frame) 00218 return link_spad(link).request_frame(link); 00219 else if(link->src->inputs[0]) 00220 return avfilter_request_frame(link->src->inputs[0]); 00221 else return -1; 00222 } 00223 00224 int avfilter_poll_frame(AVFilterLink *link) 00225 { 00226 int i, min=INT_MAX; 00227 00228 if(link_spad(link).poll_frame) 00229 return link_spad(link).poll_frame(link); 00230 00231 for (i=0; i<link->src->input_count; i++) { 00232 int val; 00233 if(!link->src->inputs[i]) 00234 return -1; 00235 val = avfilter_poll_frame(link->src->inputs[i]); 00236 min = FFMIN(min, val); 00237 } 00238 00239 return min; 00240 } 00241 00242 /* XXX: should we do the duplicating of the picture ref here, instead of 00243 * forcing the source filter to do it? */ 00244 void avfilter_start_frame(AVFilterLink *link, AVFilterPicRef *picref) 00245 { 00246 void (*start_frame)(AVFilterLink *, AVFilterPicRef *); 00247 AVFilterPad *dst = &link_dpad(link); 00248 00249 DPRINTF_START(NULL, start_frame); dprintf_link(NULL, link, 0); dprintf(NULL, " "); dprintf_picref(NULL, picref, 1); 00250 00251 if(!(start_frame = dst->start_frame)) 00252 start_frame = avfilter_default_start_frame; 00253 00254 /* prepare to copy the picture if it has insufficient permissions */ 00255 if((dst->min_perms & picref->perms) != dst->min_perms || 00256 dst->rej_perms & picref->perms) { 00257 /* 00258 av_log(link->dst, AV_LOG_INFO, 00259 "frame copy needed (have perms %x, need %x, reject %x)\n", 00260 picref->perms, 00261 link_dpad(link).min_perms, link_dpad(link).rej_perms); 00262 */ 00263 00264 link->cur_pic = avfilter_default_get_video_buffer(link, dst->min_perms, link->w, link->h); 00265 link->srcpic = picref; 00266 link->cur_pic->pts = link->srcpic->pts; 00267 link->cur_pic->pos = link->srcpic->pos; 00268 link->cur_pic->pixel_aspect = link->srcpic->pixel_aspect; 00269 } 00270 else 00271 link->cur_pic = picref; 00272 00273 start_frame(link, link->cur_pic); 00274 } 00275 00276 void avfilter_end_frame(AVFilterLink *link) 00277 { 00278 void (*end_frame)(AVFilterLink *); 00279 00280 if(!(end_frame = link_dpad(link).end_frame)) 00281 end_frame = avfilter_default_end_frame; 00282 00283 end_frame(link); 00284 00285 /* unreference the source picture if we're feeding the destination filter 00286 * a copied version dues to permission issues */ 00287 if(link->srcpic) { 00288 avfilter_unref_pic(link->srcpic); 00289 link->srcpic = NULL; 00290 } 00291 00292 } 00293 00294 void avfilter_draw_slice(AVFilterLink *link, int y, int h, int slice_dir) 00295 { 00296 uint8_t *src[4], *dst[4]; 00297 int i, j, vsub; 00298 void (*draw_slice)(AVFilterLink *, int, int, int); 00299 00300 DPRINTF_START(NULL, draw_slice); dprintf_link(NULL, link, 0); dprintf(NULL, " y:%d h:%d dir:%d\n", y, h, slice_dir); 00301 00302 /* copy the slice if needed for permission reasons */ 00303 if(link->srcpic) { 00304 vsub = av_pix_fmt_descriptors[link->format].log2_chroma_h; 00305 00306 for(i = 0; i < 4; i ++) { 00307 if(link->srcpic->data[i]) { 00308 src[i] = link->srcpic-> data[i] + 00309 (y >> (i==0 ? 0 : vsub)) * link->srcpic-> linesize[i]; 00310 dst[i] = link->cur_pic->data[i] + 00311 (y >> (i==0 ? 0 : vsub)) * link->cur_pic->linesize[i]; 00312 } else 00313 src[i] = dst[i] = NULL; 00314 } 00315 00316 for(i = 0; i < 4; i ++) { 00317 int planew = 00318 ff_get_plane_bytewidth(link->format, link->cur_pic->w, i); 00319 00320 if(!src[i]) continue; 00321 00322 for(j = 0; j < h >> (i==0 ? 0 : vsub); j ++) { 00323 memcpy(dst[i], src[i], planew); 00324 src[i] += link->srcpic ->linesize[i]; 00325 dst[i] += link->cur_pic->linesize[i]; 00326 } 00327 } 00328 } 00329 00330 if(!(draw_slice = link_dpad(link).draw_slice)) 00331 draw_slice = avfilter_default_draw_slice; 00332 draw_slice(link, y, h, slice_dir); 00333 } 00334 00335 #define MAX_REGISTERED_AVFILTERS_NB 64 00336 00337 static AVFilter *registered_avfilters[MAX_REGISTERED_AVFILTERS_NB + 1]; 00338 00339 static int next_registered_avfilter_idx = 0; 00340 00341 AVFilter *avfilter_get_by_name(const char *name) 00342 { 00343 int i; 00344 00345 for (i = 0; registered_avfilters[i]; i++) 00346 if (!strcmp(registered_avfilters[i]->name, name)) 00347 return registered_avfilters[i]; 00348 00349 return NULL; 00350 } 00351 00352 int avfilter_register(AVFilter *filter) 00353 { 00354 if (next_registered_avfilter_idx == MAX_REGISTERED_AVFILTERS_NB) 00355 return -1; 00356 00357 registered_avfilters[next_registered_avfilter_idx++] = filter; 00358 return 0; 00359 } 00360 00361 AVFilter **av_filter_next(AVFilter **filter) 00362 { 00363 return filter ? ++filter : ®istered_avfilters[0]; 00364 } 00365 00366 void avfilter_uninit(void) 00367 { 00368 memset(registered_avfilters, 0, sizeof(registered_avfilters)); 00369 next_registered_avfilter_idx = 0; 00370 } 00371 00372 static int pad_count(const AVFilterPad *pads) 00373 { 00374 int count; 00375 00376 for(count = 0; pads->name; count ++) pads ++; 00377 return count; 00378 } 00379 00380 static const char *filter_name(void *p) 00381 { 00382 AVFilterContext *filter = p; 00383 return filter->filter->name; 00384 } 00385 00386 static const AVClass avfilter_class = { 00387 "AVFilter", 00388 filter_name, 00389 NULL, 00390 LIBAVUTIL_VERSION_INT, 00391 }; 00392 00393 AVFilterContext *avfilter_open(AVFilter *filter, const char *inst_name) 00394 { 00395 AVFilterContext *ret; 00396 00397 if (!filter) 00398 return 0; 00399 00400 ret = av_mallocz(sizeof(AVFilterContext)); 00401 00402 ret->av_class = &avfilter_class; 00403 ret->filter = filter; 00404 ret->name = inst_name ? av_strdup(inst_name) : NULL; 00405 ret->priv = av_mallocz(filter->priv_size); 00406 00407 ret->input_count = pad_count(filter->inputs); 00408 if (ret->input_count) { 00409 ret->input_pads = av_malloc(sizeof(AVFilterPad) * ret->input_count); 00410 memcpy(ret->input_pads, filter->inputs, sizeof(AVFilterPad) * ret->input_count); 00411 ret->inputs = av_mallocz(sizeof(AVFilterLink*) * ret->input_count); 00412 } 00413 00414 ret->output_count = pad_count(filter->outputs); 00415 if (ret->output_count) { 00416 ret->output_pads = av_malloc(sizeof(AVFilterPad) * ret->output_count); 00417 memcpy(ret->output_pads, filter->outputs, sizeof(AVFilterPad) * ret->output_count); 00418 ret->outputs = av_mallocz(sizeof(AVFilterLink*) * ret->output_count); 00419 } 00420 00421 return ret; 00422 } 00423 00424 void avfilter_destroy(AVFilterContext *filter) 00425 { 00426 int i; 00427 00428 if(filter->filter->uninit) 00429 filter->filter->uninit(filter); 00430 00431 for(i = 0; i < filter->input_count; i ++) { 00432 if(filter->inputs[i]) 00433 filter->inputs[i]->src->outputs[filter->inputs[i]->srcpad] = NULL; 00434 av_freep(&filter->inputs[i]); 00435 } 00436 for(i = 0; i < filter->output_count; i ++) { 00437 if(filter->outputs[i]) 00438 filter->outputs[i]->dst->inputs[filter->outputs[i]->dstpad] = NULL; 00439 av_freep(&filter->outputs[i]); 00440 } 00441 00442 av_freep(&filter->name); 00443 av_freep(&filter->input_pads); 00444 av_freep(&filter->output_pads); 00445 av_freep(&filter->inputs); 00446 av_freep(&filter->outputs); 00447 av_freep(&filter->priv); 00448 av_free(filter); 00449 } 00450 00451 int avfilter_init_filter(AVFilterContext *filter, const char *args, void *opaque) 00452 { 00453 int ret=0; 00454 00455 if(filter->filter->init) 00456 ret = filter->filter->init(filter, args, opaque); 00457 return ret; 00458 } 00459