|
|
/* *************************************************************************
** 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. ** ** ************************************************************************* */ /******************************************************************************
* e1mbenc.cpp * * DESCRIPTION: * Specific encoder compression functions. * * Routines: Prototypes in: * GOB_Q_RLE_VLC_WriteBS * MB_Quantize_RLE * ComputeCheckSum * WriteMBCheckSum */ /* $Header: S:\h26x\src\enc\e1mbenc.cpv 1.47 30 Oct 1996 09:58:46 MBODART $
* $Log: S:\h26x\src\enc\e1mbenc.cpv $ //
// Rev 1.47 30 Oct 1996 09:58:46 MBODART
// Fixed assertion failure. Need to reclamp unMQuant after adding delta.
//
// Rev 1.46 29 Oct 1996 11:18:18 RHAZRA
// Bug fix: in the IA code we previously modified MQuant on a MB basis
// even if we were operating with a fixed quantizer. Now we don't
//
// Rev 1.45 21 Oct 1996 09:05:16 RHAZRA
//
// MMX integration
//
// Rev 1.44 21 Aug 1996 19:06:02 RHAZRA
// Added RTP generatio code; fixed additional divide-by-zero possibilities.
//
// Rev 1.42 21 Jun 1996 10:08:34 AKASAI
// Changes to e1enc.cpp, e1mbenc.cpp, ex5me.asm to support "improved
// bit rate control", changing MacroBlock Quantization within a
// row of MB's in addition to changing the Quantization change
// between rows of macro blocks.
//
// ex5me.asm had a problem with SLF SWD. Brian updated asm code.
//
//
// Rev 1.41 14 May 1996 11:41:18 AKASAI
// Needed to test 0th and 1st coefficient to avoid clamping errors.
//
// Rev 1.40 14 May 1996 10:39:04 AKASAI
// Two files changed to hopefully eliminate Quantization clamping
// artifacts and to reduce the max buffer overflow case: e1enc.cpp
// and e1mbenc.cpp.
//
// In e1mbenc.cpp when the MQuant level is < 6 I test to see if
// the 0th coefficient is larger than the values representable
// at that Quant level if it is I increase the Quant level until
// the clamping artifact will not occur. Note: I am test only
// the Oth coefficient, there is the possibility that some other
// coefficient is larger but the performance trade off seems to
// indicate this is good for now and if we still see clamping
// artifacts we can add more testing later.
//
// In e1enc.cpp I modified when the Overflow types of warnings are
// turn on as well as changing the rate the Quantization level
// changes at.
//
// Rev 1.39 24 Apr 1996 12:18:22 AKASAI
// Added re-compression strategy to encoder. Had to change e1enc.cpp,
// e1enc.h and e1mbenc.cpp.
// Basic strategy is if spending too many bits in a GOB quantize the
// next GOB at a higher rate. If after compressing the frame too
// many bits have been used, re-compress the last GOB at a higher
// QUANT level if that still doesn't work send a "Skip" GOB.
// Needed to add extra parameter to GOB+Q_RLE_VLC_WriteBS because
// CalcMBQuant kept decreasing the QUANT when we were in trouble with
// possibly overflowing the buffer.
//
// Rev 1.38 22 Apr 1996 11:02:14 AKASAI
// Two files changed e1enc.cpp and e1mbenc.cpp to try and support
// allowing the Quantization values to go down to 2 instead of
// CLAMP to 6.
// This is part 1 of implementing the re-compression (what to do
// if exceed max compressed buffer size 8KBytes QCIF, 32KBytes FCIF).
// Also changed in e1enc was to limit request uFrameSize to 8KB or
// 32KB. Problem was if user specified too large of a datarate
// request frame size would be larger than the allowed buffer size.
// If you try to compress qnoise10.avi or fnoise5.avi you get an
// ASSERT error until rest of re-compression is implemented.
//
// Rev 1.37 19 Apr 1996 14:26:28 SCDAY
// Added adaptive bit usage profile (Karl's BRC changes)
//
// Rev 1.36 08 Jan 1996 10:11:16 DBRUCKS
// add an assert
//
// Rev 1.35 29 Dec 1995 18:11:42 DBRUCKS
//
// optimize walking pCurrMB and add CLAMP_N_TO(qp,6,31)
//
// Rev 1.34 27 Dec 1995 16:48:06 DBRUCKS
// moved incrementing InterCodeCnt from e1enc.cpp
//
// Rev 1.33 26 Dec 1995 17:45:18 DBRUCKS
// moved statistics to e1stat
//
// Rev 1.32 20 Dec 1995 14:56:52 DBRUCKS
// add timing stats
//
// Rev 1.31 18 Dec 1995 15:38:04 DBRUCKS
// improve stats
//
// Rev 1.30 15 Dec 1995 10:53:34 AKASAI
// Fixed bug that encoded the wrong type when spatial loop filter on
// bug 0 MV. Was incorrectly been encoded with no spatial loop filter.
// This seemed to have caused the "#" bug.
//
// Rev 1.29 13 Dec 1995 13:59:08 DBRUCKS
// added include exutil.h
// parameter change in call to cnvt_fdct_output - uses INTRA boolean instead
// of blocktype
//
// Rev 1.28 07 Dec 1995 12:50:54 DBRUCKS
// integrate Macroblock checksum fixes
//
// Rev 1.27 04 Dec 1995 12:12:30 DBRUCKS
// Unsigned compares using MQuant and lastencoded -2 yielded
// unexpected results when lastencoded was 1.
//
// Rev 1.26 01 Dec 1995 15:33:14 DBRUCKS
//
// Added the bit rate controller support. The one possibly confusing
// part is that the quantizer can change in the encoder on a macro block
// that is skipped or on one that does not have coefficients. In either
// case the decoder is not told of the change. The decoder is told of
// the change on the next macroblock that has coefficients.
//
// Rev 1.25 27 Nov 1995 17:53:40 DBRUCKS
// add spatial loop filtering
//
// Rev 1.24 22 Nov 1995 17:37:34 DBRUCKS
// cleanup me changes
//
// Rev 1.23 22 Nov 1995 15:34:52 DBRUCKS
//
// Motion Estimation works - but needs to be cleaned up
//
// Rev 1.22 17 Nov 1995 14:26:20 BECHOLS
//
// Made modifications so that this file can be made for ring 0.
//
// Rev 1.21 15 Nov 1995 14:40:34 AKASAI
// Union thing change ...
// (Integration point)
//
// Rev 1.20 01 Nov 1995 09:00:16 DBRUCKS
// cleanup
//
// Rev 1.19 27 Oct 1995 17:21:12 DBRUCKS
// fix MTYPE calc, improve var names and debug
//
// Rev 1.18 27 Oct 1995 15:06:30 DBRUCKS
// update cnvt_fdct_output
//
// Rev 1.17 27 Oct 1995 14:30:36 DBRUCKS
// delta frame support "coded", key frames tested
//
// Rev 1.15 17 Oct 1995 15:56:56 DBRUCKS
// cleanup debug message
//
// Rev 1.14 17 Oct 1995 15:52:10 DBRUCKS
//
// turn off a debug message
//
// Rev 1.13 16 Oct 1995 11:41:44 DBRUCKS
// fix the sign part of the checksum
//
// Rev 1.12 29 Sep 1995 10:31:02 DBRUCKS
// change to use e35qrle to get the latest
//
// Rev 1.11 27 Sep 1995 16:53:48 DBRUCKS
// move MB checksum before MB
//
// Rev 1.10 26 Sep 1995 13:33:14 DBRUCKS
// fixed TCOEFF table 4,1 and on used earlier values
//
// Rev 1.9 26 Sep 1995 09:29:46 DBRUCKS
// turn on MBEncodeVLC
//
// Rev 1.8 26 Sep 1995 09:09:24 DBRUCKS
// add checksum test code
//
// Rev 1.7 25 Sep 1995 10:23:16 DBRUCKS
//
// add checksum info AND
// fix the final param that is passed to MBEncodeVLC
//
// Rev 1.6 21 Sep 1995 20:37:56 BECHOLS
// Modified the VLC tables for H261. I included a placeholder for the
// sign bit, so that I can achieve an optimization in the code.
//
// Rev 1.5 21 Sep 1995 18:14:48 BECHOLS
// Changed the initialization of the VLC tables for efficient use of memory,
// and proper operation with VLC code. This is an intermediate step towards
// completion, but is not operable yet.
//
// Rev 1.4 20 Sep 1995 17:50:18 BECHOLS
//
// Removed VLC_TCOEF_LAST_TBL and changed the initialization code that
// use to assume 2 DWORDS to now make use of a single DWORD to conserve
// memory.
//
// Rev 1.3 20 Sep 1995 16:34:28 BECHOLS
// Moved the data declared in E1VLC.H to this module, where it is used.
//
// Rev 1.2 20 Sep 1995 12:39:38 DBRUCKS
// turn on complete mb processing and
// cleanup two routines
//
// Rev 1.1 18 Sep 1995 10:09:54 DBRUCKS
//
// activate more of the mb processing
//
// Rev 1.0 12 Sep 1995 18:57:16 BECHOLS
// Initial revision.
*/
#include "precomp.h"
#ifdef CHECKSUM_MACRO_BLOCK
static U32 ComputeCheckSum(I8 * pi8MBRunValTriplets, I8 * pi8EndAddress, I32 iBlockNumber); static void WriteMBCheckSum(U32 uCheckSum, U8 * pu8PictureStart, U8 ** ppu8BitStream, U8 * pu8BitOffset, UN unCurrentMB); #endif
static I8 * MB_Quantize_RLE(I32 **DCTCoefs, I8 *MBRunValPairs, U8 * CodedBlocks, U8 BlockType, I32 QP, U32 *puChecksum);
extern char string[128];
/*
* VLC table for TCOEFs * Table entries are size INCLUDING PLACE HOLDER FOR SIGN BIT, code. * Stored as (size, value) */ int VLC_TCOEF[102*2] = { 0X0003, 0x0006, // 0
0X0005, 0x0008, 0X0006, 0x000A, 0X0008, 0x000C, 0X0009, 0x004C, 0X0009, 0x0042, 0X000B, 0x0014, 0X000D, 0x003A, 0X000D, 0x0030, 0X000D, 0x0026, 0X000D, 0x0020, 0X000E, 0x0034, 0X000E, 0x0032, 0X000E, 0x0030, 0X000E, 0x002E, 0X0004, 0x0006, // 1
0X0007, 0x000C, 0X0009, 0x004A, 0X000B, 0x0018, 0X000D, 0x0036, 0X000E, 0x002C, 0X000E, 0x002A, 0X0005, 0x000A, // 2
0X0008, 0x0008, 0X000B, 0x0016, 0X000D, 0x0028, 0X000E, 0x0028, 0X0006, 0x000E, // 3
0X0009, 0x0048, 0X000D, 0x0038, 0X000E, 0x0026, 0X0006, 0x000C, // 4
0X000B, 0x001E, 0X000D, 0x0024, 0X0007, 0x000E, // 5
0X000B, 0x0012, 0X000E, 0x0024, 0X0007, 0x000A, // 6
0X000D, 0x003C, 0X0007, 0x0008, // 7
0X000D, 0x002A, 0X0008, 0x000E, // 8
0X000D, 0x0022, 0X0008, 0x000A, // 9
0X000E, 0x0022, 0X0009, 0x004E, // 10
0X000E, 0x0020, 0X0009, 0x0046, // 11
0X0009, 0x0044, // 12
0X0009, 0x0040, // 13
0X000B, 0x001C, // 14
0X000B, 0x001A, // 15
0X000B, 0x0010, // 16
0X000D, 0x003E, // 17
0X000D, 0x0034, // 18
0X000D, 0x0032, // 19
0X000D, 0x002E, // 20
0X000D, 0x002C, // 21
0X000E, 0x003E, // 22
0X000E, 0x003C, // 23
0X000E, 0x003A, // 24
0X000E, 0x0038, // 25
0X000E, 0x0036 // 26
};
/*
* This table lists the maximum level represented in the * VLC table for a given run. If the level exceeds the * max, then escape codes must be used to encode the * run & level. * The table entries are of the form {maxlevel, ptr to table for this run}. */
T_MAXLEVEL_PTABLE TCOEF_RUN_MAXLEVEL[65] = { {15, &VLC_TCOEF[0]}, // run of 0
{ 7, &VLC_TCOEF[15*2]}, // run of 1
{ 5, &VLC_TCOEF[22*2]}, // run of 2
{ 4, &VLC_TCOEF[27*2]}, // run of 3
{ 3, &VLC_TCOEF[31*2]}, // run of 4
{ 3, &VLC_TCOEF[34*2]}, // run of 5
{ 2, &VLC_TCOEF[37*2]}, // run of 6
{ 2, &VLC_TCOEF[39*2]}, // run of 7
{ 2, &VLC_TCOEF[41*2]}, // run of 8
{ 2, &VLC_TCOEF[43*2]}, // run of 9
{ 2, &VLC_TCOEF[45*2]}, // run of 10
{ 1, &VLC_TCOEF[47*2]}, // run of 11
{ 1, &VLC_TCOEF[48*2]}, // run of 12
{ 1, &VLC_TCOEF[49*2]}, // run of 13
{ 1, &VLC_TCOEF[50*2]}, // run of 14
{ 1, &VLC_TCOEF[51*2]}, // run of 15
{ 1, &VLC_TCOEF[52*2]}, // run of 16
{ 1, &VLC_TCOEF[53*2]}, // run of 17
{ 1, &VLC_TCOEF[54*2]}, // run of 18
{ 1, &VLC_TCOEF[55*2]}, // run of 19
{ 1, &VLC_TCOEF[56*2]}, // run of 20
{ 1, &VLC_TCOEF[57*2]}, // run of 21
{ 1, &VLC_TCOEF[58*2]}, // run of 22
{ 1, &VLC_TCOEF[59*2]}, // run of 23
{ 1, &VLC_TCOEF[60*2]}, // run of 24
{ 1, &VLC_TCOEF[61*2]}, // run of 25
{ 1, &VLC_TCOEF[62*2]}, // run of 26
{ 0, 0}, // run of 27 not in VLC table
{ 0, 0}, // run of 28 not in VLC table
{ 0, 0}, // run of 29 not in VLC table
{ 0, 0}, // run of 30 not in VLC table
{ 0, 0}, // run of 31 not in VLC table
{ 0, 0}, // run of 32 not in VLC table
{ 0, 0}, // run of 33 not in VLC table
{ 0, 0}, // run of 34 not in VLC table
{ 0, 0}, // run of 35 not in VLC table
{ 0, 0}, // run of 36 not in VLC table
{ 0, 0}, // run of 37 not in VLC table
{ 0, 0}, // run of 38 not in VLC table
{ 0, 0}, // run of 39 not in VLC table
{ 0, 0}, // run of 40 not in VLC table
{ 0, 0}, // run of 41 not in VLC table
{ 0, 0}, // run of 42 not in VLC table
{ 0, 0}, // run of 43 not in VLC table
{ 0, 0}, // run of 44 not in VLC table
{ 0, 0}, // run of 45 not in VLC table
{ 0, 0}, // run of 46 not in VLC table
{ 0, 0}, // run of 47 not in VLC table
{ 0, 0}, // run of 48 not in VLC table
{ 0, 0}, // run of 49 not in VLC table
{ 0, 0}, // run of 50 not in VLC table
{ 0, 0}, // run of 51 not in VLC table
{ 0, 0}, // run of 52 not in VLC table
{ 0, 0}, // run of 53 not in VLC table
{ 0, 0}, // run of 54 not in VLC table
{ 0, 0}, // run of 55 not in VLC table
{ 0, 0}, // run of 56 not in VLC table
{ 0, 0}, // run of 57 not in VLC table
{ 0, 0}, // run of 58 not in VLC table
{ 0, 0}, // run of 59 not in VLC table
{ 0, 0}, // run of 60 not in VLC table
{ 0, 0}, // run of 61 not in VLC table
{ 0, 0}, // run of 62 not in VLC table
{ 0, 0}, // run of 63 not in VLC table
{ 0, 0} // run of 64 not in VLC table
};
/* VLC table for MBA
* Table is stored as {number of bits, code}. * The index to the table should be the MBA value. * The zero entry is not used. */ int VLC_MBA[34][2] = { {0, 0}, /* Not Used */ {1, 0x1}, /* 1 */ {3, 0x3}, /* 2 */ {3, 0x2}, /* 3 */ {4, 0x3}, /* 4 */ {4, 0x2}, /* 5 */ {5, 0x3}, /* 6 */ {5, 0x2}, /* 7 */ {7, 0x7}, /* 8 */ {7, 0x6}, /* 9 */ {8, 0xB}, /* 10 */ {8, 0xA}, /* 11 */ {8, 0x9}, /* 12 */ {8, 0x8}, /* 13 */ {8, 0x7}, /* 14 */ {8, 0x6}, /* 15 */ {10, 0x17}, /* 16 */ {10, 0x16}, /* 17 */ {10, 0x15}, /* 18 */ {10, 0x14}, /* 19 */ {10, 0x13}, /* 20 */ {10, 0x12}, /* 21 */ {11, 0x23}, /* 22 */ {11, 0x22}, /* 23 */ {11, 0x21}, /* 24 */ {11, 0x20}, /* 25 */ {11, 0x1F}, /* 26 */ {11, 0x1E}, /* 27 */ {11, 0x1D}, /* 28 */ {11, 0x1C}, /* 29 */ {11, 0x1B}, /* 30 */ {11, 0x1A}, /* 31 */ {11, 0x19}, /* 32 */ {11, 0x18} /* 33 */ };
/* VLC table for MTYPE
* Table is stored as {number of bits, code}. */ int VLC_MTYPE[10][2] = { {4, 0x1}, /* Intra : TCOEFF */ {7, 0x1}, /* Intra : MQUANT TCOEEF */ {1, 0x1}, /* Inter : CBP TCOEFF */ {5, 0x1}, /* Inter : MQUANT CBP TCOEFF */ {9, 0x1}, /* Inter MC : MVD */ {8, 0x1}, /* Inter MC : MVD CBP TCOEFF */ {10,0x1}, /* Inter MC : MQUANT MVD CBP TCOEFF */ {3, 0x1}, /* Inter MC FIL : MVD */ {2, 0x1}, /* Inter MC FIL : MVD CBP TCOEFF */ {6, 0x1} /* Inter MC FIL : MQUANT MVD CBP TCOEFF */ };
/* VLC table for CBP
* Table is stored as {number of bits, code}. */ int VLC_CBP[64][2] = { {0, 0}, /* Not Used - if zero it is not coded */ {5, 0x0B},/* 1 */ {5, 0x09},/* 2 */ {6, 0x0D},/* 3 */ {4, 0xD}, /* 4 */ {7, 0x17},/* 5 */ {7, 0x13},/* 6 */ {8, 0x1F},/* 7 */ {4, 0xC}, /* 8 */ {7, 0x16},/* 9 */
{7, 0x12},/* 10 */ {8, 0x1E},/* 11 */ {5, 0x13},/* 12 */ {8, 0x1B},/* 13 */ {8, 0x17},/* 14 */ {8, 0x13},/* 15 */ {4, 0xB}, /* 16 */ {7, 0x15},/* 17 */ {7, 0x11},/* 18 */ {8, 0x1D},/* 19 */
{5, 0x11},/* 20 */ {8, 0x19},/* 21 */ {8, 0x15},/* 22 */ {8, 0x11},/* 23 */ {6, 0x0F},/* 24 */ {8, 0x0F},/* 25 */ {8, 0x0D},/* 26 */ {9, 0x03},/* 27 */ {5, 0x0F},/* 28 */ {8, 0x0B},/* 29 */
{8, 0x07},/* 30 */ {9, 0x07},/* 31 */ {4, 0xA}, /* 32 */ {7, 0x14},/* 33 */ {7, 0x10},/* 34 */ {8, 0x1C},/* 35 */ {6, 0x0E},/* 36 */ {8, 0x0E},/* 37 */ {8, 0x0C},/* 38 */ {9, 0x02},/* 39 */
{5, 0x10},/* 40 */ {8, 0x18},/* 41 */ {8, 0x14},/* 42 */ {8, 0x10},/* 43 */ {5, 0x0E},/* 44 */ {8, 0x0A},/* 45 */ {8, 0x06},/* 46 */ {9, 0x06},/* 47 */ {5, 0x12},/* 48 */ {8, 0x1A},/* 49 */
{8, 0x16},/* 50 */ {8, 0x12},/* 51 */ {5, 0x0D},/* 52 */ {8, 0x09},/* 53 */ {8, 0x05},/* 54 */ {9, 0x05},/* 55 */ {5, 0x0C},/* 56 */ {8, 0x08},/* 57 */ {8, 0x04},/* 58 */ {9, 0x04},/* 59 */
{3, 0x7}, /* 60 */ {5, 0x0A},/* 61 */ {5, 0x08},/* 62 */ {6, 0x0C},/* 63 */ };
/* VLC table for MVD
* Table is stored as {number of bits, code}. */ int VLC_MVD[32][2] = { {11, 0x19}, /* -16 & 16 */ {11, 0x1B}, /* -15 & 17 */ {11, 0x1D}, /* -14 & 18 */ {11, 0x1F}, /* -13 & 19 */ {11, 0x21}, /* -12 & 20 */ {11, 0x23}, /* -11 & 21 */ {10, 0x13}, /* -10 & 22 */ {10, 0x15}, /* -9 & 23 */ {10, 0x17}, /* -8 & 24 */ { 8, 0x07}, /* -7 & 25 */ { 8, 0x09}, /* -6 & 26 */ { 8, 0x0B}, /* -5 & 27 */ { 7, 0x07}, /* -4 & 28 */ { 5, 0x03}, /* -3 & 29 */ { 4, 0x3}, /* -2 & 30 */ { 3, 0x3}, /* -1 */ { 1, 0x1}, /* 0 */ { 3, 0x2}, /* 1 */ { 4, 0x2}, /* 2 & -30 */ { 5, 0x02}, /* 3 & -29 */ { 7, 0x06}, /* 4 & -28 */ { 8, 0x0A}, /* 5 & -27 */ { 8, 0x08}, /* 6 & -26 */ { 8, 0x06}, /* 7 & -25 */ {10, 0x16}, /* 8 & -24 */ {10, 0x14}, /* 9 & -23 */ {10, 0x12}, /* 10 & -22 */ {11, 0x22}, /* 11 & -21 */ {11, 0x20}, /* 12 & -20 */ {11, 0x1E}, /* 13 & -19 */ {11, 0x1C}, /* 14 & -18 */ {11, 0x1A} /* 15 & -17 */ };
/* Table to limit quant changes through out a row of Macro Blocks */ static U8 QPMaxTbl[32] = { 0, /* Not Used */ 1, /* Not Used when clamp to (2,31) */ 1, /* 2 */ 1, /* 3 */ 2, /* 4 */ 2, /* 5 */ 2, /* 6 */ 2, /* 7 */ 2, /* 8 */ 2, /* 9 */ 2, /* 10 */ 2, /* 11 */ 2, /* 12 */ 2, /* 13 */ 2, /* 14 */ 2, /* 15 */ 2, /* 16 */ 2, /* 17 */ 2, /* 18 */ 2, /* 19 */ 2, /* 20 */ 2, /* 21 */ 2, /* 22 */ 2, /* 23 */ 2, /* 24 */ 2, /* 25 */ 2, /* 26 */ 2, /* 27 */ 2, /* 28 */ 2, /* 29 */ 2, /* 30 */ 2 /* 31 */ };
/* Table to limit Quant changes between Rows of Marco Blocks */ extern U8 MaxChangeRowMBTbl[32];
/*****************************************************************************
* * GOB_Q_RLE_VLC_WriteBS * * Quantize and RLE each macroblock, then VLC and write to stream */ void GOB_Q_RLE_VLC_WriteBS( T_H263EncoderCatalog * EC, I32 *piDCTCoefs, U8 **ppu8BitStream, U8 *pu8BitOffset, UN unStartingMB, UN unGQuant, BOOL bOverFlowWarningFlag, BOOL bRTPHeader, //RTP: switch
U32 uGOBNumber, // RTP: info
U8 u8QPMin ) { T_MBlockActionStream *pCurrMB = NULL; T_MBlockActionStream *pLastMB = NULL; int iMBIndex; int iLastMBIndex = -1; UN unCurrentMB; U32 uCheckSum; UN unMBA; UN unLastEncodedMBA=0; // RTP: information
UN unLastCodedMB = 0; // RTP: information
UN unCBP; UN unMQuant; UN unLastEncodedMQuant; UN unMType; UN bWriteTCOEFF; UN bWriteMVD; UN bWriteMQuant; I8 MBRunValSign[65*3*6], *pi8EndAddress, *rvs; T_MBlockActionStream *pMBActionStream = EC->pU8_MBlockActionStream; int bIntraBlock; int inPrecedingHMV; int inPrecedingVMV; int inHDelta; int inVDelta; U32 uCumFrmSize; U32 uBlockCount; ENC_BITSTREAM_INFO * pBSInfo = &EC->BSInfo; UN unMQuantLast;
U32 SWDmax[3] = {0,0,0}; U32 SWDmin[3] = {65536,65536,65536}; U32 SWDrange[3] = {0,0,0}; U32 SWDSum[3] = {0,0,0}; U32 SWDNum[3] = {0,0,0}; double SWDAvg[3] = {0.0,0.0,0.0}; double Step, Delta; int QPMax; int NeedClamp=0; int irow; U8 SaveQuants[3]; UN unSaveMQuant;
unMQuant = unGQuant; unMQuantLast = unMQuant; // save last MQuant so can reset if needed
/* initially it should be the same because the GOB header
* included the GQuant. */ unLastEncodedMQuant = unMQuant;
unSaveMQuant = unGQuant; SaveQuants[0] = unSaveMQuant;
/* New code to modify Quant inside a row of MB based on SWD */ /* Loop through each macroblock of the GOB to find min and max SWD
*/ pCurrMB = &pMBActionStream[unStartingMB]; for(irow = 0; irow < 3; irow++) { for(iMBIndex = irow*11 ; iMBIndex < (irow+1)*11; iMBIndex++, pLastMB = pCurrMB++) { if (pCurrMB->BlockType != INTRABLOCK) { // ASSERT(pCurrMB->SWD >= 0); Always True
SWDSum[irow] += pCurrMB->SWD; SWDNum[irow]++; if (pCurrMB->SWD > SWDmax[irow]) SWDmax[irow] = pCurrMB->SWD; if (pCurrMB->SWD < SWDmin[irow]) SWDmin[irow] = pCurrMB->SWD; } } } SWDrange[0] = SWDmax[0] - SWDmin[0]; SWDrange[1] = SWDmax[1] - SWDmin[1]; SWDrange[2] = SWDmax[2] - SWDmin[2];
if (SWDNum[0] != 0) SWDAvg[0] = (double) SWDSum[0] / SWDNum[0]; else SWDAvg[0] = 0.0;
if (SWDNum[1] != 0) SWDAvg[1] = (double) SWDSum[1] / SWDNum[1]; else SWDAvg[1] = 0.0;
if (SWDNum[2] != 0) SWDAvg[2] = (double) SWDSum[2] / SWDNum[2]; else SWDAvg[2] = 0.0;
QPMax = unGQuant + QPMaxTbl[unGQuant]; if (QPMax > 31) QPMax = 32;
if ((SWDAvg[0] - SWDmin[0]) != 0) Step = (double) (QPMax - unGQuant)/(SWDAvg[0] - SWDmin[0]); else Step = 0.0;
/* Loop through each macroblock of the GOB.
*/ pLastMB = NULL; pCurrMB = &pMBActionStream[unStartingMB]; for(iMBIndex = 0 ; iMBIndex < 33; iMBIndex++, pLastMB = pCurrMB++) {
unCurrentMB = unStartingMB + (unsigned int)iMBIndex;
#ifdef DEBUG_ENC
wsprintf(string, "MB #%d: QP=%d", unCurrentMB, unMQuant); trace(string); #endif
if (bRTPHeader) { H261RTP_MBUpdateBsInfo(EC, pCurrMB, unLastEncodedMQuant, (U32 )unLastEncodedMBA, uGOBNumber, *ppu8BitStream, (U32) *pu8BitOffset, unCurrentMB, unLastCodedMB ); }
unMQuant = unMQuantLast; // reset MQuant in case needed to
// to raise on previous MB to avoid
// Quant clamping artifact.
/* Look to update the Quant on each new row.
*/ if (EC->bBitRateControl && ((iMBIndex == 11) || (iMBIndex == 22))) { /* Calculate number of bytes used in frame so far.
*/ uCumFrmSize = *ppu8BitStream - EC->pU8_BitStream;
unMQuant = CalcMBQUANT(&(EC->BRCState), EC->uBitUsageProfile[unCurrentMB], EC->uBitUsageProfile[EC->NumMBs], uCumFrmSize, EC->PictureHeader.PicCodType);
QPMax = unMQuant + QPMaxTbl[unMQuant]; if (QPMax > 31) QPMax = 32; if ((SWDAvg[iMBIndex/11] - SWDmin[iMBIndex/11]) != 0) Step = (double) (QPMax - unMQuant)/(SWDAvg[iMBIndex/11] - SWDmin[iMBIndex/11]); else Step = 0.0;
EC->uBitUsageProfile[unCurrentMB] = uCumFrmSize;
if (bOverFlowWarningFlag) { DBOUT("DON'T CHANGE QUANT SET unMQuant = unGQuant"); unMQuant = unGQuant; } else if ((int)unMQuant > ((int)unLastEncodedMQuant + MaxChangeRowMBTbl[unGQuant])) { DBOUT("Slowing MQuant increase + [1-4]"); unMQuant = unLastEncodedMQuant + MaxChangeRowMBTbl[unMQuant]; } else if ((int)unMQuant < ((int)unLastEncodedMQuant -2)) { DBOUT("Slowing MQuant decrease to -2"); unMQuant = unLastEncodedMQuant -2; }
//CLAMP_N_TO(unMQuant,6,31);
if (EC->BRCState.uTargetFrmSize == 0) { CLAMP_N_TO(unMQuant,6,31); } else { CLAMP_N_TO(unMQuant, u8QPMin, 31); } #ifdef DEBUG_BRC
wsprintf(string,"At MB %d MQuant=%d", unCurrentMB, unMQuant); DBOUT(string); #endif
#ifdef DEBUG_RECOMPRESS
wsprintf(string,"At MB %d MQuant=%d uCumFrmSize=%d", unCurrentMB, unMQuant,uCumFrmSize*8); DBOUT(string); //trace(string);
#endif
//EC->uQP_cumulative += unMQuant;
//EC->uQP_count++;
unSaveMQuant = unMQuant; if (iMBIndex == 11) SaveQuants[1] = unSaveMQuant; else SaveQuants[2] = unSaveMQuant; }
/* new MB Quant code */ if (pCurrMB->BlockType != INTRABLOCK) { if (EC->BRCState.uTargetFrmSize != 0) { if (pCurrMB->SWD >= SWDAvg[iMBIndex/11]) { Delta = (double) -1.0 * ((double) (pCurrMB->SWD - SWDAvg[iMBIndex/11]) * Step); if (Delta < -2.0) { Delta = -2.0; NeedClamp++; } } else { Delta = (double) (SWDAvg[iMBIndex/11] - pCurrMB->SWD)*Step; } } else Delta = 0.0;
if (Delta > 0.0) { unMQuant = unSaveMQuant + (int) (Delta); /* Need to clamp again, but only worry about upper limit */ if (unMQuant > 31) unMQuant = 31; } else { unMQuant = unSaveMQuant + (int) (Delta - 0.5); /* Need to clamp again, but only worry about lower limit */ if (EC->BRCState.uTargetFrmSize == 0) { if (unMQuant < 6) unMQuant = 6; } else { if (unMQuant < 2) unMQuant = 2; } }
} /* end new stuff */
/* Quantize and RLE each block in the macroblock, skipping empty blocks as denoted by pu8CodedBlocks.
* If any more blocks are empty after quantization then the appropriate pu8CodedBlocks bit is cleared. */ //ASSERT(unMQuant >= 6 && unMQuant <= 31); /* CLAMP_N_TO(var,6,31) */
if (EC->BRCState.uTargetFrmSize == 0) { ASSERT(unMQuant >= 6 && unMQuant <= 31); /* CLAMP_N_TO(var,6,31) */ } else { ASSERT(unMQuant >= 2 && unMQuant <= 31); /* CLAMP_N_TO(var,6,31) */ }
/* Check iDCTCoefs to see if need to raise quant level to avoid
* clamping artifacts. */ // first block is at piDCTCoefs
// second block is at piDCTCoefs + 0x80 and so on
// coefficients are unsigned shorts
// first coefficient is at 6 bytes, 3 words
// second coefficient is at 38 bytes, 19 words
// third coefficient is at 4 bytes, 2 words
// forth coefficient is at 36 bytes, 18 words
unMQuantLast = unMQuant;
if (unMQuant < 6) { I8 iBlockNum; U8 u8Bitmask = 1; I32 * ptmpiDCTCoefs = piDCTCoefs; int coef0, coef1; int biggestcoefval = -2048; int smallestcoefval = 2048;
#ifdef DEBUG_QUANT
wsprintf(string,"At MB %d MQuant=%d", unCurrentMB, unMQuant); DBOUT(string); //trace(string);
#endif
for(iBlockNum = 0; iBlockNum < 6; iBlockNum++, u8Bitmask <<= 1) { /* Skip this block if not coded.
*/ if( (pCurrMB->CodedBlocks & u8Bitmask) == 0) { continue; } if(IsIntraBlock(pCurrMB->BlockType)) // if Intra
{ coef0 = ((int)*((U16*)ptmpiDCTCoefs+3)) >> 4; } else { coef0 = ((int)(*((U16*)ptmpiDCTCoefs+3) - 0x8000) ) >> 4; }
coef1 = ((int)(*((U16*)ptmpiDCTCoefs+19) - 0x8000)) >> 4;
#ifdef DEBUG_QUANT
wsprintf(string,"At Block %d 0 = %x %d", iBlockNum,coef0,coef0); //DBOUT(string);
//trace(string);
#endif
if (coef0 > biggestcoefval) { biggestcoefval = coef0; } if (coef1 > biggestcoefval) { biggestcoefval = coef1; }
if (coef0 < smallestcoefval) { smallestcoefval = coef0; } if (coef1 < smallestcoefval) { smallestcoefval = coef1; }
ptmpiDCTCoefs += 32; }
#ifdef DEBUG_QUANT
wsprintf(string,"biggest = %x %d, smallest = %x %d", biggestcoefval, biggestcoefval, smallestcoefval, smallestcoefval); DBOUT(string); // trace(string);
#endif
if (unMQuant == 5) { if ((biggestcoefval > 1275) || (smallestcoefval < -1275)) unMQuant = 6; } else if (unMQuant == 4) { if ((biggestcoefval > 1275) || (smallestcoefval < -1275)) unMQuant = 6; else if ((biggestcoefval > 1019) || (smallestcoefval < -1019)) unMQuant = 5; } else if (unMQuant == 3) { if ((biggestcoefval > 1275) || (smallestcoefval < -1275)) unMQuant = 6; else if ((biggestcoefval > 1019) || (smallestcoefval < -1019)) unMQuant = 5; else if ((biggestcoefval > 765) || (smallestcoefval < -765)) unMQuant = 4; } else { if ((biggestcoefval > 1275) || (smallestcoefval < -1275)) unMQuant = 6; else if ((biggestcoefval > 1019) || (smallestcoefval < -1019)) unMQuant = 5; else if ((biggestcoefval > 765) || (smallestcoefval < -765)) unMQuant = 4; else if ((biggestcoefval > 509) || (smallestcoefval < -509)) unMQuant = 3; }
#ifdef DEBUG_QUANT
wsprintf(string,"At MB %d MQuant=%d", unCurrentMB, unMQuant); DBOUT(string); //trace(string);
#endif
}
/* This is the place to trace how Quant on a MB bases is varying
*/ EC->uQP_cumulative += unMQuant; EC->uQP_count++;
pi8EndAddress = MB_Quantize_RLE( &piDCTCoefs, (I8 *) MBRunValSign, &(pCurrMB->CodedBlocks), pCurrMB->BlockType, unMQuant, &uCheckSum );
pBSInfo->uQuantsUsedOnBlocks[unMQuant] += 6;
bWriteMVD = (pCurrMB->BlkY1.PHMV != 0) || (pCurrMB->BlkY1.PVMV != 0) || (IsSLFBlock(pCurrMB->BlockType)) ;
if (IsInterBlock(pCurrMB->BlockType)) { /* Check if the Inter block is not coded?
*/ if ( ((pCurrMB->CodedBlocks & 0x3f) == 0) && (! bWriteMVD) ) { #ifdef DEBUG_MBLK
wsprintf(string, "Inter MB (index=#%d) has neither Coeff nor MV - skipping", unCurrentMB); DBOUT(string); #endif
#ifdef FORCE_STUFFING
PutBits(FIELDVAL_MBA_STUFFING, FIELDLEN_MBA_STUFFING, ppu8CurBitStream, pu8BitOffset); #endif
continue; } }
#ifdef CHECKSUM_MACRO_BLOCK
/* Write a checksum before all coded blocks
*/ WriteMBCheckSum(uCheckSum, EC->pU8_BitStream,ppu8BitStream, pu8BitOffset, unCurrentMB); #endif
/* Calculate the MB header information
*/
unMBA = iMBIndex - iLastMBIndex; iLastMBIndex = iMBIndex; unLastEncodedMBA = unMBA; unLastCodedMB = iMBIndex; /* Note: The calculation of whether to write MQuant is done after
* skipping macro blocks in order to handle the case that the 11th * or 22nd macro blocks are skipped. If they are skipped then * the next macro block will be used to write the new quant value. */
if(IsIntraBlock(pCurrMB->BlockType)) { ASSERT(pCurrMB->BlockType == INTRABLOCK); if (EC->PictureHeader.PicCodType != INTRAPIC) { pCurrMB->InterCodeCnt = ((U8)unCurrentMB)&0x7; }
bIntraBlock = 1; unCBP = 0; /* Never write CBP for Intra blocks */ uBlockCount = 6; bWriteTCOEFF = 1; /* Always include TCOEFF for Intra blocks */ /* Since we always have coefficients for Intra MBs we can always update
* the MQuant value. */ bWriteMQuant = (unMQuant != unLastEncodedMQuant); unLastEncodedMQuant = unMQuant; unMType = 0 + bWriteMQuant; /* Calculate MTYPE */ bWriteMVD = 0; /* No motion vectors for INTRA */ } else { ASSERT(IsInterBlock(pCurrMB->BlockType)); bIntraBlock = 0;
unCBP = (pCurrMB->CodedBlocks & 0x1) << 5; /* x0 0000 */ unCBP |= (pCurrMB->CodedBlocks & 0x2) << 3; /* 0x 0000 */ unCBP |= (pCurrMB->CodedBlocks & 0x4) << 1; /* 00 x000 */ unCBP |= (pCurrMB->CodedBlocks & 0x8) >> 1; /* 00 0x00 */ unCBP |= (pCurrMB->CodedBlocks & 0x10) >> 3; /* 00 00x0 */ unCBP |= (pCurrMB->CodedBlocks & 0x20) >> 5; /* 00 000x */
uBlockCount = 0; if (unCBP & 0x1) uBlockCount++; if (unCBP & 0x2) uBlockCount++; if (unCBP & 0x4) uBlockCount++; if (unCBP & 0x8) uBlockCount++; if (unCBP & 0x10) uBlockCount++; if (unCBP & 0x20) uBlockCount++;
/* Increment the count if it is transmitted
* "should be forcibly updated at least once every * 132 times it is transmitted" 3.4 */ if (uBlockCount != 0 ) { pCurrMB->InterCodeCnt++; } bWriteTCOEFF = (unCBP != 0); if (bWriteTCOEFF) { /* We can only update the MQuant value when we have coefficients
*/ bWriteMQuant = (unMQuant != unLastEncodedMQuant); unLastEncodedMQuant = unMQuant; } else { bWriteMQuant = 0; } #ifdef CHECKSUM_MACRO_BLOCK
/* Either there are coefficients or the checksum should equal zero
*/ ASSERT(bWriteTCOEFF || uCheckSum == 0); #endif
/* Calculate MType
*/ unMType = 1; if (bWriteMVD) { unMType += 3; if (IsSLFBlock(pCurrMB->BlockType)) { unMType += 3; } } unMType += bWriteTCOEFF; unMType += bWriteMQuant;
ASSERT(unMType > 1 && unMType < 10); }
ASSERT(unMQuant >= 1 && unMQuant <= 31); ASSERT(uBlockCount <= 6); pBSInfo->uQuantsTransmittedOnBlocks[unMQuant] += uBlockCount;
if (bWriteMVD) { /* Find the preceding motion vectors
*/ if ( (unMBA != 1) || /* skipped one or more MB */ ((unCurrentMB % 11) == 0) ) /* first MB in each row */ { inPrecedingHMV = 0; inPrecedingVMV = 0; } else { inPrecedingHMV = pLastMB->BlkY1.PHMV; inPrecedingVMV = pLastMB->BlkY1.PVMV; } /* adjust vectors:
*/ inHDelta = pCurrMB->BlkY1.PHMV - inPrecedingHMV; ASSERT((inHDelta & 0x1) == 0); ASSERT((inHDelta >> 1) == (inHDelta / 2)); inHDelta >>= 1; /* Adjust to integer pels */ if(inHDelta > 15) /* Adjust to the range of -16...+15 */ inHDelta -= 32; if(inHDelta < -16) inHDelta += 32; inHDelta = inHDelta + 16; /* 0 is at offset 16 */
inVDelta = pCurrMB->BlkY1.PVMV - inPrecedingVMV; ASSERT((inVDelta & 0x1) == 0); ASSERT((inVDelta >> 1) == (inVDelta / 2)); inVDelta >>= 1; if(inVDelta > 15) inVDelta -= 32; if(inVDelta < -16) inVDelta += 32; inVDelta = inVDelta + 16;
#ifndef RING0
#ifdef DEBUG_PRINTMV
{ char buf132[132]; int iLength; iLength = wsprintf(buf132, "MB # %d :: H MVD = %d; index = %d :: V MVD = %d; index = %d", unCurrentMB, pCurrMB->BlkY1.PHMV / 2, inHDelta, pCurrMB->BlkY1.PVMV / 2, inVDelta); DBOUT(buf132); ASSERT(iLength < 132); } #endif
#endif
} else { /* MBs without MVD need to have zero motion vectors because of
* Rule 3) under 4.2.3.4 */ pCurrMB->BlkY1.PHMV = 0; pCurrMB->BlkY1.PVMV = 0; }
/* we should only have MQuant if we have coefficients
*/ if (bWriteMQuant) { ASSERT(bWriteTCOEFF); }
/* we should only have CBP if we have coefficients
*/ if (unCBP) { ASSERT(bWriteTCOEFF); ASSERT(uBlockCount > 0); }
/* Write the MacroBlock Header
*/
#ifndef RING0
#ifdef DEBUG_MBLK
{ int iLength; char buf180[180]; iLength = wsprintf(buf180, "Enc #%d: MBType=%ld unNextMQuant=%d MQuant=%ld bWriteMVD=%d MVDH=%ld MVDV=%ld CBP=%ld", (int) unCurrentMB, unMType, (int) bWriteMQuant, unMQuant, (int) bWriteMVD, pCurrMB->BlkY1.PHMV / 2, pCurrMB->BlkY1.PVMV / 2, unCBP); DBOUT(buf180); ASSERT(iLength < 180); } #endif
#endif
/* MBA
*/ PutBits(VLC_MBA[unMBA][1], VLC_MBA[unMBA][0], ppu8BitStream, pu8BitOffset); /* MTYPE
*/ pBSInfo->uMTypeCount[unMType]++; pBSInfo->uBlockCount[unMType] += uBlockCount; PutBits(VLC_MTYPE[unMType][1], VLC_MTYPE[unMType][0], ppu8BitStream, pu8BitOffset);
/* MQUANT
*/ if (bWriteMQuant) { ASSERT(unMQuant > 0 && unMQuant < 32); /* 4.2.2.3 */ PutBits((int)unMQuant, FIELDLEN_MQUANT, ppu8BitStream, pu8BitOffset); }
/* MVD
*/ if (bWriteMVD) { ASSERT(inHDelta >= 0 && inHDelta < 32); ASSERT(inVDelta >= 0 && inVDelta < 32); PutBits(VLC_MVD[inHDelta][1], VLC_MVD[inHDelta][0], ppu8BitStream, pu8BitOffset); PutBits(VLC_MVD[inVDelta][1], VLC_MVD[inVDelta][0], ppu8BitStream, pu8BitOffset); }
/* CBP
*/ if (unCBP != 0) { PutBits(VLC_CBP[unCBP][1], VLC_CBP[unCBP][0], ppu8BitStream, pu8BitOffset); }
/* TCOEFF
*/ if (bWriteTCOEFF) { /*
* Encode intra DC and all run/val pairs. */ rvs = MBRunValSign; MBEncodeVLC( &rvs, NULL, pCurrMB->CodedBlocks, ppu8BitStream, pu8BitOffset, bIntraBlock, FALSE); }
} /* for iMBIndex */
} /* end of GOB_Q_RLE_VLC_WriteBS() */
void GOB_VLC_WriteBS( T_H263EncoderCatalog * EC, I8 *pMBRVS_Luma, I8 *pMBRVS_Chroma, U8 **ppu8BitStream, U8 *pu8BitOffset, UN unGQuant, UN unStartingMB, BOOL bRTPHeader, //RTP: switch
U32 uGOBNumber // RTP: info
) { T_MBlockActionStream *pCurrMB = NULL; T_MBlockActionStream *pLastMB = NULL; int iMBIndex; int iLastMBIndex = -1; UN unCurrentMB; UN unMBA; UN unLastEncodedMBA=0; // RTP: information
UN unLastCodedMB = 0; // RTP: information
UN unCBP; UN unMQuant; UN unLastEncodedMQuant; UN unMType; UN bWriteTCOEFF; UN bWriteMVD; UN bWriteMQuant; // I8 MBRunValSign[65*3*6], *pi8EndAddress, *rvs;
T_MBlockActionStream *pMBActionStream = EC->pU8_MBlockActionStream; int bIntraBlock; int inPrecedingHMV; int inPrecedingVMV; int inHDelta; int inVDelta; // U32 uCumFrmSize;
U32 uBlockCount; ENC_BITSTREAM_INFO * pBSInfo = &EC->BSInfo;
unMQuant = unGQuant; unLastEncodedMQuant = unGQuant; /* Loop through each macroblock of the GOB.
*/
pLastMB = NULL; pCurrMB = &pMBActionStream[unStartingMB]; for(iMBIndex = 0 ; iMBIndex < 33; iMBIndex++, pLastMB = pCurrMB++) {
unCurrentMB = unStartingMB + (unsigned int)iMBIndex;
#ifdef DEBUG_ENC
wsprintf(string, "MB #%d: QP=%d", unCurrentMB, unMQuant); trace(string); #endif
if (bRTPHeader) { H261RTP_MBUpdateBsInfo(EC, pCurrMB, unLastEncodedMQuant, (U32 )unLastEncodedMBA, uGOBNumber, *ppu8BitStream, (U32) *pu8BitOffset, unCurrentMB, unLastCodedMB ); }
EC->uQP_cumulative += unMQuant; EC->uQP_count++;
bWriteMVD = (pCurrMB->BlkY1.PHMV != 0) || (pCurrMB->BlkY1.PVMV != 0) || (IsSLFBlock(pCurrMB->BlockType)) ;
if (IsInterBlock(pCurrMB->BlockType)) { /* Check if the Inter block is not coded?
*/ if ( ((pCurrMB->CodedBlocks & 0x3f) == 0) && (! bWriteMVD) ) { #ifdef DEBUG_MBLK
wsprintf(string, "Inter MB (index=#%d) has neither Coeff nor MV - skipping", unCurrentMB); DBOUT(string); #endif
#ifdef FORCE_STUFFING
PutBits(FIELDVAL_MBA_STUFFING, FIELDLEN_MBA_STUFFING, ppu8CurBitStream, pu8BitOffset); #endif
continue; } }
#ifdef CHECKSUM_MACRO_BLOCK
/* Write a checksum before all coded blocks
*/ WriteMBCheckSum(uCheckSum, EC->pU8_BitStream,ppu8BitStream, pu8BitOffset, unCurrentMB); #endif
/* Calculate the MB header information
*/
unMBA = iMBIndex - iLastMBIndex; iLastMBIndex = iMBIndex; unLastEncodedMBA = unMBA; unLastCodedMB = iMBIndex; /* Note: The calculation of whether to write MQuant is done after
* skipping macro blocks in order to handle the case that the 11th * or 22nd macro blocks are skipped. If they are skipped then * the next macro block will be used to write the new quant value. */
if(IsIntraBlock(pCurrMB->BlockType)) { ASSERT(pCurrMB->BlockType == INTRABLOCK); if (EC->PictureHeader.PicCodType != INTRAPIC) { pCurrMB->InterCodeCnt = ((U8)unCurrentMB)&0x7; }
bIntraBlock = 1; unCBP = 0; /* Never write CBP for Intra blocks */ uBlockCount = 6; bWriteTCOEFF = 1; /* Always include TCOEFF for Intra blocks */ /* Since we always have coefficients for Intra MBs we can always update
* the MQuant value. */ //bWriteMQuant = (unMQuant != unLastEncodedMQuant);
//unLastEncodedMQuant = unMQuant;
bWriteMQuant=0; unMType = 0; // + bWriteMQuant; /* Calculate MTYPE */
bWriteMVD = 0; /* No motion vectors for INTRA */ } else { ASSERT(IsInterBlock(pCurrMB->BlockType)); bIntraBlock = 0;
unCBP = (pCurrMB->CodedBlocks & 0x1) << 5; /* x0 0000 */ unCBP |= (pCurrMB->CodedBlocks & 0x2) << 3; /* 0x 0000 */ unCBP |= (pCurrMB->CodedBlocks & 0x4) << 1; /* 00 x000 */ unCBP |= (pCurrMB->CodedBlocks & 0x8) >> 1; /* 00 0x00 */ unCBP |= (pCurrMB->CodedBlocks & 0x10) >> 3; /* 00 00x0 */ unCBP |= (pCurrMB->CodedBlocks & 0x20) >> 5; /* 00 000x */
uBlockCount = 0; if (unCBP & 0x1) uBlockCount++; if (unCBP & 0x2) uBlockCount++; if (unCBP & 0x4) uBlockCount++; if (unCBP & 0x8) uBlockCount++; if (unCBP & 0x10) uBlockCount++; if (unCBP & 0x20) uBlockCount++;
/* Increment the count if it is transmitted
* "should be forcibly updated at least once every * 132 times it is transmitted" 3.4 */ if (uBlockCount != 0 ) { pCurrMB->InterCodeCnt++; } bWriteTCOEFF = (unCBP != 0); bWriteMQuant = 0; #ifdef CHECKSUM_MACRO_BLOCK
/* Either there are coefficients or the checksum should equal zero
*/ ASSERT(bWriteTCOEFF || uCheckSum == 0); #endif
/* Calculate MType
*/ unMType = 1; if (bWriteMVD) { unMType += 3; if (IsSLFBlock(pCurrMB->BlockType)) { unMType += 3; } } unMType += bWriteTCOEFF; unMType += bWriteMQuant;
ASSERT(unMType > 1 && unMType < 10); }
ASSERT(unMQuant >= 1 && unMQuant <= 31); ASSERT(uBlockCount <= 6); pBSInfo->uQuantsTransmittedOnBlocks[unMQuant] += uBlockCount;
if (bWriteMVD) { /* Find the preceding motion vectors
*/ if ( (unMBA != 1) || /* skipped one or more MB */ ((unCurrentMB % 11) == 0) ) /* first MB in each row */ { inPrecedingHMV = 0; inPrecedingVMV = 0; } else { inPrecedingHMV = pLastMB->BlkY1.PHMV; inPrecedingVMV = pLastMB->BlkY1.PVMV; } /* adjust vectors:
*/ inHDelta = pCurrMB->BlkY1.PHMV - inPrecedingHMV; ASSERT((inHDelta & 0x1) == 0); ASSERT((inHDelta >> 1) == (inHDelta / 2)); inHDelta >>= 1; /* Adjust to integer pels */ if(inHDelta > 15) /* Adjust to the range of -16...+15 */ inHDelta -= 32; if(inHDelta < -16) inHDelta += 32; inHDelta = inHDelta + 16; /* 0 is at offset 16 */
inVDelta = pCurrMB->BlkY1.PVMV - inPrecedingVMV; ASSERT((inVDelta & 0x1) == 0); ASSERT((inVDelta >> 1) == (inVDelta / 2)); inVDelta >>= 1; if(inVDelta > 15) inVDelta -= 32; if(inVDelta < -16) inVDelta += 32; inVDelta = inVDelta + 16;
#ifndef RING0
#ifdef DEBUG_PRINTMV
{ char buf132[132]; int iLength; iLength = wsprintf(buf132, "MB # %d :: H MVD = %d; index = %d :: V MVD = %d; index = %d", unCurrentMB, pCurrMB->BlkY1.PHMV / 2, inHDelta, pCurrMB->BlkY1.PVMV / 2, inVDelta); DBOUT(buf132); ASSERT(iLength < 132); } #endif
#endif
} else { /* MBs without MVD need to have zero motion vectors because of
* Rule 3) under 4.2.3.4 */ pCurrMB->BlkY1.PHMV = 0; pCurrMB->BlkY1.PVMV = 0; }
/* we should only have MQuant if we have coefficients
*/ if (bWriteMQuant) { ASSERT(bWriteTCOEFF); }
/* we should only have CBP if we have coefficients
*/ if (unCBP) { ASSERT(bWriteTCOEFF); ASSERT(uBlockCount > 0); }
/* Write the MacroBlock Header
*/
#ifndef RING0
#ifdef DEBUG_MBLK
{ int iLength; char buf180[180]; iLength = wsprintf(buf180, "Enc #%d: MBType=%ld bWriteMQuant=%ld MQuant=%ld bWriteMVD=%d MVDH=%ld MVDV=%ld CBP=%ld", (int) unCurrentMB, unMType, (int) bWriteMQuant, unMQuant, (int) bWriteMVD, pCurrMB->BlkY1.PHMV / 2, pCurrMB->BlkY1.PVMV / 2, unCBP); DBOUT(buf180); ASSERT(iLength < 180); } #endif
#endif
/* MBA
*/ PutBits(VLC_MBA[unMBA][1], VLC_MBA[unMBA][0], ppu8BitStream, pu8BitOffset); /* MTYPE
*/ pBSInfo->uMTypeCount[unMType]++; pBSInfo->uBlockCount[unMType] += uBlockCount; PutBits(VLC_MTYPE[unMType][1], VLC_MTYPE[unMType][0], ppu8BitStream, pu8BitOffset);
/* MQUANT
*/ if (bWriteMQuant) { ASSERT(unMQuant > 0 && unMQuant < 32); /* 4.2.2.3 */ PutBits((int)unMQuant, FIELDLEN_MQUANT, ppu8BitStream, pu8BitOffset); }
/* MVD
*/ if (bWriteMVD) { ASSERT(inHDelta >= 0 && inHDelta < 32); ASSERT(inVDelta >= 0 && inVDelta < 32); PutBits(VLC_MVD[inHDelta][1], VLC_MVD[inHDelta][0], ppu8BitStream, pu8BitOffset); PutBits(VLC_MVD[inVDelta][1], VLC_MVD[inVDelta][0], ppu8BitStream, pu8BitOffset); }
/* CBP
*/ if (unCBP != 0) { PutBits(VLC_CBP[unCBP][1], VLC_CBP[unCBP][0], ppu8BitStream, pu8BitOffset); }
/* TCOEFF
*/ if (bWriteTCOEFF) { /*
* Encode intra DC and all run/val pairs. */ MBEncodeVLC( &pMBRVS_Luma, &pMBRVS_Chroma, pCurrMB->CodedBlocks, ppu8BitStream, pu8BitOffset, bIntraBlock, 1); }
} /* for iMBIndex */
} /* end of GOB_VLC_WriteBS() */
/*****************************************************************************
* * MB_Quantize_RLE * * Takes the list of coefficient pairs from the DCT routine and returns a list * of Run/Level/Sign triples (each 1 byte). The end of the run/level/sign * triples for a block is signalled by an illegal combination (TBD). */ static I8 * MB_Quantize_RLE( I32 ** ppiDCTCoefs, I8 * pi8MBRunValTriplets, U8 * pu8CodedBlocks, U8 u8BlockType, I32 iQP, U32 * puCheckSum ) { I32 iBlockNumber; U8 u8Bitmask = 1; I8 * pi8EndAddress; U32 uCheckSum;
#ifdef DEBUG_DCT
int iDCTArray[64]; #endif
/*
* Loop through all 6 blocks of macroblock. */ uCheckSum = 0; for(iBlockNumber = 0; iBlockNumber < 6; iBlockNumber++, u8Bitmask <<= 1) {
#ifdef DEBUG_ENC
wsprintf(string, "Block #%d", iBlockNumber); trace(string); #endif
/* Skip this block if not coded.
*/ if( (*pu8CodedBlocks & u8Bitmask) == 0) { continue; }
#ifdef DEBUG_DCT
cnvt_fdct_output((unsigned short *) *ppiDCTCoefs, iDCTArray, IsIntraBlock(u8BlockType)); #endif
/*
* Quantize and run-length encode a block. */ pi8EndAddress = QUANTRLE(*ppiDCTCoefs, pi8MBRunValTriplets, iQP, (I32)u8BlockType);
#ifdef DEBUG_ENC
I8 * pi8; for(pi8 = pi8MBRunValTriplets; pi8 < pi8EndAddress; pi8+=3) { wsprintf(string, "(%u, %u, %d)", (unsigned char)*pi8, (unsigned char)*(pi8+1), (int)*(pi8+2) ); trace(string); } #endif
#ifdef CHECKSUM_MACRO_BLOCK
uCheckSum += ComputeCheckSum(pi8MBRunValTriplets, pi8EndAddress, iBlockNumber); #endif
/* Clear coded block bit for this block.
*/ if ( pi8EndAddress == pi8MBRunValTriplets) { ASSERT(u8BlockType != INTRABLOCK) /* should have at least INTRADC in an INTRA blck */ *pu8CodedBlocks &= ~u8Bitmask; } else if ( (pi8EndAddress == (pi8MBRunValTriplets+3)) && (u8BlockType == INTRABLOCK) ) { *pu8CodedBlocks &= ~u8Bitmask; pi8MBRunValTriplets = pi8EndAddress; } else { pi8MBRunValTriplets = pi8EndAddress; *pi8MBRunValTriplets = -1; /* Assign an illegal run to signal end of block. */ pi8MBRunValTriplets += 3; /* Increment to the next triple. */ }
/* Increment DCT Coefficient pointer to next block.
*/ *ppiDCTCoefs += 32; }
*puCheckSum = uCheckSum;
return pi8MBRunValTriplets;
} /* end MB_Quantize_RLE() */
void InitVLC(void) { int i; int run, level;
/*
* initialize INTRADC fixed length code table. */ for(i = 1; i < 254; i++) { FLC_INTRADC[i] = i; } FLC_INTRADC[0] = 1; FLC_INTRADC[128] = 255; FLC_INTRADC[254] = 254; FLC_INTRADC[255] = 254;
/*
* Initialize tcoef tables. */
for(i = 0; i < (NUMBER_OF_TCOEF_ENTRIES); i++) { VLC_TCOEF_TBL[i] = 0x0000FFFF; } for(run = 0; run < 64; run++) { for(level = 1; level <= TCOEF_RUN_MAXLEVEL[run].maxlevel; level++) { DWORD dwSize, dwCode;
dwSize = *(TCOEF_RUN_MAXLEVEL[run].ptable + (level - 1) * 2); dwSize <<= 16; dwCode = *(TCOEF_RUN_MAXLEVEL[run].ptable + (level - 1) * 2 + 1);
VLC_TCOEF_TBL[run + (level - 1) * 64] = dwCode; VLC_TCOEF_TBL[run + (level - 1) * 64] |= dwSize; } // end of for level
} // end of for run
} // InitVLC.
#ifdef CHECKSUM_MACRO_BLOCK
/*****************************************************************************
* * ComputeCheckSum * * Compute the checksum for this block */ static U32 ComputeCheckSum( I8 * pi8MBRunValTriplets, I8 * pi8EndAddress, I32 iBlockNumber) { I8 * pi8; U32 uRun; U32 uLevel; I32 iSign; U32 uSignBit; U32 uCheckSum = 0; #if CHECKSUM_MACRO_BLOCK_DETAIL
char buf80[80]; int iLength; #endif
for (pi8 = pi8MBRunValTriplets; pi8 < pi8EndAddress; ) { uRun = (U32)*pi8++; uLevel = (U32)(U8)*pi8++; iSign = (I32)*pi8++; if (iSign == 0) { uSignBit = 0; } else { ASSERT(iSign == 0xFFFFFFFF); uSignBit = 1; }
uCheckSum += uRun << 24; uCheckSum += uLevel << 8; uCheckSum += uSignBit;
#ifdef CHECKSUM_MACRO_BLOCK_DETAIL
iLength = wsprintf(buf80,"Block=%d R=0x%x L=0x%x S=%d, CheckSum=0x%x", iBlockNumber, uRun, uLevel, uSignBit, uCheckSum); DBOUT(buf80); ASSERT(iLength < 80); #endif
} return uCheckSum; } /* end ComputeCheckSum() */
/*****************************************************************************
* * WriteMBCheckSum * * Write the macro block checksum information. */ static void WriteMBCheckSum( U32 uCheckSum, U8 * pu8PictureStart, U8 ** ppu8BitStream, U8 * pu8BitOffset, UN unCurrentMB) { U32 uBytes; U32 uTempBytes; U8 u8Bits; U8 u8TempBits; UN unCount; UN unKey; UN unData;
uBytes = *ppu8BitStream - pu8PictureStart; u8Bits = *pu8BitOffset;
/* Add in the space for the checksum info (eleven 8-bit fields + 12 "1"s + MBA stuffing)
*/ uBytes += 12; u8Bits += 4 + FIELDLEN_MBA_STUFFING;
/* Adjust bits to < 7
*/ while (u8Bits > 7) { u8Bits -= 8; uBytes++; }
#if _DEBUG
#if CHECKSUM_MACRO_BLOCK_DETAIL
{ char buf80[80]; int iLength;
iLength = wsprintf(buf80,"MB=%d CHK=0x%x Bytes=%ld Bits=%d", unCurrentMB, uCheckSum, uBytes, (int) u8Bits); DBOUT(buf80); ASSERT(iLength < 80); } #endif
#endif
/* Write the MBASTUFFING value
*/ PutBits(FIELDVAL_MBA_STUFFING, FIELDLEN_MBA_STUFFING, ppu8BitStream, pu8BitOffset);
/* Write the data to the bitstream
*/
/* Key - a value of 1 in an 8-bit field following a "1"
*/ unKey = 1; PutBits(1, 1, ppu8BitStream, pu8BitOffset); PutBits(unKey, 8, ppu8BitStream, pu8BitOffset); /* Count - number of bits after the Count field.
*/ unCount = 9*8 + 10*1; /* nine 8-bit value and 10 "1"s. */ PutBits(1, 1, ppu8BitStream, pu8BitOffset); PutBits(unCount, 8, ppu8BitStream, pu8BitOffset);
/* Bytes - high to low bytes
*/ unData = (UN) ((uBytes >> 24) & 0xFF); PutBits(1, 1, ppu8BitStream, pu8BitOffset); PutBits(unData, 8, ppu8BitStream, pu8BitOffset);
unData = (UN) ((uBytes >> 16) & 0xFF); PutBits(1, 1, ppu8BitStream, pu8BitOffset); PutBits(unData, 8, ppu8BitStream, pu8BitOffset);
unData = (UN) ((uBytes >> 8) & 0xFF); PutBits(1, 1, ppu8BitStream, pu8BitOffset); PutBits(unData, 8, ppu8BitStream, pu8BitOffset);
unData = (UN) (uBytes & 0xFF); PutBits(1, 1, ppu8BitStream, pu8BitOffset); PutBits(unData, 8, ppu8BitStream, pu8BitOffset);
/* Bits
*/ unData = (UN) u8Bits; PutBits(1, 1, ppu8BitStream, pu8BitOffset); PutBits(unData, 8, ppu8BitStream, pu8BitOffset);
/* Checksum - high to low bytes
*/ unData = (UN) ((uCheckSum >> 24) & 0xFF); PutBits(1, 1, ppu8BitStream, pu8BitOffset); PutBits(unData, 8, ppu8BitStream, pu8BitOffset);
unData = (UN) ((uCheckSum >> 16) & 0xFF); PutBits(1, 1, ppu8BitStream, pu8BitOffset); PutBits(unData, 8, ppu8BitStream, pu8BitOffset);
unData = (UN) ((uCheckSum >> 8) & 0xFF); PutBits(1, 1, ppu8BitStream, pu8BitOffset); PutBits(unData, 8, ppu8BitStream, pu8BitOffset);
unData = (UN) (uCheckSum & 0xFF); PutBits(1, 1, ppu8BitStream, pu8BitOffset); PutBits(unData, 8, ppu8BitStream, pu8BitOffset);
/* Trailing 1 bit to avoid start code duplication.
*/ PutBits(1, 1, ppu8BitStream, pu8BitOffset);
/* Check that the pointers are correct
*/ uTempBytes = *ppu8BitStream - pu8PictureStart; u8TempBits = *pu8BitOffset;
while (u8TempBits > 7) { u8TempBits -= 8; uTempBytes++; }
ASSERT(uTempBytes == uBytes); ASSERT(u8TempBits == u8Bits);
} /* end WriteMBCheckSum() */
#endif
|