[FFmpeg-soc] [soc]: r552 - dirac/libavcodec/dirac.c

marco subversion at mplayerhq.hu
Mon Jul 30 11:09:35 CEST 2007


Author: marco
Date: Mon Jul 30 11:09:35 2007
New Revision: 552

Log:
add the LeGall(5,3) IDWT

Modified:
   dirac/libavcodec/dirac.c

Modified: dirac/libavcodec/dirac.c
==============================================================================
--- dirac/libavcodec/dirac.c	(original)
+++ dirac/libavcodec/dirac.c	Mon Jul 30 11:09:35 2007
@@ -1531,14 +1531,52 @@ static void decode_component(AVCodecCont
     }
  }
 
+static void dirac_subband_idwt_reorder(AVCodecContext *avctx, int *data,
+                                       int *synth, int level) {
+    DiracContext *s = avctx->priv_data;
+    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;
+
+#define POSX(x)                av_clip(x, 0, synth_width - 1)
+#define POSY(y)                av_clip(y, 0, 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)];
+        }
+}
+
 /**
- * IDWT transform (9,5) for a specific subband
+ * IDWT transform (5,3) for a specific subband
  *
  * @param data coefficients to transform
  * @param level level of the current transform
  * @return 0 when successful, otherwise -1 is returned
  */
-static int dirac_subband_idwt(AVCodecContext *avctx, int *data, int level) {
+static int dirac_subband_idwt_53(AVCodecContext *avctx, int *data, int level) {
     DiracContext *s = avctx->priv_data;
     int *synth;
     int x, y;
@@ -1547,14 +1585,14 @@ static int dirac_subband_idwt(AVCodecCon
     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));
     if (!synth) {
         av_log(avctx, AV_LOG_ERROR, "av_malloc() failed\n");
         return -1;
     }
 
+    dirac_subband_idwt_reorder(avctx, data, synth, level);
+
 #define POSX(x)                av_clip(x, 0, synth_width - 1)
 #define POSY(y)                av_clip(y, 0, synth_height - 1)
 #define POS(x, y)              (POSX(x) + POSY(y) * synth_width)
@@ -1567,38 +1605,114 @@ static int dirac_subband_idwt(AVCodecCon
 #define VSYNTH_ODD_POS(x, y)  (x + ODD_POSY(y) * synth_width)
 #define HSYNTH_ODD_POS(x, y)  (ODD_POSX(x) + y * synth_width)
 
-    /* Reorder the coefficients.  */
-    for (y = 0; y < height; y++)
+    /* LeGall(5,3)
+       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=1, t_0=1, t_1=1:
+         A[2*n+1] += (A[2*n] + A[2*n+2] + 1) >> 1
+    */
+
+    /* Vertical synthesis: Lifting stage 1.  */
+    for (y = 0; y < height; y++) {
+        for (x = 0; x < synth_width; x++) {
+            synth[POS(x, 2*y)] -= (  synth[VSYNTH_EVEN_POS(x, 2*y - 1)]
+                                   + synth[VSYNTH_EVEN_POS(x, 2*y + 1)]
+                                   + 2) >> 2;
+        }
+    }
+
+    /* Vertical synthesis: Lifting stage 2.  */
+    for (y = 0; y < height; y++) {
+        for (x = 0; x < synth_width; x++) {
+            synth[POS(x, 2*y + 1)] += (  synth[VSYNTH_ODD_POS(x, 2*y)]
+                                       + synth[VSYNTH_ODD_POS(x, 2*y + 2)]
+                                       + 1) >> 1;
+        }
+    }
+
+    /* Horizontal synthesis.  */
+    for (y = 0; y < synth_height; y++) {
+        /* Lifting stage 1.  */
         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, y)] -= (  synth[HSYNTH_EVEN_POS(2*x - 1, y)]
+                                   + synth[HSYNTH_EVEN_POS(2*x + 1, y)]
+                                   + 2) >> 2;
+        }
 
-            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)];
+        /* Lifting stage 2.  */
+        for (x = 0; x < width; x++) {
+            synth[POS(2*x + 1, y)] += (  synth[HSYNTH_ODD_POS(2*x, y)]
+                                       + synth[HSYNTH_ODD_POS(2*x + 2, y)]
+                                       + 1) >> 1;
+        }
+    }
 
-            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)];
+    /* 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;
 
-            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)];
+    /* 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);
 
-    /* Deslauriers(9,5)
+    return 0;
+}
+
+/**
+ * IDWT transform (9,7) for a specific subband
+ *
+ * @param data coefficients to transform
+ * @param level level of the current transform
+ * @return 0 when successful, otherwise -1 is returned
+ */
+static int dirac_subband_idwt_97(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));
+    if (!synth) {
+        av_log(avctx, AV_LOG_ERROR, "av_malloc() failed\n");
+        return -1;
+    }
+
+    dirac_subband_idwt_reorder(avctx, data, synth, level);
+
+#define POSX(x)                av_clip(x, 0, synth_width - 1)
+#define POSY(y)                av_clip(y, 0, synth_height - 1)
+#define POS(x, y)              (POSX(x) + POSY(y) * synth_width)
+#define EVEN_POSX(x)           FFMAX(1, FFMIN(x, synth_width - 1))
+#define EVEN_POSY(y)           FFMAX(1, FFMIN(y, synth_height - 1))
+#define VSYNTH_EVEN_POS(x, y) (x + EVEN_POSY(y) * synth_width)
+#define HSYNTH_EVEN_POS(x, y) (EVEN_POSX(x) + y * synth_width)
+#define ODD_POSX(x)           FFMAX(0, FFMIN(x, synth_width - 2))
+#define ODD_POSY(y)           FFMAX(0, FFMIN(y, synth_height - 2))
+#define VSYNTH_ODD_POS(x, y)  (x + ODD_POSY(y) * synth_width)
+#define HSYNTH_ODD_POS(x, y)  (ODD_POSX(x) + y * synth_width)
+
+    /* Deslauriers(9,7)
        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:
+       Odd, update, s=4, 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
     */
 
@@ -1662,12 +1776,28 @@ static int dirac_subband_idwt(AVCodecCon
 
 static int dirac_idwt(AVCodecContext *avctx, int *coeffs) {
     int level;
+    int wavelet_idx;
     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);
+    for (level = 1; level <= s->frame_decoding.wavelet_depth; level++) {
+        if (s->refs == 0)
+            wavelet_idx = s->frame_decoding.wavelet_idx_intra;
+        else
+            wavelet_idx = s->frame_decoding.wavelet_idx_inter;
+
+        switch(wavelet_idx) {
+        case 0:
+            dirac_subband_idwt_97(avctx, coeffs, level);
+            break;
+        case 1:
+            dirac_subband_idwt_53(avctx, coeffs, level);
+            break;
+        default:
+            av_log(avctx, AV_LOG_INFO, "unknown IDWT index: %d\n", wavelet_idx);
+        }
+    }
 
     return 0;
 }
@@ -1772,7 +1902,7 @@ static int parse_frame(AVCodecContext *a
     /* Override wavelet transform parameters.  */
     if (get_bits(gb, 1)) {
         dprintf(avctx, "Non default filter\n");
-        filter = dirac_get_ue_golomb(gb);
+        filter = dirac_get_ue_golomb(gb); /* XXX */
     } else {
         dprintf(avctx, "Default filter\n");
         filter = s->frame_decoding.wavelet_idx_intra;



More information about the FFmpeg-soc mailing list