Indeo Audio decoder
authorKostya Shishkov <kostya.shishkov@gmail.com>
Sat, 2 Jun 2012 19:07:02 +0000 (21:07 +0200)
committerKostya Shishkov <kostya.shishkov@gmail.com>
Tue, 5 Jun 2012 16:30:54 +0000 (18:30 +0200)
Changelog
doc/general.texi
libavcodec/Makefile
libavcodec/allcodecs.c
libavcodec/avcodec.h
libavcodec/imc.c
libavcodec/imcdata.h
libavcodec/version.h
libavformat/riff.c

index 358662b..898a247 100644 (file)
--- a/Changelog
+++ b/Changelog
@@ -23,6 +23,8 @@ version <next>:
 - audio mix filter
 - avprobe output is now standard INI or JSON. The old format can still
   be used with -of old.
+- Indeo Audio decoder
+
 
 version 0.8:
 
index 680b971..dee8f9e 100644 (file)
@@ -706,6 +706,7 @@ following image formats are supported:
     @tab encoding supported through external library libgsm
 @item GSM Microsoft variant  @tab  E  @tab  X
     @tab encoding supported through external library libgsm
+@item IAC (Indeo Audio Coder)  @tab     @tab  X
 @item IMC (Intel Music Coder)  @tab     @tab  X
 @item MACE (Macintosh Audio Compression/Expansion) 3:1  @tab     @tab  X
 @item MACE (Macintosh Audio Compression/Expansion) 6:1  @tab     @tab  X
index da8aa8a..3bfd78b 100644 (file)
@@ -197,6 +197,7 @@ OBJS-$(CONFIG_H264_VAAPI_HWACCEL)      += vaapi_h264.o
 OBJS-$(CONFIG_H264_VDA_HWACCEL)        += vda_h264.o
 OBJS-$(CONFIG_HUFFYUV_DECODER)         += huffyuv.o
 OBJS-$(CONFIG_HUFFYUV_ENCODER)         += huffyuv.o
+OBJS-$(CONFIG_IAC_DECODER)             += imc.o
 OBJS-$(CONFIG_IDCIN_DECODER)           += idcinvideo.o
 OBJS-$(CONFIG_IFF_BYTERUN1_DECODER)    += iff.o
 OBJS-$(CONFIG_IFF_ILBM_DECODER)        += iff.o
index a1df47a..01d13d5 100644 (file)
@@ -260,6 +260,7 @@ void avcodec_register_all(void)
     REGISTER_ENCDEC  (FLAC, flac);
     REGISTER_DECODER (GSM, gsm);
     REGISTER_DECODER (GSM_MS, gsm_ms);
+    REGISTER_DECODER (IAC, iac);
     REGISTER_DECODER (IMC, imc);
     REGISTER_DECODER (MACE3, mace3);
     REGISTER_DECODER (MACE6, mace6);
