omxVCM4P2_EncodeMV.c revision 0c1bc742181ded4930842b46e9507372f0b1b963
10c1bc742181ded4930842b46e9507372f0b1b963James Dong/**
20c1bc742181ded4930842b46e9507372f0b1b963James Dong *
30c1bc742181ded4930842b46e9507372f0b1b963James Dong * File Name:  omxVCM4P2_EncodeMV.c
40c1bc742181ded4930842b46e9507372f0b1b963James Dong * OpenMAX DL: v1.0.2
50c1bc742181ded4930842b46e9507372f0b1b963James Dong * Revision:   9641
60c1bc742181ded4930842b46e9507372f0b1b963James Dong * Date:       Thursday, February 7, 2008
70c1bc742181ded4930842b46e9507372f0b1b963James Dong *
80c1bc742181ded4930842b46e9507372f0b1b963James Dong * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
90c1bc742181ded4930842b46e9507372f0b1b963James Dong *
100c1bc742181ded4930842b46e9507372f0b1b963James Dong *
110c1bc742181ded4930842b46e9507372f0b1b963James Dong *
120c1bc742181ded4930842b46e9507372f0b1b963James Dong * Description:
130c1bc742181ded4930842b46e9507372f0b1b963James Dong * Contains module for predicting MV of MB
140c1bc742181ded4930842b46e9507372f0b1b963James Dong *
150c1bc742181ded4930842b46e9507372f0b1b963James Dong */
160c1bc742181ded4930842b46e9507372f0b1b963James Dong
170c1bc742181ded4930842b46e9507372f0b1b963James Dong#include "omxtypes.h"
180c1bc742181ded4930842b46e9507372f0b1b963James Dong#include "armOMX.h"
190c1bc742181ded4930842b46e9507372f0b1b963James Dong#include "omxVC.h"
200c1bc742181ded4930842b46e9507372f0b1b963James Dong
210c1bc742181ded4930842b46e9507372f0b1b963James Dong#include "armCOMM.h"
220c1bc742181ded4930842b46e9507372f0b1b963James Dong#include "armCOMM_Bitstream.h"
230c1bc742181ded4930842b46e9507372f0b1b963James Dong#include "armVCM4P2_Huff_Tables_VLC.h"
240c1bc742181ded4930842b46e9507372f0b1b963James Dong
250c1bc742181ded4930842b46e9507372f0b1b963James Dong
260c1bc742181ded4930842b46e9507372f0b1b963James Dong
270c1bc742181ded4930842b46e9507372f0b1b963James Dong/**
280c1bc742181ded4930842b46e9507372f0b1b963James Dong * Function:  omxVCM4P2_EncodeMV   (6.2.4.5.4)
290c1bc742181ded4930842b46e9507372f0b1b963James Dong *
300c1bc742181ded4930842b46e9507372f0b1b963James Dong * Description:
310c1bc742181ded4930842b46e9507372f0b1b963James Dong * Predicts a motion vector for the current macroblock, encodes the
320c1bc742181ded4930842b46e9507372f0b1b963James Dong * difference, and writes the output to the stream buffer. The input MVs
330c1bc742181ded4930842b46e9507372f0b1b963James Dong * pMVCurMB, pSrcMVLeftMB, pSrcMVUpperMB, and pSrcMVUpperRightMB should lie
340c1bc742181ded4930842b46e9507372f0b1b963James Dong * within the ranges associated with the input parameter fcodeForward, as
350c1bc742181ded4930842b46e9507372f0b1b963James Dong * described in [ISO14496-2], subclause 7.6.3.  This function provides a
360c1bc742181ded4930842b46e9507372f0b1b963James Dong * superset of the functionality associated with the function
370c1bc742181ded4930842b46e9507372f0b1b963James Dong * omxVCM4P2_FindMVpred.
380c1bc742181ded4930842b46e9507372f0b1b963James Dong *
390c1bc742181ded4930842b46e9507372f0b1b963James Dong * Input Arguments:
400c1bc742181ded4930842b46e9507372f0b1b963James Dong *
410c1bc742181ded4930842b46e9507372f0b1b963James Dong *   ppBitStream - double pointer to the current byte in the bitstream buffer
420c1bc742181ded4930842b46e9507372f0b1b963James Dong *   pBitOffset - index of the first free (next available) bit in the stream
430c1bc742181ded4930842b46e9507372f0b1b963James Dong *            buffer referenced by *ppBitStream, valid in the range 0 to 7.
440c1bc742181ded4930842b46e9507372f0b1b963James Dong *   pMVCurMB - pointer to the current macroblock motion vector; a value of
450c1bc742181ded4930842b46e9507372f0b1b963James Dong *            NULL indicates unavailability.
460c1bc742181ded4930842b46e9507372f0b1b963James Dong *   pSrcMVLeftMB - pointer to the source left macroblock motion vector; a
470c1bc742181ded4930842b46e9507372f0b1b963James Dong *            value of  NULLindicates unavailability.
480c1bc742181ded4930842b46e9507372f0b1b963James Dong *   pSrcMVUpperMB - pointer to source upper macroblock motion vector; a
490c1bc742181ded4930842b46e9507372f0b1b963James Dong *            value of NULL indicates unavailability.
500c1bc742181ded4930842b46e9507372f0b1b963James Dong *   pSrcMVUpperRightMB - pointer to source upper right MB motion vector; a
510c1bc742181ded4930842b46e9507372f0b1b963James Dong *            value of NULL indicates unavailability.
520c1bc742181ded4930842b46e9507372f0b1b963James Dong *   fcodeForward - an integer with values from 1 to 7; used in encoding
530c1bc742181ded4930842b46e9507372f0b1b963James Dong *            motion vectors related to search range, as described in
540c1bc742181ded4930842b46e9507372f0b1b963James Dong *            [ISO14496-2], subclause 7.6.3.
550c1bc742181ded4930842b46e9507372f0b1b963James Dong *   MBType - macro block type, valid in the range 0 to 5
560c1bc742181ded4930842b46e9507372f0b1b963James Dong *
570c1bc742181ded4930842b46e9507372f0b1b963James Dong * Output Arguments:
580c1bc742181ded4930842b46e9507372f0b1b963James Dong *
590c1bc742181ded4930842b46e9507372f0b1b963James Dong *   ppBitStream - updated pointer to the current byte in the bit stream
600c1bc742181ded4930842b46e9507372f0b1b963James Dong *            buffer
610c1bc742181ded4930842b46e9507372f0b1b963James Dong *   pBitOffset - updated index of the next available bit position in stream
620c1bc742181ded4930842b46e9507372f0b1b963James Dong *            buffer referenced by *ppBitStream
630c1bc742181ded4930842b46e9507372f0b1b963James Dong *
640c1bc742181ded4930842b46e9507372f0b1b963James Dong * Return Value:
650c1bc742181ded4930842b46e9507372f0b1b963James Dong *
660c1bc742181ded4930842b46e9507372f0b1b963James Dong *    OMX_Sts_NoErr - no error
670c1bc742181ded4930842b46e9507372f0b1b963James Dong *    OMX_Sts_BadArgErr - bad arguments
680c1bc742181ded4930842b46e9507372f0b1b963James Dong *    -    At least one of the following pointers is NULL: ppBitStream,
690c1bc742181ded4930842b46e9507372f0b1b963James Dong *              *ppBitStream, pBitOffset, pMVCurMB
700c1bc742181ded4930842b46e9507372f0b1b963James Dong *    -    *pBitOffset < 0, or *pBitOffset >7.
710c1bc742181ded4930842b46e9507372f0b1b963James Dong *    -    fcodeForward <= 0, or fcodeForward > 7, or MBType < 0.
720c1bc742181ded4930842b46e9507372f0b1b963James Dong *
730c1bc742181ded4930842b46e9507372f0b1b963James Dong */
740c1bc742181ded4930842b46e9507372f0b1b963James Dong
750c1bc742181ded4930842b46e9507372f0b1b963James DongOMXResult omxVCM4P2_EncodeMV(
760c1bc742181ded4930842b46e9507372f0b1b963James Dong     OMX_U8 **ppBitStream,
770c1bc742181ded4930842b46e9507372f0b1b963James Dong     OMX_INT *pBitOffset,
780c1bc742181ded4930842b46e9507372f0b1b963James Dong     const OMXVCMotionVector * pMVCurMB,
790c1bc742181ded4930842b46e9507372f0b1b963James Dong     const OMXVCMotionVector * pSrcMVLeftMB,
800c1bc742181ded4930842b46e9507372f0b1b963James Dong     const OMXVCMotionVector * pSrcMVUpperMB,
810c1bc742181ded4930842b46e9507372f0b1b963James Dong     const OMXVCMotionVector * pSrcMVUpperRightMB,
820c1bc742181ded4930842b46e9507372f0b1b963James Dong     OMX_INT fcodeForward,
830c1bc742181ded4930842b46e9507372f0b1b963James Dong     OMXVCM4P2MacroblockType MBType
840c1bc742181ded4930842b46e9507372f0b1b963James Dong)
850c1bc742181ded4930842b46e9507372f0b1b963James Dong{
860c1bc742181ded4930842b46e9507372f0b1b963James Dong    OMXVCMotionVector dstMVPred, diffMV;
870c1bc742181ded4930842b46e9507372f0b1b963James Dong    OMXVCMotionVector dstMVPredME[12];
880c1bc742181ded4930842b46e9507372f0b1b963James Dong    /* Initialized to remove compilation warning */
890c1bc742181ded4930842b46e9507372f0b1b963James Dong    OMX_INT iBlk, i, count = 1;
900c1bc742181ded4930842b46e9507372f0b1b963James Dong    OMX_S32 mvHorResidual, mvVerResidual, mvHorData, mvVerData;
910c1bc742181ded4930842b46e9507372f0b1b963James Dong    OMX_U8 scaleFactor, index;
920c1bc742181ded4930842b46e9507372f0b1b963James Dong
930c1bc742181ded4930842b46e9507372f0b1b963James Dong    /* Argument error checks */
940c1bc742181ded4930842b46e9507372f0b1b963James Dong    armRetArgErrIf(ppBitStream == NULL, OMX_Sts_BadArgErr);
950c1bc742181ded4930842b46e9507372f0b1b963James Dong    armRetArgErrIf(*ppBitStream == NULL, OMX_Sts_BadArgErr);
960c1bc742181ded4930842b46e9507372f0b1b963James Dong    armRetArgErrIf(pBitOffset == NULL, OMX_Sts_BadArgErr);
970c1bc742181ded4930842b46e9507372f0b1b963James Dong    armRetArgErrIf(pMVCurMB == NULL, OMX_Sts_BadArgErr);
980c1bc742181ded4930842b46e9507372f0b1b963James Dong    armRetArgErrIf(((*pBitOffset < 0) || (*pBitOffset > 7)), OMX_Sts_BadArgErr);
990c1bc742181ded4930842b46e9507372f0b1b963James Dong    armRetArgErrIf(((fcodeForward < 1) || (fcodeForward > 7)), \
1000c1bc742181ded4930842b46e9507372f0b1b963James Dong                    OMX_Sts_BadArgErr);
1010c1bc742181ded4930842b46e9507372f0b1b963James Dong
1020c1bc742181ded4930842b46e9507372f0b1b963James Dong    if ((MBType == OMX_VC_INTRA) ||
1030c1bc742181ded4930842b46e9507372f0b1b963James Dong        (MBType == OMX_VC_INTRA_Q)
1040c1bc742181ded4930842b46e9507372f0b1b963James Dong       )
1050c1bc742181ded4930842b46e9507372f0b1b963James Dong    {
1060c1bc742181ded4930842b46e9507372f0b1b963James Dong        /* No candidate vectors hence make them zero */
1070c1bc742181ded4930842b46e9507372f0b1b963James Dong        for (i = 0; i < 12; i++)
1080c1bc742181ded4930842b46e9507372f0b1b963James Dong        {
1090c1bc742181ded4930842b46e9507372f0b1b963James Dong            dstMVPredME[i].dx = 0;
1100c1bc742181ded4930842b46e9507372f0b1b963James Dong            dstMVPredME[i].dy = 0;
1110c1bc742181ded4930842b46e9507372f0b1b963James Dong        }
1120c1bc742181ded4930842b46e9507372f0b1b963James Dong
1130c1bc742181ded4930842b46e9507372f0b1b963James Dong        return OMX_Sts_NoErr;
1140c1bc742181ded4930842b46e9507372f0b1b963James Dong    }
1150c1bc742181ded4930842b46e9507372f0b1b963James Dong
1160c1bc742181ded4930842b46e9507372f0b1b963James Dong    if ((MBType == OMX_VC_INTER4V) || (MBType == OMX_VC_INTER4V_Q))
1170c1bc742181ded4930842b46e9507372f0b1b963James Dong    {
1180c1bc742181ded4930842b46e9507372f0b1b963James Dong        count = 4;
1190c1bc742181ded4930842b46e9507372f0b1b963James Dong    }
1200c1bc742181ded4930842b46e9507372f0b1b963James Dong    else if ((MBType == OMX_VC_INTER) || (MBType == OMX_VC_INTER_Q))
1210c1bc742181ded4930842b46e9507372f0b1b963James Dong    {
1220c1bc742181ded4930842b46e9507372f0b1b963James Dong        count = 1;
1230c1bc742181ded4930842b46e9507372f0b1b963James Dong    }
1240c1bc742181ded4930842b46e9507372f0b1b963James Dong
1250c1bc742181ded4930842b46e9507372f0b1b963James Dong    /* Calculating the scale factor */
1260c1bc742181ded4930842b46e9507372f0b1b963James Dong    scaleFactor = 1 << (fcodeForward -1);
1270c1bc742181ded4930842b46e9507372f0b1b963James Dong
1280c1bc742181ded4930842b46e9507372f0b1b963James Dong    for (iBlk = 0; iBlk < count; iBlk++)
1290c1bc742181ded4930842b46e9507372f0b1b963James Dong    {
1300c1bc742181ded4930842b46e9507372f0b1b963James Dong
1310c1bc742181ded4930842b46e9507372f0b1b963James Dong        /* Find the predicted vector */
1320c1bc742181ded4930842b46e9507372f0b1b963James Dong        omxVCM4P2_FindMVpred (
1330c1bc742181ded4930842b46e9507372f0b1b963James Dong            pMVCurMB,
1340c1bc742181ded4930842b46e9507372f0b1b963James Dong            pSrcMVLeftMB,
1350c1bc742181ded4930842b46e9507372f0b1b963James Dong            pSrcMVUpperMB,
1360c1bc742181ded4930842b46e9507372f0b1b963James Dong            pSrcMVUpperRightMB,
1370c1bc742181ded4930842b46e9507372f0b1b963James Dong            &dstMVPred,
1380c1bc742181ded4930842b46e9507372f0b1b963James Dong            dstMVPredME,
1390c1bc742181ded4930842b46e9507372f0b1b963James Dong            iBlk );
1400c1bc742181ded4930842b46e9507372f0b1b963James Dong
1410c1bc742181ded4930842b46e9507372f0b1b963James Dong        /* Calculating the differential motion vector (diffMV) */
1420c1bc742181ded4930842b46e9507372f0b1b963James Dong        diffMV.dx = pMVCurMB[iBlk].dx - dstMVPred.dx;
1430c1bc742181ded4930842b46e9507372f0b1b963James Dong        diffMV.dy = pMVCurMB[iBlk].dy - dstMVPred.dy;
1440c1bc742181ded4930842b46e9507372f0b1b963James Dong
1450c1bc742181ded4930842b46e9507372f0b1b963James Dong        /* Calculating the mv_data and mv_residual for Horizantal MV */
1460c1bc742181ded4930842b46e9507372f0b1b963James Dong        if (diffMV.dx == 0)
1470c1bc742181ded4930842b46e9507372f0b1b963James Dong        {
1480c1bc742181ded4930842b46e9507372f0b1b963James Dong            mvHorResidual = 0;
1490c1bc742181ded4930842b46e9507372f0b1b963James Dong            mvHorData = 0;
1500c1bc742181ded4930842b46e9507372f0b1b963James Dong        }
1510c1bc742181ded4930842b46e9507372f0b1b963James Dong        else
1520c1bc742181ded4930842b46e9507372f0b1b963James Dong        {
1530c1bc742181ded4930842b46e9507372f0b1b963James Dong            mvHorResidual = ( armAbs(diffMV.dx) - 1) % scaleFactor;
1540c1bc742181ded4930842b46e9507372f0b1b963James Dong            mvHorData = (armAbs(diffMV.dx) - mvHorResidual + (scaleFactor - 1))
1550c1bc742181ded4930842b46e9507372f0b1b963James Dong                     / scaleFactor;
1560c1bc742181ded4930842b46e9507372f0b1b963James Dong            if (diffMV.dx < 0)
1570c1bc742181ded4930842b46e9507372f0b1b963James Dong            {
1580c1bc742181ded4930842b46e9507372f0b1b963James Dong                mvHorData = -mvHorData;
1590c1bc742181ded4930842b46e9507372f0b1b963James Dong            }
1600c1bc742181ded4930842b46e9507372f0b1b963James Dong        }
1610c1bc742181ded4930842b46e9507372f0b1b963James Dong
1620c1bc742181ded4930842b46e9507372f0b1b963James Dong        /* Calculating the mv_data and mv_residual for Vertical MV */
1630c1bc742181ded4930842b46e9507372f0b1b963James Dong        if (diffMV.dy == 0)
1640c1bc742181ded4930842b46e9507372f0b1b963James Dong        {
1650c1bc742181ded4930842b46e9507372f0b1b963James Dong            mvVerResidual = 0;
1660c1bc742181ded4930842b46e9507372f0b1b963James Dong            mvVerData = 0;
1670c1bc742181ded4930842b46e9507372f0b1b963James Dong        }
1680c1bc742181ded4930842b46e9507372f0b1b963James Dong        else
1690c1bc742181ded4930842b46e9507372f0b1b963James Dong        {
1700c1bc742181ded4930842b46e9507372f0b1b963James Dong            mvVerResidual = ( armAbs(diffMV.dy) - 1) % scaleFactor;
1710c1bc742181ded4930842b46e9507372f0b1b963James Dong            mvVerData = (armAbs(diffMV.dy) - mvVerResidual + (scaleFactor - 1))
1720c1bc742181ded4930842b46e9507372f0b1b963James Dong                     / scaleFactor;
1730c1bc742181ded4930842b46e9507372f0b1b963James Dong            if (diffMV.dy < 0)
1740c1bc742181ded4930842b46e9507372f0b1b963James Dong            {
1750c1bc742181ded4930842b46e9507372f0b1b963James Dong                mvVerData = -mvVerData;
1760c1bc742181ded4930842b46e9507372f0b1b963James Dong            }
1770c1bc742181ded4930842b46e9507372f0b1b963James Dong        }
1780c1bc742181ded4930842b46e9507372f0b1b963James Dong
1790c1bc742181ded4930842b46e9507372f0b1b963James Dong        /* Huffman encoding */
1800c1bc742181ded4930842b46e9507372f0b1b963James Dong
1810c1bc742181ded4930842b46e9507372f0b1b963James Dong        /* The index is actually calculate as
1820c1bc742181ded4930842b46e9507372f0b1b963James Dong           index = ((float) (mvHorData/2) + 16) * 2,
1830c1bc742181ded4930842b46e9507372f0b1b963James Dong           meaning the MV data is halfed and then normalized
1840c1bc742181ded4930842b46e9507372f0b1b963James Dong           to begin with zero and then doubled to take care of indexing
1850c1bc742181ded4930842b46e9507372f0b1b963James Dong           the fractional part included */
1860c1bc742181ded4930842b46e9507372f0b1b963James Dong        index = mvHorData + 32;
1870c1bc742181ded4930842b46e9507372f0b1b963James Dong        armPackVLC32 (ppBitStream, pBitOffset, armVCM4P2_aVlcMVD[index]);
1880c1bc742181ded4930842b46e9507372f0b1b963James Dong        if ((fcodeForward > 1) && (diffMV.dx != 0))
1890c1bc742181ded4930842b46e9507372f0b1b963James Dong        {
1900c1bc742181ded4930842b46e9507372f0b1b963James Dong            armPackBits (ppBitStream, pBitOffset, mvHorResidual, (fcodeForward -1));
1910c1bc742181ded4930842b46e9507372f0b1b963James Dong        }
1920c1bc742181ded4930842b46e9507372f0b1b963James Dong
1930c1bc742181ded4930842b46e9507372f0b1b963James Dong        /* The index is actually calculate as
1940c1bc742181ded4930842b46e9507372f0b1b963James Dong           index = ((float) (mvVerData/2) + 16) * 2,
1950c1bc742181ded4930842b46e9507372f0b1b963James Dong           meaning the MV data is halfed and then normalized
1960c1bc742181ded4930842b46e9507372f0b1b963James Dong           to begin with zero and then doubled to take care of indexing
1970c1bc742181ded4930842b46e9507372f0b1b963James Dong           the fractional part included */
1980c1bc742181ded4930842b46e9507372f0b1b963James Dong        index = mvVerData + 32;
1990c1bc742181ded4930842b46e9507372f0b1b963James Dong        armPackVLC32 (ppBitStream, pBitOffset, armVCM4P2_aVlcMVD[index]);
2000c1bc742181ded4930842b46e9507372f0b1b963James Dong        if ((fcodeForward > 1) && (diffMV.dy != 0))
2010c1bc742181ded4930842b46e9507372f0b1b963James Dong        {
2020c1bc742181ded4930842b46e9507372f0b1b963James Dong            armPackBits (ppBitStream, pBitOffset, mvVerResidual, (fcodeForward -1));
2030c1bc742181ded4930842b46e9507372f0b1b963James Dong        }
2040c1bc742181ded4930842b46e9507372f0b1b963James Dong    }
2050c1bc742181ded4930842b46e9507372f0b1b963James Dong
2060c1bc742181ded4930842b46e9507372f0b1b963James Dong    return OMX_Sts_NoErr;
2070c1bc742181ded4930842b46e9507372f0b1b963James Dong}
2080c1bc742181ded4930842b46e9507372f0b1b963James Dong
2090c1bc742181ded4930842b46e9507372f0b1b963James Dong
2100c1bc742181ded4930842b46e9507372f0b1b963James Dong/* End of file */
2110c1bc742181ded4930842b46e9507372f0b1b963James Dong
2120c1bc742181ded4930842b46e9507372f0b1b963James Dong
213