... | ... |
@@ -1060,6 +1060,11 @@ Either a channel layout name from channel_layout_map in |
1060 | 1060 |
@file{libavutil/channel_layout.c} or its corresponding integer representation |
1061 | 1061 |
from the AV_CH_LAYOUT_* macros in @file{libavutil/channel_layout.h} |
1062 | 1062 |
|
1063 |
+@item channels |
|
1064 |
+The number of channels of the incoming audio buffers. |
|
1065 |
+If both @var{channels} and @var{channel_layout} are specified, then they |
|
1066 |
+must be consistent. |
|
1067 |
+ |
|
1063 | 1068 |
@end table |
1064 | 1069 |
|
1065 | 1070 |
For example: |
... | ... |
@@ -55,6 +55,7 @@ typedef struct { |
55 | 55 |
int sample_rate; |
56 | 56 |
enum AVSampleFormat sample_fmt; |
57 | 57 |
char *sample_fmt_str; |
58 |
+ int channels; |
|
58 | 59 |
uint64_t channel_layout; |
59 | 60 |
char *channel_layout_str; |
60 | 61 |
|
... | ... |
@@ -240,6 +241,7 @@ static const AVOption abuffer_options[] = { |
240 | 240 |
{ "time_base", NULL, OFFSET(time_base), AV_OPT_TYPE_RATIONAL, { .dbl = 0 }, 0, INT_MAX, FLAGS }, |
241 | 241 |
{ "sample_rate", NULL, OFFSET(sample_rate), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, INT_MAX, FLAGS }, |
242 | 242 |
{ "sample_fmt", NULL, OFFSET(sample_fmt_str), AV_OPT_TYPE_STRING, .flags = FLAGS }, |
243 |
+ { "channels", NULL, OFFSET(channels), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, INT_MAX, FLAGS }, |
|
243 | 244 |
{ "channel_layout", NULL, OFFSET(channel_layout_str), AV_OPT_TYPE_STRING, .flags = FLAGS }, |
244 | 245 |
{ NULL }, |
245 | 246 |
}; |
... | ... |
@@ -265,6 +267,9 @@ static av_cold int init_audio(AVFilterContext *ctx, const char *args) |
265 | 265 |
goto fail; |
266 | 266 |
} |
267 | 267 |
|
268 |
+ if (s->channel_layout_str) { |
|
269 |
+ int n; |
|
270 |
+ /* TODO reindent */ |
|
268 | 271 |
s->channel_layout = av_get_channel_layout(s->channel_layout_str); |
269 | 272 |
if (!s->channel_layout) { |
270 | 273 |
av_log(ctx, AV_LOG_ERROR, "Invalid channel layout '%s'\n", |
... | ... |
@@ -272,6 +277,24 @@ static av_cold int init_audio(AVFilterContext *ctx, const char *args) |
272 | 272 |
ret = AVERROR(EINVAL); |
273 | 273 |
goto fail; |
274 | 274 |
} |
275 |
+ n = av_get_channel_layout_nb_channels(s->channel_layout); |
|
276 |
+ if (s->channels) { |
|
277 |
+ if (n != s->channels) { |
|
278 |
+ av_log(ctx, AV_LOG_ERROR, |
|
279 |
+ "Mismatching channel count %d and layout '%s' " |
|
280 |
+ "(%d channels)\n", |
|
281 |
+ s->channels, s->channel_layout_str, n); |
|
282 |
+ ret = AVERROR(EINVAL); |
|
283 |
+ goto fail; |
|
284 |
+ } |
|
285 |
+ } |
|
286 |
+ s->channels = n; |
|
287 |
+ } else if (!s->channels) { |
|
288 |
+ av_log(ctx, AV_LOG_ERROR, "Neither number of channels nor " |
|
289 |
+ "channel layout specified\n"); |
|
290 |
+ ret = AVERROR(EINVAL); |
|
291 |
+ goto fail; |
|
292 |
+ } |
|
275 | 293 |
|
276 | 294 |
if (!(s->fifo = av_fifo_alloc(sizeof(AVFilterBufferRef*)))) { |
277 | 295 |
ret = AVERROR(ENOMEM); |
... | ... |
@@ -324,7 +347,9 @@ static int query_formats(AVFilterContext *ctx) |
324 | 324 |
ff_add_format(&samplerates, c->sample_rate); |
325 | 325 |
ff_set_common_samplerates(ctx, samplerates); |
326 | 326 |
|
327 |
- ff_add_channel_layout(&channel_layouts, c->channel_layout); |
|
327 |
+ ff_add_channel_layout(&channel_layouts, |
|
328 |
+ c->channel_layout ? c->channel_layout : |
|
329 |
+ FF_COUNT2LAYOUT(c->channels)); |
|
328 | 330 |
ff_set_common_channel_layouts(ctx, channel_layouts); |
329 | 331 |
break; |
330 | 332 |
default: |