Add support for external OpenCORE libraries for AMR-NB/WB support.
authorDiego Biurrun <diego@biurrun.de>
Fri, 5 Jun 2009 12:32:40 +0000 (12:32 +0000)
committerDiego Biurrun <diego@biurrun.de>
Fri, 5 Jun 2009 12:32:40 +0000 (12:32 +0000)
Originally committed as revision 19117 to svn://svn.ffmpeg.org/ffmpeg/trunk

Changelog
LICENSE
configure
doc/general.texi
libavcodec/Makefile
libavcodec/allcodecs.c
libavcodec/libopencore-amr.c [new file with mode: 0644]

index 0d7152b3d0dbb26739b9d8854f146c1995f879d2..677c972f2487a52a206d4847e805ee45bce9be84 100644 (file)
--- a/Changelog
+++ b/Changelog
@@ -22,6 +22,7 @@ version <next>:
 - remaining GPL parts in AC-3 decoder converted to LGPL
 - QCP demuxer
 - SoX native format muxer and demuxer
 - remaining GPL parts in AC-3 decoder converted to LGPL
 - QCP demuxer
 - SoX native format muxer and demuxer
+- AMR-NB decoding/encoding, AMR-WB decoding via OpenCORE libraries
 
 
 
 
 
 
diff --git a/LICENSE b/LICENSE
index 58176589784ef3567ca6e58001a0fd8042e2d539..8dc2c8953dab3ae5fc4333353e89d696f50d1747 100644 (file)
--- a/LICENSE
+++ b/LICENSE
@@ -39,6 +39,11 @@ Some external libraries, e.g. libx264, are under GPL and can be used in
 conjunction with FFmpeg. They require --enable-gpl to be passed to configure
 as well.
 
 conjunction with FFmpeg. They require --enable-gpl to be passed to configure
 as well.
 
+The OpenCORE external libraries are under the Apache License 2.0. That license
+is incompatible with the LGPL v2.1 and the GPL v2, but not with version 3 of
+those licenses. So to combine the OpenCORE libraries with FFmpeg, the license
+version needs to be upgraded by passing --enable-version3 to configure.
+
 The nonfree external libraries libamrnb, libamrwb and libfaac can be hooked up
 in FFmpeg. You need to pass --enable-nonfree to configure to enable them. Employ
 this option with care as FFmpeg then becomes nonfree and unredistributable.
 The nonfree external libraries libamrnb, libamrwb and libfaac can be hooked up
 in FFmpeg. You need to pass --enable-nonfree to configure to enable them. Employ
 this option with care as FFmpeg then becomes nonfree and unredistributable.
