| |
| /*! |
| *************************************************************************** |
| * \file vlc.c |
| * |
| * \brief |
| * (CA)VLC coding functions |
| * |
| * \author |
| * Main contributors (see contributors.h for copyright, address and affiliation details) |
| * - Inge Lille-Langoy <inge.lille-langoy@telenor.com> |
| * - Detlev Marpe <marpe@hhi.de> |
| * - Stephan Wenger <stewe@cs.tu-berlin.de> |
| *************************************************************************** |
| */ |
| |
| #include "contributors.h" |
| |
| #include <stdlib.h> |
| #include <math.h> |
| #include <string.h> |
| #include <assert.h> |
| |
| #include "global.h" |
| |
| #include "vlc.h" |
| |
| #if TRACE |
| #define SYMTRACESTRING(s) strncpy(sym.tracestring,s,TRACESTRING_SIZE) |
| #else |
| #define SYMTRACESTRING(s) // do nothing |
| #endif |
| |
| //! gives codeword number from CBP value, both for intra and inter |
| static const unsigned char NCBP[2][48][2]= |
| { |
| { // 0 1 2 3 4 5 6 7 8 9 10 11 |
| { 1, 0},{10, 1},{11, 2},{ 6, 5},{12, 3},{ 7, 6},{14,14},{ 2,10},{13, 4},{15,15},{ 8, 7},{ 3,11}, |
| { 9, 8},{ 4,12},{ 5,13},{ 0, 9},{ 0, 0},{ 0, 0},{ 0, 0},{ 0, 0},{ 0, 0},{ 0, 0},{ 0, 0},{ 0, 0}, |
| { 0, 0},{ 0, 0},{ 0, 0},{ 0, 0},{ 0, 0},{ 0, 0},{ 0, 0},{ 0, 0},{ 0, 0},{ 0, 0},{ 0, 0},{ 0, 0}, |
| { 0, 0},{ 0, 0},{ 0, 0},{ 0, 0},{ 0, 0},{ 0, 0},{ 0, 0},{ 0, 0},{ 0, 0},{ 0, 0},{ 0, 0},{ 0, 0} |
| }, |
| { |
| { 3, 0},{29, 2},{30, 3},{17, 7},{31, 4},{18, 8},{37,17},{ 8,13},{32, 5},{38,18},{19, 9},{ 9,14}, |
| {20,10},{10,15},{11,16},{ 2,11},{16, 1},{33,32},{34,33},{21,36},{35,34},{22,37},{39,44},{ 4,40}, |
| {36,35},{40,45},{23,38},{ 5,41},{24,39},{ 6,42},{ 7,43},{ 1,19},{41, 6},{42,24},{43,25},{25,20}, |
| {44,26},{26,21},{46,46},{12,28},{45,27},{47,47},{27,22},{13,29},{28,23},{14,30},{15,31},{ 0,12} |
| } |
| }; |
| |
| |
| /*! |
| ************************************************************************************* |
| * \brief |
| * ue_v, writes an ue(v) syntax element, returns the length in bits |
| * |
| * \param tracestring |
| * the string for the trace file |
| * \param value |
| * the value to be coded |
| * \param bitstream |
| * the target bitstream the value should be coded into |
| * |
| * \return |
| * Number of bits used by the coded syntax element |
| * |
| * \ note |
| * This function writes always the bit buffer for the progressive scan flag, and |
| * should not be used (or should be modified appropriately) for the interlace crap |
| * When used in the context of the Parameter Sets, this is obviously not a |
| * problem. |
| * |
| ************************************************************************************* |
| */ |
| int ue_v (char *tracestring, int value, Bitstream *bitstream) |
| { |
| SyntaxElement symbol, *sym=&symbol; |
| sym->value1 = value; |
| sym->value2 = 0; |
| |
| assert (bitstream->streamBuffer != NULL); |
| |
| ue_linfo(sym->value1,sym->value2,&(sym->len),&(sym->inf)); |
| symbol2uvlc(sym); |
| |
| writeUVLC2buffer (sym, bitstream); |
| |
| #if TRACE |
| strncpy(sym->tracestring,tracestring,TRACESTRING_SIZE); |
| trace2out (sym); |
| #endif |
| |
| return (sym->len); |
| } |
| |
| |
| /*! |
| ************************************************************************************* |
| * \brief |
| * se_v, writes an se(v) syntax element, returns the length in bits |
| * |
| * \param tracestring |
| * the string for the trace file |
| * \param value |
| * the value to be coded |
| * \param bitstream |
| * the target bitstream the value should be coded into |
| * |
| * \return |
| * Number of bits used by the coded syntax element |
| * |
| * \ note |
| * This function writes always the bit buffer for the progressive scan flag, and |
| * should not be used (or should be modified appropriately) for the interlace crap |
| * When used in the context of the Parameter Sets, this is obviously not a |
| * problem. |
| * |
| ************************************************************************************* |
| */ |
| int se_v (char *tracestring, int value, Bitstream *bitstream) |
| { |
| SyntaxElement symbol, *sym=&symbol; |
| sym->value1 = value; |
| sym->value2 = 0; |
| |
| assert (bitstream->streamBuffer != NULL); |
| |
| se_linfo(sym->value1,sym->value2,&(sym->len),&(sym->inf)); |
| symbol2uvlc(sym); |
| |
| writeUVLC2buffer (sym, bitstream); |
| |
| #if TRACE |
| strncpy(sym->tracestring,tracestring,TRACESTRING_SIZE); |
| trace2out (sym); |
| #endif |
| |
| return (sym->len); |
| } |
| |
| |
| /*! |
| ************************************************************************************* |
| * \brief |
| * u_1, writes a flag (u(1) syntax element, returns the length in bits, |
| * always 1 |
| * |
| * \param tracestring |
| * the string for the trace file |
| * \param value |
| * the value to be coded |
| * \param bitstream |
| * the target bitstream the value should be coded into |
| * |
| * \return |
| * Number of bits used by the coded syntax element (always 1) |
| * |
| * \ note |
| * This function writes always the bit buffer for the progressive scan flag, and |
| * should not be used (or should be modified appropriately) for the interlace crap |
| * When used in the context of the Parameter Sets, this is obviously not a |
| * problem. |
| * |
| ************************************************************************************* |
| */ |
| Boolean u_1 (char *tracestring, int value, Bitstream *bitstream) |
| { |
| SyntaxElement symbol, *sym=&symbol; |
| |
| sym->bitpattern = value; |
| sym->len = 1; |
| sym->value1 = value; |
| |
| assert (bitstream->streamBuffer != NULL); |
| |
| writeUVLC2buffer(sym, bitstream); |
| |
| #if TRACE |
| strncpy(sym->tracestring,tracestring,TRACESTRING_SIZE); |
| trace2out (sym); |
| #endif |
| |
| return ((Boolean) sym->len); |
| } |
| |
| |
| /*! |
| ************************************************************************************* |
| * \brief |
| * u_v, writes a n bit fixed length syntax element, returns the length in bits, |
| * |
| * \param n |
| * length in bits |
| * \param tracestring |
| * the string for the trace file |
| * \param value |
| * the value to be coded |
| * \param bitstream |
| * the target bitstream the value should be coded into |
| * |
| * \return |
| * Number of bits used by the coded syntax element |
| * |
| * \ note |
| * This function writes always the bit buffer for the progressive scan flag, and |
| * should not be used (or should be modified appropriately) for the interlace crap |
| * When used in the context of the Parameter Sets, this is obviously not a |
| * problem. |
| * |
| ************************************************************************************* |
| */ |
| |
| int u_v (int n, char *tracestring, int value, Bitstream *bitstream) |
| { |
| SyntaxElement symbol, *sym=&symbol; |
| |
| sym->bitpattern = value; |
| sym->len = n; |
| sym->value1 = value; |
| |
| assert (bitstream->streamBuffer != NULL); |
| |
| writeUVLC2buffer(sym, bitstream); |
| |
| #if TRACE |
| strncpy(sym->tracestring,tracestring,TRACESTRING_SIZE); |
| trace2out (sym); |
| #endif |
| |
| return (sym->len); |
| } |
| |
| |
| /*! |
| ************************************************************************ |
| * \brief |
| * mapping for ue(v) syntax elements |
| * \param ue |
| * value to be mapped |
| * \param dummy |
| * dummy parameter |
| * \param info |
| * returns mapped value |
| * \param len |
| * returns mapped value length |
| ************************************************************************ |
| */ |
| void ue_linfo(int ue, int dummy, int *len,int *info) |
| { |
| int i,nn; |
| |
| nn=(ue+1)/2; |
| |
| for (i=0; i < 16 && nn != 0; i++) |
| { |
| nn /= 2; |
| } |
| *len= 2*i + 1; |
| *info=ue+1-(1<<i); |
| } |
| |
| |
| /*! |
| ************************************************************************ |
| * \brief |
| * mapping for se(v) syntax elements |
| * \param se |
| * value to be mapped |
| * \param dummy |
| * dummy parameter |
| * \param len |
| * returns mapped value length |
| * \param info |
| * returns mapped value |
| ************************************************************************ |
| */ |
| void se_linfo(int se, int dummy, int *len,int *info) |
| { |
| |
| int i,n,sign,nn; |
| |
| sign=0; |
| |
| if (se <= 0) |
| { |
| sign=1; |
| } |
| n=iabs(se) << 1; |
| |
| // n+1 is the number in the code table. Based on this we find length and info |
| |
| nn=n/2; |
| for (i=0; i < 16 && nn != 0; i++) |
| { |
| nn /= 2; |
| } |
| *len=i*2 + 1; |
| *info=n - (1 << i) + sign; |
| } |
| |
| |
| /*! |
| ************************************************************************ |
| * \par Input: |
| * Number in the code table |
| * \par Output: |
| * length and info |
| ************************************************************************ |
| */ |
| void cbp_linfo_intra(int cbp, int dummy, int *len,int *info) |
| { |
| ue_linfo(NCBP[img->yuv_format?1:0][cbp][0], dummy, len, info); |
| } |
| |
| |
| /*! |
| ************************************************************************ |
| * \par Input: |
| * Number in the code table |
| * \par Output: |
| * length and info |
| ************************************************************************ |
| */ |
| void cbp_linfo_inter(int cbp, int dummy, int *len,int *info) |
| { |
| ue_linfo(NCBP[img->yuv_format?1:0][cbp][1], dummy, len, info); |
| } |
| |
| |
| /*! |
| ************************************************************************ |
| * \brief |
| * 2x2 transform of chroma DC |
| * \par Input: |
| * level and run for coefficients |
| * \par Output: |
| * length and info |
| * \note |
| * see ITU document for bit assignment |
| ************************************************************************ |
| */ |
| void levrun_linfo_c2x2(int level,int run,int *len,int *info) |
| { |
| const int NTAB[2][2]= |
| { |
| {1,5}, |
| {3,0} |
| }; |
| const int LEVRUN[4]= |
| { |
| 2,1,0,0 |
| }; |
| |
| int levabs,i,n,sign,nn; |
| |
| if (level == 0) // check if the coefficient sign EOB (level=0) |
| { |
| *len=1; |
| return; |
| } |
| sign=0; |
| if (level <= 0) |
| { |
| sign=1; |
| } |
| levabs=iabs(level); |
| if (levabs <= LEVRUN[run]) |
| { |
| n=NTAB[levabs-1][run]+1; |
| } |
| else |
| { |
| n=(levabs-LEVRUN[run])*8 + run*2; |
| } |
| |
| nn=n/2; |
| |
| for (i=0; i < 16 && nn != 0; i++) |
| { |
| nn /= 2; |
| } |
| *len= 2*i + 1; |
| *info=n-(1 << i)+sign; |
| } |
| |
| |
| /*! |
| ************************************************************************ |
| * \brief |
| * Single scan coefficients |
| * \par Input: |
| * level and run for coefficients |
| * \par Output: |
| * length and info |
| * \note |
| * see ITU document for bit assignment |
| ************************************************************************ |
| */ |
| void levrun_linfo_inter(int level,int run,int *len,int *info) |
| { |
| const byte LEVRUN[16]= |
| { |
| 4,2,2,1,1,1,1,1,1,1,0,0,0,0,0,0 |
| }; |
| const byte NTAB[4][10]= |
| { |
| { 1, 3, 5, 9,11,13,21,23,25,27}, |
| { 7,17,19, 0, 0, 0, 0, 0, 0, 0}, |
| {15, 0, 0, 0, 0, 0, 0, 0, 0, 0}, |
| {29, 0, 0, 0, 0, 0, 0, 0, 0, 0}, |
| }; |
| |
| int levabs,i,n,sign,nn; |
| |
| if (level == 0) // check for EOB |
| { |
| *len=1; |
| return; |
| } |
| |
| if (level <= 0) |
| sign=1; |
| else |
| sign=0; |
| |
| levabs=iabs(level); |
| if (levabs <= LEVRUN[run]) |
| { |
| n=NTAB[levabs-1][run]+1; |
| } |
| else |
| { |
| n=(levabs-LEVRUN[run])*32 + run*2; |
| } |
| |
| nn=n/2; |
| |
| for (i=0; i < 16 && nn != 0; i++) |
| { |
| nn /= 2; |
| } |
| *len= 2*i + 1; |
| *info=n-(1 << i)+sign; |
| |
| } |
| |
| |
| /*! |
| ************************************************************************ |
| * \brief |
| * Makes code word and passes it back |
| * A code word has the following format: 0 0 0 ... 1 Xn ...X2 X1 X0. |
| * |
| * \par Input: |
| * Info : Xn..X2 X1 X0 \n |
| * Length : Total number of bits in the codeword |
| ************************************************************************ |
| */ |
| // NOTE this function is called with sym->inf > (1<<(sym->len/2)). The upper bits of inf are junk |
| int symbol2uvlc(SyntaxElement *sym) |
| { |
| int suffix_len=sym->len/2; |
| assert (suffix_len<32); |
| sym->bitpattern = (1<<suffix_len)|(sym->inf&((1<<suffix_len)-1)); |
| return 0; |
| } |
| |
| /*! |
| ************************************************************************ |
| * \brief |
| * generates UVLC code and passes the codeword to the buffer |
| ************************************************************************ |
| */ |
| void writeSE_UVLC(SyntaxElement *se, DataPartition *dp) |
| { |
| ue_linfo (se->value1,se->value2,&(se->len),&(se->inf)); |
| symbol2uvlc(se); |
| |
| writeUVLC2buffer(se, dp->bitstream); |
| |
| if(se->type != SE_HEADER) |
| dp->bitstream->write_flag = 1; |
| |
| #if TRACE |
| if(dp->bitstream->trace_enabled) |
| trace2out (se); |
| #endif |
| } |
| |
| /*! |
| ************************************************************************ |
| * \brief |
| * generates UVLC code and passes the codeword to the buffer |
| ************************************************************************ |
| */ |
| void writeSE_SVLC(SyntaxElement *se, DataPartition *dp) |
| { |
| se_linfo (se->value1,se->value2,&(se->len),&(se->inf)); |
| symbol2uvlc(se); |
| |
| writeUVLC2buffer(se, dp->bitstream); |
| |
| if(se->type != SE_HEADER) |
| dp->bitstream->write_flag = 1; |
| |
| #if TRACE |
| if(dp->bitstream->trace_enabled) |
| trace2out (se); |
| #endif |
| } |
| |
| /*! |
| ************************************************************************ |
| * \brief |
| * generates UVLC code and passes the codeword to the buffer |
| ************************************************************************ |
| */ |
| void writeCBP_VLC(SyntaxElement *se, DataPartition *dp) |
| { |
| Macroblock* currMB = &img->mb_data[img->current_mb_nr]; |
| if (IS_OLDINTRA (currMB) || currMB->mb_type == SI4MB || currMB->mb_type == I8MB) |
| { |
| cbp_linfo_intra (se->value1,se->value2,&(se->len),&(se->inf)); |
| } |
| else |
| { |
| cbp_linfo_inter (se->value1,se->value2,&(se->len),&(se->inf)); |
| } |
| symbol2uvlc(se); |
| |
| writeUVLC2buffer(se, dp->bitstream); |
| |
| if(se->type != SE_HEADER) |
| dp->bitstream->write_flag = 1; |
| |
| #if TRACE |
| if(dp->bitstream->trace_enabled) |
| trace2out (se); |
| #endif |
| } |
| |
| |
| /*! |
| ************************************************************************ |
| * \brief |
| * generates code and passes the codeword to the buffer |
| ************************************************************************ |
| */ |
| void writeIntraPredMode_CAVLC(SyntaxElement *se, DataPartition *dp) |
| { |
| |
| if (se->value1 == -1) |
| { |
| se->len = 1; |
| se->inf = 1; |
| } |
| else |
| { |
| se->len = 4; |
| se->inf = se->value1; |
| } |
| |
| se->bitpattern = se->inf; |
| writeUVLC2buffer(se, dp->bitstream); |
| |
| if(se->type != SE_HEADER) |
| dp->bitstream->write_flag = 1; |
| |
| #if TRACE |
| if(dp->bitstream->trace_enabled) |
| trace2out (se); |
| #endif |
| |
| return; |
| } |
| |
| |
| /*! |
| ************************************************************************ |
| * \brief |
| * generates UVLC code and passes the codeword to the buffer |
| * \author |
| * Tian Dong |
| ************************************************************************ |
| */ |
| int writeSyntaxElement2Buf_UVLC(SyntaxElement *se, Bitstream* this_streamBuffer ) |
| { |
| |
| se->mapping(se->value1,se->value2,&(se->len),&(se->inf)); |
| |
| symbol2uvlc(se); |
| |
| writeUVLC2buffer(se, this_streamBuffer ); |
| |
| #if TRACE |
| if(se->type <= 1) |
| trace2out (se); |
| #endif |
| |
| return (se->len); |
| } |
| |
| |
| /*! |
| ************************************************************************ |
| * \brief |
| * writes UVLC code to the appropriate buffer |
| ************************************************************************ |
| */ |
| void writeUVLC2buffer(SyntaxElement *se, Bitstream *currStream) |
| { |
| |
| int i; |
| unsigned int mask = 1 << (se->len-1); |
| assert ((se->len-1)<32); |
| |
| // Add the new bits to the bitstream. |
| // Write out a byte if it is full |
| for (i=0; i<se->len; i++) |
| { |
| currStream->byte_buf <<= 1; |
| if (se->bitpattern & mask) |
| currStream->byte_buf |= 1; |
| currStream->bits_to_go--; |
| mask >>= 1; |
| if (currStream->bits_to_go==0) |
| { |
| currStream->bits_to_go = 8; |
| currStream->streamBuffer[currStream->byte_pos++]=currStream->byte_buf; |
| currStream->byte_buf = 0; |
| } |
| } |
| } |
| |
| |
| /*! |
| ************************************************************************ |
| * \brief |
| * generates UVLC code and passes the codeword to the buffer |
| * \author |
| * Tian Dong |
| ************************************************************************ |
| */ |
| int writeSyntaxElement2Buf_Fixed(SyntaxElement *se, Bitstream* this_streamBuffer ) |
| { |
| writeUVLC2buffer(se, this_streamBuffer ); |
| |
| #if TRACE |
| if(se->type <= 1) |
| trace2out (se); |
| #endif |
| return (se->len); |
| } |
| |
| /*! |
| ************************************************************************ |
| * \brief |
| * generates UVLC code and passes the codeword to the buffer |
| * \author |
| * Tian Dong |
| ************************************************************************ |
| */ |
| void writeSE_Flag(SyntaxElement *se, DataPartition *dp ) |
| { |
| se->len = 1; |
| se->bitpattern = (se->value1 & 1); |
| |
| writeUVLC2buffer(se, dp->bitstream ); |
| |
| #if TRACE |
| if(dp->bitstream->trace_enabled) |
| trace2out (se); |
| #endif |
| } |
| |
| /*! |
| ************************************************************************ |
| * \brief |
| * generates UVLC code and passes the codeword to the buffer |
| * \author |
| * Tian Dong |
| ************************************************************************ |
| */ |
| void writeSE_invFlag(SyntaxElement *se, DataPartition *dp ) |
| { |
| se->len = 1; |
| se->bitpattern = 1-(se->value1 & 1); |
| |
| writeUVLC2buffer(se, dp->bitstream ); |
| |
| #if TRACE |
| if(dp->bitstream->trace_enabled) |
| trace2out (se); |
| #endif |
| } |
| |
| /*! |
| ************************************************************************ |
| * \brief |
| * generates UVLC code and passes the codeword to the buffer |
| * \author |
| * Tian Dong |
| ************************************************************************ |
| */ |
| void writeSE_Dummy(SyntaxElement *se, DataPartition *dp ) |
| { |
| se->len = 0; |
| } |
| |
| |
| /*! |
| ************************************************************************ |
| * \brief |
| * generates UVLC code and passes the codeword to the buffer |
| * \author |
| * Tian Dong |
| ************************************************************************ |
| */ |
| void writeSE_Fix(SyntaxElement *se, DataPartition *dp ) |
| { |
| writeUVLC2buffer(se, dp->bitstream ); |
| |
| #if TRACE |
| if(dp->bitstream->trace_enabled) |
| trace2out (se); |
| #endif |
| } |
| |
| |
| /*! |
| ************************************************************************ |
| * \brief |
| * Makes code word and passes it back |
| * |
| * \par Input: |
| * Info : Xn..X2 X1 X0 \n |
| * Length : Total number of bits in the codeword |
| ************************************************************************ |
| */ |
| |
| int symbol2vlc(SyntaxElement *sym) |
| { |
| int info_len = sym->len; |
| |
| // Convert info into a bitpattern int |
| sym->bitpattern = 0; |
| |
| // vlc coding |
| while(--info_len >= 0) |
| { |
| sym->bitpattern <<= 1; |
| sym->bitpattern |= (0x01 & (sym->inf >> info_len)); |
| } |
| return 0; |
| } |
| |
| |
| /*! |
| ************************************************************************ |
| * \brief |
| * generates VLC code and passes the codeword to the buffer |
| ************************************************************************ |
| */ |
| int writeSyntaxElement_VLC(SyntaxElement *se, DataPartition *dp) |
| { |
| |
| se->inf = se->value1; |
| se->len = se->value2; |
| symbol2vlc(se); |
| |
| writeUVLC2buffer(se, dp->bitstream); |
| |
| if(se->type != SE_HEADER) |
| dp->bitstream->write_flag = 1; |
| |
| #if TRACE |
| if(dp->bitstream->trace_enabled) |
| trace2out (se); |
| #endif |
| |
| return (se->len); |
| } |
| |
| |
| /*! |
| ************************************************************************ |
| * \brief |
| * write VLC for NumCoeff and TrailingOnes |
| ************************************************************************ |
| */ |
| |
| int writeSyntaxElement_NumCoeffTrailingOnes(SyntaxElement *se, DataPartition *dp) |
| { |
| 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}, |
| }, |
| }; |
| int vlcnum; |
| |
| vlcnum = se->len; |
| |
| // se->value1 : numcoeff |
| // se->value2 : numtrailingones |
| |
| if (vlcnum == 3) |
| { |
| se->len = 6; // 4 + 2 bit FLC |
| if (se->value1 > 0) |
| { |
| se->inf = ((se->value1-1) << 2) | se->value2; |
| } |
| else |
| { |
| se->inf = 3; |
| } |
| } |
| else |
| { |
| se->len = lentab[vlcnum][se->value2][se->value1]; |
| se->inf = codtab[vlcnum][se->value2][se->value1]; |
| } |
| //se->inf = 0; |
| |
| if (se->len == 0) |
| { |
| printf("ERROR: (numcoeff,trailingones) not valid: vlc=%d (%d, %d)\n", |
| vlcnum, se->value1, se->value2); |
| exit(-1); |
| } |
| |
| symbol2vlc(se); |
| |
| writeUVLC2buffer(se, dp->bitstream); |
| |
| if(se->type != SE_HEADER) |
| dp->bitstream->write_flag = 1; |
| |
| #if TRACE |
| if(dp->bitstream->trace_enabled) |
| trace2out (se); |
| #endif |
| |
| return (se->len); |
| } |
| |
| |
| /*! |
| ************************************************************************ |
| * \brief |
| * write VLC for NumCoeff and TrailingOnes for Chroma DC |
| ************************************************************************ |
| */ |
| int writeSyntaxElement_NumCoeffTrailingOnesChromaDC(SyntaxElement *se, DataPartition *dp) |
| { |
| 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 = img->yuv_format - 1; |
| |
| // se->value1 : numcoeff |
| // se->value2 : numtrailingones |
| se->len = lentab[yuv][se->value2][se->value1]; |
| se->inf = codtab[yuv][se->value2][se->value1]; |
| |
| if (se->len == 0) |
| { |
| printf("ERROR: (numcoeff,trailingones) not valid: (%d, %d)\n", |
| se->value1, se->value2); |
| exit(-1); |
| } |
| |
| symbol2vlc(se); |
| |
| writeUVLC2buffer(se, dp->bitstream); |
| |
| if(se->type != SE_HEADER) |
| dp->bitstream->write_flag = 1; |
| |
| #if TRACE |
| if(dp->bitstream->trace_enabled) |
| trace2out (se); |
| #endif |
| |
| return (se->len); |
| } |
| |
| |
| /*! |
| ************************************************************************ |
| * \brief |
| * write VLC for TotalZeros |
| ************************************************************************ |
| */ |
| int writeSyntaxElement_TotalZeros(SyntaxElement *se, DataPartition *dp) |
| { |
| 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; |
| |
| vlcnum = se->len; |
| |
| // se->value1 : TotalZeros |
| se->len = lentab[vlcnum][se->value1]; |
| se->inf = codtab[vlcnum][se->value1]; |
| |
| if (se->len == 0) |
| { |
| printf("ERROR: (TotalZeros) not valid: (%d)\n",se->value1); |
| exit(-1); |
| } |
| |
| symbol2vlc(se); |
| |
| writeUVLC2buffer(se, dp->bitstream); |
| |
| if(se->type != SE_HEADER) |
| dp->bitstream->write_flag = 1; |
| |
| #if TRACE |
| if(dp->bitstream->trace_enabled) |
| trace2out (se); |
| #endif |
| |
| return (se->len); |
| } |
| |
| |
| /*! |
| ************************************************************************ |
| * \brief |
| * write VLC for TotalZeros for Chroma DC |
| ************************************************************************ |
| */ |
| int writeSyntaxElement_TotalZerosChromaDC(SyntaxElement *se, DataPartition *dp) |
| { |
| 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 vlcnum; |
| int yuv = img->yuv_format - 1; |
| |
| vlcnum = se->len; |
| |
| // se->value1 : TotalZeros |
| se->len = lentab[yuv][vlcnum][se->value1]; |
| se->inf = codtab[yuv][vlcnum][se->value1]; |
| |
| if (se->len == 0) |
| { |
| printf("ERROR: (TotalZeros) not valid: (%d)\n",se->value1); |
| exit(-1); |
| } |
| |
| symbol2vlc(se); |
| |
| writeUVLC2buffer(se, dp->bitstream); |
| |
| if(se->type != SE_HEADER) |
| dp->bitstream->write_flag = 1; |
| |
| #if TRACE |
| if(dp->bitstream->trace_enabled) |
| trace2out (se); |
| #endif |
| |
| return (se->len); |
| } |
| |
| |
| /*! |
| ************************************************************************ |
| * \brief |
| * write VLC for Run Before Next Coefficient, VLC0 |
| ************************************************************************ |
| */ |
| int writeSyntaxElement_Run(SyntaxElement *se, DataPartition *dp) |
| { |
| 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; |
| |
| vlcnum = se->len; |
| |
| // se->value1 : run |
| se->len = lentab[vlcnum][se->value1]; |
| se->inf = codtab[vlcnum][se->value1]; |
| |
| if (se->len == 0) |
| { |
| printf("ERROR: (run) not valid: (%d)\n",se->value1); |
| exit(-1); |
| } |
| |
| symbol2vlc(se); |
| |
| writeUVLC2buffer(se, dp->bitstream); |
| |
| if(se->type != SE_HEADER) |
| dp->bitstream->write_flag = 1; |
| |
| #if TRACE |
| if(dp->bitstream->trace_enabled) |
| trace2out (se); |
| #endif |
| |
| return (se->len); |
| } |
| |
| |
| /*! |
| ************************************************************************ |
| * \brief |
| * write VLC for Coeff Level (VLC1) |
| ************************************************************************ |
| */ |
| int writeSyntaxElement_Level_VLC1(SyntaxElement *se, DataPartition *dp, int profile_idc) |
| { |
| int level = se->value1; |
| int levabs = iabs(level); |
| int sign = (level < 0 ? 1 : 0); |
| |
| if (levabs < 8) |
| { |
| se->len = levabs * 2 + sign - 1; |
| se->inf = 1; |
| } |
| else if (levabs < 16) //8+8) |
| { |
| // escape code1 |
| //se->len = 14 + 1 + 4; |
| se->len = 19; |
| se->inf = (1 << 4) | ((levabs - 8) << 1) | sign; |
| } |
| else |
| { |
| int iLength = 28, numPrefix = 15; |
| int iCodeword, addbit, offset; |
| int levabsm16 = levabs-16; |
| |
| // escape code2 |
| if ((levabsm16) > (1<<11)) |
| { |
| numPrefix++; |
| while ((levabsm16) > (1<<(numPrefix-3))-4096) |
| { |
| numPrefix++; |
| } |
| } |
| |
| addbit = numPrefix - 15; |
| iLength += (addbit<<1); |
| offset = (2048<<addbit)-2048; |
| |
| iCodeword = (1<<(12+addbit))|((levabsm16)<<1)|sign; |
| |
| /* Assert to make sure that the code fits in the VLC */ |
| /* make sure that we are in High Profile to represent level_prefix > 15 */ |
| if (numPrefix > 15 && profile_idc < 100) |
| { |
| //error( "level_prefix must be <= 15 except in High Profile\n", 1000 ); |
| se->len = 0x0000FFFF; // This can be some other big number |
| se->inf = iCodeword; |
| return (se->len); |
| } |
| se->len = iLength; |
| se->inf = iCodeword; |
| } |
| |
| |
| symbol2vlc(se); |
| |
| writeUVLC2buffer(se, dp->bitstream); |
| |
| if(se->type != SE_HEADER) |
| dp->bitstream->write_flag = 1; |
| |
| #if TRACE |
| if(dp->bitstream->trace_enabled) |
| trace2out (se); |
| #endif |
| |
| return (se->len); |
| } |
| |
| |
| /*! |
| ************************************************************************ |
| * \brief |
| * write VLC for Coeff Level |
| ************************************************************************ |
| */ |
| int writeSyntaxElement_Level_VLCN(SyntaxElement *se, int vlc, DataPartition *dp, int profile_idc) |
| { |
| int addbit, offset; |
| int iCodeword; |
| int iLength; |
| |
| int level = se->value1; |
| |
| int levabs = iabs(level); |
| int sign = (level < 0 ? 1 : 0); |
| |
| int shift = vlc-1; |
| int escape = (15<<shift)+1; |
| |
| int numPrefix = (levabs-1)>>shift; |
| |
| int sufmask = ~((0xffffffff)<<shift); |
| int suffix = (levabs-1)&sufmask; |
| |
| if (levabs < escape) |
| { |
| iLength = numPrefix + vlc + 1; |
| iCodeword = (1<<(shift+1))|(suffix<<1)|sign; |
| } |
| else |
| { |
| int levabsesc = levabs-escape; |
| |
| iLength = 28; |
| numPrefix = 15; |
| |
| if ((levabsesc) > (1<<11)) |
| { |
| numPrefix++; |
| while ((levabsesc) > (1<<(numPrefix-3))-4096) |
| { |
| numPrefix++; |
| } |
| } |
| |
| addbit = numPrefix - 15; |
| iLength += (addbit<<1); |
| offset = (2048<<addbit)-2048; |
| |
| iCodeword = (1<<(12+addbit))|((levabsesc-offset)<<1)|sign; |
| /* Assert to make sure that the code fits in the VLC */ |
| /* make sure that we are in High Profile to represent level_prefix > 15 */ |
| if (numPrefix > 15 && profile_idc < 100) |
| { |
| //error( "level_prefix must be <= 15 except in High Profile\n", 1000 ); |
| se->len = 0x0000FFFF; // This can be some other big number |
| se->inf = iCodeword; |
| return (se->len); |
| } |
| } |
| se->len = iLength; |
| se->inf = iCodeword; |
| |
| symbol2vlc(se); |
| |
| writeUVLC2buffer(se, dp->bitstream); |
| |
| if(se->type != SE_HEADER) |
| dp->bitstream->write_flag = 1; |
| |
| #if TRACE |
| if(dp->bitstream->trace_enabled) |
| trace2out (se); |
| #endif |
| |
| return (se->len); |
| } |
| |
| |
| /*! |
| ************************************************************************ |
| * \brief |
| * Write out a trace string on the trace file |
| ************************************************************************ |
| */ |
| #if TRACE |
| int bitcounter = 0; |
| |
| void trace2out(SyntaxElement *sym) |
| { |
| static |
| int i, chars; |
| |
| if (p_trace != NULL) |
| { |
| putc('@', p_trace); |
| chars = fprintf(p_trace, "%i", bitcounter); |
| while(chars++ < 6) |
| putc(' ',p_trace); |
| |
| chars += fprintf(p_trace, "%s", sym->tracestring); |
| while(chars++ < 55) |
| putc(' ',p_trace); |
| |
| // align bit pattern |
| if(sym->len<15) |
| { |
| for(i=0 ; i<15-sym->len ; i++) |
| fputc(' ', p_trace); |
| } |
| |
| // print bit pattern |
| bitcounter += sym->len; |
| for(i=1 ; i<=sym->len ; i++) |
| { |
| if((sym->bitpattern >> (sym->len-i)) & 0x1) |
| fputc('1', p_trace); |
| else |
| fputc('0', p_trace); |
| } |
| fprintf(p_trace, " (%3d) \n",sym->value1); |
| } |
| fflush (p_trace); |
| } |
| |
| void trace2out_cabac(SyntaxElement *sym) |
| { |
| int chars; |
| |
| if (p_trace != NULL) |
| { |
| putc('@', p_trace); |
| chars = fprintf(p_trace, "%i", bitcounter); |
| while(chars++ < 6) |
| putc(' ',p_trace); |
| |
| chars += fprintf(p_trace, "%s", sym->tracestring); |
| while(chars++ < 70) |
| putc(' ',p_trace); |
| |
| fprintf(p_trace, " (%3d) \n",sym->value1); |
| } |
| fflush (p_trace); |
| bitcounter += sym->len; |
| } |
| #endif |
| |
| |
| /*! |
| ************************************************************************ |
| * \brief |
| * puts the less than 8 bits in the byte buffer of the Bitstream into |
| * the streamBuffer. |
| * |
| * \param |
| * currStream: the Bitstream the alignment should be established |
| * |
| ************************************************************************ |
| */ |
| void writeVlcByteAlign(Bitstream* currStream) |
| { |
| if (currStream->bits_to_go < 8) |
| { // trailing bits to process |
| currStream->byte_buf = (currStream->byte_buf <<currStream->bits_to_go) | (0xff >> (8 - currStream->bits_to_go)); |
| stats->bit_use_stuffingBits[img->type]+=currStream->bits_to_go; |
| currStream->streamBuffer[currStream->byte_pos++]=currStream->byte_buf; |
| currStream->bits_to_go = 8; |
| } |
| } |
| |