[FFmpeg-devel] [RFC] libavfilter audio - af_resample channel conversion

S.N. Hemanth Meenakshisundaram smeenaks
Wed Jul 7 13:31:04 CEST 2010


On 07/04/2010 07:57 AM, Stefano Sabatini wrote:
> On date Thursday 2010-07-01 01:42:51 -0700, S.N. Hemanth Meenakshisundaram encoded:
>    
>> On 06/25/2010 05:10 PM, Stefano Sabatini wrote:
>>      
>>> On date Friday 2010-06-25 03:52:45 -0700, S.N. Hemanth Meenakshisundaram encoded:
>>>        
>>>> [...]
>>>>          
>>>        
>> Hi All,
>>
>> Here is the working af_resample.c and associated Makefile and
>> allfilters.c changes.
>>      
> [...]
> All these are duplicated of existing code. I'm not against this if
> this will get us with a working/testable audio filtering framework,
> but put at least a FIXME somewhere.
>
> Also if someone can suggest a better solution to share this code it
> would be even better.
>
>    


Hi All,

Here is an idea for a generalized channel conversion function for 
af_resample:

We could have a table of gain tables corresponding to various channel 
conversions as below:

+static const struct {
+    int64_t in_channel_layout;
+    int64_t out_channel_layout;
+    const float gain[8][8];
+} channel_mixing_table[] = {
+    {
+        .in_channel_layout = CH_LAYOUT_5POINT0,
+        .out_channel_layout = CH_LAYOUT_STEREO,
+        .gain = {
+            {1, 0, 0.5, 0.7, 0},
+            {0, 1, 0.5, 0, 0.7},
+        },
+    }
+};



The table above currently has a single gain table for 5.0 to stereo 
downmixing.

We would need to look up an appropriate gain table only when input or 
output channel layout changes. When these changes occur, we can also fix 
the conversion function to be called to be one of ten function as below 
(based on planar/non-planar and sample format).

+/* Generic channel conversion functions in case of short sample format */
+static void generic_planar_convert_short(short **outputs, short 
**inputs, float **gains, short in_channels, short out_channels, int 
samples_nb)
+{
+    int i, j, k;
+
+    for (j = 0; j < out_channels; j++)
+        for (k = 0; k < in_channels; k++)
+            for (i = 0; i < samples_nb; i++)
+                outputs[j][i] += gains[j][k] * inputs[k][i];
+}
+
+static void generic_packed_convert_short(short **outputs, short 
**inputs, float **gains, short in_channels, short out_channels, int 
samples_nb)
+{
+    int i, j, k;
+
+    for (i = 0; i < samples_nb; i++)
+        for (j = 0; j < out_channels; j++)
+            for (k = 0; k < in_channels; k++)
+                outputs[i][j] += gains[j][k] * inputs[i][k];
+}
+

And 4*2 other functions for the other 4 sample formats (planar and 
non-planar versions for each)

The for loops and multiply-add statements could be factorized as a macro 
if necessary for concise representation across the 10 functions. Only 
the order of the loops and the pointer types of data would change 
between the functions and we would cover all sample formats and any 
channel conversion for which a gain table of conversions exists.

I am testing this out for a couple of conversions now.

One potential big drawback of this is the large size of the table of 
gain tables. However, if we add these gain tables as and when necessary, 
perhaps it is acceptable?

Once the input and output channel layouts are known and channel 
conversion required is fixed, there are almost no branches in the data 
path except for the predictable loop ones.

In addition to these, perhaps we can keep the stereo-to-mono and 
mono-to-stereo functions for the common case.

Is this approach is worth pursuing? Are there any issues with this other 
than the large table required?


Regards,
Hemanth




More information about the ffmpeg-devel mailing list