ac.cpp
资源名称:NETVIDEO.rar [点击查看]
上传用户:sun1608
上传日期:2007-02-02
资源大小:6116k
文件大小:18k
源码类别:
流媒体/Mpeg4/MP4
开发平台:
Visual C++
- /* $Id: ac.cpp,v 1.2 2001/04/19 18:32:09 wmay Exp $ */
- /****************************************************************************/
- /* MPEG4 Visual Texture Coding (VTC) Mode Software */
- /* */
- /* This software was jointly developed by the following participants: */
- /* */
- /* Single-quant, multi-quant and flow control */
- /* are provided by Sarnoff Corporation */
- /* Iraj Sodagar (iraj@sarnoff.com) */
- /* Hung-Ju Lee (hjlee@sarnoff.com) */
- /* Paul Hatrack (hatrack@sarnoff.com) */
- /* Shipeng Li (shipeng@sarnoff.com) */
- /* Bing-Bing Chai (bchai@sarnoff.com) */
- /* B.S. Srinivas (bsrinivas@sarnoff.com) */
- /* */
- /* Bi-level is provided by Texas Instruments */
- /* Jie Liang (liang@ti.com) */
- /* */
- /* Shape Coding is provided by OKI Electric Industry Co., Ltd. */
- /* Zhixiong Wu (sgo@hlabs.oki.co.jp) */
- /* Yoshihiro Ueda (yueda@hlabs.oki.co.jp) */
- /* Toshifumi Kanamaru (kanamaru@hlabs.oki.co.jp) */
- /* */
- /* OKI, Sharp, Sarnoff, TI and Microsoft contributed to bitstream */
- /* exchange and bug fixing. */
- /* */
- /* */
- /* In the course of development of the MPEG-4 standard, this software */
- /* module is an implementation of a part of one or more MPEG-4 tools as */
- /* specified by the MPEG-4 standard. */
- /* */
- /* The copyright of this software belongs to ISO/IEC. ISO/IEC gives use */
- /* of the MPEG-4 standard free license to use this software module or */
- /* modifications thereof for hardware or software products claiming */
- /* conformance to the MPEG-4 standard. */
- /* */
- /* Those intending to use this software module in hardware or software */
- /* products are advised that use may infringe existing patents. The */
- /* original developers of this software module and their companies, the */
- /* subsequent editors and their companies, and ISO/IEC have no liability */
- /* and ISO/IEC have no liability for use of this software module or */
- /* modification thereof in an implementation. */
- /* */
- /* Permission is granted to MPEG members to use, copy, modify, */
- /* and distribute the software modules ( or portions thereof ) */
- /* for standardization activity within ISO/IEC JTC1/SC29/WG11. */
- /* */
- /* Copyright 1995, 1996, 1997, 1998 ISO/IEC */
- /****************************************************************************/
- /************************************************************/
- /* Sarnoff Very Low Bit Rate Still Image Coder */
- /* Copyright 1995, 1996, 1997, 1998 Sarnoff Corporation */
- /************************************************************/
- /************************************************************/
- /* Filename: ac.c */
- /* Author: B.S. Srinivas */
- /* Date Modified: April 23, 1998 */
- /* */
- /* Descriptions: */
- /* This file contains routines for Integer arithmetic */
- /* coding, which is based on the ac.c file from the SOL */
- /* package. */
- /* */
- /* The following routines are modified or created for */
- /* the latest VTC package: */
- /* static Void mzte_output_bit() */
- /* Void mzte_ac_encoder_init() */
- /* Int mzte_ac_encoder_done() */
- /* static Int mzte_input_bit() */
- /* Void mzte_ac_decoder_init() */
- /* Void mzte_ac_decoder_done() */
- /* */
- /************************************************************/
- //#include <stdio.h>
- //#include <stdlib.h>
- //#include <assert.h>
- #include "dataStruct.hpp"
- #include "ac.hpp"
- #include "bitpack.hpp"
- #include "errorHandler.hpp"
- #include "msg.hpp"
- #define codeValueBits 16
- #define peakValue (((long)1<<codeValueBits)-1)
- #define firstQtr (peakValue/4+1)
- #define Half (2*firstQtr)
- #define thirdQtr (3*firstQtr)
- #define BYTETYPE UChar
- #define SHORTTYPE UShort
- #define MIN(a,b) (((a)<(b)) ? (a) : (b))
- #define STUFFING_CNT 22
- #define MIXED 2
- /* static function prototypes */
- //static Void mzte_output_bit(ac_encoder *,Int);
- //static Void mzte_bit_plus_follow(ac_encoder *,Int);
- //static Void mzte_update_model(ac_model *,ac_model *,Int);
- //static Int mzte_input_bit(ac_decoder *);
- static Int zeroStrLen=0;
- /************************************************************************/
- /* Error Checking and Handling Macros */
- /************************************************************************/
- #define error(m)
- do {
- fflush(stdout);
- fprIntf(stderr, "%s:%d: error: ", __File__, __LINE__);
- fprIntf(stderr, m);
- fprIntf(stderr, "n");
- exit(1);
- } while (0)
- #define check(b,m)
- do {
- if (b)
- error(m);
- } while (0)
- /************************************************************************/
- /* Bit Output */
- /************************************************************************/
- /**************************************************/
- /* Added bit stuffing to prevent start code */
- /* emulation, i.e., add a "1" bit after every 22 */
- /* consecutive "0" bits in the bit stream */
- /* */
- /* Modified to use a fixed buffer and write to */
- /* file directly after the buffer is full. So the*/
- /* ace->bitstreamLength now only has the # of */
- /* bytes in current buffer. Total bits (bitCount)*/
- /* will indicate the total # bits for arithmetic */
- /* coding part. */
- /**************************************************/
- Void CVTCEncoder::mzte_output_bit(ac_encoder *ace,Int bit)
- {
- register int flag=0;
- ace->buffer *= 2;
- ace->buffer |= (bit)?0x01:0;
- (ace->bitsLeft)--;
- (ace->bitCount)++;
- if (!(ace->bitsLeft)) {
- if (!(ace->bitstream))
- errorHandler("Failure to allocate space for array Bitstream "
- "in ac_encoder structure");
- switch (flag=(ace->bitstreamLength>=MAX_BUFFER)) {
- case 1:
- write_to_bitstream(ace->bitstream,MAX_BUFFER<<3);
- ace->bitstreamLength=0;
- break;
- default:
- break;
- }
- ace->bitstream[(ace->bitstreamLength)++] = ace->buffer;
- ace->bitsLeft = 8;
- }
- /* Dealing with bit stuffing when 0's are encountered */
- zeroStrLen+=(!bit)?1:-zeroStrLen;
- if (zeroStrLen==STUFFING_CNT) {
- mzte_output_bit(ace,1);
- zeroStrLen=0;
- }
- return;
- }
- Void CVTCEncoder::mzte_bit_plus_follow(ac_encoder *ace,Int bit)
- {
- register long followBits;
- followBits = ace->followBits;
- mzte_output_bit(ace,bit);
- while (followBits) {
- mzte_output_bit(ace,!bit);
- --followBits;
- }
- ace->followBits = followBits;
- return;
- }
- /************************************************************************/
- /* Encoder */
- /************************************************************************/
- Void CVTCEncoder::mzte_ac_encoder_init(ac_encoder *ace)
- {
- ace->low = 0;
- ace->high = peakValue;
- ace->followBits = 0;
- ace->bitsLeft = 8;
- ace->buffer = 0;
- ace->bitCount = 0;
- ace->bitstreamLength = 0;
- ace->bitstream=(BYTETYPE *)malloc((MAX_BUFFER+10)*sizeof(BYTETYPE));
- if (ace->bitstream == NULL)
- errorHandler("can't allocate memory for ace->bitstream");
- // assert((ace->bitstream=(BYTETYPE *)malloc((MAX_BUFFER+10)*sizeof(BYTETYPE))));
- zeroStrLen=0;
- /* always start arithmetic coding bitstream with a 1 bit. */
- emit_bits(1,1);
- return;
- }
- /***************************************************************/
- /* Added stuffing bits to prevent start code emulation. */
- /***************************************************************/
- Int CVTCEncoder::mzte_ac_encoder_done(ac_encoder *ace)
- {
- register long bitCount;
- register Int bitsLeft;
- register Int bitsToWrite;
- register long streamLength;
- register int flag;
- ++(ace->followBits);
- flag = (ace->low >= firstQtr);
- mzte_bit_plus_follow(ace,flag);
- bitsLeft = ace->bitsLeft;
- bitCount = ace->bitCount;
- streamLength = ace->bitstreamLength;
- if (bitsLeft != 8) {
- ace->bitstream[streamLength++] = (ace->buffer << bitsLeft);
- if (!(ace->bitstream[streamLength-1]&(1<<bitsLeft))) {
- ace->bitstream[streamLength-1] += (1<<bitsLeft)-1;
- ++bitCount;
- }
- }
- bitsToWrite = (streamLength > MAX_BUFFER)?(MAX_BUFFER<<3):0;
- bitsToWrite += (bitCount % (MAX_BUFFER<<3));
- if ((bitsToWrite==0) && (streamLength==MAX_BUFFER))
- bitsToWrite=(MAX_BUFFER<<3);
- write_to_bitstream(ace->bitstream,bitsToWrite);
- if ((bitsLeft==8) && (!(ace->bitstream[streamLength-1]&1))) {
- /* stuffing bits to prevent start code emulation */
- emit_bits(1,1);
- ++bitCount;
- }
- ace->bitstreamLength=streamLength;
- ace->bitCount=bitCount;
- free(ace->bitstream);
- return(ace->bitCount);
- }
- Int CVTCEncoder::mzte_ac_encode_symbol(ac_encoder *ace, ac_model *acm, Int sym)
- {
- register long low,high;
- register long range;
- register long bitCount;
- if (sym<0 || sym>=acm->nsym)
- errorHandler("Invalid symbol passed to mzte_ac_encode_symbol "
- "(sym=%d while nsym=%d)",
- sym,acm->nsym);
- low = ace->low;
- high = ace->high;
- range = (long) (high - low) + 1;
- high=low+(range*(Int)acm->cfreq[sym])/(Int)acm->cfreq[0] - 1;
- low=low+(range*(Int)acm->cfreq[sym+1])/(Int)acm->cfreq[0];
- bitCount = ace->bitCount;
- while (1) {
- if (high < Half) {
- mzte_bit_plus_follow(ace,0);
- }
- else if (low >= Half) {
- mzte_bit_plus_follow(ace,1);
- low -= Half;
- high -= Half;
- }
- else if ((low >= firstQtr) && (high < thirdQtr)) {
- ++(ace->followBits);
- low -= firstQtr;
- high -= firstQtr;
- }
- else
- break;
- low = 2*low;
- high = 2*high + 1;
- }
- ace->low = low;
- ace->high = high;
- if (acm->adapt)
- mzte_update_model(acm,sym);
- return ace->bitCount - bitCount;
- }
- /************************************************************************/
- /* Bit Input */
- /************************************************************************/
- /*********************************************************/
- /* Modified to be consistant with the functions in */
- /* bitpack.c, i.e., using nextinputbit() to get the new */
- /* bits from the bit stream. */
- /* */
- /* Included remove stuffing bits, refer to */
- /* mzte_output_bit() for more details. */
- /*********************************************************/
- Int CVTCDecoder::mzte_input_bit(ac_decoder *acd)
- {
- register Int t;
- if (!(acd->bitsLeft))
- acd->bitsLeft = 8;
- t = nextinputbit();
- --(acd->bitsLeft);
- ++(acd->bitCount);
- /* remove stuffing bits */
- zeroStrLen+=(!t)?1:-zeroStrLen;
- if(zeroStrLen==STUFFING_CNT) {
- if (!mzte_input_bit(acd))
- errorHandler("Error in decoding stuffing bits "
- "(must be 1 after %d 0's)",STUFFING_CNT);
- zeroStrLen=0;
- }
- return(t);
- }
- /************************************************************************/
- /* Decoder */
- /************************************************************************/
- Void CVTCDecoder::mzte_ac_decoder_init(ac_decoder *acd)
- {
- register long i,value=0;
- /* remove first stuffing bit */
- if(!get_X_bits(1))
- errorHandler("Error in extracting the stuffing bit at then"
- "beginning of arithmetic decoding"
- "refer mzte_encoder_init in ac.c)");
- zeroStrLen=0;
- i = codeValueBits;
- do {
- value <<= 1;
- value += mzte_input_bit(acd);
- } while (--i);
- acd->value = value;
- acd->low = 0;
- acd->high = peakValue;
- acd->bitCount = 0;
- acd->bitsLeft = 0;
- return;
- }
- /*******************************************************/
- /* Added restore_arithmetic_offset() called to recover */
- /* the extra bits read in by decoder. This routine is */
- /* defined in bitpack.c */
- /*******************************************************/
- Void CVTCDecoder::mzte_ac_decoder_done(ac_decoder *acd)
- {
- restore_arithmetic_offset(acd->bitsLeft);
- acd->bitCount += acd->bitsLeft;
- if ((acd->bitCount)%8)
- errorHandler("Did not get alignment in arithmetic decoding");
- }
- Int CVTCDecoder::mzte_ac_decode_symbol(ac_decoder *acd,ac_model *acm)
- {
- register Int high,low,value;
- register long range;
- register Int cum;
- Int sym;
- Int modify=0;
- high=acd->high; low=acd->low; value=acd->value;
- range = (long)(high-low)+1;
- cum = (((long)(value-low)+1)*(Int)(acm->cfreq[0])-1)/range;
- for (sym=0; (Int)(acm->cfreq[sym+1])>cum; sym++)
- /* do nothing */ ;
- high = low + (range*(Int)(acm->cfreq[sym]))/(Int)(acm->cfreq[0])-1;
- low = low + (range*(Int)(acm->cfreq[sym+1]))/(Int)(acm->cfreq[0]);
- modify = acm->adapt;
- while (1) {
- if (high < Half) {
- /* do nothing */
- } else if (low >= Half) {
- value -= Half;
- low -= Half;
- high -= Half;
- }
- else if ((low >= firstQtr) && (high < thirdQtr)) {
- value -= firstQtr;
- low -= firstQtr;
- high -= firstQtr;
- }
- else
- break;
- low <<= 1;
- high = (high<<1)+1;
- value = (value<<1) + mzte_input_bit(acd);
- }
- acd->high = high;
- acd->low = low;
- acd->value = value;
- if (modify)
- mzte_update_model(acm,sym);
- return sym;
- }
- /************************************************************************/
- /* Probability Model */
- /************************************************************************/
- Void CVTCCommon::mzte_ac_model_init(ac_model *acm,Int nsym,SHORTTYPE *ifreq,Int adapt,
- Int inc)
- {
- register Int i;
- register UShort tmpFreq=0;
- acm->inc = inc;
- acm->nsym = nsym;
- acm->adapt = adapt;
- if ((acm->freq=(UShort *)malloc(nsym*sizeof(UShort)))==NULL)
- errorHandler("Can't allocate %d bytes for acm->freq in "
- "mzte_ac_model_init.",
- nsym*sizeof(UShort));
- if ((acm->cfreq=(UShort *) malloc((nsym+1)*sizeof(UShort)))==NULL)
- errorHandler("Can't allocate %d bytes for acm->cfreq in "
- "mzte_ac_model_init.",
- (nsym+1)*sizeof(UShort));
- if (ifreq) {
- acm->cfreq[nsym] = 0;
- for (i=nsym-1; i>=0; i--) {
- acm->freq[i] = ifreq[i];
- acm->cfreq[i] = tmpFreq + ifreq[i];
- tmpFreq = acm->cfreq[i];
- }
- /* NOTE: This check won't always work for mixture of models */
- if (acm->cfreq[0] > acm->Max_frequency) {
- register Int cum=0;
- acm->cfreq[nsym] = 0;
- for (i=nsym-1; i>=0; i--) {
- acm->freq[i] = ((Int) ifreq[i] + 1)/2;
- cum += (ifreq[i] + 1)/2;
- acm->cfreq[i] = cum;
- }
- }
- if (acm->cfreq[0] > acm->Max_frequency)
- errorHandler("error in acm->cfreq[0]");
- }
- else {
- for (i=0; i < nsym; i++) {
- acm->freq[i] = 1;
- acm->cfreq[i] = nsym - i;
- }
- acm->cfreq[nsym] = 0;
- }
- }
- Void CVTCCommon::mzte_ac_model_done(ac_model *acm)
- {
- acm->nsym = 0;
- free(acm->freq);
- acm->freq = NULL;
- free(acm->cfreq);
- acm->cfreq = NULL;
- }
- Void CVTCCommon::mzte_update_model(ac_model *acm,Int sym)
- {
- register SHORTTYPE *freq,*cfreq;
- register Int i;
- register Int inc;
- freq = acm->freq;
- cfreq = acm->cfreq;
- /* scale freq count down */
- if (cfreq[0] == acm->Max_frequency) {
- register Int cum=0,nsym;
- nsym = acm->nsym;
- cfreq[nsym] = 0;
- for (i=nsym-1; i>=0; i--) {
- freq[i] = ((Int)freq[i] + 1)/2;
- cum += freq[i];
- cfreq[i] = cum;
- }
- }
- inc = acm->inc;
- freq[sym] += inc;
- for (i=sym; i>=0; i--)
- cfreq[i] += inc;
- }