diff alsdec.c @ 11148:2d2780630361 libavcodec

Support arithmetic decoding in ALS.
author thilo.borgmann
date Sat, 13 Feb 2010 18:24:13 +0000
parents 327019a2d156
children 625a076b8038
line wrap: on
line diff
--- a/alsdec.c	Sat Feb 13 18:23:46 2010 +0000
+++ b/alsdec.c	Sat Feb 13 18:24:13 2010 +0000
@@ -34,6 +34,7 @@
 #include "unary.h"
 #include "mpeg4audio.h"
 #include "bytestream.h"
+#include "bgmc.h"
 
 #include <stdint.h>
 
@@ -120,6 +121,28 @@
 };
 
 
+/** Tail codes used in arithmetic coding using block Gilbert-Moore codes.
+ */
+static const uint8_t tail_code[16][6] = {
+    { 74, 44, 25, 13,  7, 3},
+    { 68, 42, 24, 13,  7, 3},
+    { 58, 39, 23, 13,  7, 3},
+    {126, 70, 37, 19, 10, 5},
+    {132, 70, 37, 20, 10, 5},
+    {124, 70, 38, 20, 10, 5},
+    {120, 69, 37, 20, 11, 5},
+    {116, 67, 37, 20, 11, 5},
+    {108, 66, 36, 20, 10, 5},
+    {102, 62, 36, 20, 10, 5},
+    { 88, 58, 34, 19, 10, 5},
+    {162, 89, 49, 25, 13, 7},
+    {156, 87, 49, 26, 14, 7},
+    {150, 86, 47, 26, 14, 7},
+    {142, 84, 47, 26, 14, 7},
+    {131, 79, 46, 26, 14, 7}
+};
+
+
 enum RA_Flag {
     RA_FLAG_NONE,
     RA_FLAG_FRAMES,
@@ -169,6 +192,8 @@
     unsigned int frame_id;          ///< the frame ID / number of the current frame
     unsigned int js_switch;         ///< if true, joint-stereo decoding is enforced
     unsigned int num_blocks;        ///< number of blocks used in the current frame
+    uint8_t *bgmc_lut;              ///< pointer at lookup tables used for BGMC
+    unsigned int *bgmc_lut_status;  ///< pointer at lookup table status flags used for BGMC
     int ltp_lag_length;             ///< number of bits used for ltp lag value
     int *use_ltp;                   ///< contains use_ltp flags for all channels
     int *ltp_lag;                   ///< contains ltp lag values for all channels
@@ -383,7 +408,6 @@
     }
 
     MISSING_ERR(sconf->floating,             "Floating point decoding",     -1);
-    MISSING_ERR(sconf->bgmc,                 "BGMC entropy decoding",       -1);
     MISSING_ERR(sconf->rlslms,               "Adaptive RLS-LMS prediction", -1);
     MISSING_ERR(sconf->chan_sort,            "Channel sorting",              0);
 
@@ -554,11 +578,13 @@
     GetBitContext *gb        = &ctx->gb;
     unsigned int k;
     unsigned int s[8];
+    unsigned int sx[8];
     unsigned int sub_blocks, log2_sub_blocks, sb_length;
     unsigned int start      = 0;
     unsigned int opt_order;
     int          sb;
     int32_t      *quant_cof = bd->quant_cof;
+    int32_t      *current_res;
 
 
     // ensure variable block decoding by reusing this field
@@ -591,9 +617,15 @@
 
     sb_length = bd->block_length >> log2_sub_blocks;
 
+    if (sconf->bgmc) {
+        s[0] = get_bits(gb, 8 + (sconf->resolution > 1));
+        for (k = 1; k < sub_blocks; k++)
+            s[k] = s[k - 1] + decode_rice(gb, 2);
 
-    if (sconf->bgmc) {
-        // TODO: BGMC mode
+        for (k = 0; k < sub_blocks; k++) {
+            sx[k]   = s[k] & 0x0F;
+            s [k] >>= 4;
+        }
     } else {
         s[0] = get_bits(gb, 4 + (sconf->resolution > 1));
         for (k = 1; k < sub_blocks; k++)
@@ -697,9 +729,76 @@
 
     // read all residuals
     if (sconf->bgmc) {
-        // TODO: BGMC mode
+        unsigned int delta[sub_blocks];
+        unsigned int k    [sub_blocks];
+        unsigned int b = av_clip((av_ceil_log2(bd->block_length) - 3) >> 1, 0, 5);
+        unsigned int i = start;
+
+        // read most significant bits
+        unsigned int high;
+        unsigned int low;
+        unsigned int value;
+
+        ff_bgmc_decode_init(gb, &high, &low, &value);
+
+        current_res = bd->raw_samples + start;
+
+        for (sb = 0; sb < sub_blocks; sb++, i = 0) {
+            k    [sb] = s[sb] > b ? s[sb] - b : 0;
+            delta[sb] = 5 - s[sb] + k[sb];
+
+            ff_bgmc_decode(gb, sb_length, current_res,
+                        delta[sb], sx[sb], &high, &low, &value, ctx->bgmc_lut, ctx->bgmc_lut_status);
+
+            current_res += sb_length;
+        }
+
+        ff_bgmc_decode_end(gb);
+
+
+        // read least significant bits and tails
+        i = start;
+        current_res = bd->raw_samples + start;
+
+        for (sb = 0; sb < sub_blocks; sb++, i = 0) {
+            unsigned int cur_tail_code = tail_code[sx[sb]][delta[sb]];
+            unsigned int cur_k         = k[sb];
+            unsigned int cur_s         = s[sb];
+
+            for (; i < sb_length; i++) {
+                int32_t res = *current_res;
+
+                if (res == cur_tail_code) {
+                    unsigned int max_msb =   (2 + (sx[sb] > 2) + (sx[sb] > 10))
+                                          << (5 - delta[sb]);
+
+                    res = decode_rice(gb, cur_s);
+
+                    if (res >= 0) {
+                        res += (max_msb    ) << cur_k;
+                    } else {
+                        res -= (max_msb - 1) << cur_k;
+                    }
+                } else {
+                    if (res > cur_tail_code)
+                        res--;
+
+                    if (res & 1)
+                        res = -res;
+
+                    res >>= 1;
+
+                    if (cur_k) {
+                        res <<= cur_k;
+                        res  |= get_bits_long(gb, cur_k);
+                    }
+                }
+
+            *current_res++ = res;
+            }
+        }
     } else {
-        int32_t *current_res = bd->raw_samples + start;
+        current_res = bd->raw_samples + start;
 
         for (sb = 0; sb < sub_blocks; sb++, start = 0)
             for (; start < sb_length; start++)
@@ -1348,6 +1447,8 @@
 
     av_freep(&ctx->sconf.chan_pos);
 
+    ff_bgmc_end(&ctx->bgmc_lut, &ctx->bgmc_lut_status);
+
     av_freep(&ctx->use_ltp);
     av_freep(&ctx->ltp_lag);
     av_freep(&ctx->ltp_gain);
@@ -1395,6 +1496,9 @@
         return -1;
     }
 
+    if (sconf->bgmc)
+        ff_bgmc_init(avctx, &ctx->bgmc_lut, &ctx->bgmc_lut_status);
+
     if (sconf->floating) {
         avctx->sample_fmt          = SAMPLE_FMT_FLT;
         avctx->bits_per_raw_sample = 32;