1/* ---------------------------------------------------------------- 2 * 3 * 4 * File Name: armVCM4P10_DecodeCoeffsToPair.c 5 * OpenMAX DL: v1.0.2 6 * Revision: 9641 7 * Date: Thursday, February 7, 2008 8 * 9 * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved. 10 * 11 * 12 * 13 * H.264 decode coefficients module 14 * 15 */ 16 17#ifdef DEBUG_ARMVCM4P10_DECODECOEFFSTOPAIR 18#undef DEBUG_ON 19#define DEBUG_ON 20#endif 21 22#include "omxtypes.h" 23#include "armOMX.h" 24#include "omxVC.h" 25 26#include "armCOMM.h" 27#include "armCOMM_Bitstream.h" 28#include "armVCM4P10_CAVLCTables.h" 29 30/* 4x4 DeZigZag table */ 31 32static const OMX_U8 armVCM4P10_ZigZag[16] = 33{ 34 0, 1, 4, 8, 5, 2, 3, 6, 9, 12, 13, 10, 7, 11, 14, 15 35}; 36 37/* 38 * Description: 39 * This function perform the work required by the OpenMAX 40 * DecodeCoeffsToPair function and DecodeChromaDCCoeffsToPair. 41 * Since most of the code is common we share it here. 42 * 43 * Parameters: 44 * [in] ppBitStream Double pointer to current byte in bit stream buffer 45 * [in] pOffset Pointer to current bit position in the byte pointed 46 * to by *ppBitStream 47 * [in] sMaxNumCoeff Maximum number of non-zero coefficients in current 48 * block (4,15 or 16) 49 * [in] nTable Table number (0 to 4) according to the five columns 50 * of Table 9-5 in the H.264 spec 51 * [out] ppBitStream *ppBitStream is updated after each block is decoded 52 * [out] pOffset *pOffset is updated after each block is decoded 53 * [out] pNumCoeff Pointer to the number of nonzero coefficients in 54 * this block 55 * [out] ppPosCoefbuf Double pointer to destination residual 56 * coefficient-position pair buffer 57 * Return Value: 58 * Standard omxError result. See enumeration for possible result codes. 59 60 */ 61 62OMXResult armVCM4P10_DecodeCoeffsToPair( 63 const OMX_U8** ppBitStream, 64 OMX_S32* pOffset, 65 OMX_U8* pNumCoeff, 66 OMX_U8 **ppPosCoefbuf, 67 OMX_INT nTable, 68 OMX_INT sMaxNumCoeff 69 ) 70{ 71 int CoeffToken, TotalCoeff, TrailingOnes; 72 int Level, LevelCode, LevelPrefix, LevelSuffix, LevelSuffixSize; 73 int SuffixLength, Run, ZerosLeft,CoeffNum; 74 int i, Flags; 75 OMX_U8 *pPosCoefbuf = *ppPosCoefbuf; 76 OMX_S16 pLevel[16]; 77 OMX_U8 pRun[16]; 78 79 CoeffToken = armUnPackVLC32(ppBitStream, pOffset, armVCM4P10_CAVLCCoeffTokenTables[nTable]); 80 armRetDataErrIf(CoeffToken == ARM_NO_CODEBOOK_INDEX, OMX_Sts_Err); 81 82 TrailingOnes = armVCM4P10_CAVLCTrailingOnes[CoeffToken]; 83 TotalCoeff = armVCM4P10_CAVLCTotalCoeff[CoeffToken]; 84 *pNumCoeff = (OMX_U8)TotalCoeff; 85 86 DEBUG_PRINTF_2("TotalCoeff = %d, TrailingOnes = %d\n", TotalCoeff, TrailingOnes); 87 88 if (TotalCoeff == 0) 89 { 90 /* Nothing to do */ 91 return OMX_Sts_NoErr; 92 } 93 94 /* Decode trailing ones */ 95 for (i=TotalCoeff-1; i>=TotalCoeff-TrailingOnes; i--) 96 { 97 if (armGetBits(ppBitStream, pOffset, 1)) 98 { 99 Level = -1; 100 } 101 else 102 { 103 Level = +1; 104 } 105 pLevel[i] = (OMX_S16)Level; 106 107 DEBUG_PRINTF_2("Level[%d] = %d\n", i, pLevel[i]); 108 } 109 110 /* Decode (non zero) level values */ 111 SuffixLength = 0; 112 if (TotalCoeff>10 && TrailingOnes<3) 113 { 114 SuffixLength=1; 115 } 116 for ( ; i>=0; i--) 117 { 118 LevelPrefix = armUnPackVLC32(ppBitStream, pOffset, armVCM4P10_CAVLCLevelPrefix); 119 armRetDataErrIf(LevelPrefix == ARM_NO_CODEBOOK_INDEX, OMX_Sts_Err); 120 121 LevelSuffixSize = SuffixLength; 122 if (LevelPrefix==14 && SuffixLength==0) 123 { 124 LevelSuffixSize = 4; 125 } 126 if (LevelPrefix==15) 127 { 128 LevelSuffixSize = 12; 129 } 130 131 LevelSuffix = 0; 132 if (LevelSuffixSize > 0) 133 { 134 LevelSuffix = armGetBits(ppBitStream, pOffset, LevelSuffixSize); 135 } 136 137 LevelCode = (LevelPrefix << SuffixLength) + LevelSuffix; 138 139 140 if (LevelPrefix==15 && SuffixLength==0) 141 { 142 LevelCode += 15; 143 } 144 145 /* LevelCode = 2*(magnitude-1) + sign */ 146 147 if (i==TotalCoeff-1-TrailingOnes && TrailingOnes<3) 148 { 149 /* Level magnitude can't be 1 */ 150 LevelCode += 2; 151 } 152 if (LevelCode & 1) 153 { 154 /* 2a+1 maps to -a-1 */ 155 Level = (-LevelCode-1)>>1; 156 } 157 else 158 { 159 /* 2a+0 maps to +a+1 */ 160 Level = (LevelCode+2)>>1; 161 } 162 pLevel[i] = (OMX_S16)Level; 163 164 DEBUG_PRINTF_2("Level[%d] = %d\n", i, pLevel[i]); 165 166 if (SuffixLength==0) 167 { 168 SuffixLength=1; 169 } 170 if ( ((LevelCode>>1)+1)>(3<<(SuffixLength-1)) && SuffixLength<6 ) 171 { 172 SuffixLength++; 173 } 174 } 175 176 /* Decode run values */ 177 ZerosLeft = 0; 178 if (TotalCoeff < sMaxNumCoeff) 179 { 180 /* Decode TotalZeros VLC */ 181 if (sMaxNumCoeff==4) 182 { 183 ZerosLeft = armUnPackVLC32(ppBitStream, pOffset, armVCM4P10_CAVLCTotalZeros2x2Tables[TotalCoeff-1]); 184 armRetDataErrIf(ZerosLeft ==ARM_NO_CODEBOOK_INDEX , OMX_Sts_Err); 185 } 186 else 187 { 188 ZerosLeft = armUnPackVLC32(ppBitStream, pOffset, armVCM4P10_CAVLCTotalZeroTables[TotalCoeff-1]); 189 armRetDataErrIf(ZerosLeft ==ARM_NO_CODEBOOK_INDEX , OMX_Sts_Err); 190 } 191 } 192 193 DEBUG_PRINTF_1("TotalZeros = %d\n", ZerosLeft); 194 195 CoeffNum=ZerosLeft+TotalCoeff-1; 196 197 for (i=TotalCoeff-1; i>0; i--) 198 { 199 Run = 0; 200 if (ZerosLeft > 0) 201 { 202 int Table = ZerosLeft; 203 if (Table > 6) 204 { 205 Table = 7; 206 } 207 Run = armUnPackVLC32(ppBitStream, pOffset, armVCM4P10_CAVLCRunBeforeTables[Table-1]); 208 armRetDataErrIf(Run == ARM_NO_CODEBOOK_INDEX, OMX_Sts_Err); 209 } 210 pRun[i] = (OMX_U8)Run; 211 212 DEBUG_PRINTF_2("Run[%d] = %d\n", i, pRun[i]); 213 214 ZerosLeft -= Run; 215 } 216 pRun[0] = (OMX_U8)ZerosLeft; 217 218 DEBUG_PRINTF_1("Run[0] = %d\n", pRun[i]); 219 220 221 /* Fill in coefficients */ 222 223 if (sMaxNumCoeff==15) 224 { 225 CoeffNum++; /* Skip the DC position */ 226 } 227 228 /*for (i=0;i<TotalCoeff;i++) 229 CoeffNum += pRun[i]+1;*/ 230 231 for (i=(TotalCoeff-1); i>=0; i--) 232 { 233 /*CoeffNum += pRun[i]+1;*/ 234 Level = pLevel[i]; 235 236 DEBUG_PRINTF_2("Coef[%d] = %d\n", CoeffNum, Level); 237 238 Flags = CoeffNum; 239 CoeffNum -= (pRun[i]+1); 240 if (sMaxNumCoeff>4) 241 { 242 /* Perform 4x4 DeZigZag */ 243 Flags = armVCM4P10_ZigZag[Flags]; 244 } 245 if (i==0) 246 { 247 /* End of block flag */ 248 Flags += 0x20; 249 } 250 if (Level<-128 || Level>127) 251 { 252 /* Overflow flag */ 253 Flags += 0x10; 254 } 255 256 *pPosCoefbuf++ = (OMX_U8)(Flags); 257 *pPosCoefbuf++ = (OMX_U8)(Level & 0xFF); 258 if (Flags & 0x10) 259 { 260 *pPosCoefbuf++ = (OMX_U8)(Level>>8); 261 } 262 } 263 264 *ppPosCoefbuf = pPosCoefbuf; 265 266 return OMX_Sts_NoErr; 267} 268