[FFmpeg-devel] [PATCH 2/2] Add support for building with old LLS ABI in libavutil

Michael Niedermayer michaelni at gmx.at
Sat Nov 16 00:01:11 CET 2013


This allows building libavutil that is compatible with what we had in
ffmpeg 1.2
The incompatibility was caused by libav changing the ABI of the lls code
without bumping the major version number

The alternative fix would be to bump the major version number / soname now
though to fix the issue for 2.0 and 2.1 it would then be needed to do that
in a point release.

lls1 taken from ff130d7

See: 502ab21af0ca68f76d6112722c46d2f35c004053
See: cc6714bb16b1f0716ba43701d47273dbe9657b8b
See: 41578f70cf8aec8e7565fba1ca7e07f3dc46c3d2
Signed-off-by: Michael Niedermayer <michaelni at gmx.at>
---
 configure          |    3 +
 libavcodec/lpc.c   |   12 ++++
 libavutil/Makefile |    9 ++-
 libavutil/lls1.c   |  176 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 libavutil/lls1.h   |   54 ++++++++++++++++
 5 files changed, 252 insertions(+), 2 deletions(-)
 create mode 100644 libavutil/lls1.c
 create mode 100644 libavutil/lls1.h

diff --git a/configure b/configure
index c3606bd..60ae85c 100755
--- a/configure
+++ b/configure
@@ -105,6 +105,7 @@ Configuration options:
   --disable-all            disable building components, libraries and programs
   --enable-incompatible-libav-abi enable incompatible Libav fork ABI [no]
   --enable-incompatible-fork-abi  enable incompatible Libav fork ABI (deprecated) [no]
+  --enable-old-libavutil52-abi enable old libavutil52 ABI [no]
 
 Program options:
   --disable-programs       do not build command line programs
@@ -1277,6 +1278,7 @@ CONFIG_LIST="
     hardcoded_tables
     incompatible_libav_abi
     incompatible_fork_abi
+    old_libavutil52_abi
     lsp
     lzo
     mdct
@@ -1386,6 +1388,7 @@ HAVE_LIST_PUB='
     fast_unaligned
     incompatible_libav_abi
     incompatible_fork_abi
+    old_libavutil52_abi
 '
 
 MATH_FUNCS="
diff --git a/libavcodec/lpc.c b/libavcodec/lpc.c
index 1989030..287a1d6 100644
--- a/libavcodec/lpc.c
+++ b/libavcodec/lpc.c
@@ -20,7 +20,11 @@
  */
 
 #include "libavutil/common.h"
+#if HAVE_OLD_LIBAVUTIL52_ABI
+#include "libavutil/lls1.h"
+#else
 #include "libavutil/lls2.h"
+#endif
 
 #define LPC_USE_DOUBLE
 #include "lpc.h"
@@ -226,7 +230,11 @@ int ff_lpc_calc_coefs(LPCContext *s,
 
                 if(pass){
                     double eval, inv, rinv;
+#if HAVE_OLD_LIBAVUTIL52_ABI
+                    eval= avpriv_evaluate_lls(&m[(pass-1)&1], var+1, max_order-1);
+#else
                     eval= m[pass&1].evaluate_lls(&m[(pass-1)&1], var+1, max_order-1);
+#endif
                     eval= (512>>pass) + fabs(eval - var[0]);
                     inv = 1/eval;
                     rinv = sqrt(inv);
@@ -236,7 +244,11 @@ int ff_lpc_calc_coefs(LPCContext *s,
                 }else
                     weight++;
 
+#if HAVE_OLD_LIBAVUTIL52_ABI
+                avpriv_update_lls(&m[pass&1], var, 1.0);
+#else
                 m[pass&1].update_lls(&m[pass&1], var);
+#endif
             }
             avpriv_solve_lls(&m[pass&1], 0.001, 0);
         }
diff --git a/libavutil/Makefile b/libavutil/Makefile
index 5d42893..b35f2ca 100644
--- a/libavutil/Makefile
+++ b/libavutil/Makefile
@@ -90,7 +90,6 @@ OBJS = adler32.o                                                        \
        intfloat_readwrite.o                                             \
        intmath.o                                                        \
        lfg.o                                                            \
