af_pan: use libswr for rematrixing.
authorNicolas George <nicolas.george@normalesup.org>
Thu, 16 Feb 2012 11:34:39 +0000 (12:34 +0100)
committerNicolas George <nicolas.george@normalesup.org>
Mon, 20 Feb 2012 19:46:35 +0000 (20:46 +0100)
doc/filters.texi
libavfilter/af_pan.c

index b885958..238401a 100644 (file)
@@ -384,9 +384,6 @@ The channel remapping will be effective if, and only if:
 @itemize
 @item gain coefficients are zeroes or ones,
 @item only one input per channel output,
-@item the number of output channels is supported by libswresample (16 at the
-      moment)
-@c if SWR_CH_MAX changes, fix the line above.
 @end itemize
 
 If all these conditions are satisfied, the filter will notify the user ("Pure
index 119111d..a93bd75 100644 (file)
@@ -234,18 +234,29 @@ static int config_props(AVFilterLink *link)
             }
         }
     }
-    // gains are pure, init the channel mapping
-    if (pan->pure_gains) {
 
+        /* TODO reindent */
         // sanity check; can't be done in query_formats since the inlink
         // channel layout is unknown at that time
-        if (pan->nb_input_channels > SWR_CH_MAX) {
+        if (pan->nb_input_channels > SWR_CH_MAX ||
+            pan->nb_output_channels > SWR_CH_MAX) {
             av_log(ctx, AV_LOG_ERROR,
                    "libswresample support a maximum of %d channels. "
                    "Feel free to ask for a higher limit.\n", SWR_CH_MAX);
             return AVERROR_PATCHWELCOME;
         }
 
+        // init libswresample context
+        pan->swr = swr_alloc_set_opts(pan->swr,
+                                      pan->out_channel_layout, link->format, link->sample_rate,
+                                      link->channel_layout,    link->format, link->sample_rate,
+                                      0, ctx);
+        if (!pan->swr)
+            return AVERROR(ENOMEM);
+
+    // gains are pure, init the channel mapping
+    if (pan->pure_gains) {
+
         // get channel map from the pure gains
         for (i = 0; i < pan->nb_output_channels; i++) {
             int ch_id = -1;
@@ -258,19 +269,9 @@ static int config_props(AVFilterLink *link)
             pan->channel_map[i] = ch_id;
         }
 
-        // init libswresample context
-        pan->swr = swr_alloc_set_opts(pan->swr,
-                                      pan->out_channel_layout, link->format, link->sample_rate,
-                                      link->channel_layout,    link->format, link->sample_rate,
-                                      0, ctx);
-        if (!pan->swr)
-            return AVERROR(ENOMEM);
         av_opt_set_int(pan->swr, "icl", pan->out_channel_layout, 0);
         av_opt_set_int(pan->swr, "uch", pan->nb_output_channels, 0);
         swr_set_channel_mapping(pan->swr, pan->channel_map);
-        r = swr_init(pan->swr);
-        if (r < 0)
-            return r;
     } else {
         // renormalize
         for (i = 0; i < pan->nb_output_channels; i++) {
@@ -289,7 +290,16 @@ static int config_props(AVFilterLink *link)
             for (j = 0; j < pan->nb_input_channels; j++)
                 pan->gain.d[i][j] /= t;
         }
+        av_opt_set_int(pan->swr, "icl", link->channel_layout, 0);
+        av_opt_set_int(pan->swr, "ocl", pan->out_channel_layout, 0);
+        swr_set_matrix(pan->swr, pan->gain.d[0],
+                       pan->gain.d[1] - pan->gain.d[0]);
     }
+
+    r = swr_init(pan->swr);
+    if (r < 0)
+        return r;
+
     // summary
     for (i = 0; i < pan->nb_output_channels; i++) {
         cur = buf;
@@ -331,30 +341,6 @@ static void filter_samples_channel_mapping(PanContext *pan,
     swr_convert(pan->swr, outsamples->data, n, (void *)insamples->data, n);
 }
 
-static void filter_samples_panning(PanContext *pan,
-                                   AVFilterBufferRef *outsamples,
-                                   AVFilterBufferRef *insamples,
-                                   int n)
-{
-    int i, o;
-
-    /* input */
-    const int16_t *in     = (int16_t *)insamples->data[0];
-    const int16_t *in_end = in + n * pan->nb_input_channels;
-
-    /* output */
-    int16_t *out = (int16_t *)outsamples->data[0];
-
-    for (; in < in_end; in += pan->nb_input_channels) {
-        for (o = 0; o < pan->nb_output_channels; o++) {
-            int v = 0;
-            for (i = 0; i < pan->nb_input_channels; i++)
-                v += pan->gain.i[o][i] * in[i];
-            *(out++) = v >> 8;
-        }
-    }
-}
-
 static void filter_samples(AVFilterLink *inlink, AVFilterBufferRef *insamples)
 {
     int n = insamples->audio->nb_samples;
@@ -379,21 +365,12 @@ static int query_formats(AVFilterContext *ctx)
     AVFilterLink *outlink = ctx->outputs[0];
     AVFilterFormats *formats;
 
-    if (pan->nb_output_channels <= SWR_CH_MAX)
+        /* TODO reindent */
         pan->pure_gains = are_gains_pure(pan);
-    if (pan->pure_gains) {
         /* libswr supports any sample and packing formats */
         avfilter_set_common_sample_formats(ctx, avfilter_make_all_formats(AVMEDIA_TYPE_AUDIO));
         avfilter_set_common_packing_formats(ctx, avfilter_make_all_packing_formats());
         pan->filter_samples = filter_samples_channel_mapping;
-    } else {
-        const enum AVSampleFormat sample_fmts[] = {AV_SAMPLE_FMT_S16, -1};
-        const int                packing_fmts[] = {AVFILTER_PACKED,   -1};
-
-        avfilter_set_common_sample_formats (ctx, avfilter_make_format_list(sample_fmts));
-        avfilter_set_common_packing_formats(ctx, avfilter_make_format_list(packing_fmts));
-        pan->filter_samples = filter_samples_panning;
-    }
 
     // inlink supports any channel layout
     formats = avfilter_make_all_channel_layouts();