Leaked source code of windows server 2003
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.
 
 
 
 
 
 

1155 lines
37 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 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()