shithub: sox

Download patch

ref: 867e2c23d814b664cea10acae920a3fb698c3656
parent: 4428da8ac391ce16d34bff8d9e685fee7ab8983e
author: cbagwell <cbagwell>
date: Sun Nov 29 15:55:56 EST 2009

Add support for dlopen() of amr-nb and amr-wb libraries.

--- a/ChangeLog
+++ b/ChangeLog
@@ -52,6 +52,8 @@
     based formats).  (cbagwell)
   o Allow libsndfile to be dlopen()'ed at runtime if --enable-dl-sndfile
     is used. (Doug Cook)
+  o Allow amr-nb/amr-wb to be dlopen()'ed at runtime if 
+    --enable-dl-amrwb or --enable-dl-amrnb is used. (Doug Cook)
   o amrnb and amrwb formats can optionally use opencore-amr libraries.
     (cbagwell)
 
--- a/INSTALL
+++ b/INSTALL
@@ -156,6 +156,8 @@
 --enable-dl-lame
 --enable-dl-mad
 --enable-dl-sndfile
+--enable-dl-amrnb
+--enable-dl-amrwb
 
 Testing
 -------
--- a/configure.ac
+++ b/configure.ac
@@ -408,18 +408,33 @@
 AC_OPTIONAL_FORMAT(flac, FLAC, [AC_CHECK_HEADER(FLAC/all.h, [AC_CHECK_LIB(FLAC, FLAC__stream_encoder_new, FLAC_LIBS="-lFLAC $FLAC_LIBS $OGG_VORBIS_LIBS",using_flac=no, $FLAC_LIBS $OGG_VORBIS_LIBS)], using_flac=no)])
 
 
-
+dnl When enable_dl_amrbw, do not let add libraries to be linked in
+dnl since they will be dlopen()'ed instead.
+ac_sox_save_AMRWB_LIBS="$AMRWB_LIBS"
 AC_OPTIONAL_FORMAT(amrwb, AMRWB, 
 		   [AC_CHECK_HEADERS(opencore-amrwb/dec_if.h,
 		    [AC_CHECK_LIB(opencore-amrwb, D_IF_init, 
-		     AMRNB_LIBS="$AMRWB_LIBS -lopencore-amrwb", using_amrwb=no)],
+		     AMRWB_LIBS="$AMRWB_LIBS -lopencore-amrwb", using_amrwb=no)],
 		    [AC_CHECK_HEADERS(amrwb/dec.h, 
 		     [AC_CHECK_LIB(amrwb, D_IF_init, 
 		      AMRWB_LIBS="$AMRWB_LIBS -lamrwb",using_amrwb=no)], 
 		      using_amrwb=no)])])