-       lls2.o                                                           \
        log.o                                                            \
        log2_tab.o                                                       \
        mathematics.o                                                    \
@@ -143,7 +142,6 @@ TESTPROGS = adler32                                                     \
             fifo                                                        \
             hmac                                                        \
             lfg                                                         \
-            lls2                                                        \
             md5                                                         \
             murmur3                                                     \
             opt                                                         \
@@ -158,6 +156,13 @@ TESTPROGS = adler32                                                     \
             xtea                                                        \
 
 TESTPROGS-$(HAVE_LZO1X_999_COMPRESS) += lzo
+ifdef HAVE_OLD_LIBAVUTIL52_ABI
+OBJS += lls1.o
+TESTPROGS += lls1
+else
+OBJS += lls2.o
+TESTPROGS += lls2
+endif
 
 TOOLS = crypto_bench ffhash ffeval ffescape
 
diff --git a/libavutil/lls1.c b/libavutil/lls1.c
new file mode 100644
index 0000000..a9b1570
--- /dev/null
+++ b/libavutil/lls1.c
@@ -0,0 +1,176 @@
+/*
+ * linear least squares model
+ *
+ * Copyright (c) 2006 Michael Niedermayer <michaelni at gmx.at>
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+/**
+ * @file
+ * linear least squares model
+ */
+
+#include <math.h>
+#include <string.h>
+
+#include "attributes.h"
+#include "version.h"
+#include "lls1.h"
+
+av_cold void avpriv_init_lls(LLSModel *m, int indep_count)
+{
+    memset(m, 0, sizeof(LLSModel));
+    m->indep_count = indep_count;
+}
+
+void avpriv_update_lls(LLSModel *m, double *var, double decay)
+{
+    int i, j;
+
+    for (i = 0; i <= m->indep_count; i++) {
+        for (j = i; j <= m->indep_count; j++) {
+            m->covariance[i][j] *= decay;
+            m->covariance[i][j] += var[i] * var[j];
+        }
+    }
+}
+
+void avpriv_solve_lls(LLSModel *m, double threshold, unsigned short min_order)
+{
+    int i, j, k;
+    double (*factor)[MAX_VARS + 1] = (void *) &m->covariance[1][0];
+    double (*covar) [MAX_VARS + 1] = (void *) &m->covariance[1][1];
+    double *covar_y                = m->covariance[0];
+    int count                      = m->indep_count;
+
+    for (i = 0; i < count; i++) {
+        for (j = i; j < count; j++) {
+            double sum = covar[i][j];
+
+            for (k = i - 1; k >= 0; k--)
+                sum -= factor[i][k] * factor[j][k];
+
+            if (i == j) {
+                if (sum < threshold)
+                    sum = 1.0;
+                factor[i][i] = sqrt(sum);
+            } else {
+                factor[j][i] = sum / factor[i][i];
+            }
+        }
+    }
+
+    for (i = 0; i < count; i++) {
+        double sum = covar_y[i + 1];
+
+        for (k = i - 1; k >= 0; k--)
+            sum -= factor[i][k] * m->coeff[0][k];
+
+        m->coeff[0][i] = sum / factor[i][i];
+    }
+
+    for (j = count - 1; j >= min_order; j--) {
+        for (i = j; i >= 0; i--) {
+            double sum = m->coeff[0][i];
+
+            for (k = i + 1; k <= j; k++)
+                sum -= factor[k][i] * m->coeff[j][k];
+
+            m->coeff[j][i] = sum / factor[i][i];
+        }
+
+        m->variance[j] = covar_y[0];
+
+        for (i = 0; i <= j; i++) {
+            double sum = m->coeff[j][i] * covar[i][i] - 2 * covar_y[i + 1];
+
+            for (k = 0; k < i; k++)
+                sum += 2 * m->coeff[j][k] * covar[k][i];
+
+            m->variance[j] += m->coeff[j][i] * sum;
+        }
+    }
+}
+
+double avpriv_evaluate_lls(LLSModel *m, double *param, int order)
+{
+    int i;
+    double out = 0;
+
+    for (i = 0; i <= order; i++)
+        out += param[i] * m->coeff[order][i];
+
+    return out;
+}
+
+#if FF_API_LLS_PRIVATE
+av_cold void av_init_lls(LLSModel *m, int indep_count)
+{
+    avpriv_init_lls(m, indep_count);
+}
+void av_update_lls(LLSModel *m, double *param, double decay)
+{
+    avpriv_update_lls(m, param, decay);
+}
+void av_solve_lls(LLSModel *m, double threshold, int min_order)
+{
+    avpriv_solve_lls(m, threshold, min_order);
+}
+double av_evaluate_lls(LLSModel *m, double *param, int order)
+{
+    return avpriv_evaluate_lls(m, param, order);
+}
+#endif /* FF_API_LLS_PRIVATE */
+
+#ifdef TEST
+
+#include <stdio.h>
+#include <limits.h>
+#include "lfg.h"
+
+int main(void)
+{
+    LLSModel m;
+    int i, order;
+    AVLFG lfg;
+
+    av_lfg_init(&lfg, 1);
+    avpriv_init_lls(&m, 3);
+
+    for (i = 0; i < 100; i++) {
+        double var[4];
+        double eval;
+
+        var[0] = (av_lfg_get(&lfg) / (double) UINT_MAX - 0.5) * 2;
+        var[1] = var[0] + av_lfg_get(&lfg) / (double) UINT_MAX - 0.5;
+        var[2] = var[1] + av_lfg_get(&lfg) / (double) UINT_MAX - 0.5;
+        var[3] = var[2] + av_lfg_get(&lfg) / (double) UINT_MAX - 0.5;
+        avpriv_update_lls(&m, var, 0.99);
+        avpriv_solve_lls(&m, 0.001, 0);
+        for (order = 0; order < 3; order++) {
+            eval = avpriv_evaluate_lls(&m, var + 1, order);
+            printf("real:%9f order:%d pred:%9f var:%f coeffs:%f %9f %9f\n",
+                   var[0], order, eval, sqrt(m.variance[order] / (i + 1)),
+                   m.coeff[order][0], m.coeff[order][1],
+                   m.coeff[order][2]);
+        }
+    }
+    return 0;
+}
+
+#endif
diff --git a/libavutil/lls1.h b/libavutil/lls1.h
new file mode 100644
index 0000000..c785d44
--- /dev/null
+++ b/libavutil/lls1.h
@@ -0,0 +1,54 @@
+/*
+ * linear least squares model
+ *
+ * Copyright (c) 2006 Michael Niedermayer <michaelni at gmx.at>
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef AVUTIL_LLS_H
+#define AVUTIL_LLS_H
+
+#include "version.h"
+
+#define MAX_VARS 32
+
+//FIXME avoid direct access to LLSModel from outside
+
+/**
+ * Linear least squares model.
+ */
+typedef struct LLSModel {
+    double covariance[MAX_VARS + 1][MAX_VARS + 1];
+    double coeff[MAX_VARS][MAX_VARS];
+    double variance[MAX_VARS];
+    int indep_count;
+} LLSModel;
+
+void avpriv_init_lls(LLSModel *m, int indep_count);
+void avpriv_update_lls(LLSModel *m, double *param, double decay);
+void avpriv_solve_lls(LLSModel *m, double threshold, unsigned short min_order);
+double avpriv_evaluate_lls(LLSModel *m, double *param, int order);
+
+#if FF_API_LLS_PRIVATE
+void av_init_lls(LLSModel *m, int indep_count);
+void av_update_lls(LLSModel *m, double *param, double decay);
+void av_solve_lls(LLSModel *m, double threshold, int min_order);
+double av_evaluate_lls(LLSModel *m, double *param, int order);
+#endif /* FF_API_LLS_PRIVATE */
+
+#endif /* AVUTIL_LLS_H */
-- 
1.7.9.5



More information about the ffmpeg-devel mailing list