]> granicus.if.org Git - handbrake/commitdiff
Use hb_audio_resample for downmixing AC3 sources. DRC is still applied by liba52.
authorRodeo <tdskywalker@gmail.com>
Thu, 2 Aug 2012 21:43:22 +0000 (21:43 +0000)
committerRodeo <tdskywalker@gmail.com>
Thu, 2 Aug 2012 21:43:22 +0000 (21:43 +0000)
Add support for center & surround mix levels to hb_audio_resample.

This allows us to support upmixing all audio sources. For sources that have at least 2 front and one back or side channel(s), allow upmixing to 5.1:

3.0/3.1 (2 front and 1 back channels)
4.0/4.1 (3 front and 1 back channels)
4.0/4.1 (2 front and 2 side channels)
5.0     (3 front and 2 side channels)

git-svn-id: svn://svn.handbrake.fr/HandBrake/trunk@4885 b64f7644-9d1e-0410-96f1-a4d463321fa5

contrib/a52dec/A00-a52-state-t-public.patch [new file with mode: 0644]
contrib/a52dec/A00-dpl2.patch [deleted file]
contrib/a52dec/A01-thread-safe.patch
contrib/a52dec/A02-imdct-shutup.patch
libhb/audio_resample.c
libhb/audio_resample.h
libhb/common.c
libhb/deca52.c
libhb/decavcodec.c
libhb/declpcm.c
libhb/encavcodecaudio.c

diff --git a/contrib/a52dec/A00-a52-state-t-public.patch b/contrib/a52dec/A00-a52-state-t-public.patch
new file mode 100644 (file)
index 0000000..5e0af35
--- /dev/null
@@ -0,0 +1,152 @@
+diff -Naur a52dec.old/include/a52.h a52dec.new/include/a52.h
+--- a52dec.old/include/a52.h   2002-01-28 06:37:54.000000000 +0100
++++ a52dec.new/include/a52.h   2012-07-16 14:13:35.000000000 +0200
+@@ -30,7 +30,71 @@
+ typedef double sample_t;
+ #endif
+-typedef struct a52_state_s a52_state_t;
++typedef struct {
++    uint8_t bai;              /* fine SNR offset, fast gain */
++    uint8_t deltbae;          /* delta bit allocation exists */
++    int8_t deltba[50];        /* per-band delta bit allocation */
++} ba_t;
++
++typedef struct {
++    uint8_t exp[256];         /* decoded channel exponents */
++    int8_t bap[256];          /* derived channel bit allocation */
++} expbap_t;
++
++typedef struct {
++    uint8_t fscod;            /* sample rate */
++    uint8_t halfrate;         /* halfrate factor */
++    uint8_t acmod;            /* coded channels */
++    uint8_t lfeon;            /* coded lfe channel */
++    sample_t clev;            /* centre channel mix level */
++    sample_t slev;            /* surround channels mix level */
++
++    int output;               /* type of output */
++    sample_t level;           /* output level */
++    sample_t bias;            /* output bias */
++
++    int dynrnge;              /* apply dynamic range */
++    sample_t dynrng;          /* dynamic range */
++    void * dynrngdata;        /* dynamic range callback funtion and data */
++    sample_t (* dynrngcall) (sample_t range, void * dynrngdata);
++
++    uint8_t chincpl;          /* channel coupled */
++    uint8_t phsflginu;        /* phase flags in use (stereo only) */
++    uint8_t cplstrtmant;      /* coupling channel start mantissa */
++    uint8_t cplendmant;       /* coupling channel end mantissa */
++    uint32_t cplbndstrc;      /* coupling band structure */
++    sample_t cplco[5][18];    /* coupling coordinates */
++
++    /* derived information */
++    uint8_t cplstrtbnd;       /* coupling start band (for bit allocation) */
++    uint8_t ncplbnd;          /* number of coupling bands */
++
++    uint8_t rematflg;         /* stereo rematrixing */
++
++    uint8_t endmant[5];       /* channel end mantissa */
++
++    uint16_t bai;             /* bit allocation information */
++
++    uint32_t * buffer_start;
++    uint16_t lfsr_state;      /* dither state */
++    uint32_t bits_left;
++    uint32_t current_word;
++
++    uint8_t csnroffst;        /* coarse SNR offset */
++    ba_t cplba;               /* coupling bit allocation parameters */
++    ba_t ba[5];               /* channel bit allocation parameters */
++    ba_t lfeba;               /* lfe bit allocation parameters */
++
++    uint8_t cplfleak;         /* coupling fast leak init */
++    uint8_t cplsleak;         /* coupling slow leak init */
++
++    expbap_t cpl_expbap;
++    expbap_t fbw_expbap[5];
++    expbap_t lfe_expbap;
++
++    sample_t * samples;
++    int downmixed;
++} a52_state_t;
+ #define A52_CHANNEL 0
+ #define A52_MONO 1
+diff -Naur a52dec.old/liba52/a52_internal.h a52dec.new/liba52/a52_internal.h
+--- a52dec.old/liba52/a52_internal.h   2002-07-28 03:52:06.000000000 +0200
++++ a52dec.new/liba52/a52_internal.h   2012-07-16 14:11:47.000000000 +0200
+@@ -21,72 +21,6 @@
+  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+  */
+-typedef struct {
+-    uint8_t bai;              /* fine SNR offset, fast gain */
+-    uint8_t deltbae;          /* delta bit allocation exists */
+-    int8_t deltba[50];                /* per-band delta bit allocation */
+-} ba_t;
+-
+-typedef struct {
+-    uint8_t exp[256];         /* decoded channel exponents */
+-    int8_t bap[256];          /* derived channel bit allocation */
+-} expbap_t;
+-
+-struct a52_state_s {
+-    uint8_t fscod;            /* sample rate */
+-    uint8_t halfrate;         /* halfrate factor */
+-    uint8_t acmod;            /* coded channels */
+-    uint8_t lfeon;            /* coded lfe channel */
+-    sample_t clev;            /* centre channel mix level */
+-    sample_t slev;            /* surround channels mix level */
+-
+-    int output;                       /* type of output */
+-    sample_t level;           /* output level */
+-    sample_t bias;            /* output bias */
+-
+-    int dynrnge;              /* apply dynamic range */
+-    sample_t dynrng;          /* dynamic range */
+-    void * dynrngdata;                /* dynamic range callback funtion and data */
+-    sample_t (* dynrngcall) (sample_t range, void * dynrngdata);
+-
+-    uint8_t chincpl;          /* channel coupled */
+-    uint8_t phsflginu;                /* phase flags in use (stereo only) */
+-    uint8_t cplstrtmant;      /* coupling channel start mantissa */
+-    uint8_t cplendmant;               /* coupling channel end mantissa */
+-    uint32_t cplbndstrc;      /* coupling band structure */
+-    sample_t cplco[5][18];    /* coupling coordinates */
+-
+-    /* derived information */
+-    uint8_t cplstrtbnd;               /* coupling start band (for bit allocation) */
+-    uint8_t ncplbnd;          /* number of coupling bands */
+-
+-    uint8_t rematflg;         /* stereo rematrixing */
+-
+-    uint8_t endmant[5];               /* channel end mantissa */
+-
+-    uint16_t bai;             /* bit allocation information */
+-
+-    uint32_t * buffer_start;
+-    uint16_t lfsr_state;      /* dither state */
+-    uint32_t bits_left;
+-    uint32_t current_word;
+-
+-    uint8_t csnroffst;                /* coarse SNR offset */
+-    ba_t cplba;                       /* coupling bit allocation parameters */
+-    ba_t ba[5];                       /* channel bit allocation parameters */
+-    ba_t lfeba;                       /* lfe bit allocation parameters */
+-
+-    uint8_t cplfleak;         /* coupling fast leak init */
+-    uint8_t cplsleak;         /* coupling slow leak init */
+-
+-    expbap_t cpl_expbap;
+-    expbap_t fbw_expbap[5];
+-    expbap_t lfe_expbap;
+-
+-    sample_t * samples;
+-    int downmixed;
+-};
+-
+ #define LEVEL_PLUS6DB 2.0
+ #define LEVEL_PLUS3DB 1.4142135623730951
+ #define LEVEL_3DB 0.7071067811865476
diff --git a/contrib/a52dec/A00-dpl2.patch b/contrib/a52dec/A00-dpl2.patch
deleted file mode 100644 (file)
index cf1c8a6..0000000
+++ /dev/null
@@ -1,114 +0,0 @@
-diff -Naur a52dec_original/include/a52.h a52dec_patched/include/a52.h
---- a52dec_original/include/a52.h      2002-01-28 05:37:54.000000000 +0000
-+++ a52dec_patched/include/a52.h       2007-04-04 19:12:57.000000000 +0100
-@@ -48,6 +48,10 @@
- #define A52_LFE 16
- #define A52_ADJUST_LEVEL 32
-+// this next constant can be ORed with A52_DOLBY to tell liba52 to use 5.0 DPLII matrix encoding,
-+// rather than just 4.0 Dolby Surround matrix encoding
-+#define A52_USE_DPLII 64
-+
- a52_state_t * a52_init (uint32_t mm_accel);
- sample_t * a52_samples (a52_state_t * state);
- int a52_syncinfo (uint8_t * buf, int * flags,
-diff -Naur a52dec_original/liba52/a52_internal.h a52dec_patched/liba52/a52_internal.h
---- a52dec_original/liba52/a52_internal.h      2002-07-28 02:52:06.000000000 +0100
-+++ a52dec_patched/liba52/a52_internal.h       2007-04-04 19:11:43.000000000 +0100
-@@ -93,6 +93,10 @@
- #define LEVEL_45DB 0.5946035575013605
- #define LEVEL_6DB 0.5
-+// these next two constants are used for DPL matrix encoding in downmix.c
-+#define LEVEL_SQRT_1_2 0.5
-+#define LEVEL_SQRT_3_4 0.8660254037844386
-+
- #define EXP_REUSE (0)
- #define EXP_D15   (1)
- #define EXP_D25   (2)
-diff -Naur a52dec_original/liba52/downmix.c a52dec_patched/liba52/downmix.c
---- a52dec_original/liba52/downmix.c   2002-01-28 05:37:54.000000000 +0000
-+++ a52dec_patched/liba52/downmix.c    2007-04-06 13:47:49.000000000 +0100
-@@ -34,6 +34,7 @@
- int a52_downmix_init (int input, int flags, sample_t * level,
-                     sample_t clev, sample_t slev)
- {
-+
-     static uint8_t table[11][8] = {
-       {A52_CHANNEL,   A52_DOLBY,      A52_STEREO,     A52_STEREO,
-        A52_STEREO,    A52_STEREO,     A52_STEREO,     A52_STEREO},
-@@ -148,6 +149,9 @@
-           break;
-       }
-+      // add the DPLII flag back into the output if it was passed in
-+      output = output | (flags & A52_USE_DPLII);
-+
-     return output;
- }
-@@ -418,17 +422,46 @@
-     }
- }
--static void mix32toS (sample_t * samples, sample_t bias)
-+static void mix32toS (sample_t * samples, sample_t bias, int use_dpl2)
- {
--    int i;
--    sample_t common, surround;
--    for (i = 0; i < 256; i++) {
--      common = samples[i + 256] + bias;
--      surround = samples[i + 768] + samples[i + 1024];
--      samples[i] += common - surround;
--      samples[i + 256] = samples[i + 512] + common + surround;
--    }
-+      if (use_dpl2 == 1) {
-+
-+              int i;
-+              sample_t cc, Lt, Rt, Ls, Rs, Lss, Rss;
-+      
-+              for (i = 0; i < 256; i++) {
-+      
-+                      cc = samples[i + 256] * LEVEL_3DB;
-+              
-+                      Lt = samples[i] + cc;
-+                      Rt = samples[i + 512] + cc;
-+              
-+                      Ls = samples[i + 768];
-+                      Rs = samples[i + 1024];
-+                      
-+                      Lss = (LEVEL_SQRT_3_4 * Ls) - (LEVEL_SQRT_1_2 * Rs);
-+                      Rss = -(LEVEL_SQRT_1_2 * Ls) + (LEVEL_SQRT_3_4 * Rs);
-+              
-+                      samples[i] = bias + Lt + Lss;
-+                      samples[i + 256] = bias + Rt + Rss;
-+      
-+              }
-+
-+      } else {
-+
-+              int i;
-+              sample_t common, surround;
-+      
-+              for (i = 0; i < 256; i++) {
-+              common = samples[i + 256] + bias;
-+              surround = samples[i + 768] + samples[i + 1024];
-+              samples[i] += common - surround;
-+              samples[i + 256] = samples[i + 512] + common + surround;
-+              }
-+
-+      }
-+
- }
- static void move2to1 (sample_t * src, sample_t * dest, sample_t bias)
-@@ -533,7 +566,7 @@
-       break;
-     case CONVERT (A52_3F2R, A52_DOLBY):
--      mix32toS (samples, bias);
-+      mix32toS (samples, bias, ((output & A52_USE_DPLII) == A52_USE_DPLII));
-       break;
-     case CONVERT (A52_3F1R, A52_3F):
index 0fa7f0a53ec9cf0e47ef8c22557946fb86a344b6..4ca2d1a087342955d3735d3b5726d132c197571d 100644 (file)
@@ -1,19 +1,19 @@
-diff -Naur -x '*.o' -x '*.lo' -x '*.a' -x '*.la' a52dec/liba52/a52_internal.h ../a52dec.new/liba52/a52_internal.h
---- a52dec/liba52/a52_internal.h       2011-04-28 07:54:05.499052327 -0700
-+++ ../a52dec.new/liba52/a52_internal.h        2011-04-28 07:50:30.998845068 -0700
-@@ -32,6 +32,11 @@
-     int8_t bap[256];          /* derived channel bit allocation */
+diff -Naur a52dec.old/include/a52.h a52dec.new/include/a52.h
+--- a52dec.old/include/a52.h   2012-07-16 14:24:14.000000000 +0200
++++ a52dec.new/include/a52.h   2012-07-16 14:31:37.000000000 +0200
+@@ -42,6 +42,11 @@
  } expbap_t;
  
-+typedef struct complex_s {
+ typedef struct {
 +    sample_t real;
 +    sample_t imag;
 +} complex_t;
 +
- struct a52_state_s {
-     uint8_t fscod;            /* sample rate */
-     uint8_t halfrate;         /* halfrate factor */
-@@ -85,6 +90,20 @@
++typedef struct {
+     uint8_t fscod;            /* sample rate */
+     uint8_t halfrate;         /* halfrate factor */
+     uint8_t acmod;            /* coded channels */
+@@ -94,6 +99,20 @@
  
      sample_t * samples;
      int downmixed;
@@ -31,10 +31,13 @@ diff -Naur -x '*.o' -x '*.lo' -x '*.a' -x '*.la' a52dec/liba52/a52_internal.h ..
 +    complex_t * post2;            // size 32
 +
 +    sample_t * a52_imdct_window;  // size 256
- };
+ } a52_state_t;
  
- #define LEVEL_PLUS6DB 2.0
-@@ -119,6 +138,6 @@
+ #define A52_CHANNEL 0
+diff -Naur a52dec.old/liba52/a52_internal.h a52dec.new/liba52/a52_internal.h
+--- a52dec.old/liba52/a52_internal.h   2012-07-16 14:24:14.000000000 +0200
++++ a52dec.new/liba52/a52_internal.h   2012-07-16 14:28:33.000000000 +0200
+@@ -49,6 +49,6 @@
                  sample_t clev, sample_t slev);
  void a52_upmix (sample_t * samples, int acmod, int output);
  
@@ -44,9 +47,9 @@ diff -Naur -x '*.o' -x '*.lo' -x '*.a' -x '*.la' a52dec/liba52/a52_internal.h ..
 +void a52_imdct_init (a52_state_t * state, uint32_t mm_accel);
 +void a52_imdct_256 (a52_state_t * state, sample_t * data, sample_t * delay, sample_t bias);
 +void a52_imdct_512 (a52_state_t * state, sample_t * data, sample_t * delay, sample_t bias);
-diff -Naur -x '*.o' -x '*.lo' -x '*.a' -x '*.la' a52dec/liba52/imdct.c ../a52dec.new/liba52/imdct.c
---- a52dec/liba52/imdct.c      2002-07-27 18:52:07.000000000 -0700
-+++ ../a52dec.new/liba52/imdct.c       2011-04-28 07:51:00.398624376 -0700
+diff -Naur a52dec.old/liba52/imdct.c a52dec.new/liba52/imdct.c
+--- a52dec.old/liba52/imdct.c  2012-07-16 14:24:14.000000000 +0200
++++ a52dec.new/liba52/imdct.c  2012-07-16 14:33:00.000000000 +0200
 @@ -40,11 +40,6 @@
  #include "a52_internal.h"
  #include "mm_accel.h"
