1/* 2 * Copyright (C) 2007-2008 ARM Limited 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 * 16 */ 17/** 18 * 19 * File Name: omxVCM4P2_EncodeMV.c 20 * OpenMAX DL: v1.0.2 21 * Revision: 9641 22 * Date: Thursday, February 7, 2008 23 * 24 * 25 * 26 * 27 * Description: 28 * Contains module for predicting MV of MB 29 * 30 */ 31 32#include "omxtypes.h" 33#include "armOMX.h" 34#include "omxVC.h" 35 36#include "armCOMM.h" 37#include "armCOMM_Bitstream.h" 38#include "armVCM4P2_Huff_Tables_VLC.h" 39 40 41 42/** 43 * Function: omxVCM4P2_EncodeMV (6.2.4.5.4) 44 * 45 * Description: 46 * Predicts a motion vector for the current macroblock, encodes the 47 * difference, and writes the output to the stream buffer. The input MVs 48 * pMVCurMB, pSrcMVLeftMB, pSrcMVUpperMB, and pSrcMVUpperRightMB should lie 49 * within the ranges associated with the input parameter fcodeForward, as 50 * described in [ISO14496-2], subclause 7.6.3. This function provides a 51 * superset of the functionality associated with the function 52 * omxVCM4P2_FindMVpred. 53 * 54 * Input Arguments: 55 * 56 * ppBitStream - double pointer to the current byte in the bitstream buffer 57 * pBitOffset - index of the first free (next available) bit in the stream 58 * buffer referenced by *ppBitStream, valid in the range 0 to 7. 59 * pMVCurMB - pointer to the current macroblock motion vector; a value of 60 * NULL indicates unavailability. 61 * pSrcMVLeftMB - pointer to the source left macroblock motion vector; a 62 * value of NULLindicates unavailability. 63 * pSrcMVUpperMB - pointer to source upper macroblock motion vector; a 64 * value of NULL indicates unavailability. 65 * pSrcMVUpperRightMB - pointer to source upper right MB motion vector; a 66 * value of NULL indicates unavailability. 67 * fcodeForward - an integer with values from 1 to 7; used in encoding 68 * motion vectors related to search range, as described in 69 * [ISO14496-2], subclause 7.6.3. 70 * MBType - macro block type, valid in the range 0 to 5 71 * 72 * Output Arguments: 73 * 74 * ppBitStream - updated pointer to the current byte in the bit stream 75 * buffer 76 * pBitOffset - updated index of the next available bit position in stream 77 * buffer referenced by *ppBitStream 78 * 79 * Return Value: 80 * 81 * OMX_Sts_NoErr - no error 82 * OMX_Sts_BadArgErr - bad arguments 83 * - At least one of the following pointers is NULL: ppBitStream, 84 * *ppBitStream, pBitOffset, pMVCurMB 85 * - *pBitOffset < 0, or *pBitOffset >7. 86 * - fcodeForward <= 0, or fcodeForward > 7, or MBType < 0. 87 * 88 */ 89 90OMXResult omxVCM4P2_EncodeMV( 91 OMX_U8 **ppBitStream, 92 OMX_INT *pBitOffset, 93 const OMXVCMotionVector * pMVCurMB, 94 const OMXVCMotionVector * pSrcMVLeftMB, 95 const OMXVCMotionVector * pSrcMVUpperMB, 96 const OMXVCMotionVector * pSrcMVUpperRightMB, 97 OMX_INT fcodeForward, 98 OMXVCM4P2MacroblockType MBType 99) 100{ 101 OMXVCMotionVector dstMVPred, diffMV; 102 OMXVCMotionVector dstMVPredME[12]; 103 /* Initialized to remove compilation warning */ 104 OMX_INT iBlk, i, count = 1; 105 OMX_S32 mvHorResidual, mvVerResidual, mvHorData, mvVerData; 106 OMX_U8 scaleFactor, index; 107 108 /* Argument error checks */ 109 armRetArgErrIf(ppBitStream == NULL, OMX_Sts_BadArgErr); 110 armRetArgErrIf(*ppBitStream == NULL, OMX_Sts_BadArgErr); 111 armRetArgErrIf(pBitOffset == NULL, OMX_Sts_BadArgErr); 112 armRetArgErrIf(pMVCurMB == NULL, OMX_Sts_BadArgErr); 113 armRetArgErrIf(((*pBitOffset < 0) || (*pBitOffset > 7)), OMX_Sts_BadArgErr); 114 armRetArgErrIf(((fcodeForward < 1) || (fcodeForward > 7)), \ 115 OMX_Sts_BadArgErr); 116 117 if ((MBType == OMX_VC_INTRA) || 118 (MBType == OMX_VC_INTRA_Q) 119 ) 120 { 121 /* No candidate vectors hence make them zero */ 122 for (i = 0; i < 12; i++) 123 { 124 dstMVPredME[i].dx = 0; 125 dstMVPredME[i].dy = 0; 126 } 127 128 return OMX_Sts_NoErr; 129 } 130 131 if ((MBType == OMX_VC_INTER4V) || (MBType == OMX_VC_INTER4V_Q)) 132 { 133 count = 4; 134 } 135 else if ((MBType == OMX_VC_INTER) || (MBType == OMX_VC_INTER_Q)) 136 { 137 count = 1; 138 } 139 140 /* Calculating the scale factor */ 141 scaleFactor = 1 << (fcodeForward -1); 142 143 for (iBlk = 0; iBlk < count; iBlk++) 144 { 145 146 /* Find the predicted vector */ 147 omxVCM4P2_FindMVpred ( 148 pMVCurMB, 149 pSrcMVLeftMB, 150 pSrcMVUpperMB, 151 pSrcMVUpperRightMB, 152 &dstMVPred, 153 dstMVPredME, 154 iBlk ); 155 156 /* Calculating the differential motion vector (diffMV) */ 157 diffMV.dx = pMVCurMB[iBlk].dx - dstMVPred.dx; 158 diffMV.dy = pMVCurMB[iBlk].dy - dstMVPred.dy; 159 160 /* Calculating the mv_data and mv_residual for Horizantal MV */ 161 if (diffMV.dx == 0) 162 { 163 mvHorResidual = 0; 164 mvHorData = 0; 165 } 166 else 167 { 168 mvHorResidual = ( armAbs(diffMV.dx) - 1) % scaleFactor; 169 mvHorData = (armAbs(diffMV.dx) - mvHorResidual + (scaleFactor - 1)) 170 / scaleFactor; 171 if (diffMV.dx < 0) 172 { 173 mvHorData = -mvHorData; 174 } 175 } 176 177 /* Calculating the mv_data and mv_residual for Vertical MV */ 178 if (diffMV.dy == 0) 179 { 180 mvVerResidual = 0; 181 mvVerData = 0; 182 } 183 else 184 { 185 mvVerResidual = ( armAbs(diffMV.dy) - 1) % scaleFactor; 186 mvVerData = (armAbs(diffMV.dy) - mvVerResidual + (scaleFactor - 1)) 187 / scaleFactor; 188 if (diffMV.dy < 0) 189 { 190 mvVerData = -mvVerData; 191 } 192 } 193 194 /* Huffman encoding */ 195 196 /* The index is actually calculate as 197 index = ((float) (mvHorData/2) + 16) * 2, 198 meaning the MV data is halfed and then normalized 199 to begin with zero and then doubled to take care of indexing 200 the fractional part included */ 201 index = mvHorData + 32; 202 armPackVLC32 (ppBitStream, pBitOffset, armVCM4P2_aVlcMVD[index]); 203 if ((fcodeForward > 1) && (diffMV.dx != 0)) 204 { 205 armPackBits (ppBitStream, pBitOffset, mvHorResidual, (fcodeForward -1)); 206 } 207 208 /* The index is actually calculate as 209 index = ((float) (mvVerData/2) + 16) * 2, 210 meaning the MV data is halfed and then normalized 211 to begin with zero and then doubled to take care of indexing 212 the fractional part included */ 213 index = mvVerData + 32; 214 armPackVLC32 (ppBitStream, pBitOffset, armVCM4P2_aVlcMVD[index]); 215 if ((fcodeForward > 1) && (diffMV.dy != 0)) 216 { 217 armPackBits (ppBitStream, pBitOffset, mvVerResidual, (fcodeForward -1)); 218 } 219 } 220 221 return OMX_Sts_NoErr; 222} 223 224 225/* End of file */ 226 227 228