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

marco subversion at mplayerhq.hu
Mon Jul 23 18:01:17 CEST 2007


Author: marco
Date: Mon Jul 23 18:01:17 2007
New Revision: 508

Log:
Add idwt for intra frames.  Intra frames can be fully decoded now. This code is still very ugly and inefficient.


Modified:
   dirac/dirac.c

Modified: dirac/dirac.c
==============================================================================
--- dirac/dirac.c	(original)
+++ dirac/dirac.c	Mon Jul 23 18:01:17 2007
@@ -899,6 +899,188 @@ static void decode_component(AVCodecCont
     }
  }
 
+static void dirac_subband_idwt(AVCodecContext *avctx, int *data, int level) {
+    DiracContext *s = avctx->priv_data;
+    int *synth;
+    int x, y;
+    int width = subband_width(avctx, level);
+    int height = subband_height(avctx, level);
+    int synth_width = width  << 1;
+    int synth_height = height << 1;
+
+    /* XXX: This should be removed, the reordering should be done in
+       place.  */
+    synth = av_malloc(synth_width * synth_height * sizeof(int));
+
+    /* XXX */
+#define POSX(x) FFMAX(0, FFMIN(x, synth_width - 1))
+#define POSY(y) FFMAX(0, FFMIN(y, synth_height - 1))
+#define POS(x, y) (POSX(x) + POSY(y) * synth_width)
+
+    /* Reorder the coefficients.  */
+    for (y = 0; y < height; y++)
+        for (x = 0; x < width; x++) {
+            synth[POS(2*x, 2*y)] =
+                data[coeff_posy(avctx, level, subband_ll, y)
+                     * s->padded_width + coeff_posx(avctx, level, subband_ll, x)];
+
+            synth[POS(2*x + 1, 2*y)] =
+                data[coeff_posy(avctx, level, subband_hl, y)
+                     * s->padded_width + coeff_posx(avctx, level, subband_hl, x)];
+
+            synth[POS(2*x, 2*y + 1)] =
+                data[coeff_posy(avctx, level, subband_lh, y)
+                     * s->padded_width + coeff_posx(avctx, level, subband_lh, x)];
+
+            synth[POS(2*x + 1, 2*y + 1)] =
+                data[coeff_posy(avctx, level, subband_hh, y)
+                     * s->padded_width + coeff_posx(avctx, level, subband_hh, x)];
+        }
+
+
+    /* Deslauriers(9,5)
+       First lifting step)
+       Even, predict, s=5, t_{-1}=-1, t_0=9, t_1=9, t_2=-1:
+         A[2*n]   -= (-A[2*n-1] + A[2*n+1] + 2) >> 2
+
+       Second lifting step)
+       Odd, update, s=5, t_{-1}=-1, t_0=9, t_1=9, t_2=-1:
+         A[2*n+1] += (-A[2*n-2] + 9*A[2*n] + 9*A[2*n+2] + A[2*n+4] + 8) >> 4
+    */
+
+    /* XXX: This code looks a lot like that of the reference
+       implementation.  for some reason they used exceptions for the
+       borders.  Either this does not match the spec, or I am
+       misunderstanding something.  So for now just do what the
+       reference implementation does and check with the BBC.  */
+
+    /* Vertical synthesis: Lifting stage 1.  */
+    /* Middle.  */
+    for (y = height-1; y > 0; y--) {
+        for (x = synth_width - 1; x >= 0; x--) {
+            synth[POS(x, 2*y)] -= (    synth[POS(x, 2*y - 1)]
+                                     + synth[POS(x, 2*y + 1)]
+                                     + 2) >> 2;
+        }
+    }
+
+    /* Top line.  */
+    for (x = synth_width - 1; x >= 0; x--) {
+        synth[POS(x, 0)] -= (    synth[POS(x, 1)]
+                               + synth[POS(x, 1)]
+                               + 2) >> 2;
+    }
+
+
+    /* Lifting stage 2.  */
+    /* Bottom lines.  */
+    for (x = synth_width-1; x >= 0; x--) {
+            synth[POS(x, synth_height-1)] += (-synth[POS(x, synth_height-2)]
+                                         + 9 * synth[POS(x, synth_height-2)]
+                                         + 9 * synth[POS(x, synth_height-2)]
+                                         -     synth[POS(x, synth_height-4)]
+                                         + 8) >> 4;
+            synth[POS(x, synth_height-3)] += (-synth[POS(x, synth_height-2)]
+                                         + 9 * synth[POS(x, synth_height-4)]
+                                         + 9 * synth[POS(x, synth_height-2)]
+                                         -     synth[POS(x, synth_height-6)]
+                                         + 8) >> 4;
+    }
+
+    /* Middle.  */
+    for (y = height-3; y > 0; y--) {
+        for (x = synth_width-1; x >= 0; x--) {
+            synth[POS(x, 2*y + 1)] += (     -synth[POS(x, 2*y - 2)]
+                                       + 9 * synth[POS(x, 2*y)]
+                                       + 9 * synth[POS(x, 2*y + 2)]
+                                       -     synth[POS(x, 2*y + 4)]
+                                       + 8) >> 4;
+        }
+    }
+
+    /* Top.  */
+    for (x = synth_width-1; x >= 0; x--) {
+            synth[POS(x, 1)] += (             -synth[POS(x, 0)]
+                                         + 9 * synth[POS(x, 2)]
+                                         + 9 * synth[POS(x, 0)]
+                                         -     synth[POS(x, 4)]
+                                         + 8) >> 4;
+    }
+
+    /* Horizontal synthesis.  */
+    for (y = synth_height-1; y >= 0; y--) {
+        /* Lifting stage 1.  */
+        /* Middle.  */
+        for (x = width-1; x > 0; x--) {
+            synth[POS(2*x, y)] -= (    synth[POS(2*x - 1, y)]
+                                     + synth[POS(2*x + 1, y)]
+                                     + 2) >> 2;
+        }
+
+        /* Top line.  */
+        synth[POS(0, y)] -= (    synth[POS(1, y)]
+                               + synth[POS(1, y)]
+                               + 2) >> 2;
+
+        /* Lifting stage 2.  */
+        /* Bottom lines.  */
+        synth[POS(synth_width - 1, y)] += (     -synth[POS(synth_width-2, y)]
+                                     + 9 * synth[POS(synth_width-2, y)]
+                                     + 9 * synth[POS(synth_width-2, y)]
+                                     -     synth[POS(synth_width-4, y)]
+                                     + 8) >> 4;
+        synth[POS(synth_width - 3, y)] += (     -synth[POS(synth_width-6, y)]
+                                     + 9 * synth[POS(synth_width-4, y)]
+                                     + 9 * synth[POS(synth_width-2, y)]
+                                     -     synth[POS(synth_width-2, y)]
+                                     + 8) >> 4;
+
+        /* Middle.  */
+        for (x = width-3; x > 0; x--) {
+            synth[POS(2*x + 1, y)] += (     -synth[POS(2*x - 2, y)]
+                                       + 9 * synth[POS(2*x, y)]
+                                       + 9 * synth[POS(2*x + 2, y)]
+                                       -     synth[POS(2*x + 4, y)]
+                                       + 8) >> 4;
+        }
+
+        /* Top line.  */
+        synth[POS(1, y)] += (               -synth[POS(0, y)]
+                                       + 9 * synth[POS(2, y)]
+                                       + 9 * synth[POS(0, y)]
+                                       -     synth[POS(4, y)]
+                                       + 8) >> 4;
+    }
+
+    /* Shift away one bit that was use for additional precision.  */
+    for (y = 0; y < synth_height; y++)
+        for (x = 0; x < synth_width; x++)
+            synth[x + y * synth_width] =
+                (synth[x + y * synth_width] + (1 << (1-1))) >> 1;
+
+    /* Make the LL subband for level+1  */
+    for (y = 0; y < synth_height; y++) {
+        for (x = 0; x < synth_width; x++) {
+            data[x + y * s->padded_width] = synth[x + y * synth_width];
+        }
+    }
+
+    av_free(synth);
+}
+
+
+static int dirac_idwt(AVCodecContext *avctx, int *coeffs) {
+    int level;
+    DiracContext *s = avctx->priv_data;
+
+    /* XXX: The spec starts with level 0.  Most likely a bug in the
+       spec.  */
+    for (level = 1; level <= s->frame_decoding.wavelet_depth; level++)
+        dirac_subband_idwt(avctx, coeffs, level);
+
+    return 0;
+}
+
 static int decode_intra_frame(AVCodecContext *avctx) {
     DiracContext *s = avctx->priv_data;
     int comp;
@@ -926,6 +1108,8 @@ static int decode_intra_frame(AVCodecCon
 
         decode_component(avctx, coeffs);
 
+        dirac_idwt(avctx, coeffs);
+
         /* XXX: Show the coefficients in a frame.  */
         for (x = 0; x < s->padded_width; x++)
             for (y = 0; y < s->padded_height; y++)



More information about the FFmpeg-soc mailing list