videoeditorengine/h263decoder/src/block.cpp
changeset 0 951a5db380a0
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/videoeditorengine/h263decoder/src/block.cpp	Fri Jan 29 14:08:33 2010 +0200
@@ -0,0 +1,1094 @@
+/*
+* Copyright (c) 2010 Ixonos Plc.
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of the "Eclipse Public License v1.0"
+* which accompanies this distribution, and is available
+* at the URL "http://www.eclipse.org/legal/epl-v10.html".
+*
+* Initial Contributors:
+* Nokia Corporation - Initial contribution
+*
+* Contributors:
+* Ixonos Plc
+*
+* Description:  
+* Motion compensation functions.
+*
+*/
+
+
+#include "h263dConfig.h"
+
+#include "block.h"
+
+#include "errcodes.h"
+#include "vdcmvc.h"
+#include "debug.h"
+
+#ifndef blcAssert
+   #define blcAssert assert
+#endif
+#include "blcllcpy.cpp"
+
+/* See the description above. */
+typedef void (* blcCopyBlock_t) (u_char *, u_char *,
+    int, int, int, int, int, int, int, int, int, int, int, int, int);
+
+/* This structure is used to pass a pointer either to blcUVCountRefXY1MV or
+   blcUVCountRefXY4MVs. */
+typedef void (* blcUVCountRefXY_t) 
+   (int, int, int *, int *, int *, int *, int *, int *);
+
+
+/*
+ * Local function prototypes
+ */
+
+static int blcCopyNormalYPredictionMBWith1MV(
+   blcCopyBlock_t copyBlock,
+   int *mvxArray, int *mvyArray, 
+   u_char *dstYBlk,
+   u_char *srcYFrame,
+   int dstYXPos, int dstYYPos, 
+   int dstYXSize,
+   int srcYXSize, int srcYYSize,
+   int fMVsOverPictureBoundaries, 
+   int rcontrol);
+
+static int blcCopyNormalYPredictionMBWith4MVs(
+   blcCopyBlock_t copyBlock,
+   int *mvxArray, int *mvyArray, 
+   u_char *dstYBlk,
+   u_char *srcYFrame,
+   int dstYXPos, int dstYYPos, 
+   int dstYXSize,
+   int srcYXSize, int srcYYSize,
+   int fMVsOverPictureBoundaries, 
+   int rcontrol);
+
+static int blcCopyUVPredictionBlocks(
+   blcUVCountRefXY_t uvCountSourceXY,
+   blcCopyBlock_t copyBlock,
+   int *mvxArray, int *mvyArray, 
+   u_char *dstUBlk, u_char *dstVBlk,
+   u_char *srcUFrame, u_char *srcVFrame, 
+   int dstUVXPos, int dstUVYPos, 
+   int dstUVXSize,
+   int srcUVXSize, int srcUVYSize,
+   int fMVsOverPictureBoundaries, 
+   int rcontrol);
+
+static void blcHandleRefOverPictBoundariesBC(
+   int xBlkSize, int yBlkSize,
+   int xSize, int ySize, 
+   int subpixelX, int subpixelY, 
+   int *sourceX, int *sourceY,
+   int *xlt0, int *xNormal, int *xgtmax, 
+   int *ylt0, int *yNormal, int *ygtmax);
+
+static int blcIsRefOverPictBoundaries(
+   int xBlkSize, int yBlkSize,
+   int xSize, int ySize, 
+   int subpixelX, int subpixelY, 
+   int sourceX, int sourceY);
+
+static void blcUVCountMVOffset4MVs(
+   int *mvxArray, int *mvyArray,
+   int *offsetX, int *offsetY,
+   int *subpixelX, int *subpixelY);
+
+static void blcUVCountRefXY1MV(
+   int origoX, int origoY,
+   int *mvxArray, int *mvyArray, 
+   int *sourceX, int *sourceY,
+   int *subpixelX, int *subpixelY);
+
+static void blcUVCountRefXY4MVs(
+   int origoX, int origoY,
+   int *mvxArray, int *mvyArray, 
+   int *sourceX, int *sourceY,
+   int *subpixelX, int *subpixelY);
+
+static void blcYCountRefXY(
+   int mvxVal, int mvyVal,
+   int destX, int destY, 
+   int *sourceX, int *sourceY,
+   int *subpixelX, int *subpixelY);
+
+
+/*
+ * Module-scope constants
+ */
+
+/* Clipping table to sature values to range 0..255 */
+static const u_char wholeClippingTable[4*256] = {
+        0,   0,   0,   0,   0,   0,   0,
+        0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+        0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+        0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+        0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+        0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+        0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+        0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+        0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+        0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+        0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+        0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+        0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+        0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+        0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+        0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+        0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+        0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+        0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+        0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+        0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+        0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+        0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+        0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+        0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+        0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+        0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+        0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+        0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+        0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+        0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+        0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+        0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+        0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+        0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+        0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+        0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+        0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+        0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+        0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+        0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+        0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+        0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+        0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+        0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+        0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+        0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+        0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+        0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+        0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+        0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+        0,   0,   0,   0,   0,   0,   1,   2,   3,   4,
+        5,   6,   7,   8,   9,  10,  11,  12,  13,  14,
+       15,  16,  17,  18,  19,  20,  21,  22,  23,  24,
+       25,  26,  27,  28,  29,  30,  31,  32,  33,  34,
+       35,  36,  37,  38,  39,  40,  41,  42,  43,  44,
+       45,  46,  47,  48,  49,  50,  51,  52,  53,  54,
+       55,  56,  57,  58,  59,  60,  61,  62,  63,  64,
+       65,  66,  67,  68,  69,  70,  71,  72,  73,  74,
+       75,  76,  77,  78,  79,  80,  81,  82,  83,  84,
+       85,  86,  87,  88,  89,  90,  91,  92,  93,  94,
+       95,  96,  97,  98,  99, 100, 101, 102, 103, 104,
+      105, 106, 107, 108, 109, 110, 111, 112, 113, 114,
+      115, 116, 117, 118, 119, 120, 121, 122, 123, 124,
+      125, 126, 127, 128, 129, 130, 131, 132, 133, 134,
+      135, 136, 137, 138, 139, 140, 141, 142, 143, 144,
+      145, 146, 147, 148, 149, 150, 151, 152, 153, 154,
+      155, 156, 157, 158, 159, 160, 161, 162, 163, 164,
+      165, 166, 167, 168, 169, 170, 171, 172, 173, 174,
+      175, 176, 177, 178, 179, 180, 181, 182, 183, 184,
+      185, 186, 187, 188, 189, 190, 191, 192, 193, 194,
+      195, 196, 197, 198, 199, 200, 201, 202, 203, 204,
+      205, 206, 207, 208, 209, 210, 211, 212, 213, 214,
+      215, 216, 217, 218, 219, 220, 221, 222, 223, 224,
+      225, 226, 227, 228, 229, 230, 231, 232, 233, 234,
+      235, 236, 237, 238, 239, 240, 241, 242, 243, 244,
+      245, 246, 247, 248, 249, 250, 251, 252, 253, 254,
+      255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+      255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+      255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+      255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+      255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+      255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+      255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+      255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+      255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+      255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+      255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+      255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+      255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+      255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+      255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+      255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+      255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+      255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+      255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+      255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+      255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+      255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+      255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+      255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+      255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+      255, 255, 255, 255, 255, 255, 255};
+
+static const u_char * const clippingTable = &wholeClippingTable[512];
+
+
+/*
+ * Global functions
+ */
+
+/* {{-output"blcAddBlock.txt"}} */
+/*
+ * blcAddBlock
+ *    
+ *
+ * Parameters:
+ *    block                block array (of 64 pixels)
+ *    dstBlk               pointer to present frame in the place,
+ *                         where the block is added
+ *    xSize                X size of the frame.
+ *    mbPlace              flag that indicates the place for the current
+ *                         macroblock inside the macroblock row:
+ *                            -1 beginning of row
+ *                             0 middle of row
+ *                             1 end of row
+ *    fourMVs              1 if Advanced Prediction Mode is used, otherwise 0
+ *    prevDiffBlock        if fourMVs == 1 and mbPlace <= 0 the difference
+ *                         block is stored to prevDiffBlock for later use
+ *
+ * Function:
+ *    This function sums the given block into block being currently decoded in
+ *    present frame. Parameters are the table consisting a block, a pointer to
+ *    the frame at the correct place and the width of the frame.
+ *
+ * Returns:
+ *    Nothing.
+ *
+ */
+
+void blcAddBlock(int *block, u_char *dstBlk, int xSize,
+   int mbPlace, u_char fourMVs, int *prevDiffBlock)
+/* {{-output"blcAddBlock.txt"}} */
+{
+   int i;
+
+   if (fourMVs && mbPlace <= 0) {
+       MEMCPY(prevDiffBlock, block, 64 * sizeof(int));
+   }
+   else {
+      for(i = 8; i; i--) {
+         *dstBlk++ = clippingTable[*dstBlk + *block++];
+         *dstBlk++ = clippingTable[*dstBlk + *block++];
+         *dstBlk++ = clippingTable[*dstBlk + *block++];
+         *dstBlk++ = clippingTable[*dstBlk + *block++];
+         *dstBlk++ = clippingTable[*dstBlk + *block++];
+         *dstBlk++ = clippingTable[*dstBlk + *block++];
+         *dstBlk++ = clippingTable[*dstBlk + *block++];
+         *dstBlk++ = clippingTable[*dstBlk + *block++];
+         dstBlk += xSize - 8;
+      }
+   }
+}
+
+
+/* {{-output"blcBlockToFrame.txt"}} */
+/*
+ * blcBlockToFrame
+ *    
+ *
+ * Parameters:
+ *    block        block array (of 64 pixels)
+ *    dstBlk       pointer to present frame in the place, where the block is
+ *                 written
+ *    xSize        X size of the frame.
+ *
+ * Function:
+ *    This function writes the given block into block being currently decoded
+ *    in present frame. Parameters are the table consisting a block, a pointer
+ *    to the frame at the correct place and the width of the frame.
+ *
+ * Returns:
+ *      Nothing.
+ *
+ */
+
+void blcBlockToFrame(int *block, u_char *dstBlk, int xSize)
+/* {{-output"blcBlockToFrame.txt"}} */
+{
+   int i;
+
+   for( i = 0; i < 8; i++ )
+   {
+     *dstBlk = clippingTable[ *block ];
+     *(dstBlk+1) = clippingTable[ *(block+1) ];
+     *(dstBlk+2) = clippingTable[ *(block+2) ];
+     *(dstBlk+3) = clippingTable[ *(block+3) ];
+     *(dstBlk+4) = clippingTable[ *(block+4) ];
+     *(dstBlk+5) = clippingTable[ *(block+5) ];
+     *(dstBlk+6) = clippingTable[ *(block+6) ];
+     *(dstBlk+7) = clippingTable[ *(block+7) ];
+     dstBlk += xSize;
+     block += 8;
+   }
+}
+
+
+/* {{-output"blcCopyPredictionMB.txt"}} */
+/*
+ * blcCopyPredictionMB
+ *    
+ *
+ * Parameters:
+ *    param                      input and output parameters
+ *
+ * Function:
+ *    This function copies one macroblock from previous frame into present
+ *    frame at the location of macroblock being currently decoded. 
+ *    The location where the macroblock is read is the location of 
+ *    the current block changed with motion vectors.
+ *
+ * Returns:
+ *    >= 0                       the function was successful
+ *    < 0                        an error occured
+ *
+ */
+
+int blcCopyPredictionMB(blcCopyPredictionMBParam_t *param)
+/* {{-output"blcCopyPredictionMB.txt"}} */
+{
+   int
+      uvWidth = param->uvWidth,
+      uvHeight = param->uvHeight,
+      yWidth = uvWidth * 2,
+      yHeight = uvHeight * 2,
+      uvDstX = param->uvBlkXCoord,
+      uvDstY = param->uvBlkYCoord,
+      yDstX = uvDstX * 2,
+      yDstY = uvDstY * 2,
+      *mvx = param->mvx, 
+      *mvy = param->mvy,
+      status;
+
+   u_char
+      *dstYBlk = param->currYMBInFrame,
+      *dstUBlk = param->currUBlkInFrame,
+      *dstVBlk = param->currVBlkInFrame,
+      *srcYFrame = param->refY,
+      *srcUFrame = param->refU,
+      *srcVFrame = param->refV;
+
+   blcCopyBlock_t copyBlock = (param->fMVsOverPictureBoundaries) ?
+      blcCopyBlockBC : blcCopyBlockNBC;
+
+   blcAssert(param != NULL);
+   blcAssert(param->rcontrol == 0 || param->rcontrol == 1);
+
+   /* Copy UV prediction blocks */
+   status = blcCopyUVPredictionBlocks(
+      (param->fourMVs) ? 
+         blcUVCountRefXY4MVs : blcUVCountRefXY1MV,
+      copyBlock,
+      mvx, mvy,
+      dstUBlk, dstVBlk,
+      srcUFrame, srcVFrame,
+      uvDstX, uvDstY,
+      uvWidth,
+      uvWidth, uvHeight,
+      param->fMVsOverPictureBoundaries,
+      param->rcontrol);
+
+   if (status < 0) 
+      return status;
+
+   /* If Advanced Prediction is in use */
+   if (param->fAdvancedPrediction) {
+
+        // not supported
+        
+   }
+
+   /* Else normal prediction mode is in use */
+   else { 
+
+      /* Copy Y prediction MB */
+      if(param->fourMVs)
+         status = blcCopyNormalYPredictionMBWith4MVs(
+            copyBlock,
+            mvx, mvy,
+            dstYBlk,
+            srcYFrame,
+            yDstX, yDstY,
+            yWidth,
+            yWidth, yHeight,
+            param->fMVsOverPictureBoundaries,
+            param->rcontrol);
+      else
+         status = blcCopyNormalYPredictionMBWith1MV(
+            copyBlock,
+            mvx, mvy,
+            dstYBlk,
+            srcYFrame,
+            yDstX, yDstY,
+            yWidth,
+            yWidth, yHeight,
+            param->fMVsOverPictureBoundaries,
+            param->rcontrol);
+      if (status < 0)
+         return status;
+   }
+
+   return 0;
+}
+
+
+
+
+
+/*
+ *    Local functions
+ */
+
+
+
+
+
+/*
+ * blcCopyNormalYPredictionMBWith1MV
+ *    
+ *
+ * Parameters:
+ *    copyBlock                  a pointer to either blcCopyBlockBC or
+ *                               blcCopyBlockNBC (or their Assembler versions)
+ *
+ *    mvxArray                   an array of four for x component of MVs
+ *    mvyArray                   an array of four for y component of MVs
+ *                               (Only the first entry of the array is used.)
+ *
+ *    dstYBlk                    a pointer to the current Y macroblock
+ *                               in the destination Y frame
+ *
+ *    srcYFrame                  the top-left corner of the source Y frame
+ *
+ *    dstYXPos                   the x coordinate of dstYBlk (in pixels)
+ *    dstYYPos                   the y coordinate of dstYBlk (in pixels)
+ *
+ *    dstYXSize                  the width of the Y destination frame
+ *    srcYXSize                  the width of the Y source frame
+ *    srcYYSize                  the height of the Y source frame
+ *
+ *    fMVsOverPictureBoundaries  non-zero if motion vectors may point outside
+ *                               picture boundaries, zero otherwise
+ *
+ *    rcontrol                   RCONTROL (section 6.1.2 of the H.263 standard)
+ *
+ * Function:
+ *    This function copies a luminance prediction macroblock from the given
+ *    source frame to the given position of the destination frame.
+ *    The prediction macroblock is associated with one motion vector.
+ *
+ * Returns:
+ *    >= 0 if everything is ok
+ *    < 0 if an error occured
+ *
+ */
+
+static int blcCopyNormalYPredictionMBWith1MV(
+   blcCopyBlock_t copyBlock,
+   int *mvxArray, int *mvyArray, 
+   u_char *dstYBlk,
+   u_char *srcYFrame,
+   int dstYXPos, int dstYYPos, 
+   int dstYXSize,
+   int srcYXSize, int srcYYSize,
+   int fMVsOverPictureBoundaries, 
+   int rcontrol)
+{
+   int 
+      mvxVal = *mvxArray, mvyVal = *mvyArray,
+      subpixelX, subpixelY,
+      xlt0, xNormal, xgtmax,
+      ylt0, yNormal, ygtmax,
+      srcXPos, srcYPos;
+   u_char *srcBlk;
+
+   blcYCountRefXY(mvxVal, mvyVal, dstYXPos, dstYYPos, &srcXPos, &srcYPos,
+      &subpixelX, &subpixelY);
+
+   if (fMVsOverPictureBoundaries)
+      blcHandleRefOverPictBoundariesBC(
+         16, 16,
+         srcYXSize, srcYYSize, 
+         subpixelX, subpixelY, 
+         &srcXPos, &srcYPos,
+         &xlt0, &xNormal, &xgtmax, 
+         &ylt0, &yNormal, &ygtmax);
+
+   else {
+      if (blcIsRefOverPictBoundaries(
+         16, 16,
+         srcYXSize, srcYYSize, 
+         subpixelX, subpixelY, 
+         srcXPos, srcYPos))
+         return -1;
+      xlt0 = xgtmax = ylt0 = ygtmax = 0;
+      xNormal = yNormal = 16;
+   }
+
+   srcBlk = srcYFrame + srcYPos * srcYXSize + srcXPos;
+
+   copyBlock(srcBlk, dstYBlk, xlt0, xNormal, xgtmax,
+      ylt0, yNormal, ygtmax, subpixelX, subpixelY,
+      srcYXSize, dstYXSize, 16, 16, rcontrol);
+
+   return 0;
+}
+
+
+/*
+ * blcCopyNormalYPredictionMBWith4MVs
+ *    
+ *
+ * Parameters:
+ *    See blcCopyNormalYPredictionMBWith1MV.
+ *    All 4 entries of mvxArray and mvyArray are used.
+ *
+ * Function:
+ *    This function copies a luminance prediction macroblock from the given
+ *    source frame to the given position of the destination frame.
+ *    The prediction macroblock is associated with four motion vectors.
+ *
+ * Returns:
+ *    >= 0 if everything is ok
+ *    < 0 if an error occured
+ *
+ */
+
+static int blcCopyNormalYPredictionMBWith4MVs(
+   blcCopyBlock_t copyBlock,
+   int *mvxArray, int *mvyArray, 
+   u_char *dstYBlk,
+   u_char *srcYFrame,
+   int dstYXPos, int dstYYPos, 
+   int dstYXSize,
+   int srcYXSize, int srcYYSize,
+   int fMVsOverPictureBoundaries, 
+   int rcontrol)
+{
+   int 
+      nh, nv, 
+      mvi = 0, 
+      mvxVal, mvyVal,
+      subpixelX, subpixelY,
+      xlt0, xNormal, xgtmax,
+      ylt0, yNormal, ygtmax,
+      srcXPos, srcYPos;
+
+   u_char 
+      *srcBlk, 
+      *origDest; 
+
+   origDest = dstYBlk; 
+   for (nv = 0; nv <= 1; nv++, dstYYPos += 8,
+      origDest += (dstYXSize << 3) - 16, dstYXPos -= 16) {
+      for (nh = 0; nh <= 1; nh++, dstYXPos += 8, origDest += 8, mvi++) { 
+         dstYBlk = origDest; 
+         mvxVal = mvxArray[mvi];
+         mvyVal = mvyArray[mvi];
+
+         blcYCountRefXY(mvxVal, mvyVal, dstYXPos, dstYYPos, &srcXPos, &srcYPos,
+            &subpixelX, &subpixelY);
+
+         if (fMVsOverPictureBoundaries)
+            blcHandleRefOverPictBoundariesBC(
+               8, 8,
+               srcYXSize, srcYYSize, 
+               subpixelX, subpixelY, 
+               &srcXPos, &srcYPos,
+               &xlt0, &xNormal, &xgtmax, 
+               &ylt0, &yNormal, &ygtmax);
+
+         else {
+            if (blcIsRefOverPictBoundaries(
+               8, 8,
+               srcYXSize, srcYYSize, 
+               subpixelX, subpixelY, 
+               srcXPos, srcYPos))
+               return -1;
+            xlt0 = xgtmax = ylt0 = ygtmax = 0;
+            xNormal = yNormal = 8;
+         }
+
+         srcBlk = srcYFrame + srcYPos * srcYXSize + srcXPos; 
+
+         copyBlock(srcBlk, dstYBlk, xlt0, xNormal, xgtmax, 
+            ylt0, yNormal, ygtmax, subpixelX, subpixelY, srcYXSize, 
+            dstYXSize, 8, 8, rcontrol); 
+      } 
+   } 
+
+   return 0;
+}
+
+
+
+/*
+ * blcCopyUVPredictionBlocks
+ *    
+ *
+ * Parameters:
+ *    uvCountSourceXY            a pointer to either blcUVCountRefXY1MV or 
+ *                               blcUVCountRefXY4MVs
+ *
+ *    copyBlock                  a pointer to either blcCopyBlockBC or
+ *                               blcCopyBlockNBC (or their Assembler versions)
+ *
+ *    mvxArray                   an array of four for x component of MVs
+ *    mvyArray                   an array of four for y component of MVs
+ *
+ *    dstUBlk                    a pointer to the current U block
+ *                               in the destination U frame
+ *    dstVBlk                    a pointer to the current V block
+ *                               in the destination V frame
+ *
+ *    srcUFrame                  the top-left corner of the source U frame
+ *    srcVFrame                  the top-left corner of the source V frame
+ *
+ *    dstUVXPos                  the x coordinate of dstUBlk
+ *    dstUVYPos                  the y coordinate of dstUBlk
+ *
+ *    dstUVXSize                 the width of the U and V destination frame
+ *    srcUVXSize                 the width of the U and V source frame
+ *    srcUVYSize                 the height of the U and V source frame
+ *
+ *    fMVsOverPictureBoundaries  non-zero if motion vectors may point outside
+ *                               picture boundaries, zero otherwise
+ *
+ *    rcontrol                   RCONTROL (section 6.1.2 of the H.263 standard)
+ *
+ * Function:
+ *    This function copies chrominance prediction blocks from the given
+ *    source frames to the given positions of the destination frames.
+ *
+ * Returns:
+ *    >= 0 if everything is ok
+ *    < 0 if an error occured
+ *
+ */
+
+static int blcCopyUVPredictionBlocks(
+   blcUVCountRefXY_t uvCountSourceXY,
+   blcCopyBlock_t copyBlock,
+   int *mvxArray, int *mvyArray, 
+   u_char *dstUBlk, u_char *dstVBlk,
+   u_char *srcUFrame, u_char *srcVFrame, 
+   int dstUVXPos, int dstUVYPos, 
+   int dstUVXSize,
+   int srcUVXSize, int srcUVYSize,
+   int fMVsOverPictureBoundaries, 
+   int rcontrol)
+{
+   int
+      srcXPos,
+      srcYPos,
+      subpixelX,
+      subpixelY,
+      xlt0,
+      xNormal,
+      xgtmax,
+      ylt0,
+      yNormal,
+      ygtmax;
+
+   u_char *srcBlk;
+
+   uvCountSourceXY(dstUVXPos, dstUVYPos, mvxArray, mvyArray, 
+       &srcXPos, &srcYPos, &subpixelX, &subpixelY);
+
+   if (fMVsOverPictureBoundaries)
+      blcHandleRefOverPictBoundariesBC(
+         8, 8,
+         srcUVXSize, srcUVYSize, 
+         subpixelX, subpixelY, 
+         &srcXPos, &srcYPos,
+         &xlt0, &xNormal, &xgtmax, 
+         &ylt0, &yNormal, &ygtmax);
+
+   else {
+      if (blcIsRefOverPictBoundaries(
+         8, 8,
+         srcUVXSize, srcUVYSize, 
+         subpixelX, subpixelY, 
+         srcXPos, srcYPos))
+         return -1;
+      xlt0 = xgtmax = ylt0 = ygtmax = 0;
+      xNormal = yNormal = 8;
+   }
+
+   /* U block */ \
+   srcBlk = srcUFrame + srcYPos * srcUVXSize + srcXPos;
+
+   /*deb0p("Copy U block\n");
+   deb1p("srcBlk %x\n", srcBlk);
+   deb1p("dstUBlk %x\n", dstUBlk);
+   deb1p("xlt0 %d\n", xlt0);
+   deb1p("xNormal %d\n", xNormal);
+   deb1p("xgtmax %d\n", xgtmax);
+   deb1p("ylt0 %d\n", ylt0);
+   deb1p("yNormal %d\n", yNormal);
+   deb1p("ygtmax %d\n", ygtmax);
+   deb1p("subpixelX %d\n", subpixelX);
+   deb1p("subpixelY %d\n", subpixelY);
+   deb1p("srcUVXSize %d\n", srcUVXSize);
+   deb1p("dstUVXSize %d\n", dstUVXSize);
+   deb1p("rcontrol %d\n", rcontrol);*/
+
+   copyBlock(srcBlk, dstUBlk, xlt0, xNormal, xgtmax,
+      ylt0, yNormal, ygtmax, subpixelX, subpixelY,
+      srcUVXSize, dstUVXSize, 8, 8, rcontrol);
+
+   /* V block */ \
+   srcBlk = srcVFrame + srcYPos * srcUVXSize + srcXPos;
+
+   copyBlock(srcBlk, dstVBlk, xlt0, xNormal, xgtmax,
+      ylt0, yNormal, ygtmax, subpixelX, subpixelY,
+      srcUVXSize, dstUVXSize, 8, 8, rcontrol);
+
+   return 0;
+}
+
+
+/*
+ * blcHandleRefOverPictBoundariesBC
+ *    
+ *
+ * Input parameters:
+ *    xBlkSize                   the width of the block to copy
+ *    yBlkSize                   the height of the block to copy
+ *    xSize                      the width of the frame
+ *    ySize                      the height of the frame
+ *
+ *    subpixelX                  1 if half pixel position is used in X direction
+ *    subpixelY                  1 if half pixel position is used in Y direction
+ *
+ * Input/output parameters:
+ *    sourceX                    input: the absolute position of the source
+ *    sourceY                    block (may be negative, half-pixel values are
+ *                               truncated to the next smaller integer)
+ *                               output: the coordinates of the first valid
+ *                               pixel in the source block
+ *
+ * Output parameters:
+ *    The next parameters describe a row of source pixels.
+ *    xlt0                       the number of the source pixels in the left of
+ *                               the image area
+ *    xNormal                    the number of the source pixels within 
+ *                               the image area
+ *    xgtmax                     the number of the source pixels in the right of
+ *                               the image area
+ *
+ *    The next parameters describe a column of source pixels.
+ *    ylt0                       the number of the source pixels above 
+ *                               the image area
+ *    yNormal                    the number of the source pixels withing 
+ *                               the image area
+ *    ygtmax                     the number of the source pixels below 
+ *                               the image area
+ *
+ * Function:
+ *    This function counts how many pixels are outside the picture area
+ *    and the coordinates of the first valid pixel in the source block.
+ *
+ * Returns:
+ *    See output parameters.
+ *
+ */
+
+static void blcHandleRefOverPictBoundariesBC(
+   int xBlkSize, int yBlkSize,
+   int xSize, int ySize, 
+   int subpixelX, int subpixelY, 
+   int *sourceX, int *sourceY,
+   int *xlt0, int *xNormal, int *xgtmax, 
+   int *ylt0, int *yNormal, int *ygtmax)
+{
+   int
+      xSizeMinus = xSize - xBlkSize,
+      ySizeMinus = ySize - yBlkSize;
+
+   if (*sourceX < 0) {
+      *xlt0 = (-(*sourceX) < xBlkSize) ? -(*sourceX) : xBlkSize;
+      *sourceX = 0;
+   }
+   else *xlt0 = 0;
+
+   if (*sourceY < 0) {
+      *ylt0 = (-(*sourceY) < yBlkSize) ? -(*sourceY) : yBlkSize;
+      *sourceY = 0;
+   }
+   else *ylt0 = 0;
+
+   if (*sourceX + subpixelX > xSizeMinus) {
+      if (*sourceX + subpixelX < xSize)
+         *xgtmax = *sourceX + subpixelX - xSizeMinus;
+      else {
+         *xgtmax = xBlkSize;
+         *sourceX = xSize - 1;
+      }
+   }
+   else *xgtmax = 0;
+
+   if (*sourceY + subpixelY > ySizeMinus) {
+      if (*sourceY + subpixelY < ySize)
+         *ygtmax = *sourceY + subpixelY - ySizeMinus;
+      else {
+         *ygtmax = yBlkSize;
+         *sourceY = ySize - 1;
+      }
+   }
+   else *ygtmax = 0;
+
+   *xNormal = xBlkSize - *xgtmax - *xlt0;
+   *yNormal = yBlkSize - *ygtmax - *ylt0;
+}
+
+
+/*
+ * blcIsRefOverPictBoundaries
+ *    
+ *
+ * Input parameters:
+ *    xBlkSize                   the width of the block to copy
+ *    yBlkSize                   the height of the block to copy
+ *    xSize                      the width of the frame
+ *    ySize                      the height of the frame
+ *
+ *    subpixelX                  1 if half pixel position is used in X direction
+ *    subpixelY                  1 if half pixel position is used in Y direction
+ *
+ *    sourceX                    the absolute position of the source
+ *    sourceY                    block (may be negative, half-pixel values are
+ *                               truncated to the next smaller integer)
+ *
+ * Function:
+ *    This function checks if the reference (source, prediction) block
+ *    is (partly) outside the picture area.
+ *
+ * Returns:
+ *    1 if the reference block is (partly) outside the picture area
+ *    0 if the whole reference block is inside the picture area
+ *
+ */
+
+static int blcIsRefOverPictBoundaries(
+   int xBlkSize, int yBlkSize,
+   int xSize, int ySize, 
+   int subpixelX, int subpixelY, 
+   int sourceX, int sourceY)
+{
+   if (sourceX < 0)
+      return 1;
+
+   if (sourceY < 0)
+      return 1;
+
+   if (sourceX + subpixelX > xSize - xBlkSize)
+      return 1;
+
+   if (sourceY + subpixelY > ySize - yBlkSize)
+      return 1;
+
+   return 0;
+}
+
+
+
+/*
+ * blcUVCountMVOffset4MVs
+ *    
+ *
+ * Input parameters:
+ *    mvxArray                   an array of the four horizontal components of
+ *                               the motion vectors for a particular macroblock
+ *    mvyArray                   an array of the four vertical components of
+ *                               the motion vectors for a particular macroblock
+ *
+ * Output parameters:
+ *    offsetX                    the relative position of the source
+ *    offsetY                    block (the origo is the destination block, 
+ *                               half-pixel values are truncated to the next 
+ *                               smaller integer)
+ *
+ *    subpixelX                  1 if half pixel position is used in X direction
+ *    subpixelY                  1 if half pixel position is used in Y direction
+ *
+ * Function:
+ *    This function counts the relative position of the chrominance source block
+ *    when it is given the motion vectors for the destination block. The macro
+ *    uses interpolation of four motion vectors described in Annex F of H.263
+ *    Recommendation.
+ *
+ * Returns:
+ *    See output parameters.
+ *
+ *    
+ *
+ */
+
+static void blcUVCountMVOffset4MVs(
+   int *mvxArray, int *mvyArray,
+   int *offsetX, int *offsetY,
+   int *subpixelX, int *subpixelY)
+{
+   /* These arrays define the table 16 in H.263 recommendation which is used
+      for interpolating chrominance motion vectors when four motion vectors
+      per macroblock is used. */
+   static const int
+      halfPixelOrig16[31] =
+         {0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0,
+          0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0},
+      * const halfPixel16 = &halfPixelOrig16[15],
+      fullPixelOrig16[31] =
+         {-1,-1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+           0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1},
+      * const fullPixel16 = &fullPixelOrig16[15];
+
+   int mvSum, pixelPos;
+
+   mvSum = mvxArray[0] + mvxArray[1] + mvxArray[2] + mvxArray[3];
+   pixelPos = (mvSum % 80) / 5;
+   *subpixelX = halfPixel16[pixelPos];
+   *offsetX = (mvSum / 80) + fullPixel16[pixelPos];
+   if (mvSum < 0 && *subpixelX)
+      (*offsetX)--;
+
+   mvSum = mvyArray[0] + mvyArray[1] + mvyArray[2] + mvyArray[3];
+   pixelPos = (mvSum % 80) / 5;
+   *subpixelY = halfPixel16[pixelPos];
+   *offsetY = (mvSum / 80) + fullPixel16[pixelPos];
+   if (mvSum < 0 && *subpixelY)
+      (*offsetY)--;
+}
+
+
+/*
+ * blcUVCountRefXY1MV
+ * blcUVCountRefXY4MVs
+ *    
+ *
+ * Input parameters:
+ *    origoX                     the coordinates of the destination block
+ *    origoY
+ *
+ *    mvxArray                   an array of the four horizontal components of
+ *                               the motion vectors for a particular macroblock
+ *    mvyArray                   an array of the four vertical components of
+ *                               the motion vectors for a particular macroblock
+ *                               In blcUVCountRefXY1MV, only the first entry of
+ *                               the array is used.
+ *
+ * Output parameters:
+ *    sourceX                    the absolute position of the source
+ *    sourceY                    block (may be negative, half-pixel values are
+ *                               truncated to the next smaller integer)
+ *
+ *    subpixelX                  1 if half pixel position is used in X direction
+ *    subpixelY                  1 if half pixel position is used in Y direction
+ *
+ * Function:
+ *    These macros count the absolute position of the chrominance source block 
+ *    (and sets sourceX, sourceY, subpixelX and subpixelY according to it) 
+ *    when it is given the position of the destination block and 
+ *    the motion vectors for the destination block. blcUVCountRefXY4MVs
+ *    uses interpolation of four motion vectors described in Annex F of H.263
+ *    Recommendation. blcUVCountRefXY1MV uses only the first motion vector
+ *    of the array as described in chapter 6.1.1 of H.263 Recommendation.
+ *
+ * Returns:
+ *    See output parameters.
+ *
+ *    
+ *
+ */
+
+static void blcUVCountRefXY1MV(
+   int origoX, int origoY,
+   int *mvxArray, int *mvyArray, 
+   int *sourceX, int *sourceY,
+   int *subpixelX, int *subpixelY)
+{
+   int mvxVal = *mvxArray, mvyVal = *mvyArray;
+
+   *sourceX = origoX + mvxVal / 20;
+   *sourceY = origoY + mvyVal / 20;
+
+   *subpixelX = (mvxVal % 20) != 0;
+   *subpixelY = (mvyVal % 20) != 0;
+
+   if (mvxVal < 0 && *subpixelX)
+      *sourceX -= 1;
+   if (mvyVal < 0 && *subpixelY)
+      *sourceY -= 1;
+}
+
+
+static void blcUVCountRefXY4MVs(
+   int origoX, int origoY,
+   int *mvxArray, int *mvyArray, 
+   int *sourceX, int *sourceY,
+   int *subpixelX, int *subpixelY)
+{
+   int offX, offY;
+
+   blcUVCountMVOffset4MVs(mvxArray, mvyArray, &offX, &offY, subpixelX, subpixelY);
+   *sourceX = origoX + offX;
+   *sourceY = origoY + offY;
+}
+
+
+/*
+ * blcYCountRefXY
+ *    
+ *
+ * Input parameters:
+ *    mvxVal                     motion vector components for the block
+ *    mvyVal
+ *
+ *    destX                      the coordinates of the destination block
+ *    destY
+ *
+ * Output parameters:
+ *    sourceX                    the absolute position of the source
+ *    sourceY                    block (may be negative, half-pixel values are
+ *                               truncated to the next smaller integer)
+ *
+ *    subpixelX                  1 if half pixel position is used in X direction
+ *    subpixelY                  1 if half pixel position is used in Y direction
+ *
+ * Function:
+ *    This function counts the absolute position of the luminance source block (and
+ *    sets sourceX, sourceY, subpixelX and subpixelY according to it) when it is
+ *    given the position of the destination block and a motion vector pointing
+ *    to the source block.
+ *
+ * Returns:
+ *    See output parameters.
+ *
+ *    
+ *
+ */
+
+static void blcYCountRefXY(
+   int mvxVal, int mvyVal,
+   int destX, int destY, 
+   int *sourceX, int *sourceY,
+   int *subpixelX, int *subpixelY)
+{
+   *sourceX = destX + mvxVal / 10;
+   *sourceY = destY + mvyVal / 10;
+
+   *subpixelX = mvxVal & 1;
+   *subpixelY = mvyVal & 1;
+
+   if (mvxVal < 0 && *subpixelX)
+      *sourceX -= 1;
+   if (mvyVal < 0 && *subpixelY)
+      *sourceY -= 1;
+}
+// End of File