📄 sac.c
字号:
#include <stdio.h>
#include "sim.h"
#include "global.h"
#define q1 16384
#define q2 32768
#define q3 49152
#define top 65535
static long low=0, high=top, opposite_bits=0, length=0, zerorun=0;
/*********************************************************************
*
* Name: AR_Encode
*
* Description: Encodes a symbol using syntax based arithmetic
* coding. Algorithm specified in H.263 (Annex E).
*
* Input: Array holding cumulative frequency data.
* Index into specific cumulative frequency array.
* Static data for encoding endpoints.
*
* Returns: Number of bits used while encoding symbol.
*
* Side Effects: Modifies low, high, length and opposite_bits
* variables.
*********************************************************************/
int AR_Encode(int index, int cumul_freq[ ])
{
int bitcount=0;
if (index<0)
return -1; /* Escape Code */
length = high - low + 1;
high = low - 1 + (length * cumul_freq[index]) / cumul_freq[0];
low += (length * cumul_freq[index+1]) / cumul_freq[0];
for ( ; ; ) {
if (high < q2) {
bitcount+=bit_opp_bits(0);
}
else if (low >= q2) {
bitcount+=bit_opp_bits(1);
low -= q2;
high -= q2;
}
else if (low >= q1 && high < q3) {
opposite_bits += 1;
low -= q1;
high -= q1;
}
else break;
low *= 2;
high = 2*high+1;
}
return bitcount;
}
int bit_opp_bits(int bit) /* Output a bit and the following opposite bits */
{
int bitcount=0;
bitcount = bit_in_psc_layer(bit);
while(opposite_bits > 0){
bitcount += bit_in_psc_layer(!bit);
opposite_bits--;
}
return bitcount;
}
/*********************************************************************
*
* Name: encoder_flush
*
* Description: Completes arithmetic coding stream before any
* fixed length codes are transmitted.
*
* Input: None
*
* Returns: Number of bits used.
*
* Side Effects: Resets low, high, zerorun and opposite_bits
* variables.
*
*********************************************************************/
int encoder_flush()
{
int bitcount = 0;
opposite_bits++;
if (low < q1) {
bitcount+=bit_opp_bits(0);
}
else {
bitcount+=bit_opp_bits(1);
}
low = 0;
high = top;
zerorun=0;
return bitcount;
}
/*********************************************************************
*
* Name: bit_in_psc_layer
*
* Description: Inserts a bit into output bitstream and avoids
* picture start code emulation by stuffing a one
* bit.
*
* Input: Bit to be output.
*
* Returns: Nothing
*
* Side Effects: Updates zerorun variable.
*
*********************************************************************/
int bit_in_psc_layer(int bit)
{
void putbits (int, int);
int bitcount = 0;
if (zerorun > 13) {
putbits (1, 1);
bitcount++;
zerorun = 0;
}
putbits (1, bit);
bitcount++;
if (bit)
zerorun = 0;
else
zerorun++;
return bitcount;
}
/*********************************************************************
*
* Name: indexfn
*
* Description: Translates between symbol value and symbol
* index.
*
* Input: Symbol value, index table, max number of
* values.
*
* Returns: Index into cumulative frequency tables or
* escape code.
*
* Side Effects: none
*
*********************************************************************/
int indexfn(int value, int table[], int max)
{
int n=0;
while(1) {
if (table[n++]==value) return n-1;
if (n>max) return -1;
}
}
void bit_out_psc_layer();
/*********************************************************************
* SAC Decoder Algorithm as Specified in H26P Annex -E
*
* Name: decode_a_symbol
*
* Description: Decodes an Aritmetically Encoded Symbol
*
* Input: array holding cumulative freq. data
* also uses static data for decoding endpoints
* and code_value variable
*
* Returns: Index to relevant symbol model
*
* Side Effects: Modifies low, high, length, cum and code_value
*
*********************************************************************/
static long dlow, dhigh, dcode_value, dbit, dlength, dsacindex, dcum, dzerorun=0;
int decode_a_symbol(int cumul_freq[ ])
{
dlength = dhigh - dlow + 1;
dcum = (-1 + (dcode_value - dlow + 1) * cumul_freq[0]) / dlength;
for (dsacindex = 1; cumul_freq[dsacindex] > dcum; dsacindex++);
dhigh = dlow - 1 + (dlength * cumul_freq[dsacindex-1]) / cumul_freq[0];
dlow += (dlength * cumul_freq[dsacindex]) / cumul_freq[0];
for ( ; ; ) {
if (dhigh < q2) ;
else if (dlow >= q2) {
dcode_value -= q2;
dlow -= q2;
dhigh -= q2;
}
else if (dlow >= q1 && dhigh < q3) {
dcode_value -= q1;
dlow -= q1;
dhigh -= q1;
}
else {
break;
}
dlow *= 2;
dhigh = 2*dhigh + 1;
bit_out_psc_layer();
dcode_value = 2*dcode_value + dbit;
}
return (dsacindex-1);
}
/*********************************************************************
*
* Name: decoder_reset
*
* Description: Fills Decoder FIFO after a fixed word length
* string has been detected.
*
* Input: None
*
* Returns: Nothing
*
* Side Effects: Fills Arithmetic Decoder FIFO
*
*********************************************************************/
void decoder_reset( )
{
int i;
dzerorun = 0; /* clear consecutive zero's counter */
dcode_value = 0;
dlow = 0;
dhigh = top;
for (i = 1; i <= 16; i++) {
bit_out_psc_layer();
dcode_value = 2 * dcode_value + dbit;
}
}
/*********************************************************************
*
* Name: bit_out_psc_layer
*
* Description: Gets a bit from the Encoded Stream, Checks for
* and removes any PSC emulation prevention bits
* inserted at the decoder, provides 'zeros' to the
* Arithmetic Decoder FIFO to allow it to finish
* data prior to the next PSC. (Garbage bits)
*
* Input: None
*
* Returns: Nothing
*
* Side Effects: Gets a bit from the Input Data Stream
*
*
*********************************************************************/
void bit_out_psc_layer()
{
if (showbits(17)!=1) { /* check for startcode in Arithmetic Decoder FIFO */
dbit = getbits(1);
if(dzerorun > 13) { /* if number of consecutive zeros = 14 */
if (!dbit) {
dzerorun = 1;
}
else { /* if there is a 'stuffing bit present */
dbit = getbits(1); /* overwrite the last bit */
dzerorun = !dbit; /* zerorun=1 if bit is a '0' */
}
}
else { /* if consecutive zero's not exceeded 14 */
if (!dbit)
dzerorun++;
else
dzerorun = 0;
}
} /* end of if !(showbits(17)) */
else {
dbit = 0;
}
/* latent diagnostics */
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -