URL
https://opencores.org/ocsvn/bluespec-h264/bluespec-h264/trunk
Subversion Repositories bluespec-h264
[/] [bluespec-h264/] [trunk/] [test/] [decoder/] [ldecod/] [src/] [vlc.c] - Rev 100
Compare with Previous | Blame | View Log
/*! ************************************************************************ * \file vlc.c * * \brief * VLC support functions * * \author * Main contributors (see contributors.h for copyright, address and affiliation details) * - Inge Lille-Langøy <inge.lille-langoy@telenor.com> * - Detlev Marpe <marpe@hhi.de> * - Gabi Blaettermann <blaetter@hhi.de> ************************************************************************ */ #include "contributors.h" #include <stdlib.h> #include <math.h> #include <string.h> #include <assert.h> #include "global.h" #include "vlc.h" #include "elements.h" // A little trick to avoid those horrible #if TRACE all over the source code #if TRACE #define SYMTRACESTRING(s) strncpy(symbol.tracestring,s,TRACESTRING_SIZE) #else #define SYMTRACESTRING(s) // do nothing #endif extern void tracebits(const char *trace_str, int len, int info,int value1); int UsedBits; // for internal statistics, is adjusted by se_v, ue_v, u_1 // Note that all NA values are filled with 0 //! for the linfo_levrun_inter routine const byte NTAB1[4][8][2] = { {{1,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}}, {{1,1},{1,2},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}}, {{2,0},{1,3},{1,4},{1,5},{0,0},{0,0},{0,0},{0,0}}, {{3,0},{2,1},{2,2},{1,6},{1,7},{1,8},{1,9},{4,0}}, }; const byte LEVRUN1[16]= { 4,2,2,1,1,1,1,1,1,1,0,0,0,0,0,0, }; const byte NTAB2[4][8][2] = { {{1,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}}, {{1,1},{2,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}}, {{1,2},{3,0},{4,0},{5,0},{0,0},{0,0},{0,0},{0,0}}, {{1,3},{1,4},{2,1},{3,1},{6,0},{7,0},{8,0},{9,0}}, }; //! for the linfo_levrun__c2x2 routine const byte LEVRUN3[4] = { 2,1,0,0 }; const byte NTAB3[2][2][2] = { {{1,0},{0,0}}, {{2,0},{1,1}}, }; /*! ************************************************************************************* * \brief * ue_v, reads an ue(v) syntax element, the length in bits is stored in * the global UsedBits variable * * \param tracestring * the string for the trace file * * \param bitstream * the stream to be read from * * \return * the value of the coded syntax element * ************************************************************************************* */ int ue_v (char *tracestring, Bitstream *bitstream) { SyntaxElement symbol; assert (bitstream->streamBuffer != NULL); symbol.type = SE_HEADER; symbol.mapping = linfo_ue; // Mapping rule SYMTRACESTRING(tracestring); readSyntaxElement_VLC (&symbol, bitstream); UsedBits+=symbol.len; return symbol.value1; } /*! ************************************************************************************* * \brief * ue_v, reads an se(v) syntax element, the length in bits is stored in * the global UsedBits variable * * \param tracestring * the string for the trace file * * \param bitstream * the stream to be read from * * \return * the value of the coded syntax element * ************************************************************************************* */ int se_v (char *tracestring, Bitstream *bitstream) { SyntaxElement symbol; assert (bitstream->streamBuffer != NULL); symbol.type = SE_HEADER; symbol.mapping = linfo_se; // Mapping rule: signed integer SYMTRACESTRING(tracestring); readSyntaxElement_VLC (&symbol, bitstream); UsedBits+=symbol.len; return symbol.value1; } /*! ************************************************************************************* * \brief * ue_v, reads an u(v) syntax element, the length in bits is stored in * the global UsedBits variable * * \param LenInBits * length of the syntax element * * \param tracestring * the string for the trace file * * \param bitstream * the stream to be read from * * \return * the value of the coded syntax element * ************************************************************************************* */ int u_v (int LenInBits, char*tracestring, Bitstream *bitstream) { SyntaxElement symbol; symbol.inf = 0; assert (bitstream->streamBuffer != NULL); symbol.type = SE_HEADER; symbol.mapping = linfo_ue; // Mapping rule symbol.len = LenInBits; SYMTRACESTRING(tracestring); readSyntaxElement_FLC (&symbol, bitstream); UsedBits+=symbol.len; return symbol.inf; } /*! ************************************************************************************* * \brief * ue_v, reads an u(1) syntax element, the length in bits is stored in * the global UsedBits variable * * \param tracestring * the string for the trace file * * \param bitstream * the stream to be read from * * \return * the value of the coded syntax element * ************************************************************************************* */ Boolean u_1 (char *tracestring, Bitstream *bitstream) { return (Boolean) u_v (1, tracestring, bitstream); } /*! ************************************************************************ * \brief * mapping rule for ue(v) syntax elements * \par Input: * lenght and info * \par Output: * number in the code table ************************************************************************ */ void linfo_ue(int len, int info, int *value1, int *dummy) { assert ((len>>1)<32); *value1 = (1<<(len>>1))+info-1; } /*! ************************************************************************ * \brief * mapping rule for se(v) syntax elements * \par Input: * lenght and info * \par Output: * signed mvd ************************************************************************ */ void linfo_se(int len, int info, int *value1, int *dummy) { int n; assert ((len>>1)<32); n = (1 << (len>>1))+info-1; *value1 = (n+1)>>1; if((n & 0x01)==0) // lsb is signed bit *value1 = -*value1; } /*! ************************************************************************ * \par Input: * length and info * \par Output: * cbp (intra) ************************************************************************ */ void linfo_cbp_intra(int len,int info,int *cbp, int *dummy) { extern const byte NCBP[2][48][2]; int cbp_idx; linfo_ue(len,info,&cbp_idx,dummy); *cbp=NCBP[active_sps->chroma_format_idc?1:0][cbp_idx][0]; } /*! ************************************************************************ * \par Input: * length and info * \par Output: * cbp (inter) ************************************************************************ */ void linfo_cbp_inter(int len,int info,int *cbp, int *dummy) { extern const byte NCBP[2][48][2]; int cbp_idx; linfo_ue(len,info,&cbp_idx,dummy); *cbp=NCBP[active_sps->chroma_format_idc?1:0][cbp_idx][1]; } /*! ************************************************************************ * \par Input: * length and info * \par Output: * level, run ************************************************************************ */ void linfo_levrun_inter(int len, int info, int *level, int *irun) { int l2; int inf; assert (((len>>1)-5)<32); if (len<=9) { l2=imax(0,(len>>1)-1); inf=info>>1; *level=NTAB1[l2][inf][0]; *irun=NTAB1[l2][inf][1]; if ((info&0x01)==1) *level=-*level; // make sign } else // if len > 9, skip using the array { *irun=(info&0x1e)>>1; *level = LEVRUN1[*irun] + (info>>5) + ( 1<< ((len>>1) - 5)); if ((info&0x01)==1) *level=-*level; } if (len == 1) // EOB *level = 0; } /*! ************************************************************************ * \par Input: * length and info * \par Output: * level, run ************************************************************************ */ void linfo_levrun_c2x2(int len, int info, int *level, int *irun) { int l2; int inf; if (len<=5) { l2=imax(0,(len>>1)-1); inf=info>>1; *level=NTAB3[l2][inf][0]; *irun=NTAB3[l2][inf][1]; if ((info&0x01)==1) *level=-*level; // make sign } else // if len > 5, skip using the array { *irun=(info&0x06)>>1; *level = LEVRUN3[*irun] + (info>>3) + (1 << ((len>>1) - 3)); if ((info&0x01)==1) *level=-*level; } if (len == 1) // EOB *level = 0; } /*! ************************************************************************ * \brief * read next UVLC codeword from UVLC-partition and * map it to the corresponding syntax element ************************************************************************ */ int readSyntaxElement_VLC(SyntaxElement *sym, Bitstream *currStream) { 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; } /*! ************************************************************************ * \brief * read next UVLC codeword from UVLC-partition and * map it to the corresponding syntax element ************************************************************************ */ int readSyntaxElement_UVLC(SyntaxElement *sym, struct img_par *img, struct datapartition *dP) { Bitstream *currStream = dP->bitstream; return (readSyntaxElement_VLC(sym, currStream)); } /*! ************************************************************************ * \brief * read next VLC codeword for 4x4 Intra Prediction Mode and * map it to the corresponding Intra Prediction Direction ************************************************************************ */ int readSyntaxElement_Intra4x4PredictionMode(SyntaxElement *sym, struct img_par *img,struct datapartition *dP) { Bitstream *currStream = dP->bitstream; 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; } 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>>3; bitoffset = 7-(totbitoffset&0x07); ctr_bit = (buffer[byteoffset] & (0x01<<bitoffset)); // set up control bit len = 1; //First bit if (ctr_bit) { *info = 0; return bitcounter; } else len=4; // make infoword inf=0; // shortest possible code is 1, then info is always 0 for(info_bit=0;(info_bit<(len-1)); info_bit++) { bitcounter++; bitoffset-=1; if (bitoffset<0) { // finished with current byte ? bitoffset=bitoffset+8; byteoffset++; } if (byteoffset > 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 } /*! ************************************************************************ * \brief * test if bit buffer contains only stop bit * * \param buffer * buffer containing VLC-coded data bits * \param totbitoffset * bit offset from start of partition * \param bytecount * buffer length * \return * true if more bits available ************************************************************************ */ int more_rbsp_data (byte buffer[],int totbitoffset,int bytecount) { 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 cnt=0; byteoffset= totbitoffset>>3; bitoffset= 7-(totbitoffset&0x07); assert (byteoffset<bytecount); // there is more until we're in the last byte if (byteoffset<(bytecount-1)) return TRUE; // read one bit ctr_bit = (buffer[byteoffset] & (0x01<<bitoffset)); // a stop bit has to be one if (ctr_bit==0) return TRUE; bitoffset--; while (bitoffset>=0) { ctr_bit = (buffer[byteoffset] & (0x01<<bitoffset)); // set up control bit if (ctr_bit>0) cnt++; bitoffset--; } return (0!=cnt); } /*! ************************************************************************ * \brief * Check if there are symbols for the next MB ************************************************************************ */ int uvlc_startcode_follows(struct img_par *img, int dummy) { int dp_Nr = assignSE2partition[img->currentSlice->dp_mode][SE_MBTYPE]; DataPartition *dP = &(img->currentSlice->partArr[dp_Nr]); Bitstream *currStream = dP->bitstream; byte *buf = currStream->streamBuffer; //KS: new function test for End of Buffer return (!(more_rbsp_data(buf, currStream->frame_bitoffset,currStream->bitstream_length))); } /*! ************************************************************************ * \brief * read one exp-golomb VLC symbol * * \param buffer * containing VLC-coded data bits * \param totbitoffset * bit offset from start of partition * \param info * returns the value of the symbol * \param bytecount * buffer length * \return * bits read ************************************************************************ */ 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>>3; bitoffset= 7-(totbitoffset&0x07); ctr_bit = (buffer[byteoffset] & (0x01<<bitoffset)); // set up control bit len=1; while (ctr_bit==0) { // find leading 1 bit len++; bitoffset-=1; bitcounter++; if (bitoffset<0) { // finish with current byte ? bitoffset=bitoffset+8; byteoffset++; } ctr_bit=buffer[byteoffset] & (0x01<<(bitoffset)); } // make infoword inf=0; // shortest possible code is 1, then info is always 0 for(info_bit=0;(info_bit<(len-1)); info_bit++) { bitcounter++; bitoffset-=1; if (bitoffset<0) { // finished with current byte ? bitoffset=bitoffset+8; byteoffset++; } if (byteoffset > 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 } extern void tracebits2(const char *trace_str, int len, int info) ; /*! ************************************************************************ * \brief * code from bitstream (2d tables) ************************************************************************ */ int code_from_bitstream_2d(SyntaxElement *sym, DataPartition *dP, const int *lentab, const int *codtab, int tabwidth, int tabheight, int *code) { Bitstream *currStream = dP->bitstream; int frame_bitoffset = currStream->frame_bitoffset; byte *buf = currStream->streamBuffer; int BitstreamLengthInBytes = currStream->bitstream_length; int i,j; int len, cod; // this VLC decoding method is not optimized for speed for (j = 0; j < tabheight; j++) { for (i = 0; i < tabwidth; i++) { len = lentab[i]; if (!len) continue; cod = codtab[i]; if ((ShowBits(buf, frame_bitoffset, BitstreamLengthInBytes, len) == cod)) { sym->value1 = i; sym->value2 = j; currStream->frame_bitoffset += len; // move bitstream pointer sym->len = len; goto found_code; } } lentab += tabwidth; codtab += tabwidth; } return -1; // failed to find code found_code: *code = cod; return 0; } /*! ************************************************************************ * \brief * read FLC codeword from UVLC-partition ************************************************************************ */ int readSyntaxElement_FLC(SyntaxElement *sym, Bitstream *currStream) { 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; } /*! ************************************************************************ * \brief * read NumCoeff/TrailingOnes codeword from UVLC-partition ************************************************************************ */ int readSyntaxElement_NumCoeffTrailingOnes(SyntaxElement *sym, DataPartition *dP, char *type) { Bitstream *currStream = dP->bitstream; int frame_bitoffset = currStream->frame_bitoffset; byte *buf = currStream->streamBuffer; int BitstreamLengthInBytes = currStream->bitstream_length; int vlcnum, retval; int code; static const int lentab[3][4][17] = { { // 0702 { 1, 6, 8, 9,10,11,13,13,13,14,14,15,15,16,16,16,16}, { 0, 2, 6, 8, 9,10,11,13,13,14,14,15,15,15,16,16,16}, { 0, 0, 3, 7, 8, 9,10,11,13,13,14,14,15,15,16,16,16}, { 0, 0, 0, 5, 6, 7, 8, 9,10,11,13,14,14,15,15,16,16}, }, { { 2, 6, 6, 7, 8, 8, 9,11,11,12,12,12,13,13,13,14,14}, { 0, 2, 5, 6, 6, 7, 8, 9,11,11,12,12,13,13,14,14,14}, { 0, 0, 3, 6, 6, 7, 8, 9,11,11,12,12,13,13,13,14,14}, { 0, 0, 0, 4, 4, 5, 6, 6, 7, 9,11,11,12,13,13,13,14}, }, { { 4, 6, 6, 6, 7, 7, 7, 7, 8, 8, 9, 9, 9,10,10,10,10}, { 0, 4, 5, 5, 5, 5, 6, 6, 7, 8, 8, 9, 9, 9,10,10,10}, { 0, 0, 4, 5, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9,10,10,10}, { 0, 0, 0, 4, 4, 4, 4, 4, 5, 6, 7, 8, 8, 9,10,10,10}, }, }; static const int codtab[3][4][17] = { { { 1, 5, 7, 7, 7, 7,15,11, 8,15,11,15,11,15,11, 7,4}, { 0, 1, 4, 6, 6, 6, 6,14,10,14,10,14,10, 1,14,10,6}, { 0, 0, 1, 5, 5, 5, 5, 5,13, 9,13, 9,13, 9,13, 9,5}, { 0, 0, 0, 3, 3, 4, 4, 4, 4, 4,12,12, 8,12, 8,12,8}, }, { { 3,11, 7, 7, 7, 4, 7,15,11,15,11, 8,15,11, 7, 9,7}, { 0, 2, 7,10, 6, 6, 6, 6,14,10,14,10,14,10,11, 8,6}, { 0, 0, 3, 9, 5, 5, 5, 5,13, 9,13, 9,13, 9, 6,10,5}, { 0, 0, 0, 5, 4, 6, 8, 4, 4, 4,12, 8,12,12, 8, 1,4}, }, { {15,15,11, 8,15,11, 9, 8,15,11,15,11, 8,13, 9, 5,1}, { 0,14,15,12,10, 8,14,10,14,14,10,14,10, 7,12, 8,4}, { 0, 0,13,14,11, 9,13, 9,13,10,13, 9,13, 9,11, 7,3}, { 0, 0, 0,12,11,10, 9, 8,13,12,12,12, 8,12,10, 6,2}, }, }; vlcnum = sym->value1; // vlcnum is the index of Table used to code coeff_token // vlcnum==3 means (8<=nC) which uses 6bit FLC if (vlcnum == 3) { // read 6 bit FLC code = ShowBits(buf, frame_bitoffset, BitstreamLengthInBytes, 6); currStream->frame_bitoffset += 6; sym->value2 = code & 3; sym->value1 = (code >> 2); if (!sym->value1 && sym->value2 == 3) { // #c = 0, #t1 = 3 => #c = 0 sym->value2 = 0; } else sym->value1++; sym->len = 6; retval = 0; } else { const int *lt = &lentab[vlcnum][0][0]; const int *ct = &codtab[vlcnum][0][0]; retval = code_from_bitstream_2d(sym, dP, lt, ct, 17, 4, &code); } if (retval) { printf("ERROR: failed to find NumCoeff/TrailingOnes\n"); exit(-1); } #if TRACE snprintf(sym->tracestring, TRACESTRING_SIZE, "%s # c & tr.1s vlc=%d #c=%d #t1=%d", type, vlcnum, sym->value1, sym->value2); tracebits2(sym->tracestring, sym->len, code); #endif return retval; } /*! ************************************************************************ * \brief * read NumCoeff/TrailingOnes codeword from UVLC-partition ChromaDC ************************************************************************ */ int readSyntaxElement_NumCoeffTrailingOnesChromaDC(SyntaxElement *sym, DataPartition *dP) { int retval; int code; static const int lentab[3][4][17] = { //YUV420 {{ 2, 6, 6, 6, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, { 0, 1, 6, 7, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, { 0, 0, 3, 7, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, { 0, 0, 0, 6, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, //YUV422 {{ 1, 7, 7, 9, 9,10,11,12,13, 0, 0, 0, 0, 0, 0, 0, 0}, { 0, 2, 7, 7, 9,10,11,12,12, 0, 0, 0, 0, 0, 0, 0, 0}, { 0, 0, 3, 7, 7, 9,10,11,12, 0, 0, 0, 0, 0, 0, 0, 0}, { 0, 0, 0, 5, 6, 7, 7,10,11, 0, 0, 0, 0, 0, 0, 0, 0}}, //YUV444 {{ 1, 6, 8, 9,10,11,13,13,13,14,14,15,15,16,16,16,16}, { 0, 2, 6, 8, 9,10,11,13,13,14,14,15,15,15,16,16,16}, { 0, 0, 3, 7, 8, 9,10,11,13,13,14,14,15,15,16,16,16}, { 0, 0, 0, 5, 6, 7, 8, 9,10,11,13,14,14,15,15,16,16}} }; static const int codtab[3][4][17] = { //YUV420 {{ 1, 7, 4, 3, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, { 0, 1, 6, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, { 0, 0, 1, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, { 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, //YUV422 {{ 1,15,14, 7, 6, 7, 7, 7, 7, 0, 0, 0, 0, 0, 0, 0, 0}, { 0, 1,13,12, 5, 6, 6, 6, 5, 0, 0, 0, 0, 0, 0, 0, 0}, { 0, 0, 1,11,10, 4, 5, 5, 4, 0, 0, 0, 0, 0, 0, 0, 0}, { 0, 0, 0, 1, 1, 9, 8, 4, 4, 0, 0, 0, 0, 0, 0, 0, 0}}, //YUV444 {{ 1, 5, 7, 7, 7, 7,15,11, 8,15,11,15,11,15,11, 7, 4}, { 0, 1, 4, 6, 6, 6, 6,14,10,14,10,14,10, 1,14,10, 6}, { 0, 0, 1, 5, 5, 5, 5, 5,13, 9,13, 9,13, 9,13, 9, 5}, { 0, 0, 0, 3, 3, 4, 4, 4, 4, 4,12,12, 8,12, 8,12, 8}} }; int yuv = active_sps->chroma_format_idc - 1; const int *lt = &lentab[yuv][0][0]; const int *ct = &codtab[yuv][0][0]; retval = code_from_bitstream_2d(sym, dP, lt, ct, 17, 4, &code); if (retval) { printf("ERROR: failed to find NumCoeff/TrailingOnes ChromaDC\n"); exit(-1); } #if TRACE snprintf(sym->tracestring, TRACESTRING_SIZE, "ChrDC # c & tr.1s #c=%d #t1=%d", sym->value1, sym->value2); tracebits2(sym->tracestring, sym->len, code); #endif return retval; } /*! ************************************************************************ * \brief * read Level VLC0 codeword from UVLC-partition ************************************************************************ */ int readSyntaxElement_Level_VLC0(SyntaxElement *sym, struct datapartition *dP) { Bitstream *currStream = dP->bitstream; int frame_bitoffset = currStream->frame_bitoffset; byte *buf = currStream->streamBuffer; int BitstreamLengthInBytes = currStream->bitstream_length; int len, sign=0, level=0, code; int offset, addbit; 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 addbit=len-16; code = ShowBits(buf, frame_bitoffset, BitstreamLengthInBytes, (len-4)); len = (len-4); frame_bitoffset += len; sign = (code & 1); offset=(2048<<addbit)+16-2048; level = (code >> 1) + offset; code |= (1 << (len)); // for display purpose only len += addbit + 16; } 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; } /*! ************************************************************************ * \brief * read Level VLC codeword from UVLC-partition ************************************************************************ */ int readSyntaxElement_Level_VLCN(SyntaxElement *sym, int vlc, struct datapartition *dP) { Bitstream *currStream = dP->bitstream; 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<<shift)+1; int addbit, offset; // read pre zeros numPrefix = 0; while (!ShowBits(buf, frame_bitoffset+numPrefix, BitstreamLengthInBytes, 1)) numPrefix++; len = numPrefix+1; code = 1; if (numPrefix < 15) { levabs = (numPrefix<<shift) + 1; // read (vlc-1) bits -> 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 { addbit = numPrefix - 15; sb = ShowBits(buf, frame_bitoffset+len, BitstreamLengthInBytes, (11+addbit)); code = (code << (11+addbit) )| sb; len += (11+addbit); offset = (2048<<addbit)+escape-2048; levabs = sb + offset; // 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; } /*! ************************************************************************ * \brief * read Total Zeros codeword from UVLC-partition ************************************************************************ */ int readSyntaxElement_TotalZeros(SyntaxElement *sym, DataPartition *dP) { int retval; int code; static const int lentab[TOTRUN_NUM][16] = { { 1,3,3,4,4,5,5,6,6,7,7,8,8,9,9,9}, { 3,3,3,3,3,4,4,4,4,5,5,6,6,6,6}, { 4,3,3,3,4,4,3,3,4,5,5,6,5,6}, { 5,3,4,4,3,3,3,4,3,4,5,5,5}, { 4,4,4,3,3,3,3,3,4,5,4,5}, { 6,5,3,3,3,3,3,3,4,3,6}, { 6,5,3,3,3,2,3,4,3,6}, { 6,4,5,3,2,2,3,3,6}, { 6,6,4,2,2,3,2,5}, { 5,5,3,2,2,2,4}, { 4,4,3,3,1,3}, { 4,4,2,1,3}, { 3,3,1,2}, { 2,2,1}, { 1,1}, }; static const int codtab[TOTRUN_NUM][16] = { {1,3,2,3,2,3,2,3,2,3,2,3,2,3,2,1}, {7,6,5,4,3,5,4,3,2,3,2,3,2,1,0}, {5,7,6,5,4,3,4,3,2,3,2,1,1,0}, {3,7,5,4,6,5,4,3,3,2,2,1,0}, {5,4,3,7,6,5,4,3,2,1,1,0}, {1,1,7,6,5,4,3,2,1,1,0}, {1,1,5,4,3,3,2,1,1,0}, {1,1,1,3,3,2,2,1,0}, {1,0,1,3,2,1,1,1,}, {1,0,1,3,2,1,1,}, {0,1,1,2,1,3}, {0,1,1,1,1}, {0,1,1,1}, {0,1,1}, {0,1}, }; int vlcnum = sym->value1; const int *lt = &lentab[vlcnum][0]; const int *ct = &codtab[vlcnum][0]; retval = code_from_bitstream_2d(sym, dP, lt, ct, 16, 1, &code); if (retval) { printf("ERROR: failed to find Total Zeros\n"); exit(-1); } #if TRACE tracebits2(sym->tracestring, sym->len, code); #endif return retval; } /*! ************************************************************************ * \brief * read Total Zeros Chroma DC codeword from UVLC-partition ************************************************************************ */ int readSyntaxElement_TotalZerosChromaDC(SyntaxElement *sym, DataPartition *dP) { int retval; int code; static const int lentab[3][TOTRUN_NUM][16] = { //YUV420 {{ 1,2,3,3}, { 1,2,2}, { 1,1}}, //YUV422 {{ 1,3,3,4,4,4,5,5}, { 3,2,3,3,3,3,3}, { 3,3,2,2,3,3}, { 3,2,2,2,3}, { 2,2,2,2}, { 2,2,1}, { 1,1}}, //YUV444 {{ 1,3,3,4,4,5,5,6,6,7,7,8,8,9,9,9}, { 3,3,3,3,3,4,4,4,4,5,5,6,6,6,6}, { 4,3,3,3,4,4,3,3,4,5,5,6,5,6}, { 5,3,4,4,3,3,3,4,3,4,5,5,5}, { 4,4,4,3,3,3,3,3,4,5,4,5}, { 6,5,3,3,3,3,3,3,4,3,6}, { 6,5,3,3,3,2,3,4,3,6}, { 6,4,5,3,2,2,3,3,6}, { 6,6,4,2,2,3,2,5}, { 5,5,3,2,2,2,4}, { 4,4,3,3,1,3}, { 4,4,2,1,3}, { 3,3,1,2}, { 2,2,1}, { 1,1}} }; static const int codtab[3][TOTRUN_NUM][16] = { //YUV420 {{ 1,1,1,0}, { 1,1,0}, { 1,0}}, //YUV422 {{ 1,2,3,2,3,1,1,0}, { 0,1,1,4,5,6,7}, { 0,1,1,2,6,7}, { 6,0,1,2,7}, { 0,1,2,3}, { 0,1,1}, { 0,1}}, //YUV444 {{1,3,2,3,2,3,2,3,2,3,2,3,2,3,2,1}, {7,6,5,4,3,5,4,3,2,3,2,3,2,1,0}, {5,7,6,5,4,3,4,3,2,3,2,1,1,0}, {3,7,5,4,6,5,4,3,3,2,2,1,0}, {5,4,3,7,6,5,4,3,2,1,1,0}, {1,1,7,6,5,4,3,2,1,1,0}, {1,1,5,4,3,3,2,1,1,0}, {1,1,1,3,3,2,2,1,0}, {1,0,1,3,2,1,1,1,}, {1,0,1,3,2,1,1,}, {0,1,1,2,1,3}, {0,1,1,1,1}, {0,1,1,1}, {0,1,1}, {0,1}} }; int yuv = active_sps->chroma_format_idc - 1; int vlcnum = sym->value1; const int *lt = &lentab[yuv][vlcnum][0]; const int *ct = &codtab[yuv][vlcnum][0]; retval = code_from_bitstream_2d(sym, dP, lt, ct, 16, 1, &code); if (retval) { printf("ERROR: failed to find Total Zeros\n"); exit(-1); } #if TRACE tracebits2(sym->tracestring, sym->len, code); #endif return retval; } /*! ************************************************************************ * \brief * read Run codeword from UVLC-partition ************************************************************************ */ int readSyntaxElement_Run(SyntaxElement *sym, DataPartition *dP) { int retval; int code; static const int lentab[TOTRUN_NUM][16] = { {1,1}, {1,2,2}, {2,2,2,2}, {2,2,2,3,3}, {2,2,3,3,3,3}, {2,3,3,3,3,3,3}, {3,3,3,3,3,3,3,4,5,6,7,8,9,10,11}, }; static const int codtab[TOTRUN_NUM][16] = { {1,0}, {1,1,0}, {3,2,1,0}, {3,2,1,1,0}, {3,2,3,2,1,0}, {3,0,1,3,2,5,4}, {7,6,5,4,3,2,1,1,1,1,1,1,1,1,1}, }; int vlcnum = sym->value1; const int *lt = &lentab[vlcnum][0]; const int *ct = &codtab[vlcnum][0]; retval = code_from_bitstream_2d(sym, dP, lt, ct, 16, 1, &code); if (retval) { printf("ERROR: failed to find Run\n"); exit(-1); } #if TRACE tracebits2(sym->tracestring, sym->len, code); #endif return retval; } /*! ************************************************************************ * \brief * Reads bits from the bitstream buffer * * \param buffer * containing VLC-coded data bits * \param totbitoffset * bit offset from start of partition * \param info * returns value of the read bits * \param bytecount * total bytes in bitstream * \param numbits * number of bits to read * ************************************************************************ */ 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>>3; bitoffset= 7-(totbitoffset&0x07); inf=0; while (numbits) { inf <<=1; inf |= (buffer[byteoffset] & (0x01<<bitoffset))>>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 } /*! ************************************************************************ * \brief * Reads bits from the bitstream buffer * * \param buffer * buffer containing VLC-coded data bits * \param totbitoffset * bit offset from start of partition * \param bytecount * total bytes in bitstream * \param numbits * number of bits to read * ************************************************************************ */ int ShowBits (byte buffer[],int totbitoffset,int bytecount, int numbits) { register int inf; long byteoffset = totbitoffset>>3; // byte from start of buffer int bitoffset = 7-(totbitoffset&0x07); // bit from start of byte inf=0; while (numbits) { inf <<=1; inf |= (buffer[byteoffset] & (0x01<<bitoffset))>>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 } /*! ************************************************************************ * \brief * peek at the next 2 UVLC codeword from UVLC-partition to determine * if a skipped MB is field/frame ************************************************************************ */ int peekSyntaxElement_UVLC(SyntaxElement *sym, struct img_par *img, struct datapartition *dP) { Bitstream *currStream = dP->bitstream; 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; 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; }