@@ -316,9 +319,9 @@ diff -Naur -x '*.o' -x '*.lo' -x '*.a' -x '*.la' a52dec/liba52/imdct.c ../a52dec
      }
  
  #ifdef LIBA52_DJBFFT
-diff -Naur -x '*.o' -x '*.lo' -x '*.a' -x '*.la' a52dec/liba52/parse.c ../a52dec.new/liba52/parse.c
---- a52dec/liba52/parse.c      2002-07-27 18:52:07.000000000 -0700
-+++ ../a52dec.new/liba52/parse.c       2011-04-28 07:40:48.030435061 -0700
+diff -Naur a52dec.old/liba52/parse.c a52dec.new/liba52/parse.c
+--- a52dec.old/liba52/parse.c  2012-07-16 14:24:14.000000000 +0200
++++ a52dec.new/liba52/parse.c  2012-07-16 14:33:00.000000000 +0200
 @@ -56,16 +56,53 @@
      a52_state_t * state;
      int i;
index 8d57ab7a3c15f3f9af44b5b67332f14e6c789bde..a22e5979e665df74d552dbff00c582f1d4745afc 100644 (file)
@@ -1,6 +1,6 @@
 diff -Naur a52dec_original/liba52/imdct.c a52dec_patched/liba52/imdct.c
---- a52dec_original/liba52/imdct.c     2002-07-28 03:52:07.000000000 +0200
-+++ a52dec_patched/liba52/imdct.c      2011-07-15 20:29:09.000000000 +0200
+--- a52dec.old/liba52/imdct.c  2002-07-28 03:52:07.000000000 +0200
++++ a52dec.new/liba52/imdct.c  2011-07-15 20:29:09.000000000 +0200
 @@ -425,7 +425,6 @@
      } else
  #endif
index ea09b38a236c16c94073d5b73d167f26e209cccb..0723511929db2d24f143feb37578cbca6d8a83f2 100644 (file)
@@ -18,7 +18,10 @@ hb_audio_resample_t* hb_audio_resample_init(enum AVSampleFormat output_sample_fm
 {
     hb_audio_resample_t *resample = malloc(sizeof(hb_audio_resample_t));
     if (resample == NULL)
+    {
+        hb_error("hb_audio_resample_init: failed to allocate resample");
         return NULL;
+    }
 
     resample->out.sample_fmt          = output_sample_fmt;
     resample->out.sample_size         =
@@ -37,6 +40,8 @@ hb_audio_resample_t* hb_audio_resample_init(enum AVSampleFormat output_sample_fm
 int hb_audio_resample_update(hb_audio_resample_t *resample,
                              enum AVSampleFormat new_sample_fmt,
                              uint64_t new_channel_layout,
+                             double new_surroundmixlev,
+                             double new_centermixlev,
                              int new_channels)
 {
     if (resample == NULL)
@@ -55,7 +60,9 @@ int hb_audio_resample_update(hb_audio_resample_t *resample,
     int resample_changed =
         (resample->resample_needed &&
          (resample->in.sample_fmt != new_sample_fmt ||
-          resample->in.channel_layout != new_channel_layout));
+          resample->in.channel_layout != new_channel_layout ||
+          resample->in.center_mix_level != new_centermixlev ||
+          resample->in.surround_mix_level != new_surroundmixlev));
 
     if (resample_changed || (resample->resample_needed &&
                              resample->avresample == NULL))
@@ -87,6 +94,10 @@ int hb_audio_resample_update(hb_audio_resample_t *resample,
                        new_sample_fmt, 0);
         av_opt_set_int(resample->avresample, "in_channel_layout",
                        new_channel_layout, 0);
+        av_opt_set_double(resample->avresample, "center_mix_level",
+                          new_centermixlev, 0);
+        av_opt_set_double(resample->avresample, "surround_mix_level",
+                          new_surroundmixlev, 0);
 
         if (avresample_open(resample->avresample) < 0)
         {
@@ -96,8 +107,10 @@ int hb_audio_resample_update(hb_audio_resample_t *resample,
             return 1;
         }
 
-        resample->in.sample_fmt     = new_sample_fmt;
-        resample->in.channel_layout = new_channel_layout;
+        resample->in.sample_fmt         = new_sample_fmt;
+        resample->in.channel_layout     = new_channel_layout;
+        resample->in.center_mix_level   = new_centermixlev;
+        resample->in.surround_mix_level = new_surroundmixlev;
     }
 
     return 0;
index 4b1586e73b92f287f3fa4061a3f0742408589a24..29a7f91d0d66ba1b07bfb61db0fb9ba3c7d31e48 100644 (file)
 #ifndef AUDIO_RESAMPLE_H
 #define AUDIO_RESAMPLE_H
 
+#include <math.h>
 #include <stdint.h>
 #include "libavutil/audioconvert.h"
 #include "libavresample/avresample.h"
 
+/* Default mix level for center and surround channels */
+#define HB_MIXLEV_DEFAULT ((double)M_SQRT1_2)
+
 typedef struct
 {
     int resample_needed;
@@ -31,6 +35,8 @@ typedef struct
         int channels;
         int linesize;
         uint64_t channel_layout;
+        double center_mix_level;
+        double surround_mix_level;
         enum AVSampleFormat sample_fmt;
     } in;
 
@@ -46,7 +52,7 @@ typedef struct
     } out;
 } hb_audio_resample_t;
 
-/* Initialize an hb_audio_resample_t to convert audio to the requested
+/* Initialize an hb_audio_resample_t for converting audio to the requested
  * sample_fmt and channel_layout, using the specified matrix_encoding.
  *
  * Input characteristics are set via hb_audio_resample_update().
@@ -65,6 +71,8 @@ hb_audio_resample_t* hb_audio_resample_init(enum AVSampleFormat output_sample_fm
 int                  hb_audio_resample_update(hb_audio_resample_t *resample,
                                               enum AVSampleFormat new_sample_fmt,
                                               uint64_t new_channel_layout,
+                                              double new_surroundmixlev,
+                                              double new_centermixlev,
                                               int new_channels);
 
 /* Free an hb_audio_remsample_t. */
index 9ff9f44a3c2c78d156352dbcc18687f3d502b266..6315498cc5bb73871ee46212660c00949266730b 100644 (file)
@@ -722,43 +722,36 @@ int hb_get_best_mixdown(uint32_t codec, uint64_t layout, int mixdown)
         // Audio passthrough, no mixdown
         return HB_AMIXDOWN_NONE;
     }