+AC_ARG_ENABLE(dl_amrwb,
+	      AC_HELP_STRING([--enable-dl-amrwb], 
+			     [Dlopen amrbw instead of linking in.]),
+			     enable_dl_amrwb=$enableval, enable_dl_amrwb=no)
+if test "x$using_amrwb" = "xyes"; then
+  if test "x$using_libltdl" = "xyes" -a "x$enable_dl_amrwb" = "xyes"; then
+    AC_DEFINE(DL_AMRWB, 1, [Define to dlopen() amrwb.]) 
+    dnl When enable_dl_amrwb, do not let SOX_PATH_AMRWB add libraries
+    dnl to be linked in (since they will be dlopen()'ed instead).
+    AMRWB_LIBS="$ac_sox_save_AMRWB_LIBS"
+  fi
+fi
 
-
-
+dnl When enable_dl_amrnb, do not let add libraries to be linked in
+dnl since they will be dlopen()'ed instead.
+ac_sox_save_AMRNB_LIBS="$AMRNB_LIBS"
 AC_OPTIONAL_FORMAT(amrnb, AMRNB, 
 		   [AC_CHECK_HEADERS(opencore-amrnb/interf_dec.h, 
 		    [AC_CHECK_LIB(opencore-amrnb, Decoder_Interface_init, 
@@ -428,6 +443,18 @@
 		     [AC_CHECK_LIB(amrnb, Decoder_Interface_init, 
 		      AMRNB_LIBS="$AMRNB_LIBS -lamrnb", using_amrnb=no)], 
 		       using_amrnb=no)])])
+AC_ARG_ENABLE(dl_amrnb,
+	      AC_HELP_STRING([--enable-dl-amrnb], 
+			     [Dlopen amrnb instead of linking in.]),
+			     enable_dl_amrnb=$enableval, enable_dl_amrnb=no)
+if test "x$using_amrnb" = "xyes"; then
+  if test "x$using_libltdl" = "xyes" -a "x$enable_dl_amrnb" = "xyes"; then
+    AC_DEFINE(DL_AMRNB, 1, [Define to dlopen() amrnb.]) 
+    dnl When enable_dl_amrnb, do not let SOX_PATH_AMRNB add libraries
+    dnl to be linked in (since they will be dlopen()'ed instead).
+    AMRNB_LIBS="$ac_sox_save_AMRNB_LIBS"
+  fi
+fi
 
 
 AC_OPTIONAL_FORMAT(wavpack, WAVPACK, [AC_CHECK_HEADER(wavpack/wavpack.h, [AC_CHECK_LIB(wavpack, WavpackGetSampleRate, WAVPACK_LIBS="$WAVPACK_LIBS -lwavpack",using_wavpack=no)], using_wavpack=no)])
@@ -586,7 +613,13 @@
 echo
 echo "OPTIONAL FILE FORMATS"
 echo "amrnb......................$using_amrnb"
+if test "x$using_amrnb" = "xyes"; then
+echo " dlopen amrnb..............$enable_dl_amrnb"
+fi
 echo "amrwb......................$using_amrwb"
+if test "x$using_amrwb" = "xyes"; then
+echo " dlopen amrwb..............$enable_dl_amrwb"
+fi
 echo "ffmpeg.....................$using_ffmpeg"
 echo "flac.......................$using_flac"
 echo "gsm........................$using_gsm $gsm_option"
--- a/src/amr-nb.c
+++ b/src/amr-nb.c
@@ -22,29 +22,66 @@
 
 #include "sox_i.h"
 
+#ifdef HAVE_AMRNB
+
 #ifdef HAVE_OPENCORE_AMRNB_INTERF_DEC_H
-#include "opencore-amrnb/interf_dec.h"
-#else
-#include "amrnb/typedef.h"
-#include "amrnb/interf_dec.h"
-#include "amrnb/sp_dec.h"
-#endif
-#define Mode  _Mode
-#define MR102 _MR102
-#define MR122 _MR122
-#define MR475 _MR475
-#define MR515 _MR515
-#define MR59  _MR59
-#define MR67  _MR67
-#define MR74  _MR74
-#define MR795 _MR795
-#define MRDTX _MRDTX
-#ifdef HAVE_OPENCORE_AMRNB_INTERF_DEC_H
-#include "opencore-amrnb/interf_enc.h"
-#else
-#include "amrnb/interf_enc.h"
-#endif
 
+  enum Mode { amrnb_mode_dummy };
+
+  int Encoder_Interface_Encode(void* state, enum Mode mode, const short* speech, unsigned char* out, int forceSpeech);
+  void* Encoder_Interface_init(int dtx);
+  void Encoder_Interface_exit(void* state);
+  void Decoder_Interface_Decode(void* state, const unsigned char* in, short* out, int bfi);
+  void* Decoder_Interface_init(void);
+  void Decoder_Interface_exit(void* state);
+
+#define AMR_FUNC_ENTRIES(f,x) \
+  AMR_FUNC(f,x, int, Encoder_Interface_Encode, (void* state, enum Mode mode, const short* speech, unsigned char* out, int forceSpeech)) \
+  AMR_FUNC(f,x, void*, Encoder_Interface_init, (int dtx)) \
+  AMR_FUNC(f,x, void, Encoder_Interface_exit, (void* state)) \
+  AMR_FUNC(f,x, void, Decoder_Interface_Decode, (void* state, const unsigned char* in, short* out, int bfi)) \
+  AMR_FUNC(f,x, void*, Decoder_Interface_init, (void)) \
+  AMR_FUNC(f,x, void, Decoder_Interface_exit, (void* state))
+
+#define D_IF_decode         Decoder_Interface_Decode
+#define D_IF_exit           Decoder_Interface_exit
+#define D_IF_init           Decoder_Interface_init
+#define E_IF_encode         Encoder_Interface_Encode
+#define E_IF_exit           Encoder_Interface_exit
+#define E_IF_init()         Encoder_Interface_init(1)
+
+#else /* HAVE_OPENCORE_AMRNB_INTERF_DEC_H */
+
+enum amrnb_mode { amrnb_mode_dummy };
+
+int GP3VADxEncoder_Interface_Encode(void *st, enum amrnb_mode mode, short *speech, unsigned char *serial, int forceSpeech, char vad2_code);
+void *VADxEncoder_Interface_init(int dtx, char vad2_code);
+void Encoder_Interface_exit(void *state);
+void GP3Decoder_Interface_Decode(void *st, unsigned char *bits, short *synth, int bfi);
+void *Decoder_Interface_init(void);
+void Decoder_Interface_exit(void *state);
+
+#define AMR_FUNC_ENTRIES(f,x) \
+  AMR_FUNC(f,x, int, GP3VADxEncoder_Interface_Encode, (void *st, enum amrnb_mode mode, short *speech, unsigned char *serial, int forceSpeech, char vad2_code)) \
+  AMR_FUNC(f,x, void*, VADxEncoder_Interface_init, (int dtx, char vad2_code)) \
+  AMR_FUNC(f,x, void, Encoder_Interface_exit, (void *state)) \
+  AMR_FUNC(f,x, void, GP3Decoder_Interface_Decode, (void *st, unsigned char *bits, short *synth, int bfi)) \
+  AMR_FUNC(f,x, void*, Decoder_Interface_init, (void)) \
+  AMR_FUNC(f,x, void, Decoder_Interface_exit, (void *state))
+
+#define E_IF_encode(st,m,sp,ser,fs) \
+                            GP3VADxEncoder_Interface_Encode(st,m,sp,ser,fs,0)
+#define E_IF_init()         VADxEncoder_Interface_init(1,0)
+#define E_IF_exit           Encoder_Interface_exit
+#define D_IF_decode         GP3Decoder_Interface_Decode
+#define D_IF_init           Decoder_Interface_init
+#define D_IF_exit           Decoder_Interface_exit
+
+#endif /* HAVE_OPENCORE_AMRNB_INTERF_DEC_H */
+
+static const unsigned amrnb_block_size[] = {13,14,16,18,20,21,27,32,6,0,0,0,0,0,0,1};
+#define block_size amrnb_block_size
+
 static char const magic[] = "#!AMR\n";
 #define AMR_CODED_MAX       32                  /* max coded size */
 #define AMR_ENCODING        SOX_ENCODING_AMR_NB
@@ -53,11 +90,32 @@
 #define AMR_MODE_MAX        7
 #define AMR_NAMES           "amr-nb", "anb"
 #define AMR_RATE            8000
-#define D_IF_decode         Decoder_Interface_Decode
-#define D_IF_exit           Decoder_Interface_exit
-#define D_IF_init           Decoder_Interface_init
-#define E_IF_encode         Encoder_Interface_Encode
-#define E_IF_exit           Encoder_Interface_exit
-#define E_IF_init()         Encoder_Interface_init(1)
-static const unsigned block_size[] = {13,14,16,18,20,21,27,32,6,1,1,1,1,1,1,1};
+#define AMR_DESC            "amr-nb library"
+
+#if !defined(HAVE_LIBLTDL)
+#undef DL_AMRNB
+#endif
+
+static const char* const amr_library_names[] =
+{
+#ifdef DL_AMRNB
+#ifdef HAVE_OPENCORE_AMRNB_INTERF_DEC_H
+  "libopencore-amrnb",
+#else
+  "libamrnb-3",
+  "libamrnb",
+  "amrnb",
+#endif
+#endif
+  NULL
+};
+
+#ifdef DL_AMRNB
+  #define AMR_FUNC  LSX_DLENTRY_DYNAMIC
+#else
+  #define AMR_FUNC  LSX_DLENTRY_STATIC
+#endif /* DL_AMRNB */
+
 #include "amr.h"
+
+#endif /* HAVE_AMRNB */
--- a/src/amr-wb.c
+++ b/src/amr-wb.c
@@ -22,26 +22,80 @@
 
 #include "sox_i.h"
 
+#ifdef HAVE_AMRWB
+
 #ifdef HAVE_OPENCORE_AMRWB_DEC_IF_H
-#include "opencore-amrwb/dec_if.h"
-#include "opencore-amrwb/if_rom.h"
+
 #define DISABLE_AMR_WB_ENCODE
-#else
-#include "amrwb/typedef.h"
-#include "amrwb/enc_if.h"
-#include "amrwb/dec_if.h"
-#include "amrwb/if_rom.h"
-#endif
 
+  void D_IF_decode(void* state, const unsigned char* bits, short* synth, int bfi);
+  void* D_IF_init(void);
+  void D_IF_exit(void* state);
+
+#define AMR_FUNC_ENTRIES(f,x) \
+  AMR_FUNC(f,x, void,  D_IF_decode,(void* state, const unsigned char* bits, short* synth, int bfi)) \
+  AMR_FUNC(f,x, void*, D_IF_init,  (void)) \
+  AMR_FUNC(f,x, void,  D_IF_exit,  (void* state))
+
+#else /* HAVE_OPENCORE_AMRWB_DEC_IF_H */
+
+  int GP3E_IF_encode(void *st, int16_t mode, int16_t *speech, uint8_t *serial, int16_t dtx);
+  void *E_IF_init(void);
+  void E_IF_exit(void *state);
+  void GP3D_IF_decode(void *st, uint8_t *bits, int16_t *synth, int32_t bfi);
+  void * D_IF_init(void);
+  void D_IF_exit(void *state);
+
+#define AMR_FUNC_ENTRIES(f,x) \
+  AMR_FUNC(f,x, int,   GP3E_IF_encode,(void *st, int16_t mode, int16_t *speech, uint8_t *serial, int16_t dtx)) \
+  AMR_FUNC(f,x, void*, E_IF_init,     (void)) \
+  AMR_FUNC(f,x, void,  E_IF_exit,     (void *state)) \
+  AMR_FUNC(f,x, void,  GP3D_IF_decode,(void *st, uint8_t *bits, int16_t *synth, int32_t bfi)) \
+  AMR_FUNC(f,x, void*, D_IF_init,     (void)) \
+  AMR_FUNC(f,x, void,  D_IF_exit,     (void *state))
+
+#define D_IF_decode GP3D_IF_decode
+#define E_IF_encode GP3E_IF_encode
+
+#endif /* HAVE_OPENCORE_AMRWB_DEC_IF_H */
+
+static const uint8_t amrwb_block_size[16]= {18, 24, 33, 37, 41, 47, 51, 59, 61, 6, 6, 0, 0, 0, 1, 1};
+#define block_size amrwb_block_size
+
 static char const magic[] = "#!AMR-WB\n";
-#define AMR_CODED_MAX       61 /* max serial size */
+#define AMR_CODED_MAX       61 /* NB_SERIAL_MAX */
 #define AMR_ENCODING        SOX_ENCODING_AMR_WB
 #define AMR_FORMAT_FN       lsx_amr_wb_format_fn
-#define AMR_FRAME           320 /* Frame size at 16kHz */
+#define AMR_FRAME           320 /* L_FRAME16k */
 #define AMR_MODE_MAX        8
 #define AMR_NAMES           "amr-wb", "awb"
 #define AMR_RATE            16000
+#define AMR_DESC            "amr-wb library"
+
+#if !defined(HAVE_LIBLTDL)
+#undef DL_AMRWB
+#endif
+
+static const char* const amr_library_names[] =
+{
+#ifdef DL_AMRWB
 #ifdef HAVE_OPENCORE_AMRWB_DEC_IF_H
-static const unsigned block_size[16] = {18, 24, 33, 37, 41, 47, 51, 59, 61, 6, 6, 0, 0, 0, 1, 1};
+  "libopencore-amrwb",
+#else
+  "libamrwb-3",
+  "libamrwb",
+  "amrwb",
 #endif
+#endif
+  NULL
+};
+
+#ifdef DL_AMRWB
+  #define AMR_FUNC  LSX_DLENTRY_DYNAMIC
+#else
+  #define AMR_FUNC  LSX_DLENTRY_STATIC
+#endif /* DL_AMRWB */
+
 #include "amr.h"
+
+#endif /* HAVE_AMRWB */
--- a/src/amr.h
+++ b/src/amr.h
@@ -23,6 +23,7 @@
   unsigned mode;
   short pcm[AMR_FRAME];
   size_t pcm_index;
+  LSX_DLENTRIES_TO_PTRS(AMR_FUNC_ENTRIES, amr_dl);
 } priv_t;
 
 static size_t decode_1_frame(sox_format_t * ft)
@@ -36,7 +37,7 @@
   n_1 = block_size[(coded[0] >> 3) & 0x0F] - 1;
   if (lsx_readbuf(ft, &coded[1], n_1) != n_1)
     return AMR_FRAME;
-  D_IF_decode(p->state, coded, p->pcm, 0);
+  p->D_IF_decode(p->state, coded, p->pcm, 0);
   return 0;
 }
 
