/* ************************************************************************* ** INTEL Corporation Proprietary Information ** ** This listing is supplied under the terms of a license ** agreement with INTEL Corporation and may not be copied ** nor disclosed except in accordance with the terms of ** that agreement. ** ** Copyright (c) 1995, 1996 Intel Corporation. ** All Rights Reserved. ** ** ************************************************************************* */ /***************************************************************************** * * d1mblk.cpp * * DESCRIPTION: * Decoder macro block functions * * Routines: Prototypes in: * H263DecodeMBHeader d1dec.h * H263DecodeMBData d1dec.h */ // $Header: S:\h26x\src\dec\d1mblk.cpv 1.23 20 Dec 1996 16:58:06 RHAZRA $ // $Log: S:\h26x\src\dec\d1mblk.cpv $ // // Rev 1.23 20 Dec 1996 16:58:06 RHAZRA // Fixed bitstream docoding for the case where MB stuffing is inserted // between MBs. This was identified by a PTEL bitstream. This fix needs // to be verified with our other tests. // // Rev 1.22 16 Dec 1996 14:41:46 RHAZRA // // Changed a bitstream error ASSERT to a bonafide error // // Rev 1.21 18 Nov 1996 17:12:22 MBODART // Replaced all debug message invocations with Active Movie's DbgLog. // // Rev 1.20 07 Nov 1996 15:44:08 SCDAY // // Added MMX_ClipAndScale to replace Raj's glue code // // Rev 1.19 04 Nov 1996 10:28:10 RHAZRA // Changed the IDCT scaling table to be a DWORD table (with rounding // factored in) that is declared as a static. // // Rev 1.18 31 Oct 1996 08:58:28 SCDAY // Raj added support for MMX decoder // // Rev 1.17 26 Sep 1996 12:35:06 RHAZRA // Forced the decoder to use the IA version of VLD_RLD_IQ routine even // when MMX is on (since we don't have a corresponding MMX routine ... yet) // // Rev 1.16 05 Aug 1996 11:00:26 MBODART // // H.261 decoder rearchitecture: // Files changed: d1gob.cpp, d1mblk.{cpp,h}, d1dec.{cpp,h}, // filelist.261, h261_32.mak // New files: d1bvriq.cpp, d1idct.cpp // Obsolete files: d1block.cpp // Work still to be done: // Update h261_mf.mak // Optimize uv pairing in d1bvriq.cpp and d1idct.cpp // Fix checksum code (it doesn't work now) // Put back in decoder stats // // Rev 1.15 18 Mar 1996 17:02:12 AKASAI // // Added pragma code_seg("IACODE2") and changed the timing statistics. // At one point changed GET_VAR_BITS into subroutine to save code // space but it didn't so left it as a macro. // // Rev 1.14 26 Dec 1995 17:42:14 DBRUCKS // changed bTimerIsOn to bTimingThisFrame // // Rev 1.13 26 Dec 1995 12:50:00 DBRUCKS // // fix copyright // add timing code // comment out define of DEBUG_MBLK // // Rev 1.12 05 Dec 1995 10:19:46 SCDAY // // Added assembler version of Spatial Loop Filter // // Rev 1.11 03 Nov 1995 11:44:30 AKASAI // // Changed the processing of MB checksum and MBA stuffing. Changed // GET_VAR_BITS & GET_GT8_BITS for how to detect MBA stuffing code. // // Rev 1.10 01 Nov 1995 13:43:48 AKASAI // // Added support for loop filter. New routines call LpFilter, // BlockAddSpecial and BlockCopySpecial. // // Rev 1.9 27 Oct 1995 18:17:20 AKASAI // // Put in fix "hack" to keep the block action stream pointers // in sync between d1dec and d1mblk. With skip macro blocks some // macroblocks were being processed multiple times. Still a problem // when gob ends with a skip macroblock. // // Rev 1.8 26 Oct 1995 15:36:28 SCDAY // // Delta frames partially working -- changed main loops to accommodate // skipped macroblocks by detecting next startcode // // Rev 1.7 17 Oct 1995 11:28:56 SCDAY // Added error message if (MBA stuffing code found && Checksum not enabled) // // Rev 1.6 16 Oct 1995 16:28:02 AKASAI // Fixed bug when CHECKSUM_MACRO_BLOCK_DETAIL & CHECKSUM_MACRO_BLOCK are // both defined. // // Rev 1.5 16 Oct 1995 13:53:24 SCDAY // // Added macroblock level checksum // // Rev 1.4 06 Oct 1995 15:32:54 SCDAY // // Integrated with latest AKK d1block // // Rev 1.3 22 Sep 1995 14:48:46 SCDAY // // added more mblock header and data decoding // // Rev 1.2 20 Sep 1995 09:52:22 SCDAY // // eliminated a warning // // Rev 1.1 19 Sep 1995 15:24:10 SCDAY // // added H261 MBA parsing // // Rev 1.0 11 Sep 1995 13:51:52 SCDAY // Initial revision. // // Rev 1.11 25 Aug 1995 09:16:32 DBRUCKS // add ifdef DEBUG_MBLK // // Rev 1.10 23 Aug 1995 19:12:02 AKASAI // Fixed gNewTAB_CBPY table building. Was using 8 as mask instead of 0xf. // // Rev 1.9 18 Aug 1995 15:03:22 CZHU // // Output more error message when DecodeBlock returns error. // // Rev 1.8 16 Aug 1995 14:26:54 CZHU // // Changed DWORD adjustment back to byte oriented reading. // // Rev 1.7 15 Aug 1995 09:54:18 DBRUCKS // improve stuffing handling and add debug msg // // Rev 1.6 14 Aug 1995 18:00:40 DBRUCKS // add chroma parsing // // Rev 1.5 11 Aug 1995 17:47:58 DBRUCKS // cleanup // // Rev 1.4 11 Aug 1995 16:12:28 DBRUCKS // add ptr check to MB data // // Rev 1.3 11 Aug 1995 15:10:58 DBRUCKS // finish INTRA mb header parsing and callblock // // Rev 1.2 03 Aug 1995 14:30:26 CZHU // Take block level operations out to d3block.cpp // // Rev 1.1 02 Aug 1995 10:21:12 CZHU // Added asm codes for VLD of TCOEFF, inverse quantization, run-length decode. // // Rev 1.0 31 Jul 1995 13:00:08 DBRUCKS // Initial revision. // // Rev 1.2 31 Jul 1995 11:45:42 CZHU // changed the parameter list // // Rev 1.1 28 Jul 1995 16:25:52 CZHU // // Added per block decoding framework. // // Rev 1.0 28 Jul 1995 15:20:16 CZHU // Initial revision. //Block level decoding for H.26x decoder #include "precomp.h" // rearch idct /***************************************************************************** * * GET_VAR_BITS * * Read a variable number of bits using a lookup table. * * The input count should be the number of bits used to index the table. * The output count is the number of bits in that symbol. * * The table should be initialized such that all don't care symbols match to * the same value. Thus if the table is indexed by 6-bits a two bit symbol * 01XX XX will be used to initialize all entries 0100 00 -> 0111 11. These * entries will include an 8-bit length in the least significant byte. * * uCount - IN * fpu8 - IN and OUT * uWork - IN and OUT * uBitsReady - IN and OUT * uResult - OUT * uCode - OUT * fpTable - IN */ #define GET_VAR_BITS(uCount, fpu8, uWork, uBitsReady, uResult, uCode, uBitCount, fpTable) { \ while (uBitsReady < uCount) { \ uWork <<= 8; \ uBitsReady += 8; \ uWork |= *fpu8++; \ } \ /* calculate how much to shift off */ \ /* and get the code */ \ uCode = uBitsReady - uCount; \ uCode = (uWork >> uCode); \ /* read the data */ \ uResult = fpTable[uCode]; \ /* count of bits used */ \ /* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */ \ /* H.261 tables are reverse order from H.263 */ \ /* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */ \ uBitCount = uResult & 0xff00; \ uBitCount >>= 8; \ /* bits remaining */ \ uBitsReady = uBitsReady - uBitCount; \ /* special case for stuffing processing */ \ /* if (uBitsReady < 0) */ \ /* kluged to test for negative */ \ if (uBitsReady > 33) \ /* if (bStuffing) */ \ { \ uWork <<= 8; \ uBitsReady += 8; \ uWork |= *fpu8++; \ } \ /* end special case for stuffing */ \ uWork &= GetBitsMask[uBitsReady]; \ } #define GET_GT8_BITS(uCount, fpu8, uWork, uBitsReady, uResult, uCode, uBitCount, fpTable) { \ while (uBitsReady < uCount) { \ uWork <<= 8; \ uBitsReady += 8; \ uWork |= *fpu8++; \ } \ /* calculate how much to shift off */ \ /* and get the code */ \ uCode = uBitsReady - uCount; \ uCode = (uWork >> uCode); \ /* read the data */ \ uResult = fpTable[uCode]; \ /* count of bits used */ \ /* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */ \ /* H.261 tables are reverse order from H.263 */ \ /* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */ \ uBitCount = uResult & 0xff00; \ if ((uBitCount & 0x8000) == 0) /* if not negative */ \ { \ uBitCount >>= 8; \ /* bits remaining */ \ uBitsReady = uBitsReady - uBitCount; \ /* special case for stuffing processing */ \ /* if (uBitsReady < 0) */ \ /* kluged to test for negative */ \ if (uBitsReady > 33) \ /* if (bStuffing) */ \ { \ uWork <<= 8; \ uBitsReady += 8; \ uWork |= *fpu8++; \ } \ /* end special case for stuffing */ \ uWork &= GetBitsMask[uBitsReady]; \ } \ else \ uWork &= GetBitsMask[uBitsReady-8]; \ } extern void BlockCopy( U32 uDstBlock, U32 uSrcBlock); extern void BlockCopySpecial( U32 uDstBlock, U32 uSrcBlock); extern void BlockAdd ( U32 uResidual, U32 uRefBlock, U32 uDstBlock); extern void BlockAddSpecial ( U32 uResidual, U32 uRefBlock, U32 uDstBlock); T_pFunc_VLD_RLD_IQ_Block pFunc_VLD_RLD_IQ_Block[2] = {VLD_RLD_IQ_Block,VLD_RLD_IQ_Block}; // New rearch //T_pFunc_VLD_RLD_IQ_Block pFunc_VLD_RLD_IQ_Block[2] = {VLD_RLD_IQ_Block, MMX_VLD_RLD_IQ_Block}; // New rearch /***************************************************************************** * * H263DecodeMBHeader * * Decode the MB header */ #pragma code_seg("IACODE1") I32 H263DecodeMBHeader( T_H263DecoderCatalog FAR * DC, BITSTREAM_STATE FAR * fpbsState, U32 * uReadChecksum) { I32 iReturn = ICERR_ERROR; U8 FAR * fpu8; U32 uBitsReady; U32 uWork; U32 uResult; U32 uCode; U32 uBitCount; int bStuffing; #define START_CODE 0xff18 #define STUFFING_CODE 0x0b22 //#define DEBUG_MBLK -- Turn this on with a define in the makefile. #ifndef RING0 #ifdef DEBUG_MBLK char buf120[120]; int iLength; #endif #endif GET_BITS_RESTORE_STATE(fpu8, uWork, uBitsReady, fpbsState) /* MBA --------------- */ /* ********************************************* */ /* minor table decode (>8 bits) not fully tested */ /* to do note: */ /* this is hacked */ /* change >8 bit processing to use major/minor */ /* tables and ONE GET_BITS routine */ /* ********************************************* */ ReadMBA: bStuffing = 0; GET_GT8_BITS(8, fpu8, uWork, uBitsReady, uResult, uCode, uBitCount, gTAB_MBA_MAJOR); if (uResult == STUFFING_CODE) { /* is stuffing code */ bStuffing = 1; /* do MB checksum stuff here */ #ifdef CHECKSUM_MACRO_BLOCK GET_BITS_SAVE_STATE(fpu8, uWork, uBitsReady, fpbsState) /* might want to move this to a separate function for readability */ GET_ONE_BIT(fpu8, uWork, uBitsReady, uResult); if (uResult == 1) { GET_FIXED_BITS(8, fpu8, uWork, uBitsReady, uResult); if (uResult == 1) { /* indicates TCOEFF checksum processing */ /* read off all but the real checksum data */ GET_FIXED_BITS(9, fpu8, uWork, uBitsReady, uResult); GET_FIXED_BITS(9, fpu8, uWork, uBitsReady, uResult); GET_FIXED_BITS(9, fpu8, uWork, uBitsReady, uResult); GET_FIXED_BITS(9, fpu8, uWork, uBitsReady, uResult); GET_FIXED_BITS(9, fpu8, uWork, uBitsReady, uResult); GET_FIXED_BITS(9, fpu8, uWork, uBitsReady, uResult); /* now get real checksum data */ /* run */ GET_FIXED_BITS(9, fpu8, uWork, uBitsReady, uResult); *uReadChecksum = ((uResult & 0xff) << 24); /* level */ GET_FIXED_BITS(9, fpu8, uWork, uBitsReady, uResult); *uReadChecksum = (*uReadChecksum | ((uResult & 0xff) << 16)); GET_FIXED_BITS(9, fpu8, uWork, uBitsReady, uResult); *uReadChecksum = (*uReadChecksum | ((uResult & 0xff) << 8)); /* sign */ GET_FIXED_BITS(9, fpu8, uWork, uBitsReady, uResult); *uReadChecksum = (*uReadChecksum | (uResult & 0xff)); GET_ONE_BIT(fpu8, uWork, uBitsReady, uResult); } else { DBOUT("ERROR :: H261MBChecksum :: Invalid Checksum Data :: ERROR"); iReturn = ICERR_ERROR; goto done; } } else { GET_BITS_RESTORE_STATE(fpu8, uWork, uBitsReady, fpbsState) goto ReadMBA; } #else /* is MBA stuffing, but checksum not enabled */ GET_BITS_SAVE_STATE(fpu8, uWork, uBitsReady, fpbsState) // GET_ONE_BIT(fpu8, uWork, uBitsReady, uResult); /*if (uResult == 1) { DbgLog((LOG_ERROR, HDBG_ALWAYS, TEXT("ERROR :: Stuffing code found, Checksum not enabled :: ERROR"))); iReturn = ICERR_ERROR; goto done; } */ // if (uResult == 1) // { // GET_BITS_RESTORE_STATE(fpu8, uWork, uBitsReady, fpbsState) // } // else { //GET_BITS_RESTORE_STATE(fpu8, uWork, uBitsReady, fpbsState) // } #endif } /* end if (uResult == STUFFING_CODE) */ /* try this for now */ else { if (uResult == START_CODE) { I8 temp; temp = (I8)(uResult & 0xff); GET_VAR_BITS(16, fpu8, uWork, uBitsReady, uResult, uCode, uBitCount, (gTAB_MBA_MINOR + temp)); if (uResult != 0x1023) { DBOUT("ERROR :: Invalid startcode :: ERROR"); iReturn = ICERR_ERROR; } else iReturn = START_CODE; GET_BITS_SAVE_STATE(fpu8, uWork, uBitsReady, fpbsState) goto done; } /* end if (uResult == START_CODE) */ else /* is not stuffing */ { /* if uResult negative, get more bits */ if (uResult & 0x8000) { I8 temp; temp = (I8)(uResult & 0xff); GET_VAR_BITS(11, fpu8, uWork, uBitsReady, uResult, uCode, uBitCount, (gTAB_MBA_MINOR + temp)); } DC->uMBA = (uResult & 0xff); }/* end else is not stuffing */ } /* When MBA==Stuffing, we jump back to the start to look for MBA */ if (bStuffing) goto ReadMBA; /* MTYPE ---------------------------------------- */ GET_GT8_BITS(8, fpu8, uWork, uBitsReady, uResult, uCode, uBitCount, gTAB_MTYPE_MAJOR); if (uResult & 0x8000) { I8 temp; temp = (I8)(uResult & 0xff); GET_VAR_BITS(10, fpu8, uWork, uBitsReady, uResult, uCode, uBitCount, (gTAB_MTYPE_MINOR + temp)); } DC->uMBType = (uResult & 0xff); /* MQUANT ---------------------------------------- */ if (DC->uMBType == 1 || DC->uMBType == 3 || DC->uMBType == 6 || DC->uMBType == 9) { /* get 5-bit MQuant */ GET_FIXED_BITS(5, fpu8, uWork, uBitsReady, uResult); DC->uMQuant = (uResult & 0xff); } /* MVD ------------------------------------------- */ /* reset previous motion vectors */ /* if MB 0,11,22 */ /* if MBA != 1 or */ /* if previous MB was not MC */ if (DC->uMBType >3) { if ((DC->uMBA != 1) || (DC->i16LastMBA == 10) || (DC->i16LastMBA == 21)) DC->i8MVDH = DC->i8MVDV = 0; /* get X motion vector */ GET_GT8_BITS(8, fpu8, uWork, uBitsReady, uResult, uCode, uBitCount, gTAB_MVD_MAJOR); if (uResult & 0x8000) { I8 temp; temp = (I8)(uResult & 0xff); GET_VAR_BITS(11, fpu8, uWork, uBitsReady, uResult, uCode, uBitCount, (gTAB_MVD_MINOR + temp)); } /* convert and make incremental */ DC->i8MVDH = gTAB_MV_ADJUST[DC->i8MVDH + (I8)(uResult & 0xff) + 32]; /* get Y motion vector */ GET_GT8_BITS(8, fpu8, uWork, uBitsReady, uResult, uCode, uBitCount, gTAB_MVD_MAJOR); if (uResult & 0x8000) { I8 temp; temp = (I8)(uResult & 0xff); GET_VAR_BITS(11, fpu8, uWork, uBitsReady, uResult, uCode, uBitCount, (gTAB_MVD_MINOR + temp)); } /* convert and make incremental */ DC->i8MVDV = gTAB_MV_ADJUST[DC->i8MVDV + (I8)(uResult & 0xff) + 32]; } /* end if (DC->MBType > 3) */ else DC->i8MVDH = DC->i8MVDV = 0; /* CBP --------------------------------------------- */ /* brute force method */ DC->uCBP = 0; /* for MType = 4 or 7 */ if (DC->uMBType == 2 || DC->uMBType == 3 || DC->uMBType == 5 || DC->uMBType == 6 || DC->uMBType == 8 || DC->uMBType == 9) { /* get CBP */ GET_VAR_BITS(9, fpu8, uWork, uBitsReady, uResult, uCode, uBitCount, gTAB_CBP); DC->uCBP = (uResult & 0xff); } /* end get CBP */ else if (DC->uMBType < 2) /* is intra */ DC->uCBP = 63; /* force CBP to 63 */ GET_BITS_SAVE_STATE(fpu8, uWork, uBitsReady, fpbsState) iReturn = ICERR_OK; #ifndef RING0 #ifdef DEBUG_MBLK iLength = wsprintf(buf120, "MBType=%ld MQuant=%ld MVDH=%ld MVDV=%ld CBP=%ld", DC->uMBType, DC->uMQuant, DC->i8MVDH, DC->i8MVDV, DC->uCBP); DBOUT(buf120); ASSERT(iLength < 120); #endif #endif done: return iReturn; } /* end H263DecodeMBHeader() */ #pragma code_seg() /***************************************************************************** * * H263DecodeMBData * * Decode each of the blocks in this macro block */ #pragma code_seg("IACODE1") I32 H263DecodeMBData( T_H263DecoderCatalog FAR * DC, T_BlkAction FAR * fpBlockAction, I32 iBlockNumber, BITSTREAM_STATE FAR * fpbsState, U8 FAR * fpu8MaxPtr, U32 * uReadChecksum, U32 **pN, // New rearch T_IQ_INDEX ** pRUN_INVERSE_Q) // New rearch { I32 iResult = ICERR_ERROR; int iCBP = (int) DC->uCBP; int i; U32 uBitsReady; U32 uBitsReadIn; U32 uBitsReadOut; U8 u8Quant; /* quantization level for this block */ U8 FAR * fpu8; U32 uByteCnt; I8 mvx, mvy, mvx2, mvy2; T_pFunc_VLD_RLD_IQ_Block pFunc_VLD =pFunc_VLD_RLD_IQ_Block[0]; U32 uCheckSum; /* checksum data returned from DecodeBlock */ #ifdef CHECKSUM_MACRO_BLOCK_DETAIL char buf80[80]; int iMBDLength; #endif #ifdef CHECKSUM_MACRO_BLOCK char buff80[80]; int iLength; #endif #ifdef DECODE_STATS U32 uStartLow = DC->uStartLow; U32 uStartHigh = DC->uStartHigh; U32 uElapsed; U32 uBefore; U32 uDecodeBlockSum = 0; U32 uLoopFilterSum = 0; U32 uBlockCopySum = 0; U32 uBlockCopySpSum = 0; U32 uBlockAddSum = 0; U32 uBlockAddSpSum = 0; int bTimingThisFrame = DC->bTimingThisFrame; DEC_TIMING_INFO * pDecTimingInfo = NULL; #endif /* On input the pointer points to the next byte. */ /* We need to change it to */ /* point to the current word on a 32-bit boundary. */ fpu8 = fpbsState->fpu8 - 1; /* point to the current byte */ uBitsReady = fpbsState->uBitsReady; while (uBitsReady >= 8) { fpu8--; uBitsReady -= 8; } uBitsReadIn = 8 - uBitsReady; u8Quant = (U8) (DC->uMQuant); if (DC->uMBType > 1) { /* calculate motion vectors */ mvx = DC->i8MVDH; mvy = DC->i8MVDV; // calculate UV blocks MV mvx2 = mvx / 2; mvy2 = mvy / 2; fpBlockAction->i8MVX = mvx; fpBlockAction->i8MVY = mvy; // duplicate other 3 Y blocks fpBlockAction[1].i8MVX = mvx; fpBlockAction[1].i8MVY = mvy; fpBlockAction[2].i8MVX = mvx; fpBlockAction[2].i8MVY = mvy; fpBlockAction[3].i8MVX = mvx; fpBlockAction[3].i8MVY = mvy; // init UV blocks fpBlockAction[4].i8MVX = mvx2; fpBlockAction[4].i8MVY = mvy2; fpBlockAction[5].i8MVX = mvx2; fpBlockAction[5].i8MVY = mvy2; } uCheckSum = 0; /* Init MB Checksum */ for (i = 0; i < 6; i++) { if (DC->uMBType <= 1) /* is intra */ fpBlockAction->u8BlkType = BT_INTRA; else if (iCBP & 0x20) /* if coded */ fpBlockAction->u8BlkType = BT_INTER; else fpBlockAction->u8BlkType = BT_EMPTY; if (fpBlockAction->u8BlkType != BT_EMPTY) { fpBlockAction->u8Quant = u8Quant; ASSERT(fpBlockAction->pCurBlock != NULL); ASSERT(fpBlockAction->uBlkNumber == (U32)iBlockNumber); /*----- DecodeBlock ----*/ #ifdef DECODE_STATS TIMER_BEFORE(bTimingThisFrame,uStartLow,uStartHigh,uBefore); #endif #ifdef CHECKSUM_MACRO_BLOCK // uBitsReadOut = DecodeBlock(fpBlockAction, fpu8, uBitsReadIn, (U32)DC+DC->uMBBuffer+i*256, fpBlockAction->pCurBlock, &uCheckSum); #else // rearch uBitsReadOut = (*pFunc_VLD) ( fpBlockAction, fpu8, uBitsReadIn, (U32 *) *pN, (U32 *) *pRUN_INVERSE_Q); // rearch #endif #ifdef DECODE_STATS TIMER_AFTER_P5(bTimingThisFrame,uStartLow,uStartHigh,uBefore,uElapsed,uDecodeBlockSum) #endif if (uBitsReadOut == 0) { DBOUT("ERROR :: H263DecodeMBData :: Error decoding a Y block :: ERROR"); DBOUT("ERROR :: DecodeBlock return 0 bits read...."); goto done; } uByteCnt = uBitsReadOut >> 3; /* divide by 8 */ uBitsReadIn = uBitsReadOut & 0x7; /* mod 8 */ fpu8 += uByteCnt; /* New for rearch */ ASSERT ( **pN < 65 ); //////////////////////////////////////////////// // End hack // //////////////////////////////////////////////// *pRUN_INVERSE_Q += **pN; if ((0xf & fpBlockAction->u8BlkType) != BT_INTER) **pN += 65; (*pN)++; /* end of new rearch */ /* allow the pointer to address up to four beyond */ /* the end reading by DWORD using postincrement. */ /* changed for detection of stuffing code at */ /* end of frame */ // ASSERT(fpu8 <= (fpu8MaxPtr+14)); if (fpu8 > (fpu8MaxPtr+14)) { iResult = ICERR_ERROR; // probably not needed goto done; } } /* end if not empty */ else /* is empty */ { /* zero out intermediate data structure and advance pointers */ /* New for rearch */ **pN = 0; (*pN)++; /* end of new rearch */ } fpBlockAction++; iCBP <<= 1; iBlockNumber++; } /* end for each block in macroblock */ #ifdef CHECKSUM_MACRO_BLOCK /* Compare checksum */ if ((uCheckSum != *uReadChecksum) && (*uReadChecksum != 0)) { iLength = wsprintf(buff80,"WARNING:MB CheckSum miss match, Enc Checksum=0x%x Dec Checksum=0x%x", *uReadChecksum, uCheckSum); DBOUT(buff80); ASSERT(iLength < 80); } #ifdef CHECKSUM_MACRO_BLOCK_DETAIL iMBDLength = wsprintf(buf80,"Block=%d CheckSum=0x%x", i, uCheckSum); DBOUT(buf80); ASSERT(iMBDLength < 80); #endif #endif /* restore the scanning pointers to point to the next byte */ /* and set the uWork and uBitsReady values. */ while (uBitsReadIn > 8) { fpu8++; uBitsReadIn -= 8; } fpbsState->uBitsReady = 8 - uBitsReadIn; fpbsState->uWork = *fpu8++; /* store the data and point to next byte */ fpbsState->uWork &= GetBitsMask[fpbsState->uBitsReady]; fpbsState->fpu8 = fpu8; #ifdef DECODE_STATS if (bTimingThisFrame) { pDecTimingInfo = DC->pDecTimingInfo + DC->uStatFrameCount; pDecTimingInfo->uDecodeBlock += uDecodeBlockSum; pDecTimingInfo->uLoopFilter += uLoopFilterSum; pDecTimingInfo->uBlockCopy += uBlockCopySum; pDecTimingInfo->uBlockCopySp += uBlockCopySpSum; pDecTimingInfo->uBlockAdd += uBlockAddSum; pDecTimingInfo->uBlockAddSp += uBlockAddSpSum; } #endif iResult = ICERR_OK; done: return iResult; } /* H263DecodeMBData() */ #pragma code_seg() /***************************************************************************** * * H263IDCTandMC * * Inverse Discrete Cosine Transform and * Motion Compensation for each block * */ #pragma code_seg("IACODE2") void H263IDCTandMC( T_H263DecoderCatalog FAR *DC, T_BlkAction FAR *fpBlockAction, int iBlock, int iMBNum, // AP-NEW int iGOBNum, // AP-NEW U32 *pN, T_IQ_INDEX *pRUN_INVERSE_Q, T_MBInfo *fpMBInfo, // AP-NEW int iEdgeFlag ) { I32 pRef; I32 mvx, mvy; ASSERT(*pN != 65); if (*pN < 65) // Inter block { // first do motion compensation // result will be pointed to by pRef mvx = fpBlockAction[iBlock].i8MVX; mvy = fpBlockAction[iBlock].i8MVY; pRef = fpBlockAction[iBlock].pRefBlock + (I32) mvx + PITCH * (I32) mvy; // now do the inverse transform (where appropriate) & combine if (*pN > 0) // and, of course, < 65. { // Get residual block; output at DC+DC->uMBBuffer+BLOCK_BUFFER_OFFSET // Finally add the residual to the reference block // TODO DecodeBlock_IDCT( (U32)pRUN_INVERSE_Q, *pN, fpBlockAction[iBlock].pCurBlock, // not used here (U32) DC + DC->uMBBuffer + BLOCK_BUFFER_OFFSET);// inter output if (fpMBInfo->i8MBType >=7) { // do spatial loop filter LoopFilter((U8 *)pRef, (U8*)DC+DC->uFilterBBuffer, PITCH); BlockAddSpecial((U32)DC+DC->uMBBuffer + BLOCK_BUFFER_OFFSET, (U32)DC+DC->uFilterBBuffer, fpBlockAction[iBlock].pCurBlock); } else { BlockAdd( (U32) DC + DC->uMBBuffer + BLOCK_BUFFER_OFFSET, // output pRef, // prediction fpBlockAction[iBlock].pCurBlock); // destination } } else // *pN == 0, so no transform coefficients for this block { // Just copy motion compensated reference block if (fpMBInfo->i8MBType >=7) { // do spatial loop filter LoopFilter((U8 *)pRef, (U8*)DC+DC->uFilterBBuffer, PITCH); //MMX_LoopFilter((U8 *)pRef, (U8*)DC+DC->uFilterBBuffer, 8); BlockCopySpecial(fpBlockAction[iBlock].pCurBlock, (U32)DC+DC->uFilterBBuffer); } else BlockCopy( fpBlockAction[iBlock].pCurBlock, // destination pRef); // prediction } } else // *pN >= 65, hence intRA { // TODO DecodeBlock_IDCT( (U32)pRUN_INVERSE_Q, *pN, fpBlockAction[iBlock].pCurBlock, // intRA transform output (U32) DC + DC->uMBBuffer + BLOCK_BUFFER_OFFSET); } // end if (*pN < 65) ... else ... } // End IDCTandMC //////////////////////////////////////////////////////////////////////////////// #pragma code_seg()