Merge remote-tracking branch 'qatar/master'
authorMichael Niedermayer <michaelni@gmx.at>
Mon, 26 Aug 2013 12:53:10 +0000 (14:53 +0200)
committerMichael Niedermayer <michaelni@gmx.at>
Mon, 26 Aug 2013 12:53:15 +0000 (14:53 +0200)
* qatar/master:
  imc: support mode 1

Merged-by: Michael Niedermayer <michaelni@gmx.at>
1  2 
libavcodec/imc.c

diff --combined libavcodec/imc.c
@@@ -4,20 -4,20 +4,20 @@@
   * Copyright (c) 2006 Benjamin Larsson
   * Copyright (c) 2006 Konstantin Shishkov
   *
 - * This file is part of Libav.
 + * This file is part of FFmpeg.
   *
 - * Libav is free software; you can redistribute it and/or
 + * 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.
   *
 - * Libav is distributed in the hope that it will be useful,
 + * 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 Libav; if not, write to the Free Software
 + * License along with FFmpeg; if not, write to the Free Software
   * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
   */
  
@@@ -38,7 -38,6 +38,7 @@@
  #include "libavutil/channel_layout.h"
  #include "libavutil/float_dsp.h"
  #include "libavutil/internal.h"
 +#include "libavutil/libm.h"
  #include "avcodec.h"
  #include "get_bits.h"
  #include "dsputil.h"
@@@ -101,6 -100,8 +101,8 @@@ typedef struct 
      DECLARE_ALIGNED(32, FFTComplex, samples)[COEFFS / 2];
      float *out_samples;
  
+     int coef0_pos;
      int8_t cyclTab[32], cyclTab2[32];
      float  weights1[31], weights2[31];
  } IMCContext;
@@@ -337,6 -338,17 +339,17 @@@ static void imc_read_level_coeffs(IMCCo
      }
  }
  
+ static void imc_read_level_coeffs_raw(IMCContext *q, int stream_format_code,
+                                       int *levlCoeffs)
+ {
+     int i;
+     q->coef0_pos  = get_bits(&q->gb, 5);
+     levlCoeffs[0] = get_bits(&q->gb, 7);
+     for (i = 1; i < BANDS; i++)
+         levlCoeffs[i] = get_bits(&q->gb, 4);
+ }
  static void imc_decode_level_coefficients(IMCContext *q, int *levlCoeffBuf,
                                            float *flcoeffs1, float *flcoeffs2)
  {
      float tmp, tmp2;
      // maybe some frequency division thingy
  
 -    flcoeffs1[0] = 20000.0 / pow (2, levlCoeffBuf[0] * 0.18945); // 0.18945 = log2(10) * 0.05703125
 +    flcoeffs1[0] = 20000.0 / exp2 (levlCoeffBuf[0] * 0.18945); // 0.18945 = log2(10) * 0.05703125
      flcoeffs2[0] = log2f(flcoeffs1[0]);
      tmp  = flcoeffs1[0];
      tmp2 = flcoeffs2[0];
@@@ -391,6 -403,28 +404,28 @@@ static void imc_decode_level_coefficien
      }
  }
  
+ static void imc_decode_level_coefficients_raw(IMCContext *q, int *levlCoeffBuf,
+                                               float *flcoeffs1, float *flcoeffs2)
+ {
+     int i, level, pos;
+     float tmp, tmp2;
+     pos = q->coef0_pos;
+     flcoeffs1[pos] = 20000.0 / pow (2, levlCoeffBuf[0] * 0.18945); // 0.18945 = log2(10) * 0.05703125
+     flcoeffs2[pos] = log2f(flcoeffs1[0]);
+     tmp  = flcoeffs1[pos];
+     tmp2 = flcoeffs2[pos];
+     levlCoeffBuf++;
+     for (i = 0; i < BANDS; i++) {
+         if (i == pos)
+             continue;
+         level = *levlCoeffBuf++;
+         flcoeffs1[i] = tmp  * powf(10.0, -level * 0.4375); //todo tab
+         flcoeffs2[i] = tmp2 - 1.4533435415 * level; // 1.4533435415 = log2(10) * 0.4375
+     }
+ }
  /**
   * Perform bit allocation depending on bits available
   */
