Browse code

af_pan: use libswr for rematrixing.

Nicolas George authored on 2012/02/16 20:34:39
Showing 2 changed files
... ...
@@ -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();