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/mem.h"
32 #include "libavutil/opt.h"
33 
34 #include "audio.h"
35 #include "avfilter.h"
36 #include "formats.h"
37 #include "filters.h"
38 #include "internal.h"
39 
40 typedef struct ChannelMap {
41  int input; ///< input stream index
42  int in_channel_idx; ///< index of in_channel in the input stream data
45 } ChannelMap;
46 
47 typedef struct JoinContext {
48  const AVClass *class;
49 
50  int inputs;
51  char *map;
53 
54  int64_t eof_pts;
55  int eof;
56 
58 
59  /**
60  * Temporary storage for input frames, until we get one on each input.
61  */
63 
64  /**
65  * Temporary storage for buffer references, for assembling the output frame.
66  */
68 } JoinContext;
69 
70 #define OFFSET(x) offsetof(JoinContext, x)
71 #define A AV_OPT_FLAG_AUDIO_PARAM
72 #define F AV_OPT_FLAG_FILTERING_PARAM
73 static const AVOption join_options[] = {
74  { "inputs", "Number of input streams.", OFFSET(inputs), AV_OPT_TYPE_INT, { .i64 = 2 }, 1, INT_MAX, A|F },
75  { "channel_layout", "Channel layout of the "
76  "output stream.", OFFSET(ch_layout), AV_OPT_TYPE_CHLAYOUT, {.str = "stereo"}, 0, 0, A|F },
77  { "map", "A comma-separated list of channels maps in the format "
78  "'input_stream.input_channel-output_channel.",
79  OFFSET(map), AV_OPT_TYPE_STRING, .flags = A|F },
80  { NULL }
81 };
82 
83 #define MAP_SEPARATOR '|'
84 
86 
88 {
89  JoinContext *s = ctx->priv;
90  char *cur = s->map;
91 
92  while (cur && *cur) {
93  ChannelMap *map;
94  char *sep, *next, *p;
95  int input_idx, out_ch_idx;
96 
97  next = strchr(cur, MAP_SEPARATOR);
98  if (next)
99  *next++ = 0;
100 
101  /* split the map into input and output parts */
102  if (!(sep = strchr(cur, '-'))) {
103  av_log(ctx, AV_LOG_ERROR, "Missing separator '-' in channel "
104  "map '%s'\n", cur);
105  return AVERROR(EINVAL);
106  }
107  *sep++ = 0;
108 
109  /* parse output channel */
110  out_ch_idx = av_channel_layout_index_from_string(&s->ch_layout, sep);
111  if (out_ch_idx < 0) {
112  av_log(ctx, AV_LOG_ERROR, "Invalid output channel: %s.\n", sep);
113  return AVERROR(EINVAL);
114  }
115 
116  map = &s->channels[out_ch_idx];
117 
118  if (map->input >= 0) {
119  av_log(ctx, AV_LOG_ERROR, "Multiple maps for output channel "
120  "'%s'.\n", sep);
121  return AVERROR(EINVAL);
122  }
123 
124  /* parse input channel */
125  input_idx = strtol(cur, &cur, 0);
126  if (input_idx < 0 || input_idx >= s->inputs) {
127  av_log(ctx, AV_LOG_ERROR, "Invalid input stream index: %d.\n",
128  input_idx);
129  return AVERROR(EINVAL);
130  }
131 
132  if (*cur)
133  cur++;
134 
135  map->input = input_idx;
136  map->in_channel = AV_CHAN_NONE;
137  map->in_channel_idx = strtol(cur, &p, 0);
138  if (p == cur) {
139  /* channel specifier is not a number, handle as channel name */
140  map->in_channel = av_channel_from_string(cur);
141  if (map->in_channel < 0) {
142  av_log(ctx, AV_LOG_ERROR, "Invalid input channel: %s.\n", cur);
143  return AVERROR(EINVAL);
144  }
145  } else if (map->in_channel_idx < 0) {
146  av_log(ctx, AV_LOG_ERROR, "Invalid input channel index: %d\n", map->in_channel_idx);
147  return AVERROR(EINVAL);
148  }
149 
150  cur = next;
151  }
152  return 0;
153 }
154 
156 {
157  JoinContext *s = ctx->priv;
158  int ret, i;
159 
160  s->channels = av_calloc(s->ch_layout.nb_channels, sizeof(*s->channels));
161  s->buffers = av_calloc(s->ch_layout.nb_channels, sizeof(*s->buffers));
162  s->input_frames = av_calloc(s->inputs, sizeof(*s->input_frames));
163  if (!s->channels || !s->buffers|| !s->input_frames)
164  return AVERROR(ENOMEM);
165 
166  for (i = 0; i < s->ch_layout.nb_channels; i++) {
167  s->channels[i].out_channel = av_channel_layout_channel_from_index(&s->ch_layout, i);
168  s->channels[i].input = -1;
169  s->channels[i].in_channel_idx = -1;
170  s->channels[i].in_channel = AV_CHAN_NONE;
171  }
172 
173  if ((ret = parse_maps(ctx)) < 0)
174  return ret;
175 
176  for (i = 0; i < s->inputs; i++) {
177  AVFilterPad pad = { 0 };
178 
179  pad.type = AVMEDIA_TYPE_AUDIO;
180  pad.name = av_asprintf("input%d", i);
181  if (!pad.name)
182  return AVERROR(ENOMEM);
183 
184  if ((ret = ff_append_inpad_free_name(ctx, &pad)) < 0)
185  return ret;
186  }
187 
188  return 0;
189 }
190 
192 {
193  JoinContext *s = ctx->priv;
194  int i;
195 
196  for (i = 0; i < s->inputs && s->input_frames; i++) {
197  av_frame_free(&s->input_frames[i]);
198  }
199 
200  av_freep(&s->channels);
201  av_freep(&s->buffers);
202  av_freep(&s->input_frames);
203 }
204 
206 {
207  JoinContext *s = ctx->priv;
209  int i, ret;
210 
211  if ((ret = ff_add_channel_layout(&layouts, &s->ch_layout)) < 0 ||
212  (ret = ff_channel_layouts_ref(layouts, &ctx->outputs[0]->incfg.channel_layouts)) < 0)
213  return ret;
214 
215  for (i = 0; i < ctx->nb_inputs; i++) {
217  if ((ret = ff_channel_layouts_ref(layouts, &ctx->inputs[i]->outcfg.channel_layouts)) < 0)
218  return ret;
219  }
220 
223  return ret;
224 
225  return 0;
226 }
227 
228 typedef struct ChannelList {
229  enum AVChannel *ch;
230  int nb_ch;
231 } ChannelList;
232 
233 static enum AVChannel channel_list_pop(ChannelList *chl, int idx)
234 {
235  enum AVChannel ret = chl->ch[idx];
236  memmove(chl->ch + idx, chl->ch + idx + 1,
237  (chl->nb_ch - idx - 1) * sizeof(*chl->ch));
238  chl->nb_ch--;
239  return ret;
240 }
241 
242 /*
243  * If ch is present in chl, remove it from the list and return it.
244  * Otherwise return AV_CHAN_NONE.
245  */
247 {
248  for (int i = 0; i < chl->nb_ch; i++)
249  if (chl->ch[i] == ch)
250  return channel_list_pop(chl, i);
251  return AV_CHAN_NONE;
252 }
253 
256 {
257  int i;
258 
259  for (i = 0; i < ctx->nb_inputs; i++) {
261  ch->input = i;
262  ch->in_channel = ch->out_channel;
263  return;
264  }
265  }
266 }
267 
270 {
271  int i;
272 
273  for (i = 0; i < ctx->nb_inputs; i++) {
274  if (inputs[i].nb_ch) {
275  ch->input = i;
276  ch->in_channel = channel_list_pop(&inputs[i], 0);
277  return;
278  }
279  }
280 }
281 
282 static int join_config_output(AVFilterLink *outlink)
283 {
284  AVFilterContext *ctx = outlink->src;
285  JoinContext *s = ctx->priv;
286  // unused channels from each input
287  ChannelList *inputs_unused;
288  char inbuf[64], outbuf[64];
289  int i, ret = 0;
290 
291  /* initialize unused channel list for each input */
292  inputs_unused = av_calloc(ctx->nb_inputs, sizeof(*inputs_unused));
293  if (!inputs_unused)
294  return AVERROR(ENOMEM);
295  for (i = 0; i < ctx->nb_inputs; i++) {
296  AVFilterLink *inlink = ctx->inputs[i];
297  AVChannelLayout *chl = &inlink->ch_layout;
298  ChannelList *iu = &inputs_unused[i];
299 
300  iu->nb_ch = chl->nb_channels;
301  iu->ch = av_malloc_array(iu->nb_ch, sizeof(*iu->ch));
302  if (!iu->ch) {
303  ret = AVERROR(ENOMEM);
304  goto fail;
305  }
306 
307  for (int ch_idx = 0; ch_idx < iu->nb_ch; ch_idx++) {
308  iu->ch[ch_idx] = av_channel_layout_channel_from_index(chl, ch_idx);
309  if (iu->ch[ch_idx] < 0) {
310  /* no channel ordering information in this input,
311  * so don't auto-map from it */
312  iu->nb_ch = 0;
313  break;
314  }
315  }
316  }
317 
318  /* process user-specified maps */
319  for (i = 0; i < s->ch_layout.nb_channels; i++) {
320  ChannelMap *ch = &s->channels[i];
322  AVChannelLayout *ichl;
323  ChannelList *iu;
324 
325  if (ch->input < 0)
326  continue;
327 
328  inlink = ctx->inputs[ch->input];
329  ichl = &inlink->ch_layout;
330  iu = &inputs_unused[ch->input];
331 
332  /* get the index for the channels defined by name */
333  if (ch->in_channel != AV_CHAN_NONE) {
335  if (ch->in_channel_idx < 0) {
336  av_channel_name(inbuf, sizeof(inbuf), ch->in_channel);
337  av_log(ctx, AV_LOG_ERROR, "Requested channel %s is not present in "
338  "input stream #%d.\n", inbuf,
339  ch->input);
340  ret = AVERROR(EINVAL);
341  goto fail;
342  }
343  }
344 
345  /* make sure channels specified by index actually exist */
346  if (ch->in_channel_idx >= ichl->nb_channels) {
347  av_log(ctx, AV_LOG_ERROR, "Requested channel with index %d is not "
348  "present in input stream #%d.\n", ch->in_channel_idx, ch->input);
349  ret = AVERROR(EINVAL);
350  goto fail;
351  }
352 
354  }
355 
356  /* guess channel maps when not explicitly defined */
357  /* first try unused matching channels */
358  for (i = 0; i < s->ch_layout.nb_channels; i++) {
359  ChannelMap *ch = &s->channels[i];
360 
361  if (ch->input < 0)
362  guess_map_matching(ctx, ch, inputs_unused);
363  }
364 
365  /* if the above failed, try to find _any_ unused input channel */
366  for (i = 0; i < s->ch_layout.nb_channels; i++) {
367  ChannelMap *ch = &s->channels[i];
368 
369  if (ch->input < 0)
370  guess_map_any(ctx, ch, inputs_unused);
371 
372  if (ch->input < 0) {
373  av_channel_name(outbuf, sizeof(outbuf), ch->out_channel);
374  av_log(ctx, AV_LOG_ERROR, "Could not find input channel for "
375  "output channel '%s'.\n",
376  outbuf);
377  ret = AVERROR(EINVAL);
378  goto fail;
379  }
380 
381  if (ch->in_channel != AV_CHAN_NONE) {
383  &ctx->inputs[ch->input]->ch_layout, ch->in_channel);
384  }
385 
386  av_assert0(ch->in_channel_idx >= 0);
387  }
388 
389  /* print mappings */
390  av_log(ctx, AV_LOG_VERBOSE, "mappings: ");
391  for (i = 0; i < s->ch_layout.nb_channels; i++) {
392  ChannelMap *ch = &s->channels[i];
393  AVFilterLink *inlink = ctx->inputs[ch->input];
394  AVChannelLayout *ichl = &inlink->ch_layout;
396  ichl, ch->in_channel_idx);
397 
398  av_channel_name(inbuf, sizeof(inbuf), in_ch);
399  av_channel_name(outbuf, sizeof(outbuf), ch->out_channel);
400  av_log(ctx, AV_LOG_VERBOSE, "%d.%s(%d) => %s(%d) ", ch->input,
401  inbuf, ch->in_channel_idx,
402  outbuf, i);
403  }
404  av_log(ctx, AV_LOG_VERBOSE, "\n");
405 
406  for (i = 0; i < ctx->nb_inputs; i++) {
407  if (inputs_unused[i].nb_ch == ctx->inputs[i]->ch_layout.nb_channels)
408  av_log(ctx, AV_LOG_WARNING, "No channels are used from input "
409  "stream %d.\n", i);
410  }
411 
412 fail:
413  for (i = 0; i < ctx->nb_inputs; i++)
414  av_freep(&inputs_unused[i].ch);
415  av_freep(&inputs_unused);
416  return ret;
417 }
418 
420 {
421  AVFilterLink *outlink = ctx->outputs[0];
422  JoinContext *s = ctx->priv;
423  AVFrame *frame;
424  int linesize = INT_MAX;
425  int nb_samples = INT_MAX;
426  int nb_buffers = 0;
427  int i, j, ret;
428 
429  for (i = 0; i < ctx->nb_inputs; i++) {
430  if (!s->input_frames[i]) {
431  nb_samples = 0;
432  break;
433  } else {
434  nb_samples = FFMIN(nb_samples, s->input_frames[i]->nb_samples);
435  }
436  }
437  if (!nb_samples)
438  goto eof;
439 
440  /* setup the output frame */
441  frame = av_frame_alloc();
442  if (!frame)
443  return AVERROR(ENOMEM);
444  if (s->ch_layout.nb_channels > FF_ARRAY_ELEMS(frame->data)) {
445  frame->extended_data = av_calloc(s->ch_layout.nb_channels,
446  sizeof(*frame->extended_data));
447  if (!frame->extended_data) {
448  ret = AVERROR(ENOMEM);
449  goto fail;
450  }
451  }
452 
453  /* copy the data pointers */
454  for (i = 0; i < s->ch_layout.nb_channels; i++) {
455  ChannelMap *ch = &s->channels[i];
456  AVFrame *cur = s->input_frames[ch->input];
457  AVBufferRef *buf;
458 
459  frame->extended_data[i] = cur->extended_data[ch->in_channel_idx];
460  linesize = FFMIN(linesize, cur->linesize[0]);
461 
462  /* add the buffer where this plan is stored to the list if it's
463  * not already there */
465  if (!buf) {
466  ret = AVERROR(EINVAL);
467  goto fail;
468  }
469  for (j = 0; j < nb_buffers; j++)
470  if (s->buffers[j]->buffer == buf->buffer)
471  break;
472  if (j == i)
473  s->buffers[nb_buffers++] = buf;
474  }
475 
476  /* create references to the buffers we copied to output */
477  if (nb_buffers > FF_ARRAY_ELEMS(frame->buf)) {
478  frame->nb_extended_buf = nb_buffers - FF_ARRAY_ELEMS(frame->buf);
479  frame->extended_buf = av_calloc(frame->nb_extended_buf,
480  sizeof(*frame->extended_buf));
481  if (!frame->extended_buf) {
482  frame->nb_extended_buf = 0;
483  ret = AVERROR(ENOMEM);
484  goto fail;
485  }
486  }
487  for (i = 0; i < FFMIN(FF_ARRAY_ELEMS(frame->buf), nb_buffers); i++) {
488  frame->buf[i] = av_buffer_ref(s->buffers[i]);
489  if (!frame->buf[i]) {
490  ret = AVERROR(ENOMEM);
491  goto fail;
492  }
493  }
494  for (i = 0; i < frame->nb_extended_buf; i++) {
495  frame->extended_buf[i] = av_buffer_ref(s->buffers[i +
496  FF_ARRAY_ELEMS(frame->buf)]);
497  if (!frame->extended_buf[i]) {
498  ret = AVERROR(ENOMEM);
499  goto fail;
500  }
501  }
502 
503  frame->nb_samples = nb_samples;
504  frame->duration = av_rescale_q(frame->nb_samples,
505  av_make_q(1, outlink->sample_rate),
506  outlink->time_base);
507 
508  if ((ret = av_channel_layout_copy(&frame->ch_layout, &outlink->ch_layout)) < 0)
509  goto fail;
510  frame->sample_rate = outlink->sample_rate;
511  frame->format = outlink->format;
512  frame->pts = s->input_frames[0]->pts;
513  frame->linesize[0] = linesize;
514  if (frame->data != frame->extended_data) {
515  memcpy(frame->data, frame->extended_data, sizeof(*frame->data) *
516  FFMIN(FF_ARRAY_ELEMS(frame->data), s->ch_layout.nb_channels));
517  }
518 
519  s->eof_pts = frame->pts + av_rescale_q(frame->nb_samples,
520  av_make_q(1, outlink->sample_rate),
521  outlink->time_base);
522  ret = ff_filter_frame(outlink, frame);
523 
524  for (i = 0; i < ctx->nb_inputs; i++)
525  av_frame_free(&s->input_frames[i]);
526 
527  return ret;
528 
529 fail:
531  return ret;
532 eof:
533  for (i = 0; i < ctx->nb_inputs; i++) {
534  if (s->eof &&
535  ff_inlink_queued_samples(ctx->inputs[i]) <= 0 &&
536  !s->input_frames[i]) {
537  ff_outlink_set_status(outlink, AVERROR_EOF, s->eof_pts);
538  break;
539  }
540  }
541 
542  return 0;
543 }
544 
546 {
547  JoinContext *s = ctx->priv;
548  int i, ret, status;
549  int nb_samples = 0;
550  int64_t pts;
551 
553 
554  if (!s->input_frames[0]) {
555  ret = ff_inlink_consume_frame(ctx->inputs[0], &s->input_frames[0]);
556  if (ret < 0) {
557  return ret;
558  } else if (ret == 0 && ff_inlink_acknowledge_status(ctx->inputs[0], &status, &pts)) {
559  s->eof |= status == AVERROR_EOF;
560  }
561 
562  if (!s->eof && !s->input_frames[0] && ff_outlink_frame_wanted(ctx->outputs[0])) {
563  ff_inlink_request_frame(ctx->inputs[0]);
564  return 0;
565  }
566  }
567 
568  if (s->input_frames[0])
569  nb_samples = s->input_frames[0]->nb_samples;
570 
571  for (i = 1; i < ctx->nb_inputs && nb_samples > 0; i++) {
572  if (s->input_frames[i])
573  continue;
574  ret = ff_inlink_consume_samples(ctx->inputs[i], nb_samples, nb_samples, &s->input_frames[i]);
575  if (ret < 0) {
576  return ret;
577  } else if (ff_inlink_acknowledge_status(ctx->inputs[i], &status, &pts)) {
578  s->eof |= status == AVERROR_EOF;
579  }
580 
581  if (!s->eof && !s->input_frames[i]) {
582  ff_inlink_request_frame(ctx->inputs[i]);
583  return 0;
584  }
585  }
586 
587  return try_push_frame(ctx);
588 }
589 
591  {
592  .name = "default",
593  .type = AVMEDIA_TYPE_AUDIO,
594  .config_props = join_config_output,
595  },
596 };
597 
599  .name = "join",
600  .description = NULL_IF_CONFIG_SMALL("Join multiple audio streams into "
601  "multi-channel output."),
602  .priv_size = sizeof(JoinContext),
603  .priv_class = &join_class,
604  .init = join_init,
605  .uninit = join_uninit,
606  .activate = activate,
607  .inputs = NULL,
611 };
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:1015
ff_channel_layouts_ref
int ff_channel_layouts_ref(AVFilterChannelLayouts *f, AVFilterChannelLayouts **ref)
Add *ref as a new reference to f.
Definition: formats.c:674
layouts
enum MovChannelLayoutTag * layouts
Definition: mov_chan.c:337
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:55
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:374
guess_map_matching
static void guess_map_matching(AVFilterContext *ctx, ChannelMap *ch, ChannelList *inputs)
Definition: af_join.c:254
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:665
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:822
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:230
channel_list_pop
static enum AVChannel channel_list_pop(ChannelList *chl, int idx)
Definition: af_join.c:233
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:1442
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:41
join_query_formats
static int join_query_formats(AVFilterContext *ctx)
Definition: af_join.c:205
pts
static int64_t pts
Definition: transcode_aac.c:644
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:67
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:62
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:87
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:868
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:1568
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:268
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:739
filters.h
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
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:1462
NULL
#define NULL
Definition: coverity.c:32
ChannelList::ch
enum AVChannel * ch
Definition: af_join.c:229
ff_append_inpad_free_name
int ff_append_inpad_free_name(AVFilterContext *f, AVFilterPad *p)
Definition: avfilter.c:132
ChannelMap::in_channel
int in_channel
Definition: af_channelmap.c:42
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:522
join_options
static const AVOption join_options[]
Definition: af_join.c:73
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:1389
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:72
init
int(* init)(AVBSFContext *ctx)
Definition: dts2pts.c:366
JoinContext::ch_layout
AVChannelLayout ch_layout
Definition: af_join.c:52
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
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:71
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:44
ff_all_channel_layouts
AVFilterChannelLayouts * ff_all_channel_layouts(void)
Construct an empty AVFilterChannelLayouts/AVFilterFormats struct – representing any channel layout (w...
Definition: formats.c:613
JoinContext
Definition: af_join.c:47
internal.h
join_uninit
static av_cold void join_uninit(AVFilterContext *ctx)
Definition: af_join.c:191
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:70
i
#define i(width, name, range_min, range_max)
Definition: cbs_h2645.c:256
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:98
AVFrame::extended_data
uint8_t ** extended_data
pointers to the data planes/channels.
Definition: frame.h:435
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:594
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:1417
av_calloc
void * av_calloc(size_t nmemb, size_t size)
Definition: mem.c:264
ChannelMap::out_channel
int out_channel
Definition: af_channelmap.c:43
activate
static int activate(AVFilterContext *ctx)
Definition: af_join.c:545
AVFilter
Filter definition.
Definition: avfilter.h:166
avfilter_af_join_outputs
static const AVFilterPad avfilter_af_join_outputs[]
Definition: af_join.c:590
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:50
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:146
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:54
status
ov_status_e status
Definition: dnn_backend_openvino.c:121
channel_layout.h
JoinContext::map
char * map
Definition: af_join.c:51
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:705
JoinContext::channels
ChannelMap * channels
Definition: af_join.c:57
AV_OPT_TYPE_INT
@ AV_OPT_TYPE_INT
Definition: opt.h:235
avfilter.h
MAP_SEPARATOR
#define MAP_SEPARATOR
Definition: af_join.c:83
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:440
mem.h
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:282
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:155
ChannelList
Definition: af_join.c:228
ff_af_join
const AVFilter ff_af_join
Definition: af_join.c:598
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:419
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:419
channel_list_pop_ch
static enum AVChannel channel_list_pop_ch(ChannelList *chl, enum AVChannel ch)
Definition: af_join.c:246
AVFILTER_DEFINE_CLASS
AVFILTER_DEFINE_CLASS(join)