Browse code

Add support for external OpenCORE libraries for AMR-NB/WB support.

Originally committed as revision 19117 to svn://svn.ffmpeg.org/ffmpeg/trunk

Diego Biurrun authored on 2009/06/05 21:32:40
Showing 7 changed files
... ...
@@ -22,6 +22,7 @@ version <next>:
22 22
 - remaining GPL parts in AC-3 decoder converted to LGPL
23 23
 - QCP demuxer
24 24
 - SoX native format muxer and demuxer
25
+- AMR-NB decoding/encoding, AMR-WB decoding via OpenCORE libraries
25 26
 
26 27
 
27 28
 
... ...
@@ -39,6 +39,11 @@ Some external libraries, e.g. libx264, are under GPL and can be used in
39 39
 conjunction with FFmpeg. They require --enable-gpl to be passed to configure
40 40
 as well.
41 41
 
42
+The OpenCORE external libraries are under the Apache License 2.0. That license
43
+is incompatible with the LGPL v2.1 and the GPL v2, but not with version 3 of
44
+those licenses. So to combine the OpenCORE libraries with FFmpeg, the license
45
+version needs to be upgraded by passing --enable-version3 to configure.
46
+
42 47
 The nonfree external libraries libamrnb, libamrwb and libfaac can be hooked up
43 48
 in FFmpeg. You need to pass --enable-nonfree to configure to enable them. Employ
44 49
 this option with care as FFmpeg then becomes nonfree and unredistributable.
