• Main Page
  • Related Pages
  • Modules
  • Data Structures
  • Files
  • File List
  • Globals

libavfilter/avfilter.c

Go to the documentation of this file.
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 : &registered_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 

Generated on Fri Sep 16 2011 17:17:47 for FFmpeg by  doxygen 1.7.1