-    else if ((layout & AV_CH_LAYOUT_5POINT1) == AV_CH_LAYOUT_5POINT1 ||
-             (layout & AV_CH_LAYOUT_5POINT1_BACK) == AV_CH_LAYOUT_5POINT1_BACK)
+    else if ((layout & AV_CH_LAYOUT_2_1) == AV_CH_LAYOUT_2_1 ||
+             (layout & AV_CH_LAYOUT_2_2) == AV_CH_LAYOUT_2_2 ||
+             (layout & AV_CH_LAYOUT_QUAD) == AV_CH_LAYOUT_QUAD)
     {
-        // full 3F2R, possibly with additional channels, and an LFE
-        // limiting factor: liba52, libdca (can't upmix)
-        if (codec == HB_ACODEC_LAME || codec == HB_ACODEC_FFAAC)
+        // at least 2 front channels and one back or side channel
+        // allow downmixing or upmixing to 5.1 (yes, we can)
+        if (codec != HB_ACODEC_LAME && codec != HB_ACODEC_FFAAC)
         {
-            best_mixdown = HB_AMIXDOWN_DOLBYPLII;
+            best_mixdown = HB_AMIXDOWN_6CH;
         }
         else
         {
-            best_mixdown = HB_AMIXDOWN_6CH;
+            best_mixdown = HB_AMIXDOWN_DOLBYPLII;
         }
     }
-    else if ((layout & AV_CH_LAYOUT_5POINT0) == AV_CH_LAYOUT_5POINT0 ||
-             (layout & AV_CH_LAYOUT_5POINT0_BACK) == AV_CH_LAYOUT_5POINT0_BACK)
+    else if (layout == AV_CH_LAYOUT_STEREO_DOWNMIX)
     {
-        // full 3F2R, possibly with additional channels, but no LFE
-        // limiting factor: liba52, libdca (can't upmix)
-        // limiting factor: libdca (can only do DPL2 with 3F2R sources)
-        best_mixdown = HB_AMIXDOWN_DOLBYPLII;
+        // Dolby in, allow Dolby out
+        best_mixdown = HB_AMIXDOWN_DOLBY;
     }
-    else if(layout == AV_CH_LAYOUT_STEREO)
+    else if (av_get_channel_layout_nb_channels(layout) > 1)
     {
-        // limiting factor: no Dolby Surround for Stereo sources
+        // more than one channel, allow Stereo downmix
         best_mixdown = HB_AMIXDOWN_STEREO;
     }
-    else if(av_get_channel_layout_nb_channels(layout) == 1)
+    else
     {
         // only one channel, not much point in upmixing
         best_mixdown = HB_AMIXDOWN_MONO;
     }
-    else
-    {
-        // everything else, including Dolby (AV_CH_LAYOUT_STEREO_DOWNMIX)
-        best_mixdown = HB_AMIXDOWN_DOLBY;
-    }
 
     // return the best that is not greater than the requested mixdown
     // HB_INVALID_AMIXDOWN means the caller requested the best available mixdown
@@ -773,7 +766,7 @@ int hb_get_default_mixdown(uint32_t codec, uint64_t layout)
     int mixdown;
     switch (codec)
     {
-        // the AC3 encoder defaults to the best mixdown up to 6-channel
+        // the FLAC and AC3 encoders default to the best mixdown up to 6-channel
         case HB_ACODEC_FFFLAC:
         case HB_ACODEC_AC3:
             mixdown = HB_AMIXDOWN_6CH;
index 0c1708de20e681dd054d18e00fdabd4dd68f3bb9..5f9960a91941c9f687c7f30611474b9929588587 100644 (file)
@@ -9,6 +9,7 @@
 
 #include "hb.h"
 #include "audio_remap.h"
+#include "audio_resample.h"
 
 #include "a52dec/a52.h"
 #include "libavutil/crc.h"
@@ -20,11 +21,9 @@ struct hb_work_private_s
     /* liba52 handle */
     a52_state_t * state;
 
-    int           flags_in;
-    int           flags_out;
+    int           flags;
     int           rate;
     int           bitrate;
-    int           out_discrete_channels;
     int           error;
     int           frames;                   // number of good frames decoded
     int           crc_errors;               // number of frames with crc errors
@@ -36,6 +35,11 @@ struct hb_work_private_s
     hb_list_t    *list;
     const AVCRC  *crc_table;
     uint8_t       frame[3840];
+
+    int                 nchannels;
+    uint64_t            channel_layout;
+    hb_audio_resample_t *resample;
+    int                 *remap_table;
 };
 
 static int  deca52Init( hb_work_object_t *, hb_job_t * );
@@ -55,6 +59,33 @@ hb_work_object_t hb_deca52 =
     deca52BSInfo
 };
 
