[FFmpeg-soc] [soc]: r789 - in dirac/libavcodec: dirac_arith.c dirac_arith.h

marco subversion at mplayerhq.hu
Tue Aug 14 22:00:34 CEST 2007


Author: marco
Date: Tue Aug 14 22:00:34 2007
New Revision: 789

Log:
add support for arithmetic coding

Modified:
   dirac/libavcodec/dirac_arith.c
   dirac/libavcodec/dirac_arith.h

Modified: dirac/libavcodec/dirac_arith.c
==============================================================================
--- dirac/libavcodec/dirac_arith.c	(original)
+++ dirac/libavcodec/dirac_arith.c	Tue Aug 14 22:00:34 2007
@@ -62,6 +62,18 @@ static unsigned int arith_lookup[256] = 
     805, 750,   690,  625,  553,  471,  376,  255
 };
 
+static void dirac_arith_init_common(dirac_arith_state_t arith) {
+    int i;
+
+    arith->low = 0;
+    arith->range = 0x10000;
+
+    /* Initialize contexts.  */
+    for (i = 0; i < ARITH_CONTEXT_COUNT; i++) {
+        arith->contexts[i] = 0x8000;
+    }
+}
+
 /**
  * Initialize arithmetic decoding
  *
@@ -71,19 +83,21 @@ static unsigned int arith_lookup[256] = 
  */
 void dirac_arith_init (dirac_arith_state_t arith,
                        GetBitContext *gb, int length) {
-    int i;
-
     align_get_bits(gb);
+    arith->pb = NULL;
     arith->bits_left = 8 * length - 16;
-    arith->low = 0;
-    arith->range = 0x10000;
     arith->code = get_bits_long(gb, 16);
     arith->gb = gb;
 
-    /* Initialize contexts.  */
-    for (i = 0; i < ARITH_CONTEXT_COUNT; i++) {
-        arith->contexts[i] = 0x8000;
-    }
+    dirac_arith_init_common(arith);
+}
+
+void dirac_arith_coder_init(dirac_arith_state_t arith, PutBitContext *pb) {
+    arith->pb = pb;
+    arith->carry = 0;
+    arith->gb = NULL;
+
+    dirac_arith_init_common(arith);
 }
 
 /**
@@ -100,6 +114,8 @@ int dirac_arith_get_bit (dirac_arith_sta
     unsigned int range_times_prob;
     unsigned int ret;
 
+    assert(!arith->pb);
+
     count = arith->code - arith->low;
     range_times_prob = (arith->range * prob_zero) >> 16;
     if (count >= range_times_prob) {
@@ -140,6 +156,43 @@ int dirac_arith_get_bit (dirac_arith_sta
     return ret;
 }
 
+void dirac_arith_put_bit(dirac_arith_state_t arith, int bit, int context) {
+    PutBitContext *pb = arith->pb;
+    unsigned int prob_zero = arith->contexts[context];
+
+    assert(!arith->gb);
+
+    if (bit == 0) {
+        arith->range  = (arith->range * prob_zero) >> 16;
+    } else {
+        arith->low   += (arith->range * prob_zero) >> 16;
+        arith->range -= (arith->range * prob_zero) >> 16;
+    }
+
+    /* Update contexts. */
+    if (bit)
+        arith->contexts[context] -= arith_lookup[arith->contexts[context] >> 8];
+    else
+        arith->contexts[context] += arith_lookup[255 - (arith->contexts[context] >> 8)];
+
+    /* Renormalisation and output.  */
+    while (arith->range <= 0x4000) {
+        if (((arith->low + arith->range - 1)^arith->low) >= 0x8000) {
+            arith->low ^= 0x4000;
+            arith->carry++;
+        } else {
+            put_bits(pb, 1, (arith->low >> 15)&1);
+            while (arith->carry > 0) {
+                put_bits(pb, 1, !((arith->low >> 15)&1));
+                arith->carry--;
+            }
+        }
+        arith->low   <<= 1;
+        arith->range <<= 1;
+        arith->low    &= 0xFFFF;
+    }
+}
+
 static unsigned inline int follow_context (int index,
                                            struct dirac_arith_context_set *context_set) {
     int pos;
@@ -187,6 +240,45 @@ int dirac_arith_read_int (dirac_arith_st
  * initialized length.
  */
 void dirac_arith_flush(dirac_arith_state_t arith) {
+    assert(!arith->pb);
     skip_bits_long(arith->gb, arith->bits_left);
     arith->bits_left = 0;
 }
+
+void dirac_arith_coder_flush(dirac_arith_state_t arith) {
+    int i;
+    int rem;
+    assert(!arith->gb);
+
+    /* Output remaining resolved msbs.  */
+    while (((arith->low + arith->range - 1)^arith->low) < 0x8000) {
+        put_bits(arith->pb, 1, (arith->low >> 15)&1);
+        while (arith->carry > 0) {
+            put_bits(arith->pb, 1, !((arith->low >> 15)&1));
+            arith->carry--;
+        }
+        arith->low   <<= 1;
+        arith->low    &= 0xFFFF;
+        arith->range <<= 1;
+    }
+
+    /* Resolve remaining straddle conditions.  */
+    while ((arith->low & 0x4000)
+           && !((arith->low + arith->range - 1) & 0x4000)) {
+        arith->carry++;
+        arith->low    ^= 0x4000;
+        arith->low   <<= 1;
+        arith->range <<= 1;
+        arith->low    &= 0xFFFF;
+    }
+
+    /* Discharge carry bits.  */
+    put_bits(arith->pb, 1, (arith->low >> 14)&1);
+    for (i = 0; i <= arith->carry; i++)
+        put_bits(arith->pb, 1, !((arith->low >> 14)&1));
+
+    /* Add padding bits.  */
+    rem = 8 - (put_bits_count(arith->pb) % 8);
+    for (i = 0; i < rem; i++)
+        put_bits(arith->pb, 1, 0);
+}

Modified: dirac/libavcodec/dirac_arith.h
==============================================================================
--- dirac/libavcodec/dirac_arith.h	(original)
+++ dirac/libavcodec/dirac_arith.h	Tue Aug 14 22:00:34 2007
@@ -78,9 +78,11 @@ typedef struct dirac_arith_state {
     unsigned int range;
     unsigned int code;
     unsigned int bits_left;
+    int carry;
     unsigned int contexts[ARITH_CONTEXT_COUNT];
 
     GetBitContext *gb;
+    PutBitContext *pb;
 } *dirac_arith_state_t;
 
 struct dirac_arith_context_set {
@@ -93,8 +95,12 @@ struct dirac_arith_context_set {
 void dirac_arith_init (dirac_arith_state_t arith,
                        GetBitContext *gb, int length);
 
+void dirac_arith_coder_init(dirac_arith_state_t arith, PutBitContext *pb);
+
 int dirac_arith_get_bit (dirac_arith_state_t arith, int context);
 
+void dirac_arith_put_bit(dirac_arith_state_t arith, int bit, int context);
+
 unsigned int dirac_arith_read_uint (dirac_arith_state_t arith,
                                     struct dirac_arith_context_set *context_set);
 
@@ -102,3 +108,5 @@ int dirac_arith_read_int (dirac_arith_st
                           struct dirac_arith_context_set *context_set);
 
 void dirac_arith_flush(dirac_arith_state_t arith);
+
+void dirac_arith_coder_flush(dirac_arith_state_t arith);



More information about the FFmpeg-soc mailing list