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

marco subversion at mplayerhq.hu
Fri Aug 31 22:54:20 CEST 2007


Author: marco
Date: Fri Aug 31 22:54:20 2007
New Revision: 1270

Log:
add padding around the reference frame so border checks can be avoided

Modified:
   dirac/libavcodec/dirac.c

Modified: dirac/libavcodec/dirac.c
==============================================================================
--- dirac/libavcodec/dirac.c	(original)
+++ dirac/libavcodec/dirac.c	Fri Aug 31 22:54:20 2007
@@ -1730,12 +1730,12 @@ static int reference_frame_idx(DiracCont
  */
 static inline void interpolate_frame_halfpel(AVFrame *refframe,
                                       int width, int height,
-                                      uint8_t *pixels, int comp) {
+                                      uint8_t *pixels, int comp, int xpad, int ypad) {
     uint8_t *lineout;
     uint8_t *lineoutodd;
     uint8_t *refdata;
     uint8_t *linein;
-    int outwidth = width * 2;
+    int outwidth = width * 2 + xpad * 4;
     int x, y;
     const int t[5] = { 167, -56, 25, -11, 3 };
 
@@ -1743,8 +1743,8 @@ START_TIMER
 
     refdata    = refframe->data[comp];
 
-    lineout    = pixels;
-    lineoutodd = pixels + outwidth;
+    lineout    = pixels + 2 * ypad * outwidth + 2 * xpad;
+    lineoutodd = lineout + outwidth;
     linein     = refdata;
     /* Top 4 lines.  */
     for (y = 0; y < 5; y++) {
@@ -1877,8 +1877,8 @@ START_TIMER
        is required..  */
 
     /* Interpolate the odd rows of pixels: Left.  */
-    lineout = pixels + 1;
-    linein  = pixels;
+    lineout = pixels + 2 * ypad * outwidth + 2 * xpad + 1;
+    linein  = pixels + 2 * ypad * outwidth + 2 * xpad;
     for (y = 0; y < height * 2; y++) {
         for (x = 0; x < 10; x += 2) {
             uint8_t *li1 = &linein[x];
@@ -1915,10 +1915,10 @@ START_TIMER
     }
 
     /* Middle.  */
-    lineout = pixels + 1;
-    linein  = pixels;
+    lineout = pixels + 2 * ypad * outwidth + 2 * xpad + 1;
+    linein  = pixels + 2 * ypad * outwidth + 2 * xpad;
     for (y = 0; y < height * 2; y++) {
-        for (x = 10; x < outwidth - 12; x += 2) {
+        for (x = 10; x < width * 2 - 12; x += 2) {
             uint8_t *li1 = &linein[x];
             uint8_t *li2 = &linein[x + 2];
             int val = 128;
@@ -1945,35 +1945,35 @@ START_TIMER
     }
 
     /* Right.  */
-    lineout = pixels + 1;
-    linein  = pixels;
+    lineout = pixels + 2 * ypad * outwidth + 2 * xpad + 1;
+    linein  = pixels + 2 * ypad * outwidth + 2 * xpad;
     for (y = 0; y < height * 2; y++) {
-        for (x = outwidth - 12; x < outwidth; x += 2) {
+        for (x = width * 2 - 12; x < width * 2; x += 2) {
             uint8_t *li1 = &linein[x];
             uint8_t *li2 = &linein[x];
             int val = 128;
 
-            if (x < outwidth - 2)
+            if (x < 2 * width - 2)
                 li2 += 2;
             val += t[0] * (*li1 + *li2);
 
             li1 -= 2;
-            if (x < outwidth - 4)
+            if (x < 2 * width - 4)
                 li2 += 2;
             val += t[1] * (*li1 + *li2);
 
             li1 -= 2;
-            if (x < outwidth - 6)
+            if (x < 2 * width - 6)
                 li2 += 2;
             val += t[2] * (*li1 + *li2);
 
             li1 -= 2;
-            if (x < outwidth - 8)
+            if (x < 2 * width - 8)
                 li2 += 2;
             val += t[3] * (*li1 + *li2);
 
             li1 -= 2;
-            if (x < outwidth - 10)
+            if (x < 2 * width - 10)
                 li2 += 2;
             val += t[4] * (*li1 + *li2);
 
@@ -1984,6 +1984,31 @@ START_TIMER
         linein  += outwidth;
     }
 
+    /* Add padding on the left and right sides of the frame.  */
+    lineout = pixels + 2 * ypad * outwidth;
+    for (y = 0; y < height * 2; y++) {
+        memset(lineout, lineout[2 * xpad], 2 * xpad);
+        memset(&lineout[2 * width + xpad * 2],
+               lineout[2 * width + xpad * 2 - 1], 2 * xpad);
+        lineout += outwidth;
+    }
+
+    /* Copy top lines.  */
+    linein  = pixels + 2 * ypad * outwidth;
+    lineout = pixels;
+    for (y = 0; y < ypad * 2; y++) {
+        memcpy(lineout, linein, outwidth);
+        lineout += outwidth;
+    }
+
+    /* Copy bottom lines.  */
+    linein  = pixels + 2 * (ypad + height - 1) * outwidth;
+    lineout = linein + outwidth;
+    for (y = 0; y < ypad * 2; y++) {
+        memcpy(lineout, linein, outwidth);
+        lineout += outwidth;
+    }
+
 STOP_TIMER("halfpel");
 }
 
@@ -2004,7 +2029,7 @@ static inline int get_halfpel(uint8_t *r
     xpos = av_clip(x, 0, width  - 1);
     ypos = av_clip(y, 0, height - 1);
 
-    return refframe[xpos + ypos * width];
+    return refframe[xpos + ypos * weight];
 }
 
 /**
@@ -2067,6 +2092,7 @@ static void motion_comp_block2refs(Dirac
     int rx1, ry1, rx2, ry2;
     const uint8_t *w1 = NULL;
     const uint8_t *w2 = NULL;
+    int xfix1 = 0, xfix2 = 0;
 
 
 START_TIMER
@@ -2130,6 +2156,19 @@ START_TIMER
 
     spatialwt = &s->spatialwt[s->xblen * (ys - ystart)];
 
+    /* Make sure the vector doesn't point to a block outside the
+       padded frame.  */
+    refystart1 = av_clip(refystart1, -s->yblen, s->height * 2 - 1);
+    refystart2 = av_clip(refystart2, -s->yblen, s->height * 2 - 1);
+    if (refxstart1 < -s->xblen)
+        xfix1 = -s->xblen - refxstart1;
+    else if (refxstart1 >= (s->width - 1) * 2)
+        xfix1 = (s->width - 1) * 2 - refxstart1;
+    if (refxstart2 < -s->xblen * 2)
+        xfix2 = -s->xblen * 2 - refxstart2;
+    else if (refxstart2 >= (s->width - 1) * 2)
+        xfix2 = (s->width - 1) * 2 - refxstart2;
+
     line = &coeffs[s->width * ys];
     refline1 = &ref1[refystart1 * s->refwidth];
     refline2 = &ref2[refystart2 * s->refwidth];
@@ -2142,16 +2181,12 @@ START_TIMER
 
             if (s->frame_decoding.mv_precision == 0) {
                 /* No interpolation.  */
-                val1 = get_halfpel(ref1, s->refwidth, s->refheight,
-                                   (x + vect1[0]) << 1, (y + vect1[1]));
-                val2 = get_halfpel(ref2, s->refwidth, s->refheight,
-                                   (x + vect2[0]) << 1, (y + vect2[1]));
+                val1 = refline1[(x + vect1[0]) << 1];
+                val2 = refline2[(x + vect2[0]) << 1];
             } else if (s->frame_decoding.mv_precision == 1) {
                 /* Halfpel interpolation.  */
-                val1 = get_halfpel(ref1, s->refwidth, s->refheight,
-                                   (x << 1) + vect1[0], (y << 1) + vect1[1]);
-                val2 = get_halfpel(ref2, s->refwidth, s->refheight,
-                                   (x << 1) + vect2[0], (y << 1) + vect2[1]);
+                val1 = refline1[(x << 1) + vect1[0]];
+                val2 = refline2[(x << 1) + vect2[0]];
             } else {
                 /* Position in halfpel interpolated frame.  */
                 int hx1, hy1, hx2, hy2;
@@ -2174,34 +2209,22 @@ START_TIMER
                     val2 = 4;
                 }
 
-                /* For val1.  */
-                if (hx1 > 0 && hy1 > 0 && hx1 < (s->refwidth - 1) && hy1 < (s->refheight - 11)) {
+                /* Fix the x position on the halfpel interpolated
+                   frame so it points to a MC block within the padded
+                   region.  */
+                hx1 += xfix1;
+                hx2 += xfix2;
+
                     val1 += w1[0] * refline1[hx1                  ];
                     val1 += w1[1] * refline1[hx1               + 1];
                     val1 += w1[2] * refline1[hx1 + s->refwidth    ];
                     val1 += w1[3] * refline1[hx1 + s->refwidth + 1];
-                } else {
-                    /* Border condition, keep using the slower code.  */
-                    val1 += w1[0] * get_halfpel(ref1, s->refwidth, s->refheight, hx1    , hy1    );
-                    val1 += w1[1] * get_halfpel(ref1, s->refwidth, s->refheight, hx1 + 1, hy1    );
-                    val1 += w1[2] * get_halfpel(ref1, s->refwidth, s->refheight, hx1    , hy1 + 1);
-                    val1 += w1[3] * get_halfpel(ref1, s->refwidth, s->refheight, hx1 + 1, hy1 + 1);
-                }
                 val1 >>= s->frame_decoding.mv_precision;
 
-                /* For val2.  */
-                if (hx2 > 0 && hy2 > 0 && hx2 < (s->refwidth - 1) && hy2 < (s->refheight - 11)) {
                     val2 += w2[0] * refline2[hx2                  ];
                     val2 += w2[1] * refline2[hx2               + 1];
                     val2 += w2[2] * refline2[hx2 + s->refwidth    ];
                     val2 += w2[3] * refline2[hx2 + s->refwidth + 1];
-                } else {
-                    /* Border condition, keep using the slower code.  */
-                    val2 += w2[0] * get_halfpel(ref2, s->refwidth, s->refheight, hx2    , hy2    );
-                    val2 += w2[1] * get_halfpel(ref2, s->refwidth, s->refheight, hx2 + 1, hy2    );
-                    val2 += w2[2] * get_halfpel(ref2, s->refwidth, s->refheight, hx2    , hy2 + 1);
-                    val2 += w2[3] * get_halfpel(ref2, s->refwidth, s->refheight, hx2 + 1, hy2 + 1);
-                }
                 val2 >>= s->frame_decoding.mv_precision;
             }
 
@@ -2262,6 +2285,7 @@ static void motion_comp_block1ref(DiracC
     /* Subhalfpixel in qpel/eighthpel interpolated frame.  */
     int rx, ry;
     const uint8_t *w = NULL;
+    int xfix = 0;
 
 START_TIMER
 
@@ -2304,6 +2328,14 @@ START_TIMER
         return;
     }
 
+    /* Make sure the vector doesn't point to a block outside the
+       padded frame.  */
+    refystart = av_clip(refystart, -s->yblen * 2, s->height * 2 - 1);
+    if (refxstart < -s->xblen * 2)
+        xfix = -s->xblen - refxstart;
+    else if (refxstart >= (s->width - 1) * 2)
+        xfix = (s->width - 1) * 2 - refxstart;
+
     spatialwt = &s->spatialwt[s->xblen * (ys - ystart)];
 
     line = &coeffs[s->width * ys];
@@ -2315,12 +2347,10 @@ START_TIMER
 
             if (s->frame_decoding.mv_precision == 0) {
                 /* No interpolation.  */
-                val = get_halfpel(refframe, s->refwidth, s->refheight,
-                                  (x + vect[0]) << 1, (y + vect[1]) << 1);
+                val = refline[(x + vect[0]) << 1];
             } else if (s->frame_decoding.mv_precision == 1) {
                 /* Halfpel interpolation.  */
-                val = get_halfpel(refframe, s->refwidth, s->refheight,
-                                  (x << 1) + vect[0], (y << 1) + vect[1]);
+                val = refline[(x << 1) + vect[0]];
             } else {
                 /* Position in halfpel interpolated frame.  */
                 int hx, hy;
@@ -2337,20 +2367,15 @@ START_TIMER
                     val = 4;
                 }
 
+                /* Fix the x position on the halfpel interpolated
+                   frame so it points to a MC block within the padded
+                   region.  */
+                hx += xfix;
 
-                if (hx > 0 && hy > 0 && hx < (s->refwidth - 1) && hy < (s->refheight - 11)) {
                     val += w[0] * refline[hx                  ];
                     val += w[1] * refline[hx               + 1];
                     val += w[2] * refline[hx + s->refwidth    ];
                     val += w[3] * refline[hx + s->refwidth + 1];
-                } else {
-                    /* Border condition, keep using the slower code.  */
-                    val += w[0] * get_halfpel(refframe, s->refwidth, s->refheight, hx    , hy    );
-                    val += w[1] * get_halfpel(refframe, s->refwidth, s->refheight, hx + 1, hy    );
-                    val += w[2] * get_halfpel(refframe, s->refwidth, s->refheight, hx    , hy + 1);
-                    val += w[3] * get_halfpel(refframe, s->refwidth, s->refheight, hx + 1, hy + 1);
-                }
-
                 val >>= s->frame_decoding.mv_precision;
             }
 
@@ -2477,8 +2502,8 @@ static int dirac_motion_compensation(Dir
     total_wt_bits = hbits + vbits
                        + s->frame_decoding.picture_weight_precision;
 
-    s->refwidth = s->width << 1;
-    s->refheight = s->height << 1;
+    s->refwidth = (s->width + 2 * s->xblen) << 1;
+    s->refheight = (s->height + 2 * s->yblen) << 1;
 
     s->spatialwt = av_malloc(s->xblen * s->yblen * sizeof(int16_t));
     if (!s->spatialwt) {
@@ -2517,7 +2542,7 @@ static int dirac_motion_compensation(Dir
                 return -1;
             }
             interpolate_frame_halfpel(ref[i], s->width, s->height,
-                                      s->refdata[i], comp);
+                                      s->refdata[i], comp, s->xblen, s->yblen);
         } else {
             s->refdata[i] = s->refframes[refidx[i]].halfpel[comp];
             cacheframe[i] = 2;
@@ -2553,6 +2578,7 @@ static int dirac_motion_compensation(Dir
             for (i = 0; i < s->current_blwidth; i++) {
                 struct dirac_blockmotion *block = &currblock[i];
                 int border;
+                int padding;
 
                 /* XXX: These calculations do not match those in the
                    Dirac specification, but are correct.  */
@@ -2565,6 +2591,9 @@ static int dirac_motion_compensation(Dir
                           && i < s->current_blwidth - 1
                           && j < s->current_blheight - 1);
 
+                padding = 2 * ((s->xblen * 2 + s->width) * 2 * s->yblen
+                               + s->xblen);
+
                 /* Intra */
                 if ((block->use_ref & 3) == 0)
                     motion_comp_dc_block(s, mcpic, i, j,
@@ -2574,19 +2603,19 @@ static int dirac_motion_compensation(Dir
                 else if ((block->use_ref & 3) == DIRAC_REF_MASK_REF1)
                     motion_comp_block1ref(s, mcpic, i, j,
                                           xstart, xstop, ystart,
-                                          ystop,s->refdata[0], 0, block, comp,
+                                          ystop,s->refdata[0] + padding, 0, block, comp,
                                           border);
                 /* Reference frame 2 only.  */
                 else if ((block->use_ref & 3) == DIRAC_REF_MASK_REF2)
                     motion_comp_block1ref(s, mcpic, i, j,
                                           xstart, xstop, ystart, ystop,
-                                          s->refdata[1], 1, block, comp,
+                                          s->refdata[1] + padding, 1, block, comp,
                                           border);
                 /* Both reference frames.  */
                 else
                     motion_comp_block2refs(s, mcpic, i, j,
                                            xstart, xstop, ystart, ystop,
-                                           s->refdata[0], s->refdata[1],
+                                           s->refdata[0] + padding, s->refdata[1] + padding,
                                            block, comp, border);
             }
             currblock += s->blwidth;



More information about the FFmpeg-soc mailing list