FFmpeg
af_join.c
Go to the documentation of this file.
1 /*
2  * This file is part of FFmpeg.
3  *
4  * FFmpeg is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2.1 of the License, or (at your option) any later version.
8  *
9  * FFmpeg is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with FFmpeg; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17  */
18 
19 /**
20  * @file
21  * Audio join filter
22  *
23  * Join multiple audio inputs as different channels in
24  * a single output
25  */
26 
27 #include "libavutil/avassert.h"
28 #include "libavutil/avstring.h"
30 #include "libavutil/common.h"
31 #include "libavutil/opt.h"
32 
33 #include "audio.h"
34 #include "avfilter.h"
35 #include "formats.h"
36 #include "filters.h"
37 #include "internal.h"
38 
39 typedef struct ChannelMap {
40  int input; ///< input stream index
41  int in_channel_idx; ///< index of in_channel in the input stream data
44 } ChannelMap;
45 
46 typedef struct JoinContext {
47  const AVClass *class;
48 
49  int inputs;
50  char *map;
52 
53  int64_t eof_pts;
54  int eof;
55 
57 
58  /**
59  * Temporary storage for input frames, until we get one on each input.
60  */
62 
63  /**
64  * Temporary storage for buffer references, for assembling the output frame.
65  */
67 } JoinContext;
68 
69 #define OFFSET(x) offsetof(JoinContext, x)
70 #define A AV_OPT_FLAG_AUDIO_PARAM
71 #define F AV_OPT_FLAG_FILTERING_PARAM
72 static const AVOption join_options[] = {
73  { "inputs", "Number of input streams.", OFFSET(inputs), AV_OPT_TYPE_INT, { .i64 = 2 }, 1, INT_MAX, A|F },
74  { "channel_layout", "Channel layout of the "
75  "output stream.", OFFSET(ch_layout), AV_OPT_TYPE_CHLAYOUT, {.str = "stereo"}, 0, 0, A|F },
76  { "map", "A comma-separated list of channels maps in the format "
77  "'input_stream.input_channel-output_channel.",
78  OFFSET(map), AV_OPT_TYPE_STRING, .flags = A|F },
79  { NULL }
80 };
81 
82 #define MAP_SEPARATOR '|'
83 
85 
87 {
88  JoinContext *s = ctx->priv;
89  char *cur = s->map;
90 
91  while (cur && *cur) {
92  ChannelMap *map;
93  char *sep, *next, *p;
94  int input_idx, out_ch_idx;
95 
96  next = strchr(cur, MAP_SEPARATOR);
97  if (next)
98  *next++ = 0;
99 
100  /* split the map into input and output parts */
101  if (!(sep = strchr(cur, '-'))) {
102  av_log(ctx, AV_LOG_ERROR, "Missing separator '-' in channel "
103  "map '%s'\n", cur);
104  return AVERROR(EINVAL);
105  }
106  *sep++ = 0;
107 
108  /* parse output channel */
109  out_ch_idx = av_channel_layout_index_from_string(&s->ch_layout, sep);
110  if (out_ch_idx < 0) {
111  av_log(ctx, AV_LOG_ERROR, "Invalid output channel: %s.\n", sep);
112  return AVERROR(EINVAL);
113  }
114 
115  map = &s->channels[out_ch_idx];
116 
117  if (map->input >= 0) {
118  av_log(ctx, AV_LOG_ERROR, "Multiple maps for output channel "
119  "'%s'.\n", sep);
120  return AVERROR(EINVAL);
121  }
122 
123  /* parse input channel */
124  input_idx = strtol(cur, &cur, 0);
125  if (input_idx < 0 || input_idx >= s->inputs) {
126  av_log(ctx, AV_LOG_ERROR, "Invalid input stream index: %d.\n",
127  input_idx);
128  return AVERROR(EINVAL);
129  }
130 
131  if (*cur)
132  cur++;
133 
134  map->input = input_idx;
135  map->in_channel = AV_CHAN_NONE;
136  map->in_channel_idx = strtol(cur, &p, 0);
137  if (p == cur) {
138  /* channel specifier is not a number, handle as channel name */
139  map->in_channel = av_channel_from_string(cur);
140  if (map->in_channel < 0) {
141  av_log(ctx, AV_LOG_ERROR, "Invalid input channel: %s.\n", cur);
142  return AVERROR(EINVAL);
143  }
144  } else if (map->in_channel_idx < 0) {
145  av_log(ctx, AV_LOG_ERROR, "Invalid input channel index: %d\n", map->in_channel_idx);
146  return AVERROR(EINVAL);
147  }
148 
149  cur = next;
150  }
151  return 0;
152 }
153 
155 {
156  JoinContext *s = ctx->priv;
157  int ret, i;
158 
159  s->channels = av_calloc(s->ch_layout.nb_channels, sizeof(*s->channels));
160  s->buffers = av_calloc(s->ch_layout.nb_channels, sizeof(*s->buffers));
161  s->input_frames = av_calloc(s->inputs, sizeof(*s->input_frames));
162  if (!s->channels || !s->buffers|| !s->input_frames)
163  return AVERROR(ENOMEM);
164 
165  for (i = 0; i < s->ch_layout.nb_channels; i++) {
166  s->channels[i].out_channel = av_channel_layout_channel_from_index(&s->ch_layout, i);
167  s->channels[i].input = -1;
168  s->channels[i].in_channel_idx = -1;
169  s->channels[i].in_channel = AV_CHAN_NONE;
170  }
171 
172  if ((ret = parse_maps(ctx)) < 0)
173  return ret;
174 
175  for (i = 0; i < s->inputs; i++) {
176  AVFilterPad pad = { 0 };
177 
178  pad.type = AVMEDIA_TYPE_AUDIO;
179  pad.name = av_asprintf("input%d", i);
180  if (!pad.name)
181  return AVERROR(ENOMEM);
182 
183  if ((ret = ff_append_inpad_free_name(ctx, &pad)) < 0)
184  return ret;
185  }
186 
187  return 0;
188 }
189 
191 {
192  JoinContext *s = ctx->priv;
193  int i;
194 
195  for (i = 0; i < s->inputs && s->input_frames; i++) {
196  av_frame_free(&s->input_frames[i]);
197  }
198 
199  av_freep(&s->channels);
200  av_freep(&s->buffers);
201  av_freep(&s->input_frames);
202 }
203 
205 {
206  JoinContext *s = ctx->priv;
208  int i, ret;
209 
210  if ((ret = ff_add_channel_layout(&layouts, &s->ch_layout)) < 0 ||
211  (ret = ff_channel_layouts_ref(layouts, &ctx->outputs[0]->incfg.channel_layouts)) < 0)
212  return ret;
213 
214  for (i = 0; i < ctx->nb_inputs; i++) {
216  if ((ret = ff_channel_layouts_ref(layouts, &ctx->inputs[i]->outcfg.channel_layouts)) < 0)
217  return ret;
218  }
219 
222  return ret;
223 
224  return 0;
225 }
226 
227 typedef struct ChannelList {
228  enum AVChannel *ch;
229  int nb_ch;
230 } ChannelList;
231 
232 static enum AVChannel channel_list_pop(ChannelList *chl, int idx)
233 {
234  enum AVChannel ret = chl->ch[idx];
235  memmove(chl->ch + idx, chl->ch + idx + 1,
236  (chl->nb_ch - idx - 1) * sizeof(*chl->ch));
237  chl->nb_ch--;
238  return ret;
239 }
240 
241 /*
242  * If ch is present in chl, remove it from the list and return it.
243  * Otherwise return AV_CHAN_NONE.
244  */
246 {
247  for (int i = 0; i < chl->nb_ch; i++)
248  if (chl->ch[i] == ch)
249  return channel_list_pop(chl, i);
250  return AV_CHAN_NONE;
251 }
252 
255 {
256  int i;
257 
258  for (i = 0; i < ctx->nb_inputs; i++) {
260  ch->input = i;
261  ch->in_channel = ch->out_channel;
262  return;
263  }
264  }
265 }
266 
269 {
270  int i;
271 
272  for (i = 0; i < ctx->nb_inputs; i++) {
273  if (inputs[i].nb_ch) {
274  ch->input = i;
275  ch->in_channel = channel_list_pop(&inputs[i], 0);
276  return;
277  }
278  }
279 }
280 
281 static int join_config_output(AVFilterLink *outlink)
282 {
283  AVFilterContext *ctx = outlink->src;
284  JoinContext *s = ctx->priv;
285  // unused channels from each input
286  ChannelList *inputs_unused;
287  char inbuf[64], outbuf[64];
288  int i, ret = 0;
289 
290  /* initialize unused channel list for each input */
291  inputs_unused = av_calloc(ctx->nb_inputs, sizeof(*inputs_unused));
292  if (!inputs_unused)
293  return AVERROR(ENOMEM);
294  for (i = 0; i < ctx->nb_inputs; i++) {
295  AVFilterLink *inlink = ctx->inputs[i];
296  AVChannelLayout *chl = &inlink->ch_layout;
297  ChannelList *iu = &inputs_unused[i];
298 
299  iu->nb_ch = chl->nb_channels;
300  iu->ch = av_malloc_array(iu->nb_ch, sizeof(*iu->ch));
301  if (!iu->ch) {
302  ret = AVERROR(ENOMEM);
303  goto fail;
304  }
305 
306  for (int ch_idx = 0; ch_idx < iu->nb_ch; ch_idx++) {
307  iu->ch[ch_idx] = av_channel_layout_channel_from_index(chl, ch_idx);
308  if (iu->ch[ch_idx] < 0) {
309  /* no channel ordering information in this input,
310  * so don't auto-map from it */
311  iu->nb_ch = 0;
312  break;
313  }
314  }
315  }
316 
317  /* process user-specified maps */
318  for (i = 0; i < s->ch_layout.nb_channels; i++) {
319  ChannelMap *ch = &s->channels[i];
321  AVChannelLayout *ichl;
322  ChannelList *iu;
323 
324  if (ch->input < 0)
325  continue;
326 
327  inlink = ctx->inputs[ch->input];
328  ichl = &inlink->ch_layout;
329  iu = &inputs_unused[ch->input];
330 
331  /* get the index for the channels defined by name */
332  if (ch->in_channel != AV_CHAN_NONE) {
334  if (ch->in_channel_idx < 0) {
335  av_channel_name(inbuf, sizeof(inbuf), ch->in_channel);
336  av_log(ctx, AV_LOG_ERROR, "Requested channel %s is not present in "
337  "input stream #%d.\n", inbuf,
338  ch->input);
339  ret = AVERROR(EINVAL);
340  goto fail;
341  }
342  }
343 
344  /* make sure channels specified by index actually exist */
345  if (ch->in_channel_idx >= ichl->nb_channels) {
346  av_log(ctx, AV_LOG_ERROR, "Requested channel with index %d is not "
347  "present in input stream #%d.\n", ch->in_channel_idx, ch->input);
348  ret = AVERROR(EINVAL);
349  goto fail;
350  }
351 
353  }
354 
355  /* guess channel maps when not explicitly defined */
356  /* first try unused matching channels */
357  for (i = 0; i < s->ch_layout.nb_channels; i++) {
358  ChannelMap *ch = &s->channels[i];
359 
360  if (ch->input < 0)
361  guess_map_matching(ctx, ch, inputs_unused);
362  }
363 
364  /* if the above failed, try to find _any_ unused input channel */
365  for (i = 0; i < s->ch_layout.nb_channels; i++) {
366  ChannelMap *ch = &s->channels[i];
367 
368  if (ch->input < 0)
369  guess_map_any(ctx, ch, inputs_unused);
370 
371  if (ch->input < 0) {
372  av_channel_name(outbuf, sizeof(outbuf), ch->out_channel);
373  av_log(ctx, AV_LOG_ERROR, "Could not find input channel for "
374  "output channel '%s'.\n",
375  outbuf);
376  ret = AVERROR(EINVAL);
377  goto fail;
378  }
379 
380  if (ch->in_channel != AV_CHAN_NONE) {
382  &ctx->inputs[ch->input]->ch_layout, ch->in_channel);
383  }
384 
385  av_assert0(ch->in_channel_idx >= 0);
386  }
387 
388  /* print mappings */
389  av_log(ctx, AV_LOG_VERBOSE, "mappings: ");
390  for (i = 0; i < s->ch_layout.nb_channels; i++) {
391  ChannelMap *ch = &s->channels[i];
392  AVFilterLink *inlink = ctx->inputs[ch->input];
393  AVChannelLayout *ichl = &inlink->ch_layout;
395  ichl, ch->in_channel_idx);
396 
397  av_channel_name(inbuf, sizeof(inbuf), in_ch);
398  av_channel_name(outbuf, sizeof(outbuf), ch->out_channel);
399  av_log(ctx, AV_LOG_VERBOSE, "%d.%s(%d) => %s(%d) ", ch->input,
400  inbuf, ch->in_channel_idx,
401  outbuf, i);
402  }
403  av_log(ctx, AV_LOG_VERBOSE, "\n");
404 
405  for (i = 0; i < ctx->nb_inputs; i++) {
406  if (inputs_unused[i].nb_ch == ctx->inputs[i]->ch_layout.nb_channels)
407  av_log(ctx, AV_LOG_WARNING, "No channels are used from input "
408  "stream %d.\n", i);
409  }
410 
411 fail:
412  for (i = 0; i < ctx->nb_inputs; i++)
413  av_freep(&inputs_unused[i].ch);
414  av_freep(&inputs_unused);
415  return ret;
416 }
417 
419 {
420  AVFilterLink *outlink = ctx->outputs[0];
421  JoinContext *s = ctx->priv;
422  AVFrame *frame;
423  int linesize = INT_MAX;
424  int nb_samples = INT_MAX;
425  int nb_buffers = 0;
426  int i, j, ret;
427 
428  for (i = 0; i < ctx->nb_inputs; i++) {
429  if (!s->input_frames[i]) {
430  nb_samples = 0;
431  break;
432  } else {
433  nb_samples = FFMIN(nb_samples, s->input_frames[i]->nb_samples);
434  }
435  }
436  if (!nb_samples)
437  goto eof;
438 
439  /* setup the output frame */
440  frame = av_frame_alloc();
441  if (!frame)
442  return AVERROR(ENOMEM);
443  if (s->ch_layout.nb_channels > FF_ARRAY_ELEMS(frame->data)) {
444  frame->extended_data = av_calloc(s->ch_layout.nb_channels,
445  sizeof(*frame->extended_data));
446  if (!frame->extended_data) {
447  ret = AVERROR(ENOMEM);
448  goto fail;
449  }
450  }
451 
452  /* copy the data pointers */
453  for (i = 0; i < s->ch_layout.nb_channels; i++) {
454  ChannelMap *ch = &s->channels[i];
455  AVFrame *cur = s->input_frames[ch->input];
456  AVBufferRef *buf;
457 
458  frame->extended_data[i] = cur->extended_data[ch->in_channel_idx];
459  linesize = FFMIN(linesize, cur->linesize[0]);
460 
461  /* add the buffer where this plan is stored to the list if it's
462  * not already there */
464  if (!buf) {
465  ret = AVERROR(EINVAL);
466  goto fail;
467  }
468  for (j = 0; j < nb_buffers; j++)
469  if (s->buffers[j]->buffer == buf->buffer)
470  break;
471  if (j == i)
472  s->buffers[nb_buffers++] = buf;
473  }
474 
475  /* create references to the buffers we copied to output */
476  if (nb_buffers > FF_ARRAY_ELEMS(frame->buf)) {
477  frame->nb_extended_buf = nb_buffers - FF_ARRAY_ELEMS(frame->buf);
478  frame->extended_buf = av_calloc(frame->nb_extended_buf,
479  sizeof(*frame->extended_buf));
480  if (!frame->extended_buf) {
481  frame->nb_extended_buf = 0;
482  ret = AVERROR(ENOMEM);
483  goto fail;
484  }
485  }
486  for (i = 0; i < FFMIN(FF_ARRAY_ELEMS(frame->buf), nb_buffers); i++) {
487  frame->buf[i] = av_buffer_ref(s->buffers[i]);
488  if (!frame->buf[i]) {
489  ret = AVERROR(ENOMEM);
490  goto fail;
491  }
492  }
493  for (i = 0; i < frame->nb_extended_buf; i++) {
494  frame->extended_buf[i] = av_buffer_ref(s->buffers[i +
495  FF_ARRAY_ELEMS(frame->buf)]);
496  if (!frame->extended_buf[i]) {
497  ret = AVERROR(ENOMEM);
498  goto fail;
499  }
500  }
501 
502  frame->nb_samples = nb_samples;
503  frame->duration = av_rescale_q(frame->nb_samples,
504  av_make_q(1, outlink->sample_rate),
505  outlink->time_base);
506 
507  if ((ret = av_channel_layout_copy(&frame->ch_layout, &outlink->ch_layout)) < 0)
508  goto fail;
509  frame->sample_rate = outlink->sample_rate;
510  frame->format = outlink->format;
511  frame->pts = s->input_frames[0]->pts;
512  frame->linesize[0] = linesize;
513  if (frame->data != frame->extended_data) {
514  memcpy(frame->data, frame->extended_data, sizeof(*frame->data) *
515  FFMIN(FF_ARRAY_ELEMS(frame->data), s->ch_layout.nb_channels));
516  }
517 
518  s->eof_pts = frame->pts + av_rescale_q(frame->nb_samples,
519  av_make_q(1, outlink->sample_rate),
520  outlink->time_base);
521  ret = ff_filter_frame(outlink, frame);
522 
523  for (i = 0; i < ctx->nb_inputs; i++)
524  av_frame_free(&s->input_frames[i]);
525 
526  return ret;
527 
528 fail:
530  return ret;
531 eof:
532  for (i = 0; i < ctx->nb_inputs; i++) {
533  if (s->eof &&
534  ff_inlink_queued_samples(ctx->inputs[i]) <= 0 &&
535  !s->input_frames[i]) {
536  ff_outlink_set_status(outlink, AVERROR_EOF, s->eof_pts);
537  break;
538  }
539  }
540 
541  return 0;
542 }
543 
545 {
546  JoinContext *s = ctx->priv;
547  int i, ret, status;
548  int nb_samples = 0;
549  int64_t pts;
550 
552 
553  if (!s->input_frames[0]) {
554  ret = ff_inlink_consume_frame(ctx->inputs[0], &s->input_frames[0]);
555  if (ret < 0) {
556  return ret;
557  } else if (ret == 0 && ff_inlink_acknowledge_status(ctx->inputs[0], &status, &pts)) {
558  s->eof |= status == AVERROR_EOF;
559  }
560 
561  if (!s->eof && !s->input_frames[0] && ff_outlink_frame_wanted(ctx->outputs[0])) {
562  ff_inlink_request_frame(ctx->inputs[0]);
563  return 0;
564  }
565  }
566 
567  if (s->input_frames[0])
568  nb_samples = s->input_frames[0]->nb_samples;
569 
570  for (i = 1; i < ctx->nb_inputs && nb_samples > 0; i++) {
571  if (s->input_frames[i])
572  continue;
573  ret = ff_inlink_consume_samples(ctx->inputs[i], nb_samples, nb_samples, &s->input_frames[i]);
574  if (ret < 0) {
575  return ret;
576  } else if (ff_inlink_acknowledge_status(ctx->inputs[i], &status, &pts)) {
577  s->eof |= status == AVERROR_EOF;
578  }
579 
580  if (!s->eof && !s->input_frames[i]) {
581  ff_inlink_request_frame(ctx->inputs[i]);
582  return 0;
583  }
584  }
585 
586  return try_push_frame(ctx);
587 }
588 
590  {
591  .name = "default",
592  .type = AVMEDIA_TYPE_AUDIO,
593  .config_props = join_config_output,
594  },
595 };
596 
598  .name = "join",
599  .description = NULL_IF_CONFIG_SMALL("Join multiple audio streams into "
600  "multi-channel output."),
601  .priv_size = sizeof(JoinContext),
602  .priv_class = &join_class,
603  .init = join_init,
604  .uninit = join_uninit,
605  .activate = activate,
606  .inputs = NULL,
610 };
AVFilterChannelLayouts
A list of supported channel layouts.
Definition: formats.h:85
AV_LOG_WARNING
#define AV_LOG_WARNING
Something somehow does not look correct.
Definition: log.h:186
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
ff_filter_frame
int ff_filter_frame(AVFilterLink *link, AVFrame *frame)
Send a frame of data to the next filter.
Definition: avfilter.c:1018
ff_channel_layouts_ref
int ff_channel_layouts_ref(AVFilterChannelLayouts *f, AVFilterChannelLayouts **ref)
Add *ref as a new reference to f.
Definition: formats.c:673
layouts
enum MovChannelLayoutTag * layouts
Definition: mov_chan.c:261
AVERROR_EOF
#define AVERROR_EOF
End of file.
Definition: error.h:57
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
JoinContext::eof
int eof
Definition: af_join.c:54
av_frame_free
void av_frame_free(AVFrame **frame)
Free the frame and any dynamically allocated objects in it, e.g.
Definition: frame.c:160
AVFrame
This structure describes decoded (raw) audio or video data.
Definition: frame.h:375
guess_map_matching
static void guess_map_matching(AVFilterContext *ctx, ChannelMap *ch, ChannelList *inputs)
Definition: af_join.c:253
av_channel_layout_channel_from_index
enum AVChannel av_channel_layout_channel_from_index(const AVChannelLayout *channel_layout, unsigned int idx)
Get the channel with the given index in a channel layout.
Definition: channel_layout.c:664
AVOption
AVOption.
Definition: opt.h:346
FILTER_QUERY_FUNC
#define FILTER_QUERY_FUNC(func)
Definition: internal.h:159
AV_LOG_VERBOSE
#define AV_LOG_VERBOSE
Detailed information.
Definition: log.h:196
ff_set_common_all_samplerates
int ff_set_common_all_samplerates(AVFilterContext *ctx)
Equivalent to ff_set_common_samplerates(ctx, ff_all_samplerates())
Definition: formats.c:821
av_buffer_ref
AVBufferRef * av_buffer_ref(const AVBufferRef *buf)
Create a new reference to an AVBuffer.
Definition: buffer.c:103
AVFilter::name
const char * name
Filter name.
Definition: avfilter.h:170
AVChannelLayout::nb_channels
int nb_channels
Number of channels in this layout.
Definition: channel_layout.h:313
ChannelList::nb_ch
int nb_ch
Definition: af_join.c:229
channel_list_pop
static enum AVChannel channel_list_pop(ChannelList *chl, int idx)
Definition: af_join.c:232
formats.h
ff_inlink_consume_frame
int ff_inlink_consume_frame(AVFilterLink *link, AVFrame **rframe)
Take a frame from the link's FIFO and update the link's stats.
Definition: avfilter.c:1445
FF_FILTER_FORWARD_STATUS_BACK_ALL
#define FF_FILTER_FORWARD_STATUS_BACK_ALL(outlink, filter)
Forward the status on an output link to all input links.
Definition: filters.h:212
fail
#define fail()
Definition: checkasm.h:179
ChannelMap::input
int input
input stream index
Definition: af_join.c:40
join_query_formats
static int join_query_formats(AVFilterContext *ctx)
Definition: af_join.c:204
pts
static int64_t pts
Definition: transcode_aac.c:643
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:106
JoinContext::buffers
AVBufferRef ** buffers
Temporary storage for buffer references, for assembling the output frame.
Definition: af_join.c:66
AVFilterPad
A filter pad used for either input or output.
Definition: internal.h:33
JoinContext::input_frames
AVFrame ** input_frames
Temporary storage for input frames, until we get one on each input.
Definition: af_join.c:61
av_frame_alloc
AVFrame * av_frame_alloc(void)
Allocate an AVFrame and set its fields to default values.
Definition: frame.c:148
parse_maps
static int parse_maps(AVFilterContext *ctx)
Definition: af_join.c:86
avassert.h
AV_LOG_ERROR
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:180
FF_ARRAY_ELEMS
#define FF_ARRAY_ELEMS(a)
Definition: sinewin_tablegen.c:29
av_cold
#define av_cold
Definition: attributes.h:90
ff_set_common_formats
int ff_set_common_formats(AVFilterContext *ctx, AVFilterFormats *formats)
A helper for query_formats() which sets all links to the same list of formats.
Definition: formats.c:867
ff_outlink_set_status
static void ff_outlink_set_status(AVFilterLink *link, int status, int64_t pts)
Set the status field of a link from the source filter.
Definition: filters.h:189
ff_inlink_request_frame
void ff_inlink_request_frame(AVFilterLink *link)
Mark that a frame is wanted on the link.
Definition: avfilter.c:1571
s
#define s(width, name)
Definition: cbs_vp9.c:198
guess_map_any
static void guess_map_any(AVFilterContext *ctx, ChannelMap *ch, ChannelList *inputs)
Definition: af_join.c:267
AVMEDIA_TYPE_AUDIO
@ AVMEDIA_TYPE_AUDIO
Definition: avutil.h:202
av_assert0
#define av_assert0(cond)
assert() equivalent, that is always enabled.
Definition: avassert.h:40
av_channel_layout_index_from_string
int av_channel_layout_index_from_string(const AVChannelLayout *channel_layout, const char *str)
Get the index in a channel layout of a channel described by the given string.
Definition: channel_layout.c:738
filters.h
ctx
AVFormatContext * ctx
Definition: movenc.c:48
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
AVClass
Describe the class of an AVClass context structure.
Definition: log.h:66
ff_inlink_consume_samples
int ff_inlink_consume_samples(AVFilterLink *link, unsigned min, unsigned max, AVFrame **rframe)
Take samples from the link's FIFO and update the link's stats.
Definition: avfilter.c:1465
NULL
#define NULL
Definition: coverity.c:32
ChannelList::ch
enum AVChannel * ch
Definition: af_join.c:228
ff_append_inpad_free_name
int ff_append_inpad_free_name(AVFilterContext *f, AVFilterPad *p)
Definition: avfilter.c:131
ChannelMap::in_channel
int in_channel
Definition: af_channelmap.c:41
inputs
these buffered frames must be flushed immediately if a new input produces new the filter must not call request_frame to get more It must just process the frame or queue it The task of requesting more frames is left to the filter s request_frame method or the application If a filter has several inputs
Definition: filter_design.txt:243
AV_OPT_TYPE_CHLAYOUT
@ AV_OPT_TYPE_CHLAYOUT
Definition: opt.h:252
ff_add_channel_layout
int ff_add_channel_layout(AVFilterChannelLayouts **l, const AVChannelLayout *channel_layout)
Definition: formats.c:521
join_options
static const AVOption join_options[]
Definition: af_join.c:72
ff_inlink_acknowledge_status
int ff_inlink_acknowledge_status(AVFilterLink *link, int *rstatus, int64_t *rpts)
Test and acknowledge the change of status on the link.
Definition: avfilter.c:1392
av_frame_get_plane_buffer
AVBufferRef * av_frame_get_plane_buffer(const AVFrame *frame, int plane)
Get the buffer reference a given data plane is stored in.
Definition: frame.c:714
F
#define F
Definition: af_join.c:71
init
int(* init)(AVBSFContext *ctx)
Definition: dts2pts.c:365
JoinContext::ch_layout
AVChannelLayout ch_layout
Definition: af_join.c:51
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:106
AVChannelLayout
An AVChannelLayout holds information about the channel layout of audio data.
Definition: channel_layout.h:303
av_make_q
static AVRational av_make_q(int num, int den)
Create an AVRational.
Definition: rational.h:71
A
#define A
Definition: af_join.c:70
AVBufferRef::buffer
AVBuffer * buffer
Definition: buffer.h:83
ChannelMap::in_channel_idx
int in_channel_idx
index of in_channel in the input stream data
Definition: af_channelmap.c:43
ff_all_channel_layouts
AVFilterChannelLayouts * ff_all_channel_layouts(void)
Construct an empty AVFilterChannelLayouts/AVFilterFormats struct – representing any channel layout (w...
Definition: formats.c:612
JoinContext
Definition: af_join.c:46
internal.h
join_uninit
static av_cold void join_uninit(AVFilterContext *ctx)
Definition: af_join.c:190
AVChannel
AVChannel
Definition: channel_layout.h:47
uninit
static void uninit(AVBSFContext *ctx)
Definition: pcm_rechunk.c:68
OFFSET
#define OFFSET(x)
Definition: af_join.c:69
i
#define i(width, name, range_min, range_max)
Definition: cbs_h2645.c:255
av_channel_name
int av_channel_name(char *buf, size_t buf_size, enum AVChannel channel_id)
Get a human readable string in an abbreviated form describing a given channel.
Definition: channel_layout.c:97
AVFrame::extended_data
uint8_t ** extended_data
pointers to the data planes/channels.
Definition: frame.h:436
av_malloc_array
#define av_malloc_array(a, b)
Definition: tableprint_vlc.h:31
common.h
FFMIN
#define FFMIN(a, b)
Definition: macros.h:49
ff_planar_sample_fmts
AVFilterFormats * ff_planar_sample_fmts(void)
Construct a formats list containing all planar sample formats.
Definition: formats.c:593
AVFilterPad::name
const char * name
Pad name.
Definition: internal.h:39
ff_inlink_queued_samples
int ff_inlink_queued_samples(AVFilterLink *link)
Definition: avfilter.c:1420
av_calloc
void * av_calloc(size_t nmemb, size_t size)
Definition: mem.c:262
ChannelMap::out_channel
int out_channel
Definition: af_channelmap.c:42
activate
static int activate(AVFilterContext *ctx)
Definition: af_join.c:544
AVFilter
Filter definition.
Definition: avfilter.h:166
avfilter_af_join_outputs
static const AVFilterPad avfilter_af_join_outputs[]
Definition: af_join.c:589
ret
ret
Definition: filter_design.txt:187
AVFilterPad::type
enum AVMediaType type
AVFilterPad type.
Definition: internal.h:44
frame
these buffered frames must be flushed immediately if a new input produces new the filter must not call request_frame to get more It must just process the frame or queue it The task of requesting more frames is left to the filter s request_frame method or the application If a filter has several the filter must be ready for frames arriving randomly on any input any filter with several inputs will most likely require some kind of queuing mechanism It is perfectly acceptable to have a limited queue and to drop frames when the inputs are too unbalanced request_frame For filters that do not use the this method is called when a frame is wanted on an output For a it should directly call filter_frame on the corresponding output For a if there are queued frames already one of these frames should be pushed If the filter should request a frame on one of its repeatedly until at least one frame has been pushed Return or at least make progress towards producing a frame
Definition: filter_design.txt:264
JoinContext::inputs
int inputs
Definition: af_join.c:49
av_channel_from_string
enum AVChannel av_channel_from_string(const char *str)
This is the inverse function of av_channel_name().
Definition: channel_layout.c:145
AV_CHAN_NONE
@ AV_CHAN_NONE
Invalid channel index.
Definition: channel_layout.h:49
JoinContext::eof_pts
int64_t eof_pts
Definition: af_join.c:53
status
ov_status_e status
Definition: dnn_backend_openvino.c:120
channel_layout.h
JoinContext::map
char * map
Definition: af_join.c:50
av_channel_layout_index_from_channel
int av_channel_layout_index_from_channel(const AVChannelLayout *channel_layout, enum AVChannel channel)
Get the index of a given channel in a channel layout.
Definition: channel_layout.c:704
JoinContext::channels
ChannelMap * channels
Definition: af_join.c:56
AV_OPT_TYPE_INT
@ AV_OPT_TYPE_INT
Definition: opt.h:235
avfilter.h
MAP_SEPARATOR
#define MAP_SEPARATOR
Definition: af_join.c:82
ChannelMap
Definition: opus_parse.h:48
AVFilterContext
An instance of a filter.
Definition: avfilter.h:407
av_channel_layout_copy
int av_channel_layout_copy(AVChannelLayout *dst, const AVChannelLayout *src)
Make a copy of a channel layout.
Definition: channel_layout.c:439
audio.h
AVBufferRef
A reference to a data buffer.
Definition: buffer.h:82
map
const VDPAUPixFmtMap * map
Definition: hwcontext_vdpau.c:71
join_config_output
static int join_config_output(AVFilterLink *outlink)
Definition: af_join.c:281
FILTER_OUTPUTS
#define FILTER_OUTPUTS(array)
Definition: internal.h:183
av_freep
#define av_freep(p)
Definition: tableprint_vlc.h:34
join_init
static av_cold int join_init(AVFilterContext *ctx)
Definition: af_join.c:154
ChannelList
Definition: af_join.c:227
ff_af_join
const AVFilter ff_af_join
Definition: af_join.c:597
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:420
av_log
#define av_log(a,...)
Definition: tableprint_vlc.h:27
ff_outlink_frame_wanted
the definition of that something depends on the semantic of the filter The callback must examine the status of the filter s links and proceed accordingly The status of output links is stored in the status_in and status_out fields and tested by the ff_outlink_frame_wanted() function. If this function returns true
avstring.h
AV_OPT_TYPE_STRING
@ AV_OPT_TYPE_STRING
Definition: opt.h:239
try_push_frame
static int try_push_frame(AVFilterContext *ctx)
Definition: af_join.c:418
channel_list_pop_ch
static enum AVChannel channel_list_pop_ch(ChannelList *chl, enum AVChannel ch)
Definition: af_join.c:245
AVFILTER_DEFINE_CLASS
AVFILTER_DEFINE_CLASS(join)