changeset 8199:8a8d40fe77d9 libavcodec

AAC: Frequency domain prediction and hence Main profile support Patch by Alex Converse ( alex converse gmail com )
author superdump
date Mon, 24 Nov 2008 00:13:50 +0000
parents de344498875e
children 843d82925adf
files aac.c aac.h aactab.c aactab.h
diffstat 4 files changed, 153 insertions(+), 2 deletions(-) [+]
line wrap: on
line diff
--- a/aac.c	Sun Nov 23 19:36:44 2008 +0000
+++ b/aac.c	Mon Nov 24 00:13:50 2008 +0000
@@ -41,7 +41,7 @@
  * N (code in SoC repo) Long Term Prediction
  * Y                    intensity stereo
  * Y                    channel coupling
- * N                    frequency domain prediction
+ * Y                    frequency domain prediction
  * Y                    Perceptual Noise Substitution
  * Y                    Mid/Side stereo
  * N                    Scalable Inverse AAC Quantization
@@ -331,6 +331,7 @@
     skip_bits_long(&gb, i);
 
     switch (ac->m4ac.object_type) {
+    case AOT_AAC_MAIN:
     case AOT_AAC_LC:
         if (decode_ga_specific_config(ac, &gb, ac->m4ac.chan_config))
             return -1;
@@ -354,6 +355,27 @@
     return previous_val * 1664525 + 1013904223;
 }
 
+static void reset_predict_state(PredictorState * ps) {
+    ps->r0 = 0.0f;
+    ps->r1 = 0.0f;
+    ps->cor0 = 0.0f;
+    ps->cor1 = 0.0f;
+    ps->var0 = 1.0f;
+    ps->var1 = 1.0f;
+}
+
+static void reset_all_predictors(PredictorState * ps) {
+    int i;
+    for (i = 0; i < MAX_PREDICTORS; i++)
+        reset_predict_state(&ps[i]);
+}
+
+static void reset_predictor_group(PredictorState * ps, int group_num) {
+    int i;
+    for (i = group_num-1; i < MAX_PREDICTORS; i+=30)
+        reset_predict_state(&ps[i]);
+}
+
 static av_cold int aac_decode_init(AVCodecContext * avccontext) {
     AACContext * ac = avccontext->priv_data;
     int i;
@@ -432,6 +454,21 @@
     skip_bits_long(gb, 8 * count);
 }
 
