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.
1448 lines
47 KiB
1448 lines
47 KiB
/* *************************************************************************
|
|
** INTEL Corporation Proprietary Information
|
|
**
|
|
** This listing is supplied under the terms of a license
|
|
** agreement with INTEL Corporation and may not be copied
|
|
** nor disclosed except in accordance with the terms of
|
|
** that agreement.
|
|
**
|
|
** Copyright (c) 1995 Intel Corporation.
|
|
** Copyright (c) 1996 Intel Corporation.
|
|
** All Rights Reserved.
|
|
**
|
|
** *************************************************************************
|
|
*/
|
|
// $Author: CZHU $
|
|
// $Date: 06 Feb 1997 15:35:30 $
|
|
// $Archive: S:\h26x\src\dec\d3mvdec.cpv $
|
|
// $Header: S:\h26x\src\dec\d3mvdec.cpv 1.47 06 Feb 1997 15:35:30 CZHU $
|
|
// $Log: S:\h26x\src\dec\d3mvdec.cpv $
|
|
//
|
|
// Rev 1.47 06 Feb 1997 15:35:30 CZHU
|
|
// Changed | to ||
|
|
//
|
|
// Rev 1.46 24 Jan 1997 13:32:56 CZHU
|
|
//
|
|
// Added fix to check uBitsReady when return from DecodingMB header for
|
|
// packet loss detection.
|
|
//
|
|
// Rev 1.45 19 Dec 1996 16:07:44 JMCVEIGH
|
|
//
|
|
// Added initialization of forward-prediction-only flag if a block
|
|
// is not coded. This is used in H.263+ only.
|
|
//
|
|
// Rev 1.44 16 Dec 1996 17:44:00 JMCVEIGH
|
|
// Allow 8x8 motion vectors if deblocking filter selected and
|
|
// support for decoding of improved PB-frame MODB.
|
|
//
|
|
// Rev 1.43 20 Oct 1996 15:51:06 AGUPTA2
|
|
// Adjusted DbgLog trace levels; 4:Frame, 5:GOB, 6:MB, 8:everything
|
|
//
|
|
// Rev 1.42 20 Oct 1996 13:21:20 AGUPTA2
|
|
// Changed DBOUT into DbgLog. ASSERT is not changed to DbgAssert.
|
|
//
|
|
//
|
|
// Rev 1.41 11 Jul 1996 15:13:16 AGUPTA2
|
|
// Changed assertion failures into errors when decoder goes past end of
|
|
// the bitstream.
|
|
//
|
|
// Rev 1.40 03 May 1996 13:05:34 CZHU
|
|
//
|
|
// Check errors at MB header for packet faults and return PACKET_FAULT
|
|
//
|
|
// Rev 1.39 22 Mar 1996 17:25:18 AGUPTA2
|
|
// Changes to accomodate MMX rtns.
|
|
//
|
|
// Rev 1.38 08 Mar 1996 16:46:28 AGUPTA2
|
|
// Added pragmas code_seg and data_seg. Changed the size of some of local data.
|
|
//
|
|
//
|
|
// Rev 1.37 23 Feb 1996 09:46:56 KLILLEVO
|
|
// fixed decoding of Unrestricted Motion Vector mode
|
|
//
|
|
// Rev 1.36 17 Jan 1996 12:44:26 RMCKENZX
|
|
// Added support for decoding motion vectors for UMV
|
|
// Reorganized motion vector decoding processes, especially
|
|
// for AP and eliminating the large HALF_PEL conversion tables.
|
|
//
|
|
// Rev 1.35 02 Jan 1996 17:55:50 RMCKENZX
|
|
//
|
|
// Updated copyright notice
|
|
//
|
|
// Rev 1.34 02 Jan 1996 15:48:54 RMCKENZX
|
|
// Added code to preserve the Block Type in the block action stream
|
|
// for P blocks when PB frames is on. This is read in H263IDCTandMC
|
|
// when AP is on.
|
|
//
|
|
// Rev 1.33 18 Dec 1995 12:42:12 RMCKENZX
|
|
// added copyright notice
|
|
//
|
|
// Rev 1.32 13 Dec 1995 22:10:06 RHAZRA
|
|
// AP bug fix
|
|
//
|
|
// Rev 1.31 13 Dec 1995 22:01:26 TRGARDOS
|
|
//
|
|
// Added more parentheses to a logical statement.
|
|
//
|
|
// Rev 1.30 13 Dec 1995 15:10:08 TRGARDOS
|
|
// Changed MV assert to be -32 <= MV <= 31, instead of strict
|
|
// inequalities.
|
|
//
|
|
// Rev 1.29 13 Dec 1995 10:59:58 RHAZRA
|
|
//
|
|
// AP+PB changes
|
|
//
|
|
// Rev 1.28 11 Dec 1995 11:34:20 RHAZRA
|
|
// 12-10-95 changes: added AP stuff
|
|
//
|
|
// Rev 1.27 09 Dec 1995 17:28:38 RMCKENZX
|
|
// Gutted and re-built file to support decoder re-architecture.
|
|
// New modules are:
|
|
// H263ComputeMotionVectors
|
|
// H263DecodeMBHeader
|
|
// H263DecodeIDCTCoeffs
|
|
// This module now contains code to support the first pass of the decoder
|
|
//
|
|
// Rev 1.26 05 Dec 1995 09:12:28 CZHU
|
|
// Added fixes for proper MV prediction when GOB header is present
|
|
//
|
|
// Rev 1.25 22 Nov 1995 13:43:42 RMCKENZX
|
|
//
|
|
// changed calls to utilize assembly modules for bi-directional
|
|
// motion compensation & removed corresponding C modules
|
|
//
|
|
// Rev 1.24 17 Nov 1995 12:58:22 RMCKENZX
|
|
// added missing ()s to adjusted_mvx & adjusted_mvy in H263BiMotionCompLuma
|
|
//
|
|
// Rev 1.23 07 Nov 1995 11:01:10 CZHU
|
|
// Include Fixes for boundary of bi-directional predictions
|
|
//
|
|
// Rev 1.22 26 Oct 1995 11:22:10 CZHU
|
|
// Compute backward MV based on TRD, not TR
|
|
//
|
|
// Rev 1.21 13 Oct 1995 16:06:22 CZHU
|
|
// First version that supports PB frames. Display B or P frames under
|
|
// VfW for now.
|
|
//
|
|
// Rev 1.20 13 Oct 1995 13:42:46 CZHU
|
|
// Added back the #define for debug messages.
|
|
//
|
|
// Rev 1.19 11 Oct 1995 17:51:00 CZHU
|
|
//
|
|
// Fixed bugs in passing MV back with DC.
|
|
//
|
|
// Rev 1.18 11 Oct 1995 13:26:08 CZHU
|
|
// Added code to support PB frame
|
|
//
|
|
// Rev 1.17 09 Oct 1995 09:44:04 CZHU
|
|
//
|
|
// Use the optimized version of (half,half) interpolation
|
|
//
|
|
// Rev 1.16 08 Oct 1995 13:45:10 CZHU
|
|
//
|
|
// Optionally use C version of interpolation
|
|
//
|
|
// Rev 1.15 03 Oct 1995 15:05:26 CZHU
|
|
// Cleaning up.
|
|
//
|
|
// Rev 1.14 02 Oct 1995 09:58:56 TRGARDOS
|
|
// Added #ifdef to debug print statement.
|
|
//
|
|
// Rev 1.13 29 Sep 1995 16:22:06 CZHU
|
|
//
|
|
// Fixed the bug in GOB 0 when compute MV2
|
|
//
|
|
// Rev 1.12 29 Sep 1995 09:02:56 CZHU
|
|
// Rearrange Chroma blocks processing
|
|
//
|
|
// Rev 1.11 28 Sep 1995 15:33:04 CZHU
|
|
//
|
|
// Call the right version of interpolation based on MV
|
|
//
|
|
// Rev 1.10 27 Sep 1995 11:54:50 CZHU
|
|
// Integrated half pel motion compensation
|
|
//
|
|
// Rev 1.9 26 Sep 1995 15:33:06 CZHU
|
|
//
|
|
// Put place holder in for half pel interpolation
|
|
//
|
|
// Rev 1.8 20 Sep 1995 14:47:50 CZHU
|
|
// Made the number of MBs in GOB a variableD
|
|
//
|
|
// Rev 1.7 19 Sep 1995 13:53:34 CZHU
|
|
// Added assertion for half-pel motion vectors
|
|
//
|
|
// Rev 1.6 18 Sep 1995 10:20:58 CZHU
|
|
// Scale the motion vectors for UV planes too.
|
|
//
|
|
// Rev 1.5 14 Sep 1995 10:12:36 CZHU
|
|
//
|
|
// Cleaning
|
|
//
|
|
// Rev 1.4 13 Sep 1995 11:56:30 CZHU
|
|
// Fixed bugs in finding the predictors for motion vector.
|
|
//
|
|
// Rev 1.3 12 Sep 1995 18:18:58 CZHU
|
|
//
|
|
// Modified table for looking up UV MV's
|
|
//
|
|
// Rev 1.2 11 Sep 1995 16:41:14 CZHU
|
|
// Added reference block address calculation
|
|
//
|
|
// Rev 1.1 11 Sep 1995 14:31:30 CZHU
|
|
// Started to add function to calculate MVs and Reference block addresses.
|
|
//
|
|
// Rev 1.0 08 Sep 1995 11:45:56 CZHU
|
|
// Initial revision.
|
|
|
|
#include "precomp.h"
|
|
|
|
/* MCBPC table format
|
|
*
|
|
* layout
|
|
*
|
|
* unused mbtype cbpc bits
|
|
* 15-13 12-10 9-8 7-0
|
|
*/
|
|
#pragma data_seg("IADATA1")
|
|
|
|
#define MCBPC_MBTYPE(d) ((d>>10) & 0x7)
|
|
#define MCBPC_CBPC(d) ((d>>8) & 0x3)
|
|
#define MCBPC_BITS(d) (d & 0xFF)
|
|
#define MCBPC_ENTRY(m,c,b) \
|
|
( ((m & 0x7) <<10) | ((c & 0x3) << 8) | (b & 0xFF) )
|
|
|
|
U16 gNewTAB_MCBPC_INTRA[64] = {
|
|
/* index 8 - stuffing */
|
|
MCBPC_ENTRY(0,0,9),
|
|
/* index 5 */
|
|
MCBPC_ENTRY(4,1,6),
|
|
/* index 6 */
|
|
MCBPC_ENTRY(4,2,6),
|
|
/* index 7 */
|
|
MCBPC_ENTRY(4,3,6),
|
|
|
|
/* index 4; 0001XX */
|
|
MCBPC_ENTRY(4,0,4), MCBPC_ENTRY(4,0,4), MCBPC_ENTRY(4,0,4), MCBPC_ENTRY(4,0,4),
|
|
|
|
/* index 1; 001XXX */
|
|
MCBPC_ENTRY(3,1,3), MCBPC_ENTRY(3,1,3), MCBPC_ENTRY(3,1,3), MCBPC_ENTRY(3,1,3),
|
|
MCBPC_ENTRY(3,1,3), MCBPC_ENTRY(3,1,3), MCBPC_ENTRY(3,1,3), MCBPC_ENTRY(3,1,3),
|
|
|
|
/* index 2; 010XXX */
|
|
MCBPC_ENTRY(3,2,3), MCBPC_ENTRY(3,2,3), MCBPC_ENTRY(3,2,3), MCBPC_ENTRY(3,2,3),
|
|
MCBPC_ENTRY(3,2,3), MCBPC_ENTRY(3,2,3), MCBPC_ENTRY(3,2,3), MCBPC_ENTRY(3,2,3),
|
|
|
|
/* index 3; 011XXX */
|
|
MCBPC_ENTRY(3,3,3), MCBPC_ENTRY(3,3,3), MCBPC_ENTRY(3,3,3), MCBPC_ENTRY(3,3,3),
|
|
MCBPC_ENTRY(3,3,3), MCBPC_ENTRY(3,3,3), MCBPC_ENTRY(3,3,3), MCBPC_ENTRY(3,3,3),
|
|
|
|
/* index 0; 1XXXXX */
|
|
MCBPC_ENTRY(3,0,1), MCBPC_ENTRY(3,0,1), MCBPC_ENTRY(3,0,1), MCBPC_ENTRY(3,0,1),
|
|
MCBPC_ENTRY(3,0,1), MCBPC_ENTRY(3,0,1), MCBPC_ENTRY(3,0,1), MCBPC_ENTRY(3,0,1),
|
|
|
|
MCBPC_ENTRY(3,0,1), MCBPC_ENTRY(3,0,1), MCBPC_ENTRY(3,0,1), MCBPC_ENTRY(3,0,1),
|
|
MCBPC_ENTRY(3,0,1), MCBPC_ENTRY(3,0,1), MCBPC_ENTRY(3,0,1), MCBPC_ENTRY(3,0,1),
|
|
|
|
MCBPC_ENTRY(3,0,1), MCBPC_ENTRY(3,0,1), MCBPC_ENTRY(3,0,1), MCBPC_ENTRY(3,0,1),
|
|
MCBPC_ENTRY(3,0,1), MCBPC_ENTRY(3,0,1), MCBPC_ENTRY(3,0,1), MCBPC_ENTRY(3,0,1),
|
|
|
|
MCBPC_ENTRY(3,0,1), MCBPC_ENTRY(3,0,1), MCBPC_ENTRY(3,0,1), MCBPC_ENTRY(3,0,1),
|
|
MCBPC_ENTRY(3,0,1), MCBPC_ENTRY(3,0,1), MCBPC_ENTRY(3,0,1), MCBPC_ENTRY(3,0,1)
|
|
};
|
|
|
|
/* MCBPC table for INTER frame
|
|
*
|
|
* Format same as MCBPC for INTRA
|
|
* layout
|
|
*
|
|
* unused mbtype cbpc bits
|
|
* 15-13 12-10 9-8 7-0
|
|
*
|
|
*/
|
|
|
|
U16 gNewTAB_MCBPC_INTER[512] = {
|
|
/* invalid code */
|
|
MCBPC_ENTRY(0,0,0),
|
|
MCBPC_ENTRY(0,0,9), //index 20, stuffing
|
|
MCBPC_ENTRY(4,3,9), //19,
|
|
MCBPC_ENTRY(4,2,9), //18
|
|
MCBPC_ENTRY(4,1,9), //17
|
|
MCBPC_ENTRY(1,3,9), //7
|
|
//2 index 14
|
|
MCBPC_ENTRY(3,2,8),MCBPC_ENTRY(3,2,8), //14
|
|
//2 index 13
|
|
MCBPC_ENTRY(3,1,8),MCBPC_ENTRY(3,1,8), //13
|
|
//2 index 11
|
|
MCBPC_ENTRY(2,3,8),MCBPC_ENTRY(2,3,8), //11
|
|
//4 index 15
|
|
MCBPC_ENTRY(3,3,7),MCBPC_ENTRY(3,3,7),MCBPC_ENTRY(3,3,7),MCBPC_ENTRY(3,3,7), //15
|
|
//4 index 10
|
|
MCBPC_ENTRY(2,2,7),MCBPC_ENTRY(2,2,7),MCBPC_ENTRY(2,2,7),MCBPC_ENTRY(2,2,7), //10
|
|
//4 index 9
|
|
MCBPC_ENTRY(2,1,7),MCBPC_ENTRY(2,1,7),MCBPC_ENTRY(2,1,7),MCBPC_ENTRY(2,1,7), //9
|
|
//4 index 6
|
|
MCBPC_ENTRY(1,2,7),MCBPC_ENTRY(1,2,7),MCBPC_ENTRY(1,2,7),MCBPC_ENTRY(1,2,7), //6
|
|
//4 index 5
|
|
MCBPC_ENTRY(1,1,7),MCBPC_ENTRY(1,1,7),MCBPC_ENTRY(1,1,7),MCBPC_ENTRY(1,1,7), //5
|
|
//8 index 16
|
|
MCBPC_ENTRY(4,0,6),MCBPC_ENTRY(4,0,6),MCBPC_ENTRY(4,0,6),MCBPC_ENTRY(4,0,6),//16
|
|
MCBPC_ENTRY(4,0,6),MCBPC_ENTRY(4,0,6),MCBPC_ENTRY(4,0,6),MCBPC_ENTRY(4,0,6),
|
|
//8 index 3
|
|
MCBPC_ENTRY(0,3,6),MCBPC_ENTRY(0,3,6),MCBPC_ENTRY(0,3,6),MCBPC_ENTRY(0,3,6),//3
|
|
MCBPC_ENTRY(0,3,6),MCBPC_ENTRY(0,3,6),MCBPC_ENTRY(0,3,6),MCBPC_ENTRY(0,3,6),//3
|
|
//16 index 12
|
|
MCBPC_ENTRY(3,0,5),MCBPC_ENTRY(3,0,5),MCBPC_ENTRY(3,0,5),MCBPC_ENTRY(3,0,5),//12
|
|
MCBPC_ENTRY(3,0,5),MCBPC_ENTRY(3,0,5),MCBPC_ENTRY(3,0,5),MCBPC_ENTRY(3,0,5),
|
|
MCBPC_ENTRY(3,0,5),MCBPC_ENTRY(3,0,5),MCBPC_ENTRY(3,0,5),MCBPC_ENTRY(3,0,5),
|
|
MCBPC_ENTRY(3,0,5),MCBPC_ENTRY(3,0,5),MCBPC_ENTRY(3,0,5),MCBPC_ENTRY(3,0,5),
|
|
//32 INDEX 2
|
|
MCBPC_ENTRY(0,2,4),MCBPC_ENTRY(0,2,4),MCBPC_ENTRY(0,2,4),MCBPC_ENTRY(0,2,4),
|
|
MCBPC_ENTRY(0,2,4),MCBPC_ENTRY(0,2,4),MCBPC_ENTRY(0,2,4),MCBPC_ENTRY(0,2,4),
|
|
MCBPC_ENTRY(0,2,4),MCBPC_ENTRY(0,2,4),MCBPC_ENTRY(0,2,4),MCBPC_ENTRY(0,2,4),
|
|
MCBPC_ENTRY(0,2,4),MCBPC_ENTRY(0,2,4),MCBPC_ENTRY(0,2,4),MCBPC_ENTRY(0,2,4),
|
|
MCBPC_ENTRY(0,2,4),MCBPC_ENTRY(0,2,4),MCBPC_ENTRY(0,2,4),MCBPC_ENTRY(0,2,4),
|
|
MCBPC_ENTRY(0,2,4),MCBPC_ENTRY(0,2,4),MCBPC_ENTRY(0,2,4),MCBPC_ENTRY(0,2,4),
|
|
MCBPC_ENTRY(0,2,4),MCBPC_ENTRY(0,2,4),MCBPC_ENTRY(0,2,4),MCBPC_ENTRY(0,2,4),
|
|
MCBPC_ENTRY(0,2,4),MCBPC_ENTRY(0,2,4),MCBPC_ENTRY(0,2,4),MCBPC_ENTRY(0,2,4),
|
|
|
|
//32 index 1
|
|
MCBPC_ENTRY(0,1,4),MCBPC_ENTRY(0,1,4),MCBPC_ENTRY(0,1,4),MCBPC_ENTRY(0,1,4),
|
|
MCBPC_ENTRY(0,1,4),MCBPC_ENTRY(0,1,4),MCBPC_ENTRY(0,1,4),MCBPC_ENTRY(0,1,4),
|
|
MCBPC_ENTRY(0,1,4),MCBPC_ENTRY(0,1,4),MCBPC_ENTRY(0,1,4),MCBPC_ENTRY(0,1,4),
|
|
MCBPC_ENTRY(0,1,4),MCBPC_ENTRY(0,1,4),MCBPC_ENTRY(0,1,4),MCBPC_ENTRY(0,1,4),
|
|
MCBPC_ENTRY(0,1,4),MCBPC_ENTRY(0,1,4),MCBPC_ENTRY(0,1,4),MCBPC_ENTRY(0,1,4),
|
|
MCBPC_ENTRY(0,1,4),MCBPC_ENTRY(0,1,4),MCBPC_ENTRY(0,1,4),MCBPC_ENTRY(0,1,4),
|
|
MCBPC_ENTRY(0,1,4),MCBPC_ENTRY(0,1,4),MCBPC_ENTRY(0,1,4),MCBPC_ENTRY(0,1,4),
|
|
MCBPC_ENTRY(0,1,4),MCBPC_ENTRY(0,1,4),MCBPC_ENTRY(0,1,4),MCBPC_ENTRY(0,1,4),
|
|
|
|
|
|
//64 index 8
|
|
MCBPC_ENTRY(2,0,3),MCBPC_ENTRY(2,0,3),MCBPC_ENTRY(2,0,3),MCBPC_ENTRY(2,0,3),
|
|
MCBPC_ENTRY(2,0,3),MCBPC_ENTRY(2,0,3),MCBPC_ENTRY(2,0,3),MCBPC_ENTRY(2,0,3),
|
|
MCBPC_ENTRY(2,0,3),MCBPC_ENTRY(2,0,3),MCBPC_ENTRY(2,0,3),MCBPC_ENTRY(2,0,3),
|
|
MCBPC_ENTRY(2,0,3),MCBPC_ENTRY(2,0,3),MCBPC_ENTRY(2,0,3),MCBPC_ENTRY(2,0,3),
|
|
MCBPC_ENTRY(2,0,3),MCBPC_ENTRY(2,0,3),MCBPC_ENTRY(2,0,3),MCBPC_ENTRY(2,0,3),
|
|
MCBPC_ENTRY(2,0,3),MCBPC_ENTRY(2,0,3),MCBPC_ENTRY(2,0,3),MCBPC_ENTRY(2,0,3),
|
|
MCBPC_ENTRY(2,0,3),MCBPC_ENTRY(2,0,3),MCBPC_ENTRY(2,0,3),MCBPC_ENTRY(2,0,3),
|
|
MCBPC_ENTRY(2,0,3),MCBPC_ENTRY(2,0,3),MCBPC_ENTRY(2,0,3),MCBPC_ENTRY(2,0,3),
|
|
|
|
MCBPC_ENTRY(2,0,3),MCBPC_ENTRY(2,0,3),MCBPC_ENTRY(2,0,3),MCBPC_ENTRY(2,0,3),
|
|
MCBPC_ENTRY(2,0,3),MCBPC_ENTRY(2,0,3),MCBPC_ENTRY(2,0,3),MCBPC_ENTRY(2,0,3),
|
|
MCBPC_ENTRY(2,0,3),MCBPC_ENTRY(2,0,3),MCBPC_ENTRY(2,0,3),MCBPC_ENTRY(2,0,3),
|
|
MCBPC_ENTRY(2,0,3),MCBPC_ENTRY(2,0,3),MCBPC_ENTRY(2,0,3),MCBPC_ENTRY(2,0,3),
|
|
MCBPC_ENTRY(2,0,3),MCBPC_ENTRY(2,0,3),MCBPC_ENTRY(2,0,3),MCBPC_ENTRY(2,0,3),
|
|
MCBPC_ENTRY(2,0,3),MCBPC_ENTRY(2,0,3),MCBPC_ENTRY(2,0,3),MCBPC_ENTRY(2,0,3),
|
|
MCBPC_ENTRY(2,0,3),MCBPC_ENTRY(2,0,3),MCBPC_ENTRY(2,0,3),MCBPC_ENTRY(2,0,3),
|
|
MCBPC_ENTRY(2,0,3),MCBPC_ENTRY(2,0,3),MCBPC_ENTRY(2,0,3),MCBPC_ENTRY(2,0,3),
|
|
|
|
|
|
|
|
//64 index 4
|
|
MCBPC_ENTRY(1,0,3),MCBPC_ENTRY(1,0,3),MCBPC_ENTRY(1,0,3),MCBPC_ENTRY(1,0,3),
|
|
MCBPC_ENTRY(1,0,3),MCBPC_ENTRY(1,0,3),MCBPC_ENTRY(1,0,3),MCBPC_ENTRY(1,0,3),
|
|
MCBPC_ENTRY(1,0,3),MCBPC_ENTRY(1,0,3),MCBPC_ENTRY(1,0,3),MCBPC_ENTRY(1,0,3),
|
|
MCBPC_ENTRY(1,0,3),MCBPC_ENTRY(1,0,3),MCBPC_ENTRY(1,0,3),MCBPC_ENTRY(1,0,3),
|
|
MCBPC_ENTRY(1,0,3),MCBPC_ENTRY(1,0,3),MCBPC_ENTRY(1,0,3),MCBPC_ENTRY(1,0,3),
|
|
MCBPC_ENTRY(1,0,3),MCBPC_ENTRY(1,0,3),MCBPC_ENTRY(1,0,3),MCBPC_ENTRY(1,0,3),
|
|
MCBPC_ENTRY(1,0,3),MCBPC_ENTRY(1,0,3),MCBPC_ENTRY(1,0,3),MCBPC_ENTRY(1,0,3),
|
|
MCBPC_ENTRY(1,0,3),MCBPC_ENTRY(1,0,3),MCBPC_ENTRY(1,0,3),MCBPC_ENTRY(1,0,3),
|
|
|
|
MCBPC_ENTRY(1,0,3),MCBPC_ENTRY(1,0,3),MCBPC_ENTRY(1,0,3),MCBPC_ENTRY(1,0,3),
|
|
MCBPC_ENTRY(1,0,3),MCBPC_ENTRY(1,0,3),MCBPC_ENTRY(1,0,3),MCBPC_ENTRY(1,0,3),
|
|
MCBPC_ENTRY(1,0,3),MCBPC_ENTRY(1,0,3),MCBPC_ENTRY(1,0,3),MCBPC_ENTRY(1,0,3),
|
|
MCBPC_ENTRY(1,0,3),MCBPC_ENTRY(1,0,3),MCBPC_ENTRY(1,0,3),MCBPC_ENTRY(1,0,3),
|
|
MCBPC_ENTRY(1,0,3),MCBPC_ENTRY(1,0,3),MCBPC_ENTRY(1,0,3),MCBPC_ENTRY(1,0,3),
|
|
MCBPC_ENTRY(1,0,3),MCBPC_ENTRY(1,0,3),MCBPC_ENTRY(1,0,3),MCBPC_ENTRY(1,0,3),
|
|
MCBPC_ENTRY(1,0,3),MCBPC_ENTRY(1,0,3),MCBPC_ENTRY(1,0,3),MCBPC_ENTRY(1,0,3),
|
|
MCBPC_ENTRY(1,0,3),MCBPC_ENTRY(1,0,3),MCBPC_ENTRY(1,0,3),MCBPC_ENTRY(1,0,3),
|
|
|
|
|
|
//256 index 0
|
|
//0--63
|
|
MCBPC_ENTRY(0,0,1),MCBPC_ENTRY(0,0,1),MCBPC_ENTRY(0,0,1),MCBPC_ENTRY(0,0,1),
|
|
MCBPC_ENTRY(0,0,1),MCBPC_ENTRY(0,0,1),MCBPC_ENTRY(0,0,1),MCBPC_ENTRY(0,0,1),
|
|
MCBPC_ENTRY(0,0,1),MCBPC_ENTRY(0,0,1),MCBPC_ENTRY(0,0,1),MCBPC_ENTRY(0,0,1),
|
|
MCBPC_ENTRY(0,0,1),MCBPC_ENTRY(0,0,1),MCBPC_ENTRY(0,0,1),MCBPC_ENTRY(0,0,1),
|
|
MCBPC_ENTRY(0,0,1),MCBPC_ENTRY(0,0,1),MCBPC_ENTRY(0,0,1),MCBPC_ENTRY(0,0,1),
|
|
MCBPC_ENTRY(0,0,1),MCBPC_ENTRY(0,0,1),MCBPC_ENTRY(0,0,1),MCBPC_ENTRY(0,0,1),
|
|
MCBPC_ENTRY(0,0,1),MCBPC_ENTRY(0,0,1),MCBPC_ENTRY(0,0,1),MCBPC_ENTRY(0,0,1),
|
|
MCBPC_ENTRY(0,0,1),MCBPC_ENTRY(0,0,1),MCBPC_ENTRY(0,0,1),MCBPC_ENTRY(0,0,1),
|
|
MCBPC_ENTRY(0,0,1),MCBPC_ENTRY(0,0,1),MCBPC_ENTRY(0,0,1),MCBPC_ENTRY(0,0,1),
|
|
MCBPC_ENTRY(0,0,1),MCBPC_ENTRY(0,0,1),MCBPC_ENTRY(0,0,1),MCBPC_ENTRY(0,0,1),
|
|
MCBPC_ENTRY(0,0,1),MCBPC_ENTRY(0,0,1),MCBPC_ENTRY(0,0,1),MCBPC_ENTRY(0,0,1),
|
|
MCBPC_ENTRY(0,0,1),MCBPC_ENTRY(0,0,1),MCBPC_ENTRY(0,0,1),MCBPC_ENTRY(0,0,1),
|
|
MCBPC_ENTRY(0,0,1),MCBPC_ENTRY(0,0,1),MCBPC_ENTRY(0,0,1),MCBPC_ENTRY(0,0,1),
|
|
MCBPC_ENTRY(0,0,1),MCBPC_ENTRY(0,0,1),MCBPC_ENTRY(0,0,1),MCBPC_ENTRY(0,0,1),
|
|
MCBPC_ENTRY(0,0,1),MCBPC_ENTRY(0,0,1),MCBPC_ENTRY(0,0,1),MCBPC_ENTRY(0,0,1),
|
|
MCBPC_ENTRY(0,0,1),MCBPC_ENTRY(0,0,1),MCBPC_ENTRY(0,0,1),MCBPC_ENTRY(0,0,1),
|
|
//64--127
|
|
MCBPC_ENTRY(0,0,1),MCBPC_ENTRY(0,0,1),MCBPC_ENTRY(0,0,1),MCBPC_ENTRY(0,0,1),
|
|
MCBPC_ENTRY(0,0,1),MCBPC_ENTRY(0,0,1),MCBPC_ENTRY(0,0,1),MCBPC_ENTRY(0,0,1),
|
|
MCBPC_ENTRY(0,0,1),MCBPC_ENTRY(0,0,1),MCBPC_ENTRY(0,0,1),MCBPC_ENTRY(0,0,1),
|
|
MCBPC_ENTRY(0,0,1),MCBPC_ENTRY(0,0,1),MCBPC_ENTRY(0,0,1),MCBPC_ENTRY(0,0,1),
|
|
MCBPC_ENTRY(0,0,1),MCBPC_ENTRY(0,0,1),MCBPC_ENTRY(0,0,1),MCBPC_ENTRY(0,0,1),
|
|
MCBPC_ENTRY(0,0,1),MCBPC_ENTRY(0,0,1),MCBPC_ENTRY(0,0,1),MCBPC_ENTRY(0,0,1),
|
|
MCBPC_ENTRY(0,0,1),MCBPC_ENTRY(0,0,1),MCBPC_ENTRY(0,0,1),MCBPC_ENTRY(0,0,1),
|
|
MCBPC_ENTRY(0,0,1),MCBPC_ENTRY(0,0,1),MCBPC_ENTRY(0,0,1),MCBPC_ENTRY(0,0,1),
|
|
MCBPC_ENTRY(0,0,1),MCBPC_ENTRY(0,0,1),MCBPC_ENTRY(0,0,1),MCBPC_ENTRY(0,0,1),
|
|
MCBPC_ENTRY(0,0,1),MCBPC_ENTRY(0,0,1),MCBPC_ENTRY(0,0,1),MCBPC_ENTRY(0,0,1),
|
|
MCBPC_ENTRY(0,0,1),MCBPC_ENTRY(0,0,1),MCBPC_ENTRY(0,0,1),MCBPC_ENTRY(0,0,1),
|
|
MCBPC_ENTRY(0,0,1),MCBPC_ENTRY(0,0,1),MCBPC_ENTRY(0,0,1),MCBPC_ENTRY(0,0,1),
|
|
MCBPC_ENTRY(0,0,1),MCBPC_ENTRY(0,0,1),MCBPC_ENTRY(0,0,1),MCBPC_ENTRY(0,0,1),
|
|
MCBPC_ENTRY(0,0,1),MCBPC_ENTRY(0,0,1),MCBPC_ENTRY(0,0,1),MCBPC_ENTRY(0,0,1),
|
|
MCBPC_ENTRY(0,0,1),MCBPC_ENTRY(0,0,1),MCBPC_ENTRY(0,0,1),MCBPC_ENTRY(0,0,1),
|
|
MCBPC_ENTRY(0,0,1),MCBPC_ENTRY(0,0,1),MCBPC_ENTRY(0,0,1),MCBPC_ENTRY(0,0,1),
|
|
//128--128+64=192
|
|
MCBPC_ENTRY(0,0,1),MCBPC_ENTRY(0,0,1),MCBPC_ENTRY(0,0,1),MCBPC_ENTRY(0,0,1),
|
|
MCBPC_ENTRY(0,0,1),MCBPC_ENTRY(0,0,1),MCBPC_ENTRY(0,0,1),MCBPC_ENTRY(0,0,1),
|
|
MCBPC_ENTRY(0,0,1),MCBPC_ENTRY(0,0,1),MCBPC_ENTRY(0,0,1),MCBPC_ENTRY(0,0,1),
|
|
MCBPC_ENTRY(0,0,1),MCBPC_ENTRY(0,0,1),MCBPC_ENTRY(0,0,1),MCBPC_ENTRY(0,0,1),
|
|
MCBPC_ENTRY(0,0,1),MCBPC_ENTRY(0,0,1),MCBPC_ENTRY(0,0,1),MCBPC_ENTRY(0,0,1),
|
|
MCBPC_ENTRY(0,0,1),MCBPC_ENTRY(0,0,1),MCBPC_ENTRY(0,0,1),MCBPC_ENTRY(0,0,1),
|
|
MCBPC_ENTRY(0,0,1),MCBPC_ENTRY(0,0,1),MCBPC_ENTRY(0,0,1),MCBPC_ENTRY(0,0,1),
|
|
MCBPC_ENTRY(0,0,1),MCBPC_ENTRY(0,0,1),MCBPC_ENTRY(0,0,1),MCBPC_ENTRY(0,0,1),
|
|
MCBPC_ENTRY(0,0,1),MCBPC_ENTRY(0,0,1),MCBPC_ENTRY(0,0,1),MCBPC_ENTRY(0,0,1),
|
|
MCBPC_ENTRY(0,0,1),MCBPC_ENTRY(0,0,1),MCBPC_ENTRY(0,0,1),MCBPC_ENTRY(0,0,1),
|
|
MCBPC_ENTRY(0,0,1),MCBPC_ENTRY(0,0,1),MCBPC_ENTRY(0,0,1),MCBPC_ENTRY(0,0,1),
|
|
MCBPC_ENTRY(0,0,1),MCBPC_ENTRY(0,0,1),MCBPC_ENTRY(0,0,1),MCBPC_ENTRY(0,0,1),
|
|
MCBPC_ENTRY(0,0,1),MCBPC_ENTRY(0,0,1),MCBPC_ENTRY(0,0,1),MCBPC_ENTRY(0,0,1),
|
|
MCBPC_ENTRY(0,0,1),MCBPC_ENTRY(0,0,1),MCBPC_ENTRY(0,0,1),MCBPC_ENTRY(0,0,1),
|
|
MCBPC_ENTRY(0,0,1),MCBPC_ENTRY(0,0,1),MCBPC_ENTRY(0,0,1),MCBPC_ENTRY(0,0,1),
|
|
MCBPC_ENTRY(0,0,1),MCBPC_ENTRY(0,0,1),MCBPC_ENTRY(0,0,1),MCBPC_ENTRY(0,0,1),
|
|
//192--255
|
|
MCBPC_ENTRY(0,0,1),MCBPC_ENTRY(0,0,1),MCBPC_ENTRY(0,0,1),MCBPC_ENTRY(0,0,1),
|
|
MCBPC_ENTRY(0,0,1),MCBPC_ENTRY(0,0,1),MCBPC_ENTRY(0,0,1),MCBPC_ENTRY(0,0,1),
|
|
MCBPC_ENTRY(0,0,1),MCBPC_ENTRY(0,0,1),MCBPC_ENTRY(0,0,1),MCBPC_ENTRY(0,0,1),
|
|
MCBPC_ENTRY(0,0,1),MCBPC_ENTRY(0,0,1),MCBPC_ENTRY(0,0,1),MCBPC_ENTRY(0,0,1),
|
|
MCBPC_ENTRY(0,0,1),MCBPC_ENTRY(0,0,1),MCBPC_ENTRY(0,0,1),MCBPC_ENTRY(0,0,1),
|
|
MCBPC_ENTRY(0,0,1),MCBPC_ENTRY(0,0,1),MCBPC_ENTRY(0,0,1),MCBPC_ENTRY(0,0,1),
|
|
MCBPC_ENTRY(0,0,1),MCBPC_ENTRY(0,0,1),MCBPC_ENTRY(0,0,1),MCBPC_ENTRY(0,0,1),
|
|
MCBPC_ENTRY(0,0,1),MCBPC_ENTRY(0,0,1),MCBPC_ENTRY(0,0,1),MCBPC_ENTRY(0,0,1),
|
|
MCBPC_ENTRY(0,0,1),MCBPC_ENTRY(0,0,1),MCBPC_ENTRY(0,0,1),MCBPC_ENTRY(0,0,1),
|
|
MCBPC_ENTRY(0,0,1),MCBPC_ENTRY(0,0,1),MCBPC_ENTRY(0,0,1),MCBPC_ENTRY(0,0,1),
|
|
MCBPC_ENTRY(0,0,1),MCBPC_ENTRY(0,0,1),MCBPC_ENTRY(0,0,1),MCBPC_ENTRY(0,0,1),
|
|
MCBPC_ENTRY(0,0,1),MCBPC_ENTRY(0,0,1),MCBPC_ENTRY(0,0,1),MCBPC_ENTRY(0,0,1),
|
|
MCBPC_ENTRY(0,0,1),MCBPC_ENTRY(0,0,1),MCBPC_ENTRY(0,0,1),MCBPC_ENTRY(0,0,1),
|
|
MCBPC_ENTRY(0,0,1),MCBPC_ENTRY(0,0,1),MCBPC_ENTRY(0,0,1),MCBPC_ENTRY(0,0,1),
|
|
MCBPC_ENTRY(0,0,1),MCBPC_ENTRY(0,0,1),MCBPC_ENTRY(0,0,1),MCBPC_ENTRY(0,0,1),
|
|
MCBPC_ENTRY(0,0,1),MCBPC_ENTRY(0,0,1),MCBPC_ENTRY(0,0,1),MCBPC_ENTRY(0,0,1)
|
|
};
|
|
|
|
/* CBPY table format
|
|
*
|
|
* layout
|
|
*
|
|
* intra inter bits
|
|
* 15-12 11-8 7-0
|
|
*
|
|
* unused entries should have zero data
|
|
*/
|
|
#define CBPY_INTRA(d) ((d>>12) & 0xf)
|
|
#define CBPY_INTER(d) ((d>>8) & 0xf)
|
|
#define CBPY_BITS(d) (d & 0xff)
|
|
#define CBPY_ENTRY(a,r,b) \
|
|
( ((a & 0xf) <<12) | ((r & 0xf) << 8) | (b & 0xFF) )
|
|
#define CBPY_NOT_USED() CBPY_ENTRY(0,0,0)
|
|
|
|
U16 gNewTAB_CBPY[64] = {
|
|
/* NotUsed - 0000 0X */
|
|
CBPY_NOT_USED(), CBPY_NOT_USED(),
|
|
|
|
/* Index 6 - 0000 10 */
|
|
CBPY_ENTRY(6,9,6),
|
|
|
|
/* Index 9 - 0000 11 */
|
|
CBPY_ENTRY(9,6,6),
|
|
|
|
/* Index 8 - 0001 0x */
|
|
CBPY_ENTRY(8,7,5), CBPY_ENTRY(8,7,5),
|
|
|
|
/* Index 4 - 0001 1x */
|
|
CBPY_ENTRY(4,11,5), CBPY_ENTRY(4,11,5),
|
|
|
|
/* Index 2 - 0010 0x */
|
|
CBPY_ENTRY(2,13,5), CBPY_ENTRY(2,13,5),
|
|
|
|
/* Index 1 - 0010 1x */
|
|
CBPY_ENTRY(1,14,5), CBPY_ENTRY(1,14,5),
|
|
|
|
/* Index 0 - 0011 xx */
|
|
CBPY_ENTRY(0,15,4), CBPY_ENTRY(0,15,4), CBPY_ENTRY(0,15,4), CBPY_ENTRY(0,15,4),
|
|
|
|
/* Index 12- 0100 xx */
|
|
CBPY_ENTRY(12,3,4), CBPY_ENTRY(12,3,4), CBPY_ENTRY(12,3,4), CBPY_ENTRY(12,3,4),
|
|
|
|
/* Index 10- 0101 xx */
|
|
CBPY_ENTRY(10,5,4), CBPY_ENTRY(10,5,4), CBPY_ENTRY(10,5,4), CBPY_ENTRY(10,5,4),
|
|
|
|
/* Index 14- 0110 xx */
|
|
CBPY_ENTRY(14,1,4), CBPY_ENTRY(14,1,4), CBPY_ENTRY(14,1,4), CBPY_ENTRY(14,1,4),
|
|
|
|
/* Index 5 - 0111 xx */
|
|
CBPY_ENTRY(5,10,4), CBPY_ENTRY(5,10,4), CBPY_ENTRY(5,10,4), CBPY_ENTRY(5,10,4),
|
|
|
|
/* Index 13- 1000 xx */
|
|
CBPY_ENTRY(13,2,4), CBPY_ENTRY(13,2,4), CBPY_ENTRY(13,2,4), CBPY_ENTRY(13,2,4),
|
|
|
|
/* Index 3 - 1001 xx */
|
|
CBPY_ENTRY(3,12,4), CBPY_ENTRY(3,12,4), CBPY_ENTRY(3,12,4), CBPY_ENTRY(3,12,4),
|
|
|
|
/* Index 11- 1010 xx */
|
|
CBPY_ENTRY(11,4,4), CBPY_ENTRY(11,4,4), CBPY_ENTRY(11,4,4), CBPY_ENTRY(11,4,4),
|
|
|
|
/* Index 7 - 1011 xx */
|
|
CBPY_ENTRY(7,8,4), CBPY_ENTRY(7,8,4), CBPY_ENTRY(7,8,4), CBPY_ENTRY(7,8,4),
|
|
|
|
/* Index 15- 11xx xx */
|
|
CBPY_ENTRY(15,0,2), CBPY_ENTRY(15,0,2), CBPY_ENTRY(15,0,2), CBPY_ENTRY(15,0,2),
|
|
CBPY_ENTRY(15,0,2), CBPY_ENTRY(15,0,2), CBPY_ENTRY(15,0,2), CBPY_ENTRY(15,0,2),
|
|
CBPY_ENTRY(15,0,2), CBPY_ENTRY(15,0,2), CBPY_ENTRY(15,0,2), CBPY_ENTRY(15,0,2),
|
|
CBPY_ENTRY(15,0,2), CBPY_ENTRY(15,0,2), CBPY_ENTRY(15,0,2), CBPY_ENTRY(15,0,2)
|
|
};
|
|
|
|
I16 gNewTAB_DQUANT[4] = { -1, -2, 1, 2 };
|
|
|
|
#ifdef USE_MMX // { USE_MMX
|
|
T_pFunc_VLD_RLD_IQ_Block pFunc_VLD_RLD_IQ_Block[2] = {VLD_RLD_IQ_Block, MMX_VLD_RLD_IQ_Block};
|
|
#endif // } USE_MMX
|
|
|
|
#pragma data_seg(".data")
|
|
/*****************************************************************************
|
|
*
|
|
* H263DecodeMBHeader
|
|
*
|
|
* Decode the MB header
|
|
*/
|
|
#pragma code_seg("IACODE1")
|
|
I32 H263DecodeMBHeader(
|
|
T_H263DecoderCatalog FAR * DC,
|
|
BITSTREAM_STATE FAR * fpbsState,
|
|
U32 **pN,
|
|
T_MBInfo FAR * fpMBInfo)
|
|
{
|
|
I32 iReturn = ICERR_ERROR;
|
|
U8 FAR * fpu8;
|
|
U32 uBitsReady;
|
|
U32 uWork;
|
|
U32 uResult;
|
|
U32 uCode;
|
|
U32 uBitCount;
|
|
U32 uMBType;
|
|
U32 bCoded;
|
|
U32 bStuffing;
|
|
U32 bGetCBPB;
|
|
U32 bGetMVDB;
|
|
U32 i;
|
|
|
|
FX_ENTRY("H263DecodeMBHeader");
|
|
|
|
GET_BITS_RESTORE_STATE(fpu8, uWork, uBitsReady, fpbsState)
|
|
|
|
// COD -----------------------------------------------------
|
|
ReadCOD:
|
|
if (! DC->bKeyFrame)
|
|
{
|
|
GET_ONE_BIT(fpu8, uWork, uBitsReady, uResult);
|
|
bCoded = !uResult; /* coded when bit is set to zero */
|
|
}
|
|
else
|
|
bCoded = 1;
|
|
DC->bCoded = (U16) bCoded;
|
|
|
|
if (!bCoded)
|
|
{
|
|
/* when a block is not coded, "the remaining part of the macroblock
|
|
* layer is empty; in that case the decoder shall treat the macroblock
|
|
* as in INTER block with motion vector for the whole block equal to
|
|
* zero and with no coefficient data" (5.3.1 p 16).
|
|
*/
|
|
DC->uMBType = 0;
|
|
|
|
fpMBInfo->i8MBType = 0; // AP-NEW
|
|
|
|
DC->uCBPC = 0;
|
|
DC->uCBPY = 0;
|
|
|
|
/* Now update the pN array. Since the block is not coded, write 0
|
|
* for all blocks in the macroblock.
|
|
*/
|
|
if (DC->bPBFrame)
|
|
{ // 12 blocks for a PB frame
|
|
fpMBInfo->i8MVDBx2 = fpMBInfo->i8MVDBy2 = 0;
|
|
for (i=0; i<12; i++)
|
|
{ // PB-NEW
|
|
**pN = 0;
|
|
(*pN)++;
|
|
}
|
|
}
|
|
else
|
|
{ // only 6 blocks for non PB frame
|
|
for (i=0; i<6; i++)
|
|
{ // NEW
|
|
**pN = 0;
|
|
(*pN)++;
|
|
}
|
|
}
|
|
|
|
#ifdef H263P
|
|
// If block is not coded, we use the original PB-frame method in Annex G.
|
|
// In other words, use bidirectional prediction (not forward only)
|
|
fpMBInfo->bForwardPredOnly = FALSE;
|
|
#endif
|
|
|
|
GET_BITS_SAVE_STATE(fpu8, uWork, uBitsReady, fpbsState)
|
|
iReturn = ICERR_OK;
|
|
goto done;
|
|
}
|
|
|
|
// MCBPC ---------------------------------------------------
|
|
bStuffing = 0;
|
|
if (DC->bKeyFrame)
|
|
{
|
|
GET_VARIABLE_BITS(6, fpu8, uWork, uBitsReady, uResult,
|
|
uCode, uBitCount, gNewTAB_MCBPC_INTRA);
|
|
if (uCode == 0)
|
|
{
|
|
/* start of the stuffing code - read the next 3-bits
|
|
*/
|
|
GET_FIXED_BITS(3, fpu8, uWork, uBitsReady, uResult);
|
|
if (uResult == 1)
|
|
bStuffing = 1;
|
|
else
|
|
{
|
|
ERRORMESSAGE(("%s: Incorrect key frame stuffing bits!\r\n", _fx_));
|
|
//#ifdef LOSS_RECOVERY
|
|
// Always True if (uBitsReady <0) uBitsReady += 9;//trick and trap, do not change it without consulting Chad
|
|
GET_BITS_SAVE_STATE(fpu8, uWork, uBitsReady, fpbsState)
|
|
iReturn = PACKET_FAULT;
|
|
//#else
|
|
// iReturn = ICERR_ERROR;
|
|
//#endif
|
|
goto done;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// Delta Frame
|
|
// mcpbc, VLD
|
|
GET_VARIABLE_BITS(9, fpu8, uWork, uBitsReady, uResult,
|
|
uCode, uBitCount, gNewTAB_MCBPC_INTER);
|
|
|
|
if (uCode == 1)
|
|
bStuffing = 1;
|
|
//#ifdef LOSS_RECOVERY
|
|
else if (uCode == 0) //catch the illegal code
|
|
{
|
|
ERRORMESSAGE(("%s: Incorrect stuffing bits!\r\n", _fx_));
|
|
// Always True if (uBitsReady <0) uBitsReady += 9;//trick and trap, do not change it without consulting Chad
|
|
GET_BITS_SAVE_STATE(fpu8, uWork, uBitsReady, fpbsState)
|
|
iReturn = PACKET_FAULT;
|
|
goto done;
|
|
}
|
|
//#endif
|
|
|
|
}
|
|
|
|
/* When MCBPC==Stuffing, the remaining part of the macroblock layer is
|
|
* skipped and the macroblock number is not incremented (5.3.2 p18)"
|
|
* We support this by jumping to the start - to look for COD
|
|
*/
|
|
if (bStuffing)
|
|
goto ReadCOD;
|
|
|
|
uMBType = MCBPC_MBTYPE(uResult);
|
|
if (DC->bKeyFrame && (uMBType != 3 && uMBType != 4))
|
|
{
|
|
ERRORMESSAGE(("%s: Bad key frame MBType!\r\n", _fx_));
|
|
iReturn = ICERR_ERROR;
|
|
goto done;
|
|
}
|
|
|
|
DC->uMBType = uMBType;
|
|
|
|
fpMBInfo->i8MBType = (I8) uMBType;
|
|
|
|
DC->uCBPC = MCBPC_CBPC(uResult);
|
|
|
|
// MODB ----------------------------------------------------
|
|
bGetCBPB = 0;
|
|
bGetMVDB = 0;
|
|
|
|
if (DC->bPBFrame)
|
|
{
|
|
ASSERT( !DC->bKeyFrame);
|
|
|
|
#ifdef H263P
|
|
// Default is to use original PB-frame method in Annex G.
|
|
fpMBInfo->bForwardPredOnly = FALSE;
|
|
|
|
if (DC->bImprovedPBFrames)
|
|
{
|
|
// See modified TABLE 8/H.263, Annex M, document LBC-96-358
|
|
GET_FIXED_BITS(1, fpu8, uWork, uBitsReady, uResult);
|
|
if (uResult)
|
|
{
|
|
// 1xx
|
|
GET_FIXED_BITS(1, fpu8, uWork, uBitsReady, uResult);
|
|
bGetCBPB = uResult;
|
|
if (!uResult)
|
|
// 10x
|
|
bGetMVDB = 1;
|
|
else
|
|
{
|
|
// 11x
|
|
GET_FIXED_BITS(1, fpu8, uWork, uBitsReady, uResult);
|
|
bGetMVDB = !uResult;
|
|
}
|
|
}
|
|
if (bGetMVDB)
|
|
// B-block is forward predicted (otherwise it is bidirectionally predicted)
|
|
fpMBInfo->bForwardPredOnly = TRUE;
|
|
}
|
|
else
|
|
#endif // H263P
|
|
{
|
|
GET_FIXED_BITS(1, fpu8, uWork, uBitsReady, uResult);
|
|
bGetCBPB = uResult; // see section 5.3.3 table 7/H.263
|
|
if (bGetCBPB)
|
|
{
|
|
bGetMVDB = 1;
|
|
GET_FIXED_BITS(1, fpu8, uWork, uBitsReady, uResult);
|
|
bGetCBPB = uResult;
|
|
}
|
|
}
|
|
}
|
|
|
|
// CBPB ----------------------------------------------------
|
|
DC->u8CBPB = 0;
|
|
if (bGetCBPB)
|
|
{
|
|
ASSERT(!DC->bKeyFrame);
|
|
GET_FIXED_BITS(6, fpu8, uWork, uBitsReady, uResult);
|
|
DC->u8CBPB = (U8)uResult;
|
|
}
|
|
|
|
// CBPY ----------------------------------------------------
|
|
GET_VARIABLE_BITS(6, fpu8, uWork, uBitsReady, uResult,
|
|
uCode, uBitCount, gNewTAB_CBPY);
|
|
if (uResult == 0)
|
|
{
|
|
ERRORMESSAGE(("%s: Undefined CBPY variable code!\r\n", _fx_));
|
|
iReturn = ICERR_ERROR;
|
|
goto done;
|
|
}
|
|
if (DC->uMBType > 2) //INTRA MB, not intra frame
|
|
DC->uCBPY = CBPY_INTRA(uResult);
|
|
else
|
|
DC->uCBPY = CBPY_INTER(uResult);
|
|
|
|
// DQUANT --------------------------------------------------
|
|
if (DC->uMBType == 1 || DC->uMBType == 4)
|
|
{
|
|
GET_FIXED_BITS(2, fpu8, uWork, uBitsReady, uResult);
|
|
DC->uDQuant = gNewTAB_DQUANT[uResult];
|
|
DC->uGQuant += DC->uDQuant;
|
|
DC->uPQuant = DC->uGQuant;
|
|
} else
|
|
DC->uDQuant = 0;
|
|
|
|
DEBUGMSG(ZONE_DECODE_MB_HEADER, (" %s: MBType = %ld, MCBPC = 0x%lX, CBPY = 0x%lX, DQuant = 0x%lX\r\n", _fx_, DC->uMBType, DC->uCBPC, DC->uCBPY, DC->uDQuant));
|
|
|
|
// MVD -----------------------------------------------------
|
|
DC->i8MVDx2=DC->i8MVDy2=0; //Zero init it anyway.
|
|
|
|
if ( DC->bPBFrame || DC->uMBType <= 2)
|
|
{
|
|
GET_VARIABLE_BITS_MV(13, fpu8, uWork, uBitsReady, uResult,uCode,
|
|
uBitCount, gTAB_MVD_MAJOR, gTAB_MVD_MINOR);
|
|
if (!uResult)
|
|
{
|
|
ERRORMESSAGE(("%s: Undefined Motion Vector code!\r\n", _fx_));
|
|
iReturn = ICERR_ERROR;
|
|
goto done;
|
|
}
|
|
DC->i8MVDx2 = (I8)(uResult>>8);
|
|
|
|
GET_VARIABLE_BITS_MV(13, fpu8, uWork, uBitsReady, uResult,uCode,
|
|
uBitCount, gTAB_MVD_MAJOR, gTAB_MVD_MINOR);
|
|
if (!uResult)
|
|
{
|
|
ERRORMESSAGE(("%s: Bad Motion Vector VLC!\r\n", _fx_));
|
|
iReturn = ICERR_ERROR;
|
|
goto done;
|
|
}
|
|
DC->i8MVDy2 = (I8)(uResult>>8);
|
|
}
|
|
|
|
// MVD 2-4 -------------------------------------------------
|
|
#ifdef H263P
|
|
// In H.263+, 8x8 motion vectors are possible if the deblocking
|
|
// filter is selected.
|
|
if ((DC->bAdvancedPrediction || DC->bDeblockingFilter)
|
|
&& (DC->uMBType == 2) )
|
|
#else
|
|
if (DC->bAdvancedPrediction && (DC->uMBType == 2) )
|
|
#endif
|
|
{
|
|
DC->i8MVD2x2 = DC->i8MVD2y2 = 0;
|
|
|
|
GET_VARIABLE_BITS_MV(13, fpu8, uWork, uBitsReady, uResult,uCode,
|
|
uBitCount, gTAB_MVD_MAJOR, gTAB_MVD_MINOR);
|
|
if (!uResult)
|
|
{
|
|
ERRORMESSAGE(("%s: Bad Block Motion Vector VLC!\r\n", _fx_));
|
|
iReturn = ICERR_ERROR;
|
|
goto done;
|
|
}
|
|
DC->i8MVD2x2 = (I8)(uResult>>8);
|
|
|
|
GET_VARIABLE_BITS_MV(13, fpu8, uWork, uBitsReady, uResult,uCode,
|
|
uBitCount, gTAB_MVD_MAJOR, gTAB_MVD_MINOR);
|
|
if (!uResult)
|
|
{
|
|
ERRORMESSAGE(("%s: Bad Block Motion Vector VLC!\r\n", _fx_));
|
|
iReturn = ICERR_ERROR;
|
|
goto done;
|
|
}
|
|
DC->i8MVD2y2 = (I8)(uResult>>8);
|
|
|
|
DC->i8MVD3x2 = DC->i8MVD3y2 = 0;
|
|
|
|
GET_VARIABLE_BITS_MV(13, fpu8, uWork, uBitsReady, uResult,uCode,
|
|
uBitCount, gTAB_MVD_MAJOR, gTAB_MVD_MINOR);
|
|
if (!uResult)
|
|
{
|
|
ERRORMESSAGE(("%s: Bad Block Motion Vector VLC!\r\n", _fx_));
|
|
iReturn = ICERR_ERROR;
|
|
goto done;
|
|
}
|
|
DC->i8MVD3x2 = (I8)(uResult>>8);
|
|
|
|
GET_VARIABLE_BITS_MV(13, fpu8, uWork, uBitsReady, uResult,uCode,
|
|
uBitCount, gTAB_MVD_MAJOR, gTAB_MVD_MINOR);
|
|
if (!uResult)
|
|
{
|
|
ERRORMESSAGE(("%s: Bad Block Motion Vector VLC!\r\n", _fx_));
|
|
iReturn = ICERR_ERROR;
|
|
goto done;
|
|
}
|
|
DC->i8MVD3y2 = (I8)(uResult>>8);
|
|
|
|
DC->i8MVD4x2 = DC->i8MVD4y2 = 0;
|
|
|
|
GET_VARIABLE_BITS_MV(13, fpu8, uWork, uBitsReady, uResult,uCode,
|
|
uBitCount, gTAB_MVD_MAJOR, gTAB_MVD_MINOR);
|
|
if (!uResult)
|
|
{
|
|
ERRORMESSAGE(("%s: Bad Block Motion Vector VLC!\r\n", _fx_));
|
|
iReturn = ICERR_ERROR;
|
|
goto done;
|
|
}
|
|
DC->i8MVD4x2 = (I8)(uResult>>8);
|
|
|
|
GET_VARIABLE_BITS_MV(13, fpu8, uWork, uBitsReady, uResult,uCode,
|
|
uBitCount, gTAB_MVD_MAJOR, gTAB_MVD_MINOR);
|
|
if (!uResult)
|
|
{
|
|
ERRORMESSAGE(("%s: Bad Block Motion Vector VLC!\r\n", _fx_));
|
|
iReturn = ICERR_ERROR;
|
|
goto done;
|
|
}
|
|
DC->i8MVD4y2 = (I8)(uResult>>8);
|
|
|
|
DEBUGMSG(ZONE_DECODE_MB_HEADER, (" %s: MVD2x2 = %d, MVD2y2 = %d, MVD3x2 = %d, MVD3y2 = %d, MVD4x2 = %d, MVD4y2 = %d\r\n", _fx_, DC->i8MVD2x2, DC->i8MVD2y2, DC->i8MVD3x2, DC->i8MVD3y2, DC->i8MVD4x2, DC->i8MVD4y2));
|
|
}
|
|
|
|
// MVDB ----------------------------------------------------
|
|
DC->i8MVDBx2 = DC->i8MVDBy2 = 0; //Zero init it anyway.
|
|
fpMBInfo->i8MVDBx2 = fpMBInfo->i8MVDBy2 = 0;
|
|
if (bGetMVDB)
|
|
{
|
|
ASSERT(DC->bPBFrame);
|
|
ASSERT(!DC->bKeyFrame);
|
|
GET_VARIABLE_BITS_MV(13, fpu8, uWork, uBitsReady, uResult,uCode,
|
|
uBitCount, gTAB_MVD_MAJOR, gTAB_MVD_MINOR);
|
|
if (!uResult)
|
|
{
|
|
ERRORMESSAGE(("%s: Bad Motion Vector MVDB!\r\n", _fx_));
|
|
iReturn = ICERR_ERROR;
|
|
goto done;
|
|
}
|
|
fpMBInfo->i8MVDBx2 = DC->i8MVDBx2 = (I8)(uResult>>8);
|
|
|
|
GET_VARIABLE_BITS_MV(13, fpu8, uWork, uBitsReady, uResult,uCode,
|
|
uBitCount, gTAB_MVD_MAJOR, gTAB_MVD_MINOR);
|
|
if (!uResult)
|
|
{
|
|
ERRORMESSAGE(("%s: Bad Motion Vector MVDB!\r\n", _fx_));
|
|
iReturn = ICERR_ERROR;
|
|
goto done;
|
|
}
|
|
fpMBInfo->i8MVDBy2 = DC->i8MVDBy2 = (I8)(uResult>>8);
|
|
}
|
|
|
|
GET_BITS_SAVE_STATE(fpu8, uWork, uBitsReady, fpbsState)
|
|
|
|
iReturn = ICERR_OK;
|
|
|
|
done:
|
|
return iReturn;
|
|
} /* end H263DecodeMBHeader() */
|
|
#pragma code_seg()
|
|
|
|
|
|
/*****************************************************************************
|
|
*
|
|
* H263DecodeIDCTCoeffs
|
|
*
|
|
* Decode each of the blocks in this macro block
|
|
*/
|
|
#pragma code_seg("IACODE1")
|
|
I32 H263DecodeIDCTCoeffs(
|
|
T_H263DecoderCatalog FAR * DC,
|
|
T_BlkAction FAR * fpBlockAction,
|
|
U32 uBlockNumber,
|
|
BITSTREAM_STATE FAR * fpbsState,
|
|
U8 FAR * fpu8MaxPtr,
|
|
U32 **pN, // NEW
|
|
T_IQ_INDEX **pRUN_INVERSE_Q) // NEW
|
|
{
|
|
I32 iResult = ICERR_ERROR;
|
|
int iBlockPattern;
|
|
int i;
|
|
U8 u8PBlkType;
|
|
U32 uBitsReady;
|
|
U32 uBitsReadIn;
|
|
U32 uBitsReadOut;
|
|
U8 u8Quant; // quantization level for this Mblock
|
|
U8 FAR * fpu8;
|
|
U32 uByteCnt;
|
|
T_BlkAction FAR * pActionStream;
|
|
#ifdef USE_MMX // { USE_MMX
|
|
T_pFunc_VLD_RLD_IQ_Block pFunc_VLD = pFunc_VLD_RLD_IQ_Block[DC->bMMXDecoder];
|
|
#else // }{ USE_MMX
|
|
T_pFunc_VLD_RLD_IQ_Block pFunc_VLD = VLD_RLD_IQ_Block;
|
|
#endif // } USE_MMX
|
|
|
|
pActionStream = fpBlockAction;
|
|
|
|
FX_ENTRY("H263DecodeIDCTCoeffs");
|
|
|
|
/* On input the pointer points to the next byte. We need to change it to
|
|
* point to the current word on a 32-bit boundary.
|
|
*/
|
|
|
|
fpu8 = fpbsState->fpu8 - 1; /* point to the current byte */
|
|
uBitsReady = fpbsState->uBitsReady;
|
|
|
|
while (uBitsReady >= 8)
|
|
{
|
|
fpu8--;
|
|
uBitsReady -= 8;
|
|
}
|
|
|
|
uBitsReadIn = 8 - uBitsReady;
|
|
u8Quant = (U8) (DC->uGQuant);
|
|
|
|
if ( (DC->bPBFrame) || ((!DC->bKeyFrame) && (DC->uMBType <= 2)))
|
|
{
|
|
// calculate motion vectors for the 6 blocks in this MB
|
|
iResult = H263ComputeMotionVectors(DC, fpBlockAction); // NEW
|
|
|
|
if (iResult != ICERR_OK)
|
|
{
|
|
ERRORMESSAGE(("%s: Error decoding MV!\r\n", _fx_));
|
|
goto done;
|
|
}
|
|
|
|
} // endif PB or (inter and not key)
|
|
|
|
// create block pattern from CBPY & CBPC
|
|
iBlockPattern = ( (int) DC->uCBPY ) << 2;
|
|
iBlockPattern |= (int) DC->uCBPC;
|
|
|
|
// Decode all 6 blocks up to, but not including, IDCT.
|
|
for (i=0; i<6; i++)
|
|
{
|
|
if (iBlockPattern & 0x20)
|
|
{
|
|
if (DC->uMBType >= 3)
|
|
fpBlockAction->u8BlkType = BT_INTRA;
|
|
else
|
|
fpBlockAction->u8BlkType = BT_INTER;
|
|
}
|
|
else
|
|
{
|
|
if (DC->uMBType >= 3)
|
|
fpBlockAction->u8BlkType = BT_INTRA_DC;
|
|
else
|
|
fpBlockAction->u8BlkType = BT_EMPTY;
|
|
}
|
|
|
|
if (fpBlockAction->u8BlkType != BT_EMPTY)
|
|
{
|
|
fpBlockAction->u8Quant = u8Quant;
|
|
ASSERT(fpBlockAction->pCurBlock != NULL);
|
|
ASSERT(fpBlockAction->uBlkNumber == uBlockNumber);
|
|
|
|
uBitsReadOut = (*pFunc_VLD)(
|
|
fpBlockAction,
|
|
fpu8,
|
|
uBitsReadIn,
|
|
(U32 *) *pN,
|
|
(U32 *) *pRUN_INVERSE_Q);
|
|
|
|
|
|
if (uBitsReadOut == 0)
|
|
{
|
|
ERRORMESSAGE(("%s: Error decoding P block: VLD_RLD_IQ_Block return 0 bits read...\r\n", _fx_));
|
|
goto done;
|
|
}
|
|
|
|
ASSERT( **pN < 65);
|
|
|
|
*pRUN_INVERSE_Q += **pN; // NEW
|
|
if (fpBlockAction->u8BlkType != BT_INTER) // NEW
|
|
**pN += 65; // NEW
|
|
(*pN)++;
|
|
|
|
uByteCnt = uBitsReadOut >> 3; /* divide by 8 */
|
|
uBitsReadIn = uBitsReadOut & 0x7; /* mod 8 */
|
|
fpu8 += uByteCnt;
|
|
|
|
// allow the pointer to address up to four beyond the end - reading
|
|
// by DWORD using postincrement; otherwise we have bitstream error.
|
|
if (fpu8 > fpu8MaxPtr+4)
|
|
goto done;
|
|
|
|
// The test matrix includes the debug version of the driver. The
|
|
// following assertion creates a problem when testing with VideoPhone
|
|
// and so please do not check-in a version with the assertion
|
|
// uncommented.
|
|
// ASSERT(fpu8 <= fpu8MaxPtr+4);
|
|
|
|
}
|
|
else
|
|
{ // block type is empty
|
|
**pN = 0; // NEW
|
|
(*pN)++;
|
|
}
|
|
|
|
fpBlockAction++;
|
|
iBlockPattern <<= 1;
|
|
uBlockNumber++;
|
|
|
|
} // end for (i=0; i<6; i++)
|
|
|
|
|
|
//--------------------------------------------------------------------
|
|
//
|
|
// Now do the 6 B-blocks -- if needed
|
|
//
|
|
//--------------------------------------------------------------------
|
|
if (DC->bPBFrame)
|
|
{ // we are doing PB frames
|
|
fpBlockAction = pActionStream; // recover the block action stream pointer
|
|
uBlockNumber -= 6;
|
|
iBlockPattern = (int) DC->u8CBPB; // block pattern
|
|
u8Quant = (U8) ( DC->uPQuant * (5 + DC->uDBQuant) / 4 );
|
|
if (u8Quant > 31) u8Quant = 31;
|
|
if (u8Quant < 1) u8Quant = 1;
|
|
|
|
// Decode all 6 blocks up to, but not including, IDCT.
|
|
for (i=0; i<6; i++)
|
|
{
|
|
// if the block is coded
|
|
if (iBlockPattern & 0x20) {
|
|
// preserve the block type of the P-frame block
|
|
u8PBlkType = fpBlockAction->u8BlkType;
|
|
|
|
fpBlockAction->u8BlkType = BT_INTER;
|
|
fpBlockAction->u8Quant = u8Quant;
|
|
|
|
ASSERT(fpBlockAction->pBBlock != NULL);
|
|
ASSERT(fpBlockAction->uBlkNumber == uBlockNumber);
|
|
|
|
uBitsReadOut = (*pFunc_VLD)(
|
|
fpBlockAction,
|
|
fpu8,
|
|
uBitsReadIn,
|
|
(U32 *) *pN,
|
|
(U32 *) *pRUN_INVERSE_Q);
|
|
|
|
if (uBitsReadOut == 0) {
|
|
ERRORMESSAGE(("%s: Error decoding B block: VLD_RLD_IQ_Block return 0 bits read...\r\n", _fx_));
|
|
goto done;
|
|
}
|
|
|
|
ASSERT( **pN < 65); // no B-frame Intra blocks
|
|
*pRUN_INVERSE_Q += **pN; // NEW
|
|
(*pN)++;
|
|
|
|
uByteCnt = uBitsReadOut >> 3; // divide by 8
|
|
uBitsReadIn = uBitsReadOut & 0x7; // mod 8
|
|
fpu8 += uByteCnt;
|
|
|
|
// allow the pointer to address up to four beyond the
|
|
// end - reading by DWORD using postincrement; otherwise we
|
|
// have bitstream error.
|
|
if (fpu8 > fpu8MaxPtr+4)
|
|
goto done;
|
|
|
|
// The test matrix includes the debug version of the driver.
|
|
// The following assertion creates a problem when testing with
|
|
// VideoPhone and so please do not check-in a version with the
|
|
// assertion uncommented.
|
|
// ASSERT(fpu8 <= fpu8MaxPtr+4);
|
|
|
|
// restore the block type of the P-frame block
|
|
fpBlockAction->u8BlkType = u8PBlkType;
|
|
|
|
}
|
|
else
|
|
{ // block is not coded
|
|
**pN = 0; // NEW
|
|
(*pN)++;
|
|
} // end if block is coded ... else ...
|
|
|
|
fpBlockAction++;
|
|
iBlockPattern <<= 1;
|
|
uBlockNumber++;
|
|
|
|
} // end for (i=0; i<6; i++)
|
|
|
|
} // end if (DC->bPBFrame)
|
|
|
|
|
|
/* restore the scanning pointers to point to the next byte and set the
|
|
* uWork and uBitsReady values.
|
|
*/
|
|
|
|
while (uBitsReadIn > 8)
|
|
{
|
|
fpu8++;
|
|
uBitsReadIn -= 8;
|
|
}
|
|
fpbsState->uBitsReady = 8 - uBitsReadIn;
|
|
fpbsState->uWork = *fpu8++; /* store the data and point to next byte */
|
|
fpbsState->uWork &= GetBitsMask[fpbsState->uBitsReady];
|
|
fpbsState->fpu8 = fpu8;
|
|
|
|
iResult = ICERR_OK;
|
|
|
|
done:
|
|
return iResult;
|
|
|
|
} /* END H263DecodeIDCTCoeffs() */
|
|
#pragma code_seg()
|
|
|
|
#pragma code_seg("IACODE1")
|
|
I32 H263ComputeMotionVectors(T_H263DecoderCatalog FAR * DC,
|
|
T_BlkAction FAR * fpBlockAction)
|
|
|
|
{
|
|
I32 mvx1, mvy1, mvx2, mvy2, mvx3, mvy3; //predictors
|
|
// motion vector predictors for AP
|
|
I32 mvxp[3], mvyp[3];
|
|
// motion vector differences for AP
|
|
I32 mvxd[4], mvyd[4];
|
|
int iAbove; // takes you up one GOB (-1 * # of blocks in a GOB)
|
|
I32 iMBNum;
|
|
I32 iMBOffset;
|
|
I32 mvx, mvy, scratch;
|
|
int i;
|
|
I32 iNumberOfMBsPerGOB; //assume QCIF for Now
|
|
BOOL bNoAbove, bNoRight, bUMV;
|
|
|
|
const char QuarterPelRound[] = {0, 1, 0, 0};
|
|
const char SixteenthPelRound[] =
|
|
{0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1};
|
|
|
|
FX_ENTRY("H263ComputeMotionVectors");
|
|
|
|
DEBUGMSG(ZONE_DECODE_COMPUTE_MOTION_VECTORS, (" %s: MB# = %d, BlockNumber = %d, (MVDx2,MVDy2) = (%d, %d)\r\n", _fx_, fpBlockAction->uBlkNumber/6, fpBlockAction->uBlkNumber, DC->i8MVDx2, DC->i8MVDy2));
|
|
|
|
#ifdef _DEBUG
|
|
if (DC->uMBType == 2)
|
|
{
|
|
DEBUGMSG(ZONE_DECODE_COMPUTE_MOTION_VECTORS, (" %s: (MVD2x2,MVD2y2) = (%d, %d), (MVD3x2,MVD3y2) = (%d, %d), (MVD4x2,MVD4y2) = (%d, %d)\r\n", _fx_, DC->i8MVD2x2, DC->i8MVD2y2, DC->i8MVD3x2, DC->i8MVD3y2, DC->i8MVD4x2, DC->i8MVD4y2));
|
|
}
|
|
#endif
|
|
|
|
iNumberOfMBsPerGOB = DC->iNumberOfMBsPerGOB;
|
|
iMBNum = fpBlockAction->uBlkNumber / 6;
|
|
iMBOffset = iMBNum % iNumberOfMBsPerGOB;
|
|
iAbove = -6 * iNumberOfMBsPerGOB;
|
|
bNoAbove = (DC->bGOBHeaderPresent) || (iMBNum < iNumberOfMBsPerGOB);
|
|
bNoRight = iMBOffset == (iNumberOfMBsPerGOB - 1);
|
|
bUMV = DC->bUnrestrictedMotionVectors;
|
|
|
|
if (DC->uMBType != 2)
|
|
{ // One motion vector per macroblock
|
|
// when either a GOB header is present or
|
|
// we are on the first GOB, only look to the left
|
|
if ( bNoAbove )
|
|
{
|
|
// only one predictor
|
|
if (iMBOffset == 0) // when on the left edge,
|
|
mvx2 = mvy2 = 0; // use 0, else
|
|
else
|
|
{
|
|
mvx2 = fpBlockAction[-6 + 1].i8MVx2; // use upper right corner
|
|
mvy2 = fpBlockAction[-6 + 1].i8MVy2; // of MB to the left
|
|
}
|
|
}
|
|
|
|
// no GOB header and not the first GOB
|
|
// need all three predictors
|
|
else
|
|
{
|
|
// left predictor
|
|
if (iMBOffset == 0) // when on the left edge,
|
|
mvx1 = mvy1 = 0; // use 0, else
|
|
else
|
|
{
|
|
mvx1 = fpBlockAction[-6 + 1].i8MVx2; // use upper right corner
|
|
mvy1 = fpBlockAction[-6 + 1].i8MVy2; // of MB to the left
|
|
}
|
|
|
|
// above predictor
|
|
// use lower left corner
|
|
// of MB directly above
|
|
mvx2 = fpBlockAction[iAbove + 2].i8MVx2;
|
|
mvy2 = fpBlockAction[iAbove + 2].i8MVy2;
|
|
|
|
// upper right predictor
|
|
if ( bNoRight ) // when on the right edge
|
|
mvx3 = mvy3 = 0; // use 0
|
|
else
|
|
{ // else use lower left corner
|
|
// of MB above & to the right
|
|
mvx3 = fpBlockAction[iAbove + 8].i8MVx2;
|
|
mvy3 = fpBlockAction[iAbove + 8].i8MVy2;
|
|
}
|
|
|
|
// select the medium value and place it in mvx2 & mvy2
|
|
MEDIAN(mvx1, mvx2, mvx3, scratch);
|
|
MEDIAN(mvy1, mvy2, mvy3, scratch);
|
|
|
|
} // end if (header or 1st GOB) ... else ...
|
|
|
|
// mvx2 and mvy2 have the medium predictors compute the motion vector
|
|
// by adding in the difference
|
|
mvx = DC->i8MVDx2 + mvx2;
|
|
mvy = DC->i8MVDy2 + mvy2;
|
|
|
|
// check for Unrestricted Motion Vector mode and adjust the motion
|
|
// vector if necessary using the appropriate strategy, finishing
|
|
// the decoding process.
|
|
if (bUMV)
|
|
{
|
|
if (mvx2 > 32)
|
|
{
|
|
if (mvx > 63) mvx -=64;
|
|
}
|
|
else if (mvx2 < -31)
|
|
{
|
|
if (mvx < -63) mvx +=64;
|
|
}
|
|
|
|
if (mvy2 > 32)
|
|
{
|
|
if (mvy > 63) mvy -=64;
|
|
}
|
|
else if (mvy2 < -31)
|
|
{
|
|
if (mvy < -63) mvy +=64;
|
|
}
|
|
}
|
|
else
|
|
{ // UMV off
|
|
if (mvx > 31) mvx -= 64;
|
|
else if (mvx < -32) mvx += 64;
|
|
if (mvy > 31) mvy -= 64;
|
|
else if (mvy < -32) mvy += 64;
|
|
}
|
|
|
|
// save into the block action stream,
|
|
// duplicating for the other 3 Y blocks.
|
|
fpBlockAction[0].i8MVx2 =
|
|
fpBlockAction[1].i8MVx2 =
|
|
fpBlockAction[2].i8MVx2 =
|
|
fpBlockAction[3].i8MVx2 = (I8)mvx;
|
|
|
|
fpBlockAction[0].i8MVy2 =
|
|
fpBlockAction[1].i8MVy2 =
|
|
fpBlockAction[2].i8MVy2 =
|
|
fpBlockAction[3].i8MVy2 = (I8)mvy;
|
|
|
|
|
|
// Chroma motion vectors
|
|
// divide by 2 and round according to spec
|
|
fpBlockAction[4].i8MVx2 =
|
|
fpBlockAction[5].i8MVx2 =
|
|
(mvx >> 1) + QuarterPelRound[mvx & 0x03];
|
|
fpBlockAction[4].i8MVy2 =
|
|
fpBlockAction[5].i8MVy2 =
|
|
(mvy >> 1) + QuarterPelRound[mvy & 0x03];
|
|
|
|
} // end one motion vector per macroblock
|
|
else
|
|
{
|
|
// fpBlockAction[iNext[i][j]] points to block #i's (j+1)th predictor
|
|
int iNext[4][3] = {-5,2,8, 0,3,8, -3,0,1, 2,0,1};
|
|
|
|
// adjust iNext pointers which need to point to the GOB above
|
|
iNext[0][1] += iAbove; // block 0, mv2 -- block 2 of above MB
|
|
iNext[0][2] += iAbove; // block 0, mv3 -- block 2 of above-right MB
|
|
iNext[1][1] += iAbove; // block 1, mv2 -- block 3 of above MB
|
|
iNext[1][2] += iAbove; // block 1, mv3 -- block 2 of above-right MB
|
|
|
|
// fetch motion vector differences
|
|
mvxd[0] = DC->i8MVDx2;
|
|
mvyd[0] = DC->i8MVDy2;
|
|
mvxd[1] = DC->i8MVD2x2;
|
|
mvyd[1] = DC->i8MVD2y2;
|
|
mvxd[2] = DC->i8MVD3x2;
|
|
mvyd[2] = DC->i8MVD3y2;
|
|
mvxd[3] = DC->i8MVD4x2;
|
|
mvyd[3] = DC->i8MVD4y2;
|
|
|
|
// loop on Lumina blocks in this MB
|
|
for (i=0, mvx=0, mvy=0; i<4; i++)
|
|
{
|
|
// get predictor 1
|
|
if ( (i&1) || (iMBOffset) )
|
|
{ // not on left edge
|
|
mvxp[0] = fpBlockAction[iNext[i][0]].i8MVx2;
|
|
mvyp[0] = fpBlockAction[iNext[i][0]].i8MVy2;
|
|
}
|
|
else
|
|
{ // on left edge, zero the predictor
|
|
mvxp[0] = mvyp[0] = 0;
|
|
}
|
|
|
|
// for predictors 2 and 3, check if we can
|
|
// look above and that we are on blocks 0 or 1
|
|
if ( (bNoAbove) && (i < 2) )
|
|
{
|
|
// set predictor 2 equal to predictor 1
|
|
mvxp[1] = mvxp[0];
|
|
mvyp[1] = mvyp[0];
|
|
|
|
if (bNoRight)
|
|
{
|
|
// if on the right edge, zero predictor 3
|
|
mvxp[2] = mvyp[2] = 0;
|
|
}
|
|
else
|
|
{ // else set predictor 3 equal to predictor 1
|
|
mvxp[2] = mvxp[0];
|
|
mvyp[2] = mvyp[0];
|
|
} // end predictor 3
|
|
|
|
}
|
|
else
|
|
{ // okay to look up
|
|
// get predictor 2
|
|
mvxp[1] = fpBlockAction[iNext[i][1]].i8MVx2;
|
|
mvyp[1] = fpBlockAction[iNext[i][1]].i8MVy2;
|
|
|
|
// get predictor 3
|
|
if ( (bNoRight) && (i < 2) ) {
|
|
// if on the right edge, zero predictor 3
|
|
mvxp[2] = mvyp[2] = 0;
|
|
}
|
|
else
|
|
{ // else fetch it from the block action stream
|
|
mvxp[2] = fpBlockAction[iNext[i][2]].i8MVx2;
|
|
mvyp[2] = fpBlockAction[iNext[i][2]].i8MVy2;
|
|
} // end predictor 3
|
|
|
|
} // end predictors 2 & 3
|
|
|
|
// got all of the candidate predictors now get the median
|
|
// output in mv-p[1]
|
|
MEDIAN( mvxp[0], mvxp[1], mvxp[2], scratch);
|
|
MEDIAN( mvyp[0], mvyp[1], mvyp[2], scratch);
|
|
|
|
// add in the difference,
|
|
// put the freshly constructed motion vector in mv-p[0]
|
|
// leaving the predictors in mv-p[1] for use if UMV is on.
|
|
mvxp[0] = mvxp[1] + mvxd[i];
|
|
mvyp[0] = mvyp[1] + mvyd[i];
|
|
|
|
// check for Unrestricted Motion Vector mode
|
|
// and, if necessary, adjust the motion vector according
|
|
// to the appropriate decoding strategy, thereby
|
|
// finishing the decoding process.
|
|
if ( bUMV )
|
|
{
|
|
if (mvxp[1] > 32)
|
|
{
|
|
if (mvxp[0] > 63) mvxp[0] -=64;
|
|
}
|
|
else if (mvxp[1] < -31)
|
|
{
|
|
if (mvxp[0] < -63) mvxp[0] +=64;
|
|
}
|
|
|
|
if (mvyp[1] > 32)
|
|
{
|
|
if (mvyp[0] > 63) mvyp[0] -=64;
|
|
}
|
|
else if (mvyp[1] < -31)
|
|
{
|
|
if (mvyp[0] < -63) mvyp[0] +=64;
|
|
}
|
|
}
|
|
else
|
|
{ // UMV off
|
|
if (mvxp[0] > 31) mvxp[0] -= 64;
|
|
else if (mvxp[0] < -32) mvxp[0] += 64;
|
|
|
|
if (mvyp[0] > 31) mvyp[0] -= 64;
|
|
else if (mvyp[0] < -32) mvyp[0] += 64;
|
|
}
|
|
|
|
// finally store the result in the block action stream and
|
|
// accumulate the sum of Lumina for the Chroma
|
|
mvx += (fpBlockAction[i].i8MVx2 = (I8)mvxp[0]);
|
|
mvy += (fpBlockAction[i].i8MVy2 = (I8)mvyp[0]);
|
|
|
|
} // end Lumina vectors
|
|
|
|
// Compute the Chroma vectors
|
|
// divide sum of Lumina by 8 and round according to spec
|
|
fpBlockAction[4].i8MVx2 =
|
|
fpBlockAction[5].i8MVx2 =
|
|
(mvx >> 3) + SixteenthPelRound[mvx & 0x0f];
|
|
fpBlockAction[4].i8MVy2 =
|
|
fpBlockAction[5].i8MVy2 =
|
|
(mvy >> 3) + SixteenthPelRound[mvy & 0x0f];
|
|
|
|
} // end 4 motion vectors per macroblock
|
|
|
|
|
|
DEBUGMSG(ZONE_DECODE_COMPUTE_MOTION_VECTORS, (" %s: Motion vector = (%d, %d)\r\n", _fx_, fpBlockAction->i8MVx2, fpBlockAction->i8MVy2));
|
|
|
|
#ifdef _DEBUG
|
|
if (DC->uMBType == 2)
|
|
{
|
|
for (int iVector = 1; iVector < 6; iVector++)
|
|
{
|
|
DEBUGMSG(
|
|
ZONE_DECODE_COMPUTE_MOTION_VECTORS,
|
|
(" %s: Motion vector %d = (%d, %d)\r\n",
|
|
_fx_, iVector, fpBlockAction[iVector].i8MVx2, fpBlockAction[iVector].i8MVy2));
|
|
}
|
|
}
|
|
#endif
|
|
|
|
return ICERR_OK;
|
|
}
|
|
#pragma code_seg()
|
|
|
|
|