index 102df3a..4a07d6d 100644 (file)
@@ -393,6 +393,7 @@ enum CodecID {
     CODEC_ID_8SVX_FIB,
     CODEC_ID_BMV_AUDIO,
     CODEC_ID_RALF,
+    CODEC_ID_IAC,
 
     /* subtitle codecs */
     CODEC_ID_FIRST_SUBTITLE = 0x17000,          ///< A dummy ID pointing at the start of subtitle codecs.
index 4b8ad7c..3856f4a 100644 (file)
@@ -79,7 +79,7 @@ typedef struct IMCChannel {
 typedef struct {
     AVFrame frame;
 
-    IMCChannel chctx[1];
+    IMCChannel chctx[2];
 
     /** MDCT tables */
     //@{
@@ -98,6 +98,9 @@ typedef struct {
     FFTContext fft;
     DECLARE_ALIGNED(32, FFTComplex, samples)[COEFFS / 2];
     float *out_samples;
+
+    int8_t cyclTab[32], cyclTab2[32];
+    float  weights1[31], weights2[31];
 } IMCContext;
 
 static VLC huffman_vlc[4][4];
@@ -117,7 +120,8 @@ static av_cold int imc_decode_init(AVCodecContext *avctx)
     IMCContext *q = avctx->priv_data;
     double r1, r2;
 
-    if (avctx->channels != 1) {
+    if ((avctx->codec_id == CODEC_ID_IMC && avctx->channels != 1)
+        || (avctx->codec_id == CODEC_ID_IAC && avctx->channels > 2)) {
         av_log_ask_for_sample(avctx, "Number of channels is not supported\n");
         return AVERROR_PATCHWELCOME;
     }
@@ -169,6 +173,18 @@ static av_cold int imc_decode_init(AVCodecContext *avctx)
     }
     q->one_div_log2 = 1 / log(2);
 
+    memcpy(q->cyclTab,  cyclTab,  sizeof(cyclTab));
+    memcpy(q->cyclTab2, cyclTab2, sizeof(cyclTab2));
+    if (avctx->codec_id == CODEC_ID_IAC) {
+        q->cyclTab[29]  = 31;
+        q->cyclTab2[31] = 28;
+        memcpy(q->weights1, iac_weights1, sizeof(iac_weights1));
+        memcpy(q->weights2, iac_weights2, sizeof(iac_weights2));
+    } else {
+        memcpy(q->weights1, imc_weights1, sizeof(imc_weights1));
+        memcpy(q->weights2, imc_weights2, sizeof(imc_weights2));
+    }
+
     if ((ret = ff_fft_init(&q->fft, 7, 1))) {
         av_log(avctx, AV_LOG_INFO, "FFT init failed\n");
         return ret;
@@ -210,13 +226,13 @@ static void imc_calculate_coeffs(IMCContext *q, float *flcoeffs1,
     }
 
     for (i = 0; i < BANDS; i++) {
-        for (cnt2 = i; cnt2 < cyclTab[i]; cnt2++)
+        for (cnt2 = i; cnt2 < q->cyclTab[i]; cnt2++)
             flcoeffs5[cnt2] = flcoeffs5[cnt2] + workT3[i];
         workT2[cnt2 - 1] = workT2[cnt2 - 1] + workT3[i];
     }
 
     for (i = 1; i < BANDS; i++) {
-        accum = (workT2[i - 1] + accum) * imc_weights1[i - 1];
+        accum = (workT2[i - 1] + accum) * q->weights1[i - 1];
         flcoeffs5[i] += accum;
     }
 
@@ -224,7 +240,7 @@ static void imc_calculate_coeffs(IMCContext *q, float *flcoeffs1,
         workT2[i] = 0.0;
 
     for (i = 0; i < BANDS; i++) {
-        for (cnt2 = i - 1; cnt2 > cyclTab2[i]; cnt2--)
+        for (cnt2 = i - 1; cnt2 > q->cyclTab2[i]; cnt2--)
             flcoeffs5[cnt2] += workT3[i];
         workT2[cnt2+1] += workT3[i];
     }
@@ -232,7 +248,7 @@ static void imc_calculate_coeffs(IMCContext *q, float *flcoeffs1,
     accum = 0.0;
 
     for (i = BANDS-2; i >= 0; i--) {
-        accum = (workT2[i+1] + accum) * imc_weights2[i];
+        accum = (workT2[i+1] + accum) * q->weights2[i];
         flcoeffs5[i] += accum;
         // there is missing code here, but it seems to never be triggered
     }
@@ -701,16 +717,17 @@ static int imc_decode_block(AVCodecContext *avctx, IMCContext *q, int ch)
 
     /* Check the frame header */
     imc_hdr = get_bits(&q->gb, 9);
-    if (imc_hdr != IMC_FRAME_ID) {
-        av_log(avctx, AV_LOG_ERROR, "imc frame header check failed!\n");
-        av_log(avctx, AV_LOG_ERROR, "got %x instead of 0x21.\n", imc_hdr);
+    if (imc_hdr & 0x18) {
+        av_log(avctx, AV_LOG_ERROR, "frame header check failed!\n");
+        av_log(avctx, AV_LOG_ERROR, "got %X.\n", imc_hdr);
         return AVERROR_INVALIDDATA;
     }
     stream_format_code = get_bits(&q->gb, 3);
 
     if (stream_format_code & 1) {
-        av_log(avctx, AV_LOG_ERROR, "Stream code format %X is not supported\n", stream_format_code);
-        return AVERROR_INVALIDDATA;
+        av_log_ask_for_sample(avctx, "Stream format %X is not supported\n",
+                              stream_format_code);
+        return AVERROR_PATCHWELCOME;
     }
 
 //    av_log(avctx, AV_LOG_DEBUG, "stream_format_code = %d\n", stream_format_code);
@@ -773,6 +790,11 @@ static int imc_decode_block(AVCodecContext *avctx, IMCContext *q, int ch)
             }
         }
     }
+    if (avctx->codec_id == CODEC_ID_IAC) {
+        bitscount += !!chctx->bandWidthT[BANDS - 1];
+        if (!(stream_format_code & 0x2))
+            bitscount += 16;
+    }
 
     if ((ret = bit_allocation(q, chctx, stream_format_code,
                               512 - bitscount - get_bits_count(&q->gb),
@@ -860,8 +882,8 @@ static int imc_decode_frame(AVCodecContext *avctx, void *data,
 
     LOCAL_ALIGNED_16(uint16_t, buf16, [IMC_BLOCK_SIZE / 2]);
 
-    if (buf_size < IMC_BLOCK_SIZE) {
-        av_log(avctx, AV_LOG_ERROR, "imc frame too small!\n");
+    if (buf_size < IMC_BLOCK_SIZE * avctx->channels) {
+        av_log(avctx, AV_LOG_ERROR, "frame too small!\n");
         return AVERROR_INVALIDDATA;
     }
 
@@ -885,6 +907,18 @@ static int imc_decode_frame(AVCodecContext *avctx, void *data,
             return ret;
     }
 
+    if (avctx->channels == 2) {
+        float *src = (float*)q->frame.data[0], t1, t2;
+
+        for (i = 0; i < COEFFS; i++) {
+            t1     = src[0];
+            t2     = src[1];
+            src[0] = t1 + t2;
+            src[1] = t1 - t2;
+            src   += 2;
+        }
+    }
+
     *got_frame_ptr   = 1;
     *(AVFrame *)data = q->frame;
 
@@ -913,3 +947,15 @@ AVCodec ff_imc_decoder = {
     .capabilities   = CODEC_CAP_DR1,
     .long_name      = NULL_IF_CONFIG_SMALL("IMC (Intel Music Coder)"),
 };
+
+AVCodec ff_iac_decoder = {
+    .name           = "iac",
+    .type           = AVMEDIA_TYPE_AUDIO,
+    .id             = CODEC_ID_IAC,
+    .priv_data_size = sizeof(IMCContext),
+    .init           = imc_decode_init,
+    .close          = imc_decode_close,
+    .decode         = imc_decode_frame,
+    .capabilities   = CODEC_CAP_DR1,
+    .long_name      = NULL_IF_CONFIG_SMALL("IAC (Indeo Audio Coder)"),
+};
index 8e99391..ea9b374 100644 (file)
@@ -44,6 +44,25 @@ static const int8_t cyclTab2[32] = {
  12, 13, 14, 15, 16, 17, 17, 18, 19, 20, 21, 22,
 23, 24, 25, 26, 27, 28, 29};
 
+static const float iac_weights1[31] = {
+    0.0538585, 0.0576251, 0.0645592, 0.0494032, 0.0428915, 0.0592188,
+    0.0604145, 0.0673549, 0.0797351, 0.0972911, 0.119376,  0.144777,
+    0.17181,   0.198625,  0.242918,  0.262113,  0.278434,  0.310752,
+    0.319978,  0.328482,  0.354631,  0.380212,  0.388783,  0.400428,
+    0.43096,   0.462397,  0.479469,  0.499329,  0.534526,  0.568631,
+    0.589218
+};
+
+static const float iac_weights2[31] = {
+    0.000375307, 0.000450455, 0.000612191, 0.000297262, 0.000202956,
+    0.000484887, 0.000511777, 0.000686431, 0.00108256,  0.00185267,
+    0.00321869,  0.00541861,  0.00860266,  0.012726,    0.0219151,
+    0.0269104,   0.0316774,   0.0426107,   0.046113,    0.0494974,
+    0.0608692,   0.0734633,   0.0780208,   0.0844921,   0.103034,
+    0.124606,    0.137421,    0.153336,    0.184296,    0.217792,
+    0.239742
+};
+
 static const float imc_weights1[31] = {
     0.119595, 0.123124, 0.129192, 9.97377e-2, 8.1923e-2, 9.61153e-2, 8.77885e-2, 8.61174e-2,
     9.00882e-2, 9.91658e-2, 0.112991, 0.131126, 0.152886, 0.177292, 0.221782, 0.244917, 0.267386,
index da7796a..e8f0b5c 100644 (file)
@@ -27,8 +27,8 @@
  */
 
 #define LIBAVCODEC_VERSION_MAJOR 54
-#define LIBAVCODEC_VERSION_MINOR 13
-#define LIBAVCODEC_VERSION_MICRO  1
+#define LIBAVCODEC_VERSION_MINOR 14
+#define LIBAVCODEC_VERSION_MICRO  0
 
 #define LIBAVCODEC_VERSION_INT  AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \
                                                LIBAVCODEC_VERSION_MINOR, \
index 8a91345..922a863 100644 (file)
@@ -322,6 +322,7 @@ const AVCodecTag ff_codec_wav_tags[] = {
     { CODEC_ID_ATRAC3,          0x0270 },
     { CODEC_ID_ADPCM_G722,      0x028F },
     { CODEC_ID_IMC,             0x0401 },
+    { CODEC_ID_IAC,             0x0402 },
     { CODEC_ID_GSM_MS,          0x1500 },
     { CODEC_ID_TRUESPEECH,      0x1501 },
     { CODEC_ID_AAC,             0x1600 }, /* ADTS AAC */