[FFmpeg-soc] [soc]: r453 - dirac/dirac.c

marco subversion at mplayerhq.hu
Tue Jul 17 17:21:21 CEST 2007


Author: marco
Date: Tue Jul 17 17:21:21 2007
New Revision: 453

Log:
Finished coefficient unpacking for intra frames. This fully works for the Y component now.
The other components, dequantizing and a full cleanup are missing.


Modified:
   dirac/dirac.c

Modified: dirac/dirac.c
==============================================================================
--- dirac/dirac.c	(original)
+++ dirac/dirac.c	Tue Jul 17 17:21:21 2007
@@ -553,7 +553,8 @@ static void arith_init (AVCodecContext *
     int i;
 
     align_get_bits(gb);
-    arith_bits_left = 8 * length;
+    /* XXX: Double check this with the spec!  */
+    arith_bits_left = 8 * length - 16;
     arith_low = 0;
     arith_range = 0x10000;
     arith_code = get_bits_long(gb, 16);
@@ -577,6 +578,10 @@ static void arith_renormalize (GetBitCon
         arith_code |= get_bits (gb, 1);
         arith_bits_left--;
     }
+    else {
+        /* Get default: */
+        arith_code |= 1;
+    }
     arith_code &= 0xffff;
 }
 
@@ -655,7 +660,7 @@ struct context_set context_sets_waveletc
         /* Parent = 0, Zero neighbourhood, sign predict 0 */
         .follow = { ARITH_CONTEXT_ZPZN_F1, ARITH_CONTEXT_ZP_F2,
                     ARITH_CONTEXT_ZP_F3, ARITH_CONTEXT_ZP_F4,
-                    ARITH_CONTEXT_ZP_F5, ARITH_CONTEXT_ZP_F6, 0 },
+                    ARITH_CONTEXT_ZP_F5, ARITH_CONTEXT_ZP_F6 },
         .follow_length = 6,
         .data = ARITH_CONTEXT_COEFF_DATA,
         .sign = ARITH_CONTEXT_SIGN_ZERO,
@@ -760,7 +765,7 @@ struct context_set context_sets_waveletc
 static unsigned int follow_context (int index, struct context_set *context_set) {
     int pos;
     pos = (index < context_set->follow_length ? index
-           : context_set->follow_length) - 1;
+           : context_set->follow_length - 1);
     return context_set->follow[pos];
 }
 
