1/** 2 * 3 * File Name: omxVCM4P2_DecodePadMV_PVOP.c 4 * OpenMAX DL: v1.0.2 5 * Revision: 9641 6 * Date: Thursday, February 7, 2008 7 * 8 * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved. 9 * 10 * 11 * 12 * Description: 13 * Contains module for decoding MV and padding the same 14 * 15 */ 16 17#include "omxtypes.h" 18#include "armOMX.h" 19#include "omxVC.h" 20 21#include "armCOMM_Bitstream.h" 22#include "armCOMM.h" 23#include "armVCM4P2_Huff_Tables_VLC.h" 24 25 26 27/** 28 * Function: omxVCM4P2_DecodePadMV_PVOP (6.2.5.1.1) 29 * 30 * Description: 31 * Decodes and pads the four motion vectors associated with a non-intra P-VOP 32 * macroblock. For macroblocks of type OMX_VC_INTER4V, the output MV is 33 * padded as specified in [ISO14496-2], subclause 7.6.1.6. Otherwise, for 34 * macroblocks of types other than OMX_VC_INTER4V, the decoded MV is copied to 35 * all four output MV buffer entries. 36 * 37 * Input Arguments: 38 * 39 * ppBitStream - pointer to the pointer to the current byte in the bit 40 * stream buffer 41 * pBitOffset - pointer to the bit position in the byte pointed to by 42 * *ppBitStream. *pBitOffset is valid within [0-7]. 43 * pSrcMVLeftMB, pSrcMVUpperMB, and pSrcMVUpperRightMB - pointers to the 44 * motion vector buffers of the macroblocks specially at the left, 45 * upper, and upper-right side of the current macroblock, 46 * respectively; a value of NULL indicates unavailability. Note: 47 * Any neighborhood macroblock outside the current VOP or video 48 * packet or outside the current GOB (when short_video_header is 49 * 1 ) for which gob_header_empty is 0 is treated as 50 * transparent, according to [ISO14496-2], subclause 7.6.5. 51 * fcodeForward - a code equal to vop_fcode_forward in MPEG-4 bit stream 52 * syntax 53 * MBType - the type of the current macroblock. If MBType is not equal to 54 * OMX_VC_INTER4V, the destination motion vector buffer is still 55 * filled with the same decoded vector. 56 * 57 * Output Arguments: 58 * 59 * ppBitStream - *ppBitStream is updated after the block is decoded, so 60 * that it points to the current byte in the bit stream buffer 61 * pBitOffset - *pBitOffset is updated so that it points to the current bit 62 * position in the byte pointed by *ppBitStream 63 * pDstMVCurMB - pointer to the motion vector buffer for the current 64 * macroblock; contains four decoded motion vectors 65 * 66 * Return Value: 67 * 68 * OMX_Sts_NoErr - no error 69 * OMX_Sts_BadArgErr - bad arguments: 70 * - At least one of the following pointers is NULL: 71 * ppBitStream, *ppBitStream, pBitOffset, pDstMVCurMB 72 * - *pBitOffset exceeds [0,7] 73 * - fcodeForward exceeds (0,7] 74 * - MBType less than zero 75 * - motion vector buffer is not 4-byte aligned. 76 * OMX_Sts_Err - status error 77 * 78 */ 79 80OMXResult omxVCM4P2_DecodePadMV_PVOP( 81 const OMX_U8 ** ppBitStream, 82 OMX_INT * pBitOffset, 83 OMXVCMotionVector * pSrcMVLeftMB, 84 OMXVCMotionVector *pSrcMVUpperMB, 85 OMXVCMotionVector * pSrcMVUpperRightMB, 86 OMXVCMotionVector * pDstMVCurMB, 87 OMX_INT fcodeForward, 88 OMXVCM4P2MacroblockType MBType 89 ) 90{ 91 OMXVCMotionVector diffMV; 92 OMXVCMotionVector dstMVPredME[12]; 93 OMX_INT iBlk, i, count = 1; 94 OMX_S32 mvHorResidual = 1, mvVerResidual = 1, mvHorData, mvVerData; 95 OMX_S8 scaleFactor, index; 96 OMX_S16 high, low, range; 97 98 99 /* Argument error checks */ 100 armRetArgErrIf(ppBitStream == NULL, OMX_Sts_BadArgErr); 101 armRetArgErrIf(*ppBitStream == NULL, OMX_Sts_BadArgErr); 102 armRetArgErrIf(pBitOffset == NULL, OMX_Sts_BadArgErr); 103 armRetArgErrIf(pDstMVCurMB == NULL, OMX_Sts_BadArgErr); 104 armRetArgErrIf(((*pBitOffset < 0) || (*pBitOffset > 7)), OMX_Sts_BadArgErr); 105 armRetArgErrIf(((fcodeForward < 1) || (fcodeForward > 7)), \ 106 OMX_Sts_BadArgErr); 107 armRetArgErrIf(!armIs4ByteAligned(pDstMVCurMB), OMX_Sts_BadArgErr); 108 109 if ((MBType == OMX_VC_INTRA) || 110 (MBType == OMX_VC_INTRA_Q) 111 ) 112 { 113 /* All MV's are zero */ 114 for (i = 0; i < 4; i++) 115 { 116 pDstMVCurMB[i].dx = 0; 117 pDstMVCurMB[i].dy = 0; 118 } 119 120 return OMX_Sts_NoErr; 121 } 122 123 if ((MBType == OMX_VC_INTER4V) || (MBType == OMX_VC_INTER4V_Q)) 124 { 125 count = 4; 126 } 127 else if ((MBType == OMX_VC_INTER) || (MBType == OMX_VC_INTER_Q)) 128 { 129 count = 1; 130 } 131 132 /* Calculating the scale factor */ 133 scaleFactor = 1 << (fcodeForward -1); 134 high = ( 32 * scaleFactor) - 1; 135 low = ( (-32) * scaleFactor); 136 range = ( 64 * scaleFactor); 137 138 /* Huffman decoding and MV reconstruction */ 139 for (iBlk = 0; iBlk < count; iBlk++) 140 { 141 142 /* Huffman decoding to get Horizontal data and residual */ 143 index = armUnPackVLC32(ppBitStream, pBitOffset, 144 armVCM4P2_aVlcMVD); 145 armRetDataErrIf(index == -1, OMX_Sts_Err); 146 147 mvHorData = index - 32; 148 149 if ((fcodeForward > 1) && (mvHorData != 0)) 150 { 151 mvHorResidual = (OMX_S32) armGetBits(ppBitStream, 152 pBitOffset, (fcodeForward -1)); 153 } 154 155 /* Huffman decoding to get Vertical data and residual */ 156 index = armUnPackVLC32(ppBitStream, pBitOffset, armVCM4P2_aVlcMVD); 157 armRetDataErrIf(index == -1, OMX_Sts_Err); 158 159 mvVerData = index - 32; 160 161 if ((fcodeForward > 1) && (mvVerData != 0)) 162 { 163 mvVerResidual = (OMX_S32) armGetBits(ppBitStream, 164 pBitOffset, (fcodeForward -1)); 165 } 166 167 /* Calculating the differtial MV */ 168 if ( (scaleFactor == 1) || (mvHorData == 0) ) 169 { 170 diffMV.dx = mvHorData; 171 } 172 else 173 { 174 diffMV.dx = ((armAbs(mvHorData) - 1) * fcodeForward) 175 + mvHorResidual + 1; 176 if (mvHorData < 0) 177 { 178 diffMV.dx = -diffMV.dx; 179 } 180 } 181 182 if ( (scaleFactor == 1) || (mvVerData == 0) ) 183 { 184 diffMV.dy = mvVerData; 185 } 186 else 187 { 188 diffMV.dy = ((armAbs(mvVerData) - 1) * fcodeForward) 189 + mvVerResidual + 1; 190 if (mvVerData < 0) 191 { 192 diffMV.dy = -diffMV.dy; 193 } 194 } 195 196 /* Find the predicted vector */ 197 omxVCM4P2_FindMVpred ( 198 pDstMVCurMB, 199 pSrcMVLeftMB, 200 pSrcMVUpperMB, 201 pSrcMVUpperRightMB, 202 &pDstMVCurMB[iBlk], 203 dstMVPredME, 204 iBlk); 205 206 /* Adding the difference to the predicted MV to reconstruct MV */ 207 pDstMVCurMB[iBlk].dx += diffMV.dx; 208 pDstMVCurMB[iBlk].dy += diffMV.dy; 209 210 /* Checking the range and keeping it within the limits */ 211 if ( pDstMVCurMB[iBlk].dx < low ) 212 { 213 pDstMVCurMB[iBlk].dx += range; 214 } 215 if (pDstMVCurMB[iBlk].dx > high) 216 { 217 pDstMVCurMB[iBlk].dx -= range; 218 } 219 220 if ( pDstMVCurMB[iBlk].dy < low ) 221 { 222 pDstMVCurMB[iBlk].dy += range; 223 } 224 if (pDstMVCurMB[iBlk].dy > high) 225 { 226 pDstMVCurMB[iBlk].dy -= range; 227 } 228 } 229 230 if ((MBType == OMX_VC_INTER) || (MBType == OMX_VC_INTER_Q)) 231 { 232 pDstMVCurMB[1] = pDstMVCurMB[0]; 233 pDstMVCurMB[2] = pDstMVCurMB[0]; 234 pDstMVCurMB[3] = pDstMVCurMB[0]; 235 } 236 237 return OMX_Sts_NoErr; 238} 239 240 241/* End of file */ 242 243 244