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.
 
 
 
 
 
 

377 lines
16 KiB

; ++ ========================================================================
;
; INTEL CORPORATION PROPRIETARY INFORMATION
;
; This software is supplied under the terms of a license
; agreement or nondisclosure agreement with Intel Corporation
; and may not be copied or disclosed except in accordance
; with the terms of that agreement.
;
; Copyright (c) 1995 Intel Corporation. All Rights Reserved.
;
; ========================================================================
;
; Declaration:
; void MBEncodeVLC (
; char * pMBRVS_Luma,
; char * pMBRVS_Chroma,
; unsigned int CodedBlkPattern,
; unsigned char ** pBitStream,
; unsigned char * pBitOffset,
; int IntraFlag,
; int MMxFlag
; );
;
; Description:
; This function encodes a macroblock's worth of RLE values.
; The RLE values are provided to me in a list of triplets
; where the triplets consist of RUN, LEVEL, and SIGN, where
; each element is a BYTE.
;
; Register Usage:
; ESI -- RLE stream cursor
; EDI -- Bit stream cursor
; EDX -- Bit stream offset
;
; $Header: S:\h26x\src\enc\e35vlc.asv 1.6 11 Oct 1996 16:44:22 BECHOLS $
;
; $Log: S:\h26x\src\enc\e35vlc.asv $
;//
;// Rev 1.6 11 Oct 1996 16:44:22 BECHOLS
;// Added a check, so that I won't choke on a zero level, even though
;// by rights the level should never be zero.
;//
;// Rev 1.5 05 Sep 1996 18:37:46 KLILLEVO
;// fixed bug which occured when value is zero after quantization
;// and run-length encoding
;//
;// Rev 1.4 15 Mar 1996 15:56:48 BECHOLS
;//
;// Changed to support separate passes over the luma and chroma.
;//
;// Rev 1.3 03 Oct 1995 20:40:40 BECHOLS
;//
;// Modified the code to reduce the code size to about .5K of cache and
;// about 4K of data. Added cache preloading, and write the VLC and sign
;// in one operation. I believe I handle the clamping correctly.
;//
;// Rev 1.2 22 Sep 1995 18:31:04 BECHOLS
;// Added clamping for the positive values as well as the negative.
;//
;// Rev 1.1 14 Sep 1995 11:45:36 BECHOLS
;// I used WDIS.EXE to determine where I could get better performance.
;// The changes I made have improved the performance by 30%.
;
; -- ========================================================================
.486
.MODEL flat, c
; ++ ========================================================================
; Name mangling in C++ forces me to declare these tables in the ASM file
; and make them externally available to C++ as extern "C" ...
; -- ========================================================================
PUBLIC FLC_INTRADC
PUBLIC VLC_TCOEF_TBL
PUBLIC VLC_TCOEF_LAST_TBL
; ++ ========================================================================
; These constants were variable in the C version, but will actually never
; change being set by the H263 specification.
; -- ========================================================================
TCOEF_ESCAPE_FIELDLEN EQU 7
TCOEF_ESCAPE_FIELDVAL EQU 3
TCOEF_RUN_FIELDLEN EQU 6
TCOEF_LEVEL_FIELDLEN EQU 8
; ++ ========================================================================
; RLS (Run Level Sign) Structure is defined just to make the code a little
; more readable.
; -- ========================================================================
RLS STRUCT
Run BYTE ?
Level BYTE ?
Sign BYTE ?
RLS ENDS
; ++ ========================================================================
; The PutBits macro puts a Variable Length Code into the bit stream. It
; expects registers to contain the correct information as follows.
; EDX -- Field Length
; EAX -- Field Value
; EDI -- Pointer to the Bitstream Pointer
; EBX -- Pointer to the Bitstream Offset
; The contents of EDI and EBX are modified and EDX and EAX are trashed.
; -- ========================================================================
PutBits MACRO
push esi
push ecx
xor ecx, ecx
mov cl, BYTE PTR [ebx] ;; Get the Bit Offset.
add edx, ecx ;; Add it to the field length.
mov ecx, 32 ;; EAX <<= (32 - (EDX + [EBX]))
sub ecx, edx ;; EDX = Field Length + Bit Offset.
mov esi, DWORD PTR [edi] ;; Set ESI to Bit Stream.
shl eax, cl ;;
bswap eax ;; Swaps byte order in EAX.
mov ecx, DWORD PTR [esi] ;; Preload cache.
or DWORD PTR [esi], eax ;; Write value to bit stream.
mov eax, edx
shr eax, 3
add [edi], eax ;; Update Bit Stream Pointer.
and edx, 000000007h
mov BYTE PTR [ebx], dl ;; Update Bit Stream Offset.
pop ecx
pop esi
ENDM
; ++ ========================================================================
; PutRunLev macro writes the ESCAPE code and Last bit, then the RUN length,
; and then the LEVEL into the stream. It assumes the following registers.
; ECX -- Last Bit
; ESI -- Pointer to RLE stream.
; EDI -- Pointer to the Bitstream Pointer
; EBX -- Pointer to the Bitstream Offset
; The contents of EDI and EBX are modified and EDX and EAX are trashed.
; -- ========================================================================
PutRunLev MACRO
LOCAL NoClamp, NotNegative, NotZero
mov eax, TCOEF_ESCAPE_FIELDVAL
mov edx, TCOEF_ESCAPE_FIELDLEN
PutBits ;; Write ESCAPE.
mov eax, ecx ;; Retrieve Last Bit.
mov edx, 1
PutBits
mov al, (RLS PTR [esi]).Run ;; Retrieve Run Length.
mov edx, TCOEF_RUN_FIELDLEN
PutBits ;; Write RUN length.
mov al, (RLS PTR [esi]).Level ;; Retrieve Level.
sub eax, 1 ; in case it is zero we want it to be modified to 127
NotZero:
cmp eax, 127
jb NoClamp
mov eax, 126
NoClamp:
add eax, 1
cmp (RLS PTR [esi]).Sign, 0FFh
jne NotNegative
mov ecx, eax
xor eax, eax
sub eax, ecx
and eax, 0000000FFh
NotNegative:
mov edx, TCOEF_LEVEL_FIELDLEN
PutBits ;; Write LEVEL.
ENDM
; ++ ========================================================================
; PutVLC macro writes the Variable Length Code and its sign bit into the
; bit stream. It expects the registers to be set up as follows.
; EDX -- VLC Code Length
; EAX -- VLC Bit Code
; ESI -- Pointer to RLE stream.
; EDI -- Pointer to the Bitstream Pointer
; EBX -- Pointer to the Bitstream Offset
; The contents of EDI and EBX are modified and EDX and EAX are trashed.
; -- ========================================================================
PutVLC MACRO
mov cl, (RLS PTR [esi]).Sign ;; Get sign bit which is [ 0 | -1 ]
and ecx, 000000001h ;; Mask off all but the low bit
or eax, ecx ;; and place it in VLC.
PutBits ;; Write the signed VLC into stream.
ENDM
; ++ ========================================================================
; CheckLast macro determines whether this is last RLE code for the block.
; It assumes the following register.
; ESI -- Pointer to RLE stream.
; It sets the following registers for subsequent use.
; EAX -- Last bit.
; ECX -- Max Table Level.
; EDX -- Pointer to the appropriate VLC table.
; -- ========================================================================
CheckLast MACRO
LOCAL IsLast, CheckDone
cmp (RLS PTR [esi + 3]).Run, 0FFh ;; Check if the last RLE.
je IsLast
xor eax, eax ;; If not then clear last bit,
lea edx, VLC_TCOEF_TBL ;; and point to proper table,
mov ecx, 12 ;; and set max table level.
jmp CheckDone
IsLast:
mov eax, 1 ;; Otherwise set the last bit,
lea edx, VLC_TCOEF_LAST_TBL ;; and point to last coef table,
mov ecx, 3 ;; and set the max table level.
CheckDone:
ENDM
; ++ ========================================================================
; IndexTable macro determines the pointer value as indexed into the table
; of coefficients. It assumes the following registers.
; ESI -- Pointer to RLE stream.
; EAX -- The level which is one (1) based.
; EDX -- The base pointer to the coefficient array.
; The EDX register is modified, EAX is trashed, and ECX is preserved
; -- ========================================================================
IndexTable MACRO
push ecx ;; Save the last bit
dec eax ;; Zero base the level value.
shl eax, 6 ;; EAX is # of run values per level
mov ecx, eax ;; added to the run value.
xor eax, eax ;;
mov al, (RLS PTR [esi]).Run ;;
add eax, ecx ;;
shl eax, 2 ;; The array has DWORDs (4 bytes)
add edx, eax ;; Add the index to the array.
pop ecx ;; Restore the last bit.
ENDM
; ++ ========================================================================
; WriteOneCode macro takes one RLE code from the triplet list and VLC
; encodes it, and writes it to the bit stream. It expects that the
; following registers will be set as shown.
; ESI -- Pointer to RLE stream.
; EDI -- Pointer to the Bitstream Pointer
; EBX -- Pointer to the Bitstream Offset
; The contents of EDI and EBX are modified and EDX , ECX, and EAX
; are trashed.
; -- ========================================================================
WriteOneCode MACRO
LOCAL RunLevel, VLCDone, NotZero
CheckLast
push eax ;; Save last bit
mov al, (RLS PTR [esi]).Level ;; Get the level value and check
test al, al ;; The level should never be zero
jnz NotZero ;; but this fixes the unlikely
mov al, 127 ;; event.
NotZero:
cmp eax, ecx ;; it against the max table level.
pop ecx ;; Restore the last bit.
jg RunLevel ;;
IndexTable ;; Sets EDX to table index
mov eax, DWORD PTR [edx] ;; Get the VLC code from table.
cmp eax, 00000FFFFh ;; Is this an escape indicator?
je RunLevel ;; If so then do RLE processing.
mov edx, eax
and eax, 00000FFFFh
shr edx, 16
PutVLC ;; Write the Variable code.
jmp VLCDone
RunLevel:
PutRunLev ;; Write the ESC RUN LEV stuff.
VLCDone:
ENDM
; ++ ========================================================================
; WriteIntraDC macro writes the Intra DC value into the bit stream. It
; expects the following registers to be set correctly.
; ESI -- Pointer to RLE stream.
; EDI -- Pointer to the Bitstream Pointer
; EBX -- Pointer to the Bitstream Offset
; The contents of EDI and EBX are modified, ESI is updated, and EDX and
; EAX are preserved.
; -- ========================================================================
WriteIntraDC MACRO
push eax
push edx
lea edx, FLC_INTRADC ;; Form index into Intra DC
mov al, (RLS PTR [esi]).Level ;; array.
add edx, eax ;;
mov al, BYTE PTR [edx] ;; Get Intra DC value.
mov edx, 8 ;; Set size of write to 8 bits.
PutBits ;; Write the Intra DC value.
add esi, SIZEOF RLS ;; Point to next triplet.
pop edx
pop eax
ENDM
; ++ ========================================================================
; WriteOneBlock macro writes all the coefficients for a single block of the
; macroblock. It assumes that the registers will be set as follows.
; ESI -- Pointer to RLE stream.
; EDI -- Pointer to the Bitstream Pointer
; EBX -- Pointer to the Bitstream Offset
; EDX -- Coded Block Pattern (CBP)
; ECX -- Intra/Inter Flag
; EAX -- CBP Mask.
; The contents of EDI and EBX are modified and EDX , ECX, and EAX are
; preserved.
; -- ========================================================================
WriteOneBlock MACRO
LOCAL NotIntra, WriteDone, WriteCodes, WriteExit
push eax
push edx
cmp ecx, 1 ;; Check to see if this is an
jne NotIntra ;; Intra block, and if so,
WriteIntraDC ;; write the DC value.
NotIntra:
and eax, edx ;; Check CBP to see if done.
jz WriteExit
WriteCodes:
mov al, BYTE PTR [esi] ;; Get the RUN value.
cmp eax, 0000000FFh ;; Check to see if done.
je WriteDone
WriteOneCode ;; Continue to write the codes
add esi, SIZEOF RLS ;; in this block until done.
jmp WriteCodes ;;
WriteDone:
add esi, SIZEOF RLS ;; Bump to next block.
WriteExit:
pop edx
pop eax
ENDM
.DATA
FLC_INTRADC DB 256 DUP (?)
VLC_TCOEF_TBL DD (64*12) DUP (?)
VLC_TCOEF_LAST_TBL DD (64*3) DUP (?)
.CODE
; ++ ========================================================================
; This is the C function call entry point. This function variable length
; encodes an entire macroblock, one block at a time.
; -- ========================================================================
MBEncodeVLC PROC PUBLIC USES edi esi ebx ecx, pMBRVS_Luma:DWORD, pMBRVS_Chroma:DWORD, CodedBlockPattern:DWORD, ppBitStream:DWORD, pBitOffset:DWORD, IntraFlag:DWORD, MMxFlag:DWORD
mov esi, pMBRVS_Luma
mov edi, ppBitStream
mov ebx, pBitOffset
mov edx, CodedBlockPattern
mov esi, [esi]
mov eax, 1 ; CBP Mask.
LumaWriteLoop:
test eax, 000000010h ; When EAX bit shifts to this
jnz LumaBlocksDone ; position, we are done with Luma.
mov ecx, IntraFlag
WriteOneBlock
shl eax, 1 ; Shift CBP mask to next block.
jmp LumaWriteLoop
LumaBlocksDone:
mov ecx, MMxFlag
test ecx, 1
jz ChromaWriteLoop
mov ecx, pMBRVS_Luma
mov [ecx],esi
mov ecx, pMBRVS_Chroma
mov esi,[ecx]
ChromaWriteLoop:
test eax, 000000040h ; When EAX bit shifts to this
jnz ChromaBlocksDone ; position, we are done.
mov ecx, IntraFlag
WriteOneBlock
shl eax, 1 ; Shift CBP mask to next block.
jmp ChromaWriteLoop
ChromaBlocksDone:
mov eax, pMBRVS_Chroma
mov ecx, MMxFlag
test ecx, 1
jz MacroBlockDone
mov [eax],esi
MacroBlockDone:
ret
MBEncodeVLC ENDP
END