[FFmpeg-cvslog] Add Dolby/DPLII downmix support to libavresample

John Stebbins git at videolan.org
Mon Jun 18 20:25:45 CEST 2012


ffmpeg | branch: master | John Stebbins <jstebbins.hb at gmail.com> | Sat Jun  9 13:45:49 2012 -0700| [3971be0eb5d382b85f1d8772c51f21cccdc68eab] | committer: Justin Ruggles

Add Dolby/DPLII downmix support to libavresample

Signed-off-by: Justin Ruggles <justin.ruggles at gmail.com>

> http://git.videolan.org/gitweb.cgi/ffmpeg.git/?a=commit;h=3971be0eb5d382b85f1d8772c51f21cccdc68eab
---

 doc/APIchanges                   |    3 ++
 libavresample/audio_mix.c        |    3 +-
 libavresample/audio_mix_matrix.c |   60 +++++++++++++++++++++++++++++++++-----
 libavresample/avresample.h       |    3 +-
 libavresample/internal.h         |    1 +
 libavresample/options.c          |    4 +++
 libavresample/version.h          |    2 +-
 libavutil/audioconvert.h         |    7 +++++
 8 files changed, 72 insertions(+), 11 deletions(-)

diff --git a/doc/APIchanges b/doc/APIchanges
index 50cc787..4d14882 100644
--- a/doc/APIchanges
+++ b/doc/APIchanges
@@ -13,6 +13,9 @@ libavutil:     2011-04-18
 
 API changes, most recent first:
 
+2012-xx-xx - xxxxxxx - lavr 0.0.3
+  Add a parameter to avresample_build_matrix() for Dolby/DPLII downmixing.
+
 2012-xx-xx - xxxxxxx - lavfi 2.23.0 - avfilter.h
   Add AVFilterContext.nb_inputs/outputs. Deprecate
   AVFilterContext.input/output_count.
diff --git a/libavresample/audio_mix.c b/libavresample/audio_mix.c
index 7ab11b0..9319222 100644
--- a/libavresample/audio_mix.c
+++ b/libavresample/audio_mix.c
@@ -320,7 +320,8 @@ int ff_audio_mix_init(AVAudioResampleContext *avr)
                                       avr->center_mix_level,
                                       avr->surround_mix_level,
                                       avr->lfe_mix_level, 1, matrix_dbl,