index 58f36c2de170356a3a40a91149b8c5b8c25d3e61..03c046aa91130d8e225de702db4b143d1449fb36 100755 (executable)
--- a/configure
+++ b/configure
@@ -152,6 +152,8 @@ show_help(){
   echo "  --enable-bzlib           enable bzlib [autodetect]"
   echo "  --enable-libamr-nb       enable libamr-nb floating point audio codec [no]"
   echo "  --enable-libamr-wb       enable libamr-wb floating point audio codec [no]"
   echo "  --enable-bzlib           enable bzlib [autodetect]"
   echo "  --enable-libamr-nb       enable libamr-nb floating point audio codec [no]"
   echo "  --enable-libamr-wb       enable libamr-wb floating point audio codec [no]"
+  echo "  --enable-libopencore-amrnb enable AMR-NB de/encoding via libopencore-amrnb [no]"
+  echo "  --enable-libopencore-amrwb enable AMR-WB decoding via libopencore-amrwb [no]"
   echo "  --enable-libdc1394       enable IIDC-1394 grabbing using libdc1394"
   echo "                           and libraw1394 [no]"
   echo "  --enable-libdirac        enable Dirac support via libdirac [no]"
   echo "  --enable-libdc1394       enable IIDC-1394 grabbing using libdc1394"
   echo "                           and libraw1394 [no]"
   echo "  --enable-libdirac        enable Dirac support via libdirac [no]"
@@ -792,6 +794,8 @@ CONFIG_LIST="
     libgsm
     libmp3lame
     libnut
     libgsm
     libmp3lame
     libnut
+    libopencore_amrnb
+    libopencore_amrwb
     libopenjpeg
     libschroedinger
     libspeex
     libopenjpeg
     libschroedinger
     libspeex
@@ -1099,6 +1103,9 @@ libgsm_encoder_deps="libgsm"
 libgsm_ms_decoder_deps="libgsm"
 libgsm_ms_encoder_deps="libgsm"
 libmp3lame_encoder_deps="libmp3lame"
 libgsm_ms_decoder_deps="libgsm"
 libgsm_ms_encoder_deps="libgsm"
 libmp3lame_encoder_deps="libmp3lame"
+libopencore_amrnb_decoder_deps="libopencore_amrnb"
+libopencore_amrnb_encoder_deps="libopencore_amrnb"
+libopencore_amrwb_decoder_deps="libopencore_amrwb"
 libopenjpeg_decoder_deps="libopenjpeg"
 libschroedinger_decoder_deps="libschroedinger"
 libschroedinger_encoder_deps="libschroedinger"
 libopenjpeg_decoder_deps="libopenjpeg"
 libschroedinger_decoder_deps="libschroedinger"
 libschroedinger_encoder_deps="libschroedinger"
@@ -1761,6 +1768,9 @@ die_license_disabled nonfree libamr_nb
 die_license_disabled nonfree libamr_wb
 die_license_disabled nonfree libfaac
 
 die_license_disabled nonfree libamr_wb
 die_license_disabled nonfree libfaac
 
+die_license_disabled version3 libopencore_amrnb
+die_license_disabled version3 libopencore_amrwb
+
 enabled version3 && { enabled gpl && enable gplv3 || enable lgplv3; }
 
 check_deps $ARCH_EXT_LIST
 enabled version3 && { enabled gpl && enable gplv3 || enable lgplv3; }
 
 check_deps $ARCH_EXT_LIST
@@ -2065,6 +2075,8 @@ enabled libfaad    && require2 libfaad faad.h faacDecOpen -lfaad
 enabled libgsm     && require  libgsm gsm.h gsm_create -lgsm
 enabled libmp3lame && require  libmp3lame lame/lame.h lame_init -lmp3lame -lm
 enabled libnut     && require  libnut libnut.h nut_demuxer_init -lnut
 enabled libgsm     && require  libgsm gsm.h gsm_create -lgsm
 enabled libmp3lame && require  libmp3lame lame/lame.h lame_init -lmp3lame -lm
 enabled libnut     && require  libnut libnut.h nut_demuxer_init -lnut
+enabled libopencore_amrnb  && require libopencore_amrnb opencore-amrnb/interf_dec.h Decoder_Interface_init -lopencore-amrnb -lm
+enabled libopencore_amrwb  && require libopencore_amrwb opencore-amrwb/dec_if.h D_IF_init -lopencore-amrwb -lm
 enabled libopenjpeg && require libopenjpeg openjpeg.h opj_version -lopenjpeg
 enabled libschroedinger && add_cflags $(pkg-config --cflags schroedinger-1.0) &&
                            require libschroedinger schroedinger/schro.h schro_init $(pkg-config --libs schroedinger-1.0)
 enabled libopenjpeg && require libopenjpeg openjpeg.h opj_version -lopenjpeg
 enabled libschroedinger && add_cflags $(pkg-config --cflags schroedinger-1.0) &&
                            require libschroedinger schroedinger/schro.h schro_init $(pkg-config --libs schroedinger-1.0)
@@ -2373,6 +2385,8 @@ echo "libfaad dlopened          ${libfaadbin-no}"
 echo "libgsm enabled            ${libgsm-no}"
 echo "libmp3lame enabled        ${libmp3lame-no}"
 echo "libnut enabled            ${libnut-no}"
 echo "libgsm enabled            ${libgsm-no}"
 echo "libmp3lame enabled        ${libmp3lame-no}"
 echo "libnut enabled            ${libnut-no}"
+echo "libopencore-amrnb support ${libopencore_amrnb-no}"
+echo "libopencore-amrwb support ${libopencore_amrwb-no}"
 echo "libopenjpeg enabled       ${libopenjpeg-no}"
 echo "libschroedinger enabled   ${libschroedinger-no}"
 echo "libspeex enabled          ${libspeex-no}"
 echo "libopenjpeg enabled       ${libopenjpeg-no}"
 echo "libschroedinger enabled   ${libschroedinger-no}"
 echo "libspeex enabled          ${libspeex-no}"
index 63c3b1938e9c1f4622eab43e78520116b0083cc0..3e95e2417ea8198820490cd61dd097e3a1928f3f 100644 (file)
@@ -18,7 +18,22 @@ explicitly requested by passing the appropriate flags to @file{./configure}.
 
 AMR comes in two different flavors, wideband and narrowband. FFmpeg can make
 use of the AMR wideband (floating-point mode) and the AMR narrowband
 
 AMR comes in two different flavors, wideband and narrowband. FFmpeg can make
 use of the AMR wideband (floating-point mode) and the AMR narrowband
-(floating-point mode) reference decoders and encoders.
+(floating-point mode) reference decoders and encoders (libamr) as well as
+the OpenCORE libraries for AMR-NB decoding/encoding and AMR-WB decoding.
+
+@subsection OpenCORE
+
+Go to @url{http://gitorious.org/opencore-amr/} and follow the instructions for
+installing the libraries. Then pass @code{--enable-libopencore-amrnb} and/or
+@code{--enable-libopencore-amrwb} to configure to enable the libraries.
+
+Note that OpenCORE is under the Apache License 2.0 (see
+@url{http://www.apache.org/licenses/LICENSE-2.0} for details), which is
+incompatible with the LGPL version 2.1 and GPL version 2. You have to
+upgrade FFmpeg's license to LGPL version 3 (or if you have enabled
+GPL components, GPL version 3) to use it.
+
+@subsection libamr
 
 Go to @url{http://www.penguin.cz/~utx/amr} and follow the instructions for
 installing the libraries. Then pass @code{--enable-libamr-nb} and/or
 
 Go to @url{http://www.penguin.cz/~utx/amr} and follow the instructions for
 installing the libraries. Then pass @code{--enable-libamr-nb} and/or
@@ -519,9 +534,10 @@ following image formats are supported:
     @tab Used in Westwood Studios games like Command and Conquer.
 @item ADPCM Yamaha           @tab  X  @tab  X
 @item AMR-NB                 @tab  E  @tab  E
     @tab Used in Westwood Studios games like Command and Conquer.
 @item ADPCM Yamaha           @tab  X  @tab  X
 @item AMR-NB                 @tab  E  @tab  E
-    @tab supported through external library libamrnb
+    @tab supported through external libraries libamrnb and libopencore-amrnb
 @item AMR-WB                 @tab  E  @tab  E
 @item AMR-WB                 @tab  E  @tab  E
-    @tab supported through external library libamrwb
+    @tab decoding supported through external libraries libamrwb and libopencore-amrwb,
+         encoding supported through external library libamrwb
 @item Apple lossless audio   @tab  X  @tab  X
     @tab QuickTime fourcc 'alac'
 @item Atrac 3                @tab     @tab  X
 @item Apple lossless audio   @tab  X  @tab  X
     @tab QuickTime fourcc 'alac'
 @item Atrac 3                @tab     @tab  X
index cb9e4c4a1e76326b0872a959d7b4d72acec2f080..adac5ae3551a08bde4a90c3eb895cf478665b1f1 100644 (file)
@@ -385,6 +385,8 @@ OBJS-$(CONFIG_LIBFAAC)                 += libfaac.o
 OBJS-$(CONFIG_LIBFAAD)                 += libfaad.o
 OBJS-$(CONFIG_LIBGSM)                  += libgsm.o
 OBJS-$(CONFIG_LIBMP3LAME)              += libmp3lame.o
 OBJS-$(CONFIG_LIBFAAD)                 += libfaad.o
 OBJS-$(CONFIG_LIBGSM)                  += libgsm.o
 OBJS-$(CONFIG_LIBMP3LAME)              += libmp3lame.o
+OBJS-$(CONFIG_LIBOPENCORE_AMRNB)       += libopencore-amr.o
+OBJS-$(CONFIG_LIBOPENCORE_AMRWB)       += libopencore-amr.o
 OBJS-$(CONFIG_LIBOPENJPEG)             += libopenjpeg.o
 OBJS-$(CONFIG_LIBSCHROEDINGER_DECODER) += libschroedingerdec.o libschroedinger.o libdirac_libschro.o
 OBJS-$(CONFIG_LIBSCHROEDINGER_ENCODER) += libschroedingerenc.o libschroedinger.o libdirac_libschro.o
 OBJS-$(CONFIG_LIBOPENJPEG)             += libopenjpeg.o
 OBJS-$(CONFIG_LIBSCHROEDINGER_DECODER) += libschroedingerdec.o libschroedinger.o libdirac_libschro.o
 OBJS-$(CONFIG_LIBSCHROEDINGER_ENCODER) += libschroedingerenc.o libschroedinger.o libdirac_libschro.o
index 7e54d0797cc0db5681deae7188d368413eb93487..7e9405535225efb7482d8e16d56dd43cd829308e 100644 (file)
@@ -309,6 +309,8 @@ void avcodec_register_all(void)
     REGISTER_ENCDEC  (LIBGSM, libgsm);
     REGISTER_ENCDEC  (LIBGSM_MS, libgsm_ms);
     REGISTER_ENCODER (LIBMP3LAME, libmp3lame);
     REGISTER_ENCDEC  (LIBGSM, libgsm);
     REGISTER_ENCDEC  (LIBGSM_MS, libgsm_ms);
     REGISTER_ENCODER (LIBMP3LAME, libmp3lame);
+    REGISTER_ENCDEC  (LIBOPENCORE_AMRNB, libopencore_amrnb);
+    REGISTER_DECODER (LIBOPENCORE_AMRWB, libopencore_amrwb);
     REGISTER_DECODER (LIBOPENJPEG, libopenjpeg);
     REGISTER_ENCDEC  (LIBSCHROEDINGER, libschroedinger);
     REGISTER_DECODER (LIBSPEEX, libspeex);
     REGISTER_DECODER (LIBOPENJPEG, libopenjpeg);
     REGISTER_ENCDEC  (LIBSCHROEDINGER, libschroedinger);
     REGISTER_DECODER (LIBSPEEX, libspeex);
diff --git a/libavcodec/libopencore-amr.c b/libavcodec/libopencore-amr.c
new file mode 100644 (file)
index 0000000..1544db7
--- /dev/null
@@ -0,0 +1,325 @@
+/*
+ * AMR Audio decoder stub
+ * Copyright (c) 2003 the ffmpeg project
+ *
+ * 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
+ */
+
+#include "avcodec.h"
+
+static void amr_decode_fix_avctx(AVCodecContext *avctx)
+{
+    const int is_amr_wb = 1 + (avctx->codec_id == CODEC_ID_AMR_WB);
+
+    if (!avctx->sample_rate)
+        avctx->sample_rate = 8000 * is_amr_wb;
+
+    if (!avctx->channels)
+        avctx->channels = 1;
+
+    avctx->frame_size = 160 * is_amr_wb;
+    avctx->sample_fmt = SAMPLE_FMT_S16;
+}
+
+#if CONFIG_LIBOPENCORE_AMRNB
+
+#include <opencore-amrnb/interf_dec.h>
+#include <opencore-amrnb/interf_enc.h>
+
+static const char nb_bitrate_unsupported[] =
+    "bitrate not supported: use one of 4.75k, 5.15k, 5.9k, 6.7k, 7.4k, 7.95k, 10.2k or 12.2k\n";
+
+/* Common code for fixed and float version*/
+typedef struct AMR_bitrates {
+    int       rate;
+    enum Mode mode;
+} AMR_bitrates;
+
+/* Match desired bitrate */
+static int getBitrateMode(int bitrate)
+{
+    /* make the correspondance between bitrate and mode */
+    AMR_bitrates rates[] = { { 4750, MR475},
+                             { 5150, MR515},
+                             { 5900, MR59},
+                             { 6700, MR67},
+                             { 7400, MR74},
+                             { 7950, MR795},
+                             {10200, MR102},
+                             {12200, MR122}, };
+    int i;
+
+    for (i = 0; i < 8; i++)
+        if (rates[i].rate == bitrate)
+            return rates[i].mode;
+    /* no bitrate matching, return an error */
+    return -1;
+}
+
+typedef struct AMRContext {
+    int   frameCount;
+    void *decState;
+    int  *enstate;
+    int   enc_bitrate;
+} AMRContext;
+
+static av_cold int amr_nb_decode_init(AVCodecContext *avctx)
+{
+    AMRContext *s = avctx->priv_data;
+
+    s->frameCount = 0;
+    s->decState   = Decoder_Interface_init();
+    if (!s->decState) {
+        av_log(avctx, AV_LOG_ERROR, "Decoder_Interface_init error\r\n");
+        return -1;
+    }
+
+    amr_decode_fix_avctx(avctx);
+
+    if (avctx->channels > 1) {
+        av_log(avctx, AV_LOG_ERROR, "amr_nb: multichannel decoding not supported\n");
+        return -1;
+    }
+
+    return 0;
+}
+
+static av_cold int amr_nb_decode_close(AVCodecContext *avctx)
+{
+    AMRContext *s = avctx->priv_data;
+
+    Decoder_Interface_exit(s->decState);
+    return 0;
+}
+
+static int amr_nb_decode_frame(AVCodecContext *avctx, void *data,
+                               int *data_size, AVPacket *avpkt)
+{
+    const uint8_t *buf = avpkt->data;
+    int buf_size       = avpkt->size;
+    AMRContext *s = avctx->priv_data;
+    const uint8_t *amrData = buf;
+    static const uint8_t block_size[16] = { 12, 13, 15, 17, 19, 20, 26, 31, 5, 0, 0, 0, 0, 0, 0, 0 };
+    enum Mode dec_mode;
+    int packet_size;
+
+    /* av_log(NULL, AV_LOG_DEBUG, "amr_decode_frame buf=%p buf_size=%d frameCount=%d!!\n",
+              buf, buf_size, s->frameCount); */
+
+    dec_mode = (buf[0] >> 3) & 0x000F;
+    packet_size = block_size[dec_mode] + 1;
+
+    if (packet_size > buf_size) {
+        av_log(avctx, AV_LOG_ERROR, "amr frame too short (%u, should be %u)\n",
+               buf_size, packet_size);
+        return -1;
+    }
+
+    s->frameCount++;
+    /* av_log(NULL, AV_LOG_DEBUG, "packet_size=%d amrData= 0x%X %X %X %X\n",
+              packet_size, amrData[0], amrData[1], amrData[2], amrData[3]); */
+    /* call decoder */
+    Decoder_Interface_Decode(s->decState, amrData, data, 0);
+    *data_size = 160 * 2;
+
+    return packet_size;
+}
+
+AVCodec libopencore_amrnb_decoder = {
+    "libopencore_amrnb",
+    CODEC_TYPE_AUDIO,
+    CODEC_ID_AMR_NB,
+    sizeof(AMRContext),
+    amr_nb_decode_init,
+    NULL,
+    amr_nb_decode_close,
+    amr_nb_decode_frame,
+    .long_name = NULL_IF_CONFIG_SMALL("OpenCORE Adaptive Multi-Rate (AMR) Narrow-Band"),
+};
+
+static av_cold int amr_nb_encode_init(AVCodecContext *avctx)
+{
+    AMRContext *s = avctx->priv_data;
+
+    s->frameCount = 0;
+
+    if (avctx->sample_rate != 8000) {
+        av_log(avctx, AV_LOG_ERROR, "Only 8000Hz sample rate supported\n");
+        return -1;
+    }
+
+    if (avctx->channels != 1) {
+        av_log(avctx, AV_LOG_ERROR, "Only mono supported\n");
+        return -1;
+    }
+
+    avctx->frame_size  = 160;
+    avctx->coded_frame = avcodec_alloc_frame();
+
+    s->enstate=Encoder_Interface_init(0);
+    if (!s->enstate) {
+        av_log(avctx, AV_LOG_ERROR, "Encoder_Interface_init error\n");
+        return -1;
+    }
+
+    if ((s->enc_bitrate = getBitrateMode(avctx->bit_rate)) < 0) {
+        av_log(avctx, AV_LOG_ERROR, nb_bitrate_unsupported);
+        return -1;
+    }
+
+    return 0;
+}
+
+static av_cold int amr_nb_encode_close(AVCodecContext *avctx)
+{
+    AMRContext *s = avctx->priv_data;
+
+    Encoder_Interface_exit(s->enstate);
+    av_freep(&avctx->coded_frame);
+    return 0;
+}
+
+static int amr_nb_encode_frame(AVCodecContext *avctx,
+                               unsigned char *frame/*out*/,
+                               int buf_size, void *data/*in*/)
+{
+    AMRContext *s = avctx->priv_data;
+    int written;
+
+    if ((s->enc_bitrate = getBitrateMode(avctx->bit_rate)) < 0) {
+        av_log(avctx, AV_LOG_ERROR, nb_bitrate_unsupported);
+        return -1;
+    }
+
+    written = Encoder_Interface_Encode(s->enstate, s->enc_bitrate, data,
+                                       frame, 0);
+    /* av_log(NULL, AV_LOG_DEBUG, "amr_nb_encode_frame encoded %u bytes, bitrate %u, first byte was %#02x\n",
+              written, s->enc_bitrate, frame[0] ); */
+
+    return written;
+}
+
+AVCodec libopencore_amrnb_encoder = {
+    "libopencore_amrnb",
+    CODEC_TYPE_AUDIO,
+    CODEC_ID_AMR_NB,
+    sizeof(AMRContext),
+    amr_nb_encode_init,
+    amr_nb_encode_frame,
+    amr_nb_encode_close,
+    NULL,
+    .sample_fmts = (enum SampleFormat[]){SAMPLE_FMT_S16,SAMPLE_FMT_NONE},
+    .long_name = NULL_IF_CONFIG_SMALL("OpenCORE Adaptive Multi-Rate (AMR) Narrow-Band"),
+};
+
+#endif
+
+/* -----------AMR wideband ------------*/
+#if CONFIG_LIBOPENCORE_AMRWB
+
+#ifdef _TYPEDEF_H
+//To avoid duplicate typedefs from typedef in amr-nb
+#define typedef_h
+#endif
+
+#include <opencore-amrwb/dec_if.h>
+#include <opencore-amrwb/if_rom.h>
+
+static const char wb_bitrate_unsupported[] =
+    "bitrate not supported: use one of 6.6k, 8.85k, 12.65k, 14.25k, 15.85k, 18.25k, 19.85k, 23.05k, or 23.85k\n";
+
+/* Common code for fixed and float version*/
+typedef struct AMRWB_bitrates {
+    int rate;
+    int mode;
+} AMRWB_bitrates;
+
+typedef struct AMRWBContext {
+    int    frameCount;
+    void  *state;
+    int    mode;
+    Word16 allow_dtx;
+} AMRWBContext;
+
+static av_cold int amr_wb_decode_init(AVCodecContext *avctx)
+{
+    AMRWBContext *s = avctx->priv_data;
+
+    s->frameCount = 0;
+    s->state      = D_IF_init();
+
+    amr_decode_fix_avctx(avctx);
+
+    if (avctx->channels > 1) {
+        av_log(avctx, AV_LOG_ERROR, "amr_wb: multichannel decoding not supported\n");
+        return -1;
+    }
+
+    return 0;
+}
+
+static int amr_wb_decode_frame(AVCodecContext *avctx, void *data,
+                               int *data_size, AVPacket *avpkt)
+{
+    const uint8_t *buf = avpkt->data;
+    int buf_size       = avpkt->size;
+    AMRWBContext *s = avctx->priv_data;
+    const uint8_t *amrData = buf;
+    int mode;
+    int packet_size;
+    static const uint8_t block_size[16] = {18, 24, 33, 37, 41, 47, 51, 59, 61, 6, 6, 0, 0, 0, 1, 1};
+
+    if (!buf_size)
+        /* nothing to do */
+        return 0;
+
+    mode = (amrData[0] >> 3) & 0x000F;
+    packet_size = block_size[mode];
+
+    if (packet_size > buf_size) {
+        av_log(avctx, AV_LOG_ERROR, "amr frame too short (%u, should be %u)\n",
+               buf_size, packet_size + 1);
+        return -1;
+    }
+
+    s->frameCount++;
+    D_IF_decode(s->state, amrData, data, _good_frame);
+    *data_size = 320 * 2;
+    return packet_size;
+}
+
+static int amr_wb_decode_close(AVCodecContext *avctx)
+{
+    AMRWBContext *s = avctx->priv_data;
+
+    D_IF_exit(s->state);
+    return 0;
+}
+
+AVCodec libopencore_amrwb_decoder = {
+    "libopencore_amrwb",
+    CODEC_TYPE_AUDIO,
+    CODEC_ID_AMR_WB,
+    sizeof(AMRWBContext),
+    amr_wb_decode_init,
+    NULL,
+    amr_wb_decode_close,
+    amr_wb_decode_frame,
+    .long_name = NULL_IF_CONFIG_SMALL("OpenCORE Adaptive Multi-Rate (AMR) Wide-Band"),
+};
+
+#endif /* CONFIG_LIBOPENCORE_AMRWB */