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

marco subversion at mplayerhq.hu
Wed Aug 8 15:11:32 CEST 2007


Author: marco
Date: Wed Aug  8 15:11:31 2007
New Revision: 631

Log:
added interpolation code, disabled because it doesn't work yet. fixed some bugs so the output is viewable

Modified:
   dirac/libavcodec/dirac.c

Modified: dirac/libavcodec/dirac.c
==============================================================================
--- dirac/libavcodec/dirac.c	(original)
+++ dirac/libavcodec/dirac.c	Wed Aug  8 15:11:31 2007
@@ -273,6 +273,13 @@ typedef struct DiracContext {
     uint32_t ref1;            ///< first reference picture
     uint32_t ref2;            ///< second reference picture
 
+    uint8_t *ref1data;
+    int ref1width;
+    int ref1height;
+    uint8_t *ref2data;
+    int ref2width;
+    int ref2height;
+
     /* Current component.  */
     int padded_width;         ///< padded width of the current component
     int padded_height;        ///< padded height of the current component
@@ -1834,21 +1841,106 @@ static int reference_frame_idx(AVCodecCo
     return -1;
 }
 
-static int upconvert(AVFrame *refframe, int width, int height,
+static void interpolate_frame_halfpel(AVFrame *refframe, int width, int height,
+                                      uint8_t *pixels, int comp) {
+    uint8_t *lineout;
+    uint8_t *linein;
+    int x, y;
+    const int t[5] = { 167, -56, 25, -11, 3 };
+
+    /* Copy even lines.  */
+    lineout = pixels;
+    linein = refframe->data[comp];
+    for (y = 0; y < height; y++) {
+        for (x = 0; x < width; x++)
+            lineout[x * 2] = linein[x];
+
+        /* Skip one line, we are copying to even lines.  */
+        lineout += width * 2;
+
+        linein += refframe->linesize[comp];
+    }
+
+    /* Interpolate odd lines.  */
+    lineout = pixels + width;
+    linein = refframe->data[comp];
+    for (y = 0; y < height; y++) {
+        for (x = 0; x < width; x++) {
+            int i;
+            int val = 0;
+
+            for (i = 0; i <= 4; i++) {
+                int ypos;
+                ypos = ((y - 1) >> 1) - i;
+
+                /* XXX: Instead of clipping, it would be better to
+                   break up the loop and handle the last lines as a
+                   special case.  */
+                val += t[i] * pixels[av_clip(ypos, 0, height - 1)
+                                     * refframe->linesize[comp] + x];
+                ypos = ((y + 1) >> 1) + i;
+                val += t[i] * pixels[av_clip(ypos, 0, height - 1)
+                                     * refframe->linesize[comp] + x];
+            }
+
+            val += 128;
+            val >>= 8;
+            lineout[x * 2] = av_clip_uint8(val);
+        }
+
+        /* Skip one line, we are copying to odd lines.  */
+        lineout += width * 2;
+
+        linein += refframe->linesize[comp];
+    }
+
+    /* At this place the even rows of pixels are in place, no copying
+       is required..  */
+
+    /* Interpolate the odd rows of pixels.  */
+    lineout = pixels;
+    linein  = pixels;
+    for (y = 0; y < height; y++) {
+        for (x = 1; x < width * 2; x += 2) {
+            int i;
+            int val = 0;
+
+            for (i = 0; i <= 4; i++) {
+                int xpos;
+                xpos = ((x - 1) >> 1) - i;
+                /* The data that is called `ref2' in the specification
+                   is stored in the even rows.  */
+                xpos <<= 1;
+                val += t[i] * linein[av_clip(xpos, 0, width - 1)];
+
+                xpos = ((x + 1) >> 1) + i;
+                /* The data that is called `ref2' in the specification
+                   is stored in the even rows.  */
+                xpos <<= 1;
+                val += t[i] * linein[av_clip(xpos, 0, width - 1)];
+            }
+
+            val += 128;
+            val >>= 8;
+            lineout[x] = av_clip_uint8(val);
+        }
+        lineout += width;
+        linein  += width;
+    }
+}
+
+static int upconvert(uint8_t *refframe, int width, int height,
                             int x, int y, int comp) {
     int xpos;
     int ypos;
-    uint8_t *frame = refframe->data[comp];
 
-    xpos = av_clip(x, 0, width  * 2);
-    ypos = av_clip(y, 0, height * 2);
+    xpos = av_clip(x, 0, width);
+    ypos = av_clip(y, 0, height);
 
-    /* XXX: This isn't proper interpolation, but it has to do for
-       now... */
-    return frame[(xpos >> 1) + (ypos >> 1) * refframe->linesize[comp]];
+    return refframe[xpos + ypos * width];
 }
 
-static int motion_comp_blockpred(AVCodecContext *avctx, AVFrame *refframe,
+static int motion_comp_blockpred(AVCodecContext *avctx, uint8_t *refframe,
                                  int ref, struct dirac_blockmotion *currblock,
                                  int x, int y, int width, int height,
                                  int comp) {
@@ -1879,9 +1971,6 @@ static int motion_comp_blockpred(AVCodec
             vect[1] >>= 1;
     }
 
-    /* XXX: Hack */
-    s->frame_decoding.mv_precision = 0;
-
     if (s->frame_decoding.mv_precision > 0) {
         px = (x << s->frame_decoding.mv_precision) + vect[0];
         py = (y << s->frame_decoding.mv_precision) + vect[1];
@@ -1890,14 +1979,14 @@ static int motion_comp_blockpred(AVCodec
         py = (y + vect[1]) << 1;
     }
 
-    /* Upconversion.  */
-    if (s->frame_decoding.mv_precision == 0
-        || s->frame_decoding.mv_precision == 1)
-        return upconvert(refframe, width, height, px, py, comp);
-
-    dprintf(avctx, "unsupported precision\n");
+    /* Set to 1 to disable interpolation.  */
+#if 1
+    px >>= s->frame_decoding.mv_precision;
+    py >>= s->frame_decoding.mv_precision;
+#endif
 
-    return 0;
+    /* Upconversion.  */
+    return upconvert(refframe, width, height, px, py, comp);
 }
 
 static inline int spatial_wt(int i, int x, int bsep, int blen,
@@ -1981,22 +2070,22 @@ static int motion_comp(AVCodecContext *a
                 val  =  currblock->dc[comp];
                 val  <<= s->frame_decoding.picture_weight_precision;
             } else if (currblock->use_ref[0]) {
-                val  =  motion_comp_blockpred(avctx, ref1, 0, currblock,
-                                              x, y, width, height, comp);
+                val  =  motion_comp_blockpred(avctx, s->ref1data, 0, currblock,
+                                              x, y, s->ref1width, s->ref1height, comp);
                 val  *= (s->frame_decoding.picture_weight_ref1
                         + s->frame_decoding.picture_weight_ref2);
             } else if (currblock->use_ref[1]) {
-                val  =  motion_comp_blockpred(avctx, ref2, 1, currblock,
-                                              x, y, width, height, comp);
+                val  =  motion_comp_blockpred(avctx, s->ref2data, 1, currblock,
+                                              x, y, s->ref2width, s->ref2height, comp);
                 val  *= (s->frame_decoding.picture_weight_ref1
                         + s->frame_decoding.picture_weight_ref2);
             } else {
                 int val1, val2;
-                val1 =  motion_comp_blockpred(avctx, ref1, 0, currblock,
-                                              x, y, width, height, comp);
+                val1 =  motion_comp_blockpred(avctx, s->ref1data, 0, currblock,
+                                              x, y, s->ref1width, s->ref1height, comp);
                 val1 *= s->frame_decoding.picture_weight_ref1;
-                val2 =  motion_comp_blockpred(avctx, ref1, 0, currblock,
-                                              x, y, width, height, comp);
+                val2 =  motion_comp_blockpred(avctx, s->ref2data, 1, currblock,
+                                              x, y, s->ref2width, s->ref2height, comp);
                 val2 *= s->frame_decoding.picture_weight_ref2;
                 val = val1 + val2;
             }
@@ -2027,13 +2116,64 @@ static int dirac_motion_compensation(AVC
 
     }
 
+    /* Set to 1 to enable interpolation code.  */
+#if 0
+    /* XXX: Quarter and eight pel interpolation is not yet
+       supported.  */
+    if (s->frame_decoding.mv_precision > 1)
+        s->frame_decoding.mv_precision = 1;
+
     refidx1 = reference_frame_idx(avctx, s->ref1);
     ref1 = &s->refframes[refidx1];
+    switch (s->frame_decoding.mv_precision) {
+    case 0:
+
+        /* XXX: Why is halfpel prediction used for precision 0?  */
+    case 1:
+        s->ref1width = width << 1;
+        s->ref1height = width << 1;
+        s->ref1data = av_malloc(s->ref1width * s->ref1height);
+        interpolate_frame_halfpel(ref1, width, height, s->ref1data, comp);
+    }
+
+    /* XXX: somehow merge with the code above.  */
     if (s->refs == 2) {
         refidx2 = reference_frame_idx(avctx, s->ref2);
         ref2 = &s->refframes[refidx2];
+
+        switch (s->frame_decoding.mv_precision) {
+        case 0:
+            /* XXX: Why is halfpel prediction used for precision 0?  */
+        case 1:
+            s->ref2width = width << 1;
+            s->ref2height = width << 1;
+            s->ref2data = av_malloc(s->ref2width * s->ref2height);
+            interpolate_frame_halfpel(ref1, width, height, s->ref2data, comp);
+        }
     }
+    else
+        s->ref2data = NULL;
+#else
+    refidx1 = reference_frame_idx(avctx, s->ref1);
+    ref1 = &s->refframes[refidx1];
+
+    s->ref1width  = ref1->linesize[comp];
+    s->ref1height = height;
+    s->ref1data   = ref1->data[comp];
+
+    if (s->refs == 2) {
+        refidx2 = reference_frame_idx(avctx, s->ref2);
+        ref2 = &s->refframes[refidx2];
+        s->ref2width  = ref2->linesize[comp];
+        s->ref2height = height;
+        s->ref2data   = ref2->data[comp];
+    }
+#endif
 
+    /* XXX: It might be more efficient to loop over the blocks,
+       because for every blocks all the parameters are the same.  For
+       now this code just copies the behavior as described in the
+       specificaiton.  */
     for (y = 0; y < height; y++)
         for (x = 0; x < width; x++) {
             coeffs[y * s->padded_width + x] += motion_comp(avctx, x, y,
@@ -2041,6 +2181,12 @@ static int dirac_motion_compensation(AVC
                                                            coeffs, comp);
         }
 
+    /* Set to 1 to enable interpolation code.  */
+#if 0
+    av_free(s->ref1data);
+    av_free(s->ref2data);
+#endif
+
     return 0;
 }
 



More information about the FFmpeg-soc mailing list