-                                      avr->in_channels);
+                                      avr->in_channels,
+                                      avr->matrix_encoding);
         if (ret < 0) {
             av_free(matrix_dbl);
             return ret;
diff --git a/libavresample/audio_mix_matrix.c b/libavresample/audio_mix_matrix.c
index 6135b02..f7121c8 100644
--- a/libavresample/audio_mix_matrix.c
+++ b/libavresample/audio_mix_matrix.c
@@ -54,6 +54,8 @@
 #define SURROUND_DIRECT_LEFT   33
 #define SURROUND_DIRECT_RIGHT  34
 
+#define SQRT3_2      1.22474487139158904909  /* sqrt(3/2) */
+
 static av_always_inline int even(uint64_t layout)
 {
     return (!layout || (layout & (layout - 1)));
@@ -83,14 +85,21 @@ static int sane_layout(uint64_t layout)
 int avresample_build_matrix(uint64_t in_layout, uint64_t out_layout,
                             double center_mix_level, double surround_mix_level,
                             double lfe_mix_level, int normalize,
-                            double *matrix_out, int stride)
+                            double *matrix_out, int stride,
+                            enum AVMatrixEncoding matrix_encoding)
 {
     int i, j, out_i, out_j;
     double matrix[64][64] = {{0}};
-    int64_t unaccounted = in_layout & ~out_layout;
+    int64_t unaccounted;
     double maxcoef = 0;
     int in_channels, out_channels;
 
+    if ((out_layout & AV_CH_LAYOUT_STEREO_DOWNMIX) == AV_CH_LAYOUT_STEREO_DOWNMIX) {
+        out_layout = AV_CH_LAYOUT_STEREO;
+    }
+
+    unaccounted = in_layout & ~out_layout;
+
     in_channels  = av_get_channel_layout_nb_channels( in_layout);
     out_channels = av_get_channel_layout_nb_channels(out_layout);
 
@@ -140,8 +149,19 @@ int avresample_build_matrix(uint64_t in_layout, uint64_t out_layout,
             matrix[SIDE_LEFT ][BACK_CENTER] += M_SQRT1_2;
             matrix[SIDE_RIGHT][BACK_CENTER] += M_SQRT1_2;
         } else if (out_layout & AV_CH_FRONT_LEFT) {
-            matrix[FRONT_LEFT ][BACK_CENTER] += surround_mix_level * M_SQRT1_2;
-            matrix[FRONT_RIGHT][BACK_CENTER] += surround_mix_level * M_SQRT1_2;
+            if (matrix_encoding == AV_MATRIX_ENCODING_DOLBY ||
+                matrix_encoding == AV_MATRIX_ENCODING_DPLII) {
+                if (unaccounted & (AV_CH_BACK_LEFT | AV_CH_SIDE_LEFT)) {
+                    matrix[FRONT_LEFT ][BACK_CENTER] -= surround_mix_level * M_SQRT1_2;
+                    matrix[FRONT_RIGHT][BACK_CENTER] += surround_mix_level * M_SQRT1_2;
+                } else {
+                    matrix[FRONT_LEFT ][BACK_CENTER] -= surround_mix_level;
+                    matrix[FRONT_RIGHT][BACK_CENTER] += surround_mix_level;
+                }
+            } else {
+                matrix[FRONT_LEFT ][BACK_CENTER] += surround_mix_level * M_SQRT1_2;
+                matrix[FRONT_RIGHT][BACK_CENTER] += surround_mix_level * M_SQRT1_2;
+            }
         } else if (out_layout & AV_CH_FRONT_CENTER) {
             matrix[FRONT_CENTER][BACK_CENTER] += surround_mix_level * M_SQRT1_2;
         } else
@@ -163,8 +183,20 @@ int avresample_build_matrix(uint64_t in_layout, uint64_t out_layout,
                 matrix[SIDE_RIGHT][BACK_RIGHT] += 1.0;
             }
         } else if (out_layout & AV_CH_FRONT_LEFT) {
-            matrix[FRONT_LEFT ][BACK_LEFT ] += surround_mix_level;
-            matrix[FRONT_RIGHT][BACK_RIGHT] += surround_mix_level;
+            if (matrix_encoding == AV_MATRIX_ENCODING_DOLBY) {
+                matrix[FRONT_LEFT ][BACK_LEFT ] -= surround_mix_level * M_SQRT1_2;
+                matrix[FRONT_LEFT ][BACK_RIGHT] -= surround_mix_level * M_SQRT1_2;
+                matrix[FRONT_RIGHT][BACK_LEFT ] += surround_mix_level * M_SQRT1_2;
+                matrix[FRONT_RIGHT][BACK_RIGHT] += surround_mix_level * M_SQRT1_2;
+            } else if (matrix_encoding == AV_MATRIX_ENCODING_DPLII) {
+                matrix[FRONT_LEFT ][BACK_LEFT ] -= surround_mix_level * SQRT3_2;
+                matrix[FRONT_LEFT ][BACK_RIGHT] -= surround_mix_level * M_SQRT1_2;
+                matrix[FRONT_RIGHT][BACK_LEFT ] += surround_mix_level * M_SQRT1_2;
+                matrix[FRONT_RIGHT][BACK_RIGHT] += surround_mix_level * SQRT3_2;
+            } else {
+                matrix[FRONT_LEFT ][BACK_LEFT ] += surround_mix_level;
+                matrix[FRONT_RIGHT][BACK_RIGHT] += surround_mix_level;
+            }
         } else if (out_layout & AV_CH_FRONT_CENTER) {
             matrix[FRONT_CENTER][BACK_LEFT ] += surround_mix_level * M_SQRT1_2;
             matrix[FRONT_CENTER][BACK_RIGHT] += surround_mix_level * M_SQRT1_2;
@@ -187,8 +219,20 @@ int avresample_build_matrix(uint64_t in_layout, uint64_t out_layout,
             matrix[BACK_CENTER][SIDE_LEFT ] += M_SQRT1_2;
             matrix[BACK_CENTER][SIDE_RIGHT] += M_SQRT1_2;
         } else if (out_layout & AV_CH_FRONT_LEFT) {
-            matrix[FRONT_LEFT ][SIDE_LEFT ] += surround_mix_level;
-            matrix[FRONT_RIGHT][SIDE_RIGHT] += surround_mix_level;
+            if (matrix_encoding == AV_MATRIX_ENCODING_DOLBY) {
+                matrix[FRONT_LEFT ][SIDE_LEFT ] -= surround_mix_level * M_SQRT1_2;
+                matrix[FRONT_LEFT ][SIDE_RIGHT] -= surround_mix_level * M_SQRT1_2;
+                matrix[FRONT_RIGHT][SIDE_LEFT ] += surround_mix_level * M_SQRT1_2;
+                matrix[FRONT_RIGHT][SIDE_RIGHT] += surround_mix_level * M_SQRT1_2;
+            } else if (matrix_encoding == AV_MATRIX_ENCODING_DPLII) {
+                matrix[FRONT_LEFT ][SIDE_LEFT ] -= surround_mix_level * SQRT3_2;
+                matrix[FRONT_LEFT ][SIDE_RIGHT] -= surround_mix_level * M_SQRT1_2;
+                matrix[FRONT_RIGHT][SIDE_LEFT ] += surround_mix_level * M_SQRT1_2;
+                matrix[FRONT_RIGHT][SIDE_RIGHT] += surround_mix_level * SQRT3_2;
+            } else {
+                matrix[FRONT_LEFT ][SIDE_LEFT ] += surround_mix_level;
+                matrix[FRONT_RIGHT][SIDE_RIGHT] += surround_mix_level;
+            }
         } else if (out_layout & AV_CH_FRONT_CENTER) {
             matrix[FRONT_CENTER][SIDE_LEFT ] += surround_mix_level * M_SQRT1_2;
             matrix[FRONT_CENTER][SIDE_RIGHT] += surround_mix_level * M_SQRT1_2;
diff --git a/libavresample/avresample.h b/libavresample/avresample.h
index 65d4d2d..002bec2 100644
--- a/libavresample/avresample.h
+++ b/libavresample/avresample.h
@@ -131,12 +131,13 @@ void avresample_free(AVAudioResampleContext **avr);
  *                            the weight of input channel i in output channel o.
  * @param stride              distance between adjacent input channels in the
  *                            matrix array
+ * @param matrix_encoding     matrixed stereo downmix mode (e.g. dplii)
  * @return                    0 on success, negative AVERROR code on failure
  */
 int avresample_build_matrix(uint64_t in_layout, uint64_t out_layout,
                             double center_mix_level, double surround_mix_level,
                             double lfe_mix_level, int normalize, double *matrix,
-                            int stride);
+                            int stride, enum AVMatrixEncoding matrix_encoding);
 
 /**
  * Get the current channel mixing matrix.
diff --git a/libavresample/internal.h b/libavresample/internal.h
index 49ea6a6..fa9499a 100644
--- a/libavresample/internal.h
+++ b/libavresample/internal.h
@@ -70,6 +70,7 @@ struct AVAudioResampleContext {
     AudioConvert *ac_out;       /**< output sample format conversion context */
     ResampleContext *resample;  /**< resampling context                      */
     AudioMix *am;               /**< channel mixing context                  */
+    enum AVMatrixEncoding matrix_encoding;      /**< matrixed stereo encoding */
 };
 
 #endif /* AVRESAMPLE_INTERNAL_H */
diff --git a/libavresample/options.c b/libavresample/options.c
index 5430c4d..a1a0b0c 100644
--- a/libavresample/options.c
+++ b/libavresample/options.c
@@ -52,6 +52,10 @@ static const AVOption options[] = {
     { "phase_shift",            "Resampling Phase Shift",   OFFSET(phase_shift),            AV_OPT_TYPE_INT,    { 10                    }, 0,                    30, /* ??? */           PARAM },
     { "linear_interp",          "Use Linear Interpolation", OFFSET(linear_interp),          AV_OPT_TYPE_INT,    { 0                     }, 0,                    1,                      PARAM },
     { "cutoff",                 "Cutoff Frequency Ratio",   OFFSET(cutoff),                 AV_OPT_TYPE_DOUBLE, { 0.8                   }, 0.0,                  1.0,                    PARAM },
+    { "matrix_encoding",        "Matrixed Stereo Encoding", OFFSET(matrix_encoding),        AV_OPT_TYPE_INT,    { AV_MATRIX_ENCODING_NONE}, AV_MATRIX_ENCODING_NONE,     AV_MATRIX_ENCODING_NB-1, PARAM, "matrix_encoding" },
+        { "none",  "None",               0, AV_OPT_TYPE_CONST, { AV_MATRIX_ENCODING_NONE  }, INT_MIN, INT_MAX, PARAM, "matrix_encoding" },
+        { "dolby", "Dolby",              0, AV_OPT_TYPE_CONST, { AV_MATRIX_ENCODING_DOLBY }, INT_MIN, INT_MAX, PARAM, "matrix_encoding" },
+        { "dplii", "Dolby Pro Logic II", 0, AV_OPT_TYPE_CONST, { AV_MATRIX_ENCODING_DPLII }, INT_MIN, INT_MAX, PARAM, "matrix_encoding" },
     { NULL },
 };
 
diff --git a/libavresample/version.h b/libavresample/version.h
index 6211a56..63f07f5 100644
--- a/libavresample/version.h
+++ b/libavresample/version.h
@@ -21,7 +21,7 @@
 
 #define LIBAVRESAMPLE_VERSION_MAJOR  0
 #define LIBAVRESAMPLE_VERSION_MINOR  0
-#define LIBAVRESAMPLE_VERSION_MICRO  2
+#define LIBAVRESAMPLE_VERSION_MICRO  3
 
 #define LIBAVRESAMPLE_VERSION_INT  AV_VERSION_INT(LIBAVRESAMPLE_VERSION_MAJOR, \
                                                   LIBAVRESAMPLE_VERSION_MINOR, \
diff --git a/libavutil/audioconvert.h b/libavutil/audioconvert.h
index 691c64a..7e79097 100644
--- a/libavutil/audioconvert.h
+++ b/libavutil/audioconvert.h
@@ -101,6 +101,13 @@
 #define AV_CH_LAYOUT_OCTAGONAL         (AV_CH_LAYOUT_5POINT0|AV_CH_BACK_LEFT|AV_CH_BACK_CENTER|AV_CH_BACK_RIGHT)
 #define AV_CH_LAYOUT_STEREO_DOWNMIX    (AV_CH_STEREO_LEFT|AV_CH_STEREO_RIGHT)
 
+enum AVMatrixEncoding {
+    AV_MATRIX_ENCODING_NONE,
+    AV_MATRIX_ENCODING_DOLBY,
+    AV_MATRIX_ENCODING_DPLII,
+    AV_MATRIX_ENCODING_NB
+};
+
 /**
  * @}
  */



More information about the ffmpeg-cvslog mailing list