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.
 
 
 
 
 
 

3137 lines
102 KiB

/* *************************************************************************
** INTEL Corporation Proprietary Information
**
** This listing is supplied under the terms of a license
** agreement with INTEL Corporation and may not be copied
** nor disclosed except in accordance with the terms of
** that agreement.
**
** Copyright (c) 1995-1996 Intel Corporation.
** All Rights Reserved.
**
** *************************************************************************
*/
/*****************************************************************************
*
* d1dec.cpp
*
* DESCRIPTION:
* H261 decoder top level functions
*
* Routines: Prototypes in:
* H263InitDecoderGlobal d1dec.h
* H263InitDecoderInstance d1dec.h
* H263Decompress d1dec.h
* H263TermDecoderInstance d1dec.h
*/
// $Header: S:\h26x\src\dec\d1dec.cpv 1.69 24 Mar 1997 11:34:36 mbodart $
// $Log: S:\h26x\src\dec\d1dec.cpv $
//
// Rev 1.69 24 Mar 1997 11:34:36 mbodart
// Added check for PREROLL, if so don't display.
//
// Rev 1.68 19 Mar 1997 16:24:36 mbodart
// Fixed potential problem where aspect ratio adjustment to uNewOffsetToLine0
// should not occur for positive pitches.
//
// Rev 1.67 19 Mar 1997 15:01:46 mbodart
// Changes to DibXY to support RGB output with a negative bitmap height.
//
// Rev 1.66 24 Jan 1997 17:05:16 RHAZRA
// RTP change: we now look for an EBS for every frame. If there is one
// then we copy the H.261 bits and the EBS separately into our local
// bitstream buffer, inserting two zero bytes between the H261 bits and
// the EBS. We need the two zero bytes to mark the end of the frame for
// the pass 1 code. If there is no EBS, then we proceed as before by
// copying the bitstream and then adding two zero bytes at the end.
//
// Rev 1.65 22 Jan 1997 13:33:40 RHAZRA
// Since PPM now fills in the source format even for a PSC packet loss,
// the check for format change has been moved back into d1pict.cpp. This
// was how the check was initially designed in the pre-RTP era.
//
// Rev 1.64 23 Dec 1996 16:32:38 MBODART
// Fixed a bug where we allowed more than 33 macro blocks to be present
// in a GOB. Now we return an error in this case.
// Also removed some dead code involving mb_start.
//
// Rev 1.63 16 Dec 1996 14:41:08 RHAZRA
// Changed a bitstream error ASSERT to a bonafide error.
//
// Rev 1.62 16 Dec 1996 09:09:42 RHAZRA
// Now LOSS_RECOVERY mode is turned on by default in Pass 1
//
// Rev 1.61 12 Dec 1996 09:36:04 SCDAY
//
// Changed size of a couple of data structures in H263InitDecoderInstance
// to improve memory footprint
//
// Rev 1.60 18 Nov 1996 17:12:38 MBODART
// Replaced all debug message invocations with Active Movie's DbgLog.
//
// Rev 1.59 13 Nov 1996 11:35:56 RHAZRA
// Added MMX_autosensing.
//
// Rev 1.58 11 Nov 1996 11:03:28 MBODART
// Fixed bug where block action block type was not explicitly initialized for
// skipped macro blocks. This led to the block edge filter being used more
// often than needed.
//
// Rev 1.57 04 Nov 1996 08:43:18 RHAZRA
// Fixed setting MMX on or off via the INI file when the MMX key
// has an illegal value (<0 or > 1) assigned to it.
//
// Rev 1.56 31 Oct 1996 08:58:34 SCDAY
// Raj added support for MMX decoder
//
// Rev 1.55 30 Oct 1996 09:59:46 MBODART
// Fixed mirroring. Need to use absolute value of dst biWidth in most context
// Also made cosmetic changes to DibXY. It's identical to H.263's DibXY, we
// should probably put it into a common file.
//
// Rev 1.54 27 Sep 1996 14:59:32 MBODART
// DECODE_STATS enabled build will now compile, but numbers aren't accurate.
//
// Rev 1.53 26 Sep 1996 12:30:00 RHAZRA
// Added (i) MMX sensing in the decoder and ini file reading (requires a new
// "MMX" section in h263test.ini to turn off MMX on a MMX CPU) and (ii)
// MMX & PentiumPro CCs.
//
// Rev 1.52 25 Sep 1996 17:35:20 BECHOLS
//
// Added code just prior to color conversion that will perform the
// Snapshot copy on request.
//
// Rev 1.51 24 Sep 1996 13:52:24 RHAZRA
// Changed fpBlockAction synchronization to deal with MBAP being biased
// by -1 in the RTP extension.
//
// Rev 1.50 17 Sep 1996 22:08:36 RHAZRA
// Added code in RTP packet loss recovery to read GOB number from the
// bitstream when the packet following the lost packet starts with a
// GOB start code.
//
// Rev 1.49 16 Sep 1996 09:28:56 RHAZRA
// Fixed a bug in MB-level fragmentation recovery.
//
// Rev 1.48 12 Sep 1996 14:23:12 MBODART
// Replaced GlobalAlloc family with HeapAlloc in the H.261 decoder.
//
// Rev 1.47 10 Sep 1996 15:51:42 RHAZRA
// Bug fixes in RTP packet loss recovery when bad GBSC or MBA is
// detected in the PPM generated lost packet.
//
// Rev 1.45 04 Sep 1996 09:52:32 RHAZRA
// Added a new pass 1 function to enable RTp decoder resiliency when
// LOSS_RECOVERY is defined.
//
// Rev 1.44 14 Aug 1996 08:41:04 RHAZRA
//
// Added support for YUV12 and YUY2 color convertors
//
// Rev 1.43 09 Aug 1996 17:23:10 MBODART
// Fixed uninitialized variable bugs: one in decoder rearchitecture, where
// MB type needed to be defined for skipped blocks; and one previously
// existing bug where the block action u8BlkType needed to be defined
// for skip blocks, in order to suppress the BEF on those blocks.
// These bugs render build 027 of H.261 broken.
//
// Rev 1.42 05 Aug 1996 11:00:30 MBODART
//
// H.261 decoder rearchitecture:
// Files changed: d1gob.cpp, d1mblk.{cpp,h}, d1dec.{cpp,h},
// filelist.261, h261_32.mak
// New files: d1bvriq.cpp, d1idct.cpp
// Obsolete files: d1block.cpp
// Work still to be done:
// Update h261_mf.mak
// Optimize uv pairing in d1bvriq.cpp and d1idct.cpp
// Fix checksum code (it doesn't work now)
// Put back in decoder stats
//
// Rev 1.41 10 Jul 1996 08:20:44 SCDAY
// Increased memory allocation for I420
//
// Rev 1.40 03 Jun 1996 12:21:52 AKASAI
// Initialized DC = NULL and added tests so that don't try to free
// and unlock if DC == NULL. This effected the "done" return area
// of H263Decompress and one other place.
//
// Also added checking of return status from reading GOB start code.
//
// Rev 1.39 03 May 1996 15:54:26 AKASAI
// Eliminate allocating space for B frame in decoder. This frame is
// not used.
//
// Rev 1.38 17 Apr 1996 18:36:30 AKASAI
// Updates to use non-distructive color convertors.
// Color Convertor has modified parameter list.
// FrameCopy is called only when BlockEdgeFilter is enabled or
// AdjustPels is enabled or when mirroring is enabled.
// For H.261 bitstreams.
// A frame copy is used for YUV12 when mirroring is enabled or
// AdjustPels is enabled.
//
// Basically normal processing without BEF you don't have to do
// a frame copy which saves ~2msec per frame QCIF.
//
// Rev 1.37 05 Apr 1996 14:22:18 AKASAI
//
// Added support for BlockEdgeFilter.
// Need to change where ReInitializeBlockActionStream was called.
//
// Rev 1.36 21 Mar 1996 16:59:54 AKASAI
// Needed to move location of picture checksum calculation because
// of the swap of Previous and Current Frames.
//
// Rev 1.35 18 Mar 1996 15:52:06 AKASAI
// Many, many changes.
// 1) To optimize for performance eliminated memcpy of current to
// previous frame. Now switch the pointers and re-initialize
// block Action stream. New routine H263ReInitializeBlockActionStream
// written and called after each frame is compressed. This
// change accounted to 3-4 of the 4-5 msec improvment.
// 2) Needed to add call to BlockCopy (NOTE: maybe BlockCopySpecial would
// be faster) to copy any skip blocks at the end of a GOB from
// previous to current. Change was necessary after 1).
// 3) Deleted some dead code
// 4) Changed timing statistic code some.
//
// Rev 1.34 29 Feb 1996 09:20:30 SCDAY
// Added support for mirroring
//
// Rev 1.33 14 Feb 1996 11:54:26 AKASAI
// Update to use new color convertors that fix palette flash.
// Also corrected data alignment problem which improves performance
// of decoder.
//
// Rev 1.32 09 Feb 1996 13:33:36 AKASAI
//
// Updated interface to call new AdjustPels routine. CustomChange
// Brightness, Saturation and Contrast seem to be working but very
// little testing has been done.
//
// Rev 1.31 12 Jan 1996 15:12:34 AKASAI
// Fixed pink blocks in RING0 QCIF TO FCIF by fixing static initialzation
// of GOBUpdate arrays. Was based on input parameter but now on constant.
//
// Rev 1.30 11 Jan 1996 16:57:00 DBRUCKS
//
// added GetDecoderOptions
// added use of bUseBlockEdgeFilter
// added use of bForceOnAspectRatioCorrection
// Changed to do aspect ratio correction for both I420 and H261 if either
// forced or specified by result of the DecompressQuery
//
// Rev 1.29 26 Dec 1995 17:40:54 DBRUCKS
//
// changed bTimerIsOn to bTimingThisFrame because it is used after STOP_TIMER
// fixed YUV12 decode when timer ifdefs are defined
//
// Rev 1.28 26 Dec 1995 12:48:18 DBRUCKS
// remove TIMING code
// add general purpose timing code using d1stat.*
//
// Rev 1.26 21 Dec 1995 17:49:06 AKASAI
// Replaced an uninitialized variable to AdjustPels with the correct on.
// Change of Contrast, Brightness and Saturation is not working correctly.
//
// Rev 1.25 13 Dec 1995 14:23:52 AKASAI
// Deleted setting of Initialized to False; Added calling of H263TermDecoderIn
// if Initialized == True.
//
// Rev 1.24 05 Dec 1995 10:20:12 SCDAY
// Cleaned up warnings
//
// Rev 1.23 17 Nov 1995 15:21:48 BECHOLS
//
// Added ring 0 stuff.
//
// Rev 1.22 17 Nov 1995 15:13:18 SCDAY
//
// Added key field to picture checksum data
//
// Rev 1.21 16 Nov 1995 18:11:42 AGANTZX
// Added p5 timing code (#define TIMING)
//
// Rev 1.20 15 Nov 1995 19:04:12 AKASAI
// Should now be able to play raw YUV12 files. Note: funny white stop
// when I play downriv4.avi.
//
// Rev 1.19 15 Nov 1995 14:27:22 AKASAI
// Added support for YUV12 "if 0" old code with aspec correction and
// 8 to 7 bit conversion. Added FrameCopy calls and DispFrame into structure.
// (Integration point)
//
// Rev 1.18 08 Nov 1995 14:58:02 SCDAY
// Added picture layer checksums
//
// Rev 1.17 03 Nov 1995 11:42:54 AKASAI
//
// Added and changed code to handle MB checksum hopefully better.
//
// Rev 1.16 01 Nov 1995 13:46:02 AKASAI
//
// Added allocation of temporary buffer for loop filter. uFilterBBuffer
// right after uMBBuffer.
//
// Rev 1.15 30 Oct 1995 16:20:26 AKASAI
// Fixed up extra bytes some more. Doug and Sylvia had already decided
// on 2 extra bytes for the decoder instead of 4. We now copy 2 zeros
// at the end of the biSizeImage.
//
// Rev 1.14 30 Oct 1995 15:38:22 AKASAI
// Frame 94 of grouch read past the end of the bit stream finding junk.
// Enabled code Sylvia had put in to copy 4 bytes of zero after biSizeImage.
// This seems to fix the problem playing grouch.avi.
//
// Rev 1.13 27 Oct 1995 19:11:26 AKASAI
// Added some special case code to handle when skip macroblock is last
// in a gob.
//
// Rev 1.12 27 Oct 1995 18:17:22 AKASAI
//
// Put in fix "hack" to keep the block action stream pointers
// in sync between d1dec and d1mblk. With skip macro blocks some
// macroblocks were being processed multiple times. Still a problem
// when gob ends with a skip macroblock.
//
// Rev 1.11 26 Oct 1995 15:33:10 SCDAY
//
// Delta frames partially working -- changed main loops to accommodate
// skipped macroblocks by detecting next startcode
//
// Rev 1.10 16 Oct 1995 13:53:46 SCDAY
//
// Added macroblock level checksum
//
// Rev 1.9 10 Oct 1995 15:44:02 SCDAY
// clean up
//
// Rev 1.8 10 Oct 1995 14:58:10 SCDAY
//
// added support for FCIF
//
// Rev 1.7 06 Oct 1995 15:32:28 SCDAY
//
// Integrated with latest AKK d1block
//
// Rev 1.6 04 Oct 1995 15:24:46 SCDAY
// changed test pattern stuff
//
// Rev 1.5 22 Sep 1995 15:07:02 SCDAY
// Doug fixed ASSERT bug, scd debug changes
//
// Rev 1.2 19 Sep 1995 15:25:32 SCDAY
//
// added H261 pict, GOB, MB/MBA parsing
//
// Rev 1.1 12 Sep 1995 15:52:24 DBRUCKS
// add SKIP_DECODE option for encoder work
//
// Rev 1.0 11 Sep 1995 13:51:48 SCDAY
// Initial revision.
//
// Rev 1.18 05 Sep 1995 17:22:12 DBRUCKS
// u & v are offset by 8 from Y in YVU12ForEnc
//
// Rev 1.17 01 Sep 1995 17:13:52 DBRUCKS
// add adjustpels
//
// Rev 1.16 01 Sep 1995 09:49:34 DBRUCKS
// checkin partial ajdust pels changes
//
// Rev 1.15 29 Aug 1995 16:50:40 DBRUCKS
// add support for YVU9 playback
//
// Rev 1.14 28 Aug 1995 17:45:58 DBRUCKS
// add yvu12forenc
//
// Rev 1.13 28 Aug 1995 10:15:14 DBRUCKS
// update to 5 July Spec and 8/25 Errata
//
// Rev 1.12 24 Aug 1995 08:51:30 CZHU
// Turned off apsect ratio correction.
//
// Rev 1.11 23 Aug 1995 12:25:10 DBRUCKS
// Turn on the color converters
//
// Rev 1.10 14 Aug 1995 16:40:34 DBRUCKS
// initialize block action stream
//
// Rev 1.9 11 Aug 1995 17:47:58 DBRUCKS
// cleanup
//
// Rev 1.8 11 Aug 1995 17:30:00 DBRUCKS
// copy source to bitstream
//
// Rev 1.7 11 Aug 1995 16:12:14 DBRUCKS
// add ptr check to MB data and add #ifndef early exit
//
// Rev 1.6 11 Aug 1995 15:10:18 DBRUCKS
// get ready to integrate with block level code and hook up macro block level code
//
// Rev 1.5 03 Aug 1995 14:57:56 DBRUCKS
// Add ASSERT macro
//
// Rev 1.4 02 Aug 1995 15:31:34 DBRUCKS
// added GOB header parsing
//
// Rev 1.3 01 Aug 1995 12:27:38 DBRUCKS
// add PSC parsing
//
// Rev 1.2 31 Jul 1995 16:28:00 DBRUCKS
// move loacl BITS defs to D3DEC.CPP
//
// Rev 1.1 31 Jul 1995 15:32:22 CZHU
// Moved global tables to d3tables.h
//
// Rev 1.0 31 Jul 1995 13:00:04 DBRUCKS
// Initial revision.
//
// Rev 1.3 28 Jul 1995 13:57:36 CZHU
// Started to add picture level decoding of fixed length codes.
//
// Rev 1.2 24 Jul 1995 14:57:52 CZHU
// Added global tables for VLD decoding. Also added instance initialization
// and termination. Several data structures are updated for H.263.
//
// Rev 1.1 17 Jul 1995 14:46:20 CZHU
//
//
// Rev 1.0 17 Jul 1995 14:14:40 CZHU
// Initial revision.
//////////////////////////////////////////////////////////////////////////////
#include "precomp.h"
static int iNumberOfGOBsBySourceFormat[2] = {
3, /* QCIF */
// 10,
12, /* CIF */
};
static int iNumberOfMBsInAGOBBySourceFormat[2] = {
33, /* QCIF */
33, /* CIF */
};
// rearch
//#ifndef LOSS_RECOVERY
#if 0
static LRESULT IAPass1ProcessFrame(
T_H263DecoderCatalog *DC,
T_BlkAction *fpBlockAction,
T_MBInfo *fpMBInfo,
BITSTREAM_STATE *fpbsState,
U8 *fpu8MaxPtr,
U32 *pN,
T_IQ_INDEX *pRUN_INVERSE_Q,
const I32 iNumberOfGOBs,
const I32 iNumberOfMBs,
const I32 iGOB_start,
const I32 iMB_start
);
#else
static LRESULT IAPass1ProcessFrameRTP(
T_H263DecoderCatalog *DC,
T_BlkAction *fpBlockAction,
T_MBInfo *fpMBInfo,
BITSTREAM_STATE *fpbsState,
U8 *fpu8MaxPtr,
U32 *pN,
T_IQ_INDEX *pRUN_INVERSE_Q,
const I32 iNumberOfGOBs,
const I32 iNumberOfMBs,
const I32 iGOB_start,
const I32 iMB_start
);
#endif
static void IAPass2ProcessFrame(
T_H263DecoderCatalog *DC,
T_BlkAction *fpBlockAction,
T_MBInfo *fpMBInfo,
U32 *pN,
T_IQ_INDEX *pRUN_INVERSE_Q,
const I32 iNumberOfGOBs,
const I32 iNumberOfMBs
);
// rearch
static long DibXY(ICDECOMPRESSEX FAR *lpicDecEx, LPINT lpiPitch, UINT yScale, BOOL bIsDCI);
static void GetDecoderOptions(T_H263DecoderCatalog *);
#define START_CODE 0xff18
static void ZeroFill(HPBYTE hpbY, HPBYTE hpbU, HPBYTE hpbV, int iPitch, U32 uWidth, U32 uHeight);
extern T_H263ColorConvertorCatalog ColorConvertorCatalog[];
extern void BlockCopy(
U32 uDstBlock,
U32 uSrcBlock);
extern void BlockEdgeFilter(U8 *YPlane, int Height, int Width, int Pitch, T_BlkAction *lpBlockAction);
LRESULT H263InitDecoderGlobal(void)
{ //For 32-bit decoder, this is empty for now, 7/29/95
//need to add code for 16 bit version.
return ICERR_OK;
}
/////////////////////////////////////////////////////////////////////////
//
// H263InitializeBlockActionStream
//
// Initialize the block action stream
//
static void H263InitializeBlockActionStream(
T_H263DecoderCatalog * DC)
{
U8 FAR * pu8;
U32 uFrameHeight = DC->uFrameHeight;
U32 uFrameWidth = DC->uFrameWidth;
U32 uCurBlock;
U32 uRefBlock;
U32 uBBlock;
U32 uYOffset;
U32 uUOffset;
U32 uVOffset;
U32 x;
U32 y;
U32 g;
U32 uPitch16;
U32 uPitch8;
U32 uYUpdate;
U32 uUVUpdate;
U32 uBlkNumber;
T_BlkAction FAR * fpBlockAction;
// Offsets for stepping thru GOBs for FCIF processing
static U32 uYGOBFCIFUpdate[12] =
{
(PITCH*3*16)-(FCIF_WIDTH>>1),
(FCIF_WIDTH>>1),
(PITCH*3*16)-(FCIF_WIDTH>>1),
(FCIF_WIDTH>>1),
(PITCH*3*16)-(FCIF_WIDTH>>1),
(FCIF_WIDTH>>1),
(PITCH*3*16)-(FCIF_WIDTH>>1),
(FCIF_WIDTH>>1),
(PITCH*3*16)-(FCIF_WIDTH>>1),
(FCIF_WIDTH>>1),
(PITCH*3*16)-(FCIF_WIDTH>>1),
(FCIF_WIDTH>>1),
};
static U32 uUVGOBFCIFUpdate[12] =
{
(PITCH*3*8)-(FCIF_WIDTH>>2),
(FCIF_WIDTH>>2),
(PITCH*3*8)-(FCIF_WIDTH>>2),
(FCIF_WIDTH>>2),
(PITCH*3*8)-(FCIF_WIDTH>>2),
(FCIF_WIDTH>>2),
(PITCH*3*8)-(FCIF_WIDTH>>2),
(FCIF_WIDTH>>2),
(PITCH*3*8)-(FCIF_WIDTH>>2),
(FCIF_WIDTH>>2),
(PITCH*3*8)-(FCIF_WIDTH>>2),
(FCIF_WIDTH>>2),
};
// assume that the width and height are multiples of 16
ASSERT((uFrameHeight & 0xF) == 0);
ASSERT((uFrameWidth & 0xF) == 0);
// Init uPitch16 and uPitch8
uPitch16 = PITCH*16;
uPitch8 = PITCH*8;
// Point to the allocated space
pu8 = (U8 FAR *) DC;
uCurBlock = (U32) (pu8 + DC->CurrFrame.X32_YPlane);
uRefBlock = (U32) (pu8 + DC->PrevFrame.X32_YPlane);
uBBlock = (U32) (pu8 + DC->PBFrame.X32_YPlane);
// skip the padding used for unconstrained motion vectors
uYOffset = Y_START;
uUOffset = DC->uSz_YPlane + UV_START;
uVOffset = uUOffset + (PITCH >> 1);
// start with block zero
uBlkNumber = 0;
if (uFrameWidth == QCIF_WIDTH)
{ /* if QCIF */
// calculate distance to the next row.
uYUpdate = (16 * PITCH) - uFrameWidth;
uUVUpdate = (8 * PITCH) - (uFrameWidth >> 1);
// Initialize the array
fpBlockAction = (T_BlkAction FAR *) (pu8 + DC->X16_BlkActionStream);
for (y = 0 ; y < uFrameHeight ; y += 16) {
for (x = 0 ; x < uFrameWidth ; x += 16) {
// Four Y Blocks
// Y0 Y1
// Y2 Y3
fpBlockAction->pCurBlock = uCurBlock + uYOffset;
fpBlockAction->pRefBlock = uRefBlock + uYOffset;
fpBlockAction->pBBlock = uBBlock + uYOffset;
fpBlockAction->u8BlkType = BT_EMPTY;
fpBlockAction->uBlkNumber = uBlkNumber++;
uYOffset += 8;
fpBlockAction++;
fpBlockAction->pCurBlock = uCurBlock + uYOffset;
fpBlockAction->pRefBlock = uRefBlock + uYOffset;
fpBlockAction->pBBlock = uBBlock + uYOffset;
fpBlockAction->u8BlkType = BT_EMPTY;
fpBlockAction->uBlkNumber = uBlkNumber++;
uYOffset = uYOffset - 8 + (8 * PITCH);
fpBlockAction++;
fpBlockAction->pCurBlock = uCurBlock + uYOffset;
fpBlockAction->pRefBlock = uRefBlock + uYOffset;
fpBlockAction->pBBlock = uBBlock + uYOffset;
fpBlockAction->u8BlkType = BT_EMPTY;
fpBlockAction->uBlkNumber = uBlkNumber++;
uYOffset += 8;
fpBlockAction++;
fpBlockAction->pCurBlock = uCurBlock + uYOffset;
fpBlockAction->pRefBlock = uRefBlock + uYOffset;
fpBlockAction->pBBlock = uBBlock + uYOffset;
fpBlockAction->u8BlkType = BT_EMPTY;
fpBlockAction->uBlkNumber = uBlkNumber++;
uYOffset = uYOffset + 8 - (8 * PITCH);
fpBlockAction++;
// One CR (V) Block
fpBlockAction->pCurBlock = uCurBlock + uVOffset;
fpBlockAction->pRefBlock = uRefBlock + uVOffset;
fpBlockAction->pBBlock = uBBlock + uVOffset;
fpBlockAction->u8BlkType = BT_EMPTY;
fpBlockAction->uBlkNumber = uBlkNumber++;
uVOffset += 8;
fpBlockAction++;
// One CB (U) Block
fpBlockAction->pCurBlock = uCurBlock + uUOffset;
fpBlockAction->pRefBlock = uRefBlock + uUOffset;
fpBlockAction->pBBlock = uBBlock + uUOffset;
fpBlockAction->u8BlkType = BT_EMPTY;
fpBlockAction->uBlkNumber = uBlkNumber++;
uUOffset += 8;
fpBlockAction++;
}
uYOffset += uYUpdate;
uUOffset += uUVUpdate;
uVOffset += uUVUpdate;
}
} /* end if QCIF */
if (uFrameWidth == FCIF_WIDTH)
{ /* if FCIF */
// calculate distance to the next row.
uYUpdate = (16 * PITCH) - (uFrameWidth >> 1);
uUVUpdate = (8 * PITCH) - (uFrameWidth >> 2);
// Initialize the array
fpBlockAction = (T_BlkAction FAR *) (pu8 + DC->X16_BlkActionStream);
for (g = 0; g < 12; g++) { /* for each GOB */
for (y = 0 ; y < 3 ; y++) { /* for each row in GOB */
for (x = 0 ; x < (uFrameWidth >> 1) ; x += 16) {
// Four Y Blocks
// Y0 Y1
// Y2 Y3
fpBlockAction->pCurBlock = uCurBlock + uYOffset;
fpBlockAction->pRefBlock = uRefBlock + uYOffset;
fpBlockAction->pBBlock = uBBlock + uYOffset;
fpBlockAction->u8BlkType = BT_EMPTY;
fpBlockAction->uBlkNumber = uBlkNumber++;
uYOffset += 8;
fpBlockAction++;
fpBlockAction->pCurBlock = uCurBlock + uYOffset;
fpBlockAction->pRefBlock = uRefBlock + uYOffset;
fpBlockAction->pBBlock = uBBlock + uYOffset;
fpBlockAction->u8BlkType = BT_EMPTY;
fpBlockAction->uBlkNumber = uBlkNumber++;
uYOffset = uYOffset - 8 + (8 * PITCH);
fpBlockAction++;
fpBlockAction->pCurBlock = uCurBlock + uYOffset;
fpBlockAction->pRefBlock = uRefBlock + uYOffset;
fpBlockAction->pBBlock = uBBlock + uYOffset;
fpBlockAction->u8BlkType = BT_EMPTY;
fpBlockAction->uBlkNumber = uBlkNumber++;
uYOffset += 8;
fpBlockAction++;
fpBlockAction->pCurBlock = uCurBlock + uYOffset;
fpBlockAction->pRefBlock = uRefBlock + uYOffset;
fpBlockAction->pBBlock = uBBlock + uYOffset;
fpBlockAction->u8BlkType = BT_EMPTY;
fpBlockAction->uBlkNumber = uBlkNumber++;
uYOffset = uYOffset + 8 - (8 * PITCH);
fpBlockAction++;
// One CR (V) Block
fpBlockAction->pCurBlock = uCurBlock + uVOffset;
fpBlockAction->pRefBlock = uRefBlock + uVOffset;
fpBlockAction->pBBlock = uBBlock + uVOffset;
fpBlockAction->u8BlkType = BT_EMPTY;
fpBlockAction->uBlkNumber = uBlkNumber++;
uVOffset += 8;
fpBlockAction++;
// One CB (U) Block
fpBlockAction->pCurBlock = uCurBlock + uUOffset;
fpBlockAction->pRefBlock = uRefBlock + uUOffset;
fpBlockAction->pBBlock = uBBlock + uUOffset;
fpBlockAction->u8BlkType = BT_EMPTY;
fpBlockAction->uBlkNumber = uBlkNumber++;
uUOffset += 8;
fpBlockAction++;
}
uYOffset += uPitch16 - (uFrameWidth >> 1);
uUOffset += uPitch8 - (uFrameWidth >> 2);
uVOffset += uPitch8 - (uFrameWidth >> 2);
}
uYOffset -= uYGOBFCIFUpdate[g];
uUOffset -= uUVGOBFCIFUpdate[g];
uVOffset -= uUVGOBFCIFUpdate[g];
}
} /* end if FCIF */
} // end H263InitializeBlockActionStream()
/////////////////////////////////////////////////////////////////////////
//
// H261ReInitializeBlockActionStream
//
// ReInitialize the block action stream
//
static void H261ReInitializeBlockActionStream(
T_H263DecoderCatalog * DC)
{
U8 FAR * pu8;
U32 uFrameHeight = DC->uFrameHeight;
U32 uFrameWidth = DC->uFrameWidth;
U32 utemp;
U32 x;
U32 y;
U32 g;
T_BlkAction FAR * fpBlockAction;
pu8 = (U8 FAR *) DC;
if (uFrameWidth == QCIF_WIDTH)
{ /* if QCIF */
// Initialize the array
fpBlockAction = (T_BlkAction FAR *) (pu8 + DC->X16_BlkActionStream);
for (y = 0 ; y < uFrameHeight ; y += 16) {
for (x = 0 ; x < uFrameWidth ; x += 16) {
// Four Y Blocks
// Y0 Y1
// Y2 Y3
utemp = fpBlockAction->pCurBlock;
fpBlockAction->pCurBlock = fpBlockAction->pRefBlock;
fpBlockAction->pRefBlock = utemp;
fpBlockAction->i8MVX=0;
fpBlockAction->i8MVY=0;
fpBlockAction->u8BlkType = BT_EMPTY;
fpBlockAction++;
utemp = fpBlockAction->pCurBlock;
fpBlockAction->pCurBlock = fpBlockAction->pRefBlock;
fpBlockAction->pRefBlock = utemp;
fpBlockAction->i8MVX=0;
fpBlockAction->i8MVY=0;
fpBlockAction->u8BlkType = BT_EMPTY;
fpBlockAction++;
utemp = fpBlockAction->pCurBlock;
fpBlockAction->pCurBlock = fpBlockAction->pRefBlock;
fpBlockAction->pRefBlock = utemp;
fpBlockAction->i8MVX=0;
fpBlockAction->i8MVY=0;
fpBlockAction->u8BlkType = BT_EMPTY;
fpBlockAction++;
utemp = fpBlockAction->pCurBlock;
fpBlockAction->pCurBlock = fpBlockAction->pRefBlock;
fpBlockAction->pRefBlock = utemp;
fpBlockAction->i8MVX=0;
fpBlockAction->i8MVY=0;
fpBlockAction->u8BlkType = BT_EMPTY;
fpBlockAction++;
// One CR (V) Block
utemp = fpBlockAction->pCurBlock;
fpBlockAction->pCurBlock = fpBlockAction->pRefBlock;
fpBlockAction->pRefBlock = utemp;
fpBlockAction->i8MVX=0;
fpBlockAction->i8MVY=0;
fpBlockAction->u8BlkType = BT_EMPTY;
fpBlockAction++;
// One CB (U) Block
utemp = fpBlockAction->pCurBlock;
fpBlockAction->pCurBlock = fpBlockAction->pRefBlock;
fpBlockAction->pRefBlock = utemp;
fpBlockAction->i8MVX=0;
fpBlockAction->i8MVY=0;
fpBlockAction->u8BlkType = BT_EMPTY;
fpBlockAction++;
}
}
} /* end if QCIF */
if (uFrameWidth == FCIF_WIDTH)
{ /* if FCIF */
// Initialize the array
fpBlockAction = (T_BlkAction FAR *) (pu8 + DC->X16_BlkActionStream);
for (g = 0; g < 12; g++) { /* for each GOB */
for (y = 0 ; y < 3 ; y++) { /* for each row in GOB */
for (x = 0 ; x < (uFrameWidth >> 1) ; x += 16) {
// Four Y Blocks
// Y0 Y1
// Y2 Y3
utemp = fpBlockAction->pCurBlock;
fpBlockAction->pCurBlock = fpBlockAction->pRefBlock;
fpBlockAction->pRefBlock = utemp;
fpBlockAction->i8MVX=0;
fpBlockAction->i8MVY=0;
fpBlockAction->u8BlkType = BT_EMPTY;
fpBlockAction++;
utemp = fpBlockAction->pCurBlock;
fpBlockAction->pCurBlock = fpBlockAction->pRefBlock;
fpBlockAction->pRefBlock = utemp;
fpBlockAction->i8MVX=0;
fpBlockAction->i8MVY=0;
fpBlockAction->u8BlkType = BT_EMPTY;
fpBlockAction++;
utemp = fpBlockAction->pCurBlock;
fpBlockAction->pCurBlock = fpBlockAction->pRefBlock;
fpBlockAction->pRefBlock = utemp;
fpBlockAction->i8MVX=0;
fpBlockAction->i8MVY=0;
fpBlockAction->u8BlkType = BT_EMPTY;
fpBlockAction++;
utemp = fpBlockAction->pCurBlock;
fpBlockAction->pCurBlock = fpBlockAction->pRefBlock;
fpBlockAction->pRefBlock = utemp;
fpBlockAction->i8MVX=0;
fpBlockAction->i8MVY=0;
fpBlockAction->u8BlkType = BT_EMPTY;
fpBlockAction++;
// One CR (V) Block
utemp = fpBlockAction->pCurBlock;
fpBlockAction->pCurBlock = fpBlockAction->pRefBlock;
fpBlockAction->pRefBlock = utemp;
fpBlockAction->i8MVX=0;
fpBlockAction->i8MVY=0;
fpBlockAction->u8BlkType = BT_EMPTY;
fpBlockAction++;
// One CB (U) Block
utemp = fpBlockAction->pCurBlock;
fpBlockAction->pCurBlock = fpBlockAction->pRefBlock;
fpBlockAction->pRefBlock = utemp;
fpBlockAction->i8MVX=0;
fpBlockAction->i8MVY=0;
fpBlockAction->u8BlkType = BT_EMPTY;
fpBlockAction++;
}
}
}
} /* end if FCIF */
} // end H261ReInitializeBlockActionStream()
//////////////////////////////////////////////////////////////////////////////
//
// H263InitDecoderInstance
//
// This function allocates and initializes the per-instance tables used by
// the H263 decoder. Note that in 16-bit Windows, the non-instance-specific
// global tables are copied to the per-instance data segment, so that they
// can be used without segment override prefixes.
//
LRESULT H263InitDecoderInstance(LPDECINST lpInst, int CodecID)
{
U32 u32YActiveHeight, u32YActiveWidth;
U32 u32UVActiveHeight, u32UVActiveWidth;
U32 u32YPlane, u32VUPlanes ,u32YVUPlanes,u32SizeBlkActionStream;
U32 uSizeBitStreamBuffer;
U32 uSizeDecTimingInfo;
U32 lOffset=0;
U32 u32TotalSize;
LRESULT iReturn= ICERR_OK;
U32 * pInitLimit;
U32 * pInitPtr;
// rearch
U32 u32SizeT_IQ_INDEXBuffer, u32SizepNBuffer, u32SizeMBInfoStream; // NEW
// rearch
T_H263DecoderCatalog * DC;
U8 * P32Inst;
SECURITY_ATTRIBUTES EventAttributes; // Used with Snapshot.
if(IsBadWritePtr((LPVOID)lpInst, sizeof(DECINSTINFO)))
{
DBOUT("ERROR :: H263InitDecoderInstance :: ICERR_BADPARAM");
iReturn = ICERR_BADPARAM;
goto done;
}
if ((CodecID == YUV12_CODEC && (lpInst->yres > 480 || lpInst->xres > 640)) ||
(CodecID == H263_CODEC && (lpInst->yres > 288 || lpInst->xres > 352)))
{
DBOUT("ERROR :: H263InitDecoderInstance :: ICERR_BADSIZE");
iReturn = ICERR_BADSIZE;
goto done;
}
if (CodecID == YUV12_CODEC)
{
/* The active height and width must be padded to a multiple of 8
* since the adjustpels routine relies on it.
*/
u32YActiveHeight = ((lpInst->yres + 0x7) & (~ 0x7));
u32YActiveWidth = ((lpInst->xres + 0x7) & (~ 0x7));
u32UVActiveHeight = ((lpInst->yres + 0xF) & (~ 0xF)) >> 1;
u32UVActiveWidth = ((lpInst->xres + 0xF) & (~ 0xF)) >> 1;
u32YPlane = u32YActiveWidth * u32YActiveHeight;
u32VUPlanes = u32UVActiveWidth * u32UVActiveHeight * 2;
u32YVUPlanes = u32YPlane + u32VUPlanes;
// added for I420 output support
// wasn't allocating enough memory for YUV12 output, no color convert case
// calculate the block action stream size. The Y portion has one block for
// every 8x8 region. The U and V portion has one block for every 16x16 region.
// We also want to make sure that the size is aligned to a cache line.
u32SizeBlkActionStream = (lpInst->xres >> 3) * (lpInst->yres >> 3);
u32SizeBlkActionStream += ((lpInst->xres >> 4) * (lpInst->yres >> 4)) * 2;
u32SizeBlkActionStream *= sizeof (T_BlkAction);
u32SizeBlkActionStream = (u32SizeBlkActionStream + 31) & ~0x1F;
// calculate the bitstream buffer size. We copy the input data to a buffer
// in our space because we read ahead up to 4 bytes beyond the end of the
// input data. The input data size changes for each frame. So the following
// is a very safe upper bound estimate.
// Add + 2 for extra zeros for start code emulation. AKK
uSizeBitStreamBuffer = lpInst->yres * lpInst->xres + 2;
#ifdef DECODE_STATS
uSizeDecTimingInfo = DEC_TIMING_INFO_FRAME_COUNT * sizeof (DEC_TIMING_INFO);
#else
uSizeDecTimingInfo = 0;
#endif
u32TotalSize = INSTANCE_DATA_FIXED_SIZE +
u32SizeBlkActionStream +
u32YVUPlanes + // current frame
u32YVUPlanes + // prev frame
BLOCK_BUFFER_SIZE +
FILTER_BLOCK_BUFFER_SIZE +
uSizeBitStreamBuffer + // input data
uSizeDecTimingInfo +
0x1F;
// u32TotalSize = 512L + 0x1FL; /* Just enough space for Decoder Catalog. */
}
else
{
ASSERT(CodecID == H263_CODEC);
u32YActiveHeight = lpInst->yres + UMV_EXPAND_Y + UMV_EXPAND_Y ;
u32YActiveWidth = lpInst->xres + UMV_EXPAND_Y + UMV_EXPAND_Y ;
u32UVActiveHeight = u32YActiveHeight/2;
u32UVActiveWidth = u32YActiveWidth /2;
u32YPlane = PITCH * u32YActiveHeight;
u32VUPlanes = PITCH * u32UVActiveHeight;
u32YVUPlanes = u32YPlane + u32VUPlanes;
// calculate the block action stream size. The Y portion has one block for
// every 8x8 region. The U and V portion has one block for every 16x16 region.
// We also want to make sure that the size is aligned to a cache line.
u32SizeBlkActionStream = (lpInst->xres >> 3) * (lpInst->yres >> 3);
u32SizeBlkActionStream += ((lpInst->xres >> 4) * (lpInst->yres >> 4)) * 2;
u32SizeBlkActionStream *= sizeof (T_BlkAction);
u32SizeBlkActionStream = (u32SizeBlkActionStream + 31) & ~0x1F;
// calculate the bitstream buffer size. We copy the input data to a buffer
// in our space because we read ahead up to 4 bytes beyond the end of the
// input data. The input data size changes for each frame. So the following
// is a very safe upper bound estimate.
// Add + 2 for extra zeros for start code emulation. AKK
// Add some additional to make sure stay dword align (rearch)
uSizeBitStreamBuffer = (lpInst->yres * lpInst->xres + 2 + 4) & ~0x3;
// rearch
// calculate sizes of NEW data structures
u32SizeT_IQ_INDEXBuffer = (lpInst->xres)*(lpInst->yres*2)*
sizeof(T_IQ_INDEX);
u32SizepNBuffer = (lpInst->xres>>4)*(lpInst->yres>>4)*sizeof(U32)*6;
u32SizeMBInfoStream = (lpInst->xres>>4)*(lpInst->yres>>4)*
sizeof(T_MBInfo);
// rearch
#ifdef DECODE_STATS
uSizeDecTimingInfo = DEC_TIMING_INFO_FRAME_COUNT * sizeof (DEC_TIMING_INFO);
#else
uSizeDecTimingInfo = 0;
#endif
u32TotalSize = INSTANCE_DATA_FIXED_SIZE +
u32SizeBlkActionStream +
u32YVUPlanes + // current frame
u32YVUPlanes + // prev frame
BLOCK_BUFFER_SIZE +
FILTER_BLOCK_BUFFER_SIZE +
uSizeBitStreamBuffer + // input data
u32SizeT_IQ_INDEXBuffer + // NEW
u32SizepNBuffer + // NEW
u32SizeMBInfoStream + // PB-NEW
uSizeDecTimingInfo +
0x1F;
}
/* If already initialized, terminate this instance before allocating
* another.
*/
if(lpInst->Initialized == TRUE)
{
H263TermDecoderInstance(lpInst);
}
// allocate the memory for the instance
lpInst->pDecoderInst = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
u32TotalSize);
if (lpInst->pDecoderInst == NULL)
{
DBOUT("ERROR :: H263InitDecoderInstance :: ICERR_MEMORY");
iReturn = ICERR_MEMORY;
goto done;
}
//build the decoder catalog
P32Inst = (U8 *) ((((U32) lpInst->pDecoderInst) + 31) & ~0x1F);
//The catalog of per-instance data is at the start of the per-instance data.
DC = (T_H263DecoderCatalog *) P32Inst;
DC->DecoderType = CodecID;
DC->uFrameHeight = lpInst->yres;
DC->uFrameWidth = lpInst->xres;
DC->uYActiveHeight = u32YActiveHeight;
DC->uYActiveWidth = u32YActiveWidth;
DC->uUVActiveHeight = u32UVActiveHeight;
DC->uUVActiveWidth = u32UVActiveWidth;
DC->uSz_YPlane = u32YPlane;
DC->uSz_VUPlanes = u32VUPlanes;
DC->uSz_YVUPlanes = u32YVUPlanes;
DC->BrightnessSetting = H26X_DEFAULT_BRIGHTNESS;
DC->ContrastSetting = H26X_DEFAULT_CONTRAST;
DC->SaturationSetting = H26X_DEFAULT_SATURATION;
DC->iAPColorConvPrev = 0;
DC->pAPInstPrev = NULL; // assume no previous AP instance.
DC->p16InstPostProcess = NULL;
DC->a16InstPostProcess = NULL;
DC->bReadSrcFormat = 0;
EventAttributes.nLength = sizeof(SECURITY_ATTRIBUTES);
EventAttributes.lpSecurityDescriptor = NULL;
EventAttributes.bInheritHandle = FALSE;
DC->SnapshotEvent = CreateEvent(&EventAttributes, TRUE, FALSE, NULL);
/* Get the Options
*/
GetDecoderOptions(DC);
if (CodecID == H263_CODEC)
{
lOffset = INSTANCE_DATA_FIXED_SIZE;
DC->Ticker = 127;
//instance dependent table here
DC->X16_BlkActionStream = lOffset;
lOffset += u32SizeBlkActionStream;
DC-> CurrFrame.X32_YPlane = lOffset;
lOffset += DC->uSz_YPlane;
DC->CurrFrame.X32_VPlane = lOffset;
DC->CurrFrame.X32_UPlane = DC->CurrFrame.X32_VPlane + U_OFFSET;
lOffset += DC->uSz_VUPlanes;
//no padding is needed
DC->PrevFrame.X32_YPlane = lOffset;
lOffset += DC->uSz_YPlane;
DC->PrevFrame.X32_VPlane = lOffset;
DC->PrevFrame.X32_UPlane = DC->PrevFrame.X32_VPlane + U_OFFSET;
lOffset += DC->uSz_VUPlanes;
DC->uMBBuffer = lOffset;
lOffset += BLOCK_BUFFER_SIZE;
DC->uFilterBBuffer = lOffset;
lOffset += FILTER_BLOCK_BUFFER_SIZE;
// Bitstream
ASSERT((lOffset & 0x3) == 0); // DWORD alignment
DC->X32_BitStream = lOffset;
lOffset += uSizeBitStreamBuffer;
DC->uSizeBitStreamBuffer = uSizeBitStreamBuffer;
// rearch
ASSERT((lOffset & 0x3) == 0); // DWORD alignment
DC->X32_InverseQuant = lOffset;
lOffset += u32SizeT_IQ_INDEXBuffer;
ASSERT((lOffset & 0x3) == 0); // DWORD alignment
DC->X32_pN = lOffset;
lOffset += u32SizepNBuffer;
ASSERT((lOffset & 0x3) == 0); // DWORD alignment
DC->X32_uMBInfoStream = lOffset;
lOffset += u32SizeMBInfoStream;
// rearch
#ifdef DECODE_STATS
// Decode Timing Info
DC->X32_DecTimingInfo = lOffset;
lOffset += uSizeDecTimingInfo;
#endif
// init the data
ASSERT((U32)lOffset <= u32TotalSize);
pInitLimit = (U32 *) (P32Inst + lOffset);
pInitPtr = (U32 *) (P32Inst + DC->CurrFrame.X32_YPlane);
for (;pInitPtr < pInitLimit;pInitPtr++) *pInitPtr =0;
// Fill the Y,U,V Previous Frame space with black, this way
// even if we lost an I frame, the background will remain black
ZeroFill((HPBYTE)P32Inst + DC->PrevFrame.X32_YPlane + Y_START,
(HPBYTE)P32Inst + DC->PrevFrame.X32_UPlane + UV_START,
(HPBYTE)P32Inst + DC->PrevFrame.X32_VPlane + UV_START,
PITCH,
DC->uFrameWidth,
DC->uFrameHeight);
H263InitializeBlockActionStream(DC);
} // not YVU9
lpInst->Initialized = TRUE;
iReturn = ICERR_OK;
done:
return iReturn;
}
/***********************************************************************
* ZeroFill
* Fill the YVU data area with black.
***********************************************************************/
static void ZeroFill(HPBYTE hpbY, HPBYTE hpbU, HPBYTE hpbV, int iPitch, U32 uWidth, U32 uHeight)
{
U32 w,h;
int y,u,v;
U32 uNext;
HPBYTE pY, pU, pV;
y = 32;
uNext = iPitch - uWidth;
for (h = 0 ; h < uHeight ; h++) {
pY = hpbY;
for (w = 0; w < uWidth ; w++) {
*hpbY++ = (U8)16;
}
hpbY += uNext;
}
uWidth = uWidth / 2;
uHeight = uHeight / 2;
uNext = iPitch - uWidth;
for (h = 0 ; h < uHeight ; h++) {
pV = hpbV;
pU = hpbU;
for (w = 0; w < uWidth ; w++) {
*hpbV++ = (U8)128;
*hpbU++ = (U8)128;
}
hpbV += uNext;
hpbU += uNext;
}
}
//***********************************************************************
//
// TestFill
//
// Fill the YVU data area with a test pattern.
//
#if 0
static void
TestFill(
HPBYTE hpbY,
HPBYTE hpbU,
HPBYTE hpbV,
int iPitch,
U32 uWidth,
U32 uHeight)
{
U32 w,h;
int y,u,v;
U32 uNext;
HPBYTE pY, pU, pV;
y = 32;
uNext = iPitch - uWidth;
for (h = 0 ; h < uHeight ; h++) {
pY = hpbY;
for (w = 0; w < uWidth ; w++) {
*hpbY++ = (U8) (y + (w & ~0xF));
}
hpbY += uNext;
}
uWidth = uWidth / 2;
uHeight = uHeight / 2;
u = 0x4e * 2;
v = 44;
uNext = iPitch - uWidth;
for (h = 0 ; h < uHeight ; h++) {
pV = hpbV;
pU = hpbU;
for (w = 0; w < uWidth ; w++) {
*hpbV++ = (U8) v;
*hpbU++ = (U8) u;
}
hpbV += uNext;
hpbU += uNext;
}
} /* end TestFill */
static void
TestFillUV(
HPBYTE hpbU,
HPBYTE hpbV,
int iPitch,
U32 uWidth,
U32 uHeight)
{
U32 w,h;
int u,v;
U32 uNext;
HPBYTE pU, pV;
uWidth = uWidth / 2;
uHeight = uHeight / 2;
u = 128;
v = 128;
uNext = iPitch - uWidth;
for (h = 0 ; h < uHeight ; h++) {
pV = hpbV;
pU = hpbU;
for (w = 0; w < uWidth ; w++) {
*hpbV++ = (U8) v;
*hpbU++ = (U8) u;
}
hpbV += uNext;
hpbU += uNext;
}
} /* end TestFill */
#endif
//*********************************************************************
//H263Decompress -- This function drives the decompress
// and display of one frame
//*********************************************************************
LRESULT H263Decompress(
LPDECINST lpInst,
ICDECOMPRESSEX FAR * lpicDecEx,
BOOL bIsDCI)
{
LRESULT iReturn = ICERR_ERROR;
U8 FAR * fpSrc;
U8 FAR * P32Inst;
U8 FAR * fpu8MaxPtr;
T_H263DecoderCatalog * DC = NULL;
int iNumberOfGOBs;
int iNumberOfMBs;
T_BlkAction FAR * fpBlockAction;
LONG lOutput;
int intPitch;
U32 uNewOffsetToLine0;
U16 u16NewFrameHeight;
int bShapingFlag;
int uYPitch;
int uUVPitch;
U8 bMirror;
HPBYTE pSource, pDestination;
U32 utemp;
// rearch
T_IQ_INDEX * pRUN_INVERSE_Q;
U32 * pN;
T_MBInfo FAR * fpMBInfo;
I32 gob_start = 1, mb_start = 1;
// rearch
/* new variables added when change to color convertor/bef */
U32 uYPlane, uVPlane, uUPlane;
U8 *pFrame, *lpAligned;
T_H26X_RTP_BSINFO_TRAILER *pBsTrailer;
/* the following is for MB Checksum */
U32 uReadChecksum = 0;
#ifdef DECODE_STATS
U32 uStartLow;
U32 uStartHigh;
U32 uElapsed;
U32 uBefore;
U32 uDecodeFrameSum = 0;
U32 uHeadersSum = 0;
U32 uMemcpySum = 0;
U32 uFrameCopySum = 0;
U32 uOutputCCSum = 0;
U32 uInitBlkActStrSum = 0;
U32 uBEFSum = 0;
int bTimingThisFrame = 0;
DEC_TIMING_INFO * pDecTimingInfo = NULL;
#endif
#ifdef CHECKSUM_PICTURE
/* the following is for Picture Checksum */
YVUCheckSum pReadYVUCksum;
YVUCheckSum YVUChkSum;
U32 uCheckSumValid = 0; // flag to skip checksum check if
// encoder calling decoder before
// checksum valid
#endif
/* The following are used for reading bits */
U32 uWork;
U32 uBitsReady;
BITSTREAM_STATE bsState;
BITSTREAM_STATE FAR * fpbsState = &bsState;
#ifdef SKIP_DECODE
TBD("Skipping Decode");
iReturn = ICERR_OK;
goto done;
#endif
/* check the input pointers
*/
if (IsBadWritePtr((LPVOID)lpInst, sizeof(DECINSTINFO))||
IsBadReadPtr((LPVOID)lpicDecEx, sizeof(ICDECOMPRESSEX)))
{
DBOUT("ERROR :: H263Decompress :: ICERR_BADPARAM");
iReturn = ICERR_BADPARAM;
goto done;
}
/* Check for a bad length
*/
if (lpicDecEx->lpbiSrc->biSizeImage == 0) {
DBOUT("ERROR :: H263Decompress :: ICERR_BADIMAGESIZE");
iReturn = ICERR_BADIMAGESIZE;
goto done;
}
/* Lock the memory
*/
if (lpInst->pDecoderInst == NULL)
{
DBOUT("ERROR :: H263Decompress :: ICERR_MEMORY");
iReturn = ICERR_MEMORY;
goto done;
}
/* Set the frame mirroring flag
*/
bMirror = FALSE;
if (lpicDecEx->lpbiDst != 0)
{
if(lpicDecEx->lpbiSrc->biWidth * lpicDecEx->lpbiDst->biWidth < 0)
bMirror = TRUE;
}
/* for testing */
/* bMirror = TRUE; */
/* Build the decoder catalog pointer
*/
P32Inst = (U8 FAR *) ((((U32) lpInst->pDecoderInst) + 31) & ~0x1F);
DC = (T_H263DecoderCatalog FAR *) P32Inst;
if (DC->DecoderType == H263_CODEC)
{
#ifdef DECODE_STATS
if ((DC->uStatFrameCount < DEC_TIMING_INFO_FRAME_COUNT) &&
(DC->ColorConvertor != YUV12ForEnc))
{
ASSERT(DC->X32_DecTimingInfo > 0);
DC->pDecTimingInfo = (DEC_TIMING_INFO FAR *)( ((U8 FAR *)P32Inst) + DC->X32_DecTimingInfo );
TIMER_START(bTimingThisFrame,uStartLow,uStartHigh);
ASSERT(bTimingThisFrame);
DC->uStartLow = uStartLow;
DC->uStartHigh = uStartHigh;
}
else
{
DC->pDecTimingInfo = (DEC_TIMING_INFO FAR *) NULL;
ASSERT(!bTimingThisFrame);
}
DC->bTimingThisFrame = bTimingThisFrame;
#endif
/* Is there room to copy the bitstream? We could at most add 2 (zeros) and 3
padding bytes for DWORD alignment to the original bitstream */\
ASSERT(lpicDecEx->lpbiSrc->biSizeImage + 5 <= DC->uSizeBitStreamBuffer);
if ((lpicDecEx->lpbiSrc->biSizeImage + 5) > DC->uSizeBitStreamBuffer)
{
DBOUT("ERROR :: H263Decompress :: ICERR_ERROR: not enough room for bitstream");
iReturn = ICERR_ERROR;
goto done;
}
/* Copy the source data to the bitstream region.
* OPTIMIZE: Integrate MRV's BLKCOPY.ASM
*/
#ifdef DECODE_STATS
TIMER_BEFORE(bTimingThisFrame,uStartLow,uStartHigh,uBefore);
#endif
fpSrc = (U8 FAR *)(P32Inst + DC->X32_BitStream);
// New: we will first look for an EBS from the PPM. If there is one, then we will
// insert two bytes of zero between the H.261 bistream and the EBS part with
// DWORD alignment and update the total bitstream size. If no EBS is found,
// then we proceed as before.
DC->iVerifiedBsExt = FALSE;
DC->Sz_BitStream = lpicDecEx->lpbiSrc->biSizeImage ;
H26XRTP_VerifyBsInfoStream(DC,(U8 *) lpicDecEx->lpSrc,lpicDecEx->lpbiSrc->biSizeImage);
if (!DC->iValidBsExt)
{
memcpy((char FAR *)fpSrc, (const char FAR *) lpicDecEx->lpSrc, lpicDecEx->lpbiSrc->biSizeImage);
// also copy 16 bits of zero for end of frame detection
fpSrc[lpicDecEx->lpbiSrc->biSizeImage] = 0;
fpSrc[lpicDecEx->lpbiSrc->biSizeImage+1] = 0;
DC->Sz_BitStream += 2;
fpu8MaxPtr = fpSrc;
fpu8MaxPtr += (lpicDecEx->lpbiSrc->biSizeImage + 2 - 1);
}
else
{
// First the H.261 stream data - relying on PPM to fill the compressed size correctly
// in the trailer.
pBsTrailer = ( (T_H26X_RTP_BSINFO_TRAILER *)(DC->pBsTrailer) );
memcpy((char FAR *)fpSrc, (const char FAR *) lpicDecEx->lpSrc, pBsTrailer->uCompressedSize);
// Now write out two bytes of zeros at the end of the H.261 bitstream
fpSrc[pBsTrailer->uCompressedSize] = 0;
fpSrc[pBsTrailer->uCompressedSize + 1] = 0;
// Now tack on the EBS after DWORD alignment.
lpAligned = (U8 *) ( (U32) (fpSrc + (pBsTrailer->uCompressedSize + 2) + 3) &
0xfffffffc);
memcpy(lpAligned, DC->pBsInfo, DC->uNumOfPackets*sizeof(T_RTP_H261_BSINFO));
memcpy(lpAligned + DC->uNumOfPackets*sizeof(T_RTP_H261_BSINFO), DC->pBsTrailer,
sizeof(T_H26X_RTP_BSINFO_TRAILER));
// update lpicDecEx->lpbiSrc->biSizeImage
DC->Sz_BitStream = lpAligned + DC->uNumOfPackets*sizeof(T_RTP_H261_BSINFO) +
sizeof(T_H26X_RTP_BSINFO_TRAILER) - fpSrc;
fpu8MaxPtr = fpSrc;
fpu8MaxPtr += (pBsTrailer->uCompressedSize + 2 - 1);
}
#ifdef DECODE_STATS
TIMER_AFTER_P5(bTimingThisFrame,uStartLow,uStartHigh,uBefore,uElapsed,uMemcpySum)
#endif
/* Initialize the bit stream reader
*/
GET_BITS_INIT(uWork, uBitsReady);
// rearch
// Initialize pointers to data structures which carry info
// between passes
pRUN_INVERSE_Q = (T_IQ_INDEX *)(P32Inst + DC->X32_InverseQuant);
pN = (U32 *)(P32Inst + DC->X32_pN);
fpMBInfo = (T_MBInfo FAR *) (P32Inst + DC->X32_uMBInfoStream);
// rearch
// #ifdef LOSS_RECOVERY
#if 1
DC->iVerifiedBsExt = FALSE;
#endif
/* Decode the Picture Header */
#ifdef DECODE_STATS
TIMER_BEFORE(bTimingThisFrame,uStartLow,uStartHigh,uBefore);
#endif
#ifdef CHECKSUM_PICTURE
iReturn = H263DecodePictureHeader(DC, fpSrc, uBitsReady, uWork, fpbsState, &pReadYVUCksum, &uCheckSumValid);
#else
iReturn = H263DecodePictureHeader(DC, fpSrc, uBitsReady, uWork, fpbsState);
#endif
if (iReturn != ICERR_OK)
{
DBOUT("ERROR :: H263Decompress :: Error reading the picture header");
goto done;
}
#ifdef DECODE_STATS
TIMER_AFTER_P5(bTimingThisFrame,uStartLow,uStartHigh,uBefore,uElapsed,uHeadersSum)
#endif
/* Set a limit for testing for bitstream over-run
*/
/* For each GOB do... */
iNumberOfGOBs = iNumberOfGOBsBySourceFormat[DC->uSrcFormat];
iNumberOfMBs = iNumberOfMBsInAGOBBySourceFormat[DC->uSrcFormat];
/* In H263 a GOB is a single row of MB, and a MB is 16x16 */
/* In H261 a GOB is 33 MBs, and a MB is 16x16 */
/* Order of GOBs depends on source format */
if (DC->uSrcFormat == SRC_FORMAT_QCIF)
{
ASSERT(((U32)iNumberOfGOBs * 3 * 16) == DC->uFrameHeight);
if (((U32)iNumberOfGOBs * 3 * 16) != DC->uFrameHeight)
{
DBOUT("ERROR :: H263Decompress :: Error matching picture header SRC field and actual frame height");
iReturn = ICERR_ERROR;
goto done;
}
ASSERT(((U32)iNumberOfMBs / 3 * 16) == DC->uFrameWidth);
if (((U32)iNumberOfMBs / 3 * 16) != DC->uFrameWidth)
{
DBOUT("ERROR :: H263Decompress :: Error matching picture header SRC field and actual frame width");
iReturn = ICERR_ERROR;
goto done;
}
}
if (DC->uSrcFormat == SRC_FORMAT_CIF)
{
ASSERT(((U32)iNumberOfGOBs / 2 * 3 * 16) == DC->uFrameHeight);
if (((U32)iNumberOfGOBs / 2 * 3 * 16) != DC->uFrameHeight)
{
DBOUT("ERROR :: H263Decompress :: Error matching picture header SRC field and actual frame height");
iReturn = ICERR_ERROR;
goto done;
}
ASSERT(((U32)iNumberOfMBs / 3 * 2 * 16) == DC->uFrameWidth);
if (((U32)iNumberOfMBs / 3 * 2 * 16) != DC->uFrameWidth)
{
DBOUT("ERROR :: H263Decompress :: Error matching picture header SRC field and actual frame width");
iReturn = ICERR_ERROR;
goto done;
}
}
fpBlockAction = (T_BlkAction FAR *) (P32Inst + DC->X16_BlkActionStream);
// rearch
// H261, re initialize the block action stream for entire Frame
// at end of H263Decompress. High bit is set in BlockType to
// indicate if need to do BEF so can't re-init between GOBs.
// H261ReInitializeBlockActionStream(DC);
/*****************************************************************
FIRST PASS - bitream parsing and IDCT prep work
***************************************************************/
// #ifndef LOSS_RECOVERY
#if 0
iReturn = IAPass1ProcessFrame(DC,
fpBlockAction,
fpMBInfo,
fpbsState,
fpu8MaxPtr,
pN,
pRUN_INVERSE_Q,
iNumberOfGOBs,
iNumberOfMBs,
gob_start,
mb_start);
#else
iReturn = IAPass1ProcessFrameRTP(DC,
fpBlockAction,
fpMBInfo,
fpbsState,
fpu8MaxPtr,
pN,
pRUN_INVERSE_Q,
iNumberOfGOBs,
iNumberOfMBs,
gob_start,
mb_start);
#endif
if (iReturn != ICERR_OK) {
DBOUT("H261Decompress : Pass 1 error");
goto done;
}
/*****************************************************************
SECOND PASS - IDCT and motion compensation (MC)
*****************************************************************/
fpBlockAction = (T_BlkAction FAR *)(P32Inst + DC->X16_BlkActionStream);
pRUN_INVERSE_Q = (T_IQ_INDEX *)(P32Inst + DC->X32_InverseQuant);
pN = (U32 *)(P32Inst + DC->X32_pN);
fpMBInfo = (T_MBInfo FAR *)(P32Inst + DC->X32_uMBInfoStream);
IAPass2ProcessFrame(DC,
fpBlockAction,
fpMBInfo,
pN,
pRUN_INVERSE_Q,
iNumberOfGOBs,
iNumberOfMBs);
// rearch
//Prepare which frame to display for inter frames
DC->DispFrame.X32_YPlane = DC->CurrFrame.X32_YPlane;
DC->DispFrame.X32_VPlane = DC->CurrFrame.X32_VPlane;
DC->DispFrame.X32_UPlane = DC->CurrFrame.X32_UPlane;
utemp = DC->CurrFrame.X32_YPlane;
DC->CurrFrame.X32_YPlane = DC->PrevFrame.X32_YPlane;
DC->PrevFrame.X32_YPlane = utemp;
utemp = DC->CurrFrame.X32_VPlane ;
DC->CurrFrame.X32_VPlane = DC->PrevFrame.X32_VPlane;
DC->PrevFrame.X32_VPlane = utemp;
utemp = DC->CurrFrame.X32_UPlane ;
DC->CurrFrame.X32_UPlane = DC->PrevFrame.X32_UPlane;
DC->PrevFrame.X32_UPlane = utemp;
#ifdef CHECKSUM_PICTURE
if (uCheckSumValid)
{
/* compute and compare picture checksum data */
iReturn = H261ComputePictureCheckSum(P32Inst, &YVUChkSum);
iReturn = H261ComparePictureCheckSum(&YVUChkSum, &pReadYVUCksum);
}
#endif
} /* end if (DC->DecoderType == H263_CODEC) */
else
{
ASSERT(DC->DecoderType == YUV12_CODEC);
DC->DispFrame.X32_YPlane = DC->CurrFrame.X32_YPlane;
DC->DispFrame.X32_VPlane = DC->CurrFrame.X32_VPlane;
DC->DispFrame.X32_UPlane = DC->CurrFrame.X32_UPlane;
}
/* Return if there is no need to update screen yet.
*/
if ((lpicDecEx->dwFlags & ICDECOMPRESS_HURRYUP)
|| (lpicDecEx->dwFlags & ICDECOMPRESS_PREROLL))
{
DBOUT("H261Decompress : Display suppressed, HURRYUP or PREROLL");
iReturn = ICERR_DONTDRAW;
goto done;
}
#if 0
/* Fill the Y,U,V Current Frame space with a test pattern
*/
TestFill((HPBYTE)P32Inst + DC->CurrFrame.X32_YPlane + Y_START,
(HPBYTE)P32Inst + DC->CurrFrame.X32_UPlane + UV_START,
(HPBYTE)P32Inst + DC->CurrFrame.X32_VPlane + UV_START,
PITCH,
DC->uFrameWidth,
DC->uFrameHeight);
#endif
#if MAKE_GRAY
/* Fill the U,V Current Frame space with a test pattern
*/
TestFillUV((HPBYTE)P32Inst + DC->CurrFrame.X32_UPlane + UV_START,
(HPBYTE)P32Inst + DC->CurrFrame.X32_VPlane + UV_START,
PITCH,
DC->uFrameWidth,
DC->uFrameHeight);
#endif
/* Special case the YUV12 for the encoder because it should not include
* BEF, Shaping or aspect ratio correction...
*/
if (DC->ColorConvertor == YUV12ForEnc)
{
H26x_YUV12ForEnc ((HPBYTE)P32Inst,
DC->PrevFrame.X32_YPlane + Y_START,
DC->PrevFrame.X32_VPlane + UV_START,
DC->PrevFrame.X32_UPlane + UV_START,
DC->uFrameWidth,
DC->uFrameHeight,
PITCH,
(HPBYTE)lpicDecEx->lpDst,
(DWORD)Y_START,
(DWORD)(MAX_HEIGHT + 2L*UMV_EXPAND_Y) * PITCH + 8 + UV_START + PITCH / 2,
(DWORD)(MAX_HEIGHT + 2L*UMV_EXPAND_Y) * PITCH + 8 + UV_START);
iReturn = ICERR_OK;
goto done;
}
/* Copy Planes to Post Processing area if mirror and/or block edge filter.
*/
if (DC->DecoderType == H263_CODEC)
{
#ifdef DECODE_STATS
TIMER_BEFORE(bTimingThisFrame,uStartLow,uStartHigh,uBefore);
#endif
if(bMirror) { // copy with mirroring
pFrame = (U8 *)DC->p16InstPostProcess;
uYPlane = DC->PostFrame.X32_YPlane;
uUPlane = DC->PostFrame.X32_UPlane;
uVPlane = DC->PostFrame.X32_VPlane;
FrameMirror(((HPBYTE) P32Inst) + DC->DispFrame.X32_YPlane + Y_START,
((HPBYTE) DC->p16InstPostProcess) + DC->PostFrame.X32_YPlane,
DC->uFrameHeight,
DC->uFrameWidth,
PITCH);
FrameMirror(((HPBYTE) P32Inst)+ DC->DispFrame.X32_UPlane + UV_START,
((HPBYTE) DC->p16InstPostProcess) + DC->PostFrame.X32_UPlane,
DC->uFrameHeight/2,
DC->uFrameWidth/2,
PITCH);
FrameMirror(((HPBYTE) P32Inst)+ DC->DispFrame.X32_VPlane + UV_START,
((HPBYTE) DC->p16InstPostProcess) + DC->PostFrame.X32_VPlane,
DC->uFrameHeight/2,
DC->uFrameWidth/2,
PITCH);
}
else
{ /* no mirroring */
if ((DC->bUseBlockEdgeFilter) || (DC->bAdjustLuma) ||
(DC->bAdjustChroma))
{
/* copy for BEF */
pFrame = (U8 *)DC->p16InstPostProcess;
uYPlane = DC->PostFrame.X32_YPlane;
uUPlane = DC->PostFrame.X32_UPlane;
uVPlane = DC->PostFrame.X32_VPlane;
FrameCopy (((HPBYTE) P32Inst) +DC->DispFrame.X32_YPlane+Y_START,
((HPBYTE) DC->p16InstPostProcess) +DC->PostFrame.X32_YPlane,
DC->uFrameHeight,
DC->uFrameWidth,
PITCH);
FrameCopy (((HPBYTE) P32Inst)+DC->DispFrame.X32_UPlane+UV_START,
((HPBYTE) DC->p16InstPostProcess) +DC->PostFrame.X32_UPlane,
DC->uFrameHeight/2,
DC->uFrameWidth/2,
PITCH);
FrameCopy (((HPBYTE) P32Inst)+DC->DispFrame.X32_VPlane+UV_START,
((HPBYTE) DC->p16InstPostProcess) +DC->PostFrame.X32_VPlane,
DC->uFrameHeight/2,
DC->uFrameWidth/2,
PITCH);
} /* end if BEF on */
else
{
/* no BEF or mirror so don't need copy */
pFrame = (U8 *) DC;
uYPlane = DC->DispFrame.X32_YPlane + Y_START;
uUPlane = DC->DispFrame.X32_UPlane + UV_START;
uVPlane = DC->DispFrame.X32_VPlane + UV_START;
} /* end of else no BEF */
} /* end else no mirroring */
#ifdef DECODE_STATS
TIMER_AFTER_P5(bTimingThisFrame,uStartLow,uStartHigh,uBefore,uElapsed,uFrameCopySum)
#endif
uYPitch = PITCH;
uUVPitch = PITCH;
if (DC->bUseBlockEdgeFilter)
{
#ifdef DECODE_STATS
TIMER_BEFORE(bTimingThisFrame,uStartLow,uStartHigh,uBefore);
#endif
fpBlockAction=(T_BlkAction FAR *) (P32Inst+DC->X16_BlkActionStream);
BlockEdgeFilter(((HPBYTE) DC->p16InstPostProcess) + DC->PostFrame.X32_YPlane,
DC->uFrameHeight,
DC->uFrameWidth,
PITCH,
fpBlockAction);
#ifdef DECODE_STATS
TIMER_AFTER_P5(bTimingThisFrame,uStartLow,uStartHigh,uBefore,uElapsed,uBEFSum)
#endif
}
}
else
{ /* YUV12 */
const U32 uHeight = DC->uFrameHeight;
const U32 uWidth = DC->uFrameWidth;
const U32 uYPlaneSize = uHeight*uWidth;
if(bMirror) // mirroring and YUV12 need to do copy
{
pFrame = (U8 *)DC->p16InstPostProcess;
uYPlane = DC->PostFrame.X32_YPlane;
uUPlane = uYPlane + uYPlaneSize;
uVPlane = uUPlane + (uYPlaneSize>>2);
pSource = (HPBYTE)lpicDecEx->lpSrc;
pDestination = (HPBYTE)(DC->p16InstPostProcess + (DWORD)DC->PostFrame.X32_YPlane);
FrameMirror (pSource, pDestination, uHeight, uWidth, uWidth);
pSource += uYPlaneSize;
pDestination += uYPlaneSize;
FrameMirror (pSource, pDestination, (uHeight>>1), (uWidth>>1), (uWidth>>1));
pSource += (uYPlaneSize>>2);
pDestination += (uYPlaneSize>>2);
FrameMirror (pSource, pDestination, (uHeight>>1), (uWidth>>1), (uWidth>>1));
}
else // no mirroring
{
if ((DC->bAdjustLuma)||(DC->bAdjustChroma)) // copy when adjust pels
{
pFrame = (U8 *)DC->p16InstPostProcess;
//uYPlane = 0;
uYPlane = DC->PostFrame.X32_YPlane;
uUPlane = uYPlane + uYPlaneSize;
uVPlane = uUPlane + (uYPlaneSize>>2);
pSource = (HPBYTE)lpicDecEx->lpSrc;
pDestination = (HPBYTE)(DC->p16InstPostProcess + (DWORD)DC->PostFrame.X32_YPlane);
FrameCopy (pSource, pDestination, uHeight, uWidth, uWidth);
pSource += uYPlaneSize;
pDestination += uYPlaneSize;
FrameCopy (pSource, pDestination, (uHeight>>1), (uWidth>>1), (uWidth>>1));
pSource += (uYPlaneSize>>2);
pDestination += (uYPlaneSize>>2);
FrameCopy (pSource, pDestination, (uHeight>>1), (uWidth>>1), (uWidth>>1));
}
else
{
/* Do not have to do memcpy because color convertors don't
* destroy input planes.
*/
pFrame = (HPBYTE)lpicDecEx->lpSrc;
uYPlane = 0;
uUPlane = uYPlane + uYPlaneSize;
uVPlane = uUPlane + (uYPlaneSize>>2);
//memcpy(((char FAR *)(DC->p16InstPostProcess + (DWORD)DC->PostFrame.X32_YPlane)),
// (const char FAR *)lpicDecEx->lpSrc,
// lpicDecEx->lpbiSrc->biSizeImage);
}
} /* end else if no mirroring */
uYPitch = DC->uFrameWidth;
uUVPitch = DC->uFrameWidth >> 1;
} /* end else YUV12 */
if (DC->bForceOnAspectRatioCorrection || lpInst->bCorrectAspectRatio) {
bShapingFlag = 1;
u16NewFrameHeight = (U16) (DC->uFrameHeight * 11 / 12);
} else {
bShapingFlag = 0;
u16NewFrameHeight = (U16) DC->uFrameHeight;
}
/* Do the PEL color adjustments if necessary.
*/
if(DC->bAdjustLuma) {
/* width is rounded up to a multiple of 8
*/
AdjustPels(pFrame,
uYPlane,
DC->uFrameWidth,
uYPitch,
DC->uFrameHeight,
(U32) DC->X16_LumaAdjustment);
}
if(DC->bAdjustChroma) {
/* width = Y-Width / 4 and then rounded up to a multiple of 8
*/
AdjustPels(pFrame,
uUPlane,
(DC->uFrameWidth >> 1),
uUVPitch,
(DC->uFrameHeight >> 1),
(U32) DC->X16_ChromaAdjustment);
AdjustPels(pFrame,
uVPlane,
(DC->uFrameWidth >> 1),
uUVPitch,
(DC->uFrameHeight >> 1),
(U32) DC->X16_ChromaAdjustment);
}
/* Determine parameters (lOutput, intPitch, uNewOffsetToLine0)
* needed for color conversion.
*/
if (lpicDecEx->lpbiDst->biCompression == FOURCC_YUY2)
{
// We are assuming here a positive pitch for YUY2.
// This typically corresponds to a negative value for
// the destination bit map height.
// If we're ever asked to use YUY2 with a positive bit map
// height, we'll have to revisit these calculations.
intPitch = (lpicDecEx->lpbiDst->biBitCount >> 3)
* abs ((int)(lpicDecEx->lpbiDst->biWidth));
lOutput = 0;
uNewOffsetToLine0 = 0;
#if 0
// Aspect ratio correction is now supported for YUY2.
// This is necessary to enable direct draw under Active Movie 1.0.
bShapingFlag=FALSE;
#endif
DBOUT("Using YUY2 ........");
}
else if ((lpicDecEx->lpbiDst->biCompression == FOURCC_YUV12) || (lpicDecEx->lpbiDst->biCompression == FOURCC_IYUV))
{
intPitch = 0xdeadbeef; // should not be used
lOutput = 0;
uNewOffsetToLine0 = DC->CCOffsetToLine0;
bShapingFlag=FALSE;
DBOUT("Using YUV ........");
}
else if (lpicDecEx->lpbiDst->biCompression == FOURCC_IF09)
{
lOutput=0;
intPitch = abs((int)(lpicDecEx->lpbiDst->biWidth));
uNewOffsetToLine0 = DC->CCOffsetToLine0;
DBOUT("USing IF09........");
}
else
{
lOutput = DibXY(lpicDecEx, &intPitch, lpInst->YScale, bIsDCI);
uNewOffsetToLine0 = DC->CCOffsetToLine0;
if (!bIsDCI)
{
// DC->CCOffsetToLine0 was initialized without taking into
// account the sign of the destination bitmap height. Let's
// compensate for that here.
if (lpicDecEx->lpbiDst->biHeight < 0)
uNewOffsetToLine0 = 0;
// Adjust uNewOffsetToLine0 for aspect ratio correction.
if (uNewOffsetToLine0 > 0)
{
ASSERT(intPitch < 0);
if (lpInst->YScale == 2)
{
uNewOffsetToLine0 += 2 * (U32)intPitch *
((U32)DC->uFrameHeight - (U32)u16NewFrameHeight);
}
else
{
uNewOffsetToLine0 += (U32)intPitch *
((U32)DC->uFrameHeight - (U32)u16NewFrameHeight);
}
}
}
}
/* Call the color convertors
*/
/////////////////////////////////////////////////////////////////////////////
// Check to see if we need to copy a Snapshot into the output buffer.
// I added new fields to the Decoder Catalog to permit asynchronous
// transfer of data. These fields are:
// DC->SnapshotRequest
// DC->SnapshotBuffer
// DC->SnapshotEvent
// Ben - 09/25/96
/////////////////////////////////////////////////////////////////////////////
if(DC->SnapshotRequest == SNAPSHOT_REQUESTED)
{
UINT uiSZ_Snapshot;
DBOUT("D1DEC:DECOMPRESS::Snapshot requested");
uiSZ_Snapshot = (DC->uFrameWidth * DC->uFrameHeight * 12) >> 3;
if(!(IsBadWritePtr(DC->SnapshotBuffer, uiSZ_Snapshot)))
{
DC->SnapshotRequest = SNAPSHOT_COPY_STARTED;
DBOUT("D1DEC:DECOMPRESS::Snapshot copy started");
ColorConvertorCatalog[YUV12NOPITCH].ColorConvertor[0]
(
(LPSTR) pFrame + uYPlane,
(LPSTR) pFrame + uVPlane,
(LPSTR) pFrame + uUPlane,
(UN) DC->uFrameWidth,
(UN) DC->uFrameHeight,
(UN) uYPitch,
(UN) uUVPitch,
(UN) (bShapingFlag ? 12 : 9999),
(LPSTR) DC->SnapshotBuffer,
0,
0,
(int) DC->uFrameWidth,
YUV12NOPITCH
);
DC->SnapshotRequest = SNAPSHOT_COPY_FINISHED;
DBOUT("D1DEC:DECOMPRESS::Snapshot copy finished");
}
else
{
DC->SnapshotRequest = SNAPSHOT_COPY_REJECTED;
DBOUT("D1DEC:DECOMPRESS::Snapshot copy rejected");
}
SetEvent(DC->SnapshotEvent);
}
#ifndef RING0
#ifdef _DEBUG
{
char msg[180];
wsprintf(msg, "Decompress before CC: (%d,%d,%d,%d) (%d,%d,%d,%d) lOut %ld, NewOff %ld, DC->Off %ld, pitch %ld",
lpicDecEx->xSrc, lpicDecEx->ySrc, lpicDecEx->dxSrc, lpicDecEx->dySrc,
lpicDecEx->xDst, lpicDecEx->yDst, lpicDecEx->dxDst, lpicDecEx->dyDst,
lOutput, uNewOffsetToLine0, DC->CCOffsetToLine0, intPitch);
DBOUT(msg);
}
#endif
#endif
#ifdef DECODE_STATS
TIMER_BEFORE(bTimingThisFrame,uStartLow,uStartHigh,uBefore);
#endif
ColorConvertorCatalog[DC->ColorConvertor].ColorConvertor[PENTIUM_CC](
(LPSTR) pFrame + uYPlane,
(LPSTR) pFrame + uVPlane,
(LPSTR) pFrame + uUPlane,
(UN) DC->uFrameWidth,
(UN) DC->uFrameHeight,
(UN) uYPitch,
(UN) uUVPitch, // ??? BSE ??? //
(UN) (bShapingFlag ? 12 : 9999), // ??? BSE ??? //
(LPSTR) lpicDecEx->lpDst,
(U32) lOutput,
(U32) uNewOffsetToLine0,
(int) intPitch, // Color converter pitch
DC->ColorConvertor);
#ifdef DECODE_STATS
TIMER_AFTER_P5(bTimingThisFrame,uStartLow,uStartHigh,uBefore,uElapsed,uOutputCCSum);
#endif
iReturn = ICERR_OK;
done:
if (DC != NULL)
{
if (DC->DecoderType == H263_CODEC)
{
#ifdef DECODE_STATS
TIMER_BEFORE(bTimingThisFrame,uStartLow,uStartHigh,uBefore);
#endif
H261ReInitializeBlockActionStream(DC);
#ifdef DECODE_STATS
TIMER_AFTER_P5(bTimingThisFrame,uStartLow,uStartHigh,uBefore,uElapsed,uInitBlkActStrSum)
#endif
} /* end if (DC->DecoderType == H263_CODEC) */
#ifdef DECODE_STATS
TIMER_STOP(bTimingThisFrame,uStartLow,uStartHigh,uDecodeFrameSum);
if (bTimingThisFrame)
{
pDecTimingInfo = DC->pDecTimingInfo + DC->uStatFrameCount;
pDecTimingInfo->uDecodeFrame = uDecodeFrameSum;
pDecTimingInfo->uHeaders += uHeadersSum;
pDecTimingInfo->uMemcpy = uMemcpySum;
pDecTimingInfo->uFrameCopy = uFrameCopySum;
pDecTimingInfo->uOutputCC = uOutputCCSum;
pDecTimingInfo->uInitBlkActStr = uInitBlkActStrSum;
pDecTimingInfo->uBEF = uBEFSum;
DC->uStatFrameCount++;
/* Verify that we have time for all the required steps
*/
ASSERT(pDecTimingInfo->uDecodeFrame);
ASSERT(pDecTimingInfo->uHeaders);
ASSERT(pDecTimingInfo->uMemcpy);
ASSERT(pDecTimingInfo->uFrameCopy);
ASSERT(pDecTimingInfo->uOutputCC);
/* ASSERT(pDecTimingInfo->uDecodeBlock); 0 if all are empty */
ASSERT(pDecTimingInfo->uInitBlkActStr);
ASSERT(pDecTimingInfo->uBEF);
}
#endif
}
return iReturn;
}
//************************************************************************
//
//H263TermDecoderInstance -- This function frees the space allocated for an
// instance of the H263 decoder.
//
//************************************************************************
LRESULT H263TermDecoderInstance(LPDECINST lpInst)
{
LRESULT iReturn = ICERR_OK;
T_H263DecoderCatalog * DC;
if(IsBadWritePtr((LPVOID)lpInst, sizeof(DECINSTINFO)))
{
DBOUT("ERROR :: H263TermDecoderInstance :: ICERR_BADPARAM");
iReturn = ICERR_BADPARAM;
}
if(lpInst->Initialized == FALSE)
{
DBOUT("Warning: H263TermDecoderInstance(): Uninitialized instance")
return(ICERR_OK);
}
lpInst->Initialized = FALSE;
DC = (T_H263DecoderCatalog *) ((((U32) lpInst->pDecoderInst) + 31) & ~0x1F);
CloseHandle(DC->SnapshotEvent);
if (DC->a16InstPostProcess != NULL)
{
HeapFree(GetProcessHeap(), 0, DC->a16InstPostProcess);
// PhilF: Also freed in H263TerminateDecoderInstance! For now set to NULL to avoid second HeapFree.
// Investigate reason for 2nd call later...
DC->a16InstPostProcess = NULL;
}
HeapFree(GetProcessHeap(), 0, lpInst->pDecoderInst);
return iReturn;
}
//****************************************************************************
//DibXY -- This function is used to map color converted output to the screen.
//note: this function came from the H261 code base.
//****************************************************************************
static long DibXY(ICDECOMPRESSEX FAR *lpicDecEx, LPINT lpiPitch, UINT yScale, BOOL bIsDCI)
{
int iPitch; /* width of DIB */
long lOffset = 0;
LPBITMAPINFOHEADER lpbi = lpicDecEx->lpbiDst;
iPitch = (((abs((int)lpbi->biWidth) * (int)lpbi->biBitCount) >> 3) + 3) & ~3;
// The source and destination rectangles in lpicDecEx are only
// meaningful if bIsDCI is true (because throughout our codec, if bIsDCI
// is FALSE, we put zeroes in these rectangles). This may change, at
// some later point, if we decide (or are required) to make use of the
// rcSource and rcTarget rectangles that are associated with an Active
// Movie media sample.
if (!bIsDCI)
{
if (lpbi->biHeight >= 0)
{
// Typically for RGB, a positive bitmap height corresponds
// to a negative pitch.
iPitch = -iPitch;
}
}
else
{
if(lpicDecEx->xDst > 0) /* go to proper X position */
lOffset += ((long)lpicDecEx->xDst * (long)lpbi->biBitCount) >> 3;
if(lpbi->biHeight * lpicDecEx->dxSrc < 0)
{ /* DIB is bottom to top */
lOffset += (long) abs((int)lpbi->biWidth) *
(long) abs((int)lpbi->biHeight) *
((long) lpbi->biBitCount >> 3) -
(long) iPitch;
/***************************************************************************/
/***** This next line is used to subtract the amount that Brian added *****/
/***** to CCOffsetToLine0 in COLOR.C during initialization. This is *****/
/***** needed because for DCI, the pitch he used is incorrect. *****/
/***************************************************************************/
lOffset -= ((long) yScale * (long)lpicDecEx->dySrc - 1) *
(long) lpicDecEx->dxDst * ((long) lpbi->biBitCount >> 3);
iPitch = -iPitch;
}
if(lpicDecEx->yDst > 0) /* go to proper Y position */
lOffset += ((long)lpicDecEx->yDst * (long)iPitch);
if(lpicDecEx->dxSrc > 0) {
lOffset += ((long)lpicDecEx->dyDst * (long)iPitch) - (long)iPitch;
iPitch = -iPitch;
}
if((lpicDecEx->dxDst == 0) && (lpicDecEx->dyDst == 0))
iPitch = -iPitch;
}
*lpiPitch = iPitch;
return(lOffset);
}
/************************************************************************
*
* GetDecoderOptions
*
* Get the options, saving them in the catalog
*/
static void GetDecoderOptions(
T_H263DecoderCatalog * DC)
{
int bSetOptions = 1;
/* Default Options
*/
const int bDefaultForceOnAspectRatioCorrection = 0;
const int bDefaultUseBlockEdgeFilter = 1;
/* INI file variables
*/
#ifndef RING0
UN unResult;
#define SECTION_NAME "Decode"
#define INI_FILE_NAME "h261test.ini"
#ifdef _DEBUG
char buf132[132];
#endif
#endif
/* Read the options from the INI file
*/
#ifndef RING0
{
DBOUT("Getting decode options from the ini file h261test.ini");
/* BlockEdgeFilter
*/
unResult = GetPrivateProfileInt(SECTION_NAME, "BlockEdgeFilter", bDefaultUseBlockEdgeFilter, INI_FILE_NAME);
if (unResult != 0 && unResult != 1)
{
#ifdef _DEBUG
wsprintf(buf132,"BlockEdgeFilter ini value error (should be 0 or 1) - using default=%d",
(int) bDefaultUseBlockEdgeFilter);
DBOUT(buf132);
#endif
unResult = bDefaultUseBlockEdgeFilter;
}
DC->bUseBlockEdgeFilter = unResult;
/* Force on aspect ratio correction.
*/
unResult = GetPrivateProfileInt(SECTION_NAME, "ForceOnAspectRatioCorrection", bDefaultForceOnAspectRatioCorrection, INI_FILE_NAME);
if (unResult != 0 && unResult != 1)
{
#ifdef _DEBUG
wsprintf(buf132,"ForceOnAspectRatioCorrection ini value error (should be 0 or 1) - using default=%d",
(int) bDefaultForceOnAspectRatioCorrection);
DBOUT(buf132);
#endif
unResult = bDefaultForceOnAspectRatioCorrection;
}
DC->bForceOnAspectRatioCorrection = unResult;
bSetOptions = 0;
}
#endif
if (bSetOptions)
{
DC->bUseBlockEdgeFilter = bDefaultUseBlockEdgeFilter;
DC->bForceOnAspectRatioCorrection = bDefaultForceOnAspectRatioCorrection;
}
/* Can only use force aspect ratio correction on if SQCIF, QCIF, or CIF
*/
if (DC->bForceOnAspectRatioCorrection)
{
if (! ( ((DC->uFrameWidth == 128) && (DC->uFrameHeight == 96)) ||
((DC->uFrameWidth == 176) && (DC->uFrameHeight == 144)) ||
((DC->uFrameWidth == 352) && (DC->uFrameHeight == 288)) ) )
{
DBOUT("Aspect ratio correction can not be forced on unless the dimensions are SQCIF, QCIF, or CIF");
DC->bForceOnAspectRatioCorrection = 0;
}
}
/* Display the options
*/
if (DC->bUseBlockEdgeFilter)
{
DBOUT("Decoder option (BlockEdgeFilter) is ON");
}
else
{
DBOUT("Decoder option (BlockEdgeFilter) is OFF");
}
if (DC->bForceOnAspectRatioCorrection)
{
DBOUT("Decoder option (ForceOnAspectRatioCorrection) is ON");
}
else
{
DBOUT("Decoder option (ForceOnAspectRatioCorrection) is OFF");
}
DBOUT("Decoder option (MMX) is OFF: get a life, get MMX");
} /* end GetDecoderOptions() */
/***********************************************************************
* Description:
* This routine parses the bit-stream and initializes two major streams:
* 1) pN: no of coefficients in each of the block (biased by 65 for INTRA)
* 2) pRun_INVERSE_Q: de-quantized coefficient stream for the frame;
* MMX stream is scaled because we use scaled IDCT.
* Other information (e.g. MVs) is kept in decoder catalog, block action
* stream, and MB infor stream.
* Parameters:
* DC: Decoder catalog ptr
* fpBlockAction: block action stream ptr
* fpMBInfo: Macroblock info ptr
* fpbsState: bit-stream state pointer
* fpu8MaxPtr: sentinel value to check for bit-stream overruns
* pN: stream of no. of coeffs (biased by block type) for each block
* pRun_INVERSE_Q:stream of de-quantized (and scaled if using MMX) coefficients
* iNumberOfGOBs: no. of GOBs in the frame
* iNumberOfMBs: no. of MBs in a GOB in the frame
* iGOB_start:
* iMB_start:
* Note:
***********************************************************************/
#pragma code_seg("IACODE1")
// #ifndef LOSS_RECOVERY
#if 0
static LRESULT IAPass1ProcessFrame(
T_H263DecoderCatalog *DC,
T_BlkAction *fpBlockAction,
T_MBInfo *fpMBInfo,
BITSTREAM_STATE *fpbsState,
U8 *fpu8MaxPtr,
U32 *pN,
T_IQ_INDEX *pRUN_INVERSE_Q,
const I32 iNumberOfGOBs,
const I32 iNumberOfMBs,
const I32 iGOB_start,
const I32 iMB_start
)
{
I32 g, iReturn, iBlockNumber = 0 ;
I32 mb_start = iMB_start;
U32 *pNnew;
U32 uReadChecksum = 0;
I8 i;
I8 tmpcnt;
#ifdef DECODE_STATS
U32 uStartLow = DC->uStartLow;
U32 uStartHigh = DC->uStartHigh;
U32 uElapsed;
U32 uBefore;
U32 uHeadersSum = 0;
int bTimingThisFrame = DC->bTimingThisFrame;
DEC_TIMING_INFO *pDecTimingInfo = NULL;
#endif
#ifdef DECODE_STATS
TIMER_BEFORE(bTimingThisFrame,uStartLow,uStartHigh,uBefore);
#endif
/* move decode of GOB start code outside of GOB header processing */
/* because if processing skipped macroblocks, looking for the last MBA */
/* will find the next start code */
iReturn = H263DecodeGOBStartCode(DC, fpbsState);
if (iReturn != ICERR_OK)
{
DBOUT("ERROR :: H263Decompress :: Error reading the GOB StartCode");
goto done;
}
#ifdef DECODE_STATS
TIMER_AFTER_P5(bTimingThisFrame,uStartLow,uStartHigh,uBefore,uElapsed,uHeadersSum)
#endif
for (g = 1 ; g <= iNumberOfGOBs; g++)
{
#ifdef DECODE_STATS
TIMER_BEFORE(bTimingThisFrame,uStartLow,uStartHigh,uBefore);
#endif
iReturn = H263DecodeGOBHeader(DC, fpbsState, g);
if (iReturn != ICERR_OK)
{
DBOUT("ERROR :: H263Decompress :: Error reading the GOB header");
goto done;
}
#ifdef DECODE_STATS
TIMER_AFTER_P5(bTimingThisFrame,uStartLow,uStartHigh,uBefore,uElapsed,uHeadersSum)
#endif
DC->i16LastMBA = -1;
DC->i8MVDH = DC->i8MVDV = 0;
// re-sync iBlockNumber, fpBlockAction, fpMBInfo at this point
iBlockNumber = (g - 1) * iNumberOfMBs*6;
fpBlockAction = (T_BlkAction FAR *)((U8 *)DC + DC->X16_BlkActionStream);
fpMBInfo = (T_MBInfo FAR *) ((U8 *)DC + DC->X32_uMBInfoStream);
fpBlockAction += iBlockNumber;
fpMBInfo += iBlockNumber/6;
pNnew = (U32 *)((U8 *)DC + DC->X32_pN) + iBlockNumber;
while (pN < pNnew ) *pN++ = 0;
/* For each MB until START_CODE detected do ...
*/
for (; ; iBlockNumber += 6, fpBlockAction += 6, fpMBInfo++)
{
#ifdef DECODE_STATS
TIMER_BEFORE(bTimingThisFrame,uStartLow,uStartHigh,uBefore);
#endif
iReturn = H263DecodeMBHeader(DC, fpbsState, &uReadChecksum);
#ifdef DECODE_STATS
TIMER_AFTER_P5(bTimingThisFrame,uStartLow,uStartHigh,uBefore,uElapsed,uHeadersSum)
#endif
if (iReturn == START_CODE)
break;
/* If we didn't see a start code, then we either got an error,
* or we have another MBA delta in DC->uMBA.
*/
if (iReturn != ICERR_OK) {
DBOUT("ERROR :: H263Decompress (First Pass) :: Error reading MB header");
goto error;
}
/* Update MBA */
DC->i16LastMBA += (I16)DC->uMBA;
if (DC->i16LastMBA > 32)
{
DBOUT("ERROR :: H263Decompress :: Bad Macro Block Address");
goto done;
}
/* New for rearch */
/* adjust for empty macroblocks */
for ( tmpcnt = (I8)DC->uMBA; tmpcnt > 1; tmpcnt--)
{
for (i=0; i<6; i++)
{
*pN = 0;
pN++;
}
iBlockNumber += 6;
fpBlockAction += 6;
/* Default fpBlockAction values were already initialized
* in (Re)InitializeBlockActionStream.
*/
fpMBInfo->i8MBType = 2;
fpMBInfo++;
}
fpMBInfo->i8MBType = (I8)DC->uMBType; // New rearch
/* end of new rearch */
// decode and inverse quantize the transform coefficients
iReturn = H263DecodeMBData(DC,
fpBlockAction,
iBlockNumber,
fpbsState,
fpu8MaxPtr,
&uReadChecksum,
&pN,
&pRUN_INVERSE_Q);
if (iReturn != ICERR_OK) {
DBOUT("ERROR :: H263Decompress (First Pass) :: Error parsing MB data");
goto error;
}
} // end for each MB
/* Fill in arrays and advance Block Action stream when there
are skip MB at the end of each GOB
*/
while (iBlockNumber != (I32)g*198) {
for (i=0; i<6; i++)
{
*pN = 0;
pN++;
}
iBlockNumber += 6;
fpBlockAction+= 6;
/* Default fpBlockAction values were already initialized
* in (Re)InitializeBlockActionStream.
*/
fpMBInfo->i8MBType = 2;
fpMBInfo++;
}
/* allow the pointer to address up to four beyond the end - reading
* by DWORD using postincrement.
*/
// ASSERT(fpbsState->fpu8 <= fpu8MaxPtr+4);
if (fpbsState->fpu8 > fpu8MaxPtr+4)
goto error;
} // End for each GOB
#ifdef DECODE_STATS
if (bTimingThisFrame)
{
pDecTimingInfo = DC->pDecTimingInfo + DC->uStatFrameCount;
pDecTimingInfo->uHeaders += uHeadersSum;
}
#endif
done:
return ICERR_OK;
error:
return ICERR_ERROR;
}
#else
static LRESULT IAPass1ProcessFrameRTP(
T_H263DecoderCatalog *DC,
T_BlkAction *fpBlockAction,
T_MBInfo *fpMBInfo,
BITSTREAM_STATE *fpbsState,
U8 *fpu8MaxPtr,
U32 *pN,
T_IQ_INDEX *pRUN_INVERSE_Q,
const I32 iNumberOfGOBs,
const I32 iNumberOfMBs,
const I32 iGOB_start,
const I32 iMB_start
)
{
BITSTREAM_STATE fpbsStateSave;
I32 g, current_g, iReturn, iBlockNumber = 0 ;
I32 mb_start = iMB_start;
U32 *pNnew;
U32 uReadChecksum = 0;
I8 i;
I8 tmpcnt;
I32 g_skip, gtmp;
I32 uMaxGOBNumber, uGOBStep, uMaxBlockNumber;
#ifdef DECODE_STATS
U32 uStartLow = DC->uStartLow;
U32 uStartHigh = DC->uStartHigh;
U32 uElapsed;
U32 uBefore;
U32 uHeadersSum = 0;
int bTimingThisFrame = DC->bTimingThisFrame;
DEC_TIMING_INFO *pDecTimingInfo = NULL;
#endif
#ifdef DECODE_STATS
TIMER_BEFORE(bTimingThisFrame,uStartLow,uStartHigh,uBefore);
#endif
/* move decode of GOB start code outside of GOB header processing */
/* because if processing skipped macroblocks, looking for the last MBA */
/* will find the next start code */
iReturn = H263DecodeGOBStartCode(DC, fpbsState);
if (iReturn != ICERR_OK)
{
DBOUT("ERROR :: H261Decompress :: Error reading the GOB StartCode");
goto done;
}
#ifdef DECODE_STATS
TIMER_AFTER_P5(bTimingThisFrame,uStartLow,uStartHigh,uBefore,uElapsed,uHeadersSum)
#endif
if (iNumberOfGOBs == 3)
{
uMaxGOBNumber = 5;
uGOBStep = 2;
}
else
{
uMaxGOBNumber = 12;
uGOBStep = 1;
}
for (g = 1; g <= uMaxGOBNumber; g+=uGOBStep)
{
current_g = g;
#ifdef DECODE_STATS
TIMER_BEFORE(bTimingThisFrame,uStartLow,uStartHigh,uBefore);
#endif
iReturn = H263DecodeGOBHeader(DC, fpbsState, g);
// #ifndef LOSS_RECOVERY
#if 0
if (iReturn != ICERR_OK)
{
DBOUT("ERROR :: H261Decompress :: Error reading the GOB header");
goto done;
}
#else
if (iReturn == PACKET_FAULT_AT_MB_OR_GOB)
{
DBOUT("Packet fault at MBA or GBSC detected.");
current_g -= uGOBStep; // back up to previous GOB
iReturn = RtpH261FindNextPacket(DC, fpbsState, &pN,
(U32 *)&(DC->uPQuant), (int *)&mb_start, (int *) &g
);
switch (iReturn)
{
case NEXT_MODE_STARTS_GOB:
// Next packet is the start of a GOB; mark missing
// macroblocks as skipped, then read GOB start code,
// and continue in the GOB loop.
// Save bitstream state
DBOUT("Next packet is NEXT_MODE_STARTS_GOB");
fpbsStateSave.fpu8 = fpbsState->fpu8;
fpbsStateSave.uWork = fpbsState->uWork;
fpbsStateSave.uBitsReady = fpbsState->uBitsReady;
// Read GOB start code
iReturn = H263DecodeGOBStartCode(DC, fpbsState);
if (iReturn != ICERR_OK)
{
DBOUT("ERROR :: H261Decompress :: Error reading the GOB StartCode");
goto done;
}
// Read GOB Header
iReturn = H263DecodeGOBHeader(DC, fpbsState, g);
if (iReturn != ICERR_OK)
{
DBOUT("ERROR :: H261Decompress :: Error reading the GOB header");
goto done;
}
g = DC->uGroupNumber;
// Restore bitstream state
fpbsState->fpu8 = fpbsStateSave.fpu8;
fpbsState->uWork = fpbsStateSave.uWork;
fpbsState->uBitsReady = fpbsStateSave.uBitsReady;
// re-sync iBlockNumber, fpBlockAction, fpMBInfo at this point
if (DC->uSrcFormat == SRC_FORMAT_QCIF)
g_skip = (g - 1) >> 1;
else
g_skip = g - 1 ;
iBlockNumber = g_skip * iNumberOfMBs * 6;
fpBlockAction = (T_BlkAction FAR *)((U8 *)DC + DC->X16_BlkActionStream);
fpMBInfo = (T_MBInfo FAR *) ((U8 *)DC + DC->X32_uMBInfoStream);
fpBlockAction += iBlockNumber;
fpMBInfo += iBlockNumber/6;
pNnew = (U32 *)((U8 *)DC + DC->X32_pN) + iBlockNumber;
while (pN < pNnew )
*pN++ = 0;
// Now read the GOB start code and get ready to
// process the new GOB.
iReturn = H263DecodeGOBStartCode(DC, fpbsState);
if (iReturn != ICERR_OK)
{
DBOUT("ERROR :: H261Decompress :: Error reading the GOB StartCode");
goto done;
}
g -= uGOBStep;
continue;
break;
case NEXT_MODE_STARTS_MB :
// Next packet starts with a macroblock; check the
// GOB Number and mark all lost macroblocks as
// skipped; initialize MBA and motion vector
// predictors from the block action stream and
// jump to the macroblock loop
DBOUT("Next packet is NEXT_MODE_STARTS_MB");
if (DC->uSrcFormat == SRC_FORMAT_QCIF)
g_skip = (g - 1) >> 1;
else
g_skip = g - 1;
iBlockNumber = iNumberOfMBs * g_skip * 6 +
(mb_start+1) * 6;
fpBlockAction = (T_BlkAction FAR *)((U8 *)DC + DC->X16_BlkActionStream);
fpMBInfo = (T_MBInfo FAR *) ((U8 *)DC + DC->X32_uMBInfoStream);
fpBlockAction += iBlockNumber;
fpMBInfo += iBlockNumber/6;
DC->uMQuant = DC->uPQuant;
//DC->i16LastMBA = (U16) (mb_start - 1);
DC->i16LastMBA = (U16) (mb_start);
pNnew = (U32 *)((U8 *)DC + DC->X32_pN) + iBlockNumber;
while (pN < pNnew )
*pN++ = 0;
goto MB_LOOP;
break;
case NEXT_MODE_LAST: // all remaining packets in frame lost !!
DBOUT("Next packet is NEXT_MODE_LAST");
uMaxBlockNumber = iNumberOfMBs * iNumberOfGOBs * 6;
pNnew = (U32 *)((U8 *)DC + DC->X32_pN) + uMaxBlockNumber;
while (pN < pNnew )
*pN++ = 0;
iReturn = ICERR_OK;
goto done;
break;
default: // should never happen !!
iReturn = ICERR_ERROR;
goto done;
} // end switch
}
else
{
if (iReturn == PACKET_FAULT_AT_PSC) // can only happen for the PSC packet
{
DBOUT("PSC packet fault detected");
iReturn = RtpGetPicHeaderFromBsExt(DC);
if (iReturn != ICERR_OK)
{
DBOUT("ERROR:: cannot read Picture Header from RTP Trailer");
goto done;
}
iReturn = RtpH261FindNextPacket(DC, fpbsState, &pN,
(U32 *)&(DC->uPQuant), (int *)&mb_start, (int *) &g);
switch (iReturn)
{
case NEXT_MODE_STARTS_GOB:
// Next packet is the start of a GOB; mark missing
// macroblocks as skipped, then read GOB start code,
// and continue in the GOB loop.
// re-sync iBlockNumber, fpBlockAction, fpMBInfo at this point
// Save bitstream state
DBOUT("Next packet is NEXT_MODE_STARTS_GOB");
fpbsStateSave.fpu8 = fpbsState->fpu8;
fpbsStateSave.uWork = fpbsState->uWork;
fpbsStateSave.uBitsReady = fpbsState->uBitsReady;
// Read GOB start code
iReturn = H263DecodeGOBStartCode(DC, fpbsState);
if (iReturn != ICERR_OK)
{
DBOUT("ERROR :: H261Decompress :: Error reading the GOB StartCode");
goto done;
}
// Read GOB Header
iReturn = H263DecodeGOBHeader(DC, fpbsState, g);
if (iReturn != ICERR_OK)
{
DBOUT("ERROR :: H261Decompress :: Error reading the GOB header");
goto done;
}
g = DC->uGroupNumber;
// Restore bitstream state
fpbsState->fpu8 = fpbsStateSave.fpu8;
fpbsState->uWork = fpbsStateSave.uWork;
fpbsState->uBitsReady = fpbsStateSave.uBitsReady;
if (DC->uSrcFormat == SRC_FORMAT_QCIF)
g_skip = (g - 1) >> 1;
else
g_skip = g - 1;
iBlockNumber = g_skip * iNumberOfMBs * 6;
fpBlockAction = (T_BlkAction FAR *)((U8 *)DC + DC->X16_BlkActionStream);
fpMBInfo = (T_MBInfo FAR *) ((U8 *)DC + DC->X32_uMBInfoStream);
fpBlockAction += iBlockNumber;
fpMBInfo += iBlockNumber/6;
pNnew = (U32 *)((U8 *)DC + DC->X32_pN) + iBlockNumber;
while (pN < pNnew )
*pN++ = 0;
// Now read the GOB start code and get ready to
// process the new GOB.
iReturn = H263DecodeGOBStartCode(DC, fpbsState);
if (iReturn != ICERR_OK)
{
DBOUT("ERROR :: H261Decompress :: Error reading the GOB StartCode");
goto done;
}
g -= uGOBStep;
continue;
break;
case NEXT_MODE_STARTS_MB :
// Next packet starts with a macroblock; check the
// GOB Number and mark all lost macroblocks as
// skipped; initialize MBA and motion vector
// predictors from the block action stream and
// jump to the macroblock loop
DBOUT("Next packet is NEXT_MODE_STARTS_MB");
if (DC->uSrcFormat == SRC_FORMAT_QCIF)
g_skip = (g - 1) >> 1;
else
g_skip = g - 1;
iBlockNumber = iNumberOfMBs * g_skip * 6 +
(mb_start+1) * 6;
fpBlockAction = (T_BlkAction FAR *)((U8 *)DC + DC->X16_BlkActionStream);
fpMBInfo = (T_MBInfo FAR *) ((U8 *)DC + DC->X32_uMBInfoStream);
fpBlockAction += iBlockNumber;
fpMBInfo += iBlockNumber/6;
DC->uMQuant = DC->uPQuant;
//DC->i16LastMBA = (U16) (mb_start - 1);
DC->i16LastMBA = (U16) (mb_start);
pNnew = (U32 *)((U8 *)DC + DC->X32_pN) + iBlockNumber;
while (pN < pNnew )
*pN++ = 0;
goto MB_LOOP;
break;
case NEXT_MODE_LAST: // all remaining packets in frame lost !!
DBOUT("Next packet is NEXT_MODE_LAST");
uMaxBlockNumber = iNumberOfMBs * iNumberOfGOBs * 6;
pNnew = (U32 *)((U8 *)DC + DC->X32_pN) + uMaxBlockNumber;
while (pN < pNnew )
*pN++ = 0;
iReturn = ICERR_OK;
goto done;
break;
default: // should never happen !!
iReturn = ICERR_ERROR;
goto done;
} // end switch
} // if .. PACKET_FAULT_AT_PSC
else
{
if (iReturn == ICERR_ERROR)
{
DBOUT("ERROR :: H261Decompress :: Error reading GOB header");
DBOUT(" Packet fault not detected");
goto done;
}
// Outdated: Do the source format check here when it is known that
// the PSC was not the canned one from the PPM.
/* if (DC->bReadSrcFormat && DC->uPrevSrcFormat != DC->uSrcFormat)
{
DBOUT("ERROR::src format changed detected with no packet loss");
DBOUT(" not supported ... bailing out");
iReturn=ICERR_ERROR;
goto done;
}
DC->uPrevSrcFormat = DC->uSrcFormat;
DC->bReadSrcFormat = TRUE; */
}
}
#endif
#ifdef DECODE_STATS
TIMER_AFTER_P5(bTimingThisFrame,uStartLow,uStartHigh,uBefore,uElapsed,uHeadersSum)
#endif
DC->i16LastMBA = -1;
DC->i8MVDH = DC->i8MVDV = 0;
// re-sync iBlockNumber, fpBlockAction, fpMBInfo at this point
if (DC->uSrcFormat == SRC_FORMAT_QCIF)
iBlockNumber = ((g - 1)>>1) * iNumberOfMBs*6;
else
iBlockNumber = (g - 1)* iNumberOfMBs*6;
fpBlockAction = (T_BlkAction FAR *)((U8 *)DC + DC->X16_BlkActionStream);
fpMBInfo = (T_MBInfo FAR *) ((U8 *)DC + DC->X32_uMBInfoStream);
fpBlockAction += iBlockNumber;
fpMBInfo += iBlockNumber/6;
pNnew = (U32 *)((U8 *)DC + DC->X32_pN) + iBlockNumber;
while (pN < pNnew ) *pN++ = 0;
/* For each MB until START_CODE detected do ...
*/
MB_LOOP:
for (; ; iBlockNumber += 6, fpBlockAction += 6, fpMBInfo++)
{
#ifdef DECODE_STATS
TIMER_BEFORE(bTimingThisFrame,uStartLow,uStartHigh,uBefore);
#endif
iReturn = H263DecodeMBHeader(DC, fpbsState, &uReadChecksum);
#ifdef DECODE_STATS
TIMER_AFTER_P5(bTimingThisFrame,uStartLow,uStartHigh,uBefore,uElapsed,uHeadersSum)
#endif
if (iReturn == START_CODE)
break;
/* If we didn't see a start code, then we either got an error,
* or we have another MBA delta in DC->uMBA.
*/
if (iReturn != ICERR_OK) {
DBOUT("ERROR :: H263Decompress (First Pass) :: Error reading MB header");
goto error;
}
/* Update MBA */
DC->i16LastMBA += (I16)DC->uMBA;
if (DC->i16LastMBA > 32)
{
DBOUT("ERROR :: H263Decompress :: Bad Macro Block Address");
goto done;
}
/* New for rearch */
/* adjust for empty macroblocks */
for ( tmpcnt = (I8)DC->uMBA; tmpcnt > 1; tmpcnt--)
{
for (i=0; i<6; i++)
{
*pN = 0;
pN++;
}
iBlockNumber += 6;
fpBlockAction += 6;
/* Default fpBlockAction values were already initialized
* in (Re)InitializeBlockActionStream.
*/
fpMBInfo->i8MBType = 2;
fpMBInfo++;
}
fpMBInfo->i8MBType = (I8)DC->uMBType; // New rearch
/* end of new rearch */
// decode and inverse quantize the transform coefficients
iReturn = H263DecodeMBData(DC,
fpBlockAction,
iBlockNumber,
fpbsState,
fpu8MaxPtr,
&uReadChecksum,
&pN,
&pRUN_INVERSE_Q);
if (iReturn != ICERR_OK) {
DBOUT("ERROR :: H263Decompress (First Pass) :: Error parsing MB data");
goto error;
}
} // end for each MB
/* Fill in arrays and advance Block Action stream when there
are skip MB at the end of each GOB
*/
if (DC->uSrcFormat == SRC_FORMAT_QCIF)
{
switch (g)
{
case 1:
gtmp = 1;
break;
case 3:
gtmp = 2;
break;
case 5:
gtmp = 3;
break;
default:
DBOUT("Bad GOB Number");
iReturn = ICERR_ERROR;
goto error;
break;
}
}
else
gtmp = g;
while (iBlockNumber != (I32)gtmp*198) {
for (i=0; i<6; i++)
{
*pN = 0;
pN++;
}
iBlockNumber += 6;
fpBlockAction+= 6;
/* Default fpBlockAction values were already initialized
* in (Re)InitializeBlockActionStream.
*/
fpMBInfo->i8MBType = 2;
fpMBInfo++;
}
/* allow the pointer to address up to four beyond the end - reading
* by DWORD using postincrement.
*/
ASSERT(fpbsState->fpu8 <= fpu8MaxPtr+4);
} // End for each GOB
#ifdef DECODE_STATS
if (bTimingThisFrame)
{
pDecTimingInfo = DC->pDecTimingInfo + DC->uStatFrameCount;
pDecTimingInfo->uHeaders += uHeadersSum;
}
#endif
done:
return ICERR_OK;
error:
return ICERR_ERROR;
}
#endif
#pragma code_seg()
/***********************************************************************
* Description:
* This routines does IDCT and motion compensation.
* Parameters:
* DC: Decoder catalog ptr
* fpBlockAction: block action stream ptr
* fpMBInfo: Macroblock info ptr
* pN: stream of no. of coeffs (biased by block type) for each block
* pRun_INVERSE_Q:stream of de-quantized (and scaled if using MMX) coefficients
* iNumberOfGOBs: no. of GOBs in the frame
* iNumberOfMBs: no. of MBs in a GOB in the frame
* Note:
***********************************************************************/
#pragma code_seg("IACODE2")
static void IAPass2ProcessFrame(
T_H263DecoderCatalog *DC,
T_BlkAction *fpBlockAction,
T_MBInfo *fpMBInfo,
U32 *pN,
T_IQ_INDEX *pRUN_INVERSE_Q,
const I32 iNumberOfGOBs,
const I32 iNumberOfMBs
)
{
I32 g, m, b, iEdgeFlag=0;
// for each GOB do
for (g = 1 ; g <= iNumberOfGOBs; g++)
{
// for each MB do
for (m = 1; m <= iNumberOfMBs; m++, fpBlockAction+=6, fpMBInfo++)
{
// for each block do
for (b = 0; b < 6; b++) { // AP-NEW
// do inverse transform & motion compensation for the block
H263IDCTandMC(DC, fpBlockAction, b, m, g, pN, pRUN_INVERSE_Q,
fpMBInfo, iEdgeFlag); // AP-NEW
// Adjust pointers for next block
if ( *pN >= 65 )
pRUN_INVERSE_Q += *pN - 65;
else
pRUN_INVERSE_Q += *pN;
pN++;
} // end for each block
} // end for each MB
} // End for each GOB
}
#pragma code_seg()
// rearch