| ... | ... |
@@ -384,9 +384,6 @@ The channel remapping will be effective if, and only if: |
| 384 | 384 |
@itemize |
| 385 | 385 |
@item gain coefficients are zeroes or ones, |
| 386 | 386 |
@item only one input per channel output, |
| 387 |
-@item the number of output channels is supported by libswresample (16 at the |
|
| 388 |
- moment) |
|
| 389 |
-@c if SWR_CH_MAX changes, fix the line above. |
|
| 390 | 387 |
@end itemize |
| 391 | 388 |
|
| 392 | 389 |
If all these conditions are satisfied, the filter will notify the user ("Pure
|
| ... | ... |
@@ -234,18 +234,29 @@ static int config_props(AVFilterLink *link) |
| 234 | 234 |
} |
| 235 | 235 |
} |
| 236 | 236 |
} |
| 237 |
- // gains are pure, init the channel mapping |
|
| 238 |
- if (pan->pure_gains) {
|
|
| 239 | 237 |
|
| 238 |
+ /* TODO reindent */ |
|
| 240 | 239 |
// sanity check; can't be done in query_formats since the inlink |
| 241 | 240 |
// channel layout is unknown at that time |
| 242 |
- if (pan->nb_input_channels > SWR_CH_MAX) {
|
|
| 241 |
+ if (pan->nb_input_channels > SWR_CH_MAX || |
|
| 242 |
+ pan->nb_output_channels > SWR_CH_MAX) {
|
|
| 243 | 243 |
av_log(ctx, AV_LOG_ERROR, |
| 244 | 244 |
"libswresample support a maximum of %d channels. " |
| 245 | 245 |
"Feel free to ask for a higher limit.\n", SWR_CH_MAX); |
| 246 | 246 |
return AVERROR_PATCHWELCOME; |
| 247 | 247 |
} |
| 248 | 248 |
|
| 249 |
+ // init libswresample context |
|
| 250 |
+ pan->swr = swr_alloc_set_opts(pan->swr, |
|
| 251 |
+ pan->out_channel_layout, link->format, link->sample_rate, |
|
| 252 |
+ link->channel_layout, link->format, link->sample_rate, |
|
| 253 |
+ 0, ctx); |
|
| 254 |
+ if (!pan->swr) |
|
| 255 |
+ return AVERROR(ENOMEM); |
|
| 256 |
+ |
|
| 257 |
+ // gains are pure, init the channel mapping |
|
| 258 |
+ if (pan->pure_gains) {
|
|
| 259 |
+ |
|
| 249 | 260 |
// get channel map from the pure gains |
| 250 | 261 |
for (i = 0; i < pan->nb_output_channels; i++) {
|
| 251 | 262 |
int ch_id = -1; |
| ... | ... |
@@ -258,19 +269,9 @@ static int config_props(AVFilterLink *link) |
| 258 | 258 |
pan->channel_map[i] = ch_id; |
| 259 | 259 |
} |
| 260 | 260 |
|
| 261 |
- // init libswresample context |
|
| 262 |
- pan->swr = swr_alloc_set_opts(pan->swr, |
|
| 263 |
- pan->out_channel_layout, link->format, link->sample_rate, |
|
| 264 |
- link->channel_layout, link->format, link->sample_rate, |
|
| 265 |
- 0, ctx); |
|
| 266 |
- if (!pan->swr) |
|
| 267 |
- return AVERROR(ENOMEM); |
|
| 268 | 261 |
av_opt_set_int(pan->swr, "icl", pan->out_channel_layout, 0); |
| 269 | 262 |
av_opt_set_int(pan->swr, "uch", pan->nb_output_channels, 0); |
| 270 | 263 |
swr_set_channel_mapping(pan->swr, pan->channel_map); |
| 271 |
- r = swr_init(pan->swr); |
|
| 272 |
- if (r < 0) |
|
| 273 |
- return r; |
|
| 274 | 264 |
} else {
|
| 275 | 265 |
// renormalize |
| 276 | 266 |
for (i = 0; i < pan->nb_output_channels; i++) {
|
| ... | ... |
@@ -289,7 +290,16 @@ static int config_props(AVFilterLink *link) |
| 289 | 289 |
for (j = 0; j < pan->nb_input_channels; j++) |
| 290 | 290 |
pan->gain.d[i][j] /= t; |
| 291 | 291 |
} |
| 292 |
+ av_opt_set_int(pan->swr, "icl", link->channel_layout, 0); |
|
| 293 |
+ av_opt_set_int(pan->swr, "ocl", pan->out_channel_layout, 0); |
|
| 294 |
+ swr_set_matrix(pan->swr, pan->gain.d[0], |
|
| 295 |
+ pan->gain.d[1] - pan->gain.d[0]); |
|
| 292 | 296 |
} |
| 297 |
+ |
|
| 298 |
+ r = swr_init(pan->swr); |
|
| 299 |
+ if (r < 0) |
|
| 300 |
+ return r; |
|
| 301 |
+ |
|
| 293 | 302 |
// summary |
| 294 | 303 |
for (i = 0; i < pan->nb_output_channels; i++) {
|
| 295 | 304 |
cur = buf; |
| ... | ... |
@@ -331,30 +341,6 @@ static void filter_samples_channel_mapping(PanContext *pan, |
| 331 | 331 |
swr_convert(pan->swr, outsamples->data, n, (void *)insamples->data, n); |
| 332 | 332 |
} |
| 333 | 333 |
|
| 334 |
-static void filter_samples_panning(PanContext *pan, |
|
| 335 |
- AVFilterBufferRef *outsamples, |
|
| 336 |
- AVFilterBufferRef *insamples, |
|
| 337 |
- int n) |
|
| 338 |
-{
|
|
| 339 |
- int i, o; |
|
| 340 |
- |
|
| 341 |
- /* input */ |
|
| 342 |
- const int16_t *in = (int16_t *)insamples->data[0]; |
|
| 343 |
- const int16_t *in_end = in + n * pan->nb_input_channels; |
|
| 344 |
- |
|
| 345 |
- /* output */ |
|
| 346 |
- int16_t *out = (int16_t *)outsamples->data[0]; |
|
| 347 |
- |
|
| 348 |
- for (; in < in_end; in += pan->nb_input_channels) {
|
|
| 349 |
- for (o = 0; o < pan->nb_output_channels; o++) {
|
|
| 350 |
- int v = 0; |
|
| 351 |
- for (i = 0; i < pan->nb_input_channels; i++) |
|
| 352 |
- v += pan->gain.i[o][i] * in[i]; |
|
| 353 |
- *(out++) = v >> 8; |
|
| 354 |
- } |
|
| 355 |
- } |
|
| 356 |
-} |
|
| 357 |
- |
|
| 358 | 334 |
static void filter_samples(AVFilterLink *inlink, AVFilterBufferRef *insamples) |
| 359 | 335 |
{
|
| 360 | 336 |
int n = insamples->audio->nb_samples; |
| ... | ... |
@@ -379,21 +365,12 @@ static int query_formats(AVFilterContext *ctx) |
| 379 | 379 |
AVFilterLink *outlink = ctx->outputs[0]; |
| 380 | 380 |
AVFilterFormats *formats; |
| 381 | 381 |
|
| 382 |
- if (pan->nb_output_channels <= SWR_CH_MAX) |
|
| 382 |
+ /* TODO reindent */ |
|
| 383 | 383 |
pan->pure_gains = are_gains_pure(pan); |
| 384 |
- if (pan->pure_gains) {
|
|
| 385 | 384 |
/* libswr supports any sample and packing formats */ |
| 386 | 385 |
avfilter_set_common_sample_formats(ctx, avfilter_make_all_formats(AVMEDIA_TYPE_AUDIO)); |
| 387 | 386 |
avfilter_set_common_packing_formats(ctx, avfilter_make_all_packing_formats()); |
| 388 | 387 |
pan->filter_samples = filter_samples_channel_mapping; |
| 389 |
- } else {
|
|
| 390 |
- const enum AVSampleFormat sample_fmts[] = {AV_SAMPLE_FMT_S16, -1};
|
|
| 391 |
- const int packing_fmts[] = {AVFILTER_PACKED, -1};
|
|
| 392 |
- |
|
| 393 |
- avfilter_set_common_sample_formats (ctx, avfilter_make_format_list(sample_fmts)); |
|
| 394 |
- avfilter_set_common_packing_formats(ctx, avfilter_make_format_list(packing_fmts)); |
|
| 395 |
- pan->filter_samples = filter_samples_panning; |
|
| 396 |
- } |
|
| 397 | 388 |
|
| 398 | 389 |
// inlink supports any channel layout |
| 399 | 390 |
formats = avfilter_make_all_channel_layouts(); |