[MPlayer-dev-eng] [PATCH] Automatic downmix

Clément Bœsch ubitux at gmail.com
Thu Sep 23 23:57:26 CEST 2010


On Thu, Sep 23, 2010 at 11:31:08PM +0200, Reimar Döffinger wrote:
> On Thu, Sep 23, 2010 at 10:07:52PM +0200, Clément Bœsch wrote:
> > > > Is this what you would like? Or as I said, forced before the format filter?
> > 
> > In fact, the prepend version issues a problem: since the pan2 downmix is
> > placed before the pan6 filter, in the second run, it still observes a 6
> > channels output at the end of the chain, and then adds again the downmix
> > filter.
> 
> Hum? I don't think it should check at the end of the chain but the decoder
> output (i.e. at the start) if it is supposed to behave as similar as possible
> to downmixing as part of the codec.

Ok so then it won't work the same for native downmixers: downmix pan won't
be added, even with the case -channels 2 -af pan=6:, but I suppose it's
fine since it's the current behavior.

Patch updated, and here again, the tests:

Flac 5.1 (non-native downmix)
--------

Stream #0.0: Audio: flac, 44100 Hz, 6 channels, s16

* Normal case

  Before downmix check: [dummy (6ch)] → End
  After downmix check:  [format (6ch)] → [pan (2ch)] → [dummy (2ch)] → End
  AO: [alsa] 48000Hz 2ch floatle (4 bytes per sample)

* -channels 2 -af pan=6:

  Before downmix check: [format (6ch)] → [pan (6ch)] → End
  After downmix check:  [format (6ch)] → [pan (2ch)] → [pan (6ch)] → End
  AO: [alsa] 44100Hz 6ch floatle (4 bytes per sample)

* -channels 2 -af pan=6: -ao oss

  Before downmix check: [format (6ch)] → [pan (6ch)] → End
  After downmix check:  [format (6ch)] → [pan (2ch)] → [pan (6ch)] → End
  AO: [oss] 44100Hz 6ch s16le (2 bytes per sample)


AC3 5.1 (native downmix)
-------

Stream #0.0: Audio: ac3, 44100 Hz, 5.1, s16, 192 kb/s

* Normal case

  Before downmix check: [dummy (2ch)] → End
  After downmix check:  [dummy (2ch)] → End
  AO: [alsa] 48000Hz 2ch s16le (2 bytes per sample)

* -channels 2 -af pan=6:

  Before downmix check: [format (2ch)] → [pan (6ch)] → End
  After downmix check:  [format (2ch)] → [pan (6ch)] → End
  AO: [alsa] 44100Hz 6ch floatle (4 bytes per sample)

* -channels 2 -af pan=6: -ao oss

  Before downmix check: [format (2ch)] → [pan (6ch)] → End
  After downmix check:  [format (2ch)] → [pan (6ch)] → End
  AO: [oss] 44100Hz 6ch s16le (2 bytes per sample)

> Of course that problem still stays the same.
> 
> > +  // Append a downmix pan filter to the end of the chain if needed
> 
> Huh? Forgot to update?

Oups yes, fixed.

Regards,

-- 
Clément B.
-------------- next part --------------
Index: libaf/af.c
===================================================================
--- libaf/af.c	(revision 32345)
+++ libaf/af.c	(working copy)
@@ -21,6 +21,7 @@
 #include <stdlib.h>
 #include <string.h>
 #include "osdep/strsep.h"
+#include "libmpcodecs/dec_audio.h"
 
 #include "af.h"
 
@@ -412,6 +413,24 @@
     return AF_OK;
 }
 
+/**
+ * Automatic downmix to stereo in case the codec does not implement it.
+ */
+static af_instance_t *af_downmix(af_stream_t* s)
+{
+    static char * const downmix_strs[AF_NCH + 1] = {
+        /*                FL       FR       RL       RR          FC          LF         AL      AR */
+        [3] = "pan=2:" "0.6:0:" "0:0.6:"                     "0.4:0.4",
+        [4] = "pan=2:" "0.6:0:" "0:0.6:" "0.4:0:"  "0:0.4",
+        [5] = "pan=2:" "0.5:0:" "0:0.5:" "0.2:0:"  "0:0.2:"  "0.3:0.3",
+        [6] = "pan=2:" "0.4:0:" "0:0.4:" "0.2:0:"  "0:0.2:"  "0.3:0.3:"   "0.1:0.1",
+        [7] = "pan=2:" "0.4:0:" "0:0.4:" "0.2:0:"  "0:0.2:"  "0.3:0.3:"              "0.1:0:" "0:0.1",
+        [8] = "pan=2:" "0.4:0:" "0:0.4:" "0.15:0:" "0:0.15:" "0.25:0.25:" "0.1:0.1:" "0.1:0:" "0:0.1",
+    };
+    char *af_pan_str = downmix_strs[s->first->data->nch];
+    return af_pan_str ? af_prepend(s, s->first, af_pan_str) : NULL;
+}
+
 /* Initialize the stream "s". This function creates a new filter list
    if necessary according to the values set in input and output. Input
    and output should contain the format of the current movie and the
@@ -423,7 +442,7 @@
    The return value is 0 if success and -1 if failure */
 int af_init(af_stream_t* s)
 {
-  int i=0;
+  int i=0, first_run;
 
   // Sanity check
   if(!s) return -1;
@@ -437,7 +456,8 @@
     s->cfg.force = (s->cfg.force & ~AF_INIT_TYPE_MASK) | AF_INIT_TYPE;
 
   // Check if this is the first call
-  if(!s->first){
+  first_run = !s->first;
+  if(first_run){
     // Add all filters in the list (if there are any)
     if(!s->cfg.list){      // To make automatic format conversion work
       if(!af_append(s,s->first,"dummy"))
@@ -460,6 +480,13 @@
     if (!af_append(s,s->first,"dummy") || AF_OK != af_reinit(s,s->first))
       return -1;
 
+  // Append a downmix pan filter at the beginning of the chain if needed
+  if (first_run && audio_output_channels == 2) {
+    af_instance_t *filter = af_downmix(s);
+    if (filter && AF_OK != af_reinit(s, filter))
+      return -1;
+  }
+
   // Check output format
   if((AF_INIT_TYPE_MASK & s->cfg.force) != AF_INIT_FORCE){
     af_instance_t* af = NULL; // New filter


More information about the MPlayer-dev-eng mailing list