+static int decode_prediction(AACContext * ac, IndividualChannelStream * ics, GetBitContext * gb) {
+    int sfb;
+    if (get_bits1(gb)) {
+        ics->predictor_reset_group = get_bits(gb, 5);
+        if (ics->predictor_reset_group == 0 || ics->predictor_reset_group > 30) {
+            av_log(ac->avccontext, AV_LOG_ERROR, "Invalid Predictor Reset Group.\n");
+            return -1;
+        }
+    }
+    for (sfb = 0; sfb < FFMIN(ics->max_sfb, ff_aac_pred_sfb_max[ac->m4ac.sampling_index]); sfb++) {
+        ics->prediction_used[sfb] = get_bits1(gb);
+    }
+    return 0;
+}
+
 /**
  * Decode Individual Channel Stream info; reference: table 4.6.
  *
@@ -464,16 +501,30 @@
         ics->swb_offset    =      swb_offset_128[ac->m4ac.sampling_index];
         ics->num_swb       =  ff_aac_num_swb_128[ac->m4ac.sampling_index];
         ics->tns_max_bands =   tns_max_bands_128[ac->m4ac.sampling_index];
+        ics->predictor_present = 0;
     } else {
         ics->max_sfb       = get_bits(gb, 6);
         ics->num_windows   = 1;
         ics->swb_offset    =     swb_offset_1024[ac->m4ac.sampling_index];
         ics->num_swb       = ff_aac_num_swb_1024[ac->m4ac.sampling_index];
         ics->tns_max_bands =  tns_max_bands_1024[ac->m4ac.sampling_index];
-        if (get_bits1(gb)) {
+        ics->predictor_present = get_bits1(gb);
+        ics->predictor_reset_group = 0;
+        if (ics->predictor_present) {
+            if (ac->m4ac.object_type == AOT_AAC_MAIN) {
+                if (decode_prediction(ac, ics, gb)) {
+                    memset(ics, 0, sizeof(IndividualChannelStream));
+                    return -1;
+                }
+            } else if (ac->m4ac.object_type == AOT_AAC_LC) {
+                av_log(ac->avccontext, AV_LOG_ERROR, "Prediction is not allowed in AAC-LC.\n");
+                memset(ics, 0, sizeof(IndividualChannelStream));
+                return -1;
+            } else {
             av_log_missing_feature(ac->avccontext, "Predictor bit set but LTP is", 1);
             memset(ics, 0, sizeof(IndividualChannelStream));
             return -1;
+            }
         }
     }
 
@@ -786,6 +837,77 @@
     return 0;
 }
 
+static av_always_inline float flt16_round(float pf) {
+    int exp;
+    pf = frexpf(pf, &exp);
+    pf = ldexpf(roundf(ldexpf(pf, 8)), exp-8);
+    return pf;
+}
+
+static av_always_inline float flt16_even(float pf) {
+    int exp;
+    pf = frexpf(pf, &exp);
+    pf = ldexpf(rintf(ldexpf(pf, 8)), exp-8);
+    return pf;
+}
+
+static av_always_inline float flt16_trunc(float pf) {
+    int exp;
+    pf = frexpf(pf, &exp);
+    pf = ldexpf(truncf(ldexpf(pf, 8)), exp-8);
+    return pf;
+}
+
+static void predict(AACContext * ac, PredictorState * ps, float* coef, int output_enable) {
+    const float a     = 0.953125; // 61.0/64
+    const float alpha = 0.90625;  // 29.0/32
+    float e0, e1;
+    float pv;
+    float k1, k2;
+
+    k1 = ps->var0 > 1 ? ps->cor0 * flt16_even(a / ps->var0) : 0;
+    k2 = ps->var1 > 1 ? ps->cor1 * flt16_even(a / ps->var1) : 0;
+
+    pv = flt16_round(k1 * ps->r0 + k2 * ps->r1);
+    if (output_enable)
+        *coef += pv * ac->sf_scale;
+
+    e0 = *coef / ac->sf_scale;
+    e1 = e0 - k1 * ps->r0;
+
+    ps->cor1 = flt16_trunc(alpha * ps->cor1 + ps->r1 * e1);
+    ps->var1 = flt16_trunc(alpha * ps->var1 + 0.5 * (ps->r1 * ps->r1 + e1 * e1));
+    ps->cor0 = flt16_trunc(alpha * ps->cor0 + ps->r0 * e0);
+    ps->var0 = flt16_trunc(alpha * ps->var0 + 0.5 * (ps->r0 * ps->r0 + e0 * e0));
+
+    ps->r1 = flt16_trunc(a * (ps->r0 - k1 * e0));
+    ps->r0 = flt16_trunc(a * e0);
+}
+
+/**
+ * Apply AAC-Main style frequency domain prediction.
+ */
+static void apply_prediction(AACContext * ac, SingleChannelElement * sce) {
+    int sfb, k;
+
+    if (!sce->ics.predictor_initialized) {
+        reset_all_predictors(sce->ics.predictor_state);
+        sce->ics.predictor_initialized = 1;
+    }
+
+    if (sce->ics.window_sequence[0] != EIGHT_SHORT_SEQUENCE) {
+        for (sfb = 0; sfb < ff_aac_pred_sfb_max[ac->m4ac.sampling_index]; sfb++) {
+            for (k = sce->ics.swb_offset[sfb]; k < sce->ics.swb_offset[sfb + 1]; k++) {
+                predict(ac, &sce->ics.predictor_state[k], &sce->coeffs[k],
+                    sce->ics.predictor_present && sce->ics.prediction_used[sfb]);
+            }
+        }
+        if (sce->ics.predictor_reset_group)
+            reset_predictor_group(sce->ics.predictor_state, sce->ics.predictor_reset_group);
+    } else
+        reset_all_predictors(sce->ics.predictor_state);
+}
+
 /**
  * Decode an individual_channel_stream payload; reference: table 4.44.
  *
@@ -840,6 +962,10 @@
 
     if (decode_spectrum_and_dequant(ac, out, gb, sce->sf, pulse_present, &pulse, ics, sce->band_type) < 0)
         return -1;
+
+    if(ac->m4ac.object_type == AOT_AAC_MAIN)
+        apply_prediction(ac, sce);
+
     return 0;
 }
 
--- a/aac.h	Sun Nov 23 19:36:44 2008 +0000
+++ b/aac.h	Mon Nov 24 00:13:50 2008 +0000
@@ -133,6 +133,20 @@
 };
 
 /**
+ * Predictor State
+ */
+typedef struct {
+    float cor0;
+    float cor1;
+    float var0;
+    float var1;
+    float r0;
+    float r1;
+} PredictorState;
+
+#define MAX_PREDICTORS 672
+
+/**
  * Individual Channel Stream
  */
 typedef struct {
@@ -145,6 +159,11 @@
     int num_swb;                ///< number of scalefactor window bands
     int num_windows;
     int tns_max_bands;
+    int predictor_present;
+    int predictor_initialized;
+    int predictor_reset_group;
+    uint8_t prediction_used[41];
+    PredictorState predictor_state[MAX_PREDICTORS];
 } IndividualChannelStream;
 
 /**
--- a/aactab.c	Sun Nov 23 19:36:44 2008 +0000
+++ b/aactab.c	Mon Nov 24 00:13:50 2008 +0000
@@ -43,6 +43,10 @@
     12, 12, 12, 14, 14, 14, 15, 15, 15, 15, 15, 15
 };
 
+const uint8_t ff_aac_pred_sfb_max[] = {
+    33, 33, 38, 40, 40, 40, 41, 41, 37, 37, 37, 34
+};
+
 const uint32_t ff_aac_scalefactor_code[121] = {
     0x3ffe8, 0x3ffe6, 0x3ffe7, 0x3ffe5, 0x7fff5, 0x7fff1, 0x7ffed, 0x7fff6,
     0x7ffee, 0x7ffef, 0x7fff0, 0x7fffc, 0x7fffd, 0x7ffff, 0x7fffe, 0x7fff7,
--- a/aactab.h	Sun Nov 23 19:36:44 2008 +0000
+++ b/aactab.h	Mon Nov 24 00:13:50 2008 +0000
@@ -54,6 +54,8 @@
 extern const uint8_t ff_aac_num_swb_128 [];
 // @}
 
+extern const uint8_t ff_aac_pred_sfb_max [];
+
 extern const uint32_t ff_aac_scalefactor_code[121];
 extern const uint8_t  ff_aac_scalefactor_bits[121];