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 int64_t channel_layouts[] = { -1 };
00046 AVABufferSinkParams *params = av_malloc(sizeof(AVABufferSinkParams));
00047
00048 if (!params)
00049 return NULL;
00050
00051 params->sample_fmts = sample_fmts;
00052 params->channel_layouts = channel_layouts;
00053 return params;
00054 }
00055
00056 typedef struct {
00057 AVFifoBuffer *fifo;
00058
00059
00060 enum PixelFormat *pixel_fmts;
00061
00062
00063 enum AVSampleFormat *sample_fmts;
00064 int64_t *channel_layouts;
00065 } BufferSinkContext;
00066
00067 #define FIFO_INIT_SIZE 8
00068
00069 static av_cold int common_init(AVFilterContext *ctx)
00070 {
00071 BufferSinkContext *buf = ctx->priv;
00072
00073 buf->fifo = av_fifo_alloc(FIFO_INIT_SIZE*sizeof(AVFilterBufferRef *));
00074 if (!buf->fifo) {
00075 av_log(ctx, AV_LOG_ERROR, "Failed to allocate fifo\n");
00076 return AVERROR(ENOMEM);
00077 }
00078 return 0;
00079 }
00080
00081 static av_cold void common_uninit(AVFilterContext *ctx)
00082 {
00083 BufferSinkContext *buf = ctx->priv;
00084 AVFilterBufferRef *picref;
00085
00086 if (buf->fifo) {
00087 while (av_fifo_size(buf->fifo) >= sizeof(AVFilterBufferRef *)) {
00088 av_fifo_generic_read(buf->fifo, &picref, sizeof(picref), NULL);
00089 avfilter_unref_buffer(picref);
00090 }
00091 av_fifo_free(buf->fifo);
00092 buf->fifo = NULL;
00093 }
00094 }
00095
00096 static void end_frame(AVFilterLink *inlink)
00097 {
00098 AVFilterContext *ctx = inlink->dst;
00099 BufferSinkContext *buf = inlink->dst->priv;
00100
00101 if (av_fifo_space(buf->fifo) < sizeof(AVFilterBufferRef *)) {
00102
00103 if (av_fifo_realloc2(buf->fifo, av_fifo_size(buf->fifo) * 2) < 0) {
00104 av_log(ctx, AV_LOG_ERROR,
00105 "Cannot buffer more frames. Consume some available frames "
00106 "before adding new ones.\n");
00107 return;
00108 }
00109 }
00110
00111
00112 av_fifo_generic_write(buf->fifo,
00113 &inlink->cur_buf, sizeof(AVFilterBufferRef *), NULL);
00114 }
00115
00116 int av_buffersink_get_buffer_ref(AVFilterContext *ctx,
00117 AVFilterBufferRef **bufref, int flags)
00118 {
00119 BufferSinkContext *buf = ctx->priv;
00120 AVFilterLink *inlink = ctx->inputs[0];
00121 int ret;
00122 *bufref = NULL;
00123
00124
00125 if (!av_fifo_size(buf->fifo)) {
00126 if (flags & AV_BUFFERSINK_FLAG_NO_REQUEST)
00127 return AVERROR(EAGAIN);
00128 if ((ret = avfilter_request_frame(inlink)) < 0)
00129 return ret;
00130 }
00131
00132 if (!av_fifo_size(buf->fifo))
00133 return AVERROR(EINVAL);
00134
00135 if (flags & AV_BUFFERSINK_FLAG_PEEK)
00136 *bufref = *((AVFilterBufferRef **)av_fifo_peek2(buf->fifo, 0));
00137 else
00138 av_fifo_generic_read(buf->fifo, bufref, sizeof(*bufref), NULL);
00139
00140 return 0;
00141 }
00142
00143 int av_buffersink_poll_frame(AVFilterContext *ctx)
00144 {
00145 BufferSinkContext *buf = ctx->priv;
00146 AVFilterLink *inlink = ctx->inputs[0];
00147
00148 return av_fifo_size(buf->fifo)/sizeof(AVFilterBufferRef *) + avfilter_poll_frame(inlink);
00149 }
00150
00151 #if FF_API_OLD_VSINK_API
00152 int av_vsink_buffer_get_video_buffer_ref(AVFilterContext *ctx,
00153 AVFilterBufferRef **picref, int flags)
00154 {
00155 return av_buffersink_get_buffer_ref(ctx, picref, flags);
00156 }
00157 #endif
00158
00159 #if CONFIG_BUFFERSINK_FILTER
00160
00161 static av_cold int vsink_init(AVFilterContext *ctx, const char *args, void *opaque)
00162 {
00163 BufferSinkContext *buf = ctx->priv;
00164 av_unused AVBufferSinkParams *params;
00165
00166 if (!opaque) {
00167 av_log(ctx, AV_LOG_WARNING,
00168 "No opaque field provided\n");
00169 buf->pixel_fmts = NULL;
00170 } else {
00171 #if FF_API_OLD_VSINK_API
00172 const int *pixel_fmts = (const enum PixelFormat *)opaque;
00173 #else
00174 params = (AVBufferSinkParams *)opaque;
00175 const int *pixel_fmts = params->pixel_fmts;
00176 #endif
00177 buf->pixel_fmts = ff_copy_int_list(pixel_fmts);
00178 if (!buf->pixel_fmts)
00179 return AVERROR(ENOMEM);
00180 }
00181
00182 return common_init(ctx);
00183 }
00184
00185 static av_cold void vsink_uninit(AVFilterContext *ctx)
00186 {
00187 BufferSinkContext *buf = ctx->priv;
00188 av_freep(&buf->pixel_fmts);
00189 return common_uninit(ctx);
00190 }
00191
00192 static int vsink_query_formats(AVFilterContext *ctx)
00193 {
00194 BufferSinkContext *buf = ctx->priv;
00195
00196 if (buf->pixel_fmts)
00197 avfilter_set_common_pixel_formats(ctx, avfilter_make_format_list(buf->pixel_fmts));
00198 else
00199 avfilter_default_query_formats(ctx);
00200
00201 return 0;
00202 }
00203
00204 AVFilter avfilter_vsink_buffersink = {
00205 .name = "buffersink",
00206 .description = NULL_IF_CONFIG_SMALL("Buffer video frames, and make them available to the end of the filter graph."),
00207 .priv_size = sizeof(BufferSinkContext),
00208 .init = vsink_init,
00209 .uninit = vsink_uninit,
00210
00211 .query_formats = vsink_query_formats,
00212
00213 .inputs = (const AVFilterPad[]) {{ .name = "default",
00214 .type = AVMEDIA_TYPE_VIDEO,
00215 .end_frame = end_frame,
00216 .min_perms = AV_PERM_READ, },
00217 { .name = NULL }},
00218 .outputs = (const AVFilterPad[]) {{ .name = NULL }},
00219 };
00220
00221 #endif
00222
00223 #if CONFIG_ABUFFERSINK_FILTER
00224
00225 static void filter_samples(AVFilterLink *link, AVFilterBufferRef *samplesref)
00226 {
00227 end_frame(link);
00228 }
00229
00230 static av_cold int asink_init(AVFilterContext *ctx, const char *args, void *opaque)
00231 {
00232 BufferSinkContext *buf = ctx->priv;
00233 AVABufferSinkParams *params;
00234
00235 if (!opaque) {
00236 av_log(ctx, AV_LOG_ERROR,
00237 "No opaque field provided, an AVABufferSinkParams struct is required\n");
00238 return AVERROR(EINVAL);
00239 } else
00240 params = (AVABufferSinkParams *)opaque;
00241
00242 buf->sample_fmts = ff_copy_int_list (params->sample_fmts);
00243 buf->channel_layouts = ff_copy_int64_list(params->channel_layouts);
00244 if (!buf->sample_fmts || !buf->channel_layouts) {
00245 av_freep(&buf->sample_fmts);
00246 av_freep(&buf->channel_layouts);
00247 return AVERROR(ENOMEM);
00248 }
00249
00250 return common_init(ctx);
00251 }
00252
00253 static av_cold void asink_uninit(AVFilterContext *ctx)
00254 {
00255 BufferSinkContext *buf = ctx->priv;
00256
00257 av_freep(&buf->sample_fmts);
00258 av_freep(&buf->channel_layouts);
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 AVFilterChannelLayouts *layouts = NULL;
00267
00268 if (!(formats = avfilter_make_format_list(buf->sample_fmts)))
00269 return AVERROR(ENOMEM);
00270 avfilter_set_common_sample_formats(ctx, formats);
00271
00272 if (!(layouts = avfilter_make_format64_list(buf->channel_layouts)))
00273 return AVERROR(ENOMEM);
00274 ff_set_common_channel_layouts(ctx, layouts);
00275 ff_set_common_samplerates (ctx, ff_all_samplerates());
00276
00277 return 0;
00278 }
00279
00280 AVFilter avfilter_asink_abuffersink = {
00281 .name = "abuffersink",
00282 .description = NULL_IF_CONFIG_SMALL("Buffer audio frames, and make them available to the end of the filter graph."),
00283 .init = asink_init,
00284 .uninit = asink_uninit,
00285 .priv_size = sizeof(BufferSinkContext),
00286 .query_formats = asink_query_formats,
00287
00288 .inputs = (const AVFilterPad[]) {{ .name = "default",
00289 .type = AVMEDIA_TYPE_AUDIO,
00290 .filter_samples = filter_samples,
00291 .min_perms = AV_PERM_READ, },
00292 { .name = NULL }},
00293 .outputs = (const AVFilterPad[]) {{ .name = NULL }},
00294 };
00295
00296 #endif