libamr.c 12.2 KB
Newer Older
1 2 3 4
/*
 * AMR Audio decoder stub
 * Copyright (c) 2003 the ffmpeg project
 *
5 6 7
 * This file is part of FFmpeg.
 *
 * FFmpeg is free software; you can redistribute it and/or
8 9
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
10
 * version 2.1 of the License, or (at your option) any later version.
11
 *
12
 * FFmpeg is distributed in the hope that it will be useful,
13 14 15 16 17
 * 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
18
 * License along with FFmpeg; if not, write to the Free Software
19
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20
 */
21

22 23 24 25 26 27 28
 /** @file
 * Adaptive Multi-Rate (AMR) Audio decoder stub.
 *
 * This code implements both an AMR-NarrowBand (AMR-NB) and an AMR-WideBand
 * (AMR-WB) audio encoder/decoder through external reference code from
 * http://www.3gpp.org/. The license of the code from 3gpp is unclear so you
 * have to download the code separately. Two versions exists: One fixed-point
29 30 31 32
 * and one floating-point. For some reason the float encoder is significantly
 * faster at least on a P4 1.5GHz (0.9s instead of 9.9s on a 30s audio clip
 * at MR102). Both float and fixed point are supported for AMR-NB, but only
 * float for AMR-WB.
33 34 35 36 37
 *
 * \section AMR-NB
 *
 * \subsection Float
 * The float version (default) can be downloaded from:
38
 * http://www.3gpp.org/ftp/Specs/archive/26_series/26.104/26104-610.zip
39 40 41 42 43 44 45
 *
 * \subsection Specification
 * The specification for AMR-NB can be found in TS 26.071
 * (http://www.3gpp.org/ftp/Specs/html-info/26071.htm) and some other
 * info at http://www.3gpp.org/ftp/Specs/html-info/26-series.htm.
 *
 * \section AMR-WB
46
 *
47 48
 * \subsection Float
 * The reference code can be downloaded from:
49
 * http://www.3gpp.org/ftp/Specs/archive/26_series/26.204/26204-600.zip
50 51
 *
 * \subsection Specification
52 53 54
 * The specification for AMR-WB can be found in TS 26.171
 * (http://www.3gpp.org/ftp/Specs/html-info/26171.htm) and some other
 * info at http://www.3gpp.org/ftp/Specs/html-info/26-series.htm.
55
 *
Zdenek Kabelac's avatar
Zdenek Kabelac committed
56
 */
57

58 59
#include "avcodec.h"

60 61
#include <amrnb/interf_dec.h>
#include <amrnb/interf_enc.h>
Zdenek Kabelac's avatar
Zdenek Kabelac committed
62

63
static const char nb_bitrate_unsupported[] =
64
    "bitrate not supported: use one of 4.75k, 5.15k, 5.9k, 6.7k, 7.4k, 7.95k, 10.2k or 12.2k\n";
65
static const char wb_bitrate_unsupported[] =
66 67
    "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";

Zdenek Kabelac's avatar
Zdenek Kabelac committed
68 69 70
/* Common code for fixed and float version*/
typedef struct AMR_bitrates
{
Benoit Fouet's avatar
Benoit Fouet committed
71
    int rate;
Zdenek Kabelac's avatar
Zdenek Kabelac committed
72 73 74
    enum Mode mode;
} AMR_bitrates;

Benoit Fouet's avatar
Benoit Fouet committed
75 76
/* Match desired bitrate */
static int getBitrateMode(int bitrate)
Zdenek Kabelac's avatar
Zdenek Kabelac committed
77
{
Benoit Fouet's avatar
Benoit Fouet committed
78 79 80 81 82 83 84 85 86
    /* 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},
Zdenek Kabelac's avatar
Zdenek Kabelac committed
87 88
                         };
    int i;
Benoit Fouet's avatar
Benoit Fouet committed
89

90
    for(i=0;i<8;i++)
Zdenek Kabelac's avatar
Zdenek Kabelac committed
91
    {
Benoit Fouet's avatar
Benoit Fouet committed
92
        if(rates[i].rate==bitrate)
Zdenek Kabelac's avatar
Zdenek Kabelac committed
93
        {
94
            return rates[i].mode;
Zdenek Kabelac's avatar
Zdenek Kabelac committed
95 96
        }
    }
Benoit Fouet's avatar
Benoit Fouet committed
97 98
    /* no bitrate matching, return an error */
    return -1;
Zdenek Kabelac's avatar
Zdenek Kabelac committed
99 100
}

