00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
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
00062 enum PixelFormat *pixel_fmts;
00063
00064
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
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
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
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
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