af_pan.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2002 Anders Johansson <ajh@atri.curtin.edu.au>
3  * Copyright (c) 2011 Clément Bœsch <ubitux@gmail.com>
4  * Copyright (c) 2011 Nicolas George <nicolas.george@normalesup.org>
5  *
6  * This file is part of FFmpeg.
7  *
8  * FFmpeg is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Lesser General Public
10  * License as published by the Free Software Foundation; either
11  * version 2.1 of the License, or (at your option) any later version.
12  *
13  * FFmpeg is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16  * GNU Lesser General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with FFmpeg; if not, write to the Free Software
20  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21  */
22 
23 /**
24  * @file
25  * Audio panning filter (channels mixing)
26  * Original code written by Anders Johansson for MPlayer,
27  * reimplemented for FFmpeg.
28  */
29 
30 #include <stdio.h>
31 #include "libavutil/avstring.h"
33 #include "libavutil/opt.h"
35 #include "audio.h"
36 #include "avfilter.h"
37 #include "formats.h"
38 #include "internal.h"
39 
40 #define MAX_CHANNELS 63
41 
42 typedef struct PanContext {
43  const AVClass *class;
44  char *args;
47  int64_t need_renorm;
51 
53  /* channel mapping specific */
55  struct SwrContext *swr;
56 } PanContext;
57 
58 static void skip_spaces(char **arg)
59 {
60  int len = 0;
61 
62  sscanf(*arg, " %n", &len);
63  *arg += len;
64 }
65 
66 static int parse_channel_name(char **arg, int *rchannel, int *rnamed)
67 {
68  char buf[8];
69  int len, i, channel_id = 0;
70  int64_t layout, layout0;
71 
72  skip_spaces(arg);
73  /* try to parse a channel name, e.g. "FL" */
74  if (sscanf(*arg, "%7[A-Z]%n", buf, &len)) {
75  layout0 = layout = av_get_channel_layout(buf);
76  /* channel_id <- first set bit in layout */
77  for (i = 32; i > 0; i >>= 1) {
78  if (layout >= (int64_t)1 << i) {
79  channel_id += i;
80  layout >>= i;
81  }
82  }
83  /* reject layouts that are not a single channel */
84  if (channel_id >= MAX_CHANNELS || layout0 != (int64_t)1 << channel_id)
85  return AVERROR(EINVAL);
86  *rchannel = channel_id;
87  *rnamed = 1;
88  *arg += len;
89  return 0;
90  }
91  /* try to parse a channel number, e.g. "c2" */
92  if (sscanf(*arg, "c%d%n", &channel_id, &len) &&
93  channel_id >= 0 && channel_id < MAX_CHANNELS) {
94  *rchannel = channel_id;
95  *rnamed = 0;
96  *arg += len;
97  return 0;
98  }
99  return AVERROR(EINVAL);
100 }
101 
102 static av_cold int init(AVFilterContext *ctx)
103 {
104  PanContext *const pan = ctx->priv;
105  char *arg, *arg0, *tokenizer, *args = av_strdup(pan->args);
106  int out_ch_id, in_ch_id, len, named, ret;
107  int nb_in_channels[2] = { 0, 0 }; // number of unnamed and named input channels
108  double gain;
109 
110  if (!pan->args) {
111  av_log(ctx, AV_LOG_ERROR,
112  "pan filter needs a channel layout and a set "
113  "of channels definitions as parameter\n");
114  return AVERROR(EINVAL);
115  }
116  if (!args)
117  return AVERROR(ENOMEM);
118  arg = av_strtok(args, "|", &tokenizer);
119  ret = ff_parse_channel_layout(&pan->out_channel_layout, arg, ctx);
120  if (ret < 0)
121  goto fail;
123 
124  /* parse channel specifications */
125  while ((arg = arg0 = av_strtok(NULL, "|", &tokenizer))) {
126  /* channel name */
127  if (parse_channel_name(&arg, &out_ch_id, &named)) {
128  av_log(ctx, AV_LOG_ERROR,
129  "Expected out channel name, got \"%.8s\"\n", arg);
130  ret = AVERROR(EINVAL);
131  goto fail;
132  }
133  if (named) {
134  if (!((pan->out_channel_layout >> out_ch_id) & 1)) {
135  av_log(ctx, AV_LOG_ERROR,
136  "Channel \"%.8s\" does not exist in the chosen layout\n", arg0);
137  ret = AVERROR(EINVAL);
138  goto fail;
139  }
140  /* get the channel number in the output channel layout:
141  * out_channel_layout & ((1 << out_ch_id) - 1) are all the
142  * channels that come before out_ch_id,
143  * so their count is the index of out_ch_id */
144  out_ch_id = av_get_channel_layout_nb_channels(pan->out_channel_layout & (((int64_t)1 << out_ch_id) - 1));
145  }
146  if (out_ch_id < 0 || out_ch_id >= pan->nb_output_channels) {
147  av_log(ctx, AV_LOG_ERROR,
148  "Invalid out channel name \"%.8s\"\n", arg0);
149  ret = AVERROR(EINVAL);
150  goto fail;
151  }
152  skip_spaces(&arg);
153  if (*arg == '=') {
154  arg++;
155  } else if (*arg == '<') {
156  pan->need_renorm |= (int64_t)1 << out_ch_id;
157  arg++;
158  } else {
159  av_log(ctx, AV_LOG_ERROR,
160  "Syntax error after channel name in \"%.8s\"\n", arg0);
161  ret = AVERROR(EINVAL);
162  goto fail;
163  }
164  /* gains */
165  while (1) {
166  gain = 1;
167  if (sscanf(arg, "%lf%n *%n", &gain, &len, &len))
168  arg += len;
169  if (parse_channel_name(&arg, &in_ch_id, &named)){
170  av_log(ctx, AV_LOG_ERROR,
171  "Expected in channel name, got \"%.8s\"\n", arg);
172  ret = AVERROR(EINVAL);
173  goto fail;
174  }
175  nb_in_channels[named]++;
176  if (nb_in_channels[!named]) {
177  av_log(ctx, AV_LOG_ERROR,
178  "Can not mix named and numbered channels\n");
179  ret = AVERROR(EINVAL);
180  goto fail;
181  }
182  pan->gain[out_ch_id][in_ch_id] = gain;
183  skip_spaces(&arg);
184  if (!*arg)
185  break;
186  if (*arg != '+') {
187  av_log(ctx, AV_LOG_ERROR, "Syntax error near \"%.8s\"\n", arg);
188  ret = AVERROR(EINVAL);
189  goto fail;
190  }
191  arg++;
192  }
193  }
194  pan->need_renumber = !!nb_in_channels[1];
195 
196  ret = 0;
197 fail:
198  av_free(args);
199  return ret;
200 }
201 
202 static int are_gains_pure(const PanContext *pan)
203 {
204  int i, j;
205 
206  for (i = 0; i < MAX_CHANNELS; i++) {
207  int nb_gain = 0;
208 
209  for (j = 0; j < MAX_CHANNELS; j++) {
210  double gain = pan->gain[i][j];
211 
212  /* channel mapping is effective only if 0% or 100% of a channel is
213  * selected... */
214  if (gain != 0. && gain != 1.)
215  return 0;
216  /* ...and if the output channel is only composed of one input */
217  if (gain && nb_gain++)
218  return 0;
219  }
220  }
221  return 1;
222 }
223 
225 {
226  PanContext *pan = ctx->priv;
227  AVFilterLink *inlink = ctx->inputs[0];
228  AVFilterLink *outlink = ctx->outputs[0];
231 
232  pan->pure_gains = are_gains_pure(pan);
233  /* libswr supports any sample and packing formats */
235 
236  formats = ff_all_samplerates();
237  if (!formats)
238  return AVERROR(ENOMEM);
239  ff_set_common_samplerates(ctx, formats);
240 
241  // inlink supports any channel layout
242  layouts = ff_all_channel_layouts();
243  ff_channel_layouts_ref(layouts, &inlink->out_channel_layouts);
244 
245  // outlink supports only requested output channel layout
246  layouts = NULL;
248  ff_channel_layouts_ref(layouts, &outlink->in_channel_layouts);
249  return 0;
250 }
251 
253 {
254  AVFilterContext *ctx = link->dst;
255  PanContext *pan = ctx->priv;
256  char buf[1024], *cur;
257  int i, j, k, r;
258  double t;
259 
261  if (pan->need_renumber) {
262  // input channels were given by their name: renumber them
263  for (i = j = 0; i < MAX_CHANNELS; i++) {
264  if ((link->channel_layout >> i) & 1) {
265  for (k = 0; k < pan->nb_output_channels; k++)
266  pan->gain[k][j] = pan->gain[k][i];
267  j++;
268  }
269  }
270  }
271 
272  // sanity check; can't be done in query_formats since the inlink
273  // channel layout is unknown at that time
274  if (pan->nb_input_channels > SWR_CH_MAX ||
276  av_log(ctx, AV_LOG_ERROR,
277  "libswresample support a maximum of %d channels. "
278  "Feel free to ask for a higher limit.\n", SWR_CH_MAX);
279  return AVERROR_PATCHWELCOME;
280  }
281 
282  // init libswresample context
283  pan->swr = swr_alloc_set_opts(pan->swr,
284  pan->out_channel_layout, link->format, link->sample_rate,
285  link->channel_layout, link->format, link->sample_rate,
286  0, ctx);
287  if (!pan->swr)
288  return AVERROR(ENOMEM);
289 
290  // gains are pure, init the channel mapping
291  if (pan->pure_gains) {
292 
293  // get channel map from the pure gains
294  for (i = 0; i < pan->nb_output_channels; i++) {
295  int ch_id = -1;
296  for (j = 0; j < pan->nb_input_channels; j++) {
297  if (pan->gain[i][j]) {
298  ch_id = j;
299  break;
300  }
301  }
302  pan->channel_map[i] = ch_id;
303  }
304 
305  av_opt_set_int(pan->swr, "icl", pan->out_channel_layout, 0);
306  av_opt_set_int(pan->swr, "uch", pan->nb_output_channels, 0);
308  } else {
309  // renormalize
310  for (i = 0; i < pan->nb_output_channels; i++) {
311  if (!((pan->need_renorm >> i) & 1))
312  continue;
313  t = 0;
314  for (j = 0; j < pan->nb_input_channels; j++)
315  t += pan->gain[i][j];
316  if (t > -1E-5 && t < 1E-5) {
317  // t is almost 0 but not exactly, this is probably a mistake
318  if (t)
319  av_log(ctx, AV_LOG_WARNING,
320  "Degenerate coefficients while renormalizing\n");
321  continue;
322  }
323  for (j = 0; j < pan->nb_input_channels; j++)
324  pan->gain[i][j] /= t;
325  }
326  av_opt_set_int(pan->swr, "icl", link->channel_layout, 0);
327  av_opt_set_int(pan->swr, "ocl", pan->out_channel_layout, 0);
328  swr_set_matrix(pan->swr, pan->gain[0], pan->gain[1] - pan->gain[0]);
329  }
330 
331  r = swr_init(pan->swr);
332  if (r < 0)
333  return r;
334 
335  // summary
336  for (i = 0; i < pan->nb_output_channels; i++) {
337  cur = buf;
338  for (j = 0; j < pan->nb_input_channels; j++) {
339  r = snprintf(cur, buf + sizeof(buf) - cur, "%s%.3g i%d",
340  j ? " + " : "", pan->gain[i][j], j);
341  cur += FFMIN(buf + sizeof(buf) - cur, r);
342  }
343  av_log(ctx, AV_LOG_VERBOSE, "o%d = %s\n", i, buf);
344  }
345  // add channel mapping summary if possible
346  if (pan->pure_gains) {
347  av_log(ctx, AV_LOG_INFO, "Pure channel mapping detected:");
348  for (i = 0; i < pan->nb_output_channels; i++)
349  if (pan->channel_map[i] < 0)
350  av_log(ctx, AV_LOG_INFO, " M");
351  else
352  av_log(ctx, AV_LOG_INFO, " %d", pan->channel_map[i]);
353  av_log(ctx, AV_LOG_INFO, "\n");
354  return 0;
355  }
356  return 0;
357 }
358 
359 static int filter_frame(AVFilterLink *inlink, AVFrame *insamples)
360 {
361  int ret;
362  int n = insamples->nb_samples;
363  AVFilterLink *const outlink = inlink->dst->outputs[0];
364  AVFrame *outsamples = ff_get_audio_buffer(outlink, n);
365  PanContext *pan = inlink->dst->priv;
366 
367  if (!outsamples)
368  return AVERROR(ENOMEM);
369  swr_convert(pan->swr, outsamples->data, n, (void *)insamples->data, n);
370  av_frame_copy_props(outsamples, insamples);
371  outsamples->channel_layout = outlink->channel_layout;
372  av_frame_set_channels(outsamples, outlink->channels);
373 
374  ret = ff_filter_frame(outlink, outsamples);
375  av_frame_free(&insamples);
376  return ret;
377 }
378 
379 static av_cold void uninit(AVFilterContext *ctx)
380 {
381  PanContext *pan = ctx->priv;
382  swr_free(&pan->swr);
383 }
384 
385 #define OFFSET(x) offsetof(PanContext, x)
386 
387 static const AVOption pan_options[] = {
388  { "args", NULL, OFFSET(args), AV_OPT_TYPE_STRING, { .str = NULL }, CHAR_MIN, CHAR_MAX, AV_OPT_FLAG_AUDIO_PARAM | AV_OPT_FLAG_FILTERING_PARAM },
389  { NULL }
390 };
391 
393 
394 
395 static const AVFilterPad pan_inputs[] = {
396  {
397  .name = "default",
398  .type = AVMEDIA_TYPE_AUDIO,
399  .config_props = config_props,
400  .filter_frame = filter_frame,
401  },
402  { NULL }
403 };
404 
405 static const AVFilterPad pan_outputs[] = {
406  {
407  .name = "default",
408  .type = AVMEDIA_TYPE_AUDIO,
409  },
410  { NULL }
411 };
412 
414  .name = "pan",
415  .description = NULL_IF_CONFIG_SMALL("Remix channels with coefficients (panning)."),
416  .priv_size = sizeof(PanContext),
417  .priv_class = &pan_class,
418  .init = init,
419  .uninit = uninit,
421  .inputs = pan_inputs,
422  .outputs = pan_outputs,
423 };
char * args
Definition: af_pan.c:44
#define MAX_CHANNELS
Definition: af_pan.c:40
int nb_input_channels
Definition: af_pan.c:49
int av_frame_copy_props(AVFrame *dst, const AVFrame *src)
Copy only "metadata" fields from src to dst.
Definition: frame.c:424
double gain[MAX_CHANNELS][MAX_CHANNELS]
Definition: af_pan.c:46
This structure describes decoded (raw) audio or video data.
Definition: frame.h:76
int swr_convert(struct SwrContext *s, uint8_t *out_arg[SWR_CH_MAX], int out_count, const uint8_t *in_arg[SWR_CH_MAX], int in_count)
Definition: swresample.c:735
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 AV_OPT_FLAG_AUDIO_PARAM
Definition: opt.h:284
static int config_props(AVFilterLink *link)
Definition: af_pan.c:252
initialize output if(nPeaks >3)%at least 3 peaks in spectrum for trying to find f0 nf0peaks
static int filter_frame(AVFilterLink *inlink, AVFrame *insamples)
Definition: af_pan.c:359
const char * name
Pad name.
AVFilterLink ** inputs
array of pointers to input links
Definition: avfilter.h:532
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.
int need_renumber
Definition: af_pan.c:48
void ff_channel_layouts_ref(AVFilterChannelLayouts *f, AVFilterChannelLayouts **ref)
Add *ref as a new reference to f.
Definition: formats.c:427
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
AVFilterFormats * ff_all_formats(enum AVMediaType type)
Return a list of all formats supported by FFmpeg for the given media type.
Definition: formats.c:357
static const AVFilterPad pan_inputs[]
Definition: af_pan.c:395
static const AVOption pan_options[]
Definition: af_pan.c:387
A filter pad used for either input or output.
libswresample public header
void av_free(void *ptr)
Free a memory block which has been allocated with av_malloc(z)() or av_realloc(). ...
Definition: mem.c:183
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 AV_OPT_FLAG_FILTERING_PARAM
a generic parameter which can be set by the user for filtering
Definition: opt.h:287
#define NULL_IF_CONFIG_SMALL(x)
Return NULL if CONFIG_SMALL is true, otherwise the argument without modification. ...
const char * r
Definition: vf_curves.c:94
void * priv
private data for use by the filter
Definition: avfilter.h:545
static int query_formats(AVFilterContext *ctx)
Definition: af_pan.c:224
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)
const char * arg
int av_opt_set_int(void *obj, const char *name, int64_t val, int search_flags)
Definition: opt.c:394
void av_log(void *avcl, int level, const char *fmt,...)
Definition: log.c:246
struct SwrContext * swr
Definition: af_pan.c:55
static int are_gains_pure(const PanContext *pan)
Definition: af_pan.c:202
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 link
uint64_t channel_layout
Channel layout of the audio data.
Definition: frame.h:331
#define AV_LOG_VERBOSE
Definition: log.h:157
audio channel layout utility functions
#define FFMIN(a, b)
Definition: common.h:58
struct PanContext PanContext
int swr_set_matrix(struct SwrContext *s, const double *matrix, int stride)
Set a customized remix matrix.
Definition: rematrix.c:56
ret
Definition: avfilter.c:821
int pure_gains
Definition: af_pan.c:52
static void skip_spaces(char **arg)
Definition: af_pan.c:58
t
Definition: genspecsines3.m:6
struct SwrContext * swr_alloc_set_opts(struct SwrContext *s, int64_t out_ch_layout, enum AVSampleFormat out_sample_fmt, int out_sample_rate, int64_t in_ch_layout, enum AVSampleFormat in_sample_fmt, int in_sample_rate, int log_offset, void *log_ctx)
Allocate SwrContext if needed and set/reset common parameters.
Definition: swresample.c:186
#define E
AVFilterChannelLayouts * ff_all_channel_layouts(void)
Construct an empty AVFilterChannelLayouts/AVFilterFormats struct – representing any channel layout (...
Definition: formats.c:402
A list of supported channel layouts.
Definition: formats.h:85
#define AVERROR_PATCHWELCOME
Not yet implemented in FFmpeg, patches welcome.
Definition: error.h:62
for k
int64_t out_channel_layout
Definition: af_pan.c:45
NULL
Definition: eval.c:55
char * av_strdup(const char *s)
Duplicate the string s.
Definition: mem.c:220
av_cold void swr_free(SwrContext **ss)
Free the given SwrContext and set the pointer to NULL.
Definition: swresample.c:220
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:148
void * buf
Definition: avisynth_c.h:594
int swr_set_channel_mapping(struct SwrContext *s, const int *channel_map)
Set a customized input channel mapping.
Definition: swresample.c:165
Describe the class of an AVClass context structure.
Definition: log.h:50
Filter definition.
Definition: avfilter.h:436
synthesis window for stochastic i
#define OFFSET(x)
Definition: af_pan.c:385
int64_t need_renorm
Definition: af_pan.c:47
const char * name
filter name
Definition: avfilter.h:437
#define snprintf
Definition: snprintf.h:34
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
AVFILTER_DEFINE_CLASS(pan)
uint8_t * data[AV_NUM_DATA_POINTERS]
pointer to the picture/channel planes.
Definition: frame.h:87
char * av_strtok(char *s, const char *delim, char **saveptr)
Split the string into several tokens which can be accessed by successive calls to av_strtok()...
Definition: avstring.c:183
void ff_set_common_samplerates(AVFilterContext *ctx, AVFilterFormats *samplerates)
Definition: formats.c:533
int channel_map[SWR_CH_MAX]
Definition: af_pan.c:54
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
void av_frame_free(AVFrame **frame)
Free the frame and any dynamically allocated objects in it, e.g.
Definition: frame.c:108
int ff_parse_channel_layout(int64_t *ret, const char *arg, void *log_ctx)
Parse a channel layout or a corresponding integer representation.
Definition: formats.c:632
#define SWR_CH_MAX
Maximum number of channels.
Definition: swresample.h:102
static int parse_channel_name(char **arg, int *rchannel, int *rnamed)
Definition: af_pan.c:66
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 layout
AVFilter avfilter_af_pan
Definition: af_pan.c:413
int len
static av_cold int init(AVFilterContext *ctx)
Definition: af_pan.c:102
uint64_t av_get_channel_layout(const char *name)
Return a channel layout id that matches name, or 0 if no match is found.
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
#define AV_LOG_INFO
Definition: log.h:156
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
static av_cold void uninit(AVFilterContext *ctx)
Definition: af_pan.c:379
av_cold int swr_init(struct SwrContext *s)
Initialize context after user parameters have been set.
Definition: swresample.c:242
static const AVFilterPad pan_outputs[]
Definition: af_pan.c:405
int nb_output_channels
Definition: af_pan.c:50