You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
891 lines
27 KiB
891 lines
27 KiB
/* *************************************************************************
|
|
** 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()
|
|
|