]> git.sesse.net Git - ffmpeg/blob - libavfilter/buffersrc.c
lpc: Add a function for calculating reflection coefficients from samples
[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 "audio.h"
27 #include "avfilter.h"
28 #include "buffersrc.h"
29 #include "formats.h"
30 #include "internal.h"
31 #include "video.h"
32
33 #include "libavutil/audioconvert.h"
34 #include "libavutil/common.h"
35 #include "libavutil/fifo.h"
36 #include "libavutil/imgutils.h"
37 #include "libavutil/opt.h"
38 #include "libavutil/samplefmt.h"
39
40 typedef struct {
41     const AVClass    *class;
42     AVFifoBuffer     *fifo;
43     AVRational        time_base;     ///< time_base to set in the output link
44
45     /* video only */
46     int               h, w;
47     enum AVPixelFormat  pix_fmt;
48     AVRational        pixel_aspect;
49
50     /* audio only */
51     int sample_rate;
52     enum AVSampleFormat sample_fmt;
53     char               *sample_fmt_str;
54     uint64_t channel_layout;
55     char    *channel_layout_str;
56
57     int eof;
58 } BufferSourceContext;
59
60 #define CHECK_VIDEO_PARAM_CHANGE(s, c, width, height, format)\
61     if (c->w != width || c->h != height || c->pix_fmt != format) {\
62         av_log(s, AV_LOG_ERROR, "Changing frame properties on the fly is not supported.\n");\
63         return AVERROR(EINVAL);\
64     }
65
66 #define CHECK_AUDIO_PARAM_CHANGE(s, c, srate, ch_layout, format)\
67     if (c->sample_fmt != format || c->sample_rate != srate ||\
68         c->channel_layout != ch_layout) {\
69         av_log(s, AV_LOG_ERROR, "Changing frame properties on the fly is not supported.\n");\
70         return AVERROR(EINVAL);\
71     }
72
73 int av_buffersrc_write_frame(AVFilterContext *buffer_filter, const AVFrame *frame)
74 {
75     BufferSourceContext *c = buffer_filter->priv;
76     AVFilterBufferRef *buf;
77     int ret;
78
79     if (!frame) {
80         c->eof = 1;
81         return 0;
82     } else if (c->eof)
83         return AVERROR(EINVAL);
84
85     if (!av_fifo_space(c->fifo) &&
86         (ret = av_fifo_realloc2(c->fifo, av_fifo_size(c->fifo) +
87                                          sizeof(buf))) < 0)
88         return ret;
89
90     switch (buffer_filter->outputs[0]->type) {
91     case AVMEDIA_TYPE_VIDEO:
92         CHECK_VIDEO_PARAM_CHANGE(buffer_filter, c, frame->width, frame->height,
93                                  frame->format);
94         buf = ff_get_video_buffer(buffer_filter->outputs[0], AV_PERM_WRITE,
95                                   c->w, c->h);
96         if (!buf)
97             return AVERROR(ENOMEM);
98
99         av_image_copy(buf->data, buf->linesize, frame->data, frame->linesize,
100                       c->pix_fmt, c->w, c->h);
101         break;
102     case AVMEDIA_TYPE_AUDIO:
103         CHECK_AUDIO_PARAM_CHANGE(buffer_filter, c, frame->sample_rate, frame->channel_layout,
104                                  frame->format);
105         buf = ff_get_audio_buffer(buffer_filter->outputs[0], AV_PERM_WRITE,
106                                   frame->nb_samples);
107         if (!buf)
108             return AVERROR(ENOMEM);
109
110         av_samples_copy(buf->extended_data, frame->extended_data,
111                         0, 0, frame->nb_samples,
112                         av_get_channel_layout_nb_channels(frame->channel_layout),
113                         frame->format);
114         break;
115     default:
116         return AVERROR(EINVAL);
117     }
118
119     avfilter_copy_frame_props(buf, frame);
120
121     if ((ret = av_fifo_generic_write(c->fifo, &buf, sizeof(buf), NULL)) < 0) {
122         avfilter_unref_buffer(buf);
123         return ret;
124     }
125
126     return 0;
127 }
128
129 int av_buffersrc_buffer(AVFilterContext *s, AVFilterBufferRef *buf)
130 {
131     BufferSourceContext *c = s->priv;
132     int ret;
133
134     if (!buf) {
135         c->eof = 1;
136         return 0;
137     } else if (c->eof)
138         return AVERROR(EINVAL);
139
140     if (!av_fifo_space(c->fifo) &&
141         (ret = av_fifo_realloc2(c->fifo, av_fifo_size(c->fifo) +
142                                          sizeof(buf))) < 0)
143         return ret;
144
145     switch (s->outputs[0]->type) {
146     case AVMEDIA_TYPE_VIDEO:
147         CHECK_VIDEO_PARAM_CHANGE(s, c, buf->video->w, buf->video->h, buf->format);
148         break;
149     case AVMEDIA_TYPE_AUDIO:
150         CHECK_AUDIO_PARAM_CHANGE(s, c, buf->audio->sample_rate, buf->audio->channel_layout,
151                                  buf->format);
152         break;
153     default:
154         return AVERROR(EINVAL);
155     }
156
157     if ((ret = av_fifo_generic_write(c->fifo, &buf, sizeof(buf), NULL)) < 0)
158         return ret;
159
160     return 0;
161 }
162
163 static av_cold int init_video(AVFilterContext *ctx, const char *args)
164 {
165     BufferSourceContext *c = ctx->priv;
166     char pix_fmt_str[128];
167     int n = 0;
168
169     if (!args ||
170         (n = sscanf(args, "%d:%d:%127[^:]:%d:%d:%d:%d", &c->w, &c->h, pix_fmt_str,
171                     &c->time_base.num, &c->time_base.den,
172                     &c->pixel_aspect.num, &c->pixel_aspect.den)) != 7) {
173         av_log(ctx, AV_LOG_ERROR, "Expected 7 arguments, but %d found in '%s'\n", n, args);
174         return AVERROR(EINVAL);
175     }
176     if ((c->pix_fmt = av_get_pix_fmt(pix_fmt_str)) == AV_PIX_FMT_NONE) {
177         char *tail;
178         c->pix_fmt = strtol(pix_fmt_str, &tail, 10);
179         if (*tail || c->pix_fmt < 0 || c->pix_fmt >= AV_PIX_FMT_NB) {
180             av_log(ctx, AV_LOG_ERROR, "Invalid pixel format string '%s'\n", pix_fmt_str);
181             return AVERROR(EINVAL);
182         }
183     }
184
185     if (!(c->fifo = av_fifo_alloc(sizeof(AVFilterBufferRef*))))
186         return AVERROR(ENOMEM);
187
188     av_log(ctx, AV_LOG_VERBOSE, "w:%d h:%d pixfmt:%s\n", c->w, c->h, av_get_pix_fmt_name(c->pix_fmt));
189     return 0;
190 }
191
192 #define OFFSET(x) offsetof(BufferSourceContext, x)
193 #define A AV_OPT_FLAG_AUDIO_PARAM
194 static const AVOption audio_options[] = {
195     { "time_base",      NULL, OFFSET(time_base),           AV_OPT_TYPE_RATIONAL, { .dbl = 0 }, 0, INT_MAX, A },
196     { "sample_rate",    NULL, OFFSET(sample_rate),         AV_OPT_TYPE_INT,      { .i64 = 0 }, 0, INT_MAX, A },
197     { "sample_fmt",     NULL, OFFSET(sample_fmt_str),      AV_OPT_TYPE_STRING,             .flags = A },
198     { "channel_layout", NULL, OFFSET(channel_layout_str),  AV_OPT_TYPE_STRING,             .flags = A },
199     { NULL },
200 };
201
202 static const AVClass abuffer_class = {
203     .class_name = "abuffer source",
204     .item_name  = av_default_item_name,
205     .option     = audio_options,
206     .version    = LIBAVUTIL_VERSION_INT,
207 };
208
209 static av_cold int init_audio(AVFilterContext *ctx, const char *args)
210 {
211     BufferSourceContext *s = ctx->priv;
212     int ret = 0;
213
214     s->class = &abuffer_class;
215     av_opt_set_defaults(s);
216
217     if ((ret = av_set_options_string(s, args, "=", ":")) < 0) {
218         av_log(ctx, AV_LOG_ERROR, "Error parsing options string: %s.\n", args);
219         goto fail;
220     }
221
222     s->sample_fmt = av_get_sample_fmt(s->sample_fmt_str);
223     if (s->sample_fmt == AV_SAMPLE_FMT_NONE) {
224         av_log(ctx, AV_LOG_ERROR, "Invalid sample format %s.\n",
225                s->sample_fmt_str);
226         ret = AVERROR(EINVAL);
227         goto fail;
228     }
229
230     s->channel_layout = av_get_channel_layout(s->channel_layout_str);
231     if (!s->channel_layout) {
232         av_log(ctx, AV_LOG_ERROR, "Invalid channel layout %s.\n",
233                s->channel_layout_str);
234         ret = AVERROR(EINVAL);
235         goto fail;
236     }
237
238     if (!(s->fifo = av_fifo_alloc(sizeof(AVFilterBufferRef*)))) {
239         ret = AVERROR(ENOMEM);
240         goto fail;
241     }
242
243     if (!s->time_base.num)
244         s->time_base = (AVRational){1, s->sample_rate};
245
246     av_log(ctx, AV_LOG_VERBOSE, "tb:%d/%d samplefmt:%s samplerate: %d "
247            "ch layout:%s\n", s->time_base.num, s->time_base.den, s->sample_fmt_str,
248            s->sample_rate, s->channel_layout_str);
249
250 fail:
251     av_opt_free(s);
252     return ret;
253 }
254
255 static av_cold void uninit(AVFilterContext *ctx)
256 {
257     BufferSourceContext *s = ctx->priv;
258     while (s->fifo && av_fifo_size(s->fifo)) {
259         AVFilterBufferRef *buf;
260         av_fifo_generic_read(s->fifo, &buf, sizeof(buf), NULL);
261         avfilter_unref_buffer(buf);
262     }
263     av_fifo_free(s->fifo);
264     s->fifo = NULL;
265 }
266
267 static int query_formats(AVFilterContext *ctx)
268 {
269     BufferSourceContext *c = ctx->priv;
270     AVFilterChannelLayouts *channel_layouts = NULL;
271     AVFilterFormats *formats = NULL;
272     AVFilterFormats *samplerates = NULL;
273
274     switch (ctx->outputs[0]->type) {
275     case AVMEDIA_TYPE_VIDEO:
276         ff_add_format(&formats, c->pix_fmt);
277         ff_set_common_formats(ctx, formats);
278         break;
279     case AVMEDIA_TYPE_AUDIO:
280         ff_add_format(&formats,           c->sample_fmt);
281         ff_set_common_formats(ctx, formats);
282
283         ff_add_format(&samplerates,       c->sample_rate);
284         ff_set_common_samplerates(ctx, samplerates);
285
286         ff_add_channel_layout(&channel_layouts, c->channel_layout);
287         ff_set_common_channel_layouts(ctx, channel_layouts);
288         break;
289     default:
290         return AVERROR(EINVAL);
291     }
292
293     return 0;
294 }
295
296 static int config_props(AVFilterLink *link)
297 {
298     BufferSourceContext *c = link->src->priv;
299
300     switch (link->type) {
301     case AVMEDIA_TYPE_VIDEO:
302         link->w = c->w;
303         link->h = c->h;
304         link->sample_aspect_ratio = c->pixel_aspect;
305         break;
306     case AVMEDIA_TYPE_AUDIO:
307         link->channel_layout = c->channel_layout;
308         link->sample_rate    = c->sample_rate;
309         break;
310     default:
311         return AVERROR(EINVAL);
312     }
313
314     link->time_base = c->time_base;
315     return 0;
316 }
317
318 static int request_frame(AVFilterLink *link)
319 {
320     BufferSourceContext *c = link->src->priv;
321     AVFilterBufferRef *buf;
322     int ret = 0;
323
324     if (!av_fifo_size(c->fifo)) {
325         if (c->eof)
326             return AVERROR_EOF;
327         return AVERROR(EAGAIN);
328     }
329     av_fifo_generic_read(c->fifo, &buf, sizeof(buf), NULL);
330
331     switch (link->type) {
332     case AVMEDIA_TYPE_VIDEO:
333         if ((ret = ff_start_frame(link, buf)) < 0 ||
334             (ret = ff_draw_slice(link, 0, link->h, 1)) < 0 ||
335             (ret = ff_end_frame(link)) < 0)
336             return ret;
337         break;
338     case AVMEDIA_TYPE_AUDIO:
339         ret = ff_filter_samples(link, buf);
340         break;
341     default:
342         avfilter_unref_bufferp(&buf);
343         return AVERROR(EINVAL);
344     }
345
346     return ret;
347 }
348
349 static int poll_frame(AVFilterLink *link)
350 {
351     BufferSourceContext *c = link->src->priv;
352     int size = av_fifo_size(c->fifo);
353     if (!size && c->eof)
354         return AVERROR_EOF;
355     return size/sizeof(AVFilterBufferRef*);
356 }
357
358 static const AVFilterPad avfilter_vsrc_buffer_outputs[] = {
359     {
360         .name          = "default",
361         .type          = AVMEDIA_TYPE_VIDEO,
362         .request_frame = request_frame,
363         .poll_frame    = poll_frame,
364         .config_props  = config_props,
365     },
366     { NULL }
367 };
368
369 AVFilter avfilter_vsrc_buffer = {
370     .name      = "buffer",
371     .description = NULL_IF_CONFIG_SMALL("Buffer video frames, and make them accessible to the filterchain."),
372     .priv_size = sizeof(BufferSourceContext),
373     .query_formats = query_formats,
374
375     .init      = init_video,
376     .uninit    = uninit,
377
378     .inputs    = NULL,
379     .outputs   = avfilter_vsrc_buffer_outputs,
380 };
381
382 static const AVFilterPad avfilter_asrc_abuffer_outputs[] = {
383     {
384         .name          = "default",
385         .type          = AVMEDIA_TYPE_AUDIO,
386         .request_frame = request_frame,
387         .poll_frame    = poll_frame,
388         .config_props  = config_props,
389     },
390     { NULL }
391 };
392
393 AVFilter avfilter_asrc_abuffer = {
394     .name          = "abuffer",
395     .description   = NULL_IF_CONFIG_SMALL("Buffer audio frames, and make them accessible to the filterchain."),
396     .priv_size     = sizeof(BufferSourceContext),
397     .query_formats = query_formats,
398
399     .init      = init_audio,
400     .uninit    = uninit,
401
402     .inputs    = NULL,
403     .outputs   = avfilter_asrc_abuffer_outputs,
404 };