[FFmpeg-cvslog] r14770 - in trunk/libavcodec: aac.c aac.h

superdump subversion
Fri Aug 15 02:05:09 CEST 2008


Author: superdump
Date: Fri Aug 15 02:05:09 2008
New Revision: 14770

Log:
More OKed sections of AAC decoder code


Modified:
   trunk/libavcodec/aac.c
   trunk/libavcodec/aac.h

Modified: trunk/libavcodec/aac.c
==============================================================================
--- trunk/libavcodec/aac.c	(original)
+++ trunk/libavcodec/aac.c	Fri Aug 15 02:05:09 2008
@@ -100,6 +100,53 @@ static VLC vlc_spectral[11];
 
 
 /**
+ * Configure output channel order based on the current program configuration element.
+ *
+ * @param   che_pos current channel position configuration
+ * @param   new_che_pos New channel position configuration - we only do something if it differs from the current one.
+ *
+ * @return  Returns error status. 0 - OK, !0 - error
+ */
+static int output_configure(AACContext *ac, enum ChannelPosition che_pos[4][MAX_ELEM_ID],
+        enum ChannelPosition new_che_pos[4][MAX_ELEM_ID]) {
+    AVCodecContext *avctx = ac->avccontext;
+    int i, type, channels = 0;
+
+    if(!memcmp(che_pos, new_che_pos, 4 * MAX_ELEM_ID * sizeof(new_che_pos[0][0])))
+        return 0; /* no change */
+
+    memcpy(che_pos, new_che_pos, 4 * MAX_ELEM_ID * sizeof(new_che_pos[0][0]));
+
+    /* Allocate or free elements depending on if they are in the
+     * current program configuration.
+     *
+     * Set up default 1:1 output mapping.
+     *
+     * For a 5.1 stream the output order will be:
+     *    [ Front Left ] [ Front Right ] [ Center ] [ LFE ] [ Surround Left ] [ Surround Right ]
+     */
+
+    for(i = 0; i < MAX_ELEM_ID; i++) {
+        for(type = 0; type < 4; type++) {
+            if(che_pos[type][i]) {
+                if(!ac->che[type][i] && !(ac->che[type][i] = av_mallocz(sizeof(ChannelElement))))
+                    return AVERROR(ENOMEM);
+                if(type != TYPE_CCE) {
+                    ac->output_data[channels++] = ac->che[type][i]->ch[0].ret;
+                    if(type == TYPE_CPE) {
+                        ac->output_data[channels++] = ac->che[type][i]->ch[1].ret;
+                    }
+                }
+            } else
+                av_freep(&ac->che[type][i]);
+        }
+    }
+
+    avctx->channels = channels;
+    return 0;
+}
+
+/**
  * Decode an array of 4 bit element IDs, optionally interleaved with a stereo/mono switching bit.
  *
  * @param cpe_map Stereo (Channel Pair Element) map, NULL if stereo bit is not present.
@@ -209,6 +256,17 @@ static int set_default_channel_config(AA
     return 0;
 }
 
+/**
+ * Decode GA "General Audio" specific configuration; reference: table 4.1.
+ *
+ * @return  Returns error status. 0 - OK, !0 - error
+ */
+static int decode_ga_specific_config(AACContext * ac, GetBitContext * gb, int channel_config) {
+    enum ChannelPosition new_che_pos[4][MAX_ELEM_ID];
+    int extension_flag, ret;
+
+    if(get_bits1(gb)) {  // frameLengthFlag
+        av_log_missing_feature(ac->avccontext, "960/120 MDCT window is", 1);
         return -1;
     }
 
@@ -289,6 +347,17 @@ static int decode_audio_specific_config(
     return 0;
 }
 
+/**
+ * linear congruential pseudorandom number generator
+ *
+ * @param   previous_val    pointer to the current state of the generator
+ *
+ * @return  Returns a 32-bit pseudorandom integer
+ */
+static av_always_inline int lcg_random(int previous_val) {
+    return previous_val * 1664525 + 1013904223;
+}
+
 static av_cold int aac_decode_init(AVCodecContext * avccontext) {
     AACContext * ac = avccontext->priv_data;
     int i;
@@ -381,6 +450,21 @@ static int decode_ics_info(AACContext * 
     ics->num_window_groups = 1;
     ics->group_len[0] = 1;
 
+        if (get_bits1(gb)) {
+            av_log_missing_feature(ac->avccontext, "Predictor bit set but LTP is", 1);
+            memset(ics, 0, sizeof(IndividualChannelStream));
+            return -1;
+        }
+    }
+
+    if(ics->max_sfb > ics->num_swb) {
+        av_log(ac->avccontext, AV_LOG_ERROR,
+            "Number of scalefactor bands in group (%d) exceeds limit (%d).\n",
+            ics->max_sfb, ics->num_swb);
+        memset(ics, 0, sizeof(IndividualChannelStream));
+        return -1;
+    }
+
     return 0;
 }
 
@@ -520,6 +604,14 @@ static void decode_pulses(Pulse * pulse,
  */
 static void decode_mid_side_stereo(ChannelElement * cpe, GetBitContext * gb,
         int ms_present) {
+    int idx;
+    if (ms_present == 1) {
+        for (idx = 0; idx < cpe->ch[0].ics.num_window_groups * cpe->ch[0].ics.max_sfb; idx++)
+            cpe->ms_mask[idx] = get_bits1(gb);
+    } else if (ms_present == 2) {
+        memset(cpe->ms_mask, 1, cpe->ch[0].ics.num_window_groups * cpe->ch[0].ics.max_sfb * sizeof(cpe->ms_mask[0]));
+    }
+}
 
 /**
  * Add pulses with particular amplitudes to the quantized spectral data; reference: 4.6.3.3.
@@ -635,6 +727,64 @@ static int decode_cpe(AACContext * ac, G
     return 0;
 }
 
+    coup->coupling_point = 2*get_bits1(gb);
+    coup->num_coupled = get_bits(gb, 3);
+    for (c = 0; c <= coup->num_coupled; c++) {
+        num_gain++;
+        coup->type[c] = get_bits1(gb) ? TYPE_CPE : TYPE_SCE;
+        coup->id_select[c] = get_bits(gb, 4);
+        if (coup->type[c] == TYPE_CPE) {
+            coup->ch_select[c] = get_bits(gb, 2);
+            if (coup->ch_select[c] == 3)
+                num_gain++;
+        } else
+            coup->ch_select[c] = 1;
+    }
+    coup->coupling_point += get_bits1(gb);
+
+    if (coup->coupling_point == 2) {
+        av_log(ac->avccontext, AV_LOG_ERROR,
+            "Independently switched CCE with 'invalid' domain signalled.\n");
+        memset(coup, 0, sizeof(ChannelCoupling));
+        return -1;
+    }
+
+    sign = get_bits(gb, 1);
+    scale = pow(2., pow(2., get_bits(gb, 2) - 3));
+
+    if ((ret = decode_ics(ac, sce, gb, 0, 0)))
+        return ret;
+
+    for (c = 0; c < num_gain; c++) {
+        int cge = 1;
+        int gain = 0;
+        float gain_cache = 1.;
+        if (c) {
+            cge = coup->coupling_point == AFTER_IMDCT ? 1 : get_bits1(gb);
+            gain = cge ? get_vlc2(gb, vlc_scalefactors.table, 7, 3) - 60: 0;
+            gain_cache = pow(scale, gain);
+        }
+        for (g = 0; g < sce->ics.num_window_groups; g++)
+            for (sfb = 0; sfb < sce->ics.max_sfb; sfb++, idx++)
+                if (sce->band_type[idx] != ZERO_BT) {
+                    if (!cge) {
+                        int t = get_vlc2(gb, vlc_scalefactors.table, 7, 3) - 60;
+                        if (t) {
+                            int s = 1;
+                            if (sign) {
+                                s  -= 2 * (t & 0x1);
+                                t >>= 1;
+                            }
+                            gain += t;
+                            gain_cache = pow(scale, gain) * s;
+                        }
+                    }
+                    coup->gain[c][idx] = gain_cache;
+                }
+    }
+    return 0;
+}
+
 /**
  * Decode Spectral Band Replication extension data; reference: table 4.55.
  *
@@ -651,6 +801,23 @@ static int decode_sbr_extension(AACConte
 }
 
 /**
+ * Parse whether channels are to be excluded from Dynamic Range Compression; reference: table 4.53.
+ *
+ * @return  Returns number of bytes consumed.
+ */
+static int decode_drc_channel_exclusions(DynamicRangeControl *che_drc, GetBitContext * gb) {
+    int i;
+    int num_excl_chan = 0;
+
+    do {
+        for (i = 0; i < 7; i++)
+            che_drc->exclude_mask[num_excl_chan++] = get_bits1(gb);
+    } while (num_excl_chan < MAX_CHANNELS - 7 && get_bits1(gb));
+
+    return num_excl_chan / 7;
+}
+
+/**
  * Decode dynamic range information; reference: table 4.52.
  *
  * @param   cnt length of TYPE_FIL syntactic element in bytes
@@ -746,6 +913,55 @@ static void imdct_and_windowing(AACConte
     float * buf = ac->buf_mdct;
     int i;
 
+    if (ics->window_sequence[0] == EIGHT_SHORT_SEQUENCE) {
+        if (ics->window_sequence[1] == ONLY_LONG_SEQUENCE || ics->window_sequence[1] == LONG_STOP_SEQUENCE)
+            av_log(ac->avccontext, AV_LOG_WARNING,
+                   "Transition from an ONLY_LONG or LONG_STOP to an EIGHT_SHORT sequence detected. "
+                   "If you heard an audible artifact, please submit the sample to the FFmpeg developers.\n");
+        for (i = 0; i < 2048; i += 256) {
+            ff_imdct_calc(&ac->mdct_small, buf + i, in + i/2);
+            ac->dsp.vector_fmul_reverse(ac->revers + i/2, buf + i + 128, swindow, 128);
+        }
+        for (i = 0; i < 448; i++)   out[i] = saved[i] + ac->add_bias;
+
+        ac->dsp.vector_fmul_add_add(out + 448 + 0*128, buf + 0*128, swindow_prev, saved + 448 ,       ac->add_bias, 128, 1);
+        ac->dsp.vector_fmul_add_add(out + 448 + 1*128, buf + 2*128, swindow,      ac->revers + 0*128, ac->add_bias, 128, 1);
+        ac->dsp.vector_fmul_add_add(out + 448 + 2*128, buf + 4*128, swindow,      ac->revers + 1*128, ac->add_bias, 128, 1);
+        ac->dsp.vector_fmul_add_add(out + 448 + 3*128, buf + 6*128, swindow,      ac->revers + 2*128, ac->add_bias, 128, 1);
+        ac->dsp.vector_fmul_add_add(out + 448 + 4*128, buf + 8*128, swindow,      ac->revers + 3*128, ac->add_bias,  64, 1);
+
+#if 0
+        vector_fmul_add_add_add(&ac->dsp, out + 448 + 1*128, buf + 2*128, swindow,      saved + 448 + 1*128, ac->revers + 0*128, ac->add_bias, 128);
+        vector_fmul_add_add_add(&ac->dsp, out + 448 + 2*128, buf + 4*128, swindow,      saved + 448 + 2*128, ac->revers + 1*128, ac->add_bias, 128);
+        vector_fmul_add_add_add(&ac->dsp, out + 448 + 3*128, buf + 6*128, swindow,      saved + 448 + 3*128, ac->revers + 2*128, ac->add_bias, 128);
+        vector_fmul_add_add_add(&ac->dsp, out + 448 + 4*128, buf + 8*128, swindow,      saved + 448 + 4*128, ac->revers + 3*128, ac->add_bias, 64);
+#endif
+
+        ac->dsp.vector_fmul_add_add(saved,       buf + 1024 + 64,    swindow + 64, ac->revers + 3*128+64,  0, 64, 1);
+        ac->dsp.vector_fmul_add_add(saved + 64,  buf + 1024 + 2*128, swindow,      ac->revers + 4*128,     0, 128, 1);
+        ac->dsp.vector_fmul_add_add(saved + 192, buf + 1024 + 4*128, swindow,      ac->revers + 5*128,     0, 128, 1);
+        ac->dsp.vector_fmul_add_add(saved + 320, buf + 1024 + 6*128, swindow,      ac->revers + 6*128,     0, 128, 1);
+        memcpy(                     saved + 448, ac->revers + 7*128, 128 * sizeof(float));
+        memset(                     saved + 576, 0,                  448 * sizeof(float));
+    } else {
+        ff_imdct_calc(&ac->mdct, buf, in);
+        if (ics->window_sequence[0] == LONG_STOP_SEQUENCE) {
+            for (i = 0;   i < 448;  i++)   out[i] =          saved[i] + ac->add_bias;
+            ac->dsp.vector_fmul_add_add(out + 448, buf + 448, swindow_prev, saved + 448, ac->add_bias, 128, 1);
+            for (i = 576; i < 1024; i++)   out[i] = buf[i] + saved[i] + ac->add_bias;
+        } else {
+            ac->dsp.vector_fmul_add_add(out, buf, lwindow_prev, saved, ac->add_bias, 1024, 1);
+        }
+        if (ics->window_sequence[0] == LONG_START_SEQUENCE) {
+            memcpy(saved, buf + 1024, 448 * sizeof(float));
+            ac->dsp.vector_fmul_reverse(saved + 448, buf + 1024 + 448, swindow, 128);
+            memset(saved + 576, 0, 448 * sizeof(float));
+        } else {
+            ac->dsp.vector_fmul_reverse(saved, buf + 1024, lwindow, 1024);
+        }
+    }
+}
+
 /**
  * Apply dependent channel coupling (applied before IMDCT).
  *
@@ -789,6 +1005,91 @@ static void apply_independent_coupling(A
         sce->ret[i] += cc->coup.gain[index][0] * (cc->ch[0].ret[i] - ac->add_bias);
 }
 
+            }
+        }
+    }
+}
+
+static int aac_decode_frame(AVCodecContext * avccontext, void * data, int * data_size, const uint8_t * buf, int buf_size) {
+    AACContext * ac = avccontext->priv_data;
+    GetBitContext gb;
+    enum RawDataBlockType elem_type;
+    int err, elem_id, data_size_tmp;
+
+    init_get_bits(&gb, buf, buf_size*8);
+
+    // parse
+    while ((elem_type = get_bits(&gb, 3)) != TYPE_END) {
+        elem_id = get_bits(&gb, 4);
+        err = -1;
+
+        if(elem_type == TYPE_SCE && elem_id == 1 &&
+                !ac->che[TYPE_SCE][elem_id] && ac->che[TYPE_LFE][0]) {
+            /* Some streams incorrectly code 5.1 audio as SCE[0] CPE[0] CPE[1] SCE[1]
+               instead of SCE[0] CPE[0] CPE[0] LFE[0]. If we seem to have
+               encountered such a stream, transfer the LFE[0] element to SCE[1] */
+            ac->che[TYPE_SCE][elem_id] = ac->che[TYPE_LFE][0];
+            ac->che[TYPE_LFE][0] = NULL;
+        }
+        if(elem_type && elem_type < TYPE_DSE) {
+            if(!ac->che[elem_type][elem_id])
+                return -1;
+            if(elem_type != TYPE_CCE)
+                ac->che[elem_type][elem_id]->coup.coupling_point = 4;
+        }
+
+        switch (elem_type) {
+
+        case TYPE_SCE:
+            err = decode_ics(ac, &ac->che[TYPE_SCE][elem_id]->ch[0], &gb, 0, 0);
+            break;
+
+        case TYPE_CPE:
+            err = decode_cpe(ac, &gb, elem_id);
+            break;
+
+        case TYPE_CCE:
+            err = decode_cce(ac, &gb, ac->che[TYPE_SCE][elem_id]);
+            break;
+
+        case TYPE_LFE:
+            err = decode_ics(ac, &ac->che[TYPE_LFE][elem_id]->ch[0], &gb, 0, 0);
+            break;
+
+        case TYPE_DSE:
+            skip_data_stream_element(&gb);
+            err = 0;
+            break;
+
+        case TYPE_PCE:
+        {
+            enum ChannelPosition new_che_pos[4][MAX_ELEM_ID];
+            memset(new_che_pos, 0, 4 * MAX_ELEM_ID * sizeof(new_che_pos[0][0]));
+            if((err = decode_pce(ac, new_che_pos, &gb)))
+                break;
+            err = output_configure(ac, ac->che_pos, new_che_pos);
+            break;
+        }
+
+        case TYPE_FIL:
+            if (elem_id == 15)
+                elem_id += get_bits(&gb, 8) - 1;
+            while (elem_id > 0)
+                elem_id -= decode_extension_payload(ac, &gb, elem_id);
+            err = 0; /* FIXME */
+            break;
+
+        default:
+            err = -1; /* should not happen, but keeps compiler happy */
+            break;
+        }
+
+        if(err)
+            return err;
+    }
+
+    spectral_to_sample(ac);
+
     if (!ac->is_saved) {
         ac->is_saved = 1;
         *data_size = 0;

Modified: trunk/libavcodec/aac.h
==============================================================================
--- trunk/libavcodec/aac.h	(original)
+++ trunk/libavcodec/aac.h	Fri Aug 15 02:05:09 2008
@@ -135,6 +135,17 @@ enum CouplingPoint {
 /**
  * Individual Channel Stream
  */
+typedef struct {
+    uint8_t max_sfb;            ///< number of scalefactor bands per group
+    enum WindowSequence window_sequence[2];
+    uint8_t use_kb_window[2];   ///< If set, use Kaiser-Bessel window, otherwise use a sinus window.
+    int num_window_groups;
+    uint8_t group_len[8];
+    const uint16_t *swb_offset; ///< table of offsets to the lowest spectral coefficient of a scalefactor band, sfb, for a particular window
+    int num_swb;                ///< number of scalefactor window bands
+    int num_windows;
+    int tns_max_bands;
+} IndividualChannelStream;
 
 /**
  * Dynamic Range Control - decoded from the bitstream but not processed further.
@@ -163,6 +174,41 @@ typedef struct {
  * coupling parameters
  */
 typedef struct {
+    enum CouplingPoint coupling_point;  ///< The point during decoding at which coupling is applied.
+    int num_coupled;       ///< number of target elements
+    enum RawDataBlockType type[8];   ///< Type of channel element to be coupled - SCE or CPE.
+    int id_select[8];      ///< element id
+    int ch_select[8];      /**< [0] shared list of gains; [1] list of gains for left channel;
+                            *   [2] list of gains for right channel; [3] lists of gains for both channels
+                            */
+    float gain[16][120];
+} ChannelCoupling;
+
+/**
+ * Single Channel Element - used for both SCE and LFE elements.
+ */
+typedef struct {
+    IndividualChannelStream ics;
+    TemporalNoiseShaping tns;
+    enum BandType band_type[120];             ///< band types
+    int band_type_run_end[120];               ///< band type run end points
+    float sf[120];                            ///< scalefactors
+    DECLARE_ALIGNED_16(float, coeffs[1024]);  ///< coefficients for IMDCT
+    DECLARE_ALIGNED_16(float, saved[1024]);   ///< overlap
+    DECLARE_ALIGNED_16(float, ret[1024]);     ///< PCM output
+} SingleChannelElement;
+
+/**
+ * channel element - generic struct for SCE/CPE/CCE/LFE
+ */
+typedef struct {
+    // CPE specific
+    uint8_t ms_mask[120];     ///< Set if mid/side stereo is used for each scalefactor window band
+    // shared
+    SingleChannelElement ch[2];
+    // CCE specific
+    ChannelCoupling coup;
+} ChannelElement;
 
 /**
  * main AAC context




More information about the ffmpeg-cvslog mailing list