@@@ -763,12 -797,56 +798,56 @@@ static int imc_get_coeffs(IMCContext *q
      return 0;
  }
  
+ static void imc_refine_bit_allocation(IMCContext *q, IMCChannel *chctx)
+ {
+     int i, j;
+     int bits, summer;
+     for (i = 0; i < BANDS; i++) {
+         chctx->sumLenArr[i]   = 0;
+         chctx->skipFlagRaw[i] = 0;
+         for (j = band_tab[i]; j < band_tab[i + 1]; j++)
+             chctx->sumLenArr[i] += chctx->CWlengthT[j];
+         if (chctx->bandFlagsBuf[i])
+             if ((((band_tab[i + 1] - band_tab[i]) * 1.5) > chctx->sumLenArr[i]) && (chctx->sumLenArr[i] > 0))
+                 chctx->skipFlagRaw[i] = 1;
+     }
+     imc_get_skip_coeff(q, chctx);
+     for (i = 0; i < BANDS; i++) {
+         chctx->flcoeffs6[i] = chctx->flcoeffs1[i];
+         /* band has flag set and at least one coded coefficient */
+         if (chctx->bandFlagsBuf[i] && (band_tab[i + 1] - band_tab[i]) != chctx->skipFlagCount[i]) {
+             chctx->flcoeffs6[i] *= q->sqrt_tab[ band_tab[i + 1] - band_tab[i]] /
+                                    q->sqrt_tab[(band_tab[i + 1] - band_tab[i] - chctx->skipFlagCount[i])];
+         }
+     }
+     /* calculate bits left, bits needed and adjust bit allocation */
+     bits = summer = 0;
+     for (i = 0; i < BANDS; i++) {
+         if (chctx->bandFlagsBuf[i]) {
+             for (j = band_tab[i]; j < band_tab[i + 1]; j++) {
+                 if (chctx->skipFlags[j]) {
+                     summer += chctx->CWlengthT[j];
+                     chctx->CWlengthT[j] = 0;
+                 }
+             }
+             bits   += chctx->skipFlagBits[i];
+             summer -= chctx->skipFlagBits[i];
+         }
+     }
+     imc_adjust_bit_allocation(q, chctx, summer);
+ }
  static int imc_decode_block(AVCodecContext *avctx, IMCContext *q, int ch)
  {
      int stream_format_code;
      int imc_hdr, i, j, ret;
      int flag;
-     int bits, summer;
+     int bits;
      int counter, bitscount;
      IMCChannel *chctx = q->chctx + ch;
  
      }
      stream_format_code = get_bits(&q->gb, 3);
  
-     if (stream_format_code & 1) {
-         avpriv_request_sample(avctx, "Stream format %X", stream_format_code);
-         return AVERROR_PATCHWELCOME;
-     }
      if (stream_format_code & 0x04)
          chctx->decoder_reset = 1;
  
      }
  
      flag = get_bits1(&q->gb);
