--- a/videoeditorengine/h263decoder/src/vdcmvc.cpp Fri Jan 29 14:08:33 2010 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,1701 +0,0 @@
-/*
-* 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 vector calculations and storage.
-*
-*/
-
-
-
-
-#include "h263dConfig.h"
-
-#include "vdcmvc.h"
-
-#include "core.h"
-#include "errcodes.h"
-#include "debug.h"
-
-
-/*
- * Defines
- */
-
-#define NEIGHBOUR_SIZE 2 /* The size for neighbour array */
-#define MVD_NOT_CODED -32767 /* Macroblock is not coded in mvcTable_t */
-#define MVD_INTRA -32765 /* Marks intra macroblock in mvcTable_t */
-
-#define MVD_UMIN_MPEG4 -10240
-
-#define MVD_MIN -160 /* The minimum for mvd. */
-#define MVD_MAX 155 /* The maximum for mvd. */
-#define MVD_UMIN_V1 -315 /* The minimum for MV in unrestricted mode (v1) */
-#define MVD_UMAX_V1 315 /* The maximum for MV in unrestricted mode (v1) */
-#define MVD_UMIN_V2 -32000 /* The minimum for MV in unrestricted mode (v2)
- Note: this value is used to check the validity
- of MVs. If there is no MV for a MB
- MVD_NOT_CODED or MVD_INTRA are used, and
- therefore any value bigger than those
- suits for this definition. In H.263 v2
- unlimited submode, MVs can have any length
- within a picture (plus 15-pixel border),
- and therefore this definition is set to small
- enough value. */
-#define MVD_155 155 /* MV for 15.5 */
-#define MVD_160 160 /* MV for 16 */
-#define MVD_320 320 /* MV for 32 */
-/* It is assumed that motion vector values are signed and in order
- (for example MV for 15.5 < MV for 16).
- No other assumptions are made. */
-
-
-/*
- * Macros
- */
-
-/* mvValid checks if the specified item is a valid motion vector */
-/* Note: MVD_NOT_CODED and MVD_INTRA are very small negative numbers.
- Thus, we can use the minimum MV for H.263 Annex D unlimited
- submode to check the validity of a passed item. Actually,
- we could use any value larger than MVD_NOT_CODED and MVD_INTRA
- and smaller than or equal to the minimum MV. */
-#define mvValid(d1item, d1y, d1time) \
- (d1item.mvx >= MVD_UMIN_V2 \
- && d1item.y == (d1y) && d1item.time == (d1time))
-
-
-#define mvValidMPEG(d1item, d1y, d1time) \
- (d1item.mvx >= MVD_UMIN_MPEG4 \
- && d1item.y == (d1y) && d1item.time == (d1time))
-
-/* mvLegal cheks if the specified item has been updated to either contain
- a motion vector or not coded / intra information */
-#define mvLegal(d5item, d5y, d5time) \
- (d5item.y == (d5y) && d5item.time == (d5time))
-
-/* mvStore puts given arguments into the motion vector array
- Used from: mvcCalcMV */
-#define mvStore(d2row, d2x, d2y, d2mvx, d2mvy, d2time, d2type) \
- d2row[d2x].mvx = d2mvx; d2row[d2x].mvy = d2mvy; \
- d2row[d2x].y = d2y; d2row[d2x].time = d2time; d2row[d2x].fourMVs = 1; \
- d2row[d2x].type = d2type
-
-/* mvStoreMB puts given arguments into the motion vector array for the
- whole macroblock
- Used from: mvcCalcMV, mvcMarkMBIntra, mvcMarkMBNotCoded */
-#define mvStoreMB(d4row1, d4row2, d4x, d4y, d4mvx, d4mvy, d4time, d4type) \
- d4row1[d4x].mvx = d4row1[d4x + 1].mvx = \
- d4row2[d4x].mvx = d4row2[d4x + 1].mvx = d4mvx; \
- d4row1[d4x].mvy = d4row1[d4x + 1].mvy = \
- d4row2[d4x].mvy = d4row2[d4x + 1].mvy = d4mvy; \
- d4row1[d4x].y = d4row1[d4x + 1].y = d4y; \
- d4row2[d4x].y = d4row2[d4x + 1].y = d4y + 1; \
- d4row1[d4x].time = d4row1[d4x + 1].time = \
- d4row2[d4x].time = d4row2[d4x + 1].time = time; \
- d4row1[d4x].fourMVs = d4row1[d4x + 1].fourMVs = \
- d4row2[d4x].fourMVs = d4row2[d4x + 1].fourMVs = 0; \
- d4row1[d4x].type = d4row1[d4x + 1].type = \
- d4row2[d4x].type = d4row2[d4x + 1].type = (d4type)
-
-/* updateRowPointers checks if currX, currY or currTime have changed
- and updates them. It also updates mvRow0, mvRow1 and mvRow2.
- Used from: mvcCalcMV, mvcMarkMBIntra, mvcMarkMBNotCoded */
-#define updateRowPointers(d3x, d3y, d3time) \
- if (d3x != mvcData->currX) \
- mvcData->currX = d3x; \
- if (d3y != mvcData->currY) { \
- int \
- mvRowIndex, \
- currMaxX = mvcData->currMaxX; \
- mvRowItem_t *mvRow = mvcData->mvRow; \
- mvcData->currY = d3y; \
- mvcData->mvRowIndex = mvRowIndex = (mvcData->mvRowIndex + 2) % 3; \
- mvcData->mvRow0 = &mvRow[(currMaxX + 1) * 2 * mvRowIndex]; \
- mvcData->mvRow1 = &mvRow[(currMaxX + 1) * 2 * ((mvRowIndex + 1) % 3)]; \
- mvcData->mvRow2 = &mvRow[(currMaxX + 1) * 2 * ((mvRowIndex + 2) % 3)]; \
- } \
- if (d3time != mvcData->currTime) \
- mvcData->currTime = d3time
-
-/* mvcInvMVD takes the other one of the possible MVD values defined in
- H.263 Recommendation */
-#define mvcInvMVD(invMv) \
- (invMv < 0) ? \
- MVD_320 + invMv : \
- -MVD_320 + invMv
-
-/* sign123(x) returns
- 1 if x < 0,
- 2 if x > 0,
- 3 if x == 0
- In other words,
- bit 0 = 1 if x <= 0,
- bit 1 = 1 if x >= 0 */
-#define sign123(x) ((x == 0) ? 3 : (x < 0) ? 1 : 2)
-
-
-/*
- * Local prototypes
- */
-
-static void mvcGetNeighbourMVs(mvcData_t *mvcData, int x, int y, int time,
- int *nmvx, int *nmvy, int prevFlag, int16 *error);
-
-__inline static void mvcCheckAndSet(
- mvRowItem_t *mvRowPtr, int xind, int yind, int time, int nind,
- int *nmvx, int *nmvy, mvRowItem_t *cmvRowPtr, int cxind, int cyind,
- int16 *error);
-
-__inline static void mvcSetToCurrent(
- mvRowItem_t *mvRowPtr, int xind, int yind, int time, int nind,
- int *nmvx, int *nmvy, int16 *error);
-
-
-/*
- * Global functions
- */
-
-
-/* {{-output"mvcSetBorders.txt"}} */
-/*
- *
- * mvcSetBorders
- *
- * Parameters:
- * mvcData mvcData_t structure
- * x the x coordinate of the MB (0 .. maxX)
- * y the y coordinate of the MB
- * (0 .. macroblock rows in frame - 1)
- * mba Macroblock address of starting MB of the slice. This
- * value SHOULD be set to -1 if Annex K is not in use.
- * numMBsInMBLine Number of MBs in MB line
- * rightOfBorder There is a border on the left of the current MB
- * downOfBorder There is a border on top of the current MB
- *
- * Function:
- * This function calculates the borders of GOBs and Slices..This function
- * SHOULD be called before mvcCalcMV.....
- *
- * Returns:
- * Nothing
- *
- * Error codes:
- * None
- *
- */
-
-void mvcSetBorders(
- mvcData_t *mvcData, int x, int y, int mba, int numMBsInMBLine,
- int *rightOfBorder, int *downOfBorder
-)
-{
- int
- upRightMBIsStart;
-
- if (mvcData) {
- mvcData->rightOfBorderPrev = mvcData->rightOfBorder;
- mvcData->downOfBorderPrev = mvcData->downOfBorder;
- }
-
- if (mba == -1) {
- if (x == 0) {
- *rightOfBorder = 1;
- }
- else {
- *rightOfBorder = 0;
- }
-
- /* Always downOfBorder is set to 1, since in QCIF and CIF every GOB
- has only 1 MB line. If larger images are supported, numMBLinesInGOB
- should be passed here. Also number of starting MB of the GOB may be
- needed...*/
- *downOfBorder = 1;
- upRightMBIsStart = 0;
- }
- else {
- int
- xs, /* x coordinate of start MB */
- ys; /* y coordinate of start MB */
- xs = mba % numMBsInMBLine;
- ys = mba / numMBsInMBLine;
-
- /* slice structured mode*/
- /* Check if there is slice border on top of the current MB:
- For that, check either current MB should be on the same MB line
- with the starting MB of slice or current MB should not be on the
- left of the starting MB if the MB is on the second line of the
- slice. */
-
- if ((y == ys) || ((x < xs) && (ys+1 == y))) {
- *downOfBorder = 1;
- }
- else {
- *downOfBorder = 0;
- }
- /* Check if there is a slice border on the left of the current MB.*/
- if (((x == xs) && (y == ys)) || (x == 0)) {
- *rightOfBorder = 1;
- }
- else {
- *rightOfBorder = 0;
- }
-
- /* Test the situation of MV2 is in another slice but MV3 in in the
- same slice... i.e:
- MB1 MB1 MB1 MB2 MB2 .........MB2
- MB2 MB2 MB2 MB2 MB2..........MB2
- *
- The MB marked with * is an exmaple. MB on top of it is in another slice
- but the MB which MV3 will come from is in the same slice...*/
- if ((x+1 == xs) && (y-1 == ys))
- upRightMBIsStart = 1;
- else
- upRightMBIsStart = 0;
- }
-
- if (mvcData) {
- mvcData->upRightMBIsStart = upRightMBIsStart;
- mvcData->downOfBorder = *downOfBorder;
- mvcData->rightOfBorder = *rightOfBorder;
- mvcData->leftOfBorder = 0;
- }
-}
-
-/* {{-output"mvcCalcMV.txt"}} */
-/*
- *
- * mvcCalcMV
- *
- * Parameters:
- * mvcData mvcData_t structure
- *
- * mvdx motion vector data returned by vlcGetMVD
- * mvdy
- *
- * *mvx the resulting motion vector is placed to *mvx and *mvy
- * *mvy
- *
- * predictorMode 0, 1, 2 or 3. See H.263 recommendation, Annex F, Figure
- * 15, where modes are in the following order:
- * 0 1
- * 2 3
- *
- * Advanced Prediction mode: It is assumed that this
- * function is called by setting predictorMode 0, 1, 2
- * and 3 in this order for a particular macroblock.
- *
- * Normal: This function should be called by setting
- * predictorMode to 0.
- *
- * fourMVs if != 0, four motion vectors for current macroblock
- * is assumed
- *
- * unrestrictedMV if != 0, unrestricted motion vector mode is used
- *
- * topOfGOB if != 0, the current MB is assumed to be in the
- * first line of the current GOB
- *
- * nonEmptyGOBHeader if != 0, the GOB header of the current GOB is
- * is assumed to be non-empty, and MV2 and MV3 are
- * set to MV1 if they are outside the GOB. If Annex K
- * is in use set this value to 1......
- *
- * x the x coordinate of the MB (0 .. maxX)
- * y the y coordinate of the MB
- * (0 .. macroblock rows in frame - 1)
- *
- * time a value which is related to the time when the current
- * frame must be shown. This value should be unique
- * among a relatively small group of consecutive frames.
- *
- * mbType must be MVC_MB_INTER or MVC_MB_INTRA. MVC_MB_INTRA
- * should be used only in PB frames mode.
- *
- * error error code
- *
- * fPLUSPTYPE PLUSTYPE flag
- *
- * fUMVLimited Annex D v2 flag
- * 1 => Limited MVs (UUI = 1)
- * 0 => Unlimited MVs (UUI = 01)
- *
- * Function:
- * This function counts the motion vector value for given macroblock.
- * See H.263 Recommendation 6.1.1 Differential Motion Vectors and
- * Annex F. Advanced Prediction Mode.
- *
- * Returns:
- * Changes *mvx, *mvy and possibly *error.
- *
- * Error codes:
- * ERR_MVC_MVDX_ILLEGAL mvdx illegal
- * ERR_MVC_MVDY_ILLEGAL mvdy illegal
- * ERR_MVC_MVX_ILLEGAL mvx is NULL
- * ERR_MVC_MVY_ILLEGAL mvy is NULL
- * ERR_MVC_MODE_ILLEGAL predictorMode illegal
- * ERR_MVC_X_ILLEGAL x < 0 or x > maxX
- * ERR_MVC_Y_ILLEGAL y < 0
- * ERR_MVC_TIME_ILLEGAL time < 0
- * ERR_MVC_MVPTR result is not legal
- *
- */
-
-void mvcCalcMV(mvcData_t *mvcData, int mvdx, int mvdy,
- int *mvx, int *mvy, u_char predictorMode, u_char fourMVs,
- u_char unrestrictedMV, u_char nonEmptyGOBHeader, int x,
- int y, int time, int mbType, int16 *error, int fPLUSPTYPE,
- int fUMVLimited)
-/* {{-output"mvcCalcMV.txt"}} */
-{
-
- int
- i, j, /* loop variables */
- mvcx[3], /* Candidates: mv[0] = MV1, mv[1] = MV2, mv[2] = MV3 */
- mvcy[3],
- *mv, /* mvcx or mvcy */
- *mvptr, /* == mvx or mvy */
- mvd, /* mvdx or mvdy */
- xx2, /* x * 2 */
- yx2, /* y * 2 */
- xmv1, /* index for MV1 */
- xmv2, /* index for MV2 */
- xmv3, /* index for MV3 */
- ymv1,
- ymv2,
- ymv3,
- mvRangeLow, /* Lower boundary for MV Range
- Look H.263+ Rec. Table D.1, D.2 */
- mvRangeHigh, /* Higher boundary for MV Range
- Look H.263+ Rec. Table D.1, D.2 */
- picDim, /* Temporary variable for luminance width or height */
- mbCorner, /* Temporary variable for MB's topleft corner's
- coordinate (x or y)*/
- mvRes; /* MB's rightmost or bottommost pixel plus MV
- for checking restriction D.1.1 */
- mvRowItem_t
- *currMvRow,
- *prevMvRow,
- *mvRow0,
- *mvRow1,
- *mvRow2;
-
- /* Check parameters */
- if ((!fPLUSPTYPE) || (!unrestrictedMV))
- {
- if (mvdx < MVD_MIN || mvdx > MVD_MAX) {
- *error = ERR_MVC_MVDX_ILLEGAL;
- return;
- }
-
- if (mvdy < MVD_MIN || mvdy > MVD_MAX) {
- *error = ERR_MVC_MVDY_ILLEGAL;
- return;
- }
- }
-
- if (!mvx) {
- *error = ERR_MVC_MVX_ILLEGAL;
- return;
- }
-
- if (!mvy) {
- *error = ERR_MVC_MVY_ILLEGAL;
- return;
- }
-
- if ((fourMVs && predictorMode > 3) ||
- (!fourMVs && predictorMode > 0)) {
- *error = ERR_MVC_MODE_ILLEGAL;
- return;
- }
-
- if (x < 0 || x > mvcData->currMaxX) {
- *error = ERR_MVC_X_ILLEGAL;
- return;
- }
-
- if (y < 0) {
- *error = ERR_MVC_Y_ILLEGAL;
- return;
- }
-
- if (time < 0) {
- *error = ERR_MVC_TIME_ILLEGAL;
- return;
- }
-
- updateRowPointers(x, y, time);
- mvRow0 = mvcData->mvRow0;
- mvRow1 = mvcData->mvRow1;
- mvRow2 = mvcData->mvRow2;
-
- /* Seek candidate predictors */
-
- xx2 = x << 1; /* xx2 = x * 2 */
- yx2 = y << 1;
-
- xmv1 = xx2 - 1 + (predictorMode & 1);
- xmv2 = xx2 + (predictorMode == 1);
- xmv3 = xx2 + 2 - (predictorMode > 1);
- ymv1 = yx2 + (predictorMode > 1);
- ymv2 = ymv3 = yx2 - 1 + (predictorMode > 1);
-
- if (predictorMode <= 1) {
- currMvRow = mvRow1;
- prevMvRow = mvRow0;
- }
- else {
- currMvRow = mvRow2;
- prevMvRow = mvRow1;
- }
-
- if ( (predictorMode & 1) || /* right column of the MB */
- ( !mvcData->rightOfBorder && mvValid(currMvRow[xmv1], ymv1, time) ) ) {
- mvcx[0] = currMvRow[xmv1].mvx;
- mvcy[0] = currMvRow[xmv1].mvy;
- }
- else
- /* if (x == 0 || motion vector for previous MB does not exist ||
- the previous MB belongs to a different slice) */
- mvcx[0] = mvcy[0] = 0;
-
- if ((y == 0 || (mvcData->downOfBorder && nonEmptyGOBHeader)) && predictorMode <= 1) {
- /* mv2 and mv3 are outside the picture or GOB
- (if non-empty GOB header) or outside the slice*/
- mvcx[1] = mvcx[0];
- mvcy[1] = mvcy[0];
- /* Check if the MB ont the previous line and on the next column
- in in the same slice (means start MBof the slice).. */
- if (!mvcData->upRightMBIsStart) {
- mvcx[2] = mvcx[0];
- mvcy[2] = mvcy[0];
- }
- if (x == mvcData->currMaxX)
- mvcx[2] = mvcy[2] = 0;
- }
- else {
- if (mvValid(prevMvRow[xmv2], ymv2, time)) {
- mvcx[1] = prevMvRow[xmv2].mvx;
- mvcy[1] = prevMvRow[xmv2].mvy;
- }
- else
- mvcx[1] = mvcy[1] = 0;
-
- if (mvValid(prevMvRow[xmv3], ymv3, time)) {
- mvcx[2] = prevMvRow[xmv3].mvx;
- mvcy[2] = prevMvRow[xmv3].mvy;
- }
- else
- mvcx[2] = mvcy[2] = 0;
- }
-
- for (j = 0, mv = mvcx, mvd = mvdx, mvptr = mvx,
- picDim = mvcData->currLumWidth, mbCorner = x,
- mvRangeLow = mvcData->mvRangeLowX,
- mvRangeHigh = mvcData->mvRangeHighX;
- j < 2;
- j++, mv = mvcy, mvd = mvdy, mvptr = mvy,
- picDim = mvcData->currLumHeight, mbCorner = y,
- mvRangeLow = mvcData->mvRangeLowY,
- mvRangeHigh = mvcData->mvRangeHighY) {
-
- int choice1, min, predictor;
-
- /* Find the median of the candidates */
-
- min = mv[0];
- predictor = 32767;
-
- for (i = 1; i < 3; i++) {
- if (mv[i] <= min) {
- predictor = min;
- min = mv[i];
- continue;
- }
- if (mv[i] < predictor)
- predictor = mv[i];
- }
-
- /* Count the new motion vector value */
-
- if (!unrestrictedMV) {
- /* Default prediction mode.
- Count the legal [-16..15.5] motion vector */
-
- choice1 = predictor + mvd;
-
- *mvptr = (MVD_MIN <= choice1 && choice1 <= MVD_MAX) ?
- choice1 :
- /*(mvd == 0) ?
- predictor :*/ /* index 32, should never happen?! */
- (mvd < 0) ?
- MVD_320 + choice1 : /* index 0..31: 32 + mvd + predictor */
- -MVD_320 + choice1; /* index 33..63: -32 + mvd + predictor */
-
- /* Check that the result is [-16..15.5] */
- if (*mvptr < MVD_MIN || *mvptr > MVD_MAX) {
- *error = ERR_MVC_MVPTR;
- return;
- }
- }
-
- else if ((-MVD_155 <= predictor && predictor <= MVD_160) && (!fPLUSPTYPE))
- /* Unrestricted motion vector mode && -15.5 <= predictor <= 16.
- mvd is always valid. */
- *mvptr = predictor + mvd;
-
- else if (!fPLUSPTYPE)
- {
- /* Unrestricted motion vector mode && predictor not in [-15.5, 16]
- Result in [-31.5, 31.5] and has the same sign as predictor */
- choice1 = predictor + mvd;
- *mvptr = (MVD_UMIN_V1 <= choice1 && choice1 <= MVD_UMAX_V1 &&
- (sign123(choice1) & sign123(predictor))) ?
- choice1 :
- /*(mvd == 0) ?
- predictor :*/ /* index 32, should never happen!? */
- (mvd < 0) ?
- MVD_320 + choice1 : /* index 0..31: 32 + mvd + predictor */
- -MVD_320 + choice1; /* index 33..63: -32 + mvd + predictor */
-
- /* Check that the result is in the appropriate range. */
- if ((predictor < -MVD_155 && *mvptr > 0) ||
- (predictor > MVD_160 && *mvptr < 0)) {
- *error = ERR_MVC_MVPTR;
- return;
- }
-
- }
- else if (fUMVLimited)
- /* fPlusType==1 && UUI == 1*/
- {
- *mvptr = predictor + mvd;
-
- if ( *mvptr > 0 )
- /* mvRes is the leftmost/topmost pixels coordinate of next
- macroblock plus 2 times MV */
- mvRes = (mbCorner+1)*32 + (*mvptr)/5 ;
- else
- /* mvRes is the leftmost/topmost pixels coordinate of current
- macroblock plus 2 times MV,
- half a pixel corresponds to 1 in integer scale */
- mvRes = mbCorner*32 + (*mvptr)/5 ;
-
- if ((mvRes < -30) || (mvRes > picDim * 2 + 30))
- /* Restriction D.1.1 */
- {
- *error = ERR_MVC_MVPTR;
- deb("Restriction D.1.1\n");
- return;
- }
-
- if ((*mvptr < mvRangeLow) || (*mvptr > mvRangeHigh))
- /* Restriction D.2 */
- {
- *error = ERR_MVC_MVPTR;
- deb("Restriction D.2 \n");
- return;
- }
- }
- else /* fPlusType==1 && UUI == 01 */
- {
- *mvptr = predictor + mvd;
- if ( *mvptr > 0 )
- mvRes = (mbCorner+1)*32 + (*mvptr)/5;
- else
- mvRes = mbCorner*32 + (*mvptr)/5;
- if ((mvRes < -30) || (mvRes > picDim * 2 + 30))
- /* Restriction D.1.1 */
- {
- *error = ERR_MVC_MVPTR;
- deb("Restriction D.1.1\n");
- return;
- }
- }
- }
-
- /* Update motion vector buffer arrays */
- switch (predictorMode) {
- case 0:
- if (fourMVs) {
- mvStore(mvRow1, xx2, yx2, *mvx, *mvy, time, mbType);
- }
- else {
- mvStoreMB(mvRow1, mvRow2, xx2, yx2, *mvx, *mvy, time, mbType);
- }
- break;
- case 1:
- mvStore(mvRow1, xx2 + 1, yx2, *mvx, *mvy, time, mbType);
- break;
- case 2:
- mvStore(mvRow2, xx2, yx2 + 1, *mvx, *mvy, time, mbType);
- break;
- case 3:
- mvStore(mvRow2, xx2 + 1, yx2 + 1, *mvx, *mvy, time, mbType);
- break;
- }
-}
-
-
-/* {{-output"mvcCalcMPEGMV.txt"}} */
-/*
- *
- * mvcCalcMPEGMV
- *
- * Parameters:
- * mvcData mvcData_t structure
- *
- * mvdx motion vector data returned by vlcGetMVD
- * mvdy
- *
- * *mvx the resulting motion vector is placed to *mvx and *mvy
- * *mvy
- *
- * predictorMode 0, 1, 2 or 3. See H.263 recommendation, Annex F, Figure
- * 15, where modes are in the following order:
- * 0 1
- * 2 3
- *
- * Advanced Prediction mode: It is assumed that this
- * function is called by setting predictorMode 0, 1, 2
- * and 3 in this order for a particular macroblock.
- *
- * Normal: This function should be called by setting
- * predictorMode to 0.
- *
- * fourMVs if != 0, four motion vectors for current macroblock
- * is assumed
- *
- * topOfVP if != 0, the current MB is assumed to be in the
- * first line of the current VideoPacket
- *
- * leftOfVP if != 0, the current MB is assumed to be the
- * first in the VideoPacket
- *
- * fmv3_out if != 0, the 3rd MB (top, right) used as MV predictor
- * is outside of the current VideoPacket
- *
- * x the x coordinate of the MB (0 .. maxX)
- * y the y coordinate of the MB
- * (0 .. macroblock rows in frame - 1)
- *
- * time a value which is related to the time when the current
- * frame must be shown. This value should be unique
- * among a relatively small group of consecutive frames.
- *
- * mbType must be MVC_MB_INTER or MVC_MB_INTRA. MVC_MB_INTRA
- * should be used only in PB frames mode.
- *
- * error error code
- *
- * Function:
- * This function counts the motion vector value for given macroblock.
- * See H.263 Recommendation 6.1.1 Differential Motion Vectors and
- * Annex F. Advanced Prediction Mode.
- *
- * Returns:
- * Changes *mvx, *mvy and possibly *error.
- *
- * Error codes:
- * The following codes are assertion-like checks:
- * ERR_MVC_MVDX_ILLEGAL mvdx illegal
- * ERR_MVC_MVDY_ILLEGAL mvdy illegal
- * ERR_MVC_MVX_ILLEGAL mvx is NULL
- * ERR_MVC_MVY_ILLEGAL mvy is NULL
- * ERR_MVC_MODE_ILLEGAL predictorMode illegal
- * ERR_MVC_X_ILLEGAL x < 0 or x > maxX
- * ERR_MVC_Y_ILLEGAL y < 0
- * ERR_MVC_TIME_ILLEGAL time < 0
- *
- * The following code may also be caused by a bit error:
- * ERR_MVC_MVPTR result is not legal
- *
- */
-
-void mvcCalcMPEGMV(mvcData_t *mvcData,
- int mvdx, int mvdy, int *mvx, int *mvy,
- u_char predictorMode, u_char fourMVs,
- u_char topOfVP, u_char leftOfVP, u_char fmv3_out,
- int x, int y, int time, int mbType, int16 *error)
-/* {{-output"mvccalc.txt"}} */
-{
- int
- i, j, /* loop variables */
- mvcx[3], /* Candidates: mv[0] = MV1, mv[1] = MV2, mv[2] = MV3 */
- mvcy[3],
- mvc1_out = 0, mvc2_out = 0, mvc3_out = 0,
- *mv, /* mvcx or mvcy */
- *mvptr, /* == mvx or mvy */
- mvd, /* mvdx or mvdy */
- xx2, /* x * 2 */
- yx2, /* y * 2 */
- xmv1, /* index for MV1 */
- xmv2, /* index for MV2 */
- xmv3, /* index for MV3 */
- ymv1,
- ymv2,
- ymv3;
- mvRowItem_t
- *currMvRow,
- *prevMvRow,
- *mvRow0,
- *mvRow1,
- *mvRow2;
-
-
- if (!mvx) {
- *error = ERR_MVC_MVX_ILLEGAL;
- return;
- }
-
- if (!mvy) {
- *error = ERR_MVC_MVY_ILLEGAL;
- return;
- }
-
- if ((fourMVs && predictorMode > 3) ||
- (!fourMVs && predictorMode > 0)) {
- *error = ERR_MVC_MODE_ILLEGAL;
- return;
- }
-
- if (x < 0 || x > mvcData->currMaxX) {
- *error = ERR_MVC_X_ILLEGAL;
- return;
- }
-
- if (y < 0) {
- *error = ERR_MVC_Y_ILLEGAL;
- return;
- }
-
- if (time < 0) {
- *error = ERR_MVC_TIME_ILLEGAL;
- return;
- }
-
- updateRowPointers(x, y, time);
- mvRow0 = mvcData->mvRow0;
- mvRow1 = mvcData->mvRow1;
- mvRow2 = mvcData->mvRow2;
-
- /* Seek candidate predictors */
-
- xx2 = x << 1; /* xx2 = x * 2 */
- yx2 = y << 1;
-
- xmv1 = xx2 - 1 + (predictorMode & 1);
- xmv2 = xx2 + (predictorMode == 1);
- xmv3 = xx2 + 2 - (predictorMode > 1);
- ymv1 = yx2 + (predictorMode > 1);
- ymv2 = ymv3 = yx2 - 1 + (predictorMode > 1);
-
- if (predictorMode <= 1) {
- currMvRow = mvRow1;
- prevMvRow = mvRow0;
- }
- else {
- currMvRow = mvRow2;
- prevMvRow = mvRow1;
- }
-
- if ((x == 0 || leftOfVP) && !(predictorMode & 1)) {
- /* mv1 is outside the VP or VOP */
- mvcx[0] = mvcy[0] = 0;
- mvc1_out = 1;
- }
- else {
- if (mvValidMPEG(currMvRow[xmv1], ymv1, time)) {
- mvcx[0] = currMvRow[xmv1].mvx;
- mvcy[0] = currMvRow[xmv1].mvy;
- }
- else mvcx[0] = mvcy[0] = 0;
- }
-
- if ((y == 0 || topOfVP) && predictorMode <= 1) {
- /* mv2 is outside the VP or VOP */
- mvcx[1] = mvcy[1] = 0;
- mvc2_out = 1;
- }
- else {
- if (mvValidMPEG(prevMvRow[xmv2], ymv2, time)) {
- mvcx[1] = prevMvRow[xmv2].mvx;
- mvcy[1] = prevMvRow[xmv2].mvy;
- }
- else mvcx[1] = mvcy[1] = 0;
- }
-
- if ((y == 0 || fmv3_out || x == mvcData->currMaxX) && predictorMode <= 1) {
- /* mv3 is outside the VP or VOP */
- mvcx[2] = mvcy[2] = 0;
- mvc3_out = 1;
- }
- else {
- if (mvValidMPEG(prevMvRow[xmv3], ymv3, time)) {
- mvcx[2] = prevMvRow[xmv3].mvx;
- mvcy[2] = prevMvRow[xmv3].mvy;
- }
- else
- mvcx[2] = mvcy[2] = 0;
- }
-
- for (j = 0, mv = mvcx, mvd = mvdx, mvptr = mvx;
- j < 2;
- j++, mv = mvcy, mvd = mvdy, mvptr = mvy) {
-
- int min, predictor;
-
- switch (mvc1_out + mvc2_out + mvc3_out)
- {
- case 3:
- predictor = 0;
- break;
- case 2:
- predictor = mv[0] + mv[1] + mv[2];
- break;
- case 1:
- case 0:
- /* Find the median of the candidates */
- min = mv[0];
- predictor = 32767;
-
- for (i = 1; i < 3; i++) {
- if (mv[i] <= min) {
- predictor = min;
- min = mv[i];
- continue;
- }
- if (mv[i] < predictor)
- predictor = mv[i];
- }
- break;
- default:
- /* Should never happen */
- vdcAssert(0);
- predictor = 0;
- break;
- }
-
- /* Count the new motion vector value */
- *mvptr = predictor + mvd;
-
- if (*mvptr < -(mvcData->range))
- *mvptr += 2*(mvcData->range);
- else if (*mvptr > (mvcData->range)-5)
- *mvptr -= 2*(mvcData->range);
- }
-
- /* Update motion vector buffer arrays */
- switch (predictorMode) {
- case 0:
- if (fourMVs) {
- mvStore(mvRow1, xx2, yx2, *mvx, *mvy, time, mbType);
- }
- else {
- mvStoreMB(mvRow1, mvRow2, xx2, yx2, *mvx, *mvy, time, mbType);
- }
- break;
- case 1:
- mvStore(mvRow1, xx2 + 1, yx2, *mvx, *mvy, time, mbType);
- break;
- case 2:
- mvStore(mvRow2, xx2, yx2 + 1, *mvx, *mvy, time, mbType);
- break;
- case 3:
- mvStore(mvRow2, xx2 + 1, yx2 + 1, *mvx, *mvy, time, mbType);
- break;
- }
-}
-
-/* {{-output"mvcFree.txt"}} */
-/*
- *
- * mvcFree
- *
- * Parameters:
- * mvcData mvcData_t structure
- *
- * Function:
- * This function frees the dynamic memory allocated by mvcStart.
- * mvcFree should be called at least when exiting the main program.
- * Alternatively it can be called whenever the playing a video has
- * ended.
- *
- * Returns:
- * Nothing
- *
- * Error codes:
- * None
- *
- *
- *
- *
- */
-
-void mvcFree(mvcData_t *mvcData)
-/* {{-output"mvcFree.txt"}} */
-{
- if (mvcData) {
- if (mvcData->mvRow) free(mvcData->mvRow);
- mvcData->currMaxX = -1;
- }
-}
-
-
-/* {{-output"mvcGetCurrentMVs.txt"}} */
-/*
- *
- * mvcGetCurrentMVs
- *
- * Parameters:
- * mvcData mvcData_t structure
- * mvx
- * mvy
- * error error code
- *
- * Function:
- * These functions return the motion vectors of the current
- * blocks.
- *
- * Returns:
- * Changes mvx, mvy and possibly error.
- *
- * Error codes:
- *
- * ERR_MVC_CURR_NOT_VALID if the motion vectors for the current
- * macroblock do not exist
- *
- * ERR_MVC_CURR_NOT_CODED if the current macroblock was not coded
- *
- * ERR_MVC_CURR_INTRA if the current macroblock was coded in
- * INTRA mode
- *
- */
-void mvcGetCurrentMVs(mvcData_t *mvcData, int *mvx, int *mvy,
- int16 *error)
-{
- int
- xx2 = mvcData->currX << 1,
- yx2 = mvcData->currY << 1;
- mvRowItem_t
- *mvRow1 = mvcData->mvRow1,
- *mvRow2 = mvcData->mvRow2;
- if (mvValid(mvRow1[xx2], yx2, mvcData->currTime) &&
- mvRow1[xx2].type == MVC_MB_INTER) {
- mvx[0] = mvRow1[xx2].mvx;
- mvx[1] = mvRow1[xx2 + 1].mvx;
- mvx[2] = mvRow2[xx2].mvx;
- mvx[3] = mvRow2[xx2 + 1].mvx;
- mvy[0] = mvRow1[xx2].mvy;
- mvy[1] = mvRow1[xx2 + 1].mvy;
- mvy[2] = mvRow2[xx2].mvy;
- mvy[3] = mvRow2[xx2 + 1].mvy;
- }
- else {
- mvx[0] = mvx[1] = mvx[2] = mvx[3] =
- mvy[0] = mvy[1] = mvy[2] = mvy[3] = 0;
- if mvLegal(mvRow1[xx2], yx2, mvcData->currTime) {
- if (mvRow1[xx2].type == MVC_MB_NOT_CODED) {
- /*deb("mvcGetCurrentMVs: ERROR - macroblock not coded.\n");*/
- *error = ERR_MVC_CURR_NOT_CODED;
- }
- else if (mvRow1[xx2].type == MVC_MB_INTRA) {
- /*deb("mvcGetCurrentMVs: ERROR - INTRA macroblock.\n");*/
- *error = ERR_MVC_CURR_INTRA;
- }
- else {
- /*deb("mvcGetCurrentMVs: ERROR - macroblock not valid.\n");*/
- *error = ERR_MVC_CURR_NOT_VALID;
- }
- }
- else {
- /*deb("mvcGetCurrentMVs: ERROR - macroblock not valid.\n");*/
- *error = ERR_MVC_CURR_NOT_VALID;
- }
- }
-}
-
-/* {{-output"mvcGetNeighbourMVs.txt"}} */
-/*
- *
- * mvcGetCurrNeighbourMVs
- * mvcGetPrevNeighbourMVs
- *
- * Parameters:
- * mvcData mvcData_t structure
- *
- * nmvx pointer to motion vector x component array
- * nmvy pointer to motion vector y component array
- * The size of the array must be 6. The indexing of the
- * neighboring motion vectors goes like this:
- * (X = the motion vector which is investigated, i.e.
- * the last one decoded (mvcGetCurrNeighbourMVs) or
- * the one before the last one (mvcGetPrevNeighbourMVs))
- * 2 3
- * 0 X X 4
- * 1 X X 5
- * It is suggested that the following defines are used
- * instead of values:
- * MVC_XM1_UP (0)
- * MVC_XM1_DOWN (1)
- * MVC_YM1_LEFT (2)
- * MVC_YM1_RIGHT (3)
- * MVC_XP1_UP (4)
- * MVC_XP1_DOWN (5)
- * (M stand for minus and P for plus)
- *
- * pmvx and pmvy are for mvcGetPrevNeighbourMVs only:
- * pmvx pointer to the motion vector x component array of the
- * previous macroblock
- * pmvy pointer to the motion vector y component array of the
- * previous macroblock
- * The size of the array must be 4. The indexing is similar
- * to normal block indexing inside a macroblock:
- * 0 1
- * 2 3
- *
- * error error code
- *
- * Function:
- * These functions return the motion vectors of the neighboring
- * blocks (on the left side, above or on the right side) of the
- * macroblock which is investigated, i.e.
- * - the last one decoded (mvcGetCurrNeighbourMVs) or
- * - the one before the last one (mvcGetPrevNeighbourMVs))
- *
- * The H.263 standard for Overlapped motion compensation for luminance
- * (Annex F.3) is followed, that is:
- * If one of the surrounding macroblocks was not coded, the
- * corresponding remote motion vector is set to zero. If one of the
- * surrounding (macro)blocks was coded in INTRA mode, the corresponding
- * remote motion vector is replaced by the motion vector for the
- * current block expect when in PB-frames mode. In this case (INTRA
- * block in PB-frame mode), the INTRA block's motion vector is used.
- * If the current block is at the border of the picture and therefore
- * a surrounding block is not present, the corresponding remote motion
- * vector is replaced by the current motion vector.
- *
- * mvcGetPrevNeighbourMVs also returns the motion vector for the
- * previous macroblock.
- *
- * Returns:
- * Changes nmvx, nmvy, pmvx, pmvy and possibly error.
- *
- * Error codes:
- * ERR_MVC_NO_PREV_MB if the current MB has x coordinate 0 and
- * mvcGetPrevNeighbourMVs is called
- *
- * ERR_MVC_NEIGHBOUR_NOT_VALID if one of the neighboring MVs is not
- * valid, i.e. it has not been updated
- * for this frame. The MV in nmvx and nmvy
- * is set to zero.
- *
- * for mvcGetPrevNeighbourMVs only:
- * ERR_MVC_PREV_NOT_VALID if the motion vectors for the previous
- * macroblock do not exist
- *
- * ERR_MVC_PREV_NOT_CODED if the previous macroblock was not coded
- *
- * ERR_MVC_PREV_INTRA if the previous macroblock was coded in
- * INTRA mode
- *
- *
- *
- *
- *
- *
- *
- */
-
-void mvcGetCurrNeighbourMVs(mvcData_t *mvcData, int *nmvx, int *nmvy,
- int16 *error)
-/* {{-output"mvcGetNeighbourMVs.txt"}} */
-{
- mvRowItem_t
- *mvRow1 = mvcData->mvRow1;
- int xx2 = mvcData->currX << 1;
-
- mvcGetNeighbourMVs(mvcData, mvcData->currX, mvcData->currY,
- mvcData->currTime, nmvx, nmvy, 0, error);
- if (*error) {
- if mvLegal(mvRow1[xx2], mvcData->currY << 1, mvcData->currTime) {
- if (mvRow1[xx2].type == MVC_MB_NOT_CODED) {
- /*deb("mvcGetPrevNeighbourMVs: ERROR - macroblock not coded.\n");*/
- *error = ERR_MVC_CURR_NOT_CODED;
- }
- else if (mvRow1[xx2].type == MVC_MB_INTRA) {
- /*deb("mvcGetPrevNeighbourMVs: ERROR - INTRA macroblock.\n");*/
- *error = ERR_MVC_CURR_INTRA;
- }
- else {
- /*deb("mvcGetPrevNeighbourMVs: ERROR - macroblock not valid.\n");*/
- *error = ERR_MVC_CURR_NOT_VALID;
- }
- }
- else {
- /*deb("mvcGetPrevNeighbourMVs: ERROR - macroblock not valid.\n");*/
- *error = ERR_MVC_CURR_NOT_VALID;
- }
- }
-}
-
-/* {{-output"mvcGetPrevNeighbourMVs.txt"}} */
-void mvcGetPrevNeighbourMVs(mvcData_t *mvcData, int *nmvx, int *nmvy,
- int *pmvx, int *pmvy, u_char *fourMVs, int16 *error)
-/* {{-output"mvcGetPrevNeighbourMVs.txt"}} */
-{
- int
- currX = mvcData->currX,
- currY = mvcData->currY;
- mvRowItem_t
- *mvRow1 = mvcData->mvRow1,
- *mvRow2 = mvcData->mvRow2;
-
- if (currX > 0) {
- int xx2 = (currX - 1) << 1;
- mvcGetNeighbourMVs(mvcData, currX - 1, currY,
- mvcData->currTime, nmvx, nmvy, 1, error);
- if (mvValid(mvRow1[xx2], currY << 1, mvcData->currTime) &&
- mvRow1[xx2].type == MVC_MB_INTER) {
- pmvx[0] = mvRow1[xx2].mvx;
- pmvx[1] = mvRow1[xx2 + 1].mvx;
- pmvx[2] = mvRow2[xx2].mvx;
- pmvx[3] = mvRow2[xx2 + 1].mvx;
- pmvy[0] = mvRow1[xx2].mvy;
- pmvy[1] = mvRow1[xx2 + 1].mvy;
- pmvy[2] = mvRow2[xx2].mvy;
- pmvy[3] = mvRow2[xx2 + 1].mvy;
- *fourMVs = mvRow1[xx2].fourMVs;
- }
- else {
- pmvx[0] = pmvx[1] = pmvx[2] = pmvx[3] =
- pmvy[0] = pmvy[1] = pmvy[2] = pmvy[3] = 0;
- *fourMVs = 0;
- if mvLegal(mvRow1[xx2], currY << 1, mvcData->currTime) {
- if (mvRow1[xx2].type == MVC_MB_NOT_CODED) {
- /*deb("mvcGetPrevNeighbourMVs: ERROR - macroblock not coded.\n");*/
- *error = ERR_MVC_PREV_NOT_CODED;
- }
- else if (mvRow1[xx2].type == MVC_MB_INTRA) {
- /*deb("mvcGetPrevNeighbourMVs: ERROR - INTRA macroblock.\n");*/
- *error = ERR_MVC_PREV_INTRA;
- }
- else {
- /*deb("mvcGetPrevNeighbourMVs: ERROR - macroblock not valid.\n");*/
- *error = ERR_MVC_PREV_NOT_VALID;
- }
- }
- else {
- /*deb("mvcGetPrevNeighbourMVs: ERROR - macroblock not valid.\n");*/
- *error = ERR_MVC_PREV_NOT_VALID;
- }
- }
- }
- else {
- /*deb("mvcGetPrevNeighbourMVs: ERROR - no previous macroblock.\n");*/
- *error = ERR_MVC_NO_PREV_MB;
- }
-}
-
-
-/* {{-output"mvcGetPrevMVFsAndMVBs.txt"}} */
-/*
- *
- * mvcGetPrevMVFsAndMVBs
- *
- * Parameters:
- * mvcData mvcData_t structure
- *
- * mvfx the resulting forward motion vector
- * mvfy
- *
- * mvbx the resulting backward motion vector
- * mvby
- *
- * fourMVs 1 if there is four motion vectors per macroblock
- * 0 otherwise
- *
- * Function:
- * This function gets the forward and backward motion vectors for the
- * previous B macroblock.
- *
- * Returns:
- * Changes *mvfx, *mvfy, *mvbx, *mvby and *fourMVs.
- *
- * Error codes:
- * ERR_MVC_NO_PREV_MB if the current MB has x coordinate 0 and
- * mvcGetPrevNeighbourMVs is called
- *
- * ERR_MVC_PREV_NOT_VALID if the motion vectors for the previous
- * macroblock do not exist
- *
- *
- */
-
-void mvcGetPrevMVFsAndMVBs(mvcData_t *mvcData, int *mvfx, int *mvfy,
- int *mvbx, int *mvby, u_char *fourMVs, int16 *error)
-/* {{-output"mvcGetPrevMVFsAndMVBs.txt"}} */
-{
- mvBFBufItem_t
- *mvFBuf = mvcData->mvFBufArray[mvcData->mvBFBufIndex ^ 1],
- *mvBBuf = mvcData->mvBBufArray[mvcData->mvBFBufIndex ^ 1];
- int i;
-
- if (mvcData->currX > 0) {
- if (mvBBuf[0].x == mvcData->currX - 1 &&
- mvValid(mvBBuf[0], mvcData->currY, mvcData->currTime)) {
- *fourMVs = mvBBuf[0].fourMVs;
- for (i = 0; i < 4; i++) {
- mvfx[i] = mvFBuf[i].mvx;
- mvfy[i] = mvFBuf[i].mvy;
- mvbx[i] = mvBBuf[i].mvx;
- mvby[i] = mvBBuf[i].mvy;
- }
- }
- else {
- /*deb("mvcGetPrevMVFsAndMVBs: ERROR - PREV_NOT_VALID.\n");*/
- *error = ERR_MVC_PREV_NOT_VALID;
- }
- }
- else {
- /*deb("mvcGetPrevMVFsAndMVBs: ERROR - NO_PREV_MB.\n");*/
- *error = ERR_MVC_NO_PREV_MB;
- }
-}
-
-
-/* {{-output"mvcMarkMB.txt"}} */
-/*
- *
- * mvcMarkMBIntra
- * mvcMarkMBNotCoded
- *
- * Parameters:
- * mvcData mvcData_t structure
- * x the x coordinate of the MB (0 .. maxX)
- * y the y coordinate of the MB
- * (0 .. macroblock rows in frame - 1)
- *
- * time a value which is related to the time when the current
- * frame must be shown. This value should be unique
- * among a relatively small group of consecutive frames.
- *
- * Function:
- * These functions are used to mark that the macroblock is either
- * intra coded or not coded at all. The information is used when
- * deciding the neighboring motion vectors of a macroblock in
- * mvcGetPrevNeighbourMVs and mvcGetCurrNeighbourMVs.
- * Note that mvcMarkMBIntra should not be called in case of
- * INTRA block in PB-frame mode. Instead mvcCalcMV should be used.
- *
- * Returns:
- * Nothing
- *
- * Error codes:
- * None
- *
- *
- *
- */
-
-void mvcMarkMBIntra(mvcData_t *mvcData, int x, int y, int time)
-/* {{-output"mvcMarkMB.txt"}} */
-{
- int
- xx2 = x << 1,
- yx2 = y << 1;
- mvRowItem_t
- *mvRow1,
- *mvRow2;
-
- updateRowPointers(x, y, time);
- mvRow1 = mvcData->mvRow1;
- mvRow2 = mvcData->mvRow2;
- mvStoreMB(mvRow1, mvRow2, xx2, yx2, MVD_INTRA, MVD_INTRA, time, MVC_MB_INTRA);
-}
-
-/* {{-output"mvcMarkMBNotCoded.txt"}} */
-void mvcMarkMBNotCoded(mvcData_t *mvcData, int x, int y, int time)
-/* {{-output"mvcMarkMBNotCoded.txt"}} */
-{
- int
- xx2 = x << 1,
- yx2 = y << 1;
- mvRowItem_t
- *mvRow1,
- *mvRow2;
-
- updateRowPointers(x, y, time);
- mvRow1 = mvcData->mvRow1;
- mvRow2 = mvcData->mvRow2;
- mvStoreMB(mvRow1, mvRow2, xx2, yx2, MVD_NOT_CODED,
- MVD_NOT_CODED, time, MVC_MB_NOT_CODED);
-}
-
-
-/* {{-output"mvcStart.txt"}} */
-/*
- *
- * mvcStart
- *
- * Parameters:
- * mvcData mvcData_t structure
- *
- * maxX the largest x coordinate possible for a macroblock
- * If maxX if different from maxX when the function was
- * last called, a new dynamic memory allocation is made.
- *
- * lumWidth Luminance width
- *
- * lumHeight Luminance height
- *
- * error error code
- *
- * Function:
- * This function initialises motion vector buffers. It also allocates
- * buffer memory if needed.
- * One should call mvcStart in the beginning of each video sequence.
- *
- * Returns:
- * Nothing
- *
- * Error codes:
- * ERR_MVC_ALLOC1 dynamic allocation error
- * ERR_MVC_MAX_X_ILLEGAL maxX <= 0
- *
- *
- *
- *
- */
-
-void mvcStart(mvcData_t *mvcData, int maxX, int lumWidth, int lumHeight, int16 *error)
-/* {{-output"mvcStart.txt"}} */
-{
- int
- i, j, /* loop variables */
- rowSize; /* the number of items in prevMV?Row */
-
- if (maxX < 0) {
- *error = ERR_MVC_MAX_X_ILLEGAL;
- return;
- }
-
- rowSize = (maxX + 1) << 1;
-
- if (mvcData->currMaxX != maxX || mvcData->mvRow == NULL) {
- /* frame size changed */
-
- if (mvcData->mvRow) free(mvcData->mvRow);
-
- mvcData->mvRow = (mvRowItem_t *) vdcMalloc(
- rowSize * 3 * sizeof(mvRowItem_t));
- if (mvcData->mvRow == NULL) {
- deb("mvcStart: ERROR - memory allocation failed.\n");
- *error = ERR_MVC_ALLOC1;
- return;
- }
-
- mvcData->currMaxX = maxX;
- }
-
- /* Horizontal motion vector range when PLUSTYPE present and UUI = 1
- See Table D.1/H.263 */
- if (mvcData->currLumHeight != lumHeight)
- {
- mvcData->currLumHeight = lumHeight;
- if ((lumHeight>=4)&&(lumHeight<=288))
- {
- mvcData->mvRangeLowY = -320;
- mvcData->mvRangeHighY = 315;
- }
- else if ((lumHeight>=292)&&(lumHeight<=576))
- {
- mvcData->mvRangeLowY = -640;
- mvcData->mvRangeHighY = 635;
- }
- else if ((lumHeight>=580)&&(lumHeight<=1152))
- {
- mvcData->mvRangeLowY = -1280;
- mvcData->mvRangeHighY = 1275;
- }
- }
-
- /* Vertical motion vector range when PLUSTYPE present and UUI = 1
- See Table D.2/H.263 */
- if (mvcData->currLumWidth != lumWidth)
- {
- mvcData->currLumWidth = lumWidth;
- if ((lumWidth>=4)&&(lumWidth<=352))
- {
- mvcData->mvRangeLowX = -320;
- mvcData->mvRangeHighX = 315;
- }
- else if ((lumWidth>=356)&&(lumWidth<=704))
- {
- mvcData->mvRangeLowX = -640;
- mvcData->mvRangeHighX = 635;
- }
- else if ((lumWidth>=708)&&(lumWidth<=1408))
- {
- mvcData->mvRangeLowX = -1280;
- mvcData->mvRangeHighX = 1275;
- }
- else if ((lumWidth>=1412)&&(lumWidth<=2048))
- {
- mvcData->mvRangeLowX = -2560;
- mvcData->mvRangeHighX = 2555;
- }
- }
- /* Set time to be impossible */
- for (i = 0; i < 3 * rowSize; i++) {
- mvcData->mvRow[i].time = -2;
- }
-
- for (j = 0; j < 2; j++) {
- for (i = 0; i < 4; i++) {
- mvcData->mvFBufArray[j][i].time = -2;
- mvcData->mvBBufArray[j][i].time = -2;
- }
- }
-
- mvcData->currX = -1;
- mvcData->currY = -1;
- mvcData->currTime = -2;
- mvcData->mvRowIndex = 0;
- mvcData->mvBFBufIndex = 0;
- mvcData->prevPredMode = 3;
-}
-
-
-/* Local functions */
-
-
-
-/*
- *
- * mvcGetNeighbourMVs
- *
- * Parameters:
- * mvcData mvcData_t structure
- * x
- * y macroblock coordinates
- * time time reference
- * nmvx pointer to motion vector x component array
- * nmvy pointer to motion vector y component array
- * See mvcGetCurrNeighbourMVs/mvcGetPrevNeighbourMVs for
- * description.
- * prevFlag If this flag is set, the previous border values should
- * be used.
- * error error code
- *
- * Function:
- * This function return the motion vectors of the neighboring
- * blocks (on the left side, above or on the right side) of the
- * macroblock which is investigated. mvcGetNeighbourMVs is used
- * by mvcGetCurrNeighbourMVs and mvcGetPrevNeighbourMVs.
- * See also the functional description for these functions.
- *
- * Returns:
- * Changes nmvx and nmvy and possibly error.
- *
- * Error codes:
- * ERR_MVC_NEIGHBOUR_NOT_VALID if one of the neighboring MVs is not
- * valid, i.e. it has not been updated
- * for this frame. The MV in nmvx and nmvy
- * is set to zero.
- *
- *
- */
-
-static void mvcGetNeighbourMVs(mvcData_t *mvcData, int x, int y, int time,
- int *nmvx, int *nmvy, int prevFlag, int16 *error)
-{
- int
- xx2 = x << 1,
- yx2 = y << 1,
- xtmp,
- ytmp,
- rightOfBorder,
- downOfBorder,
- leftOfBorder;
- mvRowItem_t
- *mvRow0 = mvcData->mvRow0,
- *mvRow1 = mvcData->mvRow1,
- *mvRow2 = mvcData->mvRow2;
-
- if (prevFlag) {
- rightOfBorder = mvcData->rightOfBorderPrev;
- downOfBorder = (mvcData->fSS)?mvcData->downOfBorderPrev:(y==0);
- leftOfBorder = 0;
- }
- else {
- rightOfBorder = mvcData->rightOfBorder;
- downOfBorder = (mvcData->fSS)?mvcData->downOfBorder:(y==0);
- leftOfBorder = (mvcData->fSS)?(x == mvcData->currMaxX)||(mvcData->leftOfBorder):(x == mvcData->currMaxX);
- }
- //if (x > 0) {
- if (!rightOfBorder) {
- xtmp = xx2 - 1;
- mvcCheckAndSet(mvRow1, xtmp, yx2, time, MVC_XM1_UP, nmvx, nmvy,
- mvRow1, xx2, yx2, error);
- mvcCheckAndSet(mvRow2, xtmp, yx2 + 1, time, MVC_XM1_DOWN, nmvx, nmvy,
- mvRow2, xx2, yx2 + 1, error);
- }
- else {
- mvcSetToCurrent(mvRow1, xx2, yx2, time, MVC_XM1_UP, nmvx, nmvy,
- error);
- mvcSetToCurrent(mvRow2, xx2, yx2 + 1, time, MVC_XM1_DOWN, nmvx, nmvy,
- error);
- }
-
- //if (y > 0) {
- if (!downOfBorder) {
- ytmp = yx2 - 1;
- mvcCheckAndSet(mvRow0, xx2, ytmp, time, MVC_YM1_LEFT, nmvx, nmvy,
- mvRow1, xx2, yx2, error);
- mvcCheckAndSet(mvRow0, xx2 + 1, ytmp, time, MVC_YM1_RIGHT, nmvx, nmvy,
- mvRow1, xx2 + 1, yx2, error);
- }
- else {
- mvcSetToCurrent(mvRow1, xx2, yx2, time, MVC_YM1_LEFT, nmvx, nmvy,
- error);
- mvcSetToCurrent(mvRow1, xx2 + 1, yx2, time, MVC_YM1_RIGHT, nmvx, nmvy,
- error);
- }
-
- //if (x < mvcData->currMaxX) {
- if (!leftOfBorder) {
- xtmp = xx2 + 2;
- mvcCheckAndSet(mvRow1, xtmp, yx2, time, MVC_XP1_UP, nmvx, nmvy,
- mvRow1, xtmp - 1, yx2, error);
- mvcCheckAndSet(mvRow2, xtmp, yx2 + 1, time, MVC_XP1_DOWN, nmvx, nmvy,
- mvRow2, xtmp -1, yx2 + 1, error);
- }
- else {
- xtmp = xx2 + 1;
- mvcSetToCurrent(mvRow1, xtmp, yx2, time, MVC_XP1_UP, nmvx, nmvy,
- error);
- mvcSetToCurrent(mvRow2, xtmp, yx2 + 1, time, MVC_XP1_DOWN, nmvx, nmvy,
- error);
- }
-}
-
-
-
-/*
- * mvcCheckAndSet
- *
- * Parameters:
- * mvRowPtr Source row item pointer
- * xind x index of the source block
- * yind y index of the source block
- * timeref time reference
- * nind index to motion vector arrays ( x and y)
- * nmvx pointer to motion vector x component array
- * nmvy pointer to motion vector y component array
- * cmvRowPtr Target row item pointer
- * cxind x index of the target block
- * cyind y index of the target block
- * error error code
- *
- * Function:
- * Sets the correct value for neighboring motion vector
- * used from: mvcGetNeighbourMVs
- *
- * Returns:
- * Nothing
- *
- * Error codes:
- *
- */
-
-__inline static void mvcCheckAndSet(
- mvRowItem_t *mvRowPtr, int xind, int yind, int timeref, int nind,
- int *nmvx, int *nmvy, mvRowItem_t *cmvRowPtr, int cxind, int cyind,
- int16 *error)
-{
-
- if (mvLegal(mvRowPtr[xind], yind, timeref)) {
- if (mvRowPtr[xind].mvx >= MVD_UMIN_V2) {
- nmvx[nind] = mvRowPtr[xind].mvx;
- nmvy[nind] = mvRowPtr[xind].mvy;
- }
- else if (mvRowPtr[xind].mvx == MVD_INTRA) {
- if (mvLegal(cmvRowPtr[cxind], cyind, timeref)) {
- if (mvValid(cmvRowPtr[cxind], cyind, timeref)) {
- nmvx[nind] = cmvRowPtr[cxind].mvx;
- nmvy[nind] = cmvRowPtr[cxind].mvy;
- }
- else /* Not coded macroblock */
- nmvx[nind] = nmvy[nind] = 0;
- }
- else {
- deb("mvcCheckAndSet: ERROR - neighbour not valid.\n");
- *error = ERR_MVC_NEIGHBOUR_NOT_VALID;
- nmvx[nind] = nmvy[nind] = 0;
- }
- }
- else { /* MVD_NOT_CODED */
- nmvx[nind] = nmvy[nind] = 0;
- }
- }
- else {
- deb("mvcCheckAndSet: ERROR - neighbour not valid.\n");
- *error = ERR_MVC_NEIGHBOUR_NOT_VALID;
- nmvx[nind] = nmvy[nind] = 0;
- }
-}
-
-/*
- * mvcSetToCurrent
- *
- * Parameters:
- * mvRowPtr Current row item pointer
- * xind x index of the block
- * yind y index of the block
- * timeref time reference
- * nind index to motion vector arrays ( x and y)
- * nmvx pointer to motion vector x component array
- * nmvy pointer to motion vector y component array
- * error error code
- *
- * Function:
- * Sets the correct value for neighboring motion vector using current
- * motion vector, used in cases of border used from: mvcGetNeighbourMVs
- *
- * Returns:
- * Nothing
- *
- * Error codes:
- *
- * History
- */
-
-__inline static void mvcSetToCurrent(
- mvRowItem_t *mvRowPtr, int xind, int yind, int timeref, int nind,
- int *nmvx, int *nmvy, int16 *error)
-{
- if (mvValid(mvRowPtr[xind], yind, timeref)) {
- nmvx[nind] = mvRowPtr[xind].mvx;
- nmvy[nind] = mvRowPtr[xind].mvy;
- }
- else {
- deb("mvcSetToCurrent: ERROR - neighbour not valid.\n");
- *error = ERR_MVC_NEIGHBOUR_NOT_VALID;
- nmvx[nind] = nmvy[nind] = 0;
- }
-}
-
-// End of File