]> git.sesse.net Git - ffmpeg/blob - libavfilter/buffersrc.c
lavfi: pass the hw frames context through the filter chain
[ffmpeg] / libavfilter / buffersrc.c
1 /*
2  * Copyright (c) 2008 Vitor Sessak
3  *
4  * This file is part of Libav.
5  *
6  * Libav is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * Libav is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with Libav; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19  */
20
21 /**
22  * @file
23  * memory buffer source filter
24  */
25
26 #include <float.h>
27
28 #include "libavutil/channel_layout.h"
29 #include "libavutil/common.h"
30 #include "libavutil/fifo.h"
31 #include "libavutil/frame.h"
32 #include "libavutil/imgutils.h"
33 #include "libavutil/internal.h"
34 #include "libavutil/opt.h"
35 #include "libavutil/samplefmt.h"
36 #include "audio.h"
37 #include "avfilter.h"
38 #include "buffersrc.h"
39 #include "formats.h"
40 #include "internal.h"
41 #include "video.h"
42
43 typedef struct BufferSourceContext {
44     const AVClass    *class;
45     AVFifoBuffer     *fifo;
46     AVRational        time_base;     ///< time_base to set in the output link
47     AVRational        frame_rate;    ///< frame_rate to set in the output link
48
49     /* video only */
50     int               h, w;
51     enum AVPixelFormat  pix_fmt;
52     char               *pix_fmt_str;
53     AVRational        pixel_aspect;
54
55     AVBufferRef *hw_frames_ctx;
56
57     /* audio only */
58     int sample_rate;
59     enum AVSampleFormat sample_fmt;
60     char               *sample_fmt_str;
61     uint64_t channel_layout;
62     char    *channel_layout_str;
63
64     int got_format_from_params;
65     int eof;
66 } BufferSourceContext;
67
68 #define CHECK_VIDEO_PARAM_CHANGE(s, c, width, height, format)\
69     if (c->w != width || c->h != height || c->pix_fmt != format) {\
70         av_log(s, AV_LOG_ERROR, "Changing frame properties on the fly is not supported.\n");\
71         return AVERROR(EINVAL);\
72     }
73
74 #define CHECK_AUDIO_PARAM_CHANGE(s, c, srate, ch_layout, format)\
75     if (c->sample_fmt != format || c->sample_rate != srate ||\
76         c->channel_layout != ch_layout) {\
77         av_log(s, AV_LOG_ERROR, "Changing frame properties on the fly is not supported.\n");\
78         return AVERROR(EINVAL);\
79     }
80
81 AVBufferSrcParameters *av_buffersrc_parameters_alloc(void)
82 {
83     AVBufferSrcParameters *par = av_mallocz(sizeof(*par));
84     if (!par)
85         return NULL;
86
87     par->format = -1;
88
89     return par;
90 }
91
92 int av_buffersrc_parameters_set(AVFilterContext *ctx, AVBufferSrcParameters *param)
93 {
94     BufferSourceContext *s = ctx->priv;
95
96     if (param->time_base.num > 0 && param->time_base.den > 0)
97         s->time_base = param->time_base;
98
99     switch (ctx->filter->outputs[0].type) {
100     case AVMEDIA_TYPE_VIDEO:
101         if (param->format != AV_PIX_FMT_NONE) {
102             s->got_format_from_params = 1;
103             s->pix_fmt = param->format;
104         }
105         if (param->width > 0)
106             s->w = param->width;
107         if (param->height > 0)
108             s->h = param->height;
109         if (param->sample_aspect_ratio.num > 0 && param->sample_aspect_ratio.den > 0)
110             s->pixel_aspect = param->sample_aspect_ratio;
111         if (param->frame_rate.num > 0 && param->frame_rate.den > 0)
112             s->frame_rate = param->frame_rate;
113         if (param->hw_frames_ctx) {
114             av_buffer_unref(&s->hw_frames_ctx);
115             s->hw_frames_ctx = av_buffer_ref(param->hw_frames_ctx);
116             if (!s->hw_frames_ctx)
117                 return AVERROR(ENOMEM);
118         }
119         break;
120     case AVMEDIA_TYPE_AUDIO:
121         if (param->format != AV_SAMPLE_FMT_NONE) {
122             s->got_format_from_params = 1;
123             s->sample_fmt = param->format;
124         }
125         if (param->sample_rate > 0)
126             s->sample_rate = param->sample_rate;
127         if (param->channel_layout)
128             s->channel_layout = param->channel_layout;
129         break;
130     default:
131         return AVERROR_BUG;
132     }
133
134     return 0;
135 }
136
137 int attribute_align_arg av_buffersrc_write_frame(AVFilterContext *ctx, const AVFrame *frame)
138 {
139     AVFrame *copy;
140     int ret = 0;
141
142     if (!(copy = av_frame_alloc()))
143         return AVERROR(ENOMEM);
144     ret = av_frame_ref(copy, frame);
145     if (ret >= 0)
146         ret = av_buffersrc_add_frame(ctx, copy);
147
148     av_frame_free(&copy);
149     return ret;
150 }
151
152 int attribute_align_arg av_buffersrc_add_frame(AVFilterContext *ctx,
153                                                AVFrame *frame)
154 {
155     BufferSourceContext *s = ctx->priv;
156     AVFrame *copy;
157     int refcounted, ret;
158
159     if (!frame) {
160         s->eof = 1;
161         return 0;
162     } else if (s->eof)
163         return AVERROR(EINVAL);
164
165     refcounted = !!frame->buf[0];
166
167     switch (ctx->outputs[0]->type) {
168     case AVMEDIA_TYPE_VIDEO:
169         CHECK_VIDEO_PARAM_CHANGE(ctx, s, frame->width, frame->height,
170                                  frame->format);
171         break;
172     case AVMEDIA_TYPE_AUDIO:
173         CHECK_AUDIO_PARAM_CHANGE(ctx, s, frame->sample_rate, frame->channel_layout,
174                                  frame->format);
175         break;
176     default:
177         return AVERROR(EINVAL);
178     }
179
180     if (!av_fifo_space(s->fifo) &&
181         (ret = av_fifo_realloc2(s->fifo, av_fifo_size(s->fifo) +
182                                          sizeof(copy))) < 0)
183         return ret;
184
185     if (!(copy = av_frame_alloc()))
186         return AVERROR(ENOMEM);
187
188     if (refcounted) {
189         av_frame_move_ref(copy, frame);
190     } else {
191         ret = av_frame_ref(copy, frame);
192         if (ret < 0) {
193             av_frame_free(&copy);
194             return ret;
195         }
196     }
197
198     if ((ret = av_fifo_generic_write(s->fifo, &copy, sizeof(copy), NULL)) < 0) {
199         if (refcounted)
200             av_frame_move_ref(frame, copy);
201         av_frame_free(&copy);
202         return ret;
203     }
204
205     return 0;
206 }
207
208 static av_cold int init_video(AVFilterContext *ctx)
209 {
210     BufferSourceContext *c = ctx->priv;
211
212     if (!(c->pix_fmt_str || c->got_format_from_params)  || !c->w || !c->h ||
213         av_q2d(c->time_base) <= 0) {
214         av_log(ctx, AV_LOG_ERROR, "Invalid parameters provided.\n");
215         return AVERROR(EINVAL);
216     }
217
218     if (c->pix_fmt_str) {
219         if ((c->pix_fmt = av_get_pix_fmt(c->pix_fmt_str)) == AV_PIX_FMT_NONE) {
220             char *tail;
221             c->pix_fmt = strtol(c->pix_fmt_str, &tail, 10);
222             if (*tail || c->pix_fmt < 0 || !av_pix_fmt_desc_get(c->pix_fmt)) {
223                 av_log(ctx, AV_LOG_ERROR, "Invalid pixel format string '%s'\n", c->pix_fmt_str);
224                 return AVERROR(EINVAL);
225             }
226         }
227     }
228
229     if (!(c->fifo = av_fifo_alloc(sizeof(AVFrame*))))
230         return AVERROR(ENOMEM);
231
232     av_log(ctx, AV_LOG_VERBOSE, "w:%d h:%d pixfmt:%s tb:%d/%d sar:%d/%d\n",
233            c->w, c->h, av_get_pix_fmt_name(c->pix_fmt),
234            c->time_base.num, c->time_base.den,
235            c->pixel_aspect.num, c->pixel_aspect.den);
236     return 0;
237 }
238
239 #define OFFSET(x) offsetof(BufferSourceContext, x)
240 #define A AV_OPT_FLAG_AUDIO_PARAM
241 #define V AV_OPT_FLAG_VIDEO_PARAM
242
243 static const AVOption video_options[] = {
244     { "width",         NULL,                     OFFSET(w),                AV_OPT_TYPE_INT,      { .i64 = 0 }, 0, INT_MAX, V },
245     { "height",        NULL,                     OFFSET(h),                AV_OPT_TYPE_INT,      { .i64 = 0 }, 0, INT_MAX, V },
246     { "pix_fmt",       NULL,                     OFFSET(pix_fmt_str),      AV_OPT_TYPE_STRING,                    .flags = V },
247 #if FF_API_OLD_FILTER_OPTS
248     /* those 4 are for compatibility with the old option passing system where each filter
249      * did its own parsing */
250     { "time_base_num", "deprecated, do not use", OFFSET(time_base.num),    AV_OPT_TYPE_INT,      { .i64 = 0 }, 0, INT_MAX, V },
251     { "time_base_den", "deprecated, do not use", OFFSET(time_base.den),    AV_OPT_TYPE_INT,      { .i64 = 0 }, 0, INT_MAX, V },
252     { "sar_num",       "deprecated, do not use", OFFSET(pixel_aspect.num), AV_OPT_TYPE_INT,      { .i64 = 0 }, 0, INT_MAX, V },
253     { "sar_den",       "deprecated, do not use", OFFSET(pixel_aspect.den), AV_OPT_TYPE_INT,      { .i64 = 0 }, 0, INT_MAX, V },
254 #endif
255     { "sar",           "sample aspect ratio",    OFFSET(pixel_aspect),     AV_OPT_TYPE_RATIONAL, { .dbl = 0 }, 0, DBL_MAX, V },
256     { "time_base",     NULL,                     OFFSET(time_base),        AV_OPT_TYPE_RATIONAL, { .dbl = 0 }, 0, DBL_MAX, V },
257     { "frame_rate",    NULL,                     OFFSET(frame_rate),       AV_OPT_TYPE_RATIONAL, { .dbl = 0 }, 0, DBL_MAX, V },
258     { NULL },
259 };
260
261 static const AVClass buffer_class = {
262     .class_name = "buffer source",
263     .item_name  = av_default_item_name,
264     .option     = video_options,
265     .version    = LIBAVUTIL_VERSION_INT,
266 };
267
268 static const AVOption audio_options[] = {
269     { "time_base",      NULL, OFFSET(time_base),           AV_OPT_TYPE_RATIONAL, { .dbl = 0 }, 0, INT_MAX, A },
270     { "sample_rate",    NULL, OFFSET(sample_rate),         AV_OPT_TYPE_INT,      { .i64 = 0 }, 0, INT_MAX, A },
271     { "sample_fmt",     NULL, OFFSET(sample_fmt_str),      AV_OPT_TYPE_STRING,             .flags = A },
272     { "channel_layout", NULL, OFFSET(channel_layout_str),  AV_OPT_TYPE_STRING,             .flags = A },
273     { NULL },
274 };
275
276 static const AVClass abuffer_class = {
277     .class_name = "abuffer source",
278     .item_name  = av_default_item_name,
279     .option     = audio_options,
280     .version    = LIBAVUTIL_VERSION_INT,
281 };
282
283 static av_cold int init_audio(AVFilterContext *ctx)
284 {
285     BufferSourceContext *s = ctx->priv;
286     int ret = 0;
287
288     if (!(s->sample_fmt_str || s->got_format_from_params)) {
289         av_log(ctx, AV_LOG_ERROR, "Sample format not provided\n");
290         return AVERROR(EINVAL);
291     }
292     if (s->sample_fmt_str)
293         s->sample_fmt = av_get_sample_fmt(s->sample_fmt_str);
294
295     if (s->sample_fmt == AV_SAMPLE_FMT_NONE) {
296         av_log(ctx, AV_LOG_ERROR, "Invalid sample format %s.\n",
297                s->sample_fmt_str);
298         return AVERROR(EINVAL);
299     }
300
301     if (s->channel_layout_str)
302         s->channel_layout = av_get_channel_layout(s->channel_layout_str);
303
304     if (!s->channel_layout) {
305         av_log(ctx, AV_LOG_ERROR, "Invalid channel layout %s.\n",
306                s->channel_layout_str);
307         return AVERROR(EINVAL);
308     }
309
310     if (!(s->fifo = av_fifo_alloc(sizeof(AVFrame*))))
311         return AVERROR(ENOMEM);
312
313     if (!s->time_base.num)
314         s->time_base = (AVRational){1, s->sample_rate};
315
316     av_log(ctx, AV_LOG_VERBOSE, "tb:%d/%d samplefmt:%s samplerate: %d "
317            "ch layout:%s\n", s->time_base.num, s->time_base.den, s->sample_fmt_str,
318            s->sample_rate, s->channel_layout_str);
319
320     return ret;
321 }
322
323 static av_cold void uninit(AVFilterContext *ctx)
324 {
325     BufferSourceContext *s = ctx->priv;
326     while (s->fifo && av_fifo_size(s->fifo)) {
327         AVFrame *frame;
328         av_fifo_generic_read(s->fifo, &frame, sizeof(frame), NULL);
329         av_frame_free(&frame);
330     }
331     av_buffer_unref(&s->hw_frames_ctx);
332     av_fifo_free(s->fifo);
333     s->fifo = NULL;
334 }
335
336 static int query_formats(AVFilterContext *ctx)
337 {
338     BufferSourceContext *c = ctx->priv;
339     AVFilterChannelLayouts *channel_layouts = NULL;
340     AVFilterFormats *formats = NULL;
341     AVFilterFormats *samplerates = NULL;
342
343     switch (ctx->outputs[0]->type) {
344     case AVMEDIA_TYPE_VIDEO:
345         ff_add_format(&formats, c->pix_fmt);
346         ff_set_common_formats(ctx, formats);
347         break;
348     case AVMEDIA_TYPE_AUDIO:
349         ff_add_format(&formats,           c->sample_fmt);
350         ff_set_common_formats(ctx, formats);
351
352         ff_add_format(&samplerates,       c->sample_rate);
353         ff_set_common_samplerates(ctx, samplerates);
354
355         ff_add_channel_layout(&channel_layouts, c->channel_layout);
356         ff_set_common_channel_layouts(ctx, channel_layouts);
357         break;
358     default:
359         return AVERROR(EINVAL);
360     }
361
362     return 0;
363 }
364
365 static int config_props(AVFilterLink *link)
366 {
367     BufferSourceContext *c = link->src->priv;
368
369     switch (link->type) {
370     case AVMEDIA_TYPE_VIDEO:
371         link->w = c->w;
372         link->h = c->h;
373         link->sample_aspect_ratio = c->pixel_aspect;
374
375         if (c->hw_frames_ctx) {
376             link->hw_frames_ctx = av_buffer_ref(c->hw_frames_ctx);
377             if (!link->hw_frames_ctx)
378                 return AVERROR(ENOMEM);
379         }
380         break;
381     case AVMEDIA_TYPE_AUDIO:
382         link->channel_layout = c->channel_layout;
383         link->sample_rate    = c->sample_rate;
384         break;
385     default:
386         return AVERROR(EINVAL);
387     }
388
389     link->time_base = c->time_base;
390     link->frame_rate = c->frame_rate;
391     return 0;
392 }
393
394 static int request_frame(AVFilterLink *link)
395 {
396     BufferSourceContext *c = link->src->priv;
397     AVFrame *frame;
398     int ret = 0;
399
400     if (!av_fifo_size(c->fifo)) {
401         if (c->eof)
402             return AVERROR_EOF;
403         return AVERROR(EAGAIN);
404     }
405     av_fifo_generic_read(c->fifo, &frame, sizeof(frame), NULL);
406
407     ret = ff_filter_frame(link, frame);
408
409     return ret;
410 }
411
412 static int poll_frame(AVFilterLink *link)
413 {
414     BufferSourceContext *c = link->src->priv;
415     int size = av_fifo_size(c->fifo);
416     if (!size && c->eof)
417         return AVERROR_EOF;
418     return size/sizeof(AVFrame*);
419 }
420
421 static const AVFilterPad avfilter_vsrc_buffer_outputs[] = {
422     {
423         .name          = "default",
424         .type          = AVMEDIA_TYPE_VIDEO,
425         .request_frame = request_frame,
426         .poll_frame    = poll_frame,
427         .config_props  = config_props,
428     },
429     { NULL }
430 };
431
432 AVFilter ff_vsrc_buffer = {
433     .name      = "buffer",
434     .description = NULL_IF_CONFIG_SMALL("Buffer video frames, and make them accessible to the filterchain."),
435     .priv_size = sizeof(BufferSourceContext),
436     .priv_class = &buffer_class,
437     .query_formats = query_formats,
438
439     .init      = init_video,
440     .uninit    = uninit,
441
442     .inputs    = NULL,
443     .outputs   = avfilter_vsrc_buffer_outputs,
444 };
445
446 static const AVFilterPad avfilter_asrc_abuffer_outputs[] = {
447     {
448         .name          = "default",
449         .type          = AVMEDIA_TYPE_AUDIO,
450         .request_frame = request_frame,
451         .poll_frame    = poll_frame,
452         .config_props  = config_props,
453     },
454     { NULL }
455 };
456
457 AVFilter ff_asrc_abuffer = {
458     .name          = "abuffer",
459     .description   = NULL_IF_CONFIG_SMALL("Buffer audio frames, and make them accessible to the filterchain."),
460     .priv_size     = sizeof(BufferSourceContext),
461     .priv_class    = &abuffer_class,
462     .query_formats = query_formats,
463
464     .init      = init_audio,
465     .uninit    = uninit,
466
467     .inputs    = NULL,
468     .outputs   = avfilter_asrc_abuffer_outputs,
469 };