-     imc_read_level_coeffs(q, stream_format_code, chctx->levlCoeffBuf);
+     if (stream_format_code & 0x1)
+         imc_decode_level_coefficients_raw(q, chctx->levlCoeffBuf,
+                                           chctx->flcoeffs1, chctx->flcoeffs2);
+     else if (stream_format_code & 0x1)
+         imc_read_level_coeffs_raw(q, stream_format_code, chctx->levlCoeffBuf);
+     else
+         imc_read_level_coeffs(q, stream_format_code, chctx->levlCoeffBuf);
  
      if (stream_format_code & 0x4)
          imc_decode_level_coefficients(q, chctx->levlCoeffBuf,
          imc_decode_level_coefficients2(q, chctx->levlCoeffBuf, chctx->old_floor,
                                         chctx->flcoeffs1, chctx->flcoeffs2);
  
 +    for(i=0; i<BANDS; i++) {
 +        if(chctx->flcoeffs1[i] > INT_MAX) {
 +            av_log(avctx, AV_LOG_ERROR, "scalefactor out of range\n");
 +            return AVERROR_INVALIDDATA;
 +        }
 +    }
 +
      memcpy(chctx->old_floor, chctx->flcoeffs1, 32 * sizeof(float));
  
      counter = 0;
-     for (i = 0; i < BANDS; i++) {
-         if (chctx->levlCoeffBuf[i] == 16) {
-             chctx->bandWidthT[i] = 0;
-             counter++;
-         } else
-             chctx->bandWidthT[i] = band_tab[i + 1] - band_tab[i];
-     }
-     memset(chctx->bandFlagsBuf, 0, BANDS * sizeof(int));
-     for (i = 0; i < BANDS - 1; i++) {
-         if (chctx->bandWidthT[i])
-             chctx->bandFlagsBuf[i] = get_bits1(&q->gb);
-     }
+     if (stream_format_code & 0x1) {
+         for (i = 0; i < BANDS; i++) {
+             chctx->bandWidthT[i]   = band_tab[i + 1] - band_tab[i];
+             chctx->bandFlagsBuf[i] = 0;
+             chctx->flcoeffs3[i]    = chctx->flcoeffs2[i] * 2;
+             chctx->flcoeffs5[i]    = 1.0;
+         }
+     } else {
+         for (i = 0; i < BANDS; i++) {
+             if (chctx->levlCoeffBuf[i] == 16) {
+                 chctx->bandWidthT[i] = 0;
+                 counter++;
+             } else
+                 chctx->bandWidthT[i] = band_tab[i + 1] - band_tab[i];
+         }
+         memset(chctx->bandFlagsBuf, 0, BANDS * sizeof(int));
+         for (i = 0; i < BANDS - 1; i++)
+             if (chctx->bandWidthT[i])
+                 chctx->bandFlagsBuf[i] = get_bits1(&q->gb);
  
-     imc_calculate_coeffs(q, chctx->flcoeffs1, chctx->flcoeffs2, chctx->bandWidthT, chctx->flcoeffs3, chctx->flcoeffs5);
+         imc_calculate_coeffs(q, chctx->flcoeffs1, chctx->flcoeffs2,
+                              chctx->bandWidthT, chctx->flcoeffs3,
+                              chctx->flcoeffs5);
+     }
  
      bitscount = 0;
      /* first 4 bands will be assigned 5 bits per coefficient */
          chctx->CWlengthT[1] = 5;
          chctx->CWlengthT[2] = 5;
          for (i = 1; i < 4; i++) {
-             bits = (chctx->levlCoeffBuf[i] == 16) ? 0 : 5;
+             if (stream_format_code & 0x1)
+                 bits = 5;
+             else
+                 bits = (chctx->levlCoeffBuf[i] == 16) ? 0 : 5;
              chctx->bitsBandT[i] = bits;
              for (j = band_tab[i]; j < band_tab[i + 1]; j++) {
                  chctx->CWlengthT[j] = bits;
          return ret;
      }
  
-     for (i = 0; i < BANDS; i++) {
-         chctx->sumLenArr[i]   = 0;
-         chctx->skipFlagRaw[i] = 0;
-         for (j = band_tab[i]; j < band_tab[i + 1]; j++)
-             chctx->sumLenArr[i] += chctx->CWlengthT[j];
-         if (chctx->bandFlagsBuf[i])
-             if ((((band_tab[i + 1] - band_tab[i]) * 1.5) > chctx->sumLenArr[i]) && (chctx->sumLenArr[i] > 0))
-                 chctx->skipFlagRaw[i] = 1;
-     }
-     imc_get_skip_coeff(q, chctx);
-     for (i = 0; i < BANDS; i++) {
-         chctx->flcoeffs6[i] = chctx->flcoeffs1[i];
-         /* band has flag set and at least one coded coefficient */
-         if (chctx->bandFlagsBuf[i] && (band_tab[i + 1] - band_tab[i]) != chctx->skipFlagCount[i]) {
-             chctx->flcoeffs6[i] *= q->sqrt_tab[ band_tab[i + 1] - band_tab[i]] /
-                                    q->sqrt_tab[(band_tab[i + 1] - band_tab[i] - chctx->skipFlagCount[i])];
-         }
-     }
-     /* calculate bits left, bits needed and adjust bit allocation */
-     bits = summer = 0;
-     for (i = 0; i < BANDS; i++) {
-         if (chctx->bandFlagsBuf[i]) {
-             for (j = band_tab[i]; j < band_tab[i + 1]; j++) {
-                 if (chctx->skipFlags[j]) {
-                     summer += chctx->CWlengthT[j];
-                     chctx->CWlengthT[j] = 0;
-                 }
-             }
-             bits   += chctx->skipFlagBits[i];
-             summer -= chctx->skipFlagBits[i];
-         }
+     if (stream_format_code & 0x1) {
+         for (i = 0; i < BANDS; i++)
+             chctx->skipFlags[i] = 0;
+     } else {
+         imc_refine_bit_allocation(q, chctx);
      }
-     imc_adjust_bit_allocation(q, chctx, summer);
  
      for (i = 0; i < BANDS; i++) {
          chctx->sumLenArr[i] = 0;
@@@ -951,8 -1006,10 +1014,8 @@@ static int imc_decode_frame(AVCodecCont
  
      /* get output buffer */
      frame->nb_samples = COEFFS;
 -    if ((ret = ff_get_buffer(avctx, frame, 0)) < 0) {
 -        av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
 +    if ((ret = ff_get_buffer(avctx, frame, 0)) < 0)
          return ret;
 -    }
  
      for (i = 0; i < avctx->channels; i++) {
          q->out_samples = (float *)frame->extended_data[i];
@@@ -987,15 -1044,7 +1050,15 @@@ static av_cold int imc_decode_close(AVC
      return 0;
  }
  
 +static av_cold void flush(AVCodecContext *avctx)
 +{
 +    IMCContext *q = avctx->priv_data;
  
 +    q->chctx[0].decoder_reset =
 +    q->chctx[1].decoder_reset = 1;
 +}
 +
 +#if CONFIG_IMC_DECODER
  AVCodec ff_imc_decoder = {
      .name           = "imc",
      .type           = AVMEDIA_TYPE_AUDIO,
      .init           = imc_decode_init,
      .close          = imc_decode_close,
      .decode         = imc_decode_frame,
 +    .flush          = flush,
      .capabilities   = CODEC_CAP_DR1,
      .long_name      = NULL_IF_CONFIG_SMALL("IMC (Intel Music Coder)"),
      .sample_fmts    = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_FLTP,
                                                        AV_SAMPLE_FMT_NONE },
  };
 -
 +#endif
 +#if CONFIG_IAC_DECODER
  AVCodec ff_iac_decoder = {
      .name           = "iac",
      .type           = AVMEDIA_TYPE_AUDIO,
      .init           = imc_decode_init,
      .close          = imc_decode_close,
      .decode         = imc_decode_frame,
 +    .flush          = flush,
      .capabilities   = CODEC_CAP_DR1,
      .long_name      = NULL_IF_CONFIG_SMALL("IAC (Indeo Audio Coder)"),
      .sample_fmts    = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_FLTP,
                                                        AV_SAMPLE_FMT_NONE },
  };
 +#endif