af_amerge.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2011 Nicolas George <nicolas.george@normalesup.org>
3  *
4  * This file is part of FFmpeg.
5  *
6  * FFmpeg is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * FFmpeg is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with FFmpeg; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19  */
20 
21 /**
22  * @file
23  * Audio merging filter
24  */
25 
26 #include "libavutil/avstring.h"
27 #include "libavutil/bprint.h"
29 #include "libavutil/opt.h"
30 #include "libswresample/swresample.h" // only for SWR_CH_MAX
31 #include "avfilter.h"
32 #include "audio.h"
33 #include "bufferqueue.h"
34 #include "internal.h"
35 
36 typedef struct {
37  const AVClass *class;
38  int nb_inputs;
39  int route[SWR_CH_MAX]; /**< channels routing, see copy_samples */
40  int bps;
41  struct amerge_input {
42  struct FFBufQueue queue;
43  int nb_ch; /**< number of channels for the input */
45  int pos;
46  } *in;
48 
49 #define OFFSET(x) offsetof(AMergeContext, x)
50 #define FLAGS AV_OPT_FLAG_AUDIO_PARAM|AV_OPT_FLAG_FILTERING_PARAM
51 
52 static const AVOption amerge_options[] = {
53  { "inputs", "specify the number of inputs", OFFSET(nb_inputs),
54  AV_OPT_TYPE_INT, { .i64 = 2 }, 2, SWR_CH_MAX, FLAGS },
55  {0}
56 };
57 
58 AVFILTER_DEFINE_CLASS(amerge);
59 
60 static av_cold void uninit(AVFilterContext *ctx)
61 {
62  AMergeContext *am = ctx->priv;
63  int i;
64 
65  for (i = 0; i < am->nb_inputs; i++) {
66  if (am->in)
68  if (ctx->input_pads)
69  av_freep(&ctx->input_pads[i].name);
70  }
71  av_freep(&am->in);
72 }
73 
75 {
76  AMergeContext *am = ctx->priv;
77  int64_t inlayout[SWR_CH_MAX], outlayout = 0;
80  int i, overlap = 0, nb_ch = 0;
81 
82  for (i = 0; i < am->nb_inputs; i++) {
83  if (!ctx->inputs[i]->in_channel_layouts ||
86  "No channel layout for input %d\n", i + 1);
87  return AVERROR(EAGAIN);
88  }
89  inlayout[i] = ctx->inputs[i]->in_channel_layouts->channel_layouts[0];
90  if (ctx->inputs[i]->in_channel_layouts->nb_channel_layouts > 1) {
91  char buf[256];
92  av_get_channel_layout_string(buf, sizeof(buf), 0, inlayout[i]);
93  av_log(ctx, AV_LOG_INFO, "Using \"%s\" for input %d\n", buf, i + 1);
94  }
95  am->in[i].nb_ch = av_get_channel_layout_nb_channels(inlayout[i]);
96  if (outlayout & inlayout[i])
97  overlap++;
98  outlayout |= inlayout[i];
99  nb_ch += am->in[i].nb_ch;
100  }
101  if (nb_ch > SWR_CH_MAX) {
102  av_log(ctx, AV_LOG_ERROR, "Too many channels (max %d)\n", SWR_CH_MAX);
103  return AVERROR(EINVAL);
104  }
105  if (overlap) {
106  av_log(ctx, AV_LOG_WARNING,
107  "Input channel layouts overlap: "
108  "output layout will be determined by the number of distinct input channels\n");
109  for (i = 0; i < nb_ch; i++)
110  am->route[i] = i;
111  outlayout = av_get_default_channel_layout(nb_ch);
112  if (!outlayout)
113  outlayout = ((int64_t)1 << nb_ch) - 1;
114  } else {
115  int *route[SWR_CH_MAX];
116  int c, out_ch_number = 0;
117 
118  route[0] = am->route;
119  for (i = 1; i < am->nb_inputs; i++)
120  route[i] = route[i - 1] + am->in[i - 1].nb_ch;
121  for (c = 0; c < 64; c++)
122  for (i = 0; i < am->nb_inputs; i++)
123  if ((inlayout[i] >> c) & 1)
124  *(route[i]++) = out_ch_number++;
125  }
127  ff_set_common_formats(ctx, formats);
128  for (i = 0; i < am->nb_inputs; i++) {
129  layouts = NULL;
130  ff_add_channel_layout(&layouts, inlayout[i]);
132  }
133  layouts = NULL;
134  ff_add_channel_layout(&layouts, outlayout);
137  return 0;
138 }
139 
140 static int config_output(AVFilterLink *outlink)
141 {
142  AVFilterContext *ctx = outlink->src;
143  AMergeContext *am = ctx->priv;
144  AVBPrint bp;
145  int i;
146 
147  for (i = 1; i < am->nb_inputs; i++) {
148  if (ctx->inputs[i]->sample_rate != ctx->inputs[0]->sample_rate) {
149  av_log(ctx, AV_LOG_ERROR,
150  "Inputs must have the same sample rate "
151  "%d for in%d vs %d\n",
152  ctx->inputs[i]->sample_rate, i, ctx->inputs[0]->sample_rate);
153  return AVERROR(EINVAL);
154  }
155  }
156  am->bps = av_get_bytes_per_sample(ctx->outputs[0]->format);
157  outlink->sample_rate = ctx->inputs[0]->sample_rate;
158  outlink->time_base = ctx->inputs[0]->time_base;
159 
160  av_bprint_init(&bp, 0, 1);
161  for (i = 0; i < am->nb_inputs; i++) {
162  av_bprintf(&bp, "%sin%d:", i ? " + " : "", i);
164  }
165  av_bprintf(&bp, " -> out:");
167  av_log(ctx, AV_LOG_VERBOSE, "%s\n", bp.str);
168 
169  return 0;
170 }
171 
172 static int request_frame(AVFilterLink *outlink)
173 {
174  AVFilterContext *ctx = outlink->src;
175  AMergeContext *am = ctx->priv;
176  int i, ret;
177 
178  for (i = 0; i < am->nb_inputs; i++)
179  if (!am->in[i].nb_samples)
180  if ((ret = ff_request_frame(ctx->inputs[i])) < 0)
181  return ret;
182  return 0;
183 }
184 
185 /**
186  * Copy samples from several input streams to one output stream.
187  * @param nb_inputs number of inputs
188  * @param in inputs; used only for the nb_ch field;
189  * @param route routing values;
190  * input channel i goes to output channel route[i];
191  * i < in[0].nb_ch are the channels from the first output;
192  * i >= in[0].nb_ch are the channels from the second output
193  * @param ins pointer to the samples of each inputs, in packed format;
194  * will be left at the end of the copied samples
195  * @param outs pointer to the samples of the output, in packet format;
196  * must point to a buffer big enough;
197  * will be left at the end of the copied samples
198  * @param ns number of samples to copy
199  * @param bps bytes per sample
200  */
201 static inline void copy_samples(int nb_inputs, struct amerge_input in[],
202  int *route, uint8_t *ins[],
203  uint8_t **outs, int ns, int bps)
204 {
205  int *route_cur;
206  int i, c, nb_ch = 0;
207 
208  for (i = 0; i < nb_inputs; i++)
209  nb_ch += in[i].nb_ch;
210  while (ns--) {
211  route_cur = route;
212  for (i = 0; i < nb_inputs; i++) {
213  for (c = 0; c < in[i].nb_ch; c++) {
214  memcpy((*outs) + bps * *(route_cur++), ins[i], bps);
215  ins[i] += bps;
216  }
217  }
218  *outs += nb_ch * bps;
219  }
220 }
221 
222 static int filter_frame(AVFilterLink *inlink, AVFrame *insamples)
223 {
224  AVFilterContext *ctx = inlink->dst;
225  AMergeContext *am = ctx->priv;
226  AVFilterLink *const outlink = ctx->outputs[0];
227  int input_number;
228  int nb_samples, ns, i;
229  AVFrame *outbuf, *inbuf[SWR_CH_MAX];
230  uint8_t *ins[SWR_CH_MAX], *outs;
231 
232  for (input_number = 0; input_number < am->nb_inputs; input_number++)
233  if (inlink == ctx->inputs[input_number])
234  break;
235  av_assert1(input_number < am->nb_inputs);
236  if (ff_bufqueue_is_full(&am->in[input_number].queue)) {
237  av_frame_free(&insamples);
238  return AVERROR(ENOMEM);
239  }
240  ff_bufqueue_add(ctx, &am->in[input_number].queue, av_frame_clone(insamples));
241  am->in[input_number].nb_samples += insamples->nb_samples;
242  av_frame_free(&insamples);
243  nb_samples = am->in[0].nb_samples;
244  for (i = 1; i < am->nb_inputs; i++)
245  nb_samples = FFMIN(nb_samples, am->in[i].nb_samples);
246  if (!nb_samples)
247  return 0;
248 
249  outbuf = ff_get_audio_buffer(ctx->outputs[0], nb_samples);
250  if (!outbuf)
251  return AVERROR(ENOMEM);
252  outs = outbuf->data[0];
253  for (i = 0; i < am->nb_inputs; i++) {
254  inbuf[i] = ff_bufqueue_peek(&am->in[i].queue, 0);
255  ins[i] = inbuf[i]->data[0] +
256  am->in[i].pos * am->in[i].nb_ch * am->bps;
257  }
258  av_frame_copy_props(outbuf, inbuf[0]);
259  outbuf->pts = inbuf[0]->pts == AV_NOPTS_VALUE ? AV_NOPTS_VALUE :
260  inbuf[0]->pts +
261  av_rescale_q(am->in[0].pos,
262  (AVRational){ 1, ctx->inputs[0]->sample_rate },
263  ctx->outputs[0]->time_base);
264 
265  outbuf->nb_samples = nb_samples;
266  outbuf->channel_layout = outlink->channel_layout;
267  av_frame_set_channels(outbuf, outlink->channels);
268 
269  while (nb_samples) {
270  ns = nb_samples;
271  for (i = 0; i < am->nb_inputs; i++)
272  ns = FFMIN(ns, inbuf[i]->nb_samples - am->in[i].pos);
273  /* Unroll the most common sample formats: speed +~350% for the loop,
274  +~13% overall (including two common decoders) */
275  switch (am->bps) {
276  case 1:
277  copy_samples(am->nb_inputs, am->in, am->route, ins, &outs, ns, 1);
278  break;
279  case 2:
280  copy_samples(am->nb_inputs, am->in, am->route, ins, &outs, ns, 2);
281  break;
282  case 4:
283  copy_samples(am->nb_inputs, am->in, am->route, ins, &outs, ns, 4);
284  break;
285  default:
286  copy_samples(am->nb_inputs, am->in, am->route, ins, &outs, ns, am->bps);
287  break;
288  }
289 
290  nb_samples -= ns;
291  for (i = 0; i < am->nb_inputs; i++) {
292  am->in[i].nb_samples -= ns;
293  am->in[i].pos += ns;
294  if (am->in[i].pos == inbuf[i]->nb_samples) {
295  am->in[i].pos = 0;
296  av_frame_free(&inbuf[i]);
297  ff_bufqueue_get(&am->in[i].queue);
298  inbuf[i] = ff_bufqueue_peek(&am->in[i].queue, 0);
299  ins[i] = inbuf[i] ? inbuf[i]->data[0] : NULL;
300  }
301  }
302  }
303  return ff_filter_frame(ctx->outputs[0], outbuf);
304 }
305 
306 static av_cold int init(AVFilterContext *ctx)
307 {
308  AMergeContext *am = ctx->priv;
309  int i;
310 
311  am->in = av_calloc(am->nb_inputs, sizeof(*am->in));
312  if (!am->in)
313  return AVERROR(ENOMEM);
314  for (i = 0; i < am->nb_inputs; i++) {
315  char *name = av_asprintf("in%d", i);
316  AVFilterPad pad = {
317  .name = name,
318  .type = AVMEDIA_TYPE_AUDIO,
319  .filter_frame = filter_frame,
320  };
321  if (!name)
322  return AVERROR(ENOMEM);
323  ff_insert_inpad(ctx, i, &pad);
324  }
325  return 0;
326 }
327 
328 static const AVFilterPad amerge_outputs[] = {
329  {
330  .name = "default",
331  .type = AVMEDIA_TYPE_AUDIO,
332  .config_props = config_output,
333  .request_frame = request_frame,
334  },
335  { NULL }
336 };
337 
339  .name = "amerge",
340  .description = NULL_IF_CONFIG_SMALL("Merge two or more audio streams into "
341  "a single multi-channel stream."),
342  .priv_size = sizeof(AMergeContext),
343  .init = init,
344  .uninit = uninit,
346  .inputs = NULL,
347  .outputs = amerge_outputs,
348  .priv_class = &amerge_class,
350 };
const char * name
Definition: avisynth_c.h:675
static AVFrame * ff_bufqueue_get(struct FFBufQueue *queue)
Get the first buffer from the queue and remove it.
Definition: bufferqueue.h:98
struct AMergeContext::amerge_input * in
void av_bprintf(AVBPrint *buf, const char *fmt,...)
Definition: bprint.c:93
int av_frame_copy_props(AVFrame *dst, const AVFrame *src)
Copy only "metadata" fields from src to dst.
Definition: frame.c:424
int nb_ch
number of channels for the input
Definition: af_amerge.c:43
This structure describes decoded (raw) audio or video data.
Definition: frame.h:76
AVOption.
Definition: opt.h:251
static const AVFilterPad outputs[]
Definition: af_ashowinfo.c:117
external API header
#define AV_LOG_WARNING
Something somehow does not look correct.
Definition: log.h:154
#define AVFILTER_FLAG_DYNAMIC_INPUTS
The number of the filter inputs is not determined just by AVFilter.inputs.
Definition: avfilter.h:424
struct FFBufQueue queue
Definition: af_amerge.c:42
About Git write you should know how to use GIT properly Luckily Git comes with excellent documentation git help man git shows you the available git< command > help man git< command > shows information about the subcommand< command > The most comprehensive manual is the website Git Reference visit they are quite exhaustive You do not need a special username or password All you need is to provide a ssh public key to the Git server admin What follows now is a basic introduction to Git and some FFmpeg specific guidelines Read it at least if you are granted commit privileges to the FFmpeg project you are expected to be familiar with these rules I if not You can get git from etc no matter how small Every one of them has been saved from looking like a fool by this many times It s very easy for stray debug output or cosmetic modifications to slip in
Definition: git-howto.txt:5
AVFILTER_DEFINE_CLASS(amerge)
void av_freep(void *arg)
Free a memory block which has been allocated with av_malloc(z)() or av_realloc() and set the pointer ...
Definition: mem.c:198
AVFilterFormats * ff_make_format_list(const int *fmts)
Create a list of supported formats.
Definition: formats.c:308
Structure holding the queue.
Definition: bufferqueue.h:49
const char * name
Pad name.
AVFilterLink ** inputs
array of pointers to input links
Definition: avfilter.h:532
uint8_t
it can be given away to ff_start_frame *A reference passed to ff_filter_frame(or the deprecated ff_start_frame) is given away and must no longer be used.*A reference created with avfilter_ref_buffer belongs to the code that created it.*A reference obtained with ff_get_video_buffer or ff_get_audio_buffer belongs to the code that requested it.*A reference given as return value by the get_video_buffer or get_audio_buffer method is given away and must no longer be used.Link reference fields---------------------The AVFilterLink structure has a few AVFilterBufferRef fields.The cur_buf and out_buf were used with the deprecated start_frame/draw_slice/end_frame API and should no longer be used.src_buf
#define av_cold
Definition: attributes.h:78
AVOptions.
static enum AVSampleFormat ff_packed_sample_fmts_array[]
Definition: audio.h:28
int64_t pts
Presentation timestamp in time_base units (time when frame should be shown to user).
Definition: frame.h:159
void ff_channel_layouts_ref(AVFilterChannelLayouts *f, AVFilterChannelLayouts **ref)
Add *ref as a new reference to f.
Definition: formats.c:427
static av_cold int init(AVFilterContext *ctx)
Definition: af_amerge.c:306
void 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:545
static int filter_frame(AVFilterLink *inlink, AVFrame *insamples)
Definition: af_amerge.c:222
static av_cold void uninit(AVFilterContext *ctx)
Definition: af_amerge.c:60
A filter pad used for either input or output.
int64_t av_rescale_q(int64_t a, AVRational bq, AVRational cq)
Rescale a 64-bit integer by 2 rational numbers.
Definition: mathematics.c:130
static const AVFilterPad amerge_outputs[]
Definition: af_amerge.c:328
libswresample public header
AVFilterPad * input_pads
array of input pads
Definition: avfilter.h:531
static const AVOption amerge_options[]
Definition: af_amerge.c:52
int ff_add_channel_layout(AVFilterChannelLayouts **l, uint64_t channel_layout)
Definition: formats.c:350
AVFrame * ff_get_audio_buffer(AVFilterLink *link, int nb_samples)
Request an audio samples buffer with a specific set of permissions.
Definition: audio.c:84
#define NULL_IF_CONFIG_SMALL(x)
Return NULL if CONFIG_SMALL is true, otherwise the argument without modification. ...
void av_bprint_init(AVBPrint *buf, unsigned size_init, unsigned size_max)
Init a print buffer.
Definition: bprint.c:68
void * priv
private data for use by the filter
Definition: avfilter.h:545
uint64_t * channel_layouts
list of channel layouts
Definition: formats.h:86
int av_get_channel_layout_nb_channels(uint64_t channel_layout)
Return the number of channels in the channel layout.
void av_frame_set_channels(AVFrame *frame, int val)
void av_log(void *avcl, int level, const char *fmt,...)
Definition: log.c:246
uint64_t channel_layout
Channel layout of the audio data.
Definition: frame.h:331
char * av_asprintf(const char *fmt,...)
Definition: avstring.c:112
AVFrame * queue[FF_BUFQUEUE_SIZE]
Definition: bufferqueue.h:50
#define AV_LOG_VERBOSE
Definition: log.h:157
static int request_frame(AVFilterLink *outlink)
Definition: af_amerge.c:172
static int config_output(AVFilterLink *outlink)
Definition: af_amerge.c:140
Buffer to print data progressively.
Definition: bprint.h:75
audio channel layout utility functions
#define av_assert1(cond)
assert() equivalent, that does not lie in speed critical code.
Definition: avassert.h:53
#define FFMIN(a, b)
Definition: common.h:58
static int ff_bufqueue_is_full(struct FFBufQueue *queue)
Test if a buffer queue is full.
Definition: bufferqueue.h:60
ret
Definition: avfilter.c:821
static void ff_bufqueue_discard_all(struct FFBufQueue *queue)
Unref and remove all buffers from the queue.
Definition: bufferqueue.h:111
A list of supported channel layouts.
Definition: formats.h:85
int av_get_bytes_per_sample(enum AVSampleFormat sample_fmt)
Return number of bytes per sample.
Definition: samplefmt.c:104
AVFrame * av_frame_clone(AVFrame *src)
Create a new frame that references the same data as src.
Definition: frame.c:317
#define FLAGS
Definition: af_amerge.c:50
NULL
Definition: eval.c:55
static int query_formats(AVFilterContext *ctx)
Definition: af_amerge.c:74
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:148
void * buf
Definition: avisynth_c.h:594
Describe the class of an AVClass context structure.
Definition: log.h:50
Filter definition.
Definition: avfilter.h:436
synthesis window for stochastic i
rational number numerator/denominator
Definition: rational.h:43
const char * name
filter name
Definition: avfilter.h:437
Filter the word “frame” indicates either a video frame or a group of audio as stored in an AVFilterBuffer 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.Buffer references ownership and permissions
AVFilterLink ** outputs
array of pointers to output links
Definition: avfilter.h:539
enum MovChannelLayoutTag * layouts
Definition: mov_chan.c:434
AVFilterFormats * ff_all_samplerates(void)
Definition: formats.c:396
void * av_calloc(size_t nmemb, size_t size)
Allocate a block of nmemb * size bytes with alignment suitable for all memory accesses (including vec...
Definition: mem.c:213
static int flags
Definition: cpu.c:23
uint8_t * data[AV_NUM_DATA_POINTERS]
pointer to the picture/channel planes.
Definition: frame.h:87
void ff_set_common_samplerates(AVFilterContext *ctx, AVFilterFormats *samplerates)
Definition: formats.c:533
int nb_channel_layouts
number of channel layouts
Definition: formats.h:87
The official guide to swscale for confused that consecutive non overlapping rectangles of slice_bottom special converter These generally are unscaled converters of common formats
Definition: swscale.txt:33
#define OFFSET(x)
Definition: af_amerge.c:49
void av_frame_free(AVFrame **frame)
Free the frame and any dynamically allocated objects in it, e.g.
Definition: frame.c:108
static double c[64]
#define SWR_CH_MAX
Maximum number of channels.
Definition: swresample.h:102
unsigned bps
Definition: movenc.c:895
int route[SWR_CH_MAX]
channels routing, see copy_samples
Definition: af_amerge.c:39
static void ff_insert_inpad(AVFilterContext *f, unsigned index, AVFilterPad *p)
Insert a new input pad for the filter.
A list of supported formats for one end of a filter link.
Definition: formats.h:64
An instance of a filter.
Definition: avfilter.h:524
AVFilter avfilter_af_amerge
Definition: af_amerge.c:338
#define AV_LOG_INFO
Definition: log.h:156
static void copy_samples(int nb_inputs, struct amerge_input in[], int *route, uint8_t *ins[], uint8_t **outs, int ns, int bps)
Copy samples from several input streams to one output stream.
Definition: af_amerge.c:201
static void ff_bufqueue_add(void *log, struct FFBufQueue *queue, AVFrame *buf)
Add a buffer to the queue.
Definition: bufferqueue.h:71
int ff_request_frame(AVFilterLink *link)
Request an input frame from the filter at the other end of the link.
Definition: avfilter.c:319
internal API functions
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
int nb_samples
number of audio samples (per channel) described by this frame
Definition: frame.h:127
for(j=16;j >0;--j)
#define AV_NOPTS_VALUE
Undefined timestamp value.
Definition: avutil.h:190
void av_get_channel_layout_string(char *buf, int buf_size, int nb_channels, uint64_t channel_layout)
Return a description of a channel layout.
void av_bprint_channel_layout(struct AVBPrint *bp, int nb_channels, uint64_t channel_layout)
Append a description of a channel layout to a bprint buffer.
static AVFrame * ff_bufqueue_peek(struct FFBufQueue *queue, unsigned index)
Get a buffer from the queue without altering it.
Definition: bufferqueue.h:87
int64_t av_get_default_channel_layout(int nb_channels)
Return default channel layout for a given number of channels.