+/* Translate acmod and lfeon on AV_CH_LAYOUT */
+static const uint64_t acmod2layout[] =
+{
+    AV_CH_LAYOUT_STEREO,         // A52_CHANNEL   (0)
+    AV_CH_LAYOUT_MONO,           // A52_MONO      (1)
+    AV_CH_LAYOUT_STEREO,         // A52_STEREO    (2)
+    AV_CH_LAYOUT_SURROUND,       // A52_3F        (3)
+    AV_CH_LAYOUT_2_1,            // A52_2F1R      (4)
+    AV_CH_LAYOUT_4POINT0,        // A52_3F1R      (5)
+    AV_CH_LAYOUT_2_2,            // A52_2F2R      (6)
+    AV_CH_LAYOUT_5POINT0,        // A52_3F2R      (7)
+    AV_CH_LAYOUT_MONO,           // A52_CHANNEL1  (8)
+    AV_CH_LAYOUT_MONO,           // A52_CHANNEL2  (9)
+    AV_CH_LAYOUT_STEREO_DOWNMIX, // A52_DOLBY    (10)
+    AV_CH_LAYOUT_STEREO,
+    AV_CH_LAYOUT_STEREO,
+    AV_CH_LAYOUT_STEREO,
+    AV_CH_LAYOUT_STEREO,
+    AV_CH_LAYOUT_STEREO,     // A52_CHANNEL_MASK (15)
+};
+
+static const uint64_t lfeon2layout[] =
+{
+    0,
+    AV_CH_LOW_FREQUENCY,
+};
+
 /***********************************************************************
  * Local prototypes
  **********************************************************************/
@@ -89,48 +120,36 @@ static sample_t dynrng_call (sample_t c, void *data)
  ***********************************************************************
  * Allocate the work object, initialize liba52
  **********************************************************************/
-static int deca52Init( hb_work_object_t * w, hb_job_t * job )
+static int deca52Init(hb_work_object_t *w, hb_job_t *job)
 {
-    hb_work_private_t * pv = calloc( 1, sizeof( hb_work_private_t ) );
-    hb_audio_t * audio = w->audio;
+    hb_work_private_t *pv = calloc(1, sizeof(hb_work_private_t));
+    hb_audio_t *audio = w->audio;
     w->private_data = pv;
 
-    pv->job   = job;
-
-    pv->crc_table = av_crc_get_table( AV_CRC_16_ANSI );
+    pv->job       = job;
+    pv->state     = a52_init(0);
     pv->list      = hb_list_init();
-    pv->state     = a52_init( 0 );
-    pv->level     = 1.0;
-    pv->dynamic_range_compression = audio->config.out.dynamic_range_compression;
+    pv->crc_table = av_crc_get_table(AV_CRC_16_ANSI);
 
-    /* Decide what format we want out of a52dec;
-     * work.c has already done some of this deduction for us in do_job(). */
-    switch( audio->config.out.mixdown )
+    /* Downmixing */
+    if (audio->config.out.codec != HB_ACODEC_AC3_PASS)
     {
-        case HB_AMIXDOWN_6CH:
-            pv->flags_out = (A52_3F2R|A52_LFE);
-            break;
-
-        case HB_AMIXDOWN_DOLBYPLII:
-            pv->flags_out = (A52_DOLBY|A52_USE_DPLII);
-            break;
-
-        case HB_AMIXDOWN_DOLBY:
-            pv->flags_out = A52_DOLBY;
-            break;
-
-        case HB_AMIXDOWN_MONO:
-            pv->flags_out = A52_MONO;
-            break;
-
-        default:
-            pv->flags_out = A52_STEREO;
-            break;
+        /* We want AV_SAMPLE_FMT_FLT samples */
+        pv->level = 1.0;
+        pv->dynamic_range_compression =
+            audio->config.out.dynamic_range_compression;
+
+        int mode;
+        uint64_t layout = hb_ff_mixdown_xlat(audio->config.out.mixdown, &mode);
+        pv->resample = hb_audio_resample_init(AV_SAMPLE_FMT_FLT, layout, mode,
+                                              audio->config.out.normalize_mix_level);
+        if (pv->resample == NULL)
+        {
+            hb_error("deca52Init: hb_audio_resample_init() failed");
+            return 1;
+        }
     }
 
-    /* pass the number of channels used into the private work data */
-    pv->out_discrete_channels = hb_mixdown_get_discrete_channel_count( audio->config.out.mixdown );
-
     return 0;
 }
 
@@ -139,19 +158,25 @@ static int deca52Init( hb_work_object_t * w, hb_job_t * job )
  ***********************************************************************
  * Free memory
  **********************************************************************/
-static void deca52Close( hb_work_object_t * w )
+static void deca52Close(hb_work_object_t *w)
 {
-    hb_work_private_t * pv = w->private_data;
+    hb_work_private_t *pv = w->private_data;
+    w->private_data = NULL;
 
-    if ( pv->crc_errors )
+    if (pv->crc_errors)
     {
-        hb_log( "deca52: %d frames decoded, %d crc errors, %d bytes dropped",
-                pv->frames, pv->crc_errors, pv->bytes_dropped );
+        hb_log("deca52: %d frames decoded, %d crc errors, %d bytes dropped",
+               pv->frames, pv->crc_errors, pv->bytes_dropped);
     }
-    a52_free( pv->state );
-    hb_list_empty( &pv->list );
-    free( pv );
-    w->private_data = NULL;
+
+    if (pv->remap_table != NULL)
+    {
+        free(pv->remap_table);
+    }
+    hb_audio_resample_free(pv->resample);
+    hb_list_empty(&pv->list);
+    a52_free(pv->state);
+    free(pv);
 }
 
 /***********************************************************************
@@ -200,13 +225,12 @@ static int deca52Work( hb_work_object_t * w, hb_buffer_t ** buf_in,
  ***********************************************************************
  *
  **********************************************************************/
