|
|
/* *************************************************************************
** 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 Intel Corporation. ** All Rights Reserved. ** ** ************************************************************************* */ // $Author: JMCVEIGH $
// $Date: 21 Jan 1997 08:53:16 $
// $Archive: S:\h26x\src\dec\d3mblk.cpv $
// $Header: S:\h26x\src\dec\d3mblk.cpv 1.60 21 Jan 1997 08:53:16 JMCVEIGH $
// $Log: S:\h26x\src\dec\d3mblk.cpv $
//
// Rev 1.60 21 Jan 1997 08:53:16 JMCVEIGH
// Before we calculated the interpolated index for MC prior to
// clipping for UMV. We might then reference outside of the 16 pel
// wide padded border. Moved calculation of interp_index to after
// UMV clipping.
//
// Rev 1.59 16 Dec 1996 17:45:26 JMCVEIGH
// Proper motion vector decoding and prediction for forward prediction
// in B portion of improved PB-frame.
//
// Rev 1.58 09 Dec 1996 15:54:10 GMLIM
//
// Added a debug message in H263BBlockPrediction() for the case where
// TR == TR_Prev. Set iTRD = 256 to avoid divide by 0.
//
// Rev 1.57 27 Sep 1996 17:29:24 KLILLEVO
//
// added clipping of extended motion vectors for MMX
//
// Rev 1.56 26 Sep 1996 13:56:52 KLILLEVO
//
// fixed a totally bogus version of the extended motion vectors
//
// Rev 1.55 26 Sep 1996 11:32:16 KLILLEVO
// extended motion vectors now work for AP on the P54C chip
//
// Rev 1.54 25 Sep 1996 08:05:32 KLILLEVO
// initial extended motion vectors support
// does not work for AP yet
//
// Rev 1.53 09 Jul 1996 16:46:00 AGUPTA2
// MMX code now clears DC value for INTRA blocks and adds it back during
// ClipANdMove; this is to solve overflow problem.
//
// Rev 1.52 29 May 1996 10:18:36 AGUPTA2
// MMX need not be defd to use MMX decoder.
//
// Rev 1.51 04 Apr 1996 11:06:16 AGUPTA2
// Added calls to MMX_BlockCopy().
//
// Rev 1.50 01 Apr 1996 13:05:28 RMCKENZX
// Added MMx functionality for Advance Prediction and PB Frames.
//
// Rev 1.49 22 Mar 1996 17:50:30 AGUPTA2
// MMX support. MMX support is included only if MMX defined. MMX is
// not defined by default so that we do not impact IA code size.
//
// Rev 1.48 08 Mar 1996 16:46:22 AGUPTA2
// Added pragmas code_seg and data_seg to place code and data in appropriate
// segments. Created a function table of interpolation rtns.; interpolation
// rtns. are now called thru this function table. Commented out the clipping of
// MV code. It is not needed now and it needs to be re-written to be more
// efficient.
//
//
// Rev 1.47 23 Feb 1996 09:46:54 KLILLEVO
// fixed decoding of Unrestricted Motion Vector mode
//
// Rev 1.46 29 Jan 1996 17:50:48 RMCKENZX
// Reorganized logic in H263IDCTandMC for AP, optimizing the changes
// made for revision 1.42 and simplifying logic for determining iNext[i].
// Also corrected omission for UMV decoding in H263BBlockPrediction.
//
// Rev 1.0 29 Jan 1996 12:44:00 RMCKENZX
// Initial revision.
//
// Rev 1.45 24 Jan 1996 13:22:06 BNICKERS
// Turn OBMC back on.
//
// Rev 1.44 16 Jan 1996 11:46:22 RMCKENZX
// Added support for UMV -- to correctly decode B-block
// motion vectors when UMV is on
//
// Rev 1.43 15 Jan 1996 14:34:32 BNICKERS
//
// Temporarily turn off OBMC until encoder can be changed to do it too.
//
// Rev 1.42 12 Jan 1996 16:29:48 BNICKERS
//
// Correct OBMC to be spec compliant when neighbor is Intra coded.
//
// Rev 1.41 06 Jan 1996 18:36:58 RMCKENZX
// Simplified rounding logic for chroma motion vector computation
// using MUCH smaller tables (at the cost of a shift, add, and mask
// per vector).
//
// Rev 1.40 05 Jan 1996 15:59:12 RMCKENZX
//
// fixed bug in decoding forward b-frame motion vectors
// so that they will stay within the legal ranges.
// re-organized the BBlockPredict function - using only
// one test for 4 motion vectors and a unified call to
// do the backward prediction for both lumina and chroma blocks.
//
// Rev 1.39 21 Dec 1995 17:05:24 TRGARDOS
// Added comments about descrepancy with H.263 spec.
//
// Rev 1.38 21 Dec 1995 13:24:28 RMCKENZX
// Fixed bug on pRefL, re-architected IDCTandMC
//
// Rev 1.37 18 Dec 1995 12:46:34 RMCKENZX
// added copyright notice
//
// Rev 1.36 16 Dec 1995 20:34:04 RHAZRA
//
// Changed declaration of pRefX to U32
//
// Rev 1.35 15 Dec 1995 13:53:32 RHAZRA
//
// AP cleanup
//
// Rev 1.34 15 Dec 1995 10:51:38 RHAZRA
//
// Changed reference block addresses in AP
//
// Rev 1.33 14 Dec 1995 17:04:16 RHAZRA
//
// Cleanup in the if-then-else structure in the OBMC part
//
// Rev 1.32 13 Dec 1995 22:11:56 RHAZRA
// AP cleanup
//
// Rev 1.31 13 Dec 1995 10:59:26 RHAZRA
// More AP+PB fixes
//
// Rev 1.29 11 Dec 1995 11:33:12 RHAZRA
// 12-10-95 changes: added AP stuff
//
// Rev 1.28 09 Dec 1995 17:31:22 RMCKENZX
// Gutted and re-built file to support decoder re-architecture.
// New modules are:
// H263IDCTandMC
// H263BFrameIDCTandBiMC
// H263BBlockPrediction
// This module now contains code to support the second pass of the decoder.
//
// Rev 1.27 23 Oct 1995 13:28:42 CZHU
// Use the right quant for B blocks and call BlockAdd for type 3/4 too
//
// Rev 1.26 17 Oct 1995 17:18:24 CZHU
// Fixed the bug in decoding PB block CBPC
//
// Rev 1.25 13 Oct 1995 16:06:20 CZHU
// First version that supports PB frames. Display B or P frames under
// VfW for now.
//
// Rev 1.24 11 Oct 1995 17:46:28 CZHU
// Fixed bitstream bugs
//
// Rev 1.23 11 Oct 1995 13:26:00 CZHU
// Added code to support PB frame
//
// Rev 1.22 27 Sep 1995 16:24:14 TRGARDOS
//
// Added debug print statements.
//
// Rev 1.21 26 Sep 1995 15:33:52 CZHU
//
// Adjusted buffers used for MB for inter frame motion compensation
//
// Rev 1.20 19 Sep 1995 10:37:04 CZHU
//
// Cleaning up
//
// Rev 1.19 15 Sep 1995 09:39:34 CZHU
//
// Update both GOB Quant and Picture Quant after DQUANT
//
// Rev 1.18 14 Sep 1995 10:11:48 CZHU
// Fixed bugs updating Quant for the picture
//
// Rev 1.17 13 Sep 1995 11:57:08 CZHU
//
// Fixed bugs in calling Chroma BlockAdd parameters.
//
// Rev 1.16 12 Sep 1995 18:18:40 CZHU
// Call BlockAdd finally.
//
// Rev 1.15 12 Sep 1995 11:12:38 CZHU
// Call blockCopy for MB that is not coded.
//
// Rev 1.14 11 Sep 1995 16:43:26 CZHU
// Changed interface to DecodeBlock. Added interface calls to BlockCopy and Bl
//
// Rev 1.13 11 Sep 1995 14:30:12 CZHU
// MVs decoding.
//
// Rev 1.12 08 Sep 1995 11:48:12 CZHU
// Added support for Delta frames, also fixed early bugs regarding INTER CBPY
//
// 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"
extern "C" { void H263BiMotionComp(U32, U32, I32, I32, I32); void H263OBMC(U32, U32, U32, U32, U32, U32); }
#ifdef USE_MMX // { USE_MMX
extern "C" { void MMX_AdvancePredict(T_BlkAction FAR *, int *, U8 *, I8 *, I8 *); void MMX_BiMotionComp(U32, U32, I32, I32, I32); } #endif // } USE_MMX
void AdvancePredict(T_BlkAction FAR *fpBlockAction, int *iNext, U8 *pDst, int, int, BOOL);
#pragma data_seg("IARDATA2")
char QuarterPelRound[] = {0, 1, 0, 0}; char SixteenthPelRound[] = {0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1}; void (*Interpolate_Table[4])(U32, U32) = {NULL, Interpolate_Half_Int, Interpolate_Int_Half, Interpolate_Half_Half}; #ifdef USE_MMX // { USE_MMX
void (_fastcall * MMX_Interpolate_Table[4])(U32, U32) = {NULL, MMX_Interpolate_Half_Int, MMX_Interpolate_Int_Half, MMX_Interpolate_Half_Half}; #endif // } USE_MMX
I8 i8EMVClipTbl_NoClip[128] = { -64,-63,-62,-61,-60,-59,-58,-57, -56,-55,-54,-53,-52,-51,-50,-49, -48,-47,-46,-45,-44,-43,-42,-41, -40,-39,-38,-37,-36,-35,-34,-33, -32,-31,-30,-29,-28,-27,-26,-25, -24,-23,-22,-21,-20,-19,-18,-17, -16,-15,-14,-13,-12,-11,-10, -9, -8, -7, -6, -5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, }; I8 i8EMVClipTbl_HiClip[128] = { -64,-63,-62,-61,-60,-59,-58,-57, -56,-55,-54,-53,-52,-51,-50,-49, -48,-47,-46,-45,-44,-43,-42,-41, -40,-39,-38,-37,-36,-35,-34,-33, -32,-31,-30,-29,-28,-27,-26,-25, -24,-23,-22,-21,-20,-19,-18,-17, -16,-15,-14,-13,-12,-11,-10, -9, -8, -7, -6, -5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, }; I8 i8EMVClipTbl_LoClip[128] = { -32,-32,-32,-32,-32,-32,-32,-32, -32,-32,-32,-32,-32,-32,-32,-32, -32,-32,-32,-32,-32,-32,-32,-32, -32,-32,-32,-32,-32,-32,-32,-32, -32,-31,-30,-29,-28,-27,-26,-25, -24,-23,-22,-21,-20,-19,-18,-17, -16,-15,-14,-13,-12,-11,-10, -9, -8, -7, -6, -5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, };
#pragma data_seg(".data")
#pragma code_seg("IACODE2")
// doing this as a function instead of a macro should save
// some codespace.
void UmvOnEdgeClipMotionVectors2(I32 *mvx, I32 *mvy, int EdgeFlag, int BlockNo) { int MaxVec;
if (BlockNo < 4) MaxVec = 32; else MaxVec = 16;
if (EdgeFlag & LEFT_EDGE) { if (*mvx < -MaxVec) *mvx = -MaxVec; } if (EdgeFlag & RIGHT_EDGE) { if (*mvx > MaxVec ) *mvx = MaxVec ; } if (EdgeFlag & TOP_EDGE) { if (*mvy < -MaxVec ) *mvy = -MaxVec ; } if (EdgeFlag & BOTTOM_EDGE) { if (*mvy > MaxVec ) *mvy = MaxVec ; } } #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; int iNext[4]; // Left-Right-Above-Below
I32 mvx, mvy; U32 pRefTmp; int i;
ASSERT(*pN != 65); if (*pN < 65) // Inter block
{ int interp_index;
// first do motion compensation
// result will be pointed to by pRef
pRef = (U32) DC + DC->uMBBuffer; mvx = fpBlockAction[iBlock].i8MVx2; mvy = fpBlockAction[iBlock].i8MVy2;
// Clip motion vectors pointing outside active image area
if (DC->bUnrestrictedMotionVectors) { UmvOnEdgeClipMotionVectors2(&mvx,&mvy,iEdgeFlag,iBlock); }
pRefTmp = fpBlockAction[iBlock].pRefBlock + (I32) (mvx >> 1) + PITCH * (I32) (mvy >> 1);
// Must calculate AFTER UMV clipping
interp_index = ((mvy & 0x1)<<1) | (mvx & 0x1);
// Do non-OBMC prediction if this is a chroma block OR
// a luma block in non-AP mode of operation
if ( (!DC->bAdvancedPrediction) || (iBlock > 3) ) { if (interp_index) { // TODO
#ifdef USE_MMX // { USE_MMX
if (DC->bMMXDecoder) (*MMX_Interpolate_Table[interp_index])(pRefTmp, pRef); else (*Interpolate_Table[interp_index])(pRefTmp, pRef); #else // }{ USE_MMX
(*Interpolate_Table[interp_index])(pRefTmp, pRef); #endif // } USE_MMX
} else pRef = pRefTmp; } else // Overlapped block motion compensation
{ ASSERT (DC->bAdvancedPrediction); ASSERT ( (iBlock <= 3) );
// Compute iNext[i] which will point at the adjacent blocks.
// Left & Right blocks
if (iBlock & 1) { // blocks 1 or 3, on right
iNext[0] = -1; if ( iMBNum == DC->iNumberOfMBsPerGOB ) iNext[1] = 0; else iNext[1] = 5; } else { // blocks 0 or 2, on left
iNext[1] = 1; if (iMBNum == 1) iNext[0] = 0; else iNext[0] = -5; }
// Above & Below blocks
if (iBlock > 1) { // blocks 2 or 3, on bottom
iNext[2] = -2; iNext[3] = 0; } else { // blocks 0 or 1, on top
iNext[3] = 2; if (iGOBNum == 1) iNext[2] = 0; else iNext[2] = -6*DC->iNumberOfMBsPerGOB + 2; }
// When PB frames are OFF
// if there is a neighbor and it is INTRA, use this block's vector instead.
if (!DC->bPBFrame) for (i=0; i<4; i++) // block types: 0=INTRA_DC, 1=INTRA, 2=INTER, 3=EMPTY, 4=ERROR
if (iNext[i] && fpBlockAction[iBlock+iNext[i]].u8BlkType < 2) iNext[i] = 0; // Now do overlapped motion compensation; output to pRef
#ifdef USE_MMX // { USE_MMX
if (DC->bMMXDecoder) {
I8 *pClipX, *pClipY;
pClipY = pClipX = &i8EMVClipTbl_NoClip[0]; if (DC->bUnrestrictedMotionVectors) { if (iEdgeFlag & TOP_EDGE) pClipY = &i8EMVClipTbl_LoClip[0]; else if (iEdgeFlag & BOTTOM_EDGE) pClipY = &i8EMVClipTbl_HiClip[0]; if (iEdgeFlag & LEFT_EDGE) pClipX = &i8EMVClipTbl_LoClip[0]; else if (iEdgeFlag & RIGHT_EDGE) pClipX = &i8EMVClipTbl_HiClip[0]; } MMX_AdvancePredict(fpBlockAction+iBlock, iNext, (U8*)pRef, pClipX, pClipY); } else AdvancePredict(fpBlockAction+iBlock, iNext, (U8*)pRef, iEdgeFlag, iBlock, DC->bUnrestrictedMotionVectors); #else // }{ USE_MMX
AdvancePredict(fpBlockAction+iBlock, iNext, (U8*)pRef, iEdgeFlag, iBlock, DC->bUnrestrictedMotionVectors); #endif // } USE_MMX
} // end OBMC
// 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
#ifdef USE_MMX // { USE_MMX
if (DC->bMMXDecoder) { MMX_DecodeBlock_IDCT( (U32)pRUN_INVERSE_Q, *pN, (U32) DC + DC->uMBBuffer + BLOCK_BUFFER_OFFSET); // inter output
MMX_BlockAdd( (U32) DC + DC->uMBBuffer + BLOCK_BUFFER_OFFSET, // output
pRef, // prediction
fpBlockAction[iBlock].pCurBlock); // destination
} else { DecodeBlock_IDCT( (U32)pRUN_INVERSE_Q, *pN, fpBlockAction[iBlock].pCurBlock, // not used here
(U32) DC + DC->uMBBuffer + BLOCK_BUFFER_OFFSET);// inter output
BlockAdd( (U32) DC + DC->uMBBuffer + BLOCK_BUFFER_OFFSET, // output
pRef, // prediction
fpBlockAction[iBlock].pCurBlock); // destination
} #else // }{ USE_MMX
DecodeBlock_IDCT( (U32)pRUN_INVERSE_Q, *pN, fpBlockAction[iBlock].pCurBlock, // not used here
(U32) DC + DC->uMBBuffer + BLOCK_BUFFER_OFFSET);// inter output
BlockAdd( (U32) DC + DC->uMBBuffer + BLOCK_BUFFER_OFFSET, // output
pRef, // prediction
fpBlockAction[iBlock].pCurBlock); // destination
#endif // } USE_MMX
} else // *pN == 0, so no transform coefficients for this block
{ // Just copy motion compensated reference block
#ifdef USE_MMX // { USE_MMX
if (DC->bMMXDecoder) MMX_BlockCopy( fpBlockAction[iBlock].pCurBlock, // destination
pRef); // prediction
else BlockCopy( fpBlockAction[iBlock].pCurBlock, // destination
pRef); // prediction
#else // }{ USE_MMX
BlockCopy( fpBlockAction[iBlock].pCurBlock, // destination
pRef); // prediction
#endif // } USE_MMX
} } else // *pN >= 65, hence intRA
{ // TODO
#ifdef USE_MMX // { USE_MMX
if (DC->bMMXDecoder) { U32 ScaledDC = pRUN_INVERSE_Q->dInverseQuant; pRUN_INVERSE_Q->dInverseQuant = 0; MMX_DecodeBlock_IDCT( (U32)pRUN_INVERSE_Q, //
*pN - 65, // No. of coeffs
(U32) DC + DC->uMBBuffer + BLOCK_BUFFER_OFFSET); MMX_ClipAndMove((U32) DC + DC->uMBBuffer + BLOCK_BUFFER_OFFSET, fpBlockAction[iBlock].pCurBlock, (U32)ScaledDC); } else DecodeBlock_IDCT( (U32)pRUN_INVERSE_Q, *pN, fpBlockAction[iBlock].pCurBlock, // INTRA transform output
(U32) DC + DC->uMBBuffer + BLOCK_BUFFER_OFFSET); #else // }{ USE_MMX
DecodeBlock_IDCT( (U32)pRUN_INVERSE_Q, *pN, fpBlockAction[iBlock].pCurBlock, // INTRA transform output
(U32) DC + DC->uMBBuffer + BLOCK_BUFFER_OFFSET); #endif // } USE_MMX
} // end if (*pN < 65) ... else ...
} // End IDCTandMC
////////////////////////////////////////////////////////////////////////////////
#pragma code_seg()
/*****************************************************************************
* * AdvancePredict * * Motion Compensation for Advance Prediction * This module is only called in the non-MMx case. * In the MMx case, MMX_AdvancePredict is called instead. * ****************************************************************************/
#pragma code_seg("IACODE2")
void AdvancePredict( T_BlkAction FAR *fpBlockAction, int *iNext, U8 *pDst, int iEdgeFlag, int iBlock, BOOL bUnrestrictedMotionVectors ) {
U32 pRefC, pRefN[4]; // Left-Right-Above-Below
I32 mvx, mvy; U32 pRefTmp; int i; int interp_index; mvx = fpBlockAction->i8MVx2; mvy = fpBlockAction->i8MVy2;
// Clip motion vectors pointing outside active image area
if (bUnrestrictedMotionVectors) { UmvOnEdgeClipMotionVectors2(&mvx,&mvy,iEdgeFlag,iBlock); }
interp_index = ((mvy & 0x1)<<1) | (mvx & 0x1);
pRefTmp = fpBlockAction->pRefBlock + (I32) (mvx >> 1) + PITCH * (I32) (mvy >> 1);
pRefC = (U32) pDst + 8; pRefN[0] = (U32) pDst + 16; pRefN[1] = (U32) pDst + 24; pRefN[2] = (U32) pDst + 32; pRefN[3] = (U32) pDst + 40;
// Current block
if (interp_index) (*Interpolate_Table[interp_index])(pRefTmp, pRefC); else pRefC = pRefTmp; // Compute and apply motion vectors
// Prediction is placed at pRefN[i]
for (i=0; i<4; i++) {
if (iNext[i]) {
// Get the motion vector components.
// Note that for macroblocks that were not coded, THESE MUST BE 0!
// (Which is what H263InitializeBlockActionStream sets them to.)
mvx = fpBlockAction[iNext[i]].i8MVx2; mvy = fpBlockAction[iNext[i]].i8MVy2; // Clip motion vectors pointing outside active image area
if (bUnrestrictedMotionVectors) { UmvOnEdgeClipMotionVectors2(&mvx,&mvy,iEdgeFlag,iBlock); } // apply motion vector to get reference block at pRefN[i]
pRefTmp = fpBlockAction->pRefBlock + (I32) (mvx >> 1) + PITCH * (I32) (mvy >> 1); // do interpolation if needed
interp_index = ((mvy & 0x1)<<1) | (mvx & 0x1); if (interp_index) (*Interpolate_Table[interp_index])(pRefTmp, pRefN[i]); else pRefN[i] = pRefTmp;
} // end if (iNext[i])
else { // use this block's reference
pRefN[i] = pRefC; } // end if (iNext[i] && ...) ... else ...
} // end for (i=0; i<4; i++) {}
// Now do overlapped motion compensation.
H263OBMC(pRefC, pRefN[0], pRefN[1], pRefN[2], pRefN[3], (U32)pDst); } // End AdvancePredict
////////////////////////////////////////////////////////////////////////////////
#pragma code_seg()
/*****************************************************************************
* * BBlockPrediction * * Compute the predictions from the "forward" and "backward" motion vectors. * ****************************************************************************/ #pragma code_seg("IACODE2")
void H263BBlockPrediction( T_H263DecoderCatalog FAR *DC, T_BlkAction FAR *fpBlockAction, U32 pRef[], T_MBInfo FAR *fpMBInfo, int iEdgeFlag ) { //find out the MVf and MVb first from TR
I32 mv_f_x[6], mv_b_x[6], mv_f_y[6], mv_b_y[6]; I32 mvx_expectation, mvy_expectation; I32 iTRD, iTRB; I32 i; U32 pRefTmp;
int mvfx, mvbx, mvfy, mvby;
FX_ENTRY("H263BBlockPrediction")
iTRB = DC->uBFrameTempRef; iTRD = DC->uTempRef - DC->uTempRefPrev;
if (!iTRD) { DEBUGMSG(ZONE_DECODE_DETAILS, ("%s: Warning: given TR == last TR, set TRD = 256\r\n", _fx_)); iTRD = 256; } else if (iTRD < 0) iTRD += 256;
// final MVD for P blocks is in
// fpBlockAction[0].i8MVx2,... and fpBlockAction[3].i8MVx2, and
// fpBlockAction[0].i8MVy2,... and fpBlockAction[3].i8MVy2.
// check for 4 motion vectors per macroblock
// TODO can motion vector calculation be done in the first pass
if (fpMBInfo->i8MBType == 2) { // yep, we got 4 of 'em
#ifdef H263P
// If H.263+, we can have 8x8 MV's if the deblocking filter
// was selected.
ASSERT(DC->bAdvancedPrediction || DC->bDeblockingFilter); #else
ASSERT(DC->bAdvancedPrediction); #endif
// Do luma vectors first
for (i=0; i<4; i++) { #ifdef H263P
// If we are using improved PB-frame mode (H.263+) and the B-block
// was signalled to be predicted in the forward direction only,
// the motion vector contained in MVDB is the actual forward MV -
// no prediction is used.
if (DC->bImprovedPBFrames == TRUE && fpMBInfo->bForwardPredOnly == TRUE) { // Zero-out the expectation (the motion vector prediction)
mvx_expectation = 0; mvy_expectation = 0; } else #endif
{ // compute forward expectation
mvx_expectation = ( iTRB * (I32)fpBlockAction[i].i8MVx2 / iTRD ); mvy_expectation = ( iTRB * (I32)fpBlockAction[i].i8MVy2 / iTRD ); } // add in differential
mv_f_x[i] = mvx_expectation + fpMBInfo->i8MVDBx2; mv_f_y[i] = mvy_expectation + fpMBInfo->i8MVDBy2;
// check to see if the differential carried us too far
if (DC->bUnrestrictedMotionVectors) { if (mvx_expectation > 32) { if (mv_f_x[i] > 63) mv_f_x[i] -=64; } else if (mvx_expectation < -31) { if (mv_f_x[i] < -63) mv_f_x[i] +=64; } // always use "first column" when expectation lies in [-31, +32]
if (mvy_expectation > 32) { if (mv_f_y[i] > 63) mv_f_y[i] -=64; } else if (mvy_expectation < -31) { if (mv_f_y[i] < -63) mv_f_y[i] +=64; } } else // UMV off
{ if (mv_f_x[i] >= 32) mv_f_x[i] -= 64; else if (mv_f_x[i] < -32) mv_f_x[i] += 64;
if (mv_f_y[i] >= 32) mv_f_y[i] -= 64; else if (mv_f_y[i] < -32) mv_f_y[i] += 64; } // end if (UMV) ... else ...
// Do backwards motion vectors
// Backward vectors are not required if using improved PB-frame mode
// and the B-block uses only forward prediction. We will keep the calculation
// of mv_b_{x,y} here since it doesn't harm anything.
// TODO
if (fpMBInfo->i8MVDBx2) mv_b_x[i] = mv_f_x[i] - fpBlockAction[i].i8MVx2; else mv_b_x[i] = ( (iTRB - iTRD) * (I32)fpBlockAction[i].i8MVx2 / iTRD ); if (fpMBInfo->i8MVDBy2) mv_b_y[i] = mv_f_y[i] - fpBlockAction[i].i8MVy2; else mv_b_y[i] = ( (iTRB - iTRD) * (I32)fpBlockAction[i].i8MVy2 / iTRD );
} // end for(i=0; i<4; i++){}
// Now do the chromas
// first get average times 4
for (i=0, mvfx=mvbx=mvfy=mvby=0; i<4; i++) { mvfx += mv_f_x[i]; mvfy += mv_f_y[i]; mvbx += mv_b_x[i]; mvby += mv_b_y[i]; } // now interpolate
mv_f_x[4] = mv_f_x[5] = (mvfx >> 3) + SixteenthPelRound[mvfx & 0x0f]; mv_f_y[4] = mv_f_y[5] = (mvfy >> 3) + SixteenthPelRound[mvfy & 0x0f]; mv_b_x[4] = mv_b_x[5] = (mvbx >> 3) + SixteenthPelRound[mvbx & 0x0f]; mv_b_y[4] = mv_b_y[5] = (mvby >> 3) + SixteenthPelRound[mvby & 0x0f]; } else // only 1 motion vector for this macroblock
{
#ifdef H263P
// If we are using improved PB-frame mode (H.263+) and the B-block
// was signalled to be predicted in the forward direction only,
// the motion vector contained in MVDB is the actual forward MV -
// no prediction is used.
if (DC->bImprovedPBFrames == TRUE && fpMBInfo->bForwardPredOnly == TRUE) { // Zero-out the expectation (the motion vector prediction)
mvx_expectation = 0; mvy_expectation = 0; } else #endif
{ // compute forward expectation
mvx_expectation = ( iTRB * (I32)fpBlockAction[0].i8MVx2 / iTRD ); mvy_expectation = ( iTRB * (I32)fpBlockAction[0].i8MVy2 / iTRD ); } // add in differential
mv_f_x[0] = mvx_expectation + fpMBInfo->i8MVDBx2; mv_f_y[0] = mvy_expectation + fpMBInfo->i8MVDBy2;
// check to see if the differential carried us too far
// TODO: Clipping of motion vector needs to happen when decoder needs
// to interoperate
if (DC->bUnrestrictedMotionVectors) { if (mvx_expectation > 32) { if (mv_f_x[0] > 63) mv_f_x[0] -=64; } else if (mvx_expectation < -31) { if (mv_f_x[0] < -63) mv_f_x[0] +=64; } // always use "first column" when expectation lies in [-31, +32]
if (mvy_expectation > 32) { if (mv_f_y[0] > 63) mv_f_y[0] -=64; } else if (mvy_expectation < -31) { if (mv_f_y[0] < -63) mv_f_y[0] +=64; } } else // UMV off, decode normally
{ if (mv_f_x[0] >= 32) mv_f_x[0] -= 64; else if (mv_f_x[0] < -32) mv_f_x[0] += 64;
if (mv_f_y[0] >= 32) mv_f_y[0] -= 64; else if (mv_f_y[0] < -32) mv_f_y[0] += 64; } // finished decoding
// copy for other 3 motion vectors
mv_f_x[1] = mv_f_x[2] = mv_f_x[3] = mv_f_x[0]; mv_f_y[1] = mv_f_y[2] = mv_f_y[3] = mv_f_y[0];
// do backwards motion vectors
// Backward vectors are not required if using improved PB-frame mode
// and the B-block uses only forward prediction. We will keep the calculation
// of mv_b_{x,y} here since it doesn't harm anything.
// TODO
if (fpMBInfo->i8MVDBx2) mv_b_x[0] = mv_f_x[0] - fpBlockAction[0].i8MVx2; else mv_b_x[0] = ( (iTRB - iTRD) * (I32)fpBlockAction[0].i8MVx2 / iTRD );
if (fpMBInfo->i8MVDBy2) mv_b_y[0] = mv_f_y[0] - fpBlockAction[0].i8MVy2; else mv_b_y[0] = ( (iTRB - iTRD) * (I32)fpBlockAction[0].i8MVy2 / iTRD );
// copy for other 3 motion vectors
mv_b_x[1] = mv_b_x[2] = mv_b_x[3] = mv_b_x[0]; mv_b_y[1] = mv_b_y[2] = mv_b_y[3] = mv_b_y[0];
// interpolate for chroma
mv_f_x[4] = mv_f_x[5] = (mv_f_x[0] >> 1) + QuarterPelRound[mv_f_x[0] & 0x03]; mv_f_y[4] = mv_f_y[5] = (mv_f_y[0] >> 1) + QuarterPelRound[mv_f_y[0] & 0x03]; mv_b_x[4] = mv_b_x[5] = (mv_b_x[0] >> 1) + QuarterPelRound[mv_b_x[0] & 0x03]; mv_b_y[4] = mv_b_y[5] = (mv_b_y[0] >> 1) + QuarterPelRound[mv_b_y[0] & 0x03];
} // end else 1 motion vector per macroblock
// Prediction from Previous decoder P frames, referenced by RefBlock
// Note: The previous decoder P blocks in in RefBlock, and
// the just decoder P blocks are in CurBlock
// the target B blocks are in BBlock
// translate MV into address of reference blocks.
pRefTmp = (U32) DC + DC->uMBBuffer; for (i=0; i<6; i++) { pRef[i] = pRefTmp; pRefTmp += 8; }
// Do the forward predictions
for (i=0; i<6; i++) { int interp_index; // in UMV mode: clip MVs pointing outside 16 pels wide edge
if (DC->bUnrestrictedMotionVectors) { UmvOnEdgeClipMotionVectors2(&mv_f_x[i],&mv_f_y[i], iEdgeFlag, i); // no need to clip backward vectors
}
// Put forward predictions at addresses pRef[0], ..., pRef[5].
pRefTmp = fpBlockAction[i].pRefBlock + (I32)(mv_f_x[i]>>1) + PITCH * (I32)(mv_f_y[i]>>1); // TODO
interp_index = ((mv_f_y[i] & 0x1)<<1) | (mv_f_x[i] & 0x1); if (interp_index) { #ifdef USE_MMX // { USE_MMX
if (DC->bMMXDecoder) (*MMX_Interpolate_Table[interp_index])(pRefTmp, pRef[i]); else (*Interpolate_Table[interp_index])(pRefTmp, pRef[i]); #else // }{ USE_MMX
(*Interpolate_Table[interp_index])(pRefTmp, pRef[i]); #endif // } USE_MMX
} else { #ifdef USE_MMX // { USE_MMX
if (DC->bMMXDecoder) MMX_BlockCopy( pRef[i], // destination
pRefTmp); // prediction
else BlockCopy(pRef[i], pRefTmp); #else // }{ USE_MMX
BlockCopy(pRef[i], pRefTmp); #endif // } USE_MMX
} #ifdef H263P
// If we are using improved PB-frame mode (H.263+) and the B-block
// was signalled to be predicted in the forward direction only,
// we do not adjust with the backward prediction from the future.
if (DC->bImprovedPBFrames == FALSE || fpMBInfo->bForwardPredOnly == FALSE) #endif
{ #ifdef USE_MMX // { USE_MMX
if (DC->bMMXDecoder) // adjust with bacward prediction from the future
MMX_BiMotionComp( pRef[i], fpBlockAction[i].pCurBlock, (I32) mv_b_x[i], (I32) mv_b_y[i], i); else // adjust with bacward prediction from the future
H263BiMotionComp( pRef[i], fpBlockAction[i].pCurBlock, (I32) mv_b_x[i], (I32) mv_b_y[i], i); #else // }{ USE_MMX
// adjust with bacward prediction from the future
H263BiMotionComp( pRef[i], fpBlockAction[i].pCurBlock, (I32) mv_b_x[i], (I32) mv_b_y[i], i); #endif // } USE_MMX
}
} // end for (i=0; i<6; i++) {}
} #pragma code_seg()
/*****************************************************************************
* * H263BFrameIDCTandBiMC * * B Frame IDCT and * Bi-directional MC for B blocks */
#pragma code_seg("IACODE2")
void H263BFrameIDCTandBiMC( T_H263DecoderCatalog FAR *DC, T_BlkAction FAR *fpBlockAction, int iBlock, U32 *pN, T_IQ_INDEX *pRUN_INVERSE_Q, U32 *pRef ) { ASSERT(*pN < 65); // do the inverse transform (where appropriate) & combine
if (*pN > 0) {
#ifdef USE_MMX // { USE_MMX
if (DC->bMMXDecoder) { MMX_DecodeBlock_IDCT( (U32)pRUN_INVERSE_Q, *pN, (U32) DC + DC->uMBBuffer + BLOCK_BUFFER_OFFSET); // inter output
MMX_BlockAdd( (U32) DC + DC->uMBBuffer + BLOCK_BUFFER_OFFSET, // output
pRef[iBlock], // prediction
fpBlockAction[iBlock].pBBlock); // destination
} else { // Get residual block; put output at DC+DC->uMBBuffer+BLOCK_BUFFER_OFFSET
DecodeBlock_IDCT( (U32)pRUN_INVERSE_Q, *pN, fpBlockAction[iBlock].pBBlock, // intRA not used here
(U32) DC + DC->uMBBuffer + BLOCK_BUFFER_OFFSET); // inter output
// Add the residual to the reference block
BlockAdd( (U32) DC + DC->uMBBuffer + BLOCK_BUFFER_OFFSET, // transform output
pRef[iBlock], // prediction
fpBlockAction[iBlock].pBBlock); // destination
} #else // }{ USE_MMX
// Get residual block; put output at DC+DC->uMBBuffer+BLOCK_BUFFER_OFFSET
DecodeBlock_IDCT( (U32)pRUN_INVERSE_Q, *pN, fpBlockAction[iBlock].pBBlock, // intRA not used here
(U32) DC + DC->uMBBuffer + BLOCK_BUFFER_OFFSET); // inter output
// Add the residual to the reference block
BlockAdd( (U32) DC + DC->uMBBuffer + BLOCK_BUFFER_OFFSET, // transform output
pRef[iBlock], // prediction
fpBlockAction[iBlock].pBBlock); // destination
#endif // } USE_MMX
} else { // No transform coefficients for this block,
// copy the prediction to the output.
#ifdef USE_MMX // { USE_MMX
if (DC->bMMXDecoder) MMX_BlockCopy( fpBlockAction[iBlock].pBBlock, // destination
pRef[iBlock]); // prediction
else BlockCopy( fpBlockAction[iBlock].pBBlock, // destination
pRef[iBlock]); // prediction
#else // }{ USE_MMX
BlockCopy( fpBlockAction[iBlock].pBBlock, // destination
pRef[iBlock]); // prediction
#endif // } USE_MMX
} } #pragma code_seg()
|