videoeditorengine/h263decoder/src/vdcmvc.cpp
branchRCL_3
changeset 3 e0b5df5c0969
parent 0 951a5db380a0
child 7 4c409de21d23
equal deleted inserted replaced
0:951a5db380a0 3:e0b5df5c0969
     1 /*
       
     2 * Copyright (c) 2010 Ixonos Plc.
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of the "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - Initial contribution
       
    11 *
       
    12 * Contributors:
       
    13 * Ixonos Plc
       
    14 *
       
    15 * Description:  
       
    16 * Motion vector calculations and storage.
       
    17 *
       
    18 */
       
    19 
       
    20 
       
    21 
       
    22 
       
    23 #include "h263dConfig.h"
       
    24 
       
    25 #include "vdcmvc.h"
       
    26 
       
    27 #include "core.h"
       
    28 #include "errcodes.h"
       
    29 #include "debug.h"
       
    30 
       
    31 
       
    32 /* 
       
    33  * Defines 
       
    34  */
       
    35 
       
    36 #define NEIGHBOUR_SIZE 2      /* The size for neighbour array */
       
    37 #define MVD_NOT_CODED -32767  /* Macroblock is not coded in mvcTable_t */
       
    38 #define MVD_INTRA -32765      /* Marks intra macroblock in mvcTable_t */
       
    39 
       
    40 #define MVD_UMIN_MPEG4 -10240
       
    41 
       
    42 #define MVD_MIN -160          /* The minimum for mvd. */
       
    43 #define MVD_MAX 155           /* The maximum for mvd. */
       
    44 #define MVD_UMIN_V1 -315      /* The minimum for MV in unrestricted mode (v1) */
       
    45 #define MVD_UMAX_V1 315       /* The maximum for MV in unrestricted mode (v1) */
       
    46 #define MVD_UMIN_V2 -32000    /* The minimum for MV in unrestricted mode (v2)
       
    47                                  Note: this value is used to check the validity
       
    48                                  of MVs. If there is no MV for a MB 
       
    49                                  MVD_NOT_CODED or MVD_INTRA are used, and
       
    50                                  therefore any value bigger than those
       
    51                                  suits for this definition. In H.263 v2 
       
    52                                  unlimited submode, MVs can have any length
       
    53                                  within a picture (plus 15-pixel border),
       
    54                                  and therefore this definition is set to small
       
    55                                  enough value. */
       
    56 #define MVD_155 155           /* MV for 15.5 */
       
    57 #define MVD_160 160           /* MV for 16 */
       
    58 #define MVD_320 320           /* MV for 32 */
       
    59 /* It is assumed that motion vector values are signed and in order
       
    60    (for example MV for 15.5 < MV for 16).
       
    61    No other assumptions are made. */
       
    62 
       
    63 
       
    64 /* 
       
    65  * Macros 
       
    66  */
       
    67 
       
    68 /* mvValid checks if the specified item is a valid motion vector */
       
    69 /* Note: MVD_NOT_CODED and MVD_INTRA are very small negative numbers.
       
    70          Thus, we can use the minimum MV for H.263 Annex D unlimited
       
    71          submode to check the validity of a passed item. Actually,
       
    72          we could use any value larger than MVD_NOT_CODED and MVD_INTRA
       
    73          and smaller than or equal to the minimum MV. */
       
    74 #define mvValid(d1item, d1y, d1time) \
       
    75    (d1item.mvx >= MVD_UMIN_V2 \
       
    76       && d1item.y == (d1y) && d1item.time == (d1time))
       
    77 
       
    78 
       
    79 #define mvValidMPEG(d1item, d1y, d1time) \
       
    80    (d1item.mvx >= MVD_UMIN_MPEG4 \
       
    81       && d1item.y == (d1y) && d1item.time == (d1time))
       
    82 
       
    83 /* mvLegal cheks if the specified item has been updated to either contain
       
    84    a motion vector or not coded / intra information */
       
    85 #define mvLegal(d5item, d5y, d5time) \
       
    86    (d5item.y == (d5y) && d5item.time == (d5time))
       
    87 
       
    88 /* mvStore puts given arguments into the motion vector array
       
    89    Used from: mvcCalcMV */
       
    90 #define mvStore(d2row, d2x, d2y, d2mvx, d2mvy, d2time, d2type) \
       
    91    d2row[d2x].mvx = d2mvx; d2row[d2x].mvy = d2mvy; \
       
    92    d2row[d2x].y = d2y; d2row[d2x].time = d2time; d2row[d2x].fourMVs = 1; \
       
    93    d2row[d2x].type = d2type
       
    94 
       
    95 /* mvStoreMB puts given arguments into the motion vector array for the
       
    96    whole macroblock
       
    97    Used from: mvcCalcMV, mvcMarkMBIntra, mvcMarkMBNotCoded */
       
    98 #define mvStoreMB(d4row1, d4row2, d4x, d4y, d4mvx, d4mvy, d4time, d4type) \
       
    99    d4row1[d4x].mvx = d4row1[d4x + 1].mvx = \
       
   100       d4row2[d4x].mvx = d4row2[d4x + 1].mvx = d4mvx; \
       
   101    d4row1[d4x].mvy = d4row1[d4x + 1].mvy = \
       
   102       d4row2[d4x].mvy = d4row2[d4x + 1].mvy = d4mvy; \
       
   103    d4row1[d4x].y = d4row1[d4x + 1].y = d4y; \
       
   104    d4row2[d4x].y = d4row2[d4x + 1].y = d4y + 1; \
       
   105    d4row1[d4x].time = d4row1[d4x + 1].time = \
       
   106       d4row2[d4x].time = d4row2[d4x + 1].time = time; \
       
   107    d4row1[d4x].fourMVs = d4row1[d4x + 1].fourMVs = \
       
   108       d4row2[d4x].fourMVs = d4row2[d4x + 1].fourMVs = 0; \
       
   109    d4row1[d4x].type = d4row1[d4x + 1].type = \
       
   110       d4row2[d4x].type = d4row2[d4x + 1].type = (d4type)
       
   111 
       
   112 /* updateRowPointers checks if currX, currY or currTime have changed
       
   113    and updates them. It also updates mvRow0, mvRow1 and mvRow2.
       
   114    Used from: mvcCalcMV, mvcMarkMBIntra, mvcMarkMBNotCoded */
       
   115 #define updateRowPointers(d3x, d3y, d3time) \
       
   116    if (d3x != mvcData->currX) \
       
   117       mvcData->currX = d3x; \
       
   118    if (d3y != mvcData->currY) { \
       
   119       int \
       
   120          mvRowIndex, \
       
   121          currMaxX = mvcData->currMaxX; \
       
   122       mvRowItem_t *mvRow = mvcData->mvRow; \
       
   123       mvcData->currY = d3y; \
       
   124       mvcData->mvRowIndex = mvRowIndex = (mvcData->mvRowIndex + 2) % 3; \
       
   125       mvcData->mvRow0 = &mvRow[(currMaxX + 1) * 2 * mvRowIndex]; \
       
   126       mvcData->mvRow1 = &mvRow[(currMaxX + 1) * 2 * ((mvRowIndex + 1) % 3)]; \
       
   127       mvcData->mvRow2 = &mvRow[(currMaxX + 1) * 2 * ((mvRowIndex + 2) % 3)]; \
       
   128    } \
       
   129    if (d3time != mvcData->currTime) \
       
   130       mvcData->currTime = d3time 
       
   131 
       
   132 /* mvcInvMVD takes the other one of the possible MVD values defined in
       
   133    H.263 Recommendation */
       
   134 #define mvcInvMVD(invMv) \
       
   135    (invMv < 0) ? \
       
   136       MVD_320 + invMv : \
       
   137       -MVD_320 + invMv
       
   138 
       
   139 /* sign123(x) returns
       
   140       1 if x < 0,
       
   141       2 if x > 0,
       
   142       3 if x == 0 
       
   143    In other words,
       
   144       bit 0 = 1 if x <= 0, 
       
   145       bit 1 = 1 if x >= 0 */
       
   146 #define sign123(x) ((x == 0) ? 3 : (x < 0) ? 1 : 2)
       
   147 
       
   148 
       
   149 /* 
       
   150  * Local prototypes
       
   151  */
       
   152 
       
   153 static void mvcGetNeighbourMVs(mvcData_t *mvcData, int x, int y, int time,
       
   154    int *nmvx, int *nmvy, int prevFlag, int16 *error);
       
   155 
       
   156 __inline static void mvcCheckAndSet( 
       
   157       mvRowItem_t *mvRowPtr, int xind, int yind, int time, int nind, 
       
   158       int *nmvx, int *nmvy, mvRowItem_t *cmvRowPtr, int cxind, int cyind,
       
   159       int16 *error);
       
   160 
       
   161 __inline static void mvcSetToCurrent( 
       
   162       mvRowItem_t *mvRowPtr, int xind, int yind, int time, int nind,
       
   163       int *nmvx, int *nmvy, int16 *error);
       
   164 
       
   165 
       
   166 /*
       
   167  * Global functions
       
   168  */
       
   169 
       
   170 
       
   171 /* {{-output"mvcSetBorders.txt"}} */
       
   172 /*
       
   173  *
       
   174  * mvcSetBorders
       
   175  *
       
   176  * Parameters:
       
   177  *    mvcData        mvcData_t structure
       
   178  *    x              the x coordinate of the MB (0 .. maxX)
       
   179  *    y              the y coordinate of the MB
       
   180  *                   (0 .. macroblock rows in frame - 1)
       
   181  *    mba            Macroblock address of starting MB of the slice. This 
       
   182  *                   value SHOULD be set to -1 if Annex K is not in use.
       
   183  *    numMBsInMBLine    Number of MBs in MB line    
       
   184  *    rightOfBorder     There is a border on the left of the current MB
       
   185  *    downOfBorder      There is a border on top of the current MB
       
   186  *
       
   187  * Function:
       
   188  *    This function calculates the borders of GOBs and Slices..This function 
       
   189  *    SHOULD be called before mvcCalcMV.....
       
   190  *
       
   191  * Returns:
       
   192  *    Nothing
       
   193  *
       
   194  * Error codes:
       
   195  *    None
       
   196  *
       
   197  */
       
   198 
       
   199 void mvcSetBorders(
       
   200       mvcData_t *mvcData, int x, int y, int mba, int numMBsInMBLine, 
       
   201       int *rightOfBorder, int *downOfBorder 
       
   202 )
       
   203 {
       
   204    int
       
   205       upRightMBIsStart;
       
   206 
       
   207    if (mvcData)   {
       
   208       mvcData->rightOfBorderPrev = mvcData->rightOfBorder;
       
   209       mvcData->downOfBorderPrev = mvcData->downOfBorder;
       
   210    }
       
   211 
       
   212    if (mba == -1) {
       
   213       if (x == 0) {
       
   214          *rightOfBorder = 1;
       
   215       }
       
   216       else  {
       
   217          *rightOfBorder = 0;
       
   218       }
       
   219       
       
   220       /* Always downOfBorder is set to 1, since in QCIF and CIF every GOB
       
   221          has only 1 MB line. If larger images are supported, numMBLinesInGOB
       
   222          should be passed here. Also number of starting MB of the GOB may be
       
   223          needed...*/
       
   224       *downOfBorder = 1;
       
   225       upRightMBIsStart = 0;
       
   226    }
       
   227    else  {
       
   228       int
       
   229          xs,   /* x coordinate of start MB */
       
   230          ys;   /* y coordinate of start MB */
       
   231       xs = mba % numMBsInMBLine;
       
   232       ys = mba / numMBsInMBLine;
       
   233 
       
   234       /* slice structured mode*/
       
   235       /* Check if there is slice border on top of the  current MB:
       
   236          For that, check either current MB should be on the same MB line 
       
   237          with the starting MB of slice or current MB should not be on the
       
   238          left of the starting MB if the MB is on the second line of the 
       
   239          slice. */
       
   240       
       
   241       if ((y == ys) || ((x < xs) && (ys+1 == y)))  {
       
   242          *downOfBorder = 1;
       
   243       }
       
   244       else  {
       
   245          *downOfBorder = 0;
       
   246       }   
       
   247       /* Check if there is a slice border on the left of the current MB.*/
       
   248       if (((x == xs) && (y == ys)) || (x == 0))  {
       
   249          *rightOfBorder = 1;
       
   250       }
       
   251       else  {
       
   252          *rightOfBorder = 0;
       
   253       }
       
   254 
       
   255       /* Test the situation of MV2 is in another slice but MV3 in in the
       
   256          same slice... i.e:
       
   257          MB1 MB1 MB1 MB2 MB2 .........MB2
       
   258          MB2 MB2 MB2 MB2 MB2..........MB2
       
   259                   *                        
       
   260          The MB marked with * is an exmaple. MB on top of it is in another slice
       
   261          but the MB which MV3 will come from is in the same slice...*/
       
   262       if ((x+1 == xs) && (y-1 == ys))
       
   263          upRightMBIsStart = 1;
       
   264       else
       
   265          upRightMBIsStart = 0;
       
   266    }   
       
   267 
       
   268    if (mvcData)   {
       
   269       mvcData->upRightMBIsStart = upRightMBIsStart;
       
   270       mvcData->downOfBorder = *downOfBorder;
       
   271       mvcData->rightOfBorder = *rightOfBorder;
       
   272       mvcData->leftOfBorder = 0;
       
   273    }
       
   274 }
       
   275 
       
   276 /* {{-output"mvcCalcMV.txt"}} */
       
   277 /*
       
   278  *
       
   279  * mvcCalcMV
       
   280  *
       
   281  * Parameters:
       
   282  *       mvcData        mvcData_t structure
       
   283  *
       
   284  *       mvdx           motion vector data returned by vlcGetMVD
       
   285  *       mvdy
       
   286  *
       
   287  *       *mvx           the resulting motion vector is placed to *mvx and *mvy
       
   288  *       *mvy
       
   289  *
       
   290  *       predictorMode  0, 1, 2 or 3. See H.263 recommendation, Annex F, Figure
       
   291  *                      15, where modes are in the following order:
       
   292  *                         0  1
       
   293  *                         2  3
       
   294  *
       
   295  *                      Advanced Prediction mode: It is assumed that this
       
   296  *                      function is called by setting predictorMode 0, 1, 2
       
   297  *                      and 3 in this order for a particular macroblock.
       
   298  *
       
   299  *                      Normal: This function should be called by setting
       
   300  *                      predictorMode to 0.
       
   301  *
       
   302  *       fourMVs        if != 0, four motion vectors for current macroblock
       
   303  *                      is assumed
       
   304  *
       
   305  *       unrestrictedMV       if != 0, unrestricted motion vector mode is used
       
   306  *
       
   307  *       topOfGOB             if != 0, the current MB is assumed to be in the
       
   308  *                            first line of the current GOB
       
   309  *
       
   310  *       nonEmptyGOBHeader    if != 0, the GOB header of the current GOB is
       
   311  *                            is assumed to be non-empty, and MV2 and MV3 are
       
   312  *                            set to MV1 if they are outside the GOB. If Annex K
       
   313  *                            is in use set this value to 1......
       
   314  *
       
   315  *       x              the x coordinate of the MB (0 .. maxX)
       
   316  *       y              the y coordinate of the MB
       
   317  *                      (0 .. macroblock rows in frame - 1)
       
   318  *
       
   319  *       time           a value which is related to the time when the current
       
   320  *                      frame must be shown. This value should be unique
       
   321  *                      among a relatively small group of consecutive frames.
       
   322  *
       
   323  *       mbType         must be MVC_MB_INTER or MVC_MB_INTRA. MVC_MB_INTRA 
       
   324  *                      should be used only in PB frames mode.
       
   325  *
       
   326  *       error          error code
       
   327  *
       
   328  *       fPLUSPTYPE     PLUSTYPE flag
       
   329  *
       
   330  *       fUMVLimited    Annex D v2 flag
       
   331  *                      1  => Limited MVs    (UUI = 1)
       
   332  *                      0  => Unlimited MVs  (UUI = 01)
       
   333  *
       
   334  * Function:
       
   335  *       This function counts the motion vector value for given macroblock.
       
   336  *       See H.263 Recommendation 6.1.1 Differential Motion Vectors and
       
   337  *       Annex F. Advanced Prediction Mode.
       
   338  *
       
   339  * Returns:
       
   340  *       Changes *mvx, *mvy and possibly *error.
       
   341  *
       
   342  * Error codes:
       
   343  *       ERR_MVC_MVDX_ILLEGAL    mvdx illegal
       
   344  *       ERR_MVC_MVDY_ILLEGAL    mvdy illegal
       
   345  *       ERR_MVC_MVX_ILLEGAL     mvx is NULL
       
   346  *       ERR_MVC_MVY_ILLEGAL     mvy is NULL
       
   347  *       ERR_MVC_MODE_ILLEGAL    predictorMode illegal
       
   348  *       ERR_MVC_X_ILLEGAL       x < 0 or x > maxX
       
   349  *       ERR_MVC_Y_ILLEGAL       y < 0
       
   350  *       ERR_MVC_TIME_ILLEGAL    time < 0
       
   351  *       ERR_MVC_MVPTR           result is not legal
       
   352  *
       
   353  */
       
   354 
       
   355 void mvcCalcMV(mvcData_t *mvcData, int mvdx, int mvdy,
       
   356    int *mvx, int *mvy, u_char predictorMode, u_char fourMVs,
       
   357    u_char unrestrictedMV,  u_char nonEmptyGOBHeader, int x, 
       
   358    int y, int time, int mbType, int16 *error, int fPLUSPTYPE, 
       
   359    int fUMVLimited)
       
   360 /* {{-output"mvcCalcMV.txt"}} */
       
   361 {
       
   362 
       
   363    int 
       
   364       i, j,    /* loop variables */
       
   365       mvcx[3], /* Candidates: mv[0] = MV1, mv[1] = MV2, mv[2] = MV3 */
       
   366       mvcy[3],
       
   367       *mv,     /* mvcx or mvcy */
       
   368       *mvptr,  /* == mvx or mvy */
       
   369       mvd,     /* mvdx or mvdy */
       
   370       xx2,     /* x * 2 */
       
   371       yx2,     /* y * 2 */
       
   372       xmv1,    /* index for MV1 */
       
   373       xmv2,    /* index for MV2 */
       
   374       xmv3,    /* index for MV3 */
       
   375       ymv1,
       
   376       ymv2,
       
   377       ymv3,
       
   378       mvRangeLow,    /* Lower boundary for MV Range  
       
   379                         Look H.263+ Rec. Table D.1, D.2 */
       
   380       mvRangeHigh,   /* Higher boundary for MV Range  
       
   381                         Look H.263+ Rec. Table D.1, D.2 */
       
   382       picDim,        /* Temporary variable for luminance width or height */
       
   383       mbCorner,      /* Temporary variable for MB's topleft corner's 
       
   384                         coordinate (x or y)*/
       
   385       mvRes;         /* MB's rightmost or bottommost pixel plus MV
       
   386                         for checking restriction D.1.1 */
       
   387    mvRowItem_t
       
   388       *currMvRow,
       
   389       *prevMvRow,
       
   390       *mvRow0,
       
   391       *mvRow1,
       
   392       *mvRow2;
       
   393 
       
   394    /* Check parameters */
       
   395     if ((!fPLUSPTYPE) || (!unrestrictedMV))
       
   396    {
       
   397       if (mvdx < MVD_MIN || mvdx > MVD_MAX) {
       
   398          *error = ERR_MVC_MVDX_ILLEGAL;
       
   399          return;
       
   400       }
       
   401 
       
   402       if (mvdy < MVD_MIN || mvdy > MVD_MAX) {
       
   403          *error = ERR_MVC_MVDY_ILLEGAL;
       
   404          return;
       
   405       }
       
   406    }
       
   407 
       
   408    if (!mvx) {
       
   409       *error = ERR_MVC_MVX_ILLEGAL;
       
   410       return;
       
   411    }
       
   412 
       
   413    if (!mvy) {
       
   414       *error = ERR_MVC_MVY_ILLEGAL;
       
   415       return;
       
   416    }
       
   417 
       
   418    if ((fourMVs && predictorMode > 3) ||
       
   419       (!fourMVs && predictorMode > 0)) {
       
   420       *error = ERR_MVC_MODE_ILLEGAL;
       
   421       return;
       
   422    }
       
   423 
       
   424    if (x < 0 || x > mvcData->currMaxX) {
       
   425       *error = ERR_MVC_X_ILLEGAL;
       
   426       return;
       
   427    }
       
   428 
       
   429    if (y < 0) {
       
   430       *error = ERR_MVC_Y_ILLEGAL;
       
   431       return;
       
   432    }
       
   433 
       
   434    if (time < 0) {
       
   435       *error = ERR_MVC_TIME_ILLEGAL;
       
   436       return;
       
   437    }
       
   438 
       
   439    updateRowPointers(x, y, time);
       
   440    mvRow0 = mvcData->mvRow0;
       
   441    mvRow1 = mvcData->mvRow1;
       
   442    mvRow2 = mvcData->mvRow2;
       
   443 
       
   444    /* Seek candidate predictors */
       
   445 
       
   446    xx2 = x << 1; /* xx2 = x * 2 */
       
   447    yx2 = y << 1;
       
   448 
       
   449    xmv1 = xx2 - 1 + (predictorMode & 1);
       
   450    xmv2 = xx2 + (predictorMode == 1);
       
   451    xmv3 = xx2 + 2 - (predictorMode > 1);
       
   452    ymv1 = yx2 + (predictorMode > 1);
       
   453    ymv2 = ymv3 = yx2 - 1 + (predictorMode > 1);
       
   454 
       
   455    if (predictorMode <= 1) {
       
   456       currMvRow = mvRow1;
       
   457       prevMvRow = mvRow0;
       
   458    }
       
   459    else {
       
   460       currMvRow = mvRow2;
       
   461       prevMvRow = mvRow1;
       
   462    }
       
   463 
       
   464    if ( (predictorMode & 1) || /* right column of the MB */
       
   465       ( !mvcData->rightOfBorder && mvValid(currMvRow[xmv1], ymv1, time) ) ) {
       
   466       mvcx[0] = currMvRow[xmv1].mvx;
       
   467       mvcy[0] = currMvRow[xmv1].mvy;
       
   468    }
       
   469    else
       
   470       /* if (x == 0 || motion vector for previous MB does not exist ||
       
   471              the previous MB belongs to a different slice) */
       
   472       mvcx[0] = mvcy[0] = 0;
       
   473 
       
   474    if ((y == 0 || (mvcData->downOfBorder && nonEmptyGOBHeader)) && predictorMode <= 1) {
       
   475       /* mv2 and mv3 are outside the picture or GOB
       
   476          (if non-empty GOB header) or outside the slice*/
       
   477       mvcx[1] = mvcx[0];
       
   478       mvcy[1] = mvcy[0];
       
   479       /* Check if the MB ont the previous line and on the next column
       
   480          in in the same slice (means start MBof the slice).. */
       
   481       if (!mvcData->upRightMBIsStart)   {
       
   482          mvcx[2] = mvcx[0];
       
   483          mvcy[2] = mvcy[0];
       
   484       }
       
   485       if (x == mvcData->currMaxX)
       
   486          mvcx[2] = mvcy[2] = 0;
       
   487    }
       
   488    else {
       
   489       if (mvValid(prevMvRow[xmv2], ymv2, time)) {
       
   490          mvcx[1] = prevMvRow[xmv2].mvx;
       
   491          mvcy[1] = prevMvRow[xmv2].mvy;
       
   492       }
       
   493       else 
       
   494          mvcx[1] = mvcy[1] = 0;
       
   495 
       
   496       if (mvValid(prevMvRow[xmv3], ymv3, time)) {
       
   497          mvcx[2] = prevMvRow[xmv3].mvx;
       
   498          mvcy[2] = prevMvRow[xmv3].mvy;
       
   499       }
       
   500       else
       
   501          mvcx[2] = mvcy[2] = 0;
       
   502    }
       
   503 
       
   504     for (j = 0, mv = mvcx, mvd = mvdx, mvptr = mvx,
       
   505          picDim = mvcData->currLumWidth, mbCorner = x,
       
   506          mvRangeLow = mvcData->mvRangeLowX,
       
   507          mvRangeHigh = mvcData->mvRangeHighX;
       
   508          j < 2;
       
   509          j++, mv = mvcy, mvd = mvdy, mvptr = mvy, 
       
   510          picDim = mvcData->currLumHeight, mbCorner = y,
       
   511          mvRangeLow = mvcData->mvRangeLowY,
       
   512          mvRangeHigh = mvcData->mvRangeHighY) {
       
   513 
       
   514       int choice1, min, predictor;
       
   515 
       
   516       /* Find the median of the candidates */
       
   517 
       
   518       min = mv[0];
       
   519       predictor = 32767;
       
   520 
       
   521       for (i = 1; i < 3; i++) {
       
   522          if (mv[i] <= min) {
       
   523             predictor = min;
       
   524             min = mv[i];
       
   525             continue;
       
   526          }
       
   527          if (mv[i] < predictor)
       
   528             predictor = mv[i];
       
   529       }
       
   530 
       
   531       /* Count the new motion vector value */
       
   532 
       
   533       if (!unrestrictedMV) {
       
   534          /* Default prediction mode.
       
   535             Count the legal [-16..15.5] motion vector */
       
   536 
       
   537          choice1 = predictor + mvd;
       
   538 
       
   539          *mvptr = (MVD_MIN <= choice1 && choice1 <= MVD_MAX) ?
       
   540             choice1 :
       
   541             /*(mvd == 0) ?
       
   542                predictor :*/ /* index 32, should never happen?! */
       
   543                (mvd < 0) ?
       
   544                   MVD_320 + choice1 : /* index 0..31: 32 + mvd + predictor */
       
   545                   -MVD_320 + choice1; /* index 33..63: -32 + mvd + predictor */
       
   546 
       
   547          /* Check that the result is [-16..15.5] */
       
   548          if (*mvptr < MVD_MIN || *mvptr > MVD_MAX) {
       
   549             *error = ERR_MVC_MVPTR;
       
   550             return;
       
   551          }
       
   552       }
       
   553 
       
   554       else if ((-MVD_155 <= predictor && predictor <= MVD_160) && (!fPLUSPTYPE))
       
   555          /* Unrestricted motion vector mode && -15.5 <= predictor <= 16.
       
   556             mvd is always valid. */
       
   557          *mvptr = predictor + mvd;
       
   558 
       
   559        else if (!fPLUSPTYPE)
       
   560        {
       
   561          /* Unrestricted motion vector mode && predictor not in [-15.5, 16]
       
   562             Result in [-31.5, 31.5] and has the same sign as predictor */
       
   563          choice1 = predictor + mvd;
       
   564          *mvptr = (MVD_UMIN_V1 <= choice1 && choice1 <= MVD_UMAX_V1 &&
       
   565             (sign123(choice1) & sign123(predictor))) ?
       
   566             choice1 :
       
   567             /*(mvd == 0) ?
       
   568                predictor :*/ /* index 32, should never happen!? */
       
   569                (mvd < 0) ?
       
   570                   MVD_320 + choice1 : /* index 0..31: 32 + mvd + predictor */
       
   571                   -MVD_320 + choice1; /* index 33..63: -32 + mvd + predictor */
       
   572 
       
   573          /* Check that the result is in the appropriate range. */
       
   574          if ((predictor < -MVD_155 && *mvptr > 0) ||
       
   575             (predictor > MVD_160 && *mvptr < 0)) {
       
   576             *error = ERR_MVC_MVPTR;
       
   577             return;
       
   578          }
       
   579 
       
   580       }
       
   581        else if (fUMVLimited)  
       
   582       /* fPlusType==1 && UUI == 1*/
       
   583       {
       
   584          *mvptr = predictor + mvd;
       
   585 
       
   586          if ( *mvptr > 0 )
       
   587             /* mvRes is the leftmost/topmost pixels coordinate of next
       
   588                macroblock plus 2 times MV */
       
   589               mvRes = (mbCorner+1)*32 + (*mvptr)/5 ;
       
   590            else
       
   591              /* mvRes is the leftmost/topmost pixels coordinate of current
       
   592                macroblock plus 2 times MV,
       
   593             half a pixel corresponds to 1 in integer scale */
       
   594                mvRes = mbCorner*32 + (*mvptr)/5 ;
       
   595 
       
   596          if ((mvRes < -30) || (mvRes > picDim * 2 + 30))
       
   597          /* Restriction D.1.1 */
       
   598          {
       
   599             *error = ERR_MVC_MVPTR;
       
   600             deb("Restriction D.1.1\n");
       
   601             return;
       
   602          }
       
   603       
       
   604          if ((*mvptr < mvRangeLow) || (*mvptr > mvRangeHigh))
       
   605          /* Restriction D.2 */
       
   606          {
       
   607             *error = ERR_MVC_MVPTR;
       
   608             deb("Restriction D.2 \n");
       
   609             return;
       
   610          }
       
   611       }
       
   612       else  /* fPlusType==1 && UUI == 01 */
       
   613       {
       
   614          *mvptr = predictor + mvd;
       
   615          if ( *mvptr > 0 )
       
   616                mvRes = (mbCorner+1)*32 + (*mvptr)/5;
       
   617            else
       
   618                mvRes = mbCorner*32 + (*mvptr)/5;
       
   619          if ((mvRes < -30) || (mvRes > picDim * 2 + 30))
       
   620          /* Restriction D.1.1 */
       
   621          {
       
   622             *error = ERR_MVC_MVPTR;
       
   623             deb("Restriction D.1.1\n");
       
   624             return;
       
   625          }
       
   626       }
       
   627    }
       
   628 
       
   629    /* Update motion vector buffer arrays */
       
   630    switch (predictorMode) {
       
   631       case 0:
       
   632          if (fourMVs) {
       
   633             mvStore(mvRow1, xx2, yx2, *mvx, *mvy, time, mbType);
       
   634          }
       
   635          else {
       
   636             mvStoreMB(mvRow1, mvRow2, xx2, yx2, *mvx, *mvy, time, mbType);
       
   637          }
       
   638          break;
       
   639       case 1:
       
   640          mvStore(mvRow1, xx2 + 1, yx2, *mvx, *mvy, time, mbType);
       
   641          break;
       
   642       case 2:
       
   643          mvStore(mvRow2, xx2, yx2 + 1, *mvx, *mvy, time, mbType);
       
   644          break;
       
   645       case 3:
       
   646          mvStore(mvRow2, xx2 + 1, yx2 + 1, *mvx, *mvy, time, mbType);
       
   647          break;
       
   648    }
       
   649 }
       
   650 
       
   651 
       
   652 /* {{-output"mvcCalcMPEGMV.txt"}} */
       
   653 /*
       
   654  *
       
   655  * mvcCalcMPEGMV
       
   656  *
       
   657  * Parameters:
       
   658  *       mvcData        mvcData_t structure
       
   659  *
       
   660  *       mvdx           motion vector data returned by vlcGetMVD
       
   661  *       mvdy
       
   662  *
       
   663  *       *mvx           the resulting motion vector is placed to *mvx and *mvy
       
   664  *       *mvy
       
   665  *
       
   666  *       predictorMode  0, 1, 2 or 3. See H.263 recommendation, Annex F, Figure
       
   667  *                      15, where modes are in the following order:
       
   668  *                         0  1
       
   669  *                         2  3
       
   670  *
       
   671  *                      Advanced Prediction mode: It is assumed that this
       
   672  *                      function is called by setting predictorMode 0, 1, 2
       
   673  *                      and 3 in this order for a particular macroblock.
       
   674  *
       
   675  *                      Normal: This function should be called by setting
       
   676  *                      predictorMode to 0.
       
   677  *
       
   678  *       fourMVs        if != 0, four motion vectors for current macroblock
       
   679  *                      is assumed
       
   680  *
       
   681  *       topOfVP        if != 0, the current MB is assumed to be in the
       
   682  *                      first line of the current VideoPacket
       
   683  *
       
   684  *       leftOfVP       if != 0, the current MB is assumed to be the
       
   685  *                      first in the VideoPacket
       
   686  *
       
   687  *       fmv3_out       if != 0, the 3rd MB (top, right) used as MV predictor
       
   688  *                      is outside of the current VideoPacket
       
   689  *
       
   690  *       x              the x coordinate of the MB (0 .. maxX)
       
   691  *       y              the y coordinate of the MB
       
   692  *                      (0 .. macroblock rows in frame - 1)
       
   693  *
       
   694  *       time           a value which is related to the time when the current
       
   695  *                      frame must be shown. This value should be unique
       
   696  *                      among a relatively small group of consecutive frames.
       
   697  *
       
   698  *       mbType         must be MVC_MB_INTER or MVC_MB_INTRA. MVC_MB_INTRA 
       
   699  *                      should be used only in PB frames mode.
       
   700  *
       
   701  *       error          error code
       
   702  *
       
   703  * Function:
       
   704  *       This function counts the motion vector value for given macroblock.
       
   705  *       See H.263 Recommendation 6.1.1 Differential Motion Vectors and
       
   706  *       Annex F. Advanced Prediction Mode.
       
   707  *
       
   708  * Returns:
       
   709  *       Changes *mvx, *mvy and possibly *error.
       
   710  *
       
   711  * Error codes:
       
   712  *       The following codes are assertion-like checks:
       
   713  *       ERR_MVC_MVDX_ILLEGAL    mvdx illegal
       
   714  *       ERR_MVC_MVDY_ILLEGAL    mvdy illegal
       
   715  *       ERR_MVC_MVX_ILLEGAL     mvx is NULL
       
   716  *       ERR_MVC_MVY_ILLEGAL     mvy is NULL
       
   717  *       ERR_MVC_MODE_ILLEGAL    predictorMode illegal
       
   718  *       ERR_MVC_X_ILLEGAL       x < 0 or x > maxX
       
   719  *       ERR_MVC_Y_ILLEGAL       y < 0
       
   720  *       ERR_MVC_TIME_ILLEGAL    time < 0
       
   721  *
       
   722  *       The following code may also be caused by a bit error:
       
   723  *       ERR_MVC_MVPTR           result is not legal
       
   724  *
       
   725  */
       
   726 
       
   727 void mvcCalcMPEGMV(mvcData_t *mvcData,
       
   728    int mvdx, int mvdy, int *mvx, int *mvy,
       
   729    u_char predictorMode, u_char fourMVs,
       
   730    u_char topOfVP, u_char leftOfVP, u_char fmv3_out,
       
   731    int x, int y, int time, int mbType, int16 *error)
       
   732 /* {{-output"mvccalc.txt"}} */
       
   733 {
       
   734    int 
       
   735       i, j,    /* loop variables */
       
   736       mvcx[3], /* Candidates: mv[0] = MV1, mv[1] = MV2, mv[2] = MV3 */
       
   737       mvcy[3],
       
   738       mvc1_out = 0, mvc2_out = 0, mvc3_out = 0,
       
   739       *mv,     /* mvcx or mvcy */
       
   740       *mvptr,  /* == mvx or mvy */
       
   741       mvd,     /* mvdx or mvdy */
       
   742       xx2,     /* x * 2 */
       
   743       yx2,     /* y * 2 */
       
   744       xmv1,    /* index for MV1 */
       
   745       xmv2,    /* index for MV2 */
       
   746       xmv3,    /* index for MV3 */
       
   747       ymv1,
       
   748       ymv2,
       
   749       ymv3;
       
   750    mvRowItem_t
       
   751       *currMvRow,
       
   752       *prevMvRow,
       
   753       *mvRow0,
       
   754       *mvRow1,
       
   755       *mvRow2;
       
   756 
       
   757 
       
   758    if (!mvx) {
       
   759       *error = ERR_MVC_MVX_ILLEGAL;
       
   760       return;
       
   761    }
       
   762 
       
   763    if (!mvy) {
       
   764       *error = ERR_MVC_MVY_ILLEGAL;
       
   765       return;
       
   766    }
       
   767 
       
   768    if ((fourMVs && predictorMode > 3) ||
       
   769       (!fourMVs && predictorMode > 0)) {
       
   770       *error = ERR_MVC_MODE_ILLEGAL;
       
   771       return;
       
   772    }
       
   773 
       
   774    if (x < 0 || x > mvcData->currMaxX) {
       
   775       *error = ERR_MVC_X_ILLEGAL;
       
   776       return;
       
   777    }
       
   778 
       
   779    if (y < 0) {
       
   780       *error = ERR_MVC_Y_ILLEGAL;
       
   781       return;
       
   782    }
       
   783 
       
   784    if (time < 0) {
       
   785       *error = ERR_MVC_TIME_ILLEGAL;
       
   786       return;
       
   787    }
       
   788 
       
   789    updateRowPointers(x, y, time);
       
   790    mvRow0 = mvcData->mvRow0;
       
   791    mvRow1 = mvcData->mvRow1;
       
   792    mvRow2 = mvcData->mvRow2;
       
   793 
       
   794    /* Seek candidate predictors */
       
   795 
       
   796    xx2 = x << 1; /* xx2 = x * 2 */
       
   797    yx2 = y << 1;
       
   798 
       
   799    xmv1 = xx2 - 1 + (predictorMode & 1);
       
   800    xmv2 = xx2 + (predictorMode == 1);
       
   801    xmv3 = xx2 + 2 - (predictorMode > 1);
       
   802    ymv1 = yx2 + (predictorMode > 1);
       
   803    ymv2 = ymv3 = yx2 - 1 + (predictorMode > 1);
       
   804 
       
   805    if (predictorMode <= 1) {
       
   806       currMvRow = mvRow1;
       
   807       prevMvRow = mvRow0;
       
   808    }
       
   809    else {
       
   810       currMvRow = mvRow2;
       
   811       prevMvRow = mvRow1;
       
   812    }
       
   813 
       
   814    if ((x == 0 || leftOfVP) && !(predictorMode & 1)) {
       
   815       /* mv1 is outside the VP or VOP */
       
   816       mvcx[0] = mvcy[0] = 0;
       
   817       mvc1_out = 1;
       
   818    }
       
   819    else {
       
   820       if (mvValidMPEG(currMvRow[xmv1], ymv1, time)) {
       
   821           mvcx[0] = currMvRow[xmv1].mvx;
       
   822           mvcy[0] = currMvRow[xmv1].mvy;
       
   823       }
       
   824       else mvcx[0] = mvcy[0] = 0;
       
   825    }
       
   826 
       
   827    if ((y == 0 || topOfVP) && predictorMode <= 1) {
       
   828       /* mv2 is outside the VP or VOP */
       
   829       mvcx[1] = mvcy[1] = 0;
       
   830       mvc2_out = 1;
       
   831    }
       
   832    else {
       
   833       if (mvValidMPEG(prevMvRow[xmv2], ymv2, time)) {
       
   834          mvcx[1] = prevMvRow[xmv2].mvx;
       
   835          mvcy[1] = prevMvRow[xmv2].mvy;
       
   836       }
       
   837       else mvcx[1] = mvcy[1] = 0;
       
   838    }
       
   839 
       
   840    if ((y == 0 || fmv3_out || x == mvcData->currMaxX) && predictorMode <= 1) {
       
   841       /* mv3 is outside the VP or VOP */
       
   842       mvcx[2] = mvcy[2] = 0;
       
   843       mvc3_out = 1;
       
   844    }
       
   845    else {
       
   846       if (mvValidMPEG(prevMvRow[xmv3], ymv3, time)) {
       
   847          mvcx[2] = prevMvRow[xmv3].mvx;
       
   848          mvcy[2] = prevMvRow[xmv3].mvy;
       
   849       }
       
   850       else
       
   851          mvcx[2] = mvcy[2] = 0;
       
   852    }
       
   853 
       
   854    for (j = 0, mv = mvcx, mvd = mvdx, mvptr = mvx;
       
   855       j < 2;
       
   856       j++, mv = mvcy, mvd = mvdy, mvptr = mvy) {
       
   857 
       
   858       int min, predictor;
       
   859 
       
   860       switch (mvc1_out + mvc2_out + mvc3_out)
       
   861       {
       
   862          case 3:
       
   863              predictor = 0;
       
   864              break;
       
   865          case 2:
       
   866              predictor = mv[0] + mv[1] + mv[2];
       
   867              break;
       
   868          case 1:
       
   869          case 0:
       
   870              /* Find the median of the candidates */
       
   871              min = mv[0];
       
   872              predictor = 32767;
       
   873 
       
   874              for (i = 1; i < 3; i++) {
       
   875                  if (mv[i] <= min) {
       
   876                      predictor = min;
       
   877                      min = mv[i];
       
   878                      continue;
       
   879                  }
       
   880                  if (mv[i] < predictor)
       
   881                      predictor = mv[i];
       
   882              }
       
   883              break;
       
   884          default:
       
   885             /* Should never happen */
       
   886             vdcAssert(0);
       
   887             predictor = 0;
       
   888             break;
       
   889       }
       
   890 
       
   891       /* Count the new motion vector value */
       
   892       *mvptr = predictor + mvd;
       
   893 
       
   894       if (*mvptr < -(mvcData->range))
       
   895         *mvptr += 2*(mvcData->range);
       
   896       else if (*mvptr > (mvcData->range)-5)
       
   897         *mvptr -= 2*(mvcData->range);
       
   898    }
       
   899 
       
   900    /* Update motion vector buffer arrays */
       
   901    switch (predictorMode) {
       
   902       case 0:
       
   903          if (fourMVs) {
       
   904             mvStore(mvRow1, xx2, yx2, *mvx, *mvy, time, mbType);
       
   905          }
       
   906          else {
       
   907             mvStoreMB(mvRow1, mvRow2, xx2, yx2, *mvx, *mvy, time, mbType);
       
   908          }
       
   909          break;
       
   910       case 1:
       
   911          mvStore(mvRow1, xx2 + 1, yx2, *mvx, *mvy, time, mbType);
       
   912          break;
       
   913       case 2:
       
   914          mvStore(mvRow2, xx2, yx2 + 1, *mvx, *mvy, time, mbType);
       
   915          break;
       
   916       case 3:
       
   917          mvStore(mvRow2, xx2 + 1, yx2 + 1, *mvx, *mvy, time, mbType);
       
   918          break;
       
   919    }
       
   920 }
       
   921 
       
   922 /* {{-output"mvcFree.txt"}} */
       
   923 /*
       
   924  *
       
   925  * mvcFree
       
   926  *
       
   927  * Parameters:
       
   928  *    mvcData        mvcData_t structure
       
   929  *
       
   930  * Function:
       
   931  *    This function frees the dynamic memory allocated by mvcStart.
       
   932  *    mvcFree should be called at least when exiting the main program.
       
   933  *    Alternatively it can be called whenever the playing a video has
       
   934  *    ended.
       
   935  *
       
   936  * Returns:
       
   937  *    Nothing
       
   938  *
       
   939  * Error codes:
       
   940  *    None
       
   941  *
       
   942  *    
       
   943  *    
       
   944  *    
       
   945  */
       
   946 
       
   947 void mvcFree(mvcData_t *mvcData)
       
   948 /* {{-output"mvcFree.txt"}} */
       
   949 {
       
   950    if (mvcData) {
       
   951       if (mvcData->mvRow) free(mvcData->mvRow);
       
   952       mvcData->currMaxX = -1;
       
   953    }
       
   954 }
       
   955 
       
   956 
       
   957 /* {{-output"mvcGetCurrentMVs.txt"}} */
       
   958 /*
       
   959  *
       
   960  * mvcGetCurrentMVs
       
   961  *
       
   962  * Parameters:
       
   963  *       mvcData  mvcData_t structure
       
   964  *       mvx
       
   965  *       mvy
       
   966  *       error    error code
       
   967  *
       
   968  * Function:
       
   969  *       These functions return the motion vectors of the current 
       
   970  *       blocks.
       
   971  *
       
   972  * Returns:
       
   973  *       Changes mvx, mvy and possibly error.
       
   974  *
       
   975  * Error codes:
       
   976  *
       
   977  *    ERR_MVC_CURR_NOT_VALID        if the motion vectors for the current
       
   978  *                                  macroblock do not exist
       
   979  *
       
   980  *    ERR_MVC_CURR_NOT_CODED        if the current macroblock was not coded
       
   981  *
       
   982  *    ERR_MVC_CURR_INTRA            if the current macroblock was coded in
       
   983  *                                  INTRA mode
       
   984  *
       
   985  */
       
   986 void mvcGetCurrentMVs(mvcData_t *mvcData, int *mvx, int *mvy,
       
   987    int16 *error)
       
   988 {
       
   989    int
       
   990       xx2 = mvcData->currX << 1,
       
   991       yx2 = mvcData->currY << 1;
       
   992    mvRowItem_t
       
   993       *mvRow1 = mvcData->mvRow1,
       
   994       *mvRow2 = mvcData->mvRow2;
       
   995    if (mvValid(mvRow1[xx2], yx2, mvcData->currTime) &&
       
   996          mvRow1[xx2].type == MVC_MB_INTER) {
       
   997       mvx[0] = mvRow1[xx2].mvx;
       
   998       mvx[1] = mvRow1[xx2 + 1].mvx;
       
   999       mvx[2] = mvRow2[xx2].mvx;
       
  1000       mvx[3] = mvRow2[xx2 + 1].mvx;
       
  1001       mvy[0] = mvRow1[xx2].mvy;
       
  1002       mvy[1] = mvRow1[xx2 + 1].mvy;
       
  1003       mvy[2] = mvRow2[xx2].mvy;
       
  1004       mvy[3] = mvRow2[xx2 + 1].mvy;
       
  1005    }
       
  1006    else  {
       
  1007       mvx[0] = mvx[1] = mvx[2] = mvx[3] =
       
  1008       mvy[0] = mvy[1] = mvy[2] = mvy[3] = 0;
       
  1009       if mvLegal(mvRow1[xx2], yx2, mvcData->currTime) {
       
  1010          if (mvRow1[xx2].type == MVC_MB_NOT_CODED) {
       
  1011             /*deb("mvcGetCurrentMVs: ERROR - macroblock not coded.\n");*/
       
  1012             *error = ERR_MVC_CURR_NOT_CODED;
       
  1013          }
       
  1014          else if (mvRow1[xx2].type == MVC_MB_INTRA) {
       
  1015             /*deb("mvcGetCurrentMVs: ERROR - INTRA macroblock.\n");*/
       
  1016             *error = ERR_MVC_CURR_INTRA;
       
  1017          }
       
  1018          else {
       
  1019             /*deb("mvcGetCurrentMVs: ERROR - macroblock not valid.\n");*/
       
  1020             *error = ERR_MVC_CURR_NOT_VALID;
       
  1021          }
       
  1022       }
       
  1023       else {
       
  1024          /*deb("mvcGetCurrentMVs: ERROR - macroblock not valid.\n");*/
       
  1025          *error = ERR_MVC_CURR_NOT_VALID;
       
  1026       }
       
  1027    }
       
  1028 }
       
  1029 
       
  1030 /* {{-output"mvcGetNeighbourMVs.txt"}} */
       
  1031 /*
       
  1032  *
       
  1033  * mvcGetCurrNeighbourMVs
       
  1034  * mvcGetPrevNeighbourMVs
       
  1035  *
       
  1036  * Parameters:
       
  1037  *       mvcData  mvcData_t structure
       
  1038  *
       
  1039  *       nmvx     pointer to motion vector x component array
       
  1040  *       nmvy     pointer to motion vector y component array
       
  1041  *                The size of the array must be 6. The indexing of the
       
  1042  *                neighboring motion vectors goes like this:
       
  1043  *                (X = the motion vector which is investigated, i.e.
       
  1044  *                the last one decoded (mvcGetCurrNeighbourMVs) or
       
  1045  *                the one before the last one (mvcGetPrevNeighbourMVs))
       
  1046  *                     2 3
       
  1047  *                   0 X X 4
       
  1048  *                   1 X X 5
       
  1049  *                It is suggested that the following defines are used
       
  1050  *                instead of values:
       
  1051  *                   MVC_XM1_UP (0)
       
  1052  *                   MVC_XM1_DOWN (1)
       
  1053  *                   MVC_YM1_LEFT (2)
       
  1054  *                   MVC_YM1_RIGHT (3)
       
  1055  *                   MVC_XP1_UP (4)
       
  1056  *                   MVC_XP1_DOWN (5)
       
  1057  *                (M stand for minus and P for plus)
       
  1058  *
       
  1059  *       pmvx and pmvy are for mvcGetPrevNeighbourMVs only:
       
  1060  *       pmvx     pointer to the motion vector x component array of the
       
  1061  *                previous macroblock
       
  1062  *       pmvy     pointer to the motion vector y component array of the
       
  1063  *                previous macroblock
       
  1064  *                The size of the array must be 4. The indexing is similar
       
  1065  *                to normal block indexing inside a macroblock:
       
  1066  *                     0 1
       
  1067  *                     2 3
       
  1068  *
       
  1069  *       error    error code
       
  1070  *
       
  1071  * Function:
       
  1072  *       These functions return the motion vectors of the neighboring
       
  1073  *       blocks (on the left side, above or on the right side) of the
       
  1074  *       macroblock which is investigated, i.e.
       
  1075  *          - the last one decoded (mvcGetCurrNeighbourMVs) or
       
  1076  *          - the one before the last one (mvcGetPrevNeighbourMVs))
       
  1077  *
       
  1078  *       The H.263 standard for Overlapped motion compensation for luminance
       
  1079  *       (Annex F.3) is followed, that is:
       
  1080  *       If one of the surrounding macroblocks was not coded, the
       
  1081  *       corresponding remote motion vector is set to zero. If one of the
       
  1082  *       surrounding (macro)blocks was coded in INTRA mode, the corresponding
       
  1083  *       remote motion vector is replaced by the motion vector for the
       
  1084  *       current block expect when in PB-frames mode. In this case (INTRA
       
  1085  *       block in PB-frame mode), the INTRA block's motion vector is used.
       
  1086  *       If the current block is at the border of the picture and therefore
       
  1087  *       a surrounding block is not present, the corresponding remote motion
       
  1088  *       vector is replaced by the current motion vector.
       
  1089  *
       
  1090  *       mvcGetPrevNeighbourMVs also returns the motion vector for the
       
  1091  *       previous macroblock.
       
  1092  *
       
  1093  * Returns:
       
  1094  *       Changes nmvx, nmvy, pmvx, pmvy and possibly error.
       
  1095  *
       
  1096  * Error codes:
       
  1097  *    ERR_MVC_NO_PREV_MB            if the current MB has x coordinate 0 and
       
  1098  *                                  mvcGetPrevNeighbourMVs is called
       
  1099  *
       
  1100  *    ERR_MVC_NEIGHBOUR_NOT_VALID   if one of the neighboring MVs is not
       
  1101  *                                  valid, i.e. it has not been updated
       
  1102  *                                  for this frame. The MV in nmvx and nmvy
       
  1103  *                                  is set to zero.
       
  1104  *
       
  1105  *    for mvcGetPrevNeighbourMVs only:
       
  1106  *    ERR_MVC_PREV_NOT_VALID        if the motion vectors for the previous
       
  1107  *                                  macroblock do not exist
       
  1108  *
       
  1109  *    ERR_MVC_PREV_NOT_CODED        if the previous macroblock was not coded
       
  1110  *
       
  1111  *    ERR_MVC_PREV_INTRA            if the previous macroblock was coded in
       
  1112  *                                  INTRA mode
       
  1113  *
       
  1114  *    
       
  1115  *    
       
  1116  *    
       
  1117  *    
       
  1118  *    
       
  1119  *    
       
  1120  */
       
  1121 
       
  1122 void mvcGetCurrNeighbourMVs(mvcData_t *mvcData, int *nmvx, int *nmvy,
       
  1123    int16 *error)
       
  1124 /* {{-output"mvcGetNeighbourMVs.txt"}} */
       
  1125 {
       
  1126    mvRowItem_t
       
  1127       *mvRow1 = mvcData->mvRow1;
       
  1128    int xx2 = mvcData->currX << 1;
       
  1129 
       
  1130    mvcGetNeighbourMVs(mvcData, mvcData->currX, mvcData->currY,
       
  1131       mvcData->currTime, nmvx, nmvy, 0, error);
       
  1132    if (*error)   {
       
  1133       if mvLegal(mvRow1[xx2], mvcData->currY << 1, mvcData->currTime) {
       
  1134          if (mvRow1[xx2].type == MVC_MB_NOT_CODED) {
       
  1135             /*deb("mvcGetPrevNeighbourMVs: ERROR - macroblock not coded.\n");*/
       
  1136             *error = ERR_MVC_CURR_NOT_CODED;
       
  1137          }
       
  1138          else if (mvRow1[xx2].type == MVC_MB_INTRA) {
       
  1139             /*deb("mvcGetPrevNeighbourMVs: ERROR - INTRA macroblock.\n");*/
       
  1140             *error = ERR_MVC_CURR_INTRA;
       
  1141          }
       
  1142          else {
       
  1143             /*deb("mvcGetPrevNeighbourMVs: ERROR - macroblock not valid.\n");*/
       
  1144             *error = ERR_MVC_CURR_NOT_VALID;
       
  1145          }
       
  1146       }
       
  1147       else {
       
  1148          /*deb("mvcGetPrevNeighbourMVs: ERROR - macroblock not valid.\n");*/
       
  1149          *error = ERR_MVC_CURR_NOT_VALID;
       
  1150       }
       
  1151    }
       
  1152 }
       
  1153 
       
  1154 /* {{-output"mvcGetPrevNeighbourMVs.txt"}} */
       
  1155 void mvcGetPrevNeighbourMVs(mvcData_t *mvcData, int *nmvx, int *nmvy,
       
  1156    int *pmvx, int *pmvy, u_char *fourMVs, int16 *error)
       
  1157 /* {{-output"mvcGetPrevNeighbourMVs.txt"}} */
       
  1158 {
       
  1159    int
       
  1160       currX = mvcData->currX,
       
  1161       currY = mvcData->currY;
       
  1162    mvRowItem_t
       
  1163       *mvRow1 = mvcData->mvRow1,
       
  1164       *mvRow2 = mvcData->mvRow2;
       
  1165 
       
  1166    if (currX > 0) {
       
  1167       int xx2 = (currX - 1) << 1;
       
  1168       mvcGetNeighbourMVs(mvcData, currX - 1, currY,
       
  1169          mvcData->currTime, nmvx, nmvy, 1, error);
       
  1170       if (mvValid(mvRow1[xx2], currY << 1, mvcData->currTime) &&
       
  1171          mvRow1[xx2].type == MVC_MB_INTER) {
       
  1172          pmvx[0] = mvRow1[xx2].mvx;
       
  1173          pmvx[1] = mvRow1[xx2 + 1].mvx;
       
  1174          pmvx[2] = mvRow2[xx2].mvx;
       
  1175          pmvx[3] = mvRow2[xx2 + 1].mvx;
       
  1176          pmvy[0] = mvRow1[xx2].mvy;
       
  1177          pmvy[1] = mvRow1[xx2 + 1].mvy;
       
  1178          pmvy[2] = mvRow2[xx2].mvy;
       
  1179          pmvy[3] = mvRow2[xx2 + 1].mvy;
       
  1180          *fourMVs = mvRow1[xx2].fourMVs;
       
  1181       }
       
  1182       else {
       
  1183          pmvx[0] = pmvx[1] = pmvx[2] = pmvx[3] =
       
  1184          pmvy[0] = pmvy[1] = pmvy[2] = pmvy[3] = 0;
       
  1185          *fourMVs = 0;
       
  1186          if mvLegal(mvRow1[xx2], currY << 1, mvcData->currTime) {
       
  1187             if (mvRow1[xx2].type == MVC_MB_NOT_CODED) {
       
  1188                /*deb("mvcGetPrevNeighbourMVs: ERROR - macroblock not coded.\n");*/
       
  1189                *error = ERR_MVC_PREV_NOT_CODED;
       
  1190             }
       
  1191             else if (mvRow1[xx2].type == MVC_MB_INTRA) {
       
  1192                /*deb("mvcGetPrevNeighbourMVs: ERROR - INTRA macroblock.\n");*/
       
  1193                *error = ERR_MVC_PREV_INTRA;
       
  1194             }
       
  1195             else {
       
  1196                /*deb("mvcGetPrevNeighbourMVs: ERROR - macroblock not valid.\n");*/
       
  1197                *error = ERR_MVC_PREV_NOT_VALID;
       
  1198             }
       
  1199          }
       
  1200          else {
       
  1201             /*deb("mvcGetPrevNeighbourMVs: ERROR - macroblock not valid.\n");*/
       
  1202             *error = ERR_MVC_PREV_NOT_VALID;
       
  1203          }
       
  1204       }
       
  1205    }
       
  1206    else {
       
  1207       /*deb("mvcGetPrevNeighbourMVs: ERROR - no previous macroblock.\n");*/
       
  1208       *error = ERR_MVC_NO_PREV_MB;
       
  1209    }
       
  1210 }
       
  1211 
       
  1212 
       
  1213 /* {{-output"mvcGetPrevMVFsAndMVBs.txt"}} */
       
  1214 /*
       
  1215  *
       
  1216  * mvcGetPrevMVFsAndMVBs
       
  1217  *
       
  1218  * Parameters:
       
  1219  *    mvcData           mvcData_t structure
       
  1220  *
       
  1221  *    mvfx              the resulting forward motion vector
       
  1222  *    mvfy
       
  1223  *
       
  1224  *    mvbx              the resulting backward motion vector
       
  1225  *    mvby
       
  1226  *
       
  1227  *    fourMVs           1 if there is four motion vectors per macroblock
       
  1228  *                      0 otherwise
       
  1229  *
       
  1230  * Function:
       
  1231  *    This function gets the forward and backward motion vectors for the
       
  1232  *    previous B macroblock.
       
  1233  *
       
  1234  * Returns:
       
  1235  *    Changes *mvfx, *mvfy, *mvbx, *mvby and *fourMVs.
       
  1236  *
       
  1237  * Error codes:
       
  1238  *    ERR_MVC_NO_PREV_MB            if the current MB has x coordinate 0 and
       
  1239  *                                  mvcGetPrevNeighbourMVs is called
       
  1240  *
       
  1241  *    ERR_MVC_PREV_NOT_VALID        if the motion vectors for the previous
       
  1242  *                                  macroblock do not exist
       
  1243  *
       
  1244  *    
       
  1245  */
       
  1246 
       
  1247 void mvcGetPrevMVFsAndMVBs(mvcData_t *mvcData, int *mvfx, int *mvfy,
       
  1248    int *mvbx, int *mvby, u_char *fourMVs, int16 *error)
       
  1249 /* {{-output"mvcGetPrevMVFsAndMVBs.txt"}} */
       
  1250 {
       
  1251    mvBFBufItem_t
       
  1252       *mvFBuf = mvcData->mvFBufArray[mvcData->mvBFBufIndex ^ 1],
       
  1253       *mvBBuf = mvcData->mvBBufArray[mvcData->mvBFBufIndex ^ 1];
       
  1254    int i;
       
  1255 
       
  1256    if (mvcData->currX > 0) {
       
  1257       if (mvBBuf[0].x == mvcData->currX - 1 &&
       
  1258          mvValid(mvBBuf[0], mvcData->currY, mvcData->currTime)) {
       
  1259          *fourMVs = mvBBuf[0].fourMVs;
       
  1260          for (i = 0; i < 4; i++) {
       
  1261             mvfx[i] = mvFBuf[i].mvx;
       
  1262             mvfy[i] = mvFBuf[i].mvy;
       
  1263             mvbx[i] = mvBBuf[i].mvx;
       
  1264             mvby[i] = mvBBuf[i].mvy;
       
  1265          }
       
  1266       }
       
  1267       else {
       
  1268          /*deb("mvcGetPrevMVFsAndMVBs: ERROR - PREV_NOT_VALID.\n");*/
       
  1269          *error = ERR_MVC_PREV_NOT_VALID;
       
  1270       }
       
  1271    }
       
  1272    else {
       
  1273       /*deb("mvcGetPrevMVFsAndMVBs: ERROR - NO_PREV_MB.\n");*/
       
  1274       *error = ERR_MVC_NO_PREV_MB;
       
  1275    }
       
  1276 }
       
  1277 
       
  1278 
       
  1279 /* {{-output"mvcMarkMB.txt"}} */
       
  1280 /*
       
  1281  *
       
  1282  * mvcMarkMBIntra
       
  1283  * mvcMarkMBNotCoded
       
  1284  *
       
  1285  * Parameters:
       
  1286  *    mvcData        mvcData_t structure
       
  1287  *    x              the x coordinate of the MB (0 .. maxX)
       
  1288  *    y              the y coordinate of the MB
       
  1289  *                   (0 .. macroblock rows in frame - 1)
       
  1290  *
       
  1291  *    time           a value which is related to the time when the current
       
  1292  *                   frame must be shown. This value should be unique
       
  1293  *                   among a relatively small group of consecutive frames.
       
  1294  *
       
  1295  * Function:
       
  1296  *    These functions are used to mark that the macroblock is either
       
  1297  *    intra coded or not coded at all. The information is used when
       
  1298  *    deciding the neighboring motion vectors of a macroblock in
       
  1299  *    mvcGetPrevNeighbourMVs and mvcGetCurrNeighbourMVs.
       
  1300  *    Note that mvcMarkMBIntra should not be called in case of
       
  1301  *    INTRA block in PB-frame mode. Instead mvcCalcMV should be used.
       
  1302  *
       
  1303  * Returns:
       
  1304  *    Nothing
       
  1305  *
       
  1306  * Error codes:
       
  1307  *    None
       
  1308  *
       
  1309  *    
       
  1310  *    
       
  1311  */
       
  1312 
       
  1313 void mvcMarkMBIntra(mvcData_t *mvcData, int x, int y, int time)
       
  1314 /* {{-output"mvcMarkMB.txt"}} */
       
  1315 {
       
  1316    int
       
  1317       xx2 = x << 1,
       
  1318       yx2 = y << 1;
       
  1319    mvRowItem_t
       
  1320       *mvRow1,
       
  1321       *mvRow2;
       
  1322 
       
  1323    updateRowPointers(x, y, time);
       
  1324    mvRow1 = mvcData->mvRow1;
       
  1325    mvRow2 = mvcData->mvRow2;
       
  1326    mvStoreMB(mvRow1, mvRow2, xx2, yx2, MVD_INTRA, MVD_INTRA, time, MVC_MB_INTRA);
       
  1327 }
       
  1328 
       
  1329 /* {{-output"mvcMarkMBNotCoded.txt"}} */
       
  1330 void mvcMarkMBNotCoded(mvcData_t *mvcData, int x, int y, int time)
       
  1331 /* {{-output"mvcMarkMBNotCoded.txt"}} */
       
  1332 {
       
  1333    int
       
  1334       xx2 = x << 1,
       
  1335       yx2 = y << 1;
       
  1336    mvRowItem_t
       
  1337       *mvRow1,
       
  1338       *mvRow2;
       
  1339 
       
  1340    updateRowPointers(x, y, time);
       
  1341    mvRow1 = mvcData->mvRow1;
       
  1342    mvRow2 = mvcData->mvRow2;
       
  1343    mvStoreMB(mvRow1, mvRow2, xx2, yx2, MVD_NOT_CODED,
       
  1344       MVD_NOT_CODED, time, MVC_MB_NOT_CODED);
       
  1345 }
       
  1346 
       
  1347 
       
  1348 /* {{-output"mvcStart.txt"}} */
       
  1349 /*
       
  1350  *
       
  1351  * mvcStart
       
  1352  *
       
  1353  * Parameters:
       
  1354  *       mvcData        mvcData_t structure
       
  1355  *
       
  1356  *       maxX           the largest x coordinate possible for a macroblock
       
  1357  *                      If maxX if different from maxX when the function was
       
  1358  *                      last called, a new dynamic memory allocation is made.
       
  1359  *
       
  1360  *       lumWidth       Luminance width
       
  1361  *
       
  1362  *       lumHeight      Luminance height
       
  1363  *
       
  1364  *       error          error code
       
  1365  *
       
  1366  * Function:
       
  1367  *       This function initialises motion vector buffers. It also allocates
       
  1368  *       buffer memory if needed.
       
  1369  *       One should call mvcStart in the beginning of each video sequence.
       
  1370  *
       
  1371  * Returns:
       
  1372  *       Nothing
       
  1373  *
       
  1374  * Error codes:
       
  1375  *       ERR_MVC_ALLOC1          dynamic allocation error
       
  1376  *       ERR_MVC_MAX_X_ILLEGAL   maxX <= 0
       
  1377  *
       
  1378  *      
       
  1379  *      
       
  1380  *  
       
  1381  */
       
  1382 
       
  1383 void mvcStart(mvcData_t *mvcData, int maxX, int lumWidth, int lumHeight, int16 *error)
       
  1384 /* {{-output"mvcStart.txt"}} */
       
  1385 {
       
  1386    int
       
  1387       i, j, /* loop variables */
       
  1388       rowSize; /* the number of items in prevMV?Row */
       
  1389 
       
  1390    if (maxX < 0) {
       
  1391       *error = ERR_MVC_MAX_X_ILLEGAL;
       
  1392       return;
       
  1393    }
       
  1394 
       
  1395    rowSize = (maxX + 1) << 1;
       
  1396 
       
  1397    if (mvcData->currMaxX != maxX || mvcData->mvRow == NULL) {
       
  1398       /* frame size changed */
       
  1399 
       
  1400       if (mvcData->mvRow) free(mvcData->mvRow);
       
  1401 
       
  1402       mvcData->mvRow = (mvRowItem_t *) vdcMalloc(
       
  1403          rowSize * 3 * sizeof(mvRowItem_t));
       
  1404       if (mvcData->mvRow == NULL) {
       
  1405          deb("mvcStart: ERROR - memory allocation failed.\n");
       
  1406          *error = ERR_MVC_ALLOC1;
       
  1407          return;
       
  1408       }
       
  1409 
       
  1410       mvcData->currMaxX = maxX;
       
  1411    }
       
  1412    
       
  1413    /* Horizontal motion vector range when PLUSTYPE present and UUI = 1
       
  1414       See Table D.1/H.263 */
       
  1415    if (mvcData->currLumHeight != lumHeight)
       
  1416    {
       
  1417       mvcData->currLumHeight = lumHeight;
       
  1418       if ((lumHeight>=4)&&(lumHeight<=288))
       
  1419       {
       
  1420          mvcData->mvRangeLowY = -320;
       
  1421          mvcData->mvRangeHighY = 315;
       
  1422       }
       
  1423       else if ((lumHeight>=292)&&(lumHeight<=576))
       
  1424       {
       
  1425          mvcData->mvRangeLowY = -640;
       
  1426          mvcData->mvRangeHighY = 635;
       
  1427       }
       
  1428       else if ((lumHeight>=580)&&(lumHeight<=1152))
       
  1429       {
       
  1430          mvcData->mvRangeLowY = -1280;
       
  1431          mvcData->mvRangeHighY = 1275;
       
  1432       }
       
  1433    }
       
  1434 
       
  1435    /* Vertical motion vector range when PLUSTYPE present and UUI = 1
       
  1436       See Table D.2/H.263 */
       
  1437    if (mvcData->currLumWidth != lumWidth)
       
  1438    {
       
  1439       mvcData->currLumWidth = lumWidth;
       
  1440       if ((lumWidth>=4)&&(lumWidth<=352))
       
  1441       {
       
  1442          mvcData->mvRangeLowX = -320;
       
  1443          mvcData->mvRangeHighX = 315;
       
  1444       }
       
  1445       else if ((lumWidth>=356)&&(lumWidth<=704))
       
  1446       {
       
  1447          mvcData->mvRangeLowX = -640;
       
  1448          mvcData->mvRangeHighX = 635;
       
  1449       }
       
  1450       else if ((lumWidth>=708)&&(lumWidth<=1408))
       
  1451       {
       
  1452          mvcData->mvRangeLowX = -1280;
       
  1453          mvcData->mvRangeHighX = 1275;
       
  1454       }
       
  1455       else if ((lumWidth>=1412)&&(lumWidth<=2048))
       
  1456       {
       
  1457          mvcData->mvRangeLowX = -2560;
       
  1458          mvcData->mvRangeHighX = 2555;
       
  1459       }
       
  1460    }
       
  1461    /* Set time to be impossible */
       
  1462    for (i = 0; i < 3 * rowSize; i++) {
       
  1463       mvcData->mvRow[i].time = -2;
       
  1464    }
       
  1465 
       
  1466    for (j = 0; j < 2; j++) {
       
  1467       for (i = 0; i < 4; i++) {
       
  1468          mvcData->mvFBufArray[j][i].time = -2;
       
  1469          mvcData->mvBBufArray[j][i].time = -2;
       
  1470       }
       
  1471    }
       
  1472 
       
  1473    mvcData->currX = -1;
       
  1474    mvcData->currY = -1;
       
  1475    mvcData->currTime = -2;
       
  1476    mvcData->mvRowIndex = 0;
       
  1477    mvcData->mvBFBufIndex = 0;
       
  1478    mvcData->prevPredMode = 3;
       
  1479 }
       
  1480 
       
  1481 
       
  1482 /* Local functions */
       
  1483 
       
  1484 
       
  1485 
       
  1486 /*
       
  1487  *
       
  1488  * mvcGetNeighbourMVs
       
  1489  *
       
  1490  * Parameters:
       
  1491  *       mvcData  mvcData_t structure
       
  1492  *       x
       
  1493  *       y        macroblock coordinates
       
  1494  *       time     time reference
       
  1495  *       nmvx     pointer to motion vector x component array
       
  1496  *       nmvy     pointer to motion vector y component array
       
  1497  *                See mvcGetCurrNeighbourMVs/mvcGetPrevNeighbourMVs for
       
  1498  *                description.
       
  1499  *       prevFlag If this flag is set, the previous border values should
       
  1500  *                be used.
       
  1501  *       error    error code
       
  1502  *
       
  1503  * Function:
       
  1504  *       This function return the motion vectors of the neighboring
       
  1505  *       blocks (on the left side, above or on the right side) of the
       
  1506  *       macroblock which is investigated. mvcGetNeighbourMVs is used
       
  1507  *       by mvcGetCurrNeighbourMVs and mvcGetPrevNeighbourMVs.
       
  1508  *       See also the functional description for these functions.
       
  1509  *
       
  1510  * Returns:
       
  1511  *       Changes nmvx and nmvy and possibly error.
       
  1512  *
       
  1513  * Error codes:
       
  1514  *    ERR_MVC_NEIGHBOUR_NOT_VALID   if one of the neighboring MVs is not
       
  1515  *                                  valid, i.e. it has not been updated
       
  1516  *                                  for this frame. The MV in nmvx and nmvy
       
  1517  *                                  is set to zero.
       
  1518  *
       
  1519  *    
       
  1520  */
       
  1521 
       
  1522 static void mvcGetNeighbourMVs(mvcData_t *mvcData, int x, int y, int time,
       
  1523    int *nmvx, int *nmvy, int prevFlag, int16 *error)
       
  1524 {
       
  1525    int
       
  1526       xx2 = x << 1,
       
  1527       yx2 = y << 1,
       
  1528       xtmp,
       
  1529       ytmp,
       
  1530       rightOfBorder,
       
  1531       downOfBorder,
       
  1532       leftOfBorder;
       
  1533    mvRowItem_t
       
  1534       *mvRow0 = mvcData->mvRow0,
       
  1535       *mvRow1 = mvcData->mvRow1,
       
  1536       *mvRow2 = mvcData->mvRow2;
       
  1537 
       
  1538    if (prevFlag)  {
       
  1539       rightOfBorder = mvcData->rightOfBorderPrev;
       
  1540       downOfBorder = (mvcData->fSS)?mvcData->downOfBorderPrev:(y==0);
       
  1541       leftOfBorder = 0;
       
  1542    }
       
  1543    else  {
       
  1544       rightOfBorder = mvcData->rightOfBorder;
       
  1545       downOfBorder = (mvcData->fSS)?mvcData->downOfBorder:(y==0);
       
  1546       leftOfBorder = (mvcData->fSS)?(x == mvcData->currMaxX)||(mvcData->leftOfBorder):(x == mvcData->currMaxX);
       
  1547    }
       
  1548    //if (x > 0) {
       
  1549    if (!rightOfBorder)  {
       
  1550       xtmp = xx2 - 1;
       
  1551       mvcCheckAndSet(mvRow1, xtmp, yx2, time, MVC_XM1_UP, nmvx, nmvy, 
       
  1552          mvRow1, xx2, yx2, error);
       
  1553       mvcCheckAndSet(mvRow2, xtmp, yx2 + 1, time, MVC_XM1_DOWN, nmvx, nmvy, 
       
  1554          mvRow2, xx2, yx2 + 1, error);
       
  1555    }
       
  1556    else {
       
  1557       mvcSetToCurrent(mvRow1, xx2, yx2, time, MVC_XM1_UP, nmvx, nmvy, 
       
  1558          error);
       
  1559       mvcSetToCurrent(mvRow2, xx2, yx2 + 1, time, MVC_XM1_DOWN, nmvx, nmvy, 
       
  1560          error);
       
  1561    }
       
  1562 
       
  1563    //if (y > 0) {
       
  1564    if (!downOfBorder)   {
       
  1565       ytmp = yx2 - 1;
       
  1566       mvcCheckAndSet(mvRow0, xx2, ytmp, time, MVC_YM1_LEFT, nmvx, nmvy, 
       
  1567          mvRow1, xx2, yx2, error);
       
  1568       mvcCheckAndSet(mvRow0, xx2 + 1, ytmp, time, MVC_YM1_RIGHT, nmvx, nmvy,
       
  1569          mvRow1, xx2 + 1, yx2, error);
       
  1570    }
       
  1571    else {
       
  1572       mvcSetToCurrent(mvRow1, xx2, yx2, time, MVC_YM1_LEFT, nmvx, nmvy, 
       
  1573          error);
       
  1574       mvcSetToCurrent(mvRow1, xx2 + 1, yx2, time, MVC_YM1_RIGHT, nmvx, nmvy, 
       
  1575          error);
       
  1576    }
       
  1577 
       
  1578    //if (x < mvcData->currMaxX) {
       
  1579    if (!leftOfBorder) {
       
  1580       xtmp = xx2 + 2;
       
  1581       mvcCheckAndSet(mvRow1, xtmp, yx2, time, MVC_XP1_UP, nmvx, nmvy, 
       
  1582          mvRow1, xtmp - 1, yx2, error);
       
  1583       mvcCheckAndSet(mvRow2, xtmp, yx2 + 1, time, MVC_XP1_DOWN, nmvx, nmvy,
       
  1584          mvRow2, xtmp -1, yx2 + 1, error);
       
  1585    }
       
  1586    else {
       
  1587       xtmp = xx2 + 1;
       
  1588       mvcSetToCurrent(mvRow1, xtmp, yx2, time, MVC_XP1_UP, nmvx, nmvy, 
       
  1589          error);
       
  1590       mvcSetToCurrent(mvRow2, xtmp, yx2 + 1, time, MVC_XP1_DOWN, nmvx, nmvy, 
       
  1591          error);
       
  1592    }
       
  1593 }
       
  1594 
       
  1595 
       
  1596 
       
  1597 /*
       
  1598  * mvcCheckAndSet
       
  1599  *
       
  1600  * Parameters:
       
  1601  *    mvRowPtr    Source row item pointer
       
  1602  *    xind        x index of the source block
       
  1603  *    yind        y index of the source block
       
  1604  *    timeref     time reference
       
  1605  *    nind        index to motion vector arrays ( x and y)
       
  1606  *    nmvx        pointer to motion vector x component array
       
  1607  *    nmvy        pointer to motion vector y component array
       
  1608  *    cmvRowPtr   Target row item pointer
       
  1609  *    cxind       x index of the target block
       
  1610  *    cyind       y index of the target block
       
  1611  *    error       error code
       
  1612  *
       
  1613  * Function:
       
  1614  *       Sets the correct value for neighboring motion vector
       
  1615  *       used from: mvcGetNeighbourMVs 
       
  1616  *
       
  1617  * Returns:
       
  1618  *       Nothing
       
  1619  *
       
  1620  * Error codes:
       
  1621  *
       
  1622  */
       
  1623 
       
  1624 __inline static void mvcCheckAndSet( 
       
  1625       mvRowItem_t *mvRowPtr, int xind, int yind, int timeref, int nind, 
       
  1626       int *nmvx, int *nmvy, mvRowItem_t *cmvRowPtr, int cxind, int cyind,
       
  1627       int16 *error)
       
  1628 {
       
  1629 
       
  1630    if (mvLegal(mvRowPtr[xind], yind, timeref))  {
       
  1631       if (mvRowPtr[xind].mvx >= MVD_UMIN_V2) {
       
  1632          nmvx[nind] = mvRowPtr[xind].mvx; 
       
  1633          nmvy[nind] = mvRowPtr[xind].mvy; 
       
  1634       } 
       
  1635       else if (mvRowPtr[xind].mvx == MVD_INTRA) { 
       
  1636          if (mvLegal(cmvRowPtr[cxind], cyind, timeref)) { 
       
  1637             if (mvValid(cmvRowPtr[cxind], cyind, timeref)) { 
       
  1638                nmvx[nind] = cmvRowPtr[cxind].mvx; 
       
  1639                nmvy[nind] = cmvRowPtr[cxind].mvy; 
       
  1640             } 
       
  1641             else /* Not coded macroblock */ 
       
  1642                nmvx[nind] = nmvy[nind] = 0; 
       
  1643          } 
       
  1644          else { 
       
  1645             deb("mvcCheckAndSet: ERROR - neighbour not valid.\n"); 
       
  1646             *error = ERR_MVC_NEIGHBOUR_NOT_VALID; 
       
  1647             nmvx[nind] = nmvy[nind] = 0; 
       
  1648          } 
       
  1649       } 
       
  1650       else { /* MVD_NOT_CODED */ 
       
  1651          nmvx[nind] = nmvy[nind] = 0; 
       
  1652       } 
       
  1653    } 
       
  1654    else { 
       
  1655       deb("mvcCheckAndSet: ERROR - neighbour not valid.\n"); 
       
  1656       *error = ERR_MVC_NEIGHBOUR_NOT_VALID; 
       
  1657       nmvx[nind] = nmvy[nind] = 0; 
       
  1658    }
       
  1659 }
       
  1660 
       
  1661 /*
       
  1662  * mvcSetToCurrent
       
  1663  *
       
  1664  * Parameters:
       
  1665  *    mvRowPtr    Current row item pointer
       
  1666  *    xind        x index of the block
       
  1667  *    yind        y index of the block
       
  1668  *    timeref     time reference
       
  1669  *    nind        index to motion vector arrays ( x and y)
       
  1670  *    nmvx        pointer to motion vector x component array
       
  1671  *    nmvy        pointer to motion vector y component array
       
  1672  *    error       error code
       
  1673  *
       
  1674  * Function:
       
  1675  *       Sets the correct value for neighboring motion vector using current
       
  1676  *       motion vector, used in cases of border used from: mvcGetNeighbourMVs
       
  1677  *
       
  1678  * Returns:
       
  1679  *       Nothing
       
  1680  *
       
  1681  * Error codes:
       
  1682  *
       
  1683  * History
       
  1684  */
       
  1685 
       
  1686 __inline static void mvcSetToCurrent( 
       
  1687       mvRowItem_t *mvRowPtr, int xind, int yind, int timeref, int nind,
       
  1688       int *nmvx, int *nmvy, int16 *error)
       
  1689 {
       
  1690    if (mvValid(mvRowPtr[xind], yind, timeref)) { 
       
  1691       nmvx[nind] = mvRowPtr[xind].mvx; 
       
  1692       nmvy[nind] = mvRowPtr[xind].mvy; 
       
  1693    } 
       
  1694    else { 
       
  1695       deb("mvcSetToCurrent: ERROR - neighbour not valid.\n"); 
       
  1696       *error = ERR_MVC_NEIGHBOUR_NOT_VALID; 
       
  1697       nmvx[nind] = nmvy[nind] = 0; 
       
  1698    }
       
  1699 }
       
  1700 
       
  1701 // End of File