-static hb_buffer_t * Decode( hb_work_object_t * w )
+static hb_buffer_t* Decode(hb_work_object_t *w)
 {
-    hb_work_private_t * pv = w->private_data;
-    hb_buffer_t * buf;
-    hb_audio_t  * audio = w->audio;
-    int           i, j, k;
-    int           size = 0;
+    hb_work_private_t *pv = w->private_data;
+    hb_audio_t *audio = w->audio;
+    hb_buffer_t *out;
+    int size = 0;
 
     // check that we're at the start of a valid frame and align to the
     // start of a valid frame if we're not.
@@ -216,7 +240,7 @@ static hb_buffer_t * Decode( hb_work_object_t * w )
     {
         /* check if this is a valid header */
         hb_list_seebytes( pv->list, pv->frame, 7 );
-        size = a52_syncinfo( pv->frame, &pv->flags_in, &pv->rate, &pv->bitrate );
+        size = a52_syncinfo(pv->frame, &pv->flags, &pv->rate, &pv->bitrate);
         if ( size > 0 )
         {
             // header looks valid - check the crc1
@@ -277,65 +301,96 @@ static hb_buffer_t * Decode( hb_work_object_t * w )
         ipts = -1;
     }
 
-    double pts = ( ipts != -1 ) ? ipts : pv->next_expected_pts;
     double frame_dur = (6. * 256. * 90000.) / pv->rate;
+    double pts       = (ipts != -1) ? (double)ipts : pv->next_expected_pts;
 
     /* AC3 passthrough: don't decode the AC3 frame */
-    if( audio->config.out.codec == HB_ACODEC_AC3_PASS )
+    if (audio->config.out.codec == HB_ACODEC_AC3_PASS)
     {
-        buf = hb_buffer_init( size );
-        memcpy( buf->data, pv->frame, size );
-        buf->s.start = pts;
-        buf->s.duration = frame_dur;
-        pts += frame_dur;
-        buf->s.stop  = pts;
-        pv->next_expected_pts = pts;
-        return buf;
+        out = hb_buffer_init(size);
+        memcpy(out->data, pv->frame, size);
     }
-
-    /* Feed liba52 */
-    a52_frame( pv->state, pv->frame, &pv->flags_out, &pv->level, 0 );
-
-    /* If a user specifies strong dynamic range compression (>1), adjust it.
-       If a user specifies default dynamic range compression (1), leave it alone.
-       If a user specifies no dynamic range compression (0), call a null function. */
-    if( pv->dynamic_range_compression > 1.0 )
-    {
-        a52_dynrng( pv->state, dynrng_call, &pv->dynamic_range_compression );
-    }
-    else if( !pv->dynamic_range_compression )
+    else
     {
-        a52_dynrng( pv->state, NULL, NULL );
-    }
+        int i, j, k;
+        hb_buffer_t *flt;
 
-    /* 6 blocks per frame, 256 samples per block, channelsused channels */
-    buf        = hb_buffer_init( 6 * 256 * pv->out_discrete_channels * sizeof( float ) );
-    buf->s.start = pts;
-    buf->s.duration = frame_dur;
-    pts += frame_dur;
-    buf->s.stop  = pts;
-    pv->next_expected_pts = pts;
+        /* Feed liba52 */
+        a52_frame(pv->state, pv->frame, &pv->flags, &pv->level, 0);
 
-    for( i = 0; i < 6; i++ )
-    {
-        sample_t * samples_in;
-        float    * samples_out;
+        /* If the user requested strong DRC (>1), adjust it.
+         * If the user requested default DRC (1), leave it alone.
+         * If the user requested no DRC (0), call a null function. */
+        if (pv->dynamic_range_compression > 1.0)
+        {
+            a52_dynrng(pv->state, dynrng_call, &pv->dynamic_range_compression);
+        }
+        else if (!pv->dynamic_range_compression)
+        {
+            a52_dynrng(pv->state, NULL, NULL);
+        }
+
+        /* Update input channel layout and prepare remapping */
+        uint64_t new_layout = (acmod2layout[(pv->flags & A52_CHANNEL_MASK)] |
+                               lfeon2layout[(pv->flags & A52_LFE) != 0]);
+        if (new_layout != pv->channel_layout)
+        {
+            if (pv->remap_table != NULL)
+            {
+                free(pv->remap_table);
+            }
+            pv->remap_table = hb_audio_remap_build_table(new_layout,
+                                                         &hb_libav_chan_map,
+                                                         &hb_liba52_chan_map);
+            if (pv->remap_table == NULL)
+            {
+                hb_error("deca52: hb_audio_remap_build_table() failed");
+                return NULL;
+            }
+            pv->channel_layout = new_layout;
+            pv->nchannels = av_get_channel_layout_nb_channels(new_layout);
+        }
 
-        a52_block( pv->state );
-        samples_in  = a52_samples( pv->state );
-        samples_out = ((float *) buf->data) + 256 * pv->out_discrete_channels * i;
+        /* 6 blocks per frame, 256 samples per block, pv->nchannels channels */
+        flt = hb_buffer_init(1536 * pv->nchannels * sizeof(float));
 
-        /* Interleave */
-        for( j = 0; j < 256; j++ )
+        for (i = 0; i < 6; i++)
         {
-            for ( k = 0; k < pv->out_discrete_channels; k++ )
+            sample_t *samples_in;
+            float    *samples_out;
+
+            a52_block(pv->state);
+            samples_in  = a52_samples(pv->state);
+            samples_out = ((float*)flt->data) + 256 * pv->nchannels * i;
+
+            /* Planar -> interleaved, remap to Libav channel order */
+            for (j = 0; j < 256; j++)
             {
-                samples_out[(pv->out_discrete_channels*j)+k]   = samples_in[(256*k)+j];
+                for (k = 0; k < pv->nchannels; k++)
+                {
+                    samples_out[(pv->nchannels*j)+k] =
+                     samples_in[(256*pv->remap_table[k])+j];
+                }
             }
         }
+        hb_audio_resample_update(pv->resample, AV_SAMPLE_FMT_FLT,
+                                 pv->channel_layout, (double)pv->state->slev,
+                                 (double)pv->state->clev, pv->nchannels);
+        out = hb_audio_resample(pv->resample, (void*)flt->data, 1536);
+        hb_buffer_close(&flt);
+    }
 
+    if (out == NULL)
+    {
+        return NULL;
     }
-    return buf;
+
+    out->s.start          = pts;
+    out->s.duration       = frame_dur;
+    pts                  += frame_dur;
+    out->s.stop           = pts;
+    pv->next_expected_pts = pts;
+    return out;
 }
 
 static int find_sync( const uint8_t *buf, int len )
@@ -439,52 +494,11 @@ static int deca52BSInfo( hb_work_object_t *w, const hb_buffer_t *b,
     info->mode = raw & 0x7;      /* bsmod is the following 3 bits */
     info->samples_per_frame = 1536;
 
-    switch( flags & A52_CHANNEL_MASK )
-    {
-        /* mono sources */
-        case A52_MONO:
-        case A52_CHANNEL1:
-        case A52_CHANNEL2:
-            info->channel_layout = AV_CH_LAYOUT_MONO;
-            break;
-        /* stereo input */
-        case A52_CHANNEL:
-        case A52_STEREO:
-            info->channel_layout = AV_CH_LAYOUT_STEREO;
-            break;
-        /* Dolby Pro Logic (a.k.a. Dolby Surround), 4.0 channels (matrix-encoded) */
-        case A52_DOLBY:
-            info->channel_layout = AV_CH_LAYOUT_STEREO_DOWNMIX;
-            break;
-        /* 3F/2R input */
-        case A52_3F2R:
-            info->channel_layout = AV_CH_LAYOUT_5POINT0;
-            break;
-        /* 3F/1R input */
-        case A52_3F1R:
-            info->channel_layout = AV_CH_LAYOUT_4POINT0;
-            break;
-        /* other inputs */
-        case A52_3F:
-            info->channel_layout = AV_CH_LAYOUT_SURROUND;
-            break;
-        case A52_2F1R:
-            info->channel_layout = AV_CH_LAYOUT_2_1;
-            break;
-        case A52_2F2R:
-            info->channel_layout = AV_CH_LAYOUT_2_2;
-            break;
-        /* unknown */
-        default:
-            info->channel_layout = AV_CH_LAYOUT_STEREO;
-    }
-
-    if (flags & A52_LFE)
-    {
-        info->channel_layout |= AV_CH_LOW_FREQUENCY;
-    }
+    info->channel_layout = (acmod2layout[(flags & A52_CHANNEL_MASK)] |
+                            lfeon2layout[(flags & A52_LFE) != 0]);
 
-    info->channel_map = &hb_liba52_chan_map;
+    // we remap to Libav order in Decode()
+    info->channel_map = &hb_libav_chan_map;
 
     return 1;
 }
index 934f7611e453ae462162c9505d3c10522c8b3c43..5dc3b75b56b621f7f7b463234cc3a6091f7d9507 100644 (file)
@@ -1454,6 +1454,7 @@ static void decodeAudio(hb_audio_t *audio, hb_work_private_t *pv, uint8_t *data,
             {
                 hb_audio_resample_update(pv->resample, pv->context->sample_fmt,
                                          pv->context->channel_layout,
+                                         HB_MIXLEV_DEFAULT, HB_MIXLEV_DEFAULT,
                                          pv->context->channels);
                 out = hb_audio_resample(pv->resample, (void*)frame.data[0],
                                         frame.nb_samples);
index 0d4e449d11c7b63b46f654a41f55be8fdcc3c026..1511a6abd4b416255ddd51ee57d59a0afff5ccaa 100644 (file)
@@ -331,7 +331,8 @@ static hb_buffer_t *Decode( hb_work_object_t *w )
 
     hb_buffer_t *out;
     hb_audio_resample_update(pv->resample, AV_SAMPLE_FMT_FLT,
-                             hdr2layout[pv->nchannels - 1], pv->nchannels);
+                             hdr2layout[pv->nchannels - 1], HB_MIXLEV_DEFAULT,
+                             HB_MIXLEV_DEFAULT, pv->nchannels);
     out = hb_audio_resample(pv->resample, (void*)pv->data, pv->nsamples);
     if (out == NULL)
     {
index ef5297ccab22e3e2be68f8eb9606ad4414acc271..8435b022d1fbe1baeb4445d95e2e71f8cd6354fd 100644 (file)
@@ -121,7 +121,8 @@ static int encavcodecaInit(hb_work_object_t *w, hb_job_t *job)
                                           context->channel_layout,
                                           AV_MATRIX_ENCODING_NONE, 0);
     if (hb_audio_resample_update(pv->resample, AV_SAMPLE_FMT_FLT,
-                                 context->channel_layout, context->channels))
+                                 context->channel_layout, HB_MIXLEV_DEFAULT,
+                                 HB_MIXLEV_DEFAULT, context->channels))
     {
         hb_error("encavcodecaInit: hb_audio_resample_update() failed");
         hb_audio_resample_free(pv->resample);