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