blob: 291d2a5a9138fab294c7c97008be2a8f51429fb0 [file] [log] [blame]
/*!
************************************************************************
* \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,
signed 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;
}