... ...
@@ -152,6 +152,8 @@ show_help(){
152 152
   echo "  --enable-bzlib           enable bzlib [autodetect]"
153 153
   echo "  --enable-libamr-nb       enable libamr-nb floating point audio codec [no]"
154 154
   echo "  --enable-libamr-wb       enable libamr-wb floating point audio codec [no]"
155
+  echo "  --enable-libopencore-amrnb enable AMR-NB de/encoding via libopencore-amrnb [no]"
156
+  echo "  --enable-libopencore-amrwb enable AMR-WB decoding via libopencore-amrwb [no]"
155 157
   echo "  --enable-libdc1394       enable IIDC-1394 grabbing using libdc1394"
156 158
   echo "                           and libraw1394 [no]"
157 159
   echo "  --enable-libdirac        enable Dirac support via libdirac [no]"
... ...
@@ -792,6 +794,8 @@ CONFIG_LIST="
792 792
     libgsm
793 793
     libmp3lame
794 794
     libnut
795
+    libopencore_amrnb
796
+    libopencore_amrwb
795 797
     libopenjpeg
796 798
     libschroedinger
797 799
     libspeex
... ...
@@ -1099,6 +1103,9 @@ libgsm_encoder_deps="libgsm"
1099 1099
 libgsm_ms_decoder_deps="libgsm"
1100 1100
 libgsm_ms_encoder_deps="libgsm"
1101 1101
 libmp3lame_encoder_deps="libmp3lame"
1102
+libopencore_amrnb_decoder_deps="libopencore_amrnb"
1103
+libopencore_amrnb_encoder_deps="libopencore_amrnb"
1104
+libopencore_amrwb_decoder_deps="libopencore_amrwb"
1102 1105
 libopenjpeg_decoder_deps="libopenjpeg"
1103 1106
 libschroedinger_decoder_deps="libschroedinger"
1104 1107
 libschroedinger_encoder_deps="libschroedinger"
... ...
@@ -1761,6 +1768,9 @@ die_license_disabled nonfree libamr_nb
1761 1761
 die_license_disabled nonfree libamr_wb
1762 1762
 die_license_disabled nonfree libfaac
1763 1763
 
1764
+die_license_disabled version3 libopencore_amrnb
1765
+die_license_disabled version3 libopencore_amrwb
1766
+
1764 1767
 enabled version3 && { enabled gpl && enable gplv3 || enable lgplv3; }
1765 1768
 
1766 1769
 check_deps $ARCH_EXT_LIST
... ...
@@ -2065,6 +2075,8 @@ enabled libfaad    && require2 libfaad faad.h faacDecOpen -lfaad
2065 2065
 enabled libgsm     && require  libgsm gsm.h gsm_create -lgsm
2066 2066
 enabled libmp3lame && require  libmp3lame lame/lame.h lame_init -lmp3lame -lm
2067 2067
 enabled libnut     && require  libnut libnut.h nut_demuxer_init -lnut
2068
+enabled libopencore_amrnb  && require libopencore_amrnb opencore-amrnb/interf_dec.h Decoder_Interface_init -lopencore-amrnb -lm
2069
+enabled libopencore_amrwb  && require libopencore_amrwb opencore-amrwb/dec_if.h D_IF_init -lopencore-amrwb -lm
2068 2070
 enabled libopenjpeg && require libopenjpeg openjpeg.h opj_version -lopenjpeg
2069 2071
 enabled libschroedinger && add_cflags $(pkg-config --cflags schroedinger-1.0) &&
2070 2072
                            require libschroedinger schroedinger/schro.h schro_init $(pkg-config --libs schroedinger-1.0)
... ...
@@ -2373,6 +2385,8 @@ echo "libfaad dlopened          ${libfaadbin-no}"
2373 2373
 echo "libgsm enabled            ${libgsm-no}"
2374 2374
 echo "libmp3lame enabled        ${libmp3lame-no}"
2375 2375
 echo "libnut enabled            ${libnut-no}"
2376
+echo "libopencore-amrnb support ${libopencore_amrnb-no}"
2377
+echo "libopencore-amrwb support ${libopencore_amrwb-no}"
2376 2378
 echo "libopenjpeg enabled       ${libopenjpeg-no}"
2377 2379
 echo "libschroedinger enabled   ${libschroedinger-no}"
2378 2380
 echo "libspeex enabled          ${libspeex-no}"
... ...
@@ -18,7 +18,22 @@ explicitly requested by passing the appropriate flags to @file{./configure}.
18 18
 
19 19
 AMR comes in two different flavors, wideband and narrowband. FFmpeg can make
20 20
 use of the AMR wideband (floating-point mode) and the AMR narrowband
21
-(floating-point mode) reference decoders and encoders.
21
+(floating-point mode) reference decoders and encoders (libamr) as well as
22
+the OpenCORE libraries for AMR-NB decoding/encoding and AMR-WB decoding.
23
+
24
+@subsection OpenCORE
25
+
26
+Go to @url{http://gitorious.org/opencore-amr/} and follow the instructions for
27
+installing the libraries. Then pass @code{--enable-libopencore-amrnb} and/or
28
+@code{--enable-libopencore-amrwb} to configure to enable the libraries.
29
+
30
+Note that OpenCORE is under the Apache License 2.0 (see
31
+@url{http://www.apache.org/licenses/LICENSE-2.0} for details), which is
32
+incompatible with the LGPL version 2.1 and GPL version 2. You have to
33
+upgrade FFmpeg's license to LGPL version 3 (or if you have enabled
34
+GPL components, GPL version 3) to use it.
35
+
36
+@subsection libamr
22 37
 
23 38
 Go to @url{http://www.penguin.cz/~utx/amr} and follow the instructions for
24 39
 installing the libraries. Then pass @code{--enable-libamr-nb} and/or
... ...
@@ -519,9 +534,10 @@ following image formats are supported:
519 519
     @tab Used in Westwood Studios games like Command and Conquer.
520 520
 @item ADPCM Yamaha           @tab  X  @tab  X
521 521
 @item AMR-NB                 @tab  E  @tab  E
522
-    @tab supported through external library libamrnb
522
+    @tab supported through external libraries libamrnb and libopencore-amrnb
523 523
 @item AMR-WB                 @tab  E  @tab  E
524
-    @tab supported through external library libamrwb
524
+    @tab decoding supported through external libraries libamrwb and libopencore-amrwb,
525
+         encoding supported through external library libamrwb
525 526
 @item Apple lossless audio   @tab  X  @tab  X
526 527
     @tab QuickTime fourcc 'alac'
527 528
 @item Atrac 3                @tab     @tab  X
... ...
@@ -385,6 +385,8 @@ OBJS-$(CONFIG_LIBFAAC)                 += libfaac.o
385 385
 OBJS-$(CONFIG_LIBFAAD)                 += libfaad.o
386 386
 OBJS-$(CONFIG_LIBGSM)                  += libgsm.o
387 387
 OBJS-$(CONFIG_LIBMP3LAME)              += libmp3lame.o
388
+OBJS-$(CONFIG_LIBOPENCORE_AMRNB)       += libopencore-amr.o
389
+OBJS-$(CONFIG_LIBOPENCORE_AMRWB)       += libopencore-amr.o
388 390
 OBJS-$(CONFIG_LIBOPENJPEG)             += libopenjpeg.o
389 391
 OBJS-$(CONFIG_LIBSCHROEDINGER_DECODER) += libschroedingerdec.o libschroedinger.o libdirac_libschro.o
390 392
 OBJS-$(CONFIG_LIBSCHROEDINGER_ENCODER) += libschroedingerenc.o libschroedinger.o libdirac_libschro.o
... ...
@@ -309,6 +309,8 @@ void avcodec_register_all(void)
309 309
     REGISTER_ENCDEC  (LIBGSM, libgsm);
310 310
     REGISTER_ENCDEC  (LIBGSM_MS, libgsm_ms);
311 311
     REGISTER_ENCODER (LIBMP3LAME, libmp3lame);
312
+    REGISTER_ENCDEC  (LIBOPENCORE_AMRNB, libopencore_amrnb);
313
+    REGISTER_DECODER (LIBOPENCORE_AMRWB, libopencore_amrwb);
312 314
     REGISTER_DECODER (LIBOPENJPEG, libopenjpeg);
313 315
     REGISTER_ENCDEC  (LIBSCHROEDINGER, libschroedinger);
314 316
     REGISTER_DECODER (LIBSPEEX, libspeex);
315 317
new file mode 100644
... ...
@@ -0,0 +1,325 @@
0
+/*
1
+ * AMR Audio decoder stub
2
+ * Copyright (c) 2003 the ffmpeg project
3
+ *
4
+ * This file is part of FFmpeg.
5
+ *
6
+ * FFmpeg is free software; you can redistribute it and/or
7
+ * modify it under the terms of the GNU Lesser General Public
8
+ * License as published by the Free Software Foundation; either
9
+ * version 2.1 of the License, or (at your option) any later version.
10
+ *
11
+ * FFmpeg is distributed in the hope that it will be useful,
12
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14
+ * Lesser General Public License for more details.
15
+ *
16
+ * You should have received a copy of the GNU Lesser General Public
17
+ * License along with FFmpeg; if not, write to the Free Software
18
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19
+ */
20
+
21
+#include "avcodec.h"
22
+
23
+static void amr_decode_fix_avctx(AVCodecContext *avctx)
24
+{
25
+    const int is_amr_wb = 1 + (avctx->codec_id == CODEC_ID_AMR_WB);
26
+
27
+    if (!avctx->sample_rate)
28
+        avctx->sample_rate = 8000 * is_amr_wb;
29
+
30
+    if (!avctx->channels)
31
+        avctx->channels = 1;
32
+
33
+    avctx->frame_size = 160 * is_amr_wb;
34
+    avctx->sample_fmt = SAMPLE_FMT_S16;
35
+}
36
+
37
+#if CONFIG_LIBOPENCORE_AMRNB
38
+
39
+#include <opencore-amrnb/interf_dec.h>
40
+#include <opencore-amrnb/interf_enc.h>
41
+
42
+static const char nb_bitrate_unsupported[] =
43
+    "bitrate not supported: use one of 4.75k, 5.15k, 5.9k, 6.7k, 7.4k, 7.95k, 10.2k or 12.2k\n";
44
+
45
+/* Common code for fixed and float version*/
46
+typedef struct AMR_bitrates {
47
+    int       rate;
48
+    enum Mode mode;
49
+} AMR_bitrates;
50
+
51
+/* Match desired bitrate */
52
+static int getBitrateMode(int bitrate)
53
+{
54
+    /* make the correspondance between bitrate and mode */
55
+    AMR_bitrates rates[] = { { 4750, MR475},
56
+                             { 5150, MR515},
57
+                             { 5900, MR59},
58
+                             { 6700, MR67},
59
+                             { 7400, MR74},
60
+                             { 7950, MR795},
61
+                             {10200, MR102},
62
+                             {12200, MR122}, };
63
+    int i;
64
+
65
+    for (i = 0; i < 8; i++)
66
+        if (rates[i].rate == bitrate)
67
+            return rates[i].mode;
68
+    /* no bitrate matching, return an error */
69
+    return -1;
70
+}
71
+
72
+typedef struct AMRContext {
73
+    int   frameCount;
74
+    void *decState;
75
+    int  *enstate;
76
+    int   enc_bitrate;
77
+} AMRContext;
78
+
79
+static av_cold int amr_nb_decode_init(AVCodecContext *avctx)
80
+{
81
+    AMRContext *s = avctx->priv_data;
82
+
83
+    s->frameCount = 0;
84
+    s->decState   = Decoder_Interface_init();
85
+    if (!s->decState) {
86
+        av_log(avctx, AV_LOG_ERROR, "Decoder_Interface_init error\r\n");
87
+        return -1;
88
+    }
89
+
90
+    amr_decode_fix_avctx(avctx);
91
+
92
+    if (avctx->channels > 1) {
93
+        av_log(avctx, AV_LOG_ERROR, "amr_nb: multichannel decoding not supported\n");
94
+        return -1;
95
+    }
96
+
97
+    return 0;
98
+}
99
+
100
+static av_cold int amr_nb_decode_close(AVCodecContext *avctx)
101
+{
102
+    AMRContext *s = avctx->priv_data;
103
+
104
+    Decoder_Interface_exit(s->decState);
105
+    return 0;
106
+}
107
+
108
+static int amr_nb_decode_frame(AVCodecContext *avctx, void *data,
109
+                               int *data_size, AVPacket *avpkt)
110
+{
111
+    const uint8_t *buf = avpkt->data;
112
+    int buf_size       = avpkt->size;
113
+    AMRContext *s = avctx->priv_data;
114
+    const uint8_t *amrData = buf;
115
+    static const uint8_t block_size[16] = { 12, 13, 15, 17, 19, 20, 26, 31, 5, 0, 0, 0, 0, 0, 0, 0 };
116
+    enum Mode dec_mode;
117
+    int packet_size;
118
+
119
+    /* av_log(NULL, AV_LOG_DEBUG, "amr_decode_frame buf=%p buf_size=%d frameCount=%d!!\n",
120
+              buf, buf_size, s->frameCount); */
121
+
122
+    dec_mode = (buf[0] >> 3) & 0x000F;
123
+    packet_size = block_size[dec_mode] + 1;
124
+
125
+    if (packet_size > buf_size) {
126
+        av_log(avctx, AV_LOG_ERROR, "amr frame too short (%u, should be %u)\n",
127
+               buf_size, packet_size);
128
+        return -1;
129
+    }
130
+
131
+    s->frameCount++;
132
+    /* av_log(NULL, AV_LOG_DEBUG, "packet_size=%d amrData= 0x%X %X %X %X\n",
133
+              packet_size, amrData[0], amrData[1], amrData[2], amrData[3]); */
134
+    /* call decoder */
135
+    Decoder_Interface_Decode(s->decState, amrData, data, 0);
136
+    *data_size = 160 * 2;
137
+
138
+    return packet_size;
139
+}
140
+
141
+AVCodec libopencore_amrnb_decoder = {
142
+    "libopencore_amrnb",
143
+    CODEC_TYPE_AUDIO,
144
+    CODEC_ID_AMR_NB,
145
+    sizeof(AMRContext),
146
+    amr_nb_decode_init,
147
+    NULL,
148
+    amr_nb_decode_close,
149
+    amr_nb_decode_frame,
150
+    .long_name = NULL_IF_CONFIG_SMALL("OpenCORE Adaptive Multi-Rate (AMR) Narrow-Band"),
151
+};
152
+
153
+static av_cold int amr_nb_encode_init(AVCodecContext *avctx)
154
+{
155
+    AMRContext *s = avctx->priv_data;
156
+
157
+    s->frameCount = 0;
158
+
159
+    if (avctx->sample_rate != 8000) {
160
+        av_log(avctx, AV_LOG_ERROR, "Only 8000Hz sample rate supported\n");
161
+        return -1;
162
+    }
163
+
164
+    if (avctx->channels != 1) {
165
+        av_log(avctx, AV_LOG_ERROR, "Only mono supported\n");
166
+        return -1;
167
+    }
168
+
169
+    avctx->frame_size  = 160;
170
+    avctx->coded_frame = avcodec_alloc_frame();
171
+
172
+    s->enstate=Encoder_Interface_init(0);
173
+    if (!s->enstate) {
174
+        av_log(avctx, AV_LOG_ERROR, "Encoder_Interface_init error\n");
175
+        return -1;
176
+    }
177
+
178
+    if ((s->enc_bitrate = getBitrateMode(avctx->bit_rate)) < 0) {
179
+        av_log(avctx, AV_LOG_ERROR, nb_bitrate_unsupported);
180
+        return -1;
181
+    }
182
+
183
+    return 0;
184
+}
185
+
186
+static av_cold int amr_nb_encode_close(AVCodecContext *avctx)
187
+{
188
+    AMRContext *s = avctx->priv_data;
189
+
190
+    Encoder_Interface_exit(s->enstate);
191
+    av_freep(&avctx->coded_frame);
192
+    return 0;
193
+}
194
+
195
+static int amr_nb_encode_frame(AVCodecContext *avctx,
196
+                               unsigned char *frame/*out*/,
197
+                               int buf_size, void *data/*in*/)
198
+{
199
+    AMRContext *s = avctx->priv_data;
200
+    int written;
201
+
202
+    if ((s->enc_bitrate = getBitrateMode(avctx->bit_rate)) < 0) {
203
+        av_log(avctx, AV_LOG_ERROR, nb_bitrate_unsupported);
204
+        return -1;
205
+    }
206
+
207
+    written = Encoder_Interface_Encode(s->enstate, s->enc_bitrate, data,
208
+                                       frame, 0);
209
+    /* av_log(NULL, AV_LOG_DEBUG, "amr_nb_encode_frame encoded %u bytes, bitrate %u, first byte was %#02x\n",
210
+              written, s->enc_bitrate, frame[0] ); */
211
+
212
+    return written;
213
+}
214
+
215
+AVCodec libopencore_amrnb_encoder = {
216
+    "libopencore_amrnb",
217
+    CODEC_TYPE_AUDIO,
218
+    CODEC_ID_AMR_NB,
219
+    sizeof(AMRContext),
220
+    amr_nb_encode_init,
221
+    amr_nb_encode_frame,
222
+    amr_nb_encode_close,
223
+    NULL,
224
+    .sample_fmts = (enum SampleFormat[]){SAMPLE_FMT_S16,SAMPLE_FMT_NONE},
225
+    .long_name = NULL_IF_CONFIG_SMALL("OpenCORE Adaptive Multi-Rate (AMR) Narrow-Band"),
226
+};
227
+
228
+#endif
229
+
230
+/* -----------AMR wideband ------------*/
231
+#if CONFIG_LIBOPENCORE_AMRWB
232
+
233
+#ifdef _TYPEDEF_H
234
+//To avoid duplicate typedefs from typedef in amr-nb
235
+#define typedef_h
236
+#endif
237
+
238
+#include <opencore-amrwb/dec_if.h>
239
+#include <opencore-amrwb/if_rom.h>
240
+
241
+static const char wb_bitrate_unsupported[] =
242
+    "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";
243
+
244
+/* Common code for fixed and float version*/
245
+typedef struct AMRWB_bitrates {
246
+    int rate;
247
+    int mode;
248
+} AMRWB_bitrates;
249
+
250
+typedef struct AMRWBContext {
251
+    int    frameCount;
252
+    void  *state;
253
+    int    mode;
254
+    Word16 allow_dtx;
255
+} AMRWBContext;
256
+
257
+static av_cold int amr_wb_decode_init(AVCodecContext *avctx)
258
+{
259
+    AMRWBContext *s = avctx->priv_data;
260
+
261
+    s->frameCount = 0;
262
+    s->state      = D_IF_init();
263
+
264
+    amr_decode_fix_avctx(avctx);
265
+
266
+    if (avctx->channels > 1) {
267
+        av_log(avctx, AV_LOG_ERROR, "amr_wb: multichannel decoding not supported\n");
268
+        return -1;
269
+    }
270
+
271
+    return 0;
272
+}
273
+
274
+static int amr_wb_decode_frame(AVCodecContext *avctx, void *data,
275
+                               int *data_size, AVPacket *avpkt)
276
+{
277
+    const uint8_t *buf = avpkt->data;
278
+    int buf_size       = avpkt->size;
279
+    AMRWBContext *s = avctx->priv_data;
280
+    const uint8_t *amrData = buf;
281
+    int mode;
282
+    int packet_size;
283
+    static const uint8_t block_size[16] = {18, 24, 33, 37, 41, 47, 51, 59, 61, 6, 6, 0, 0, 0, 1, 1};
284
+
285
+    if (!buf_size)
286
+        /* nothing to do */
287
+        return 0;
288
+
289
+    mode = (amrData[0] >> 3) & 0x000F;
290
+    packet_size = block_size[mode];
291
+
292
+    if (packet_size > buf_size) {
293
+        av_log(avctx, AV_LOG_ERROR, "amr frame too short (%u, should be %u)\n",
294
+               buf_size, packet_size + 1);
295
+        return -1;
296
+    }
297
+
298
+    s->frameCount++;
299
+    D_IF_decode(s->state, amrData, data, _good_frame);
300
+    *data_size = 320 * 2;
301
+    return packet_size;
302
+}
303
+
304
+static int amr_wb_decode_close(AVCodecContext *avctx)
305
+{
306
+    AMRWBContext *s = avctx->priv_data;
307
+
308
+    D_IF_exit(s->state);
309
+    return 0;
310
+}
311
+
312
+AVCodec libopencore_amrwb_decoder = {
313
+    "libopencore_amrwb",
314
+    CODEC_TYPE_AUDIO,
315
+    CODEC_ID_AMR_WB,
316
+    sizeof(AMRWBContext),
317
+    amr_wb_decode_init,
318
+    NULL,
319
+    amr_wb_decode_close,
320
+    amr_wb_decode_frame,
321
+    .long_name = NULL_IF_CONFIG_SMALL("OpenCORE Adaptive Multi-Rate (AMR) Wide-Band"),
322
+};
323
+
324
+#endif /* CONFIG_LIBOPENCORE_AMRWB */