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
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()
|
|
|