blob: 054b4860d21fc41e402699ac0e6f9378b812527e [file] [log] [blame]
/*
* Copyright (C) 2007-2008 ARM Limited
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
/**
*
* File Name: omxVCM4P2_FindMVpred.c
* OpenMAX DL: v1.0.2
* Revision: 9641
* Date: Thursday, February 7, 2008
*
*
*
*
* Description:
* Contains module for predicting MV of MB
*
*/
#include "omxtypes.h"
#include "armOMX.h"
#include "omxVC.h"
#include "armCOMM.h"
/**
* Function: omxVCM4P2_FindMVpred (6.2.3.1.1)
*
* Description:
* Predicts a motion vector for the current block using the procedure
* specified in [ISO14496-2], subclause 7.6.5. The resulting predicted MV is
* returned in pDstMVPred. If the parameter pDstMVPredME if is not NULL then
* the set of three MV candidates used for prediction is also returned,
* otherwise pDstMVPredMEis NULL upon return.
*
* Input Arguments:
*
* pSrcMVCurMB - pointer to the MV buffer associated with the current Y
* macroblock; a value of NULL indicates unavailability.
* pSrcCandMV1 - pointer to the MV buffer containing the 4 MVs associated
* with the MB located to the left of the current MB; set to NULL
* if there is no MB to the left.
* pSrcCandMV2 - pointer to the MV buffer containing the 4 MVs associated
* with the MB located above the current MB; set to NULL if there
* is no MB located above the current MB.
* pSrcCandMV3 - pointer to the MV buffer containing the 4 MVs associated
* with the MB located to the right and above the current MB; set
* to NULL if there is no MB located to the above-right.
* iBlk - the index of block in the current macroblock
* pDstMVPredME - MV candidate return buffer; if set to NULL then
* prediction candidate MVs are not returned and pDstMVPredME will
* be NULL upon function return; if pDstMVPredME is non-NULL then it
* must point to a buffer containing sufficient space for three
* return MVs.
*
* Output Arguments:
*
* pDstMVPred - pointer to the predicted motion vector
* pDstMVPredME - if non-NULL upon input then pDstMVPredME points upon
* return to a buffer containing the three motion vector candidates
* used for prediction as specified in [ISO14496-2], subclause
* 7.6.5, otherwise if NULL upon input then pDstMVPredME is NULL
* upon output.
*
* Return Value:
*
* OMX_Sts_NoErr - no error
* OMX_Sts_BadArgErr - bad arguments; returned under any of the following
* conditions:
* - the pointer pDstMVPred is NULL
* - the parameter iBlk does not fall into the range 0 <= iBlk<=3
*
*/
OMXResult omxVCM4P2_FindMVpred(
const OMXVCMotionVector* pSrcMVCurMB,
const OMXVCMotionVector* pSrcCandMV1,
const OMXVCMotionVector* pSrcCandMV2,
const OMXVCMotionVector* pSrcCandMV3,
OMXVCMotionVector* pDstMVPred,
OMXVCMotionVector* pDstMVPredME,
OMX_INT iBlk
)
{
OMXVCMotionVector CandMV;
const OMXVCMotionVector *pCandMV1;
const OMXVCMotionVector *pCandMV2;
const OMXVCMotionVector *pCandMV3;
/* Argument error checks */
armRetArgErrIf(iBlk!=0 && pSrcMVCurMB == NULL, OMX_Sts_BadArgErr);
armRetArgErrIf(pDstMVPred == NULL, OMX_Sts_BadArgErr);
armRetArgErrIf((iBlk < 0) || (iBlk > 3), OMX_Sts_BadArgErr);
CandMV.dx = CandMV.dy = 0;
/* Based on the position of the block extract the motion vectors and
the tranperancy status */
/* Set the default value for these to be used if pSrcCandMV[1|2|3] == NULL */
pCandMV1 = pCandMV2 = pCandMV3 = &CandMV;
switch (iBlk)
{
case 0:
{
if(pSrcCandMV1 != NULL)
{
pCandMV1 = &pSrcCandMV1[1];
}
if(pSrcCandMV2 != NULL)
{
pCandMV2 = &pSrcCandMV2[2];
}
if(pSrcCandMV3 != NULL)
{
pCandMV3 = &pSrcCandMV3[2];
}
if ((pSrcCandMV1 == NULL) && (pSrcCandMV2 == NULL))
{
pCandMV1 = pCandMV2 = pCandMV3;
}
else if((pSrcCandMV1 == NULL) && (pSrcCandMV3 == NULL))
{
pCandMV1 = pCandMV3 = pCandMV2;
}
else if((pSrcCandMV2 == NULL) && (pSrcCandMV3 == NULL))
{
pCandMV2 = pCandMV3 = pCandMV1;
}
break;
}
case 1:
{
pCandMV1 = &pSrcMVCurMB[0];
if(pSrcCandMV2 != NULL)
{
pCandMV2 = &pSrcCandMV2[3];
}
if(pSrcCandMV3 != NULL)
{
pCandMV3 = &pSrcCandMV3[2];
}
if((pSrcCandMV2 == NULL) && (pSrcCandMV3 == NULL))
{
pCandMV2 = pCandMV3 = pCandMV1;
}
break;
}
case 2:
{
if(pSrcCandMV1 != NULL)
{
pCandMV1 = &pSrcCandMV1[3];
}
pCandMV2 = &pSrcMVCurMB[0];
pCandMV3 = &pSrcMVCurMB[1];
break;
}
case 3:
{
pCandMV1 = &pSrcMVCurMB[2];
pCandMV2 = &pSrcMVCurMB[0];
pCandMV3 = &pSrcMVCurMB[1];
break;
}
}
/* Find the median of the 3 candidate MV's */
pDstMVPred->dx = armMedianOf3 (pCandMV1->dx, pCandMV2->dx, pCandMV3->dx);
pDstMVPred->dy = armMedianOf3 (pCandMV1->dy, pCandMV2->dy, pCandMV3->dy);
if (pDstMVPredME != NULL)
{
/* Store the candidate MV's into the pDstMVPredME, these can be used
in the fast algorithm if implemented */
pDstMVPredME[0].dx = pCandMV1->dx;
pDstMVPredME[0].dy = pCandMV1->dy;
pDstMVPredME[1].dx = pCandMV2->dx;
pDstMVPredME[1].dy = pCandMV2->dy;
pDstMVPredME[2].dx = pCandMV3->dx;
pDstMVPredME[2].dy = pCandMV3->dy;
}
return OMX_Sts_NoErr;
}
/* End of file */