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