libavfilter/sink_buffer.c

Go to the documentation of this file.
00001 /*
00002  * Copyright (c) 2011 Stefano Sabatini
00003  *
00004  * This file is part of FFmpeg.
00005  *
00006  * FFmpeg is free software; you can redistribute it and/or
00007  * modify it under the terms of the GNU Lesser General Public
00008  * License as published by the Free Software Foundation; either
00009  * version 2.1 of the License, or (at your option) any later version.
00010  *
00011  * FFmpeg is distributed in the hope that it will be useful,
00012  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
00014  * Lesser General Public License for more details.
00015  *
00016  * You should have received a copy of the GNU Lesser General Public
00017  * License along with FFmpeg; if not, write to the Free Software
00018  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
00019  */
00020 
00026 #include "libavutil/fifo.h"
00027 #include "avfilter.h"
00028 #include "buffersink.h"
00029 #include "internal.h"
00030 
00031 AVBufferSinkParams *av_buffersink_params_alloc(void)
00032 {
00033 static const int pixel_fmts[] = { -1 };
00034 AVBufferSinkParams *params = av_malloc(sizeof(AVBufferSinkParams));
00035 if (!params)
00036 return NULL;
00037 
00038 params->pixel_fmts = pixel_fmts;
00039 return params;
00040 }
00041 
00042 AVABufferSinkParams *av_abuffersink_params_alloc(void)
00043 {
00044 static const int sample_fmts[] = { -1 };
00045 static const int packing_fmts[] = { -1 };
00046 static const int64_t channel_layouts[] = { -1 };
00047 AVABufferSinkParams *params = av_malloc(sizeof(AVABufferSinkParams));
00048 
00049 if (!params)
00050 return NULL;
00051 
00052 params->sample_fmts = sample_fmts;
00053 params->channel_layouts = channel_layouts;
00054 params->packing_fmts = packing_fmts;
00055 return params;
00056 }
00057 
00058 typedef struct {
00059 AVFifoBuffer *fifo; 
00060 
00061 /* only used for video */
00062 enum PixelFormat *pixel_fmts; 
00063 
00064 /* only used for audio */
00065 enum AVSampleFormat *sample_fmts; 
00066 int64_t *channel_layouts; 
00067 int *packing_fmts; 
00068 } BufferSinkContext;
00069 
00070 #define FIFO_INIT_SIZE 8
00071 
00072 static av_cold int common_init(AVFilterContext *ctx)
00073 {
00074 BufferSinkContext *buf = ctx->priv;
00075 
00076 buf->fifo = av_fifo_alloc(FIFO_INIT_SIZE*sizeof(AVFilterBufferRef *));
00077 if (!buf->fifo) {
00078 av_log(ctx, AV_LOG_ERROR, "Failed to allocate fifo\n");
00079 return AVERROR(ENOMEM);
00080 }
00081 return 0;
00082 }
00083 
00084 static av_cold void common_uninit(AVFilterContext *ctx)
00085 {
00086 BufferSinkContext *buf = ctx->priv;
00087 AVFilterBufferRef *picref;
00088 
00089 if (buf->fifo) {
00090 while (av_fifo_size(buf->fifo) >= sizeof(AVFilterBufferRef *)) {
00091 av_fifo_generic_read(buf->fifo, &picref, sizeof(picref), NULL);
00092 avfilter_unref_buffer(picref);
00093 }
00094 av_fifo_free(buf->fifo);
00095 buf->fifo = NULL;
00096 }
00097 }
00098 
00099 static void end_frame(AVFilterLink *inlink)
00100 {
00101 AVFilterContext *ctx = inlink->dst;
00102 BufferSinkContext *buf = inlink->dst->priv;
00103 
00104 if (av_fifo_space(buf->fifo) < sizeof(AVFilterBufferRef *)) {
00105 /* realloc fifo size */
00106 if (av_fifo_realloc2(buf->fifo, av_fifo_size(buf->fifo) * 2) < 0) {
00107 av_log(ctx, AV_LOG_ERROR,
00108 "Cannot buffer more frames. Consume some available frames "
00109 "before adding new ones.\n");
00110 return;
00111 }
00112 }
00113 
00114 /* cache frame */
00115 av_fifo_generic_write(buf->fifo,
00116 &inlink->cur_buf, sizeof(AVFilterBufferRef *), NULL);
00117 }
00118 
00119 int av_buffersink_get_buffer_ref(AVFilterContext *ctx,
00120 AVFilterBufferRef **bufref, int flags)
00121 {
00122 BufferSinkContext *buf = ctx->priv;
00123 AVFilterLink *inlink = ctx->inputs[0];
00124 int ret;
00125 *bufref = NULL;
00126 
00127 /* no picref available, fetch it from the filterchain */
00128 if (!av_fifo_size(buf->fifo)) {
00129 if ((ret = avfilter_request_frame(inlink)) < 0)
00130 return ret;
00131 }
00132 
00133 if (!av_fifo_size(buf->fifo))
00134 return AVERROR(EINVAL);
00135 
00136 if (flags & AV_BUFFERSINK_FLAG_PEEK)
00137 *bufref = *((AVFilterBufferRef **)av_fifo_peek2(buf->fifo, 0));
00138 else
00139 av_fifo_generic_read(buf->fifo, bufref, sizeof(*bufref), NULL);
00140 
00141 return 0;
00142 }
00143 
00144 int av_buffersink_poll_frame(AVFilterContext *ctx)
00145 {
00146 BufferSinkContext *buf = ctx->priv;
00147 AVFilterLink *inlink = ctx->inputs[0];
00148 
00149 return av_fifo_size(buf->fifo)/sizeof(AVFilterBufferRef *) + avfilter_poll_frame(inlink);
00150 }
00151 
00152 #if FF_API_OLD_VSINK_API
00153 int av_vsink_buffer_get_video_buffer_ref(AVFilterContext *ctx,
00154 AVFilterBufferRef **picref, int flags)
00155 {
00156 return av_buffersink_get_buffer_ref(ctx, picref, flags);
00157 }
00158 #endif
00159 
00160 #if CONFIG_BUFFERSINK_FILTER
00161 
00162 static av_cold int vsink_init(AVFilterContext *ctx, const char *args, void *opaque)
00163 {
00164 BufferSinkContext *buf = ctx->priv;
00165 av_unused AVBufferSinkParams *params;
00166 
00167 if (!opaque) {
00168 av_log(ctx, AV_LOG_ERROR,
00169 "No opaque field provided\n");
00170 return AVERROR(EINVAL);
00171 } else {
00172 #if FF_API_OLD_VSINK_API
00173 const int *pixel_fmts = (const enum PixelFormat *)opaque;
00174 #else
00175 params = (AVBufferSinkParams *)opaque;
00176 const int *pixel_fmts = params->pixel_fmts;
00177 #endif
00178 buf->pixel_fmts = ff_copy_int_list(pixel_fmts);
00179 if (!buf->pixel_fmts)
00180 return AVERROR(ENOMEM);
00181 }
00182 
00183 return common_init(ctx);
00184 }
00185 
00186 static av_cold void vsink_uninit(AVFilterContext *ctx)
00187 {
00188 BufferSinkContext *buf = ctx->priv;
00189 av_freep(&buf->pixel_fmts);
00190 return common_uninit(ctx);
00191 }
00192 
00193 static int vsink_query_formats(AVFilterContext *ctx)
00194 {
00195 BufferSinkContext *buf = ctx->priv;
00196 
00197 avfilter_set_common_pixel_formats(ctx, avfilter_make_format_list(buf->pixel_fmts));
00198 return 0;
00199 }
00200 
00201 AVFilter avfilter_vsink_buffersink = {
00202 .name = "buffersink",
00203 .description = NULL_IF_CONFIG_SMALL("Buffer video frames, and make them available to the end of the filter graph."),
00204 .priv_size = sizeof(BufferSinkContext),
00205 .init = vsink_init,
00206 .uninit = vsink_uninit,
00207 
00208 .query_formats = vsink_query_formats,
00209 
00210 .inputs = (const AVFilterPad[]) {{ .name = "default",
00211 .type = AVMEDIA_TYPE_VIDEO,
00212 .end_frame = end_frame,
00213 .min_perms = AV_PERM_READ, },
00214 { .name = NULL }},
00215 .outputs = (const AVFilterPad[]) {{ .name = NULL }},
00216 };
00217 
00218 #endif /* CONFIG_BUFFERSINK_FILTER */
00219 
00220 #if CONFIG_ABUFFERSINK_FILTER
00221 
00222 static void filter_samples(AVFilterLink *link, AVFilterBufferRef *samplesref)
00223 {
00224 end_frame(link);
00225 }
00226 
00227 static av_cold int asink_init(AVFilterContext *ctx, const char *args, void *opaque)
00228 {
00229 BufferSinkContext *buf = ctx->priv;
00230 AVABufferSinkParams *params;
00231 
00232 if (!opaque) {
00233 av_log(ctx, AV_LOG_ERROR,
00234 "No opaque field provided, an AVABufferSinkParams struct is required\n");
00235 return AVERROR(EINVAL);
00236 } else
00237 params = (AVABufferSinkParams *)opaque;
00238 
00239 buf->sample_fmts = ff_copy_int_list (params->sample_fmts);
00240 buf->channel_layouts = ff_copy_int64_list(params->channel_layouts);
00241 buf->packing_fmts = ff_copy_int_list (params->packing_fmts);
00242 if (!buf->sample_fmts || !buf->channel_layouts || !buf->sample_fmts) {
00243 av_freep(&buf->sample_fmts);
00244 av_freep(&buf->channel_layouts);
00245 av_freep(&buf->packing_fmts);
00246 return AVERROR(ENOMEM);
00247 }
00248 
00249 return common_init(ctx);
00250 }
00251 
00252 static av_cold void asink_uninit(AVFilterContext *ctx)
00253 {
00254 BufferSinkContext *buf = ctx->priv;
00255 
00256 av_freep(&buf->sample_fmts);
00257 av_freep(&buf->channel_layouts);
00258 av_freep(&buf->packing_fmts);
00259 return common_uninit(ctx);
00260 }
00261 
00262 static int asink_query_formats(AVFilterContext *ctx)
00263 {
00264 BufferSinkContext *buf = ctx->priv;
00265 AVFilterFormats *formats = NULL;
00266 
00267 if (!(formats = avfilter_make_format_list(buf->sample_fmts)))
00268 return AVERROR(ENOMEM);
00269 avfilter_set_common_sample_formats(ctx, formats);
00270 
00271 if (!(formats = avfilter_make_format64_list(buf->channel_layouts)))
00272 return AVERROR(ENOMEM);
00273 avfilter_set_common_channel_layouts(ctx, formats);
00274 
00275 if (!(formats = avfilter_make_format_list(buf->packing_fmts)))
00276 return AVERROR(ENOMEM);
00277 avfilter_set_common_packing_formats(ctx, formats);
00278 
00279 return 0;
00280 }
00281 
00282 AVFilter avfilter_asink_abuffersink = {
00283 .name = "abuffersink",
00284 .description = NULL_IF_CONFIG_SMALL("Buffer audio frames, and make them available to the end of the filter graph."),
00285 .init = asink_init,
00286 .uninit = asink_uninit,
00287 .priv_size = sizeof(BufferSinkContext),
00288 .query_formats = asink_query_formats,
00289 
00290 .inputs = (const AVFilterPad[]) {{ .name = "default",
00291 .type = AVMEDIA_TYPE_AUDIO,
00292 .filter_samples = filter_samples,
00293 .min_perms = AV_PERM_READ, },
00294 { .name = NULL }},
00295 .outputs = (const AVFilterPad[]) {{ .name = NULL }},
00296 };
00297 
00298 #endif /* CONFIG_ABUFFERSINK_FILTER */

Generated on Fri Oct 26 02:46:02 2012 for FFmpeg by doxygen 1.5.8

AltStyle によって変換されたページ (->オリジナル) /