@@ -44,10 +45,8 @@
 {
   priv_t * p = (priv_t *)ft->priv;
   char buffer[sizeof(magic) - 1];
+  int open_library_result;
 
-  p->pcm_index = AMR_FRAME;
-  p->state = D_IF_init();
-
   if (lsx_readchars(ft, buffer, sizeof(buffer)))
     return SOX_EOF;
   if (memcmp(buffer, magic, sizeof(buffer))) {
@@ -54,6 +53,20 @@
     lsx_fail_errno(ft, SOX_EHDR, "invalid magic number");
     return SOX_EOF;
   }
+
+  LSX_DLLIBRARY_OPEN(
+      p,
+      amr_dl,
+      AMR_FUNC_ENTRIES,
+      AMR_DESC,
+      amr_library_names,
+      open_library_result);
+  if (open_library_result)
+    return SOX_EOF;
+
+  p->pcm_index = AMR_FRAME;
+  p->state = p->D_IF_init();
+
   ft->signal.rate = AMR_RATE;
   ft->encoding.encoding = AMR_ENCODING;
   ft->signal.channels = 1;
@@ -78,7 +91,8 @@
 static int stopread(sox_format_t * ft)
 {
   priv_t * p = (priv_t *)ft->priv;
-  D_IF_exit(p->state);
+  p->D_IF_exit(p->state);
+  LSX_DLLIBRARY_CLOSE(p, amr_dl);
   return SOX_SUCCESS;
 }
 
@@ -89,8 +103,10 @@
   return SOX_EOF;
 #else
   priv_t * p = (priv_t *)ft->priv;
+  int open_library_result;
+
   if (ft->encoding.compression != HUGE_VAL) {
-    p->mode = ft->encoding.compression;
+    p->mode = (unsigned)ft->encoding.compression;
     if (p->mode != ft->encoding.compression || p->mode > AMR_MODE_MAX) {
       lsx_fail_errno(ft, SOX_EINVAL, "compression level must be a whole number from 0 to %i", AMR_MODE_MAX);
       return SOX_EOF;
@@ -98,7 +114,20 @@
   }
   else p->mode = 0;
 
-#include "amr2.h"
+  LSX_DLLIBRARY_OPEN(
+      p,
+      amr_dl,
+      AMR_FUNC_ENTRIES,
+      AMR_DESC,
+      amr_library_names,
+      open_library_result);
+  if (open_library_result)
+    return SOX_EOF;
+
+#define IGNORE_WARNING \
+  p->state = p->E_IF_init();
+#include "ignore-warning.h"
+
   lsx_writes(ft, magic);
   p->pcm_index = 0;
   return SOX_SUCCESS;
@@ -110,7 +139,9 @@
 {
   priv_t * p = (priv_t *)ft->priv;
   uint8_t coded[AMR_CODED_MAX];
-#include "amr1.h"
+#define IGNORE_WARNING \
+  int n = p->E_IF_encode(p->state, p->mode, p->pcm, coded, 1);
+#include "ignore-warning.h"
   sox_bool result = lsx_writebuf(ft, coded, (size_t) (size_t) (unsigned)n) == (unsigned)n;
   if (!result)
     lsx_fail_errno(ft, errno, "write error");
@@ -154,7 +185,7 @@
     if (!encode_1_frame(ft))
       result = SOX_EOF;
   }
-  E_IF_exit(p->state);
+  p->E_IF_exit(p->state);
   return result;
 }
 #endif