FFmpeg
vf_stack.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2015 Paul B. Mahol
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 #include "config_components.h"
22 
23 #include "libavutil/avstring.h"
24 #include "libavutil/imgutils.h"
25 #include "libavutil/mem.h"
26 #include "libavutil/opt.h"
27 #include "libavutil/parseutils.h"
28 #include "libavutil/pixdesc.h"
29 
30 #include "avfilter.h"
31 #include "drawutils.h"
32 #include "filters.h"
33 #include "formats.h"
34 #include "framesync.h"
35 #include "video.h"
36 
37 typedef struct StackItem {
38  int x[4], y[4];
39  int linesize[4];
40  int height[4];
41 } StackItem;
42 
43 typedef struct StackContext {
44  const AVClass *class;
46  int nb_inputs;
47  char *layout;
48  int shortest;
51  int nb_planes;
54  uint8_t fillcolor[4];
57 
60 
64 } StackContext;
65 
66 static int query_formats(const AVFilterContext *ctx,
67  AVFilterFormatsConfig **cfg_in,
68  AVFilterFormatsConfig **cfg_out)
69 {
70  const StackContext *s = ctx->priv;
71  int reject_flags = AV_PIX_FMT_FLAG_BITSTREAM |
74 
75  if (s->fillcolor_enable) {
76  return ff_set_common_formats2(ctx, cfg_in, cfg_out,
78  }
79 
80  return ff_set_common_formats2(ctx, cfg_in, cfg_out,
81  ff_formats_pixdesc_filter(0, reject_flags));
82 }
83 
85 {
86  StackContext *s = ctx->priv;
87  int i, ret;
88 
89  if (!strcmp(ctx->filter->name, "vstack"))
90  s->is_vertical = 1;
91 
92  if (!strcmp(ctx->filter->name, "hstack"))
93  s->is_horizontal = 1;
94 
95  if (!strcmp(ctx->filter->name, "xstack")) {
96  int is_grid;
97  if (strcmp(s->fillcolor_str, "none") &&
98  av_parse_color(s->fillcolor, s->fillcolor_str, -1, ctx) >= 0) {
99  s->fillcolor_enable = 1;
100  } else {
101  s->fillcolor_enable = 0;
102  }
103  is_grid = s->nb_grid_rows && s->nb_grid_columns;
104  if (s->layout && is_grid) {
105  av_log(ctx, AV_LOG_ERROR, "Both layout and grid were specified. Only one is allowed.\n");
106  return AVERROR(EINVAL);
107  }
108  if (!s->layout && !is_grid) {
109  if (s->nb_inputs == 2) {
110  s->nb_grid_rows = 1;
111  s->nb_grid_columns = 2;
112  is_grid = 1;
113  } else {
114  av_log(ctx, AV_LOG_ERROR, "No layout or grid specified.\n");
115  return AVERROR(EINVAL);
116  }
117  }
118 
119  if (is_grid)
120  s->nb_inputs = s->nb_grid_rows * s->nb_grid_columns;
121  }
122 
123  s->frames = av_calloc(s->nb_inputs, sizeof(*s->frames));
124  if (!s->frames)
125  return AVERROR(ENOMEM);
126 
127  s->items = av_calloc(s->nb_inputs, sizeof(*s->items));
128  if (!s->items)
129  return AVERROR(ENOMEM);
130 
131  for (i = 0; i < s->nb_inputs; i++) {
132  AVFilterPad pad = { 0 };
133 
134  pad.type = AVMEDIA_TYPE_VIDEO;
135  pad.name = av_asprintf("input%d", i);
136  if (!pad.name)
137  return AVERROR(ENOMEM);
138 
139  if ((ret = ff_append_inpad_free_name(ctx, &pad)) < 0)
140  return ret;
141  }
142 
143  return 0;
144 }
145 
146 static int process_slice(AVFilterContext *ctx, void *arg, int job, int nb_jobs)
147 {
148  StackContext *s = ctx->priv;
149  AVFrame *out = arg;
150  AVFrame **in = s->frames;
151  const int start = (s->nb_inputs * job ) / nb_jobs;
152  const int end = (s->nb_inputs * (job+1)) / nb_jobs;
153 
154  for (int i = start; i < end; i++) {
155  StackItem *item = &s->items[i];
156 
157  for (int p = 0; p < s->nb_planes; p++) {
158  av_image_copy_plane(out->data[p] + out->linesize[p] * item->y[p] + item->x[p],
159  out->linesize[p],
160  in[i]->data[p],
161  in[i]->linesize[p],
162  item->linesize[p], item->height[p]);
163  }
164  }
165 
166  return 0;
167 }
168 
170 {
171  AVFilterContext *ctx = fs->parent;
172  AVFilterLink *outlink = ctx->outputs[0];
173  StackContext *s = fs->opaque;
174  AVFrame **in = s->frames;
175  AVFrame *out;
176  int i, ret;
177 
178  for (i = 0; i < s->nb_inputs; i++) {
179  if ((ret = ff_framesync_get_frame(&s->fs, i, &in[i], 0)) < 0)
180  return ret;
181  }
182 
183  out = ff_get_video_buffer(outlink, outlink->w, outlink->h);
184  if (!out)
185  return AVERROR(ENOMEM);
186  out->pts = av_rescale_q(s->fs.pts, s->fs.time_base, outlink->time_base);
187  out->sample_aspect_ratio = outlink->sample_aspect_ratio;
188 
189  if (s->fillcolor_enable)
190  ff_fill_rectangle(&s->draw, &s->color, out->data, out->linesize,
191  0, 0, outlink->w, outlink->h);
192 
194  FFMIN(s->nb_inputs, ff_filter_get_nb_threads(ctx)));
195 
196  return ff_filter_frame(outlink, out);
197 }
198 
199 static int config_output(AVFilterLink *outlink)
200 {
201  AVFilterContext *ctx = outlink->src;
202  StackContext *s = ctx->priv;
203  FilterLink *il = ff_filter_link(ctx->inputs[0]);
204  FilterLink *ol = ff_filter_link(outlink);
205  AVRational frame_rate = il->frame_rate;
206  AVRational sar = ctx->inputs[0]->sample_aspect_ratio;
207  int height = ctx->inputs[0]->h;
208  int width = ctx->inputs[0]->w;
209  FFFrameSyncIn *in;
210  int i, ret;
211 
212  s->desc = av_pix_fmt_desc_get(outlink->format);
213  if (!s->desc)
214  return AVERROR_BUG;
215 
216  if (s->is_vertical) {
217  for (i = 0; i < s->nb_inputs; i++) {
218  AVFilterLink *inlink = ctx->inputs[i];
219  StackItem *item = &s->items[i];
220 
221  if (ctx->inputs[i]->w != width) {
222  av_log(ctx, AV_LOG_ERROR, "Input %d width %d does not match input %d width %d.\n", i, ctx->inputs[i]->w, 0, width);
223  return AVERROR(EINVAL);
224  }
225 
226  if ((ret = av_image_fill_linesizes(item->linesize, inlink->format, inlink->w)) < 0) {
227  return ret;
228  }
229 
230  item->height[1] = item->height[2] = AV_CEIL_RSHIFT(inlink->h, s->desc->log2_chroma_h);
231  item->height[0] = item->height[3] = inlink->h;
232 
233  if (i) {
234  item->y[1] = item->y[2] = AV_CEIL_RSHIFT(height, s->desc->log2_chroma_h);
235  item->y[0] = item->y[3] = height;
236 
237  height += ctx->inputs[i]->h;
238  }
239  }
240  } else if (s->is_horizontal) {
241  for (i = 0; i < s->nb_inputs; i++) {
242  AVFilterLink *inlink = ctx->inputs[i];
243  StackItem *item = &s->items[i];
244 
245  if (ctx->inputs[i]->h != height) {
246  av_log(ctx, AV_LOG_ERROR, "Input %d height %d does not match input %d height %d.\n", i, ctx->inputs[i]->h, 0, height);
247  return AVERROR(EINVAL);
248  }
249 
250  if ((ret = av_image_fill_linesizes(item->linesize, inlink->format, inlink->w)) < 0) {
251  return ret;
252  }
253 
254  item->height[1] = item->height[2] = AV_CEIL_RSHIFT(inlink->h, s->desc->log2_chroma_h);
255  item->height[0] = item->height[3] = inlink->h;
256 
257  if (i) {
258  if ((ret = av_image_fill_linesizes(item->x, inlink->format, width)) < 0) {
259  return ret;
260  }
261 
262  width += ctx->inputs[i]->w;
263  }
264  }
265  } else if (s->nb_grid_rows && s->nb_grid_columns) {
266  int inw = 0, inh = 0;
267  int k = 0;
268  int row_height;
269  height = 0;
270  width = 0;
271  for (i = 0; i < s->nb_grid_rows; i++, inh += row_height) {
272  row_height = ctx->inputs[i * s->nb_grid_columns]->h;
273  inw = 0;
274  for (int j = 0; j < s->nb_grid_columns; j++, k++) {
275  AVFilterLink *inlink = ctx->inputs[k];
276  StackItem *item = &s->items[k];
277 
278  if (ctx->inputs[k]->h != row_height) {
279  av_log(ctx, AV_LOG_ERROR, "Input %d height %d does not match current row's height %d.\n",
280  k, ctx->inputs[k]->h, row_height);
281  return AVERROR(EINVAL);
282  }
283 
284  if ((ret = av_image_fill_linesizes(item->linesize, inlink->format, inlink->w)) < 0) {
285  return ret;
286  }
287 
288  item->height[1] = item->height[2] = AV_CEIL_RSHIFT(inlink->h, s->desc->log2_chroma_h);
289  item->height[0] = item->height[3] = inlink->h;
290 
291  if ((ret = av_image_fill_linesizes(item->x, inlink->format, inw)) < 0) {
292  return ret;
293  }
294 
295  item->y[1] = item->y[2] = AV_CEIL_RSHIFT(inh, s->desc->log2_chroma_h);
296  item->y[0] = item->y[3] = inh;
297  inw += ctx->inputs[k]->w;
298  }
299  height += row_height;
300  if (!i)
301  width = inw;
302  if (i && width != inw) {
303  av_log(ctx, AV_LOG_ERROR, "Row %d width %d does not match previous row width %d.\n", i, inw, width);
304  return AVERROR(EINVAL);
305  }
306  }
307  } else {
308  char *arg, *p = s->layout, *saveptr = NULL;
309  char *arg2, *p2, *saveptr2 = NULL;
310  char *arg3, *p3, *saveptr3 = NULL;
311  int inw, inh, size;
312 
313  if (s->fillcolor_enable) {
314  const AVFilterLink *inlink = ctx->inputs[0];
315  ff_draw_init2(&s->draw, inlink->format, inlink->colorspace, inlink->color_range, 0);
316  ff_draw_color(&s->draw, &s->color, s->fillcolor);
317  }
318 
319  for (i = 0; i < s->nb_inputs; i++) {
320  AVFilterLink *inlink = ctx->inputs[i];
321  StackItem *item = &s->items[i];
322 
323  if (!(arg = av_strtok(p, "|", &saveptr)))
324  return AVERROR(EINVAL);
325 
326  p = NULL;
327 
328  if ((ret = av_image_fill_linesizes(item->linesize, inlink->format, inlink->w)) < 0) {
329  return ret;
330  }
331 
332  item->height[1] = item->height[2] = AV_CEIL_RSHIFT(inlink->h, s->desc->log2_chroma_h);
333  item->height[0] = item->height[3] = inlink->h;
334 
335  p2 = arg;
336  inw = inh = 0;
337 
338  for (int j = 0; j < 2; j++) {
339  if (!(arg2 = av_strtok(p2, "_", &saveptr2)))
340  return AVERROR(EINVAL);
341 
342  p2 = NULL;
343  p3 = arg2;
344  while ((arg3 = av_strtok(p3, "+", &saveptr3))) {
345  p3 = NULL;
346  if (sscanf(arg3, "w%d", &size) == 1) {
347  if (size == i || size < 0 || size >= s->nb_inputs)
348  return AVERROR(EINVAL);
349 
350  if (!j)
351  inw += ctx->inputs[size]->w;
352  else
353  inh += ctx->inputs[size]->w;
354  } else if (sscanf(arg3, "h%d", &size) == 1) {
355  if (size == i || size < 0 || size >= s->nb_inputs)
356  return AVERROR(EINVAL);
357 
358  if (!j)
359  inw += ctx->inputs[size]->h;
360  else
361  inh += ctx->inputs[size]->h;
362  } else if (sscanf(arg3, "%d", &size) == 1) {
363  if (size < 0)
364  return AVERROR(EINVAL);
365 
366  if (!j)
367  inw += size;
368  else
369  inh += size;
370  } else {
371  return AVERROR(EINVAL);
372  }
373  }
374  }
375 
376  if ((ret = av_image_fill_linesizes(item->x, inlink->format, inw)) < 0) {
377  return ret;
378  }
379 
380  item->y[1] = item->y[2] = AV_CEIL_RSHIFT(inh, s->desc->log2_chroma_h);
381  item->y[0] = item->y[3] = inh;
382 
383  width = FFMAX(width, inlink->w + inw);
384  height = FFMAX(height, inlink->h + inh);
385  }
386  }
387 
388  s->nb_planes = av_pix_fmt_count_planes(outlink->format);
389 
390  outlink->w = width;
391  outlink->h = height;
392  ol->frame_rate = frame_rate;
393  outlink->sample_aspect_ratio = sar;
394 
395  for (i = 1; i < s->nb_inputs; i++) {
396  il = ff_filter_link(ctx->inputs[i]);
397  if (ol->frame_rate.num != il->frame_rate.num ||
398  ol->frame_rate.den != il->frame_rate.den) {
400  "Video inputs have different frame rates, output will be VFR\n");
401  ol->frame_rate = av_make_q(1, 0);
402  break;
403  }
404  }
405 
406  if ((ret = ff_framesync_init(&s->fs, ctx, s->nb_inputs)) < 0)
407  return ret;
408 
409  in = s->fs.in;
410  s->fs.opaque = s;
411  s->fs.on_event = process_frame;
412 
413  for (i = 0; i < s->nb_inputs; i++) {
414  AVFilterLink *inlink = ctx->inputs[i];
415 
416  in[i].time_base = inlink->time_base;
417  in[i].sync = 1;
418  in[i].before = EXT_STOP;
419  in[i].after = s->shortest ? EXT_STOP : EXT_INFINITY;
420  }
421 
422  ret = ff_framesync_configure(&s->fs);
423  outlink->time_base = s->fs.time_base;
424 
425  return ret;
426 }
427 
429 {
430  StackContext *s = ctx->priv;
431 
432  ff_framesync_uninit(&s->fs);
433  av_freep(&s->frames);
434  av_freep(&s->items);
435 }
436 
438 {
439  StackContext *s = ctx->priv;
440  return ff_framesync_activate(&s->fs);
441 }
442 
443 #define OFFSET(x) offsetof(StackContext, x)
444 #define FLAGS AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_FILTERING_PARAM
445 static const AVOption stack_options[] = {
446  { "inputs", "set number of inputs", OFFSET(nb_inputs), AV_OPT_TYPE_INT, {.i64=2}, 2, INT_MAX, .flags = FLAGS },
447  { "shortest", "force termination when the shortest input terminates", OFFSET(shortest), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, .flags = FLAGS },
448  { NULL },
449 };
450 
451 AVFILTER_DEFINE_CLASS_EXT(stack, "(h|v)stack", stack_options);
452 
453 static const AVFilterPad outputs[] = {
454  {
455  .name = "default",
456  .type = AVMEDIA_TYPE_VIDEO,
457  .config_props = config_output,
458  },
459 };
460 
461 #if CONFIG_HSTACK_FILTER
462 
463 const AVFilter ff_vf_hstack = {
464  .name = "hstack",
465  .description = NULL_IF_CONFIG_SMALL("Stack video inputs horizontally."),
466  .priv_class = &stack_class,
467  .priv_size = sizeof(StackContext),
470  .init = init,
471  .uninit = uninit,
472  .activate = activate,
474 };
475 
476 #endif /* CONFIG_HSTACK_FILTER */
477 
478 #if CONFIG_VSTACK_FILTER
479 
480 const AVFilter ff_vf_vstack = {
481  .name = "vstack",
482  .description = NULL_IF_CONFIG_SMALL("Stack video inputs vertically."),
483  .priv_class = &stack_class,
484  .priv_size = sizeof(StackContext),
487  .init = init,
488  .uninit = uninit,
489  .activate = activate,
491 };
492 
493 #endif /* CONFIG_VSTACK_FILTER */
494 
495 #if CONFIG_XSTACK_FILTER
496 
497 static const AVOption xstack_options[] = {
498  { "inputs", "set number of inputs", OFFSET(nb_inputs), AV_OPT_TYPE_INT, {.i64=2}, 2, INT_MAX, .flags = FLAGS },
499  { "layout", "set custom layout", OFFSET(layout), AV_OPT_TYPE_STRING, {.str=NULL}, 0, 0, .flags = FLAGS },
500  { "grid", "set fixed size grid layout", OFFSET(nb_grid_columns), AV_OPT_TYPE_IMAGE_SIZE, {.str=NULL}, 0, 0, .flags = FLAGS },
501  { "shortest", "force termination when the shortest input terminates", OFFSET(shortest), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, .flags = FLAGS },
502  { "fill", "set the color for unused pixels", OFFSET(fillcolor_str), AV_OPT_TYPE_STRING, {.str = "none"}, .flags = FLAGS },
503  { NULL },
504 };
505 
506 AVFILTER_DEFINE_CLASS(xstack);
507 
508 const AVFilter ff_vf_xstack = {
509  .name = "xstack",
510  .description = NULL_IF_CONFIG_SMALL("Stack video inputs into custom layout."),
511  .priv_size = sizeof(StackContext),
512  .priv_class = &xstack_class,
515  .init = init,
516  .uninit = uninit,
517  .activate = activate,
519 };
520 
521 #endif /* CONFIG_XSTACK_FILTER */
ff_get_video_buffer
AVFrame * ff_get_video_buffer(AVFilterLink *link, int w, int h)
Request a picture buffer with a specific set of permissions.
Definition: video.c:116
StackItem::x
int x[4]
Definition: vf_stack.c:38
FFFrameSyncIn::time_base
AVRational time_base
Time base for the incoming frames.
Definition: framesync.h:117
ff_framesync_configure
int ff_framesync_configure(FFFrameSync *fs)
Configure a frame sync structure.
Definition: framesync.c:137
StackContext::fillcolor
uint8_t fillcolor[4]
Definition: vf_stack.c:54
FFDrawColor
Definition: drawutils.h:51
AVERROR
Filter the word “frame” indicates either a video frame or a group of audio as stored in an AVFrame structure Format for each input and each output the list of supported formats For video that means pixel format For audio that means channel sample they are references to shared objects When the negotiation mechanism computes the intersection of the formats supported at each end of a all references to both lists are replaced with a reference to the intersection And when a single format is eventually chosen for a link amongst the remaining all references to the list are updated That means that if a filter requires that its input and output have the same format amongst a supported all it has to do is use a reference to the same list of formats query_formats can leave some formats unset and return AVERROR(EAGAIN) to cause the negotiation mechanism toagain later. That can be used by filters with complex requirements to use the format negotiated on one link to set the formats supported on another. Frame references ownership and permissions
opt.h
StackContext::fillcolor_str
char * fillcolor_str
Definition: vf_stack.c:55
ff_framesync_uninit
void ff_framesync_uninit(FFFrameSync *fs)
Free all memory currently allocated.
Definition: framesync.c:301
out
FILE * out
Definition: movenc.c:55
ff_filter_frame
int ff_filter_frame(AVFilterLink *link, AVFrame *frame)
Send a frame of data to the next filter.
Definition: avfilter.c:1062
av_pix_fmt_desc_get
const AVPixFmtDescriptor * av_pix_fmt_desc_get(enum AVPixelFormat pix_fmt)
Definition: pixdesc.c:3170
av_parse_color
int av_parse_color(uint8_t *rgba_color, const char *color_string, int slen, void *log_ctx)
Put the RGBA values that correspond to color_string in rgba_color.
Definition: parseutils.c:356
ff_framesync_get_frame
int ff_framesync_get_frame(FFFrameSync *fs, unsigned in, AVFrame **rframe, unsigned get)
Get the current frame in an input.
Definition: framesync.c:269
StackContext::fs
FFFrameSync fs
Definition: vf_stack.c:63
ff_set_common_formats2
int ff_set_common_formats2(const AVFilterContext *ctx, AVFilterFormatsConfig **cfg_in, AVFilterFormatsConfig **cfg_out, AVFilterFormats *formats)
Definition: formats.c:1007
inlink
The exact code depends on how similar the blocks are and how related they are to the and needs to apply these operations to the correct inlink or outlink if there are several Macros are available to factor that when no extra processing is inlink
Definition: filter_design.txt:212
av_asprintf
char * av_asprintf(const char *fmt,...)
Definition: avstring.c:115
AVFILTER_DEFINE_CLASS_EXT
AVFILTER_DEFINE_CLASS_EXT(stack, "(h|v)stack", stack_options)
StackContext::color
FFDrawColor color
Definition: vf_stack.c:59
AVFrame
This structure describes decoded (raw) audio or video data.
Definition: frame.h:389
pixdesc.h
AVOption
AVOption.
Definition: opt.h:429
AV_LOG_VERBOSE
#define AV_LOG_VERBOSE
Detailed information.
Definition: log.h:225
FFMAX
#define FFMAX(a, b)
Definition: macros.h:47
AVFilter::name
const char * name
Filter name.
Definition: avfilter.h:205
FFFrameSync
Frame sync structure.
Definition: framesync.h:168
EXT_INFINITY
@ EXT_INFINITY
Extend the frame to infinity.
Definition: framesync.h:75
video.h
StackContext::shortest
int shortest
Definition: vf_stack.c:48
AVFrame::data
uint8_t * data[AV_NUM_DATA_POINTERS]
pointer to the picture/channel planes.
Definition: frame.h:410
av_image_copy_plane
void av_image_copy_plane(uint8_t *dst, int dst_linesize, const uint8_t *src, int src_linesize, int bytewidth, int height)
Copy image plane from src to dst.
Definition: imgutils.c:374
OFFSET
#define OFFSET(x)
Definition: vf_stack.c:443
formats.h
av_pix_fmt_count_planes
int av_pix_fmt_count_planes(enum AVPixelFormat pix_fmt)
Definition: pixdesc.c:3210
uninit
static av_cold void uninit(AVFilterContext *ctx)
Definition: vf_stack.c:428
EXT_STOP
@ EXT_STOP
Completely stop all streams with this one.
Definition: framesync.h:65
AV_PIX_FMT_FLAG_HWACCEL
#define AV_PIX_FMT_FLAG_HWACCEL
Pixel format is an HW accelerated format.
Definition: pixdesc.h:128
FFFrameSyncIn
Input stream structure.
Definition: framesync.h:102
outputs
static const AVFilterPad outputs[]
Definition: vf_stack.c:453
activate
static int activate(AVFilterContext *ctx)
Definition: vf_stack.c:437
StackContext::nb_planes
int nb_planes
Definition: vf_stack.c:51
FFFrameSyncIn::sync
unsigned sync
Synchronization level: frames on input at the highest sync level will generate output frame events.
Definition: framesync.h:160
AVFILTER_FLAG_DYNAMIC_INPUTS
#define AVFILTER_FLAG_DYNAMIC_INPUTS
The number of the filter inputs is not determined just by AVFilter.inputs.
Definition: avfilter.h:141
AVRational::num
int num
Numerator.
Definition: rational.h:59
AVFilterPad
A filter pad used for either input or output.
Definition: filters.h:38
AV_LOG_ERROR
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:209
init
static av_cold int init(AVFilterContext *ctx)
Definition: vf_stack.c:84
av_cold
#define av_cold
Definition: attributes.h:90
av_image_fill_linesizes
int av_image_fill_linesizes(int linesizes[4], enum AVPixelFormat pix_fmt, int width)
Fill plane linesizes for an image with pixel format pix_fmt and width width.
Definition: imgutils.c:89
s
#define s(width, name)
Definition: cbs_vp9.c:198
AV_CEIL_RSHIFT
#define AV_CEIL_RSHIFT(a, b)
Definition: common.h:60
StackItem::height
int height[4]
Definition: vf_stack.c:40
av_strtok
char * av_strtok(char *s, const char *delim, char **saveptr)
Split the string into several tokens which can be accessed by successive calls to av_strtok().
Definition: avstring.c:178
filters.h
StackContext::is_vertical
int is_vertical
Definition: vf_stack.c:49
ctx
AVFormatContext * ctx
Definition: movenc.c:49
av_rescale_q
int64_t av_rescale_q(int64_t a, AVRational bq, AVRational cq)
Rescale a 64-bit integer by 2 rational numbers.
Definition: mathematics.c:142
process_frame
static int process_frame(FFFrameSync *fs)
Definition: vf_stack.c:169
FILTER_OUTPUTS
#define FILTER_OUTPUTS(array)
Definition: filters.h:263
arg
const char * arg
Definition: jacosubdec.c:67
config_output
static int config_output(AVFilterLink *outlink)
Definition: vf_stack.c:199
AVClass
Describe the class of an AVClass context structure.
Definition: log.h:75
NULL
#define NULL
Definition: coverity.c:32
fs
#define fs(width, name, subs,...)
Definition: cbs_vp9.c:200
AVRational
Rational number (pair of numerator and denominator).
Definition: rational.h:58
ff_append_inpad_free_name
int ff_append_inpad_free_name(AVFilterContext *f, AVFilterPad *p)
Definition: avfilter.c:132
AV_OPT_TYPE_IMAGE_SIZE
@ AV_OPT_TYPE_IMAGE_SIZE
Underlying C type is two consecutive integers.
Definition: opt.h:303
parseutils.h
ff_vf_hstack
const AVFilter ff_vf_hstack
AVFILTER_DEFINE_CLASS
#define AVFILTER_DEFINE_CLASS(fname)
Definition: filters.h:273
ff_vf_vstack
const AVFilter ff_vf_vstack
AVFilterFormatsConfig
Lists of formats / etc.
Definition: avfilter.h:111
ff_filter_link
static FilterLink * ff_filter_link(AVFilterLink *link)
Definition: filters.h:197
query_formats
static int query_formats(const AVFilterContext *ctx, AVFilterFormatsConfig **cfg_in, AVFilterFormatsConfig **cfg_out)
Definition: vf_stack.c:66
StackContext::items
StackItem * items
Definition: vf_stack.c:61
NULL_IF_CONFIG_SMALL
#define NULL_IF_CONFIG_SMALL(x)
Return NULL if CONFIG_SMALL is true, otherwise the argument without modification.
Definition: internal.h:94
height
#define height
Definition: dsp.h:85
ff_draw_init2
int ff_draw_init2(FFDrawContext *draw, enum AVPixelFormat format, enum AVColorSpace csp, enum AVColorRange range, unsigned flags)
Init a draw context.
Definition: drawutils.c:95
size
int size
Definition: twinvq_data.h:10344
av_make_q
static AVRational av_make_q(int num, int den)
Create an AVRational.
Definition: rational.h:71
ff_fill_rectangle
void ff_fill_rectangle(FFDrawContext *draw, FFDrawColor *color, uint8_t *dst[], int dst_linesize[], int dst_x, int dst_y, int w, int h)
Fill a rectangle with an uniform color.
Definition: drawutils.c:246
AV_PIX_FMT_FLAG_BITSTREAM
#define AV_PIX_FMT_FLAG_BITSTREAM
All values of a component are bit-wise packed end to end.
Definition: pixdesc.h:124
StackContext::is_horizontal
int is_horizontal
Definition: vf_stack.c:50
StackContext::draw
FFDrawContext draw
Definition: vf_stack.c:58
StackContext::desc
const AVPixFmtDescriptor * desc
Definition: vf_stack.c:45
layout
Filter the word “frame” indicates either a video frame or a group of audio as stored in an AVFrame structure Format for each input and each output the list of supported formats For video that means pixel format For audio that means channel layout
Definition: filter_design.txt:18
ff_formats_pixdesc_filter
AVFilterFormats * ff_formats_pixdesc_filter(unsigned want, unsigned rej)
Construct a formats list containing all pixel formats with certain properties.
Definition: formats.c:553
i
#define i(width, name, range_min, range_max)
Definition: cbs_h2645.c:256
StackContext::nb_grid_columns
int nb_grid_columns
Definition: vf_stack.c:52
FLAGS
#define FLAGS
Definition: vf_stack.c:444
ff_draw_supported_pixel_formats
AVFilterFormats * ff_draw_supported_pixel_formats(unsigned flags)
Return the list of pixel formats supported by the draw functions.
Definition: drawutils.c:662
ff_filter_get_nb_threads
int ff_filter_get_nb_threads(AVFilterContext *ctx)
Get number of threads for current filter instance.
Definition: avfilter.c:841
FILTER_QUERY_FUNC2
#define FILTER_QUERY_FUNC2(func)
Definition: filters.h:239
StackContext::layout
char * layout
Definition: vf_stack.c:47
FFMIN
#define FFMIN(a, b)
Definition: macros.h:49
FFDrawContext
Definition: drawutils.h:36
AVFilterPad::name
const char * name
Pad name.
Definition: filters.h:44
av_calloc
void * av_calloc(size_t nmemb, size_t size)
Definition: mem.c:264
ff_draw_color
void ff_draw_color(FFDrawContext *draw, FFDrawColor *color, const uint8_t rgba[4])
Prepare a color.
Definition: drawutils.c:171
AVFilter
Filter definition.
Definition: avfilter.h:201
ret
ret
Definition: filter_design.txt:187
AVFilterPad::type
enum AVMediaType type
AVFilterPad type.
Definition: filters.h:49
ff_vf_xstack
const AVFilter ff_vf_xstack
ff_framesync_init
int ff_framesync_init(FFFrameSync *fs, AVFilterContext *parent, unsigned nb_in)
Initialize a frame sync structure.
Definition: framesync.c:86
FFFrameSyncIn::before
enum FFFrameSyncExtMode before
Extrapolation mode for timestamps before the first frame.
Definition: framesync.h:107
StackItem::y
int y[4]
Definition: vf_stack.c:38
framesync.h
ff_filter_execute
int ff_filter_execute(AVFilterContext *ctx, avfilter_action_func *func, void *arg, int *ret, int nb_jobs)
Definition: avfilter.c:1667
AVRational::den
int den
Denominator.
Definition: rational.h:60
AV_OPT_TYPE_INT
@ AV_OPT_TYPE_INT
Underlying C type is int.
Definition: opt.h:259
avfilter.h
StackItem::linesize
int linesize[4]
Definition: vf_stack.c:39
AVFilterContext
An instance of a filter.
Definition: avfilter.h:457
StackContext::nb_grid_rows
int nb_grid_rows
Definition: vf_stack.c:53
AVFILTER_FLAG_SLICE_THREADS
#define AVFILTER_FLAG_SLICE_THREADS
The filter supports multithreading by splitting frames into multiple parts and processing them concur...
Definition: avfilter.h:152
AVMEDIA_TYPE_VIDEO
@ AVMEDIA_TYPE_VIDEO
Definition: avutil.h:201
mem.h
StackContext::fillcolor_enable
int fillcolor_enable
Definition: vf_stack.c:56
AVPixFmtDescriptor
Descriptor that unambiguously describes how the bits of a pixel are stored in the up to 4 data planes...
Definition: pixdesc.h:69
StackItem
Definition: vf_stack.c:37
AV_OPT_TYPE_BOOL
@ AV_OPT_TYPE_BOOL
Underlying C type is int.
Definition: opt.h:327
process_slice
static int process_slice(AVFilterContext *ctx, void *arg, int job, int nb_jobs)
Definition: vf_stack.c:146
av_freep
#define av_freep(p)
Definition: tableprint_vlc.h:34
StackContext
Definition: vf_stack.c:43
imgutils.h
AVERROR_BUG
#define AVERROR_BUG
Internal bug, also see AVERROR_BUG2.
Definition: error.h:52
AVFrame::linesize
int linesize[AV_NUM_DATA_POINTERS]
For video, a positive or negative value, which is typically indicating the size in bytes of each pict...
Definition: frame.h:434
av_log
#define av_log(a,...)
Definition: tableprint_vlc.h:27
FFFrameSyncIn::after
enum FFFrameSyncExtMode after
Extrapolation mode for timestamps after the last frame.
Definition: framesync.h:112
ff_framesync_activate
int ff_framesync_activate(FFFrameSync *fs)
Examine the frames in the filter's input and try to produce output.
Definition: framesync.c:352
avstring.h
AV_OPT_TYPE_STRING
@ AV_OPT_TYPE_STRING
Underlying C type is a uint8_t* that is either NULL or points to a C string allocated with the av_mal...
Definition: opt.h:276
width
#define width
Definition: dsp.h:85
drawutils.h
AV_PIX_FMT_FLAG_PAL
#define AV_PIX_FMT_FLAG_PAL
Pixel format has a palette in data[1], values are indexes in this palette.
Definition: pixdesc.h:120
stack_options
static const AVOption stack_options[]
Definition: vf_stack.c:445
StackContext::nb_inputs
int nb_inputs
Definition: vf_stack.c:46
StackContext::frames
AVFrame ** frames
Definition: vf_stack.c:62