libavfilter/defaults.c
Go to the documentation of this file.
00001 /*
00002  * Filter layer - default implementations
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 #include "libavutil/avassert.h"
00023 #include "libavutil/audioconvert.h"
00024 #include "libavutil/imgutils.h"
00025 #include "libavutil/samplefmt.h"
00026 #include "avfilter.h"
00027 #include "internal.h"
00028 
00029 void ff_avfilter_default_free_buffer(AVFilterBuffer *ptr)
00030 {
00031     av_free(ptr->data[0]);
00032     av_free(ptr);
00033 }
00034 
00035 /* TODO: set the buffer's priv member to a context structure for the whole
00036  * filter chain.  This will allow for a buffer pool instead of the constant
00037  * alloc & free cycle currently implemented. */
00038 AVFilterBufferRef *avfilter_default_get_video_buffer(AVFilterLink *link, int perms, int w, int h)
00039 {
00040     int linesize[4];
00041     uint8_t *data[4];
00042     int i;
00043     AVFilterBufferRef *picref = NULL;
00044     AVFilterPool *pool = link->pool;
00045 
00046     if (pool) {
00047         for (i = 0; i < POOL_SIZE; i++) {
00048             picref = pool->pic[i];
00049             if (picref && picref->buf->format == link->format && picref->buf->w == w && picref->buf->h == h) {
00050                 AVFilterBuffer *pic = picref->buf;
00051                 pool->pic[i] = NULL;
00052                 pool->count--;
00053                 picref->video->w = w;
00054                 picref->video->h = h;
00055                 picref->perms = perms | AV_PERM_READ;
00056                 picref->format = link->format;
00057                 pic->refcount = 1;
00058                 memcpy(picref->data,     pic->data,     sizeof(picref->data));
00059                 memcpy(picref->linesize, pic->linesize, sizeof(picref->linesize));
00060                 pool->refcount++;
00061                 return picref;
00062             }
00063         }
00064     } else {
00065         pool = link->pool = av_mallocz(sizeof(AVFilterPool));
00066         pool->refcount = 1;
00067     }
00068 
00069     // align: +2 is needed for swscaler, +16 to be SIMD-friendly
00070     if ((i = av_image_alloc(data, linesize, w, h, link->format, 32)) < 0)
00071         return NULL;
00072 
00073     picref = avfilter_get_video_buffer_ref_from_arrays(data, linesize,
00074                                                        perms, w, h, link->format);
00075     if (!picref) {
00076         av_free(data[0]);
00077         return NULL;
00078     }
00079     memset(data[0], 128, i);
00080 
00081     picref->buf->priv = pool;
00082     picref->buf->free = NULL;
00083     pool->refcount++;
00084 
00085     return picref;
00086 }
00087 
00088 AVFilterBufferRef *avfilter_default_get_audio_buffer(AVFilterLink *link, int perms,
00089                                                      int nb_samples)
00090 {
00091     AVFilterBufferRef *samplesref = NULL;
00092     int linesize[8] = {0};
00093     uint8_t *data[8] = {0};
00094     int ch, nb_channels = av_get_channel_layout_nb_channels(link->channel_layout);
00095 
00096     /* right now we don't support more than 8 channels */
00097     av_assert0(nb_channels <= 8);
00098 
00099     /* Calculate total buffer size, round to multiple of 16 to be SIMD friendly */
00100     if (av_samples_alloc(data, linesize,
00101                          nb_channels, nb_samples,
00102                          av_get_alt_sample_fmt(link->format, link->planar),
00103                          16) < 0)
00104         return NULL;
00105 
00106     for (ch = 1; link->planar && ch < nb_channels; ch++)
00107         linesize[ch] = linesize[0];
00108     samplesref =
00109         avfilter_get_audio_buffer_ref_from_arrays(data, linesize, perms,
00110                                                   nb_samples, link->format,
00111                                                   link->channel_layout, link->planar);
00112     if (!samplesref) {
00113         av_free(data[0]);
00114         return NULL;
00115     }
00116 
00117     return samplesref;
00118 }
00119 
00120 void avfilter_default_start_frame(AVFilterLink *inlink, AVFilterBufferRef *picref)
00121 {
00122     AVFilterLink *outlink = NULL;
00123 
00124     if (inlink->dst->output_count)
00125         outlink = inlink->dst->outputs[0];
00126 
00127     if (outlink) {
00128         outlink->out_buf = avfilter_get_video_buffer(outlink, AV_PERM_WRITE, outlink->w, outlink->h);
00129         avfilter_copy_buffer_ref_props(outlink->out_buf, picref);
00130         avfilter_start_frame(outlink, avfilter_ref_buffer(outlink->out_buf, ~0));
00131     }
00132 }
00133 
00134 void avfilter_default_draw_slice(AVFilterLink *inlink, int y, int h, int slice_dir)
00135 {
00136     AVFilterLink *outlink = NULL;
00137 
00138     if (inlink->dst->output_count)
00139         outlink = inlink->dst->outputs[0];
00140 
00141     if (outlink)
00142         avfilter_draw_slice(outlink, y, h, slice_dir);
00143 }
00144 
00145 void avfilter_default_end_frame(AVFilterLink *inlink)
00146 {
00147     AVFilterLink *outlink = NULL;
00148 
00149     if (inlink->dst->output_count)
00150         outlink = inlink->dst->outputs[0];
00151 
00152     avfilter_unref_buffer(inlink->cur_buf);
00153     inlink->cur_buf = NULL;
00154 
00155     if (outlink) {
00156         if (outlink->out_buf) {
00157             avfilter_unref_buffer(outlink->out_buf);
00158             outlink->out_buf = NULL;
00159         }
00160         avfilter_end_frame(outlink);
00161     }
00162 }
00163 
00164 /* FIXME: samplesref is same as link->cur_buf. Need to consider removing the redundant parameter. */
00165 void avfilter_default_filter_samples(AVFilterLink *inlink, AVFilterBufferRef *samplesref)
00166 {
00167     AVFilterLink *outlink = NULL;
00168 
00169     if (inlink->dst->output_count)
00170         outlink = inlink->dst->outputs[0];
00171 
00172     if (outlink) {
00173         outlink->out_buf = avfilter_default_get_audio_buffer(inlink, AV_PERM_WRITE,
00174                                                              samplesref->audio->nb_samples);
00175         outlink->out_buf->pts                = samplesref->pts;
00176         outlink->out_buf->audio->sample_rate = samplesref->audio->sample_rate;
00177         avfilter_filter_samples(outlink, avfilter_ref_buffer(outlink->out_buf, ~0));
00178         avfilter_unref_buffer(outlink->out_buf);
00179         outlink->out_buf = NULL;
00180     }
00181     avfilter_unref_buffer(samplesref);
00182     inlink->cur_buf = NULL;
00183 }
00184 
00185 static void set_common_formats(AVFilterContext *ctx, AVFilterFormats *fmts,
00186                                enum AVMediaType type, int offin, int offout)
00187 {
00188     int i;
00189     for (i = 0; i < ctx->input_count; i++)
00190         if (ctx->inputs[i] && ctx->inputs[i]->type == type)
00191             avfilter_formats_ref(fmts,
00192                                  (AVFilterFormats **)((uint8_t *)ctx->inputs[i]+offout));
00193 
00194     for (i = 0; i < ctx->output_count; i++)
00195         if (ctx->outputs[i] && ctx->outputs[i]->type == type)
00196             avfilter_formats_ref(fmts,
00197                                  (AVFilterFormats **)((uint8_t *)ctx->outputs[i]+offin));
00198 
00199     if (!fmts->refcount) {
00200         av_free(fmts->formats);
00201         av_free(fmts->refs);
00202         av_free(fmts);
00203     }
00204 }
00205 
00206 void avfilter_set_common_pixel_formats(AVFilterContext *ctx, AVFilterFormats *formats)
00207 {
00208     set_common_formats(ctx, formats, AVMEDIA_TYPE_VIDEO,
00209                        offsetof(AVFilterLink, in_formats),
00210                        offsetof(AVFilterLink, out_formats));
00211 }
00212 
00213 void avfilter_set_common_sample_formats(AVFilterContext *ctx, AVFilterFormats *formats)
00214 {
00215     set_common_formats(ctx, formats, AVMEDIA_TYPE_AUDIO,
00216                        offsetof(AVFilterLink, in_formats),
00217                        offsetof(AVFilterLink, out_formats));
00218 }
00219 
00220 void avfilter_set_common_channel_layouts(AVFilterContext *ctx, AVFilterFormats *formats)
00221 {
00222     set_common_formats(ctx, formats, AVMEDIA_TYPE_AUDIO,
00223                        offsetof(AVFilterLink, in_chlayouts),
00224                        offsetof(AVFilterLink, out_chlayouts));
00225 }
00226 
00227 void avfilter_set_common_packing_formats(AVFilterContext *ctx, AVFilterFormats *formats)
00228 {
00229     set_common_formats(ctx, formats, AVMEDIA_TYPE_AUDIO,
00230                        offsetof(AVFilterLink, in_packing),
00231                        offsetof(AVFilterLink, out_packing));
00232 }
00233 
00234 int avfilter_default_query_formats(AVFilterContext *ctx)
00235 {
00236     avfilter_set_common_pixel_formats(ctx, avfilter_make_all_formats(AVMEDIA_TYPE_VIDEO));
00237     avfilter_set_common_sample_formats(ctx, avfilter_make_all_formats(AVMEDIA_TYPE_AUDIO));
00238     avfilter_set_common_channel_layouts(ctx, avfilter_make_all_channel_layouts());
00239     avfilter_set_common_packing_formats(ctx, avfilter_make_all_packing_formats());
00240 
00241     return 0;
00242 }
00243 
00244 void avfilter_null_start_frame(AVFilterLink *link, AVFilterBufferRef *picref)
00245 {
00246     avfilter_start_frame(link->dst->outputs[0], picref);
00247 }
00248 
00249 void avfilter_null_draw_slice(AVFilterLink *link, int y, int h, int slice_dir)
00250 {
00251     avfilter_draw_slice(link->dst->outputs[0], y, h, slice_dir);
00252 }
00253 
00254 void avfilter_null_end_frame(AVFilterLink *link)
00255 {
00256     avfilter_end_frame(link->dst->outputs[0]);
00257 }
00258 
00259 void avfilter_null_filter_samples(AVFilterLink *link, AVFilterBufferRef *samplesref)
00260 {
00261     avfilter_filter_samples(link->dst->outputs[0], samplesref);
00262 }
00263 
00264 AVFilterBufferRef *avfilter_null_get_video_buffer(AVFilterLink *link, int perms, int w, int h)
00265 {
00266     return avfilter_get_video_buffer(link->dst->outputs[0], perms, w, h);
00267 }
00268 
00269 AVFilterBufferRef *avfilter_null_get_audio_buffer(AVFilterLink *link, int perms,
00270                                                   int nb_samples)
00271 {
00272     return avfilter_get_audio_buffer(link->dst->outputs[0], perms, nb_samples);
00273 }
00274