@@ -824,16 +829,16 @@ static int inline coeff_posy(AVCodecCont
 
 static int zero_neighbourhood(AVCodecContext *avctx, int *data, int level,
                               subband_t orientation, int v, int h) {
-    int x = coeff_posx(avctx, level, orientation, v);
-    int y = coeff_posy(avctx, level, orientation, h);
+    int x = coeff_posx(avctx, level, orientation, h);
+    int y = coeff_posy(avctx, level, orientation, v);
     DiracContext *s = avctx->priv_data;
 
     /* Check if there is a zero to the left and top left of this
        coefficient.  */
-    if (v > 0 && (data[x + y * s->padded_width - 1]
+    if (v > 0 && ((data[x + (y - 1) * s->padded_width])
                   || ( h > 0 && data[x + (y - 1) * s->padded_width - 1])))
         return 0;
-    else if  (h > 0 && data[x + (y - 1) * s->padded_width])
+    else if  (h > 0 && data[x + y * s->padded_width - 1])
         return 0;
     /* XXX: The behavior above is used in the standard, but seems a
        bit broken to me.  Either I am wrong or I am, double check!  */
@@ -842,8 +847,8 @@ static int zero_neighbourhood(AVCodecCon
 
 static int sign_predict(AVCodecContext *avctx, int *data, int level,
                         subband_t orientation, int v, int h) {
-    int x = coeff_posx(avctx, level - 1, orientation, v >> 1);
-    int y = coeff_posy(avctx, level - 1, orientation, h >> 1);
+    int x = coeff_posx(avctx, level, orientation, h);
+    int y = coeff_posy(avctx, level, orientation, v);
     DiracContext *s = avctx->priv_data;
 
     switch (orientation) {
@@ -853,13 +858,17 @@ static int sign_predict(AVCodecContext *
     case subband_hl:
         if (v == 0)
             return 0;
-        else
+        else {
+            if (data[x + (y - 1) * s->padded_width] == 0) return 0;
             return (data[x + (y - 1) * s->padded_width] < 0) ? -1 : 1;
+        }
     case subband_lh:
         if (h == 0)
             return 0;
-        else
+        else {
+            if (data[x + y * s->padded_width - 1] == 0) return 0;
             return (data[x + y * s->padded_width - 1] < 0) ? -1 : 1;
+        }
     }
 
     return 0;
@@ -878,12 +887,18 @@ static void coeff_unpack(AVCodecContext 
 
     /* The value of the pixel belonging to the lower level.  */
     if (level >= 2) {
-        int x = coeff_posx(avctx, level - 1, orientation, v >> 1);
-        int y = coeff_posy(avctx, level - 1, orientation, h >> 1);
-        parent = data[s->padded_width * y + x];
+        int x = coeff_posx(avctx, level - 1, orientation, h >> 1);
+        int y = coeff_posy(avctx, level - 1, orientation, v >> 1);
+        parent = data[s->padded_width * y + x] != 0;
     }
 
-    /* Determine if the pixel has a zero in its neighbourhood.  */
+    /* XXX: this is what the reference implementation effectively
+       does, although this does not seem to comply with the spec.  I
+       have asked the Dirac BBC why this seems to be required.  */
+    if (level < 2)
+        parent = 1;
+
+    /* Determine if the pixel has only zeros in its neighbourhood.  */
     nhood = zero_neighbourhood(avctx, data, level, orientation, v, h);
 
     sign_pred = sign_predict(avctx, data, level, orientation, v, h);
@@ -898,8 +913,8 @@ static void coeff_unpack(AVCodecContext 
     context = &context_sets_waveletcoeff[idx];
 
     coeff = arith_read_int(s->gb, context);
-    vdata = coeff_posx(avctx, level, orientation, v);
-    hdata = coeff_posy(avctx, level, orientation, h);
+    vdata = coeff_posy(avctx, level, orientation, v);
+    hdata = coeff_posx(avctx, level, orientation, h);
     data[hdata + vdata * s->padded_width] = coeff;
 }
 
@@ -910,24 +925,25 @@ static void codeblock(AVCodecContext *av
     int blockcnt = s->codeblocksh[level] * s->codeblocksv[level];
     int zero = 0;
 
-    int bottom = (subband_width(avctx, level) * x) / s->codeblocksh[level];
-    int top = (subband_width(avctx, level) * (x + 1)) / s->codeblocksh[level];
-    int left = (subband_height(avctx, level) * y) / s->codeblocksv[level];
-    int right = (subband_height(avctx, level) * (y + 1)) / s->codeblocksv[level];
+    int left = (subband_width(avctx, level) * x) / s->codeblocksh[level];
+    int right = (subband_width(avctx, level) * (x + 1)) / s->codeblocksh[level];
+    int top = (subband_height(avctx, level) * y) / s->codeblocksv[level];
+    int bottom = (subband_height(avctx, level) * (y + 1)) / s->codeblocksv[level];
 
     int v, h;
 
-    if (blockcnt != 1) {
+    if (blockcnt != 1 && orientation != subband_ll) {
         /* Determine if this codeblock is a zero block.  */
         zero = arith_get_bit(gb, ARITH_CONTEXT_ZERO_BLOCK);
     }
 
-    dprintf(avctx, "Zero: %d\n", zero);
     if (zero)
         return; /* All coefficients remain 0.  */
 
-    for (v = bottom; v > top; v--)
-        for (h = right; h > left; h--)
+    /* XXX: This matches the reference implementation, check the
+       spec.  */
+    for (v = top; v < bottom; v++)
+        for (h = left; h < right; h++)
             coeff_unpack(avctx, data, level, orientation, v, h);
 
     /* XXX: Quantization.  */
@@ -940,8 +956,8 @@ static void intra_dc_prediction(AVCodecC
 
     for (v = 0; v < subband_width(avctx, 0); v++)
         for (h = 0; h < subband_height(avctx, 0); h++) {
-            int x = coeff_posx(avctx, level, orientation, v);
-            int y = coeff_posy(avctx, level, orientation, h);
+            int x = coeff_posx(avctx, level, orientation, h);
+            int y = coeff_posy(avctx, level, orientation, v);
 
             if (h > 0) {
                 if (v > 0) {
@@ -972,19 +988,13 @@ static int subband(AVCodecContext *avctx
     int quant;
     int x, y;
 
-    dprintf(avctx, "Subband level: %d, width: %d, height: %d, orientation: %d\n",
-            level, subband_width(avctx, level), subband_height(avctx, level), orientation);
     length = dirac_golomb(gb);
     if (! length)
         {
             align_get_bits(gb);
-            dprintf (avctx, "Zero subband\n");
-
-            return 0;
         } else {
             quant = dirac_golomb(gb);
 
-            dprintf(avctx, "Length: %d, quant: %d\n", length, quant);
             arith_init(avctx, gb, length);
 
             for (y = 0; y < s->codeblocksv[level]; y++)
@@ -1058,7 +1068,6 @@ static int decode_intra_frame(AVCodecCon
     dprintf(avctx, "width: %d, height: %d, padded width: %d, padded height: %d\n",
             width, height, s->padded_width, s->padded_height);
 
-
    /* Align for coefficient bitstream.  */
     align_get_bits(gb);
 
@@ -1068,15 +1077,12 @@ static int decode_intra_frame(AVCodecCon
     /* Unpack all other subbands.  */
     for (level = 1; level <= s->frame_decoding.wavelet_depth; level++) {
         /* Unpack HL, level i.  */
-        align_get_bits(gb);
         subband(avctx, coeffs, level, width, height, subband_hl);
 
         /* Unpack LH, level i.  */
-        align_get_bits(gb);
         subband(avctx, coeffs, level, width, height, subband_lh);
 
         /* Unpack HH, level i.  */
-        align_get_bits(gb);
         subband(avctx, coeffs, level, width, height, subband_hh);
     }
 
@@ -1158,8 +1164,8 @@ static int parse_frame(AVCodecContext *a
             /* Set defaults for the codeblocks.  */
             /* XXX: Hardcoded for intra frames.  */
             for (i = 0; i <= s->frame_decoding.wavelet_depth; i++) {
-                s->codeblocksh[i] = i <= 2 ? 1 : 3;
-                s->codeblocksv[i] = i <= 2 ? 1 : 4;
+                s->codeblocksh[i] = i <= 2 ? 1 : 4;
+                s->codeblocksv[i] = i <= 2 ? 1 : 3;
                 dprintf(avctx, "codeblock size level=%d, v=%d, h=%d\n", i,
                         s->codeblocksv[i], s->codeblocksh[i]);
 



More information about the FFmpeg-soc mailing list