Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

727 lines
27 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) 1996 Intel Corporation.
** All Rights Reserved.
**
** *************************************************************************
*/
////////////////////////////////////////////////////////////////////////////
// $Author:$
// $Date:$
// $Archive:$
// $Header:$
// $Log:$
////////////////////////////////////////////////////////////////////////////
//--------------------------------------------------------------------------
//
// d1bvriq.cpp
//
// Description:
// This routine performs run length decoding and inverse quantization
// of transform coefficients for one non-empty block.
//
// Routines:
// VLD_RLD_IQ_Block
//
// Inputs (dwords pushed onto stack by caller):
// lpBlockAction pointer to Block action stream for current blk.
//
// lpSrc The input bitstream.
//
// uBitsInOut Number of bits already read.
//
// pIQ_INDEX Pointer to coefficients and indices.
//
// pN Pointer to number of coefficients read.
//
// Returns:
// 0 on bit stream error, otherwise total number of bits read
// (including number read prior to call).
//
// Note:
// This has not been verfied as layout!!!
// The structure of gTAB_TCOEFF_MAJOR is as follows:
// bits name: description
// ---- ----- -----------
// 25-18 bits: number of bitstream bits used
// 17 last: flag for last coefficient
// 16-9 run: number of preceeding 0 coefficients plus 1
// 8-2 level: absolute value of coefficient
// 1 sign: sign of coefficient
// 0 hit: 1 = major table miss, 0 = major table hit
//
// The structure of gTAB_TCOEFF_MINOR is the same, right shifted by 1 bit.
// A gTAB_TCOEFF_MAJOR value of 00000001h indicates the escape code.
//
//--------------------------------------------------------------------------
//Block level decoding for H.261 decoder
#include "precomp.h"
#define HIGH_FREQ_CUTOFF 6 + 4
// local variable definitions
#define FRAMEPOINTER esp
#define L_BITSUSED FRAMEPOINTER + 0 // 4 byte
#define L_QUANT L_BITSUSED + 4
#define L_RUNCUM L_QUANT + 4
#define L_EVENT L_RUNCUM + 4
#define L_BLOCKTYPE L_EVENT + 4
#define L_COEFFINDEX L_BLOCKTYPE + 4
#define L_INPUTSRC L_COEFFINDEX + 4
#define L_LPACTION L_INPUTSRC + 4
#define L_ecx L_LPACTION + 4
#define L_NUMOFBYTES L_ecx + 4
#define L_NUMOFBITS L_NUMOFBYTES + 4
#ifdef CHECKSUM_MACRO_BLOCK
#define L_SAVEREG L_NUMOFBITS + 4
#define L_SAVEREG2 L_SAVEREG + 4
#define L_CHECKSUM L_SAVEREG2 + 4
#define L_CHECKSUMADDR L_CHECKSUM + 4
#define L_COEFFCOUNT L_CHECKSUMADDR + 4
#define L_COEFFVALUE L_COEFFCOUNT + 4
#else
#define L_COEFFCOUNT L_NUMOFBITS + 4
#define L_COEFFVALUE L_COEFFCOUNT + 4
#endif
#define L_END_OF_FRAME FRAMEPOINTER + 128 // nothing
#define LOCALSIZE ((128+3)&~3) // keep aligned
#define HUFFMAN_ESCAPE 0x5f02 // Huffman escape code
////////////////////////////////////////////////////////////////
// Decode a none empty block
//
////////////////////////////////////////////////////////////////
#pragma code_seg("IACODE1")
extern "C" __declspec(naked)
U32 VLD_RLD_IQ_Block(T_BlkAction *lpBlockAction,
U8 *lpSrc,
U32 uBitsread,
U32 *pN,
U32 *pIQ_INDEX)
{
__asm {
push ebp // save callers frame pointer
mov ebp, esp // make parameters accessible
push esi // assumed preserved
push edi
push ebx
xor eax, eax
xor edx, edx
sub esp, LOCALSIZE // reserve local storage
mov esi, lpSrc
#ifdef CHECKSUM_MACRO_BLOCK
mov edi, uCheckSum
;
mov ecx, [edi]
mov [L_CHECKSUMADDR], edi
;
mov [L_CHECKSUM], ecx
#endif
// zero out the BLOCKSTORE , 64*2 /32 load, 64*2/4 writes
// it is very likely that the cache has been loaded for
// the stack. Need to find out this later.
mov edi, lpBlockAction //pair with operation above
xor ecx, ecx
mov [L_INPUTSRC], esi
mov eax, uBitsread
mov [L_LPACTION], edi
mov [L_COEFFCOUNT], ecx // zero out coefficient counter
mov [L_COEFFVALUE], ecx // zero out coefficient value
mov [L_NUMOFBYTES], ecx // zero out number of bytes used
mov dl, [edi]T_BlkAction.u8Quant
mov cl, al // init cl to no. of bits used
shl edx, 6 // leave room for val later,
// quant*32 shift by 6 because,
// 5-bits for quant look up &
// it's a word table. Don't need
// to multiply by 2 later
mov [L_BITSUSED], eax // init the counter
mov bl, [edi]T_BlkAction.u8BlkType
mov edi, pIQ_INDEX // Load edi with address of output
// array
mov [L_QUANT], edx // save quant for this block;
mov [L_BLOCKTYPE], ebx // save block type
;
/////////////////////////////////////////////////////////////////////
// registers:
// eax: 4 bytes input bits
// ebx: block type
// ecx: bits count
// edx: quant*64
// esi: input source
// edi: output array address
// ebp: bits count >>4
mov DWORD PTR [L_RUNCUM], 0ffh // Adjust total run for INTER Blocks
cmp bl, 1 // bl has block type
ja ac_coeff // jump if not INTRA coded
//decode DC first, and invserse quanitzation, 13 clocks
mov ah,[esi]
xor ebx, ebx
mov al,[esi+1]
mov DWORD PTR [L_RUNCUM], ebx
shl eax, cl
;
and eax, 0ffffh
;
shr eax, 8
;
#ifdef CHECKSUM_MACRO_BLOCK
mov [L_SAVEREG], eax // save eax in temp
mov edi, [L_CHECKSUM]
shl eax, 8
and eax, 0000ff00h // just get DC
;
cmp eax, 0000ff00h // special case when INTRADC==ff, use 80
jne not_255_chk
mov eax, 00008000h
not_255_chk:
add edi, eax // add to DC checksum
;
mov [L_CHECKSUM], edi // save updated checksum
mov eax, [L_SAVEREG] // restore eax
#endif
shl eax, 3 // INTRADC*8
xor ecx, ecx
cmp eax, 7f8h // take out 11111111 code word.
jne not_255
mov eax, 0400h
not_255:
mov ebx, eax // inversed quantized DC
// save in output array value and index
mov [edi], eax // DC inversed quantized value
mov [edi+4], ecx // index 0
add edi, 8 // increment output address
mov ecx,[L_COEFFCOUNT] // get coefficient counter
mov ebx,[L_BLOCKTYPE]
inc ecx
mov [L_COEFFCOUNT], ecx // save updated coef counter
mov ecx,[L_BITSUSED]
test bl,bl
jz done_dc // jump if only the INTRADC present
add cl, 8 // Add 8 to bits used counter for DC
jmp vld_code // Skip around 1s special case
ac_coeff:
nop
mov ah,[esi]
mov al,[esi+1]
mov dh,[esi+2]
shl eax,16
mov dl,[esi+3]
mov ax, dx
shl eax, cl
mov [L_ecx], ecx
mov edx, eax //save in edx
shr eax, 24 //mask of high order 24 bits
;
; // agi
;
mov bh, gTAB_TCOEFF_tc1a[eax*2] //get the codewords
mov bl, gTAB_TCOEFF_tc1a[eax*2+1] //get the codewords
jmp InFrom1stac
vld_code:
mov ah,[esi]
mov dh,[esi+2]
mov al,[esi+1]
mov dl,[esi+3]
shl eax,16
mov ax, dx
shl eax, cl
mov [L_ecx], ecx
mov edx, eax //save in edx
shr eax, 24 //mask of high order 24 bits
;
; // agi
;
mov bh, gTAB_TCOEFF_tc1[eax*2] //get the codewords
mov bl, gTAB_TCOEFF_tc1[eax*2+1] //get the codewords
InFrom1stac:
mov ax, bx
cmp bx, HUFFMAN_ESCAPE
mov [L_EVENT], eax // 3-bits lenght-1,1-bit if code>8bits,
// 4-bits run,8-bits val
je Handle_Escapes
sar ax, 12 // if 12th bit NOT set, code <= 8-bits
mov [L_NUMOFBITS], ax // save for later the number of bits
js Gt8bits // jump
mov eax, [L_EVENT]
mov ebx, [L_QUANT] //bx:4::8 quant has val
and eax, 0ffh
movsx eax, al //sign extend level
add eax, eax
jns AROUND // if positive jump
neg eax // convert neg to positive
inc eax // increment
#ifdef CHECKSUM_MACRO_BLOCK
/* add in sign to checksum */
mov [L_SAVEREG2], edi // save edi in temp
mov edi, [L_CHECKSUM]
inc edi // add 1 to checksum when sign negative
/* add in level, shift left 8 and add to checksum */
mov [L_SAVEREG], eax // save eax in temp
mov eax, [L_EVENT]
and eax, 0ffh
neg eax
and eax, 0ffh
shl eax, 8 // shift level left 8
add edi, eax // add to level checksum
mov eax, [L_SAVEREG] // restore eax
mov [L_CHECKSUM], edi // save updated checksum
mov edi, [L_SAVEREG2] // restore edi
jmp NEG_AROUND
#endif
AROUND:
#ifdef CHECKSUM_MACRO_BLOCK
/* add in level, shift left 8 and add to checksum */
mov [L_SAVEREG], eax // save eax in temp
mov [L_SAVEREG2], edi // save edi in temp
mov eax, [L_EVENT]
shl eax, 8 // shift level left 8
mov edi, [L_CHECKSUM]
and eax, 0000ff00h // just get level
;
add edi, eax // add to level checksum
mov eax, [L_SAVEREG] // restore eax
mov [L_CHECKSUM], edi // save updated checksum
mov edi, [L_SAVEREG2] // restore edi
NEG_AROUND:
#endif
mov bx, gTAB_INVERSE_Q[2*eax+ebx] //ebx has the inverse quant
mov eax, [L_EVENT]
shr eax, 8 //leave RUN at al
;
and eax, 0fh // RUN is just 4-bits
#ifdef CHECKSUM_MACRO_BLOCK
/* add in run, shift left 24 and add to checksum */
mov [L_SAVEREG], eax // save eax in temp
mov [L_SAVEREG2], edi // save edi in temp
shl eax, 24 // shift run left 24
mov edi, [L_CHECKSUM]
add edi, eax // add run to checksum
mov eax, [L_SAVEREG] // restore eax
mov [L_CHECKSUM], edi // save updated checksum
mov edi, [L_SAVEREG2] // restore edi
#endif
mov edx, [L_RUNCUM] // Zig-zag and run length decode
inc al // run+1
add dl, al // dl cumulated run
mov [L_RUNCUM], edx // update the cumulated run ;
mov ecx, gTAB_ZZ_RUN[edx*4]
mov edx, [L_EVENT] // restore run, level to temp
movsx ebx,bx
and edx, 0ffh // get just level
add edx, edx // For EOB level will be zero
jz last_coeff // jump to last_coeff if EOB
// save in output array value and index
mov [edi], ebx // save inversed quantized value
mov [edi+4], ecx // save index
mov ecx,[L_COEFFCOUNT] // get coefficient counter
inc ecx
mov [L_COEFFCOUNT], ecx // save updated coef counter
mov ecx, [L_ecx]
mov eax, [L_NUMOFBITS] // fetch num of bits-1
inc al
add edi, 8 // increment output address
add cl, al //adjust bits used,
mov ebx, [L_NUMOFBYTES] // fetch number of bytes used
test al, al
jz error
cmp cl, 16
jl vld_code //if needs to save ebx, and edx, jump
add esi, 2 //to vld_code to reload
inc ebx // increment number of bytes used
mov [L_NUMOFBYTES], ebx // store updated number of bytes used
;
sub cl, 16
jmp vld_code
/////////
Gt8bits:
// code > 8-bits
neg ax // -(no of bits -1)
shl edx, 8 // shift of just used 8 bits
add ecx, 8 // Update bit counter by 8
add cx, ax // Update by extra bits
and ebx, 0ffh
dec ecx // dec because desired value is no of
// bits -1
mov [L_ecx], ecx // store
mov cl, 32 // 32
sub cl, al // get just the extra bits
shr edx, cl
add bx, dx
xor ecx, ecx
movzx ebx, bx
shl edx, 3 //do this even if hit major
mov [L_NUMOFBITS], ecx // set num of bits for codes > 8 to 0
// because already updated ecx.
mov ah,gTAB_TCOEFF_tc2[ebx*2]//use minor table with 10 bits
mov al, gTAB_TCOEFF_tc2[ebx*2+1]
mov ebx, [L_QUANT] //bx:4::8 quant has val
mov [L_EVENT], eax
// RLD+ ZZ and Inverse quantization
and eax, 0ffh
movsx eax, al //sign extend level
add eax, eax
jns AROUND1 // if positive jump
neg eax // convert neg to positive
inc eax // increment
#ifdef CHECKSUM_MACRO_BLOCK
/* add in sign to checksum */
mov [L_SAVEREG2], edi // save edi in temp
mov edi, [L_CHECKSUM]
inc edi // add 1 to checksum when sign negative
/* add in level, shift left 8 and add to checksum */
mov [L_SAVEREG], eax // save eax in temp
mov eax, [L_EVENT]
and eax, 0ffh
neg eax
and eax, 0ffh
shl eax, 8 // shift level left 8
add edi, eax // add to level checksum
mov eax, [L_SAVEREG] // restore eax
mov [L_CHECKSUM], edi // save updated checksum
mov edi, [L_SAVEREG2] // restore edi
jmp NEG_AROUND1
#endif
AROUND1:
#ifdef CHECKSUM_MACRO_BLOCK
/* add in level, shift left 8 and add to checksum */
mov [L_SAVEREG], eax // save eax in temp
mov [L_SAVEREG2], edi // save edi in temp
mov eax, [L_EVENT]
shl eax, 8 // shift level left 8
mov edi, [L_CHECKSUM]
and eax, 0000ff00h // just get level
;
add edi, eax // add to level checksum
mov eax, [L_SAVEREG] // restore eax
mov [L_CHECKSUM], edi // save updated checksum
mov edi, [L_SAVEREG2] // restore edi
NEG_AROUND1:
#endif
mov bx, gTAB_INVERSE_Q[2*eax+ebx] //ebx has the inverse quant
mov eax, [L_EVENT]
shr eax, 8 //leave RUN at al
and eax, 01fh // RUN is just 5-bits
#ifdef CHECKSUM_MACRO_BLOCK
/* add in run, shift left 24 and add to checksum */
mov [L_SAVEREG], eax // save eax in temp
mov [L_SAVEREG2], edi // save edi in temp
shl eax, 24 // shift run left 24
mov edi, [L_CHECKSUM]
add edi, eax // add run to checksum
mov eax, [L_SAVEREG] // restore eax
mov [L_CHECKSUM], edi // save updated checksum
mov edi, [L_SAVEREG2] // restore edi
#endif
mov edx, [L_RUNCUM] //Zig-zag and run length decode
inc al // run+1
add dl, al //dl cumulated run
movsx ebx,bx
mov [L_RUNCUM], edx //update the cumulated run ;
mov ecx, gTAB_ZZ_RUN[edx*4]
mov edx, [L_EVENT] // restore run, level to temp
and edx, 0ffh // get just level
add edx, edx // For EOB level will be zero
jz last_coeff // jump to last_coeff if EOB
// save in output array value and index
mov [edi], ebx // store inversed quantized value
mov [edi+4], ecx // store index
mov ecx,[L_COEFFCOUNT] // get coefficient counter
inc ecx
mov [L_COEFFCOUNT], ecx // save updated coef counter
mov ecx, [L_ecx]
mov eax, [L_NUMOFBITS] // fetch num of bits-1
inc al
add edi, 8 // increment output address
add cl, al //adjust bits used,
mov ebx, [L_NUMOFBYTES] // fetch num of bytes used
test al, al
jz error
cmp cl, 16
jl vld_code //if needs to save ebx, and edx, jump
add esi, 2 //to vld_code to reload
inc ebx // increment number of bytes used
mov [L_NUMOFBYTES], ebx // store updated number of bytes used
;
sub cl, 16
jmp vld_code
last_coeff: //need to tell it is INTRA or INTER coded
mov ecx, [L_ecx] // restore no of bits used
mov eax, [L_NUMOFBITS] // get no of bits-1
inc al
add cl,al //update bits used count
mov [L_ecx], ecx
#ifdef CHECKSUM_MACRO_BLOCK
mov ecx, [L_CHECKSUM]
mov edi, [L_CHECKSUMADDR]
mov [edi], ecx
#endif
// Add in High Frequency Cutoff check
//
mov eax, [L_RUNCUM] // Total run
mov edx, [L_LPACTION] //pair with operation above
cmp eax, HIGH_FREQ_CUTOFF
jg No_set
mov bl, [edx]T_BlkAction.u8BlkType
or bl, 80h // set hi bit
mov [edx]T_BlkAction.u8BlkType, bl
//
No_set:
mov eax, pN
mov ecx,[L_COEFFCOUNT] // get coefficient counter
mov [eax], ecx // return number of coef
//akk
mov edi,[L_NUMOFBYTES]
mov eax,[L_ecx]
shl edi, 4 // convert bytes used to bits used
add esp,LOCALSIZE // free locals
add eax,edi // add bits used to last few bits used
pop ebx
pop edi
pop esi
pop ebp
ret
error:
#ifdef CHECKSUM_MACRO_BLOCK
mov ecx, [L_CHECKSUM]
mov edi, [L_CHECKSUMADDR]
mov [edi], ecx
#endif
xor eax,eax
add esp,LOCALSIZE // free locals
pop ebx
pop edi
pop esi
pop ebp
ret
//NOTES: 1. the following codes need to be optimized later.
// 2. the codes will be rarely used.
// at this point: eax has 32bits - cl valid bits
// first cl+7 bits
Handle_Escapes: //process escape code separately
add cl, 6 // escape 6-bit code
mov ebx, [L_NUMOFBYTES] // fetch number of bytes used
cmp cl, 16
jl less_16
add esi, 2
sub cl, 16
inc ebx // increment number of bytes used
mov [L_NUMOFBYTES], ebx // store updated number of bytes used
less_16:
mov ah,[esi] // these codes will be further
mov dh,[esi+2]
mov al,[esi+1]
mov dl,[esi+3]
shl eax,16
mov ebx, [L_RUNCUM]
mov ax, dx
inc bl //increae the total run
shl eax, cl
mov edx,eax
shr eax, 32-6 //al has run
#ifdef CHECKSUM_MACRO_BLOCK
/* add in run, shift left 24 and add to checksum */
mov [L_SAVEREG], eax // save eax in temp
mov [L_SAVEREG2], edi // save edi in temp
shl eax, 24 // shift run left 24
mov edi, [L_CHECKSUM]
add edi, eax // add run to checksum
mov eax, [L_SAVEREG] // restore eax
mov [L_CHECKSUM], edi // save updated checksum
mov edi, [L_SAVEREG2] // restore edi
#endif
shl edx, 6 // cl < 6, cl+6 < 16
add al,bl
sar edx, 32-8 //8 bits level, keep the sign
mov [L_RUNCUM], eax
; // agi
;
mov ebx, gTAB_ZZ_RUN[eax*4] //run length decode
mov eax, [L_QUANT] //bx:4::8 quant has val
shr eax, 6 //recover quant
mov [L_COEFFINDEX], ebx
#ifdef CHECKSUM_MACRO_BLOCK
/* add in level, shift left 8 and add to checksum */
mov [L_SAVEREG], edx // save edx in temp
mov [L_SAVEREG2], edi // save edi in temp
mov edi, [L_CHECKSUM]
cmp edx, 0 // test level
jns Pos_Level
neg edx
inc edi // add 1 when sign negative
Pos_Level:
shl edx, 8 // shift level left 8
and edx, 0000ff00h // just get level
;
add edi, edx // add to level checksum
mov edx, [L_SAVEREG] // restore edx
mov [L_CHECKSUM], edi // save updated checksum
mov edi, [L_SAVEREG2] // restore edi
#endif
// new code
test edx, 7fh // test for invalid codes
jz error
imul edx, eax // edx = L*Q
;
dec eax // Q-1
mov ebx, edx // mask = LQ
sar ebx, 31 // -l if L neq, else 0
or eax, 1 // Q-1 if Even, else Q
xor eax, ebx // -Q[-1] if L neg, else = Q[-1]
add edx, edx // 2*L*Q
sub eax, ebx // -(Q[-1]) if L neg, else = Q[-1]
add edx, eax // 2LQ +- Q[-1]
// now clip to -2048 ... +2047 (12 bits: 0xfffff800 <= res <= 0x000007ff)
cmp edx, -2048
jge skip1
mov edx, -2048
jmp run_zz_q_fixed
skip1:
cmp edx, +2047
jle run_zz_q_fixed
mov edx, +2047
run_zz_q_fixed:
mov ebx, [L_COEFFINDEX]
// save in output array value and index
mov [edi], edx // save inversed quantized value
mov [edi+4], ebx // save index
mov ebx,[L_COEFFCOUNT] // get coefficient counter
inc ebx
mov [L_COEFFCOUNT], ebx // save updated coef counter
add cl, 14
add edi, 8 // increment output address
mov ebx, [L_NUMOFBYTES] // fetch number of bytes used
cmp cl, 16
jl vld_code
add esi, 2
sub cl, 16
inc ebx // increment number of bytes used
mov [L_NUMOFBYTES], ebx // store updated number of bytes used
jmp vld_code
// 18 clocks without cache misses in the inner loop for
// the most frequenctly used events 8/2/95
// the above numbers changed becuase of integration with
// bitstream parsing and IDCT. 8/21/95
done_dc://intra coded block
add ecx, 8
#ifdef CHECKSUM_MACRO_BLOCK
mov ecx, [L_CHECKSUM]
mov edi, [L_CHECKSUMADDR]
mov [edi], ecx
#endif
// Add in High Frequency Cutoff check
//
mov edx, [L_RUNCUM] // Total run
mov eax, lpBlockAction //pair with operation above
cmp edx, HIGH_FREQ_CUTOFF
jg No_set_Intra
mov bl, [eax]T_BlkAction.u8BlkType
or bl, 80h // set hi bit
mov [eax]T_BlkAction.u8BlkType, bl
//
No_set_Intra:
mov eax, pN
mov ebx,[L_COEFFCOUNT] // get coefficient counter
mov [eax], ebx // return number of coef
add esp,LOCALSIZE // free locals
mov eax,ecx
pop ebx
pop edi
pop esi
pop ebp
ret
} //end of asm
} // end of VLD_RLD_IQ_Block
#pragma code_seg()