www.pudn.com > AvsVideoCodec.rar > vlc.c
/* ***************************************************************************** * COPYRIGHT AND WARRANTY INFORMATION * * Copyright 2003, Advanced Audio Video Coding Standard, Part II * * DISCLAIMER OF WARRANTY * * The contents of this file are subject to the Mozilla Public License * Version 1.1 (the "License"); you may not use this file except in * compliance with the License. You may obtain a copy of the License at * http://www.mozilla.org/MPL/ * * Software distributed under the License is distributed on an "AS IS" * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the * License for the specific language governing rights and limitations under * the License. * * THIS IS NOT A GRANT OF PATENT RIGHTS - SEE THE AVS PATENT POLICY. * The AVS Working Group doesn't represent or warrant that the programs * furnished here under are free of infringement of any third-party patents. * Commercial implementations of AVS, including shareware, may be * subject to royalty fees to patent holders. Information regarding * the AVS patent policy for standardization procedure is available at * AVS Web site http://www.avs.org.cn. Patent Licensing is outside * of AVS Working Group. * * The Original Code is Reference Software for China National Standard * GB/T 20090.2-2006 (short for AVS-P2 or AVS Video) at version RM52J. * * The Initial Developer of the Original Code is Video subgroup of AVS * Workinggroup (Audio and Video coding Standard Working Group of China). * Contributors: Guoping Li, Siwei Ma, Jian Lou, Qiang Wang , * Jianwen Chen,Haiwu Zhao, Xiaozhen Zheng, Junhao Zheng, Zhiming Wang * ****************************************************************************** */ /* ************************************************************************************* * File name: vlc.c * Function: VLC support functions * ************************************************************************************* */ #include "contributors.h" #include#include #include #include #include #include "global.h" #include "vlc.h" #include "elements.h" #include "header.h" #include "golomb_dec.h" // A little trick to avoid those horrible #if TRACE all over the source code #if TRACE #define SYMTRACESTRING(s) strncpy(sym->tracestring,s,TRACESTRING_SIZE) #else #define SYMTRACESTRING(s) // do nothing #endif extern void tracebits(const char *trace_str, int len, int info,int value1); extern void tracebits3(const char *trace_str, int len, int info,int value1); int UsedBits; // for internal statistics, is adjusted by se_v, ue_v, u_1 /* ************************************************************************* * Function:ue_v, reads an ue(v) syntax element, the length in bits is stored in the global UsedBits variable * Input: tracestring the string for the trace file bitstream the stream to be read from * Output: * Return: the value of the coded syntax element * Attention: ************************************************************************* */ int ue_v (char *tracestring) { SyntaxElement symbol, *sym=&symbol; assert (currStream->streamBuffer != NULL); sym->type = SE_HEADER; sym->mapping = linfo_ue; // Mapping rule SYMTRACESTRING(tracestring); readSyntaxElement_VLC (sym); return sym->value1; } /* ************************************************************************* * Function:ue_v, reads an se(v) syntax element, the length in bits is stored in the global UsedBits variable * Input: tracestring the string for the trace file bitstream the stream to be read from * Output: * Return: the value of the coded syntax element * Attention: ************************************************************************* */ int se_v (char *tracestring) { SyntaxElement symbol, *sym=&symbol; assert (currStream->streamBuffer != NULL); sym->type = SE_HEADER; sym->mapping = linfo_se; // Mapping rule: signed integer SYMTRACESTRING(tracestring); readSyntaxElement_VLC (sym); return sym->value1; } /* ************************************************************************* * Function:ue_v, reads an u(v) syntax element, the length in bits is stored in the global UsedBits variable * Input: tracestring the string for the trace file bitstream the stream to be read from * Output: * Return: the value of the coded syntax element * Attention: ************************************************************************* */ int u_v (int LenInBits, char*tracestring) { SyntaxElement symbol, *sym=&symbol; assert (currStream->streamBuffer != NULL); sym->type = SE_HEADER; sym->mapping = linfo_ue; // Mapping rule sym->len = LenInBits; SYMTRACESTRING(tracestring); readSyntaxElement_FLC (sym); return sym->inf; } int i_8(char *tracestring) //add by wuzhongmou 0610 { int frame_bitoffset = currStream->frame_bitoffset; byte *buf = currStream->streamBuffer; int BitstreamLengthInBytes = currStream->bitstream_length; SyntaxElement symbol, *sym=&symbol; assert (currStream->streamBuffer != NULL); sym->len = 8; sym->type = SE_HEADER; sym->mapping = linfo_ue; SYMTRACESTRING(tracestring); if ((GetBits(buf, frame_bitoffset, &(sym->inf), BitstreamLengthInBytes, sym->len)) < 0) return -1; currStream->frame_bitoffset += sym->len; // move bitstream pointer sym->value1 = sym->inf; if (sym->inf & 0x80) sym->inf= -(~((int)0xffffff00 | sym->inf) + 1); #if TRACE tracebits2(sym->tracestring, sym->len, sym->inf); #endif return sym->inf; //add by wuzhongmou 0610 } /* ************************************************************************* * Function:ue_v, reads an u(1) syntax element, the length in bits is stored in the global UsedBits variable * Input: tracestring the string for the trace file bitstream the stream to be read from * Output: * Return: the value of the coded syntax element * Attention: ************************************************************************* */ int u_1 (char *tracestring) { return u_v (1, tracestring); } /* ************************************************************************* * Function:mapping rule for ue(v) syntax elements * Input:lenght and info * Output:number in the code table * Return: * Attention: ************************************************************************* */ void linfo_ue(int len, int info, int *value1, int *dummy) { *value1 = (int)pow(2,(len/2))+info-1; // *value1 = (int)(2<<(len>>1))+info-1; } /* ************************************************************************* * Function:mapping rule for se(v) syntax elements * Input:lenght and info * Output:signed mvd * Return: * Attention: ************************************************************************* */ void linfo_se(int len, int info, int *value1, int *dummy) { int n; n = (int)pow(2,(len/2))+info-1; *value1 = (n+1)/2; if((n & 0x01)==0) // lsb is signed bit *value1 = -*value1; } /* ************************************************************************* * Function:lenght and info * Input: * Output:cbp (intra) * Return: * Attention: ************************************************************************* */ void linfo_cbp_intra(int len,int info,int *cbp, int *dummy) { // extern const byte NCBP[48][2]; extern const byte NCBP[64][2]; //jlzheng 7.20 int cbp_idx; linfo_ue(len,info,&cbp_idx,dummy); *cbp=NCBP[cbp_idx][0]; } /* ************************************************************************* * Function: * Input:lenght and info * Output:cbp (inter) * Return: * Attention: ************************************************************************* */ void linfo_cbp_inter(int len,int info,int *cbp, int *dummy) { //extern const byte NCBP[48][2]; extern const byte NCBP[64][2]; //cjw 20060321 int cbp_idx; linfo_ue(len,info,&cbp_idx,dummy); *cbp=NCBP[cbp_idx][1]; } /* ************************************************************************* * Function:read next UVLC codeword from UVLC-partition and map it to the corresponding syntax element * Input: * Output: * Return: * Attention: ************************************************************************* */ int readSyntaxElement_VLC(SyntaxElement *sym) { int frame_bitoffset = currStream->frame_bitoffset; byte *buf = currStream->streamBuffer; int BitstreamLengthInBytes = currStream->bitstream_length; sym->len = GetVLCSymbol (buf, frame_bitoffset, &(sym->inf), BitstreamLengthInBytes); if (sym->len == -1) return -1; currStream->frame_bitoffset += sym->len; sym->mapping(sym->len,sym->inf,&(sym->value1),&(sym->value2)); #if TRACE tracebits(sym->tracestring, sym->len, sym->inf, sym->value1); #endif return 1; } /* ************************************************************************* * Function:read next UVLC codeword from UVLC-partition and map it to the corresponding syntax element * Input: * Output: * Return: * Attention: ************************************************************************* */ int readSyntaxElement_UVLC(SyntaxElement *sym, struct inp_par *inp) { int frame_bitoffset = currStream->frame_bitoffset; byte *buf = currStream->streamBuffer; int BitstreamLengthInBytes = currStream->bitstream_length; if( sym->golomb_maxlevels && (sym->type==SE_LUM_DC_INTRA||sym->type==SE_LUM_AC_INTRA||sym->type==SE_LUM_DC_INTER||sym->type==SE_LUM_AC_INTER) ) return readSyntaxElement_GOLOMB(sym,img,inp); if(sym->type == SE_REFFRAME) { sym->len = 1; if ((GetVLCSymbol_refidx(buf, frame_bitoffset, &(sym->inf), BitstreamLengthInBytes)) < 0) return -1; sym->value1 = sym->inf; currStream->frame_bitoffset += sym->len; #if TRACE tracebits3(sym->tracestring, sym->len, sym->inf, sym->value1);//sym->inf, sym->value1); #endif } else { sym->len = GetVLCSymbol (buf, frame_bitoffset, &(sym->inf), BitstreamLengthInBytes); if (sym->len == -1) return -1; currStream->frame_bitoffset += sym->len; sym->mapping(sym->len,sym->inf,&(sym->value1),&(sym->value2)); #if TRACE tracebits(sym->tracestring, sym->len, sym->inf, sym->value1); #endif } return 1; } /* ************************************************************************* * Function:read next VLC codeword for 4x4 Intra Prediction Mode and map it to the corresponding Intra Prediction Direction * Input: * Output: * Return: * Attention: ************************************************************************* */ int readSyntaxElement_Intra8x8PredictionMode(SyntaxElement *sym) { int frame_bitoffset = currStream->frame_bitoffset; byte *buf = currStream->streamBuffer; int BitstreamLengthInBytes = currStream->bitstream_length; sym->len = GetVLCSymbol_IntraMode (buf, frame_bitoffset, &(sym->inf), BitstreamLengthInBytes); if (sym->len == -1) return -1; currStream->frame_bitoffset += sym->len; sym->value1 = sym->len == 1 ? -1 : sym->inf; #if TRACE tracebits2(sym->tracestring, sym->len, sym->value1); #endif return 1; } /* ************************************************************************* * Function: * Input: * Output: * Return: * Attention: ************************************************************************* */ int GetVLCSymbol_IntraMode (byte buffer[],int totbitoffset,int *info, int bytecount) { register int inf; long byteoffset; // byte from start of buffer int bitoffset; // bit from start of byte int ctr_bit=0; // control bit for current bit posision int bitcounter=1; int len; int info_bit; byteoffset = totbitoffset/8; bitoffset = 7-(totbitoffset%8); ctr_bit = (buffer[byteoffset] & (0x01< bytecount) { return -1; } inf=(inf<<1); if(buffer[byteoffset] & (0x01<<(bitoffset))) inf |=1; } *info = inf; return bitcounter; // return absolute offset in bit from start of frame } /* ************************************************************************* * Function: Moves the read pointer of the partition forward by one symbol * Input: byte buffer[] containing VLC-coded data bits int totbitoffset bit offset from start of partition int type expected data type (Partiotion ID) * Output: * Return: Length and Value of the next symbol * Attention:As in both nal_bits.c and nal_part.c all data of one partition, slice, picture was already read into a buffer, there is no need to read any data here again. \par This function could (and should) be optimized considerably \par If it is ever decided to have different VLC tables for different symbol types, then this would be the place for the implementation \par An alternate VLC table is implemented based on exponential Golomb codes. The encoder must have a matching define selected. \par GetVLCInfo was extracted because there should be only one place in the source code that has knowledge about symbol extraction, regardless of the number of different NALs. ************************************************************************* */ int GetVLCSymbol (byte buffer[],int totbitoffset,int *info, int bytecount) { register int inf; long byteoffset; // byte from start of buffer int bitoffset; // bit from start of byte int ctr_bit=0; // control bit for current bit posision int bitcounter=1; int len; int info_bit; byteoffset= totbitoffset/8; bitoffset= 7-(totbitoffset%8); ctr_bit = (buffer[byteoffset] & (0x01< bytecount) { return -1; } inf=(inf<<1); if(buffer[byteoffset] & (0x01<<(bitoffset))) inf |=1; } *info = inf; return bitcounter; // return absolute offset in bit from start of frame } /* ************************************************************************* * Function: * Input: * Output: * Return: * Attention: ************************************************************************* */ int GetVLCSymbol_refidx (byte buffer[],int totbitoffset,int *info, int bytecount) { register int inf; long byteoffset; // byte from start of buffer int bitoffset; // bit from start of byte int bitcounter=1; int len; int info_bit; byteoffset= totbitoffset/8; bitoffset= 7-(totbitoffset%8); len=1; inf=0; for(info_bit=0;(info_bit bytecount) { return -1; } if(buffer[byteoffset] & (0x01<<(bitoffset))) inf = 1; bitcounter++; bitoffset-=1; } *info = inf; return bitcounter; // return absolute offset in bit from start of frame } extern void tracebits2(const char *trace_str, int len, int info) ; /* ************************************************************************* * Function:read FLC codeword from UVLC-partition * Input: * Output: * Return: * Attention: ************************************************************************* */ int readSyntaxElement_FLC(SyntaxElement *sym) { int frame_bitoffset = currStream->frame_bitoffset; byte *buf = currStream->streamBuffer; int BitstreamLengthInBytes = currStream->bitstream_length; if ((GetBits(buf, frame_bitoffset, &(sym->inf), BitstreamLengthInBytes, sym->len)) < 0) return -1; currStream->frame_bitoffset += sym->len; // move bitstream pointer sym->value1 = sym->inf; #if TRACE tracebits2(sym->tracestring, sym->len, sym->inf); #endif return 1; } /* ************************************************************************* * Function:read Level VLC0 codeword from UVLC-partition * Input: * Output: * Return: * Attention: ************************************************************************* */ int readSyntaxElement_Level_VLC0(SyntaxElement *sym) { int frame_bitoffset = currStream->frame_bitoffset; byte *buf = currStream->streamBuffer; int BitstreamLengthInBytes = currStream->bitstream_length; int len, sign, level, code; len = 0; while (!ShowBits(buf, frame_bitoffset+len, BitstreamLengthInBytes, 1)) len++; len++; code = 1; frame_bitoffset += len; if (len < 15) { sign = (len - 1) & 1; level = (len-1) / 2 + 1; } else if (len == 15) { // escape code code = (code << 4) | ShowBits(buf, frame_bitoffset, BitstreamLengthInBytes, 4); len += 4; frame_bitoffset += 4; sign = (code & 1); level = ((code >> 1) & 0x7) + 8; } else if (len == 16) { // escape code code = (code << 12) | ShowBits(buf, frame_bitoffset, BitstreamLengthInBytes, 12); len += 12; frame_bitoffset += 12; sign = (code & 1); level = ((code >> 1) & 0x7ff) + 16; } else { printf("ERROR reading Level code\n"); exit(-1); } if (sign) level = -level; sym->inf = level; sym->len = len; #if TRACE tracebits2(sym->tracestring, sym->len, code); #endif currStream->frame_bitoffset = frame_bitoffset; return 0; } /* ************************************************************************* * Function:read Level VLC codeword from UVLC-partition * Input: * Output: * Return: * Attention: ************************************************************************* */ int readSyntaxElement_Level_VLCN(SyntaxElement *sym, int vlc) { int frame_bitoffset = currStream->frame_bitoffset; byte *buf = currStream->streamBuffer; int BitstreamLengthInBytes = currStream->bitstream_length; int levabs, sign; int len = 0; int code, sb; int numPrefix; int shift = vlc-1; int escape = (15< suffix if (vlc-1) { sb = ShowBits(buf, frame_bitoffset+len, BitstreamLengthInBytes, vlc-1); code = (code << (vlc-1) )| sb; levabs += sb; len += (vlc-1); } // read 1 bit -> sign sign = ShowBits(buf, frame_bitoffset+len, BitstreamLengthInBytes, 1); code = (code << 1)| sign; len ++; } else // escape { // read 11 bits -> levabs sb = ShowBits(buf, frame_bitoffset+len, BitstreamLengthInBytes, 11); code = (code << 11 )| sb; levabs = sb + escape; len+=11; // read 1 bit -> sign sign = ShowBits(buf, frame_bitoffset+len, BitstreamLengthInBytes, 1); code = (code << 1)| sign; len++; } sym->inf = (sign)?-levabs:levabs; sym->len = len; currStream->frame_bitoffset = frame_bitoffset+len; #if TRACE tracebits2(sym->tracestring, sym->len, code); #endif return 0; } /* ************************************************************************* * Function:Reads bits from the bitstream buffer * Input: byte buffer[] containing VLC-coded data bits int totbitoffset bit offset from start of partition int bytecount total bytes in bitstream int numbits number of bits to read * Output: * Return: * Attention: ************************************************************************* */ int GetBits (byte buffer[],int totbitoffset,int *info, int bytecount, int numbits) { register int inf; long byteoffset; // byte from start of buffer int bitoffset; // bit from start of byte int bitcounter=numbits; byteoffset= totbitoffset/8; bitoffset= 7-(totbitoffset%8); inf=0; while (numbits) { inf <<=1; inf |= (buffer[byteoffset] & (0x01< >bitoffset; numbits--; bitoffset--; if (bitoffset < 0) { byteoffset++; bitoffset += 8; if (byteoffset > bytecount) { return -1; } } } *info = inf; return bitcounter; // return absolute offset in bit from start of frame } /* ************************************************************************* * Function:Reads bits from the bitstream buffer * Input: byte buffer[] containing VLC-coded data bits int totbitoffset bit offset from start of partition int bytecount total bytes in bitstream int numbits number of bits to read * Output: * Return: * Attention: ************************************************************************* */ int ShowBits (byte buffer[],int totbitoffset,int bytecount, int numbits) { register int inf; long byteoffset; // byte from start of buffer int bitoffset; // bit from start of byte byteoffset= totbitoffset/8; bitoffset= 7-(totbitoffset%8); inf=0; while (numbits) { inf <<=1; inf |= (buffer[byteoffset] & (0x01< >bitoffset; numbits--; bitoffset--; if (bitoffset < 0) { byteoffset++; bitoffset += 8; if (byteoffset > bytecount) { return -1; } } } return inf; // return absolute offset in bit from start of frame } //////////////////////////////////////////////////////////////////////////// // Yulj 2004.07.15 // for decision of slice end. //////////////////////////////////////////////////////////////////////////// int get_uv (int LenInBits, char*tracestring) { SyntaxElement symbol, *sym=&symbol; assert (currStream->streamBuffer != NULL); sym->mapping = linfo_ue; // Mapping rule sym->len = LenInBits; SYMTRACESTRING(tracestring); GetSyntaxElement_FLC (sym); return sym->inf; } ///////////////////////////////////////////////////////////// // Yulj 2004.07.15 // for decision of slice end. ///////////////////////////////////////////////////////////// int GetSyntaxElement_FLC(SyntaxElement *sym) { int frame_bitoffset = currStream->frame_bitoffset; byte *buf = currStream->streamBuffer; int BitstreamLengthInBytes = currStream->bitstream_length; if ((GetBits(buf, frame_bitoffset, &(sym->inf), BitstreamLengthInBytes, sym->len)) < 0) return -1; sym->value1 = sym->inf; #if TRACE tracebits2(sym->tracestring, sym->len, sym->inf); #endif return 1; }