Andrew Voznytsa's avatar
Andrew Voznytsa committed
101 102 103 104 105 106 107 108 109 110 111 112 113 114 115
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 == 0)
    {
        avctx->sample_rate = 8000 * is_amr_wb;
    }

    if(avctx->channels == 0)
    {
        avctx->channels = 1;
    }

    avctx->frame_size = 160 * is_amr_wb;
116
    avctx->sample_fmt = SAMPLE_FMT_S16;
Andrew Voznytsa's avatar
Andrew Voznytsa committed
117 118
}

119
#if CONFIG_LIBAMR_NB
Zdenek Kabelac's avatar
Zdenek Kabelac committed
120 121 122 123 124

typedef struct AMRContext {
    int frameCount;
    void * decState;
    int *enstate;
Benoit Fouet's avatar
Benoit Fouet committed
125
    int enc_bitrate;
Zdenek Kabelac's avatar
Zdenek Kabelac committed
126 127
} AMRContext;

128
static av_cold int amr_nb_decode_init(AVCodecContext * avctx)
Zdenek Kabelac's avatar
Zdenek Kabelac committed
129 130
{
    AMRContext *s = avctx->priv_data;
Benoit Fouet's avatar
Benoit Fouet committed
131

Zdenek Kabelac's avatar
Zdenek Kabelac committed
132 133 134 135
    s->frameCount=0;
    s->decState=Decoder_Interface_init();
    if(!s->decState)
    {
Michael Niedermayer's avatar
Michael Niedermayer committed
136
        av_log(avctx, AV_LOG_ERROR, "Decoder_Interface_init error\r\n");
Zdenek Kabelac's avatar
Zdenek Kabelac committed
137 138
        return -1;
    }
Andrew Voznytsa's avatar
Andrew Voznytsa committed
139 140 141 142 143 144 145 146 147

    amr_decode_fix_avctx(avctx);

    if(avctx->channels > 1)
    {
        av_log(avctx, AV_LOG_ERROR, "amr_nb: multichannel decoding not supported\n");
        return -1;
    }

Zdenek Kabelac's avatar
Zdenek Kabelac committed
148 149 150
    return 0;
}

151
static av_cold int amr_nb_encode_init(AVCodecContext * avctx)
Zdenek Kabelac's avatar
Zdenek Kabelac committed
152 153
{
    AMRContext *s = avctx->priv_data;
Benoit Fouet's avatar
Benoit Fouet committed
154

Zdenek Kabelac's avatar
Zdenek Kabelac committed
155
    s->frameCount=0;
156

Zdenek Kabelac's avatar
Zdenek Kabelac committed
157 158
    if(avctx->sample_rate!=8000)
    {
159
        av_log(avctx, AV_LOG_ERROR, "Only 8000Hz sample rate supported\n");
Zdenek Kabelac's avatar
Zdenek Kabelac committed
160 161 162 163 164
        return -1;
    }

    if(avctx->channels!=1)
    {
165
        av_log(avctx, AV_LOG_ERROR, "Only mono supported\n");
Zdenek Kabelac's avatar
Zdenek Kabelac committed
166 167 168 169 170 171 172 173 174
        return -1;
    }

    avctx->frame_size=160;
    avctx->coded_frame= avcodec_alloc_frame();

    s->enstate=Encoder_Interface_init(0);
    if(!s->enstate)
    {
175
        av_log(avctx, AV_LOG_ERROR, "Encoder_Interface_init error\n");
Zdenek Kabelac's avatar
Zdenek Kabelac committed
176 177 178
        return -1;
    }

Benoit Fouet's avatar
Benoit Fouet committed
179 180
    if((s->enc_bitrate=getBitrateMode(avctx->bit_rate))<0)
    {
181
        av_log(avctx, AV_LOG_ERROR, nb_bitrate_unsupported);
Benoit Fouet's avatar
Benoit Fouet committed
182 183
        return -1;
    }
Zdenek Kabelac's avatar
Zdenek Kabelac committed
184 185 186 187

    return 0;
}

188
static av_cold int amr_nb_decode_close(AVCodecContext * avctx)
Zdenek Kabelac's avatar
Zdenek Kabelac committed
189 190
{
    AMRContext *s = avctx->priv_data;
Benoit Fouet's avatar
Benoit Fouet committed
191

Zdenek Kabelac's avatar
Zdenek Kabelac committed
192 193 194 195
    Decoder_Interface_exit(s->decState);
    return 0;
}

196
static av_cold int amr_nb_encode_close(AVCodecContext * avctx)
Zdenek Kabelac's avatar
Zdenek Kabelac committed
197 198
{
    AMRContext *s = avctx->priv_data;
Benoit Fouet's avatar
Benoit Fouet committed
199

Zdenek Kabelac's avatar
Zdenek Kabelac committed
200 201 202 203 204 205 206
    Encoder_Interface_exit(s->enstate);
    av_freep(&avctx->coded_frame);
    return 0;
}

static int amr_nb_decode_frame(AVCodecContext * avctx,
            void *data, int *data_size,
207
            AVPacket *avpkt)
Zdenek Kabelac's avatar
Zdenek Kabelac committed
208
{
209 210
    const uint8_t *buf = avpkt->data;
    int buf_size = avpkt->size;
211
    AMRContext *s = avctx->priv_data;
212
    const uint8_t*amrData=buf;
213
    static const uint8_t block_size[16]={ 12, 13, 15, 17, 19, 20, 26, 31, 5, 0, 0, 0, 0, 0, 0, 0 };
Zdenek Kabelac's avatar
Zdenek Kabelac committed
214 215 216
    enum Mode dec_mode;
    int packet_size;

217
    /* av_log(NULL,AV_LOG_DEBUG,"amr_decode_frame buf=%p buf_size=%d frameCount=%d!!\n",buf,buf_size,s->frameCount); */
218

219 220 221 222 223 224 225
    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;
    }
226

227 228 229 230 231
    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;
232

233
    return packet_size;
234 235
}

Zdenek Kabelac's avatar
Zdenek Kabelac committed
236
static int amr_nb_encode_frame(AVCodecContext *avctx,
237
                            unsigned char *frame/*out*/, int buf_size, void *data/*in*/)
Zdenek Kabelac's avatar
Zdenek Kabelac committed
238
{
239
    AMRContext *s = avctx->priv_data;
Zdenek Kabelac's avatar
Zdenek Kabelac committed
240 241
    int written;

Benoit Fouet's avatar
Benoit Fouet committed
242 243
    if((s->enc_bitrate=getBitrateMode(avctx->bit_rate))<0)
    {
244
        av_log(avctx, AV_LOG_ERROR, nb_bitrate_unsupported);
Benoit Fouet's avatar
Benoit Fouet committed
245 246
        return -1;
    }
247

248 249 250 251
    written = Encoder_Interface_Encode(s->enstate,
        s->enc_bitrate,
        data,
        frame,
Zdenek Kabelac's avatar
Zdenek Kabelac committed
252
        0);
253
    /* 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] ); */
Zdenek Kabelac's avatar
Zdenek Kabelac committed
254 255 256 257 258 259

    return written;
}

#endif

260
#if CONFIG_LIBAMR_NB
261

262
AVCodec libamr_nb_decoder =
263
{
264
    "libamr_nb",
265 266
    CODEC_TYPE_AUDIO,
    CODEC_ID_AMR_NB,
Zdenek Kabelac's avatar
Zdenek Kabelac committed
267
    sizeof(AMRContext),
268 269
    amr_nb_decode_init,
    NULL,
Zdenek Kabelac's avatar
Zdenek Kabelac committed
270
    amr_nb_decode_close,
271
    amr_nb_decode_frame,
272
    .long_name = NULL_IF_CONFIG_SMALL("libamr-nb Adaptive Multi-Rate (AMR) Narrow-Band"),
273 274
};

275
AVCodec libamr_nb_encoder =
Zdenek Kabelac's avatar
Zdenek Kabelac committed
276
{
277
    "libamr_nb",
Zdenek Kabelac's avatar
Zdenek Kabelac committed
278 279 280 281 282 283 284
    CODEC_TYPE_AUDIO,
    CODEC_ID_AMR_NB,
    sizeof(AMRContext),
    amr_nb_encode_init,
    amr_nb_encode_frame,
    amr_nb_encode_close,
    NULL,
285
    .sample_fmts = (enum SampleFormat[]){SAMPLE_FMT_S16,SAMPLE_FMT_NONE},
286
    .long_name = NULL_IF_CONFIG_SMALL("libamr-nb Adaptive Multi-Rate (AMR) Narrow-Band"),
Zdenek Kabelac's avatar
Zdenek Kabelac committed
287
};
288

289 290
#endif

291
/* -----------AMR wideband ------------*/
292
#if CONFIG_LIBAMR_WB
293 294

#ifdef _TYPEDEF_H
Diego Biurrun's avatar
typo  
Diego Biurrun committed
295
//To avoid duplicate typedefs from typedef in amr-nb
296 297 298
#define typedef_h
#endif

299 300 301
#include <amrwb/enc_if.h>
#include <amrwb/dec_if.h>
#include <amrwb/if_rom.h>
302 303 304 305

/* Common code for fixed and float version*/
typedef struct AMRWB_bitrates
{
Benoit Fouet's avatar
Benoit Fouet committed
306
    int rate;
307 308 309 310 311
    int mode;
} AMRWB_bitrates;

static int getWBBitrateMode(int bitrate)
{
Benoit Fouet's avatar
Benoit Fouet committed
312 313 314 315 316 317 318 319 320 321
    /* make the correspondance between bitrate and mode */
    AMRWB_bitrates rates[]={ {6600,0},
                           {8850,1},
                           {12650,2},
                           {14250,3},
                           {15850,4},
                           {18250,5},
                           {19850,6},
                           {23050,7},
                           {23850,8},
322 323 324 325 326
                         };
    int i;

    for(i=0;i<9;i++)
    {
Benoit Fouet's avatar
Benoit Fouet committed
327
        if(rates[i].rate==bitrate)
328
        {
329
            return rates[i].mode;
330 331
        }
    }
Benoit Fouet's avatar
Benoit Fouet committed
332 333
    /* no bitrate matching, return an error */
    return -1;
334 335 336 337 338 339 340 341 342 343 344 345
}


typedef struct AMRWBContext {
    int frameCount;
    void *state;
    int mode;
    Word16 allow_dtx;
} AMRWBContext;

static int amr_wb_encode_init(AVCodecContext * avctx)
{
346
    AMRWBContext *s = avctx->priv_data;
Benoit Fouet's avatar
Benoit Fouet committed
347

348
    s->frameCount=0;
349

350 351
    if(avctx->sample_rate!=16000)
    {
352
        av_log(avctx, AV_LOG_ERROR, "Only 16000Hz sample rate supported\n");
353 354 355 356 357
        return -1;
    }

    if(avctx->channels!=1)
    {
358
        av_log(avctx, AV_LOG_ERROR, "Only mono supported\n");
359 360 361
        return -1;
    }

Benoit Fouet's avatar
Benoit Fouet committed
362 363
    if((s->mode=getWBBitrateMode(avctx->bit_rate))<0)
    {
364
        av_log(avctx, AV_LOG_ERROR, wb_bitrate_unsupported);
Benoit Fouet's avatar
Benoit Fouet committed
365 366 367
        return -1;
    }

368 369 370 371 372 373 374 375 376 377 378
    avctx->frame_size=320;
    avctx->coded_frame= avcodec_alloc_frame();

    s->state = E_IF_init();
    s->allow_dtx=0;

    return 0;
}

static int amr_wb_encode_close(AVCodecContext * avctx)
{
379
    AMRWBContext *s = avctx->priv_data;
Benoit Fouet's avatar
Benoit Fouet committed
380

381 382 383 384 385 386 387
    E_IF_exit(s->state);
    av_freep(&avctx->coded_frame);
    s->frameCount++;
    return 0;
}

static int amr_wb_encode_frame(AVCodecContext *avctx,
388
                            unsigned char *frame/*out*/, int buf_size, void *data/*in*/)
389
{
390
    AMRWBContext *s = avctx->priv_data;
391
    int size;
392

Benoit Fouet's avatar
Benoit Fouet committed
393 394
    if((s->mode=getWBBitrateMode(avctx->bit_rate))<0)
    {
395
        av_log(avctx, AV_LOG_ERROR, wb_bitrate_unsupported);
Benoit Fouet's avatar
Benoit Fouet committed
396 397
        return -1;
    }
398
    size = E_IF_encode(s->state, s->mode, data, frame, s->allow_dtx);
399 400 401 402 403
    return size;
}

static int amr_wb_decode_init(AVCodecContext * avctx)
{
404
    AMRWBContext *s = avctx->priv_data;
Benoit Fouet's avatar
Benoit Fouet committed
405

406 407
    s->frameCount=0;
    s->state = D_IF_init();
Andrew Voznytsa's avatar
Andrew Voznytsa committed
408 409 410 411 412 413 414 415 416

    amr_decode_fix_avctx(avctx);

    if(avctx->channels > 1)
    {
        av_log(avctx, AV_LOG_ERROR, "amr_wb: multichannel decoding not supported\n");
        return -1;
    }

417 418 419 420 421
    return 0;
}

static int amr_wb_decode_frame(AVCodecContext * avctx,
            void *data, int *data_size,
422
            AVPacket *avpkt)
423
{
424 425
    const uint8_t *buf = avpkt->data;
    int buf_size = avpkt->size;
426
    AMRWBContext *s = avctx->priv_data;
427
    const uint8_t*amrData=buf;
428 429
    int mode;
    int packet_size;
430
    static const uint8_t block_size[16] = {18, 23, 33, 37, 41, 47, 51, 59, 61, 6, 6, 0, 0, 0, 1, 1};
431

432 433 434 435 436 437 438 439 440 441 442
    if(buf_size==0) {
        /* 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;
443
    }
444

445 446 447 448
    s->frameCount++;
    D_IF_decode( s->state, amrData, data, _good_frame);
    *data_size=320*2;
    return packet_size;
449 450 451 452
}

static int amr_wb_decode_close(AVCodecContext * avctx)
{
453
    AMRWBContext *s = avctx->priv_data;
Benoit Fouet's avatar
Benoit Fouet committed
454

455 456 457 458
    D_IF_exit(s->state);
    return 0;
}

459
AVCodec libamr_wb_decoder =
460
{
461
    "libamr_wb",
462 463 464 465 466 467 468
    CODEC_TYPE_AUDIO,
    CODEC_ID_AMR_WB,
    sizeof(AMRWBContext),
    amr_wb_decode_init,
    NULL,
    amr_wb_decode_close,
    amr_wb_decode_frame,
469
    .long_name = NULL_IF_CONFIG_SMALL("libamr-wb Adaptive Multi-Rate (AMR) Wide-Band"),
470 471
};

472
AVCodec libamr_wb_encoder =
473
{
474
    "libamr_wb",
475 476 477 478 479 480 481
    CODEC_TYPE_AUDIO,
    CODEC_ID_AMR_WB,
    sizeof(AMRWBContext),
    amr_wb_encode_init,
    amr_wb_encode_frame,
    amr_wb_encode_close,
    NULL,
482
    .sample_fmts = (enum SampleFormat[]){SAMPLE_FMT_S16,SAMPLE_FMT_NONE},
483
    .long_name = NULL_IF_CONFIG_SMALL("libamr-wb Adaptive Multi-Rate (AMR) Wide-Band"),
484 485
};

486
#endif //CONFIG_LIBAMR_WB