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;
53 
54  int64_t eof_pts;
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(channel_layout_str), AV_OPT_TYPE_STRING, {.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  ret = av_channel_layout_from_string(&s->ch_layout, s->channel_layout_str);
160  if (ret < 0) {
161 #if FF_API_OLD_CHANNEL_LAYOUT
162  uint64_t mask;
164  mask = av_get_channel_layout(s->channel_layout_str);
165  if (!mask) {
166 #endif
167  av_log(ctx, AV_LOG_ERROR, "Error parsing channel layout '%s'.\n",
168  s->channel_layout_str);
169  return AVERROR(EINVAL);
170 #if FF_API_OLD_CHANNEL_LAYOUT
171  }
173  av_log(ctx, AV_LOG_WARNING, "Channel layout '%s' uses a deprecated syntax.\n",
174  s->channel_layout_str);
175  av_channel_layout_from_mask(&s->ch_layout, mask);
176 #endif
177  }
178 
179  s->channels = av_calloc(s->ch_layout.nb_channels, sizeof(*s->channels));
180  s->buffers = av_calloc(s->ch_layout.nb_channels, sizeof(*s->buffers));
181  s->input_frames = av_calloc(s->inputs, sizeof(*s->input_frames));
182  if (!s->channels || !s->buffers|| !s->input_frames)
183  return AVERROR(ENOMEM);
184 
185  for (i = 0; i < s->ch_layout.nb_channels; i++) {
186  s->channels[i].out_channel = av_channel_layout_channel_from_index(&s->ch_layout, i);
187  s->channels[i].input = -1;
188  s->channels[i].in_channel_idx = -1;
189  s->channels[i].in_channel = AV_CHAN_NONE;
190  }
191 
192  if ((ret = parse_maps(ctx)) < 0)
193  return ret;
194 
195  for (i = 0; i < s->inputs; i++) {
196  AVFilterPad pad = { 0 };
197 
198  pad.type = AVMEDIA_TYPE_AUDIO;
199  pad.name = av_asprintf("input%d", i);
200  if (!pad.name)
201  return AVERROR(ENOMEM);
202 
203  if ((ret = ff_append_inpad_free_name(ctx, &pad)) < 0)
204  return ret;
205  }
206 
207  return 0;
208 }
209 
211 {
212  JoinContext *s = ctx->priv;
213  int i;
214 
215  for (i = 0; i < s->inputs && s->input_frames; i++) {
216  av_frame_free(&s->input_frames[i]);
217  }
218 
219  av_freep(&s->channels);
220  av_freep(&s->buffers);
221  av_freep(&s->input_frames);
222 }
223 
225 {
226  JoinContext *s = ctx->priv;
228  int i, ret;
229 
230  if ((ret = ff_add_channel_layout(&layouts, &s->ch_layout)) < 0 ||
231  (ret = ff_channel_layouts_ref(layouts, &ctx->outputs[0]->incfg.channel_layouts)) < 0)
232  return ret;
233 
234  for (i = 0; i < ctx->nb_inputs; i++) {
236  if ((ret = ff_channel_layouts_ref(layouts, &ctx->inputs[i]->outcfg.channel_layouts)) < 0)
237  return ret;
238  }
239 
242  return ret;
243 
244  return 0;
245 }
246 
247 typedef struct ChannelList {
248  enum AVChannel *ch;
249  int nb_ch;
250 } ChannelList;
251 
252 static enum AVChannel channel_list_pop(ChannelList *chl, int idx)
253 {
254  enum AVChannel ret = chl->ch[idx];
255  memmove(chl->ch + idx, chl->ch + idx + 1,
256  (chl->nb_ch - idx - 1) * sizeof(*chl->ch));
257  chl->nb_ch--;
258  return ret;
259 }
260 
261 /*
262  * If ch is present in chl, remove it from the list and return it.
263  * Otherwise return AV_CHAN_NONE.
264  */
266 {
267  for (int i = 0; i < chl->nb_ch; i++)
268  if (chl->ch[i] == ch)
269  return channel_list_pop(chl, i);
270  return AV_CHAN_NONE;
271 }
272 
275 {
276  int i;
277 
278  for (i = 0; i < ctx->nb_inputs; i++) {
280  ch->input = i;
281  ch->in_channel = ch->out_channel;
282  return;
283  }
284  }
285 }
286 
289 {
290  int i;
291 
292  for (i = 0; i < ctx->nb_inputs; i++) {
293  if (inputs[i].nb_ch) {
294  ch->input = i;
295  ch->in_channel = channel_list_pop(&inputs[i], 0);
296  return;
297  }
298  }
299 }
300 
301 static int join_config_output(AVFilterLink *outlink)
302 {
303  AVFilterContext *ctx = outlink->src;
304  JoinContext *s = ctx->priv;
305  // unused channels from each input
306  ChannelList *inputs_unused;
307  char inbuf[64], outbuf[64];
308  int i, ret = 0;
309 
310  /* initialize unused channel list for each input */
311  inputs_unused = av_calloc(ctx->nb_inputs, sizeof(*inputs_unused));
312  if (!inputs_unused)
313  return AVERROR(ENOMEM);
314  for (i = 0; i < ctx->nb_inputs; i++) {
315  AVFilterLink *inlink = ctx->inputs[i];
316  AVChannelLayout *chl = &inlink->ch_layout;
317  ChannelList *iu = &inputs_unused[i];
318 
319  iu->nb_ch = chl->nb_channels;
320  iu->ch = av_malloc_array(iu->nb_ch, sizeof(*iu->ch));
321  if (!iu->ch) {
322  ret = AVERROR(ENOMEM);
323  goto fail;
324  }
325 
326  for (int ch_idx = 0; ch_idx < iu->nb_ch; ch_idx++) {
327  iu->ch[ch_idx] = av_channel_layout_channel_from_index(chl, ch_idx);
328  if (iu->ch[ch_idx] < 0) {
329  /* no channel ordering information in this input,
330  * so don't auto-map from it */
331  iu->nb_ch = 0;
332  break;
333  }
334  }
335  }
336 
337  /* process user-specified maps */
338  for (i = 0; i < s->ch_layout.nb_channels; i++) {
339  ChannelMap *ch = &s->channels[i];
341  AVChannelLayout *ichl;
342  ChannelList *iu;
343 
344  if (ch->input < 0)
345  continue;
346 
347  inlink = ctx->inputs[ch->input];
348  ichl = &inlink->ch_layout;
349  iu = &inputs_unused[ch->input];
350 
351  /* get the index for the channels defined by name */
352  if (ch->in_channel != AV_CHAN_NONE) {
354  if (ch->in_channel_idx < 0) {
355  av_channel_name(inbuf, sizeof(inbuf), ch->in_channel);
356  av_log(ctx, AV_LOG_ERROR, "Requested channel %s is not present in "
357  "input stream #%d.\n", inbuf,
358  ch->input);
359  ret = AVERROR(EINVAL);
360  goto fail;
361  }
362  }
363 
364  /* make sure channels specified by index actually exist */
365  if (ch->in_channel_idx >= ichl->nb_channels) {
366  av_log(ctx, AV_LOG_ERROR, "Requested channel with index %d is not "
367  "present in input stream #%d.\n", ch->in_channel_idx, ch->input);
368  ret = AVERROR(EINVAL);
369  goto fail;
370  }
371 
373  }
374 
375  /* guess channel maps when not explicitly defined */
376  /* first try unused matching channels */
377  for (i = 0; i < s->ch_layout.nb_channels; i++) {
378  ChannelMap *ch = &s->channels[i];
379 
380  if (ch->input < 0)
381  guess_map_matching(ctx, ch, inputs_unused);
382  }
383 
384  /* if the above failed, try to find _any_ unused input channel */
385  for (i = 0; i < s->ch_layout.nb_channels; i++) {
386  ChannelMap *ch = &s->channels[i];
387 
388  if (ch->input < 0)
389  guess_map_any(ctx, ch, inputs_unused);
390 
391  if (ch->input < 0) {
392  av_channel_name(outbuf, sizeof(outbuf), ch->out_channel);
393  av_log(ctx, AV_LOG_ERROR, "Could not find input channel for "
394  "output channel '%s'.\n",
395  outbuf);
396  ret = AVERROR(EINVAL);
397  goto fail;
398  }
399 
400  if (ch->in_channel != AV_CHAN_NONE) {
402  &ctx->inputs[ch->input]->ch_layout, ch->in_channel);
403  }
404 
405  av_assert0(ch->in_channel_idx >= 0);
406  }
407 
408  /* print mappings */
409  av_log(ctx, AV_LOG_VERBOSE, "mappings: ");
410  for (i = 0; i < s->ch_layout.nb_channels; i++) {
411  ChannelMap *ch = &s->channels[i];
412  AVFilterLink *inlink = ctx->inputs[ch->input];
413  AVChannelLayout *ichl = &inlink->ch_layout;
415  ichl, ch->in_channel_idx);
416 
417  av_channel_name(inbuf, sizeof(inbuf), in_ch);
418  av_channel_name(outbuf, sizeof(outbuf), ch->out_channel);
419  av_log(ctx, AV_LOG_VERBOSE, "%d.%s(%d) => %s(%d) ", ch->input,
420  inbuf, ch->in_channel_idx,
421  outbuf, i);
422  }
423  av_log(ctx, AV_LOG_VERBOSE, "\n");
424 
425  for (i = 0; i < ctx->nb_inputs; i++) {
426  if (inputs_unused[i].nb_ch == ctx->inputs[i]->ch_layout.nb_channels)
427  av_log(ctx, AV_LOG_WARNING, "No channels are used from input "
428  "stream %d.\n", i);
429  }
430 
431 fail:
432  for (i = 0; i < ctx->nb_inputs; i++)
433  av_freep(&inputs_unused[i].ch);
434  av_freep(&inputs_unused);
435  return ret;
436 }
437 
439 {
440  AVFilterLink *outlink = ctx->outputs[0];
441  JoinContext *s = ctx->priv;
442  AVFrame *frame;
443  int linesize = INT_MAX;
444  int nb_samples = INT_MAX;
445  int nb_buffers = 0;
446  int i, j, ret;
447 
448  for (i = 0; i < ctx->nb_inputs; i++) {
449  if (!s->input_frames[i]) {
450  nb_samples = 0;
451  break;
452  } else {
453  nb_samples = FFMIN(nb_samples, s->input_frames[i]->nb_samples);
454  }
455  }
456  if (!nb_samples)
457  goto eof;
458 
459  /* setup the output frame */
460  frame = av_frame_alloc();
461  if (!frame)
462  return AVERROR(ENOMEM);
463  if (s->ch_layout.nb_channels > FF_ARRAY_ELEMS(frame->data)) {
464  frame->extended_data = av_calloc(s->ch_layout.nb_channels,
465  sizeof(*frame->extended_data));
466  if (!frame->extended_data) {
467  ret = AVERROR(ENOMEM);
468  goto fail;
469  }
470  }
471 
472  /* copy the data pointers */
473  for (i = 0; i < s->ch_layout.nb_channels; i++) {
474  ChannelMap *ch = &s->channels[i];
475  AVFrame *cur = s->input_frames[ch->input];
476  AVBufferRef *buf;
477 
478  frame->extended_data[i] = cur->extended_data[ch->in_channel_idx];
479  linesize = FFMIN(linesize, cur->linesize[0]);
480 
481  /* add the buffer where this plan is stored to the list if it's
482  * not already there */
484  if (!buf) {
485  ret = AVERROR(EINVAL);
486  goto fail;
487  }
488  for (j = 0; j < nb_buffers; j++)
489  if (s->buffers[j]->buffer == buf->buffer)
490  break;
491  if (j == i)
492  s->buffers[nb_buffers++] = buf;
493  }
494 
495  /* create references to the buffers we copied to output */
496  if (nb_buffers > FF_ARRAY_ELEMS(frame->buf)) {
497  frame->nb_extended_buf = nb_buffers - FF_ARRAY_ELEMS(frame->buf);
498  frame->extended_buf = av_calloc(frame->nb_extended_buf,
499  sizeof(*frame->extended_buf));
500  if (!frame->extended_buf) {
501  frame->nb_extended_buf = 0;
502  ret = AVERROR(ENOMEM);
503  goto fail;
504  }
505  }
506  for (i = 0; i < FFMIN(FF_ARRAY_ELEMS(frame->buf), nb_buffers); i++) {
507  frame->buf[i] = av_buffer_ref(s->buffers[i]);
508  if (!frame->buf[i]) {
509  ret = AVERROR(ENOMEM);
510  goto fail;
511  }
512  }
513  for (i = 0; i < frame->nb_extended_buf; i++) {
514  frame->extended_buf[i] = av_buffer_ref(s->buffers[i +
515  FF_ARRAY_ELEMS(frame->buf)]);
516  if (!frame->extended_buf[i]) {
517  ret = AVERROR(ENOMEM);
518  goto fail;
519  }
520  }
521 
522  frame->nb_samples = nb_samples;
523 #if FF_API_OLD_CHANNEL_LAYOUT
525  frame->channel_layout = outlink->channel_layout;
526  frame->channels = outlink->ch_layout.nb_channels;
528 #endif
529  if ((ret = av_channel_layout_copy(&frame->ch_layout, &outlink->ch_layout)) < 0)
530  return ret;
531  frame->sample_rate = outlink->sample_rate;
532  frame->format = outlink->format;
533  frame->pts = s->input_frames[0]->pts;
534  frame->linesize[0] = linesize;
535  if (frame->data != frame->extended_data) {
536  memcpy(frame->data, frame->extended_data, sizeof(*frame->data) *
537  FFMIN(FF_ARRAY_ELEMS(frame->data), s->ch_layout.nb_channels));
538  }
539 
540  s->eof_pts = frame->pts + av_rescale_q(frame->nb_samples,
541  av_make_q(1, outlink->sample_rate),
542  outlink->time_base);
543  ret = ff_filter_frame(outlink, frame);
544 
545  for (i = 0; i < ctx->nb_inputs; i++)
546  av_frame_free(&s->input_frames[i]);
547 
548  return ret;
549 
550 fail:
552  return ret;
553 eof:
554  for (i = 0; i < ctx->nb_inputs; i++) {
555  if (ff_outlink_get_status(ctx->inputs[i]) &&
556  ff_inlink_queued_samples(ctx->inputs[i]) <= 0 &&
557  !s->input_frames[i]) {
558  ff_outlink_set_status(outlink, AVERROR_EOF, s->eof_pts);
559  }
560  }
561 
562  return 0;
563 }
564 
566 {
567  JoinContext *s = ctx->priv;
568  int i, ret, status;
569  int nb_samples = 0;
570  int64_t pts;
571 
573 
574  if (!s->input_frames[0]) {
575  ret = ff_inlink_consume_frame(ctx->inputs[0], &s->input_frames[0]);
576  if (ret < 0) {
577  return ret;
578  } else if (ret == 0 && ff_inlink_acknowledge_status(ctx->inputs[0], &status, &pts)) {
579  ff_outlink_set_status(ctx->outputs[0], status, s->eof_pts);
580  return 0;
581  }
582 
583  if (!s->input_frames[0] && ff_outlink_frame_wanted(ctx->outputs[0])) {
584  ff_inlink_request_frame(ctx->inputs[0]);
585  return 0;
586  }
587  }
588 
589  if (s->input_frames[0])
590  nb_samples = s->input_frames[0]->nb_samples;
591 
592  for (i = 1; i < ctx->nb_inputs && nb_samples > 0; i++) {
593  if (s->input_frames[i])
594  continue;
595  ret = ff_inlink_consume_samples(ctx->inputs[i], nb_samples, nb_samples, &s->input_frames[i]);
596  if (ret < 0) {
597  return ret;
598  } else if (ff_inlink_acknowledge_status(ctx->inputs[i], &status, &pts)) {
599  ff_outlink_set_status(ctx->outputs[0], status, pts);
600  return 0;
601  }
602 
603  if (!s->input_frames[i]) {
604  ff_inlink_request_frame(ctx->inputs[i]);
605  return 0;
606  }
607  }
608 
609  return try_push_frame(ctx);
610 }
611 
613  {
614  .name = "default",
615  .type = AVMEDIA_TYPE_AUDIO,
616  .config_props = join_config_output,
617  },
618 };
619 
621  .name = "join",
622  .description = NULL_IF_CONFIG_SMALL("Join multiple audio streams into "
623  "multi-channel output."),
624  .priv_size = sizeof(JoinContext),
625  .priv_class = &join_class,
626  .init = join_init,
627  .uninit = join_uninit,
628  .activate = activate,
629  .inputs = NULL,
633 };
FF_ENABLE_DEPRECATION_WARNINGS
#define FF_ENABLE_DEPRECATION_WARNINGS
Definition: internal.h:83
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
status
they must not be accessed directly The fifo field contains the frames that are queued in the input for processing by the filter The status_in and status_out fields contains the queued status(EOF or error) of the link
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:999
ff_channel_layouts_ref
int ff_channel_layouts_ref(AVFilterChannelLayouts *f, AVFilterChannelLayouts **ref)
Add *ref as a new reference to f.
Definition: formats.c:591
layouts
enum MovChannelLayoutTag * layouts
Definition: mov_chan.c:330
AVERROR_EOF
#define AVERROR_EOF
End of file.
Definition: error.h:57
av_get_channel_layout
uint64_t av_get_channel_layout(const char *name)
Return a channel layout id that matches name, or 0 if no match is found.
Definition: channel_layout.c:237
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:116
AV_CHAN_NONE
@ AV_CHAN_NONE
Invalid channel index.
Definition: channel_layout.h:43
av_frame_free
void av_frame_free(AVFrame **frame)
Free the frame and any dynamically allocated objects in it, e.g.
Definition: frame.c:116
AVFrame
This structure describes decoded (raw) audio or video data.
Definition: frame.h:325
guess_map_matching
static void guess_map_matching(AVFilterContext *ctx, ChannelMap *ch, ChannelList *inputs)
Definition: af_join.c:273
AVOption
AVOption.
Definition: opt.h:251
FILTER_QUERY_FUNC
#define FILTER_QUERY_FUNC(func)
Definition: internal.h:167
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:739
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:175
AVChannelLayout::nb_channels
int nb_channels
Number of channels in this layout.
Definition: channel_layout.h:300
ChannelList::nb_ch
int nb_ch
Definition: af_join.c:249
channel_list_pop
static enum AVChannel channel_list_pop(ChannelList *chl, int idx)
Definition: af_join.c:252
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:637
formats.h
init
static int init
Definition: av_tx.c:47
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:1394
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
AVChannel
AVChannel
Definition: channel_layout.h:41
fail
#define fail()
Definition: checkasm.h:131
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:224
pts
static int64_t pts
Definition: transcode_aac.c:654
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:116
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:49
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:104
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:749
mask
static const uint16_t mask[17]
Definition: lzw.c:38
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:1511
s
#define s(width, name)
Definition: cbs_vp9.c:256
guess_map_any
static void guess_map_any(AVFilterContext *ctx, ChannelMap *ch, ChannelList *inputs)
Definition: af_join.c:287
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:37
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:1413
NULL
#define NULL
Definition: coverity.c:32
ChannelList::ch
enum AVChannel * ch
Definition: af_join.c:248
ff_append_inpad_free_name
int ff_append_inpad_free_name(AVFilterContext *f, AVFilterPad *p)
Definition: avfilter.c:123
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
ff_add_channel_layout
int ff_add_channel_layout(AVFilterChannelLayouts **l, const AVChannelLayout *channel_layout)
Definition: formats.c:466
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:1348
JoinContext::channel_layout_str
char * channel_layout_str
Definition: af_join.c:51
F
#define F
Definition: af_join.c:71
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:117
AVChannelLayout
An AVChannelLayout holds information about the channel layout of audio data.
Definition: channel_layout.h:290
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:141
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:557
JoinContext
Definition: af_join.c:46
internal.h
join_uninit
static av_cold void join_uninit(AVFilterContext *ctx)
Definition: af_join.c:210
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:101
OFFSET
#define OFFSET(x)
Definition: af_join.c:69
i
#define i(width, name, range_min, range_max)
Definition: cbs_h2645.c:269
AVFrame::extended_data
uint8_t ** extended_data
pointers to the data planes/channels.
Definition: frame.h:386
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:538
AVFilterPad::name
const char * name
Pad name.
Definition: internal.h:55
ff_inlink_queued_samples
int ff_inlink_queued_samples(AVFilterLink *link)
Definition: avfilter.c:1373
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:834
av_calloc
void * av_calloc(size_t nmemb, size_t size)
Definition: mem.c:272
ChannelMap::out_channel
int out_channel
Definition: af_channelmap.c:42
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:794
activate
static int activate(AVFilterContext *ctx)
Definition: af_join.c:565
AVFilter
Filter definition.
Definition: avfilter.h:171
av_channel_layout_from_mask
FF_ENABLE_DEPRECATION_WARNINGS int av_channel_layout_from_mask(AVChannelLayout *channel_layout, uint64_t mask)
Initialize a native channel layout from a bitmask indicating which channels are present.
Definition: channel_layout.c:389
avfilter_af_join_outputs
static const AVFilterPad avfilter_af_join_outputs[]
Definition: af_join.c:612
ret
ret
Definition: filter_design.txt:187
AVFilterPad::type
enum AVMediaType type
AVFilterPad type.
Definition: internal.h:60
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
JoinContext::eof_pts
int64_t eof_pts
Definition: af_join.c:54
channel_layout.h
JoinContext::map
char * map
Definition: af_join.c:50
av_channel_layout_from_string
int av_channel_layout_from_string(AVChannelLayout *channel_layout, const char *str)
Initialize a channel layout from a given string description.
Definition: channel_layout.c:402
JoinContext::channels
ChannelMap * channels
Definition: af_join.c:56
AV_OPT_TYPE_INT
@ AV_OPT_TYPE_INT
Definition: opt.h:225
avfilter.h
MAP_SEPARATOR
#define MAP_SEPARATOR
Definition: af_join.c:82
ChannelMap
Definition: opus.h:147
ff_outlink_get_status
int ff_outlink_get_status(AVFilterLink *link)
Get the status on an output link.
Definition: avfilter.c:1534
AVFilterContext
An instance of a filter.
Definition: avfilter.h:408
FF_DISABLE_DEPRECATION_WARNINGS
#define FF_DISABLE_DEPRECATION_WARNINGS
Definition: internal.h:82
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:301
FILTER_OUTPUTS
#define FILTER_OUTPUTS(array)
Definition: internal.h:191
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:247
ff_af_join
const AVFilter ff_af_join
Definition: af_join.c:620
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:370
av_log
#define av_log(a,...)
Definition: tableprint_vlc.h:27
av_frame_get_plane_buffer
AVBufferRef * av_frame_get_plane_buffer(AVFrame *frame, int plane)
Get the buffer reference a given data plane is stored in.
Definition: frame.c:608
uninit
static av_cold int uninit(AVCodecContext *avctx)
Definition: crystalhd.c:285
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:229
try_push_frame
static int try_push_frame(AVFilterContext *ctx)
Definition: af_join.c:438
channel_list_pop_ch
static enum AVChannel channel_list_pop_ch(ChannelList *chl, enum AVChannel ch)
Definition: af_join.c:265
AVFILTER_DEFINE_CLASS
AVFILTER_DEFINE_CLASS(join)
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:868