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