FFmpeg
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
buffersrc.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2008 Vitor Sessak
3  *
4  * This file is part of FFmpeg.
5  *
6  * FFmpeg 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  * FFmpeg 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 FFmpeg; 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 
27 #include "libavutil/common.h"
28 #include "libavutil/fifo.h"
29 #include "libavutil/imgutils.h"
30 #include "libavutil/opt.h"
31 #include "libavutil/samplefmt.h"
32 #include "audio.h"
33 #include "avfilter.h"
34 #include "buffersrc.h"
35 #include "formats.h"
36 #include "internal.h"
37 #include "video.h"
38 #include "avcodec.h"
39 
40 typedef struct {
41  const AVClass *class;
43  AVRational time_base; ///< time_base to set in the output link
44  AVRational frame_rate; ///< frame_rate to set in the output link
46  unsigned warning_limit;
47 
48  /* video only */
49  int w, h;
52  char *sws_param;
53 
54  /* audio only */
58  int channels;
59  uint64_t channel_layout;
61 
62  int eof;
64 
65 #define CHECK_VIDEO_PARAM_CHANGE(s, c, width, height, format)\
66  if (c->w != width || c->h != height || c->pix_fmt != format) {\
67  av_log(s, AV_LOG_INFO, "Changing frame properties on the fly is not supported by all filters.\n");\
68  }
69 
70 #define CHECK_AUDIO_PARAM_CHANGE(s, c, srate, ch_layout, format)\
71  if (c->sample_fmt != format || c->sample_rate != srate ||\
72  c->channel_layout != ch_layout) {\
73  av_log(s, AV_LOG_ERROR, "Changing frame properties on the fly is not supported.\n");\
74  return AVERROR(EINVAL);\
75  }
76 
78  const AVFrame *frame, int flags)
79 {
80  AVFilterBufferRef *picref;
81  int ret;
82 
83  if (!frame) /* NULL for EOF */
84  return av_buffersrc_add_ref(buffer_src, NULL, flags);
85 
86  picref = avfilter_get_buffer_ref_from_frame(buffer_src->outputs[0]->type,
87  frame, AV_PERM_WRITE);
88  if (!picref)
89  return AVERROR(ENOMEM);
90  ret = av_buffersrc_add_ref(buffer_src, picref, flags);
91  picref->buf->data[0] = NULL;
92  avfilter_unref_buffer(picref);
93  return ret;
94 }
95 
97 {
98  return av_buffersrc_add_frame(buffer_filter, frame, 0);
99 }
100 
102 {
103  BufferSourceContext *c = s->priv;
104  AVFilterBufferRef *to_free = NULL;
105  int ret;
106 
107  if (!buf) {
108  c->eof = 1;
109  return 0;
110  } else if (c->eof)
111  return AVERROR(EINVAL);
112 
113  if (!av_fifo_space(c->fifo) &&
114  (ret = av_fifo_realloc2(c->fifo, av_fifo_size(c->fifo) +
115  sizeof(buf))) < 0)
116  return ret;
117 
118  if (!(flags & AV_BUFFERSRC_FLAG_NO_CHECK_FORMAT)) {
119  switch (s->outputs[0]->type) {
120  case AVMEDIA_TYPE_VIDEO:
121  CHECK_VIDEO_PARAM_CHANGE(s, c, buf->video->w, buf->video->h, buf->format);
122  break;
123  case AVMEDIA_TYPE_AUDIO:
124  if (!buf->audio->channel_layout)
127  buf->format);
128  break;
129  default:
130  return AVERROR(EINVAL);
131  }
132  }
133  if (!(flags & AV_BUFFERSRC_FLAG_NO_COPY))
134  to_free = buf = ff_copy_buffer_ref(s->outputs[0], buf);
135  if(!buf)
136  return -1;
137 
138  if ((ret = av_fifo_generic_write(c->fifo, &buf, sizeof(buf), NULL)) < 0) {
139  avfilter_unref_buffer(to_free);
140  return ret;
141  }
142  c->nb_failed_requests = 0;
143  if (c->warning_limit &&
144  av_fifo_size(c->fifo) / sizeof(buf) >= c->warning_limit) {
146  "%d buffers queued in %s, something may be wrong.\n",
147  c->warning_limit,
148  (char *)av_x_if_null(s->name, s->filter->name));
149  c->warning_limit *= 10;
150  }
151 
152  if ((flags & AV_BUFFERSRC_FLAG_PUSH))
153  if ((ret = s->output_pads[0].request_frame(s->outputs[0])) < 0)
154  return ret;
155 
156  return 0;
157 }
158 
159 #ifdef FF_API_BUFFERSRC_BUFFER
160 int av_buffersrc_buffer(AVFilterContext *s, AVFilterBufferRef *buf)
161 {
163 }
164 #endif
165 
167 {
168  return ((BufferSourceContext *)buffer_src->priv)->nb_failed_requests;
169 }
170 
171 #define OFFSET(x) offsetof(BufferSourceContext, x)
172 #define FLAGS AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_VIDEO_PARAM
173 static const AVOption buffer_options[] = {
174  { "time_base", NULL, OFFSET(time_base), AV_OPT_TYPE_RATIONAL, { .dbl = 0 }, 0, INT_MAX, FLAGS },
175  { "frame_rate", NULL, OFFSET(frame_rate), AV_OPT_TYPE_RATIONAL, { .dbl = 0 }, 0, INT_MAX, FLAGS },
176  { "video_size", NULL, OFFSET(w), AV_OPT_TYPE_IMAGE_SIZE, .flags = FLAGS },
177  { "pix_fmt", NULL, OFFSET(pix_fmt), AV_OPT_TYPE_PIXEL_FMT, .flags = FLAGS },
178  { "pixel_aspect", NULL, OFFSET(pixel_aspect), AV_OPT_TYPE_RATIONAL, { .dbl = 0 }, 0, INT_MAX, FLAGS },
179  { "sws_param", NULL, OFFSET(sws_param), AV_OPT_TYPE_STRING, .flags = FLAGS },
180  { NULL },
181 };
182 #undef FLAGS
183 
185 
186 static av_cold int init_video(AVFilterContext *ctx, const char *args)
187 {
188  BufferSourceContext *c = ctx->priv;
189  char pix_fmt_str[128], sws_param[256] = "", *colon, *equal;
190  int ret, n = 0;
191 
192  c->class = &buffer_class;
193 
194  if (!args) {
195  av_log(ctx, AV_LOG_ERROR, "Arguments required\n");
196  return AVERROR(EINVAL);
197  }
198  colon = strchr(args, ':');
199  equal = strchr(args, '=');
200  if (equal && (!colon || equal < colon)) {
202  ret = av_set_options_string(c, args, "=", ":");
203  if (ret < 0)
204  goto fail;
205  } else {
206  if ((n = sscanf(args, "%d:%d:%127[^:]:%d:%d:%d:%d:%255c", &c->w, &c->h, pix_fmt_str,
207  &c->time_base.num, &c->time_base.den,
208  &c->pixel_aspect.num, &c->pixel_aspect.den, sws_param)) < 7) {
209  av_log(ctx, AV_LOG_ERROR, "Expected at least 7 arguments, but only %d found in '%s'\n", n, args);
210  ret = AVERROR(EINVAL);
211  goto fail;
212  }
213  av_log(ctx, AV_LOG_WARNING, "Flat options syntax is deprecated, use key=value pairs\n");
214 
215  if ((ret = ff_parse_pixel_format(&c->pix_fmt, pix_fmt_str, ctx)) < 0)
216  goto fail;
217  c->sws_param = av_strdup(sws_param);
218  if (!c->sws_param) {
219  ret = AVERROR(ENOMEM);
220  goto fail;
221  }
222  }
223 
224  if (!(c->fifo = av_fifo_alloc(sizeof(AVFilterBufferRef*)))) {
225  ret = AVERROR(ENOMEM);
226  goto fail;
227  }
228 
229  av_log(ctx, AV_LOG_VERBOSE, "w:%d h:%d pixfmt:%s tb:%d/%d fr:%d/%d sar:%d/%d sws_param:%s\n",
230  c->w, c->h, av_get_pix_fmt_name(c->pix_fmt),
232  c->pixel_aspect.num, c->pixel_aspect.den, (char *)av_x_if_null(c->sws_param, ""));
233  c->warning_limit = 100;
234  return 0;
235 
236 fail:
237  av_opt_free(c);
238  return ret;
239 }
240 
241 #define FLAGS AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_AUDIO_PARAM
242 static const AVOption abuffer_options[] = {
243  { "time_base", NULL, OFFSET(time_base), AV_OPT_TYPE_RATIONAL, { .dbl = 0 }, 0, INT_MAX, FLAGS },
244  { "sample_rate", NULL, OFFSET(sample_rate), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, INT_MAX, FLAGS },
245  { "sample_fmt", NULL, OFFSET(sample_fmt_str), AV_OPT_TYPE_STRING, .flags = FLAGS },
246  { "channels", NULL, OFFSET(channels), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, INT_MAX, FLAGS },
247  { "channel_layout", NULL, OFFSET(channel_layout_str), AV_OPT_TYPE_STRING, .flags = FLAGS },
248  { NULL },
249 };
250 
251 AVFILTER_DEFINE_CLASS(abuffer);
252 
253 static av_cold int init_audio(AVFilterContext *ctx, const char *args)
254 {
255  BufferSourceContext *s = ctx->priv;
256  int ret = 0;
257 
258  s->class = &abuffer_class;
260 
261  if ((ret = av_set_options_string(s, args, "=", ":")) < 0)
262  goto fail;
263 
265  if (s->sample_fmt == AV_SAMPLE_FMT_NONE) {
266  av_log(ctx, AV_LOG_ERROR, "Invalid sample format '%s'\n",
267  s->sample_fmt_str);
268  ret = AVERROR(EINVAL);
269  goto fail;
270  }
271 
272  if (s->channel_layout_str) {
273  int n;
274  /* TODO reindent */
276  if (!s->channel_layout) {
277  av_log(ctx, AV_LOG_ERROR, "Invalid channel layout '%s'\n",
278  s->channel_layout_str);
279  ret = AVERROR(EINVAL);
280  goto fail;
281  }
283  if (s->channels) {
284  if (n != s->channels) {
285  av_log(ctx, AV_LOG_ERROR,
286  "Mismatching channel count %d and layout '%s' "
287  "(%d channels)\n",
288  s->channels, s->channel_layout_str, n);
289  ret = AVERROR(EINVAL);
290  goto fail;
291  }
292  }
293  s->channels = n;
294  } else if (!s->channels) {
295  av_log(ctx, AV_LOG_ERROR, "Neither number of channels nor "
296  "channel layout specified\n");
297  ret = AVERROR(EINVAL);
298  goto fail;
299  }
300 
301  if (!(s->fifo = av_fifo_alloc(sizeof(AVFilterBufferRef*)))) {
302  ret = AVERROR(ENOMEM);
303  goto fail;
304  }
305 
306  if (!s->time_base.num)
307  s->time_base = (AVRational){1, s->sample_rate};
308 
309  av_log(ctx, AV_LOG_VERBOSE,
310  "tb:%d/%d samplefmt:%s samplerate:%d chlayout:%s\n",
313  s->warning_limit = 100;
314 
315 fail:
316  av_opt_free(s);
317  return ret;
318 }
319 
320 static av_cold void uninit(AVFilterContext *ctx)
321 {
322  BufferSourceContext *s = ctx->priv;
323  while (s->fifo && av_fifo_size(s->fifo)) {
324  AVFilterBufferRef *buf;
325  av_fifo_generic_read(s->fifo, &buf, sizeof(buf), NULL);
327  }
328  av_fifo_free(s->fifo);
329  s->fifo = NULL;
330  av_freep(&s->sws_param);
331 }
332 
334 {
335  BufferSourceContext *c = ctx->priv;
336  AVFilterChannelLayouts *channel_layouts = NULL;
338  AVFilterFormats *samplerates = NULL;
339 
340  switch (ctx->outputs[0]->type) {
341  case AVMEDIA_TYPE_VIDEO:
342  ff_add_format(&formats, c->pix_fmt);
343  ff_set_common_formats(ctx, formats);
344  break;
345  case AVMEDIA_TYPE_AUDIO:
346  ff_add_format(&formats, c->sample_fmt);
347  ff_set_common_formats(ctx, formats);
348 
349  ff_add_format(&samplerates, c->sample_rate);
350  ff_set_common_samplerates(ctx, samplerates);
351 
352  ff_add_channel_layout(&channel_layouts,
355  ff_set_common_channel_layouts(ctx, channel_layouts);
356  break;
357  default:
358  return AVERROR(EINVAL);
359  }
360 
361  return 0;
362 }
363 
364 static int config_props(AVFilterLink *link)
365 {
366  BufferSourceContext *c = link->src->priv;
367 
368  switch (link->type) {
369  case AVMEDIA_TYPE_VIDEO:
370  link->w = c->w;
371  link->h = c->h;
373  break;
374  case AVMEDIA_TYPE_AUDIO:
375  if (!c->channel_layout)
376  c->channel_layout = link->channel_layout;
377  break;
378  default:
379  return AVERROR(EINVAL);
380  }
381 
382  link->time_base = c->time_base;
383  link->frame_rate = c->frame_rate;
384  return 0;
385 }
386 
387 static int request_frame(AVFilterLink *link)
388 {
389  BufferSourceContext *c = link->src->priv;
390  AVFilterBufferRef *buf;
391 
392  if (!av_fifo_size(c->fifo)) {
393  if (c->eof)
394  return AVERROR_EOF;
395  c->nb_failed_requests++;
396  return AVERROR(EAGAIN);
397  }
398  av_fifo_generic_read(c->fifo, &buf, sizeof(buf), NULL);
399 
400  return ff_filter_frame(link, buf);
401 }
402 
403 static int poll_frame(AVFilterLink *link)
404 {
405  BufferSourceContext *c = link->src->priv;
406  int size = av_fifo_size(c->fifo);
407  if (!size && c->eof)
408  return AVERROR_EOF;
409  return size/sizeof(AVFilterBufferRef*);
410 }
411 
413  {
414  .name = "default",
415  .type = AVMEDIA_TYPE_VIDEO,
416  .request_frame = request_frame,
417  .poll_frame = poll_frame,
418  .config_props = config_props,
419  },
420  { NULL }
421 };
422 
424  .name = "buffer",
425  .description = NULL_IF_CONFIG_SMALL("Buffer video frames, and make them accessible to the filterchain."),
426  .priv_size = sizeof(BufferSourceContext),
428 
429  .init = init_video,
430  .uninit = uninit,
431 
432  .inputs = NULL,
433  .outputs = avfilter_vsrc_buffer_outputs,
434  .priv_class = &buffer_class,
435 };
436 
438  {
439  .name = "default",
440  .type = AVMEDIA_TYPE_AUDIO,
441  .request_frame = request_frame,
442  .poll_frame = poll_frame,
443  .config_props = config_props,
444  },
445  { NULL }
446 };
447 
449  .name = "abuffer",
450  .description = NULL_IF_CONFIG_SMALL("Buffer audio frames, and make them accessible to the filterchain."),
451  .priv_size = sizeof(BufferSourceContext),
453 
454  .init = init_audio,
455  .uninit = uninit,
456 
457  .inputs = NULL,
458  .outputs = avfilter_asrc_abuffer_outputs,
459  .priv_class = &abuffer_class,
460 };