/************************************************************* Copyright (C) 1990, 1991, 1993 Andy C. Hung, all rights reserved. PUBLIC DOMAIN LICENSE: Stanford University Portable Video Research Group. If you use this software, you agree to the following: This program package is purely experimental, and is licensed "as is". Permission is granted to use, modify, and distribute this program without charge for any purpose, provided this license/ disclaimer notice appears in the copies. No warranty or maintenance is given, either expressed or implied. In no event shall the author(s) be liable to you or a third party for any special, incidental, consequential, or other damages, arising out of the use or inability to use the program for any purpose (or the loss of data), even if we have been advised of such possibilities. Any public reference or advertisement of this source code should refer to it as the Portable Video Research Group (PVRG) code, and not by any author(s) (or Stanford University) name. *************************************************************/ /* ************************************************************ codec.c This file contains the routines to run-length encode the ac and dc coefficients. ************************************************************ */ /*LABEL codec.c */ #include "globals.h" #include "csize.h" #define fputv mputv #define fgetv mgetv #define fputb mputb #define fgetb mgetb /*PUBLIC*/ extern void EncodeAC(); extern void CBPEncodeAC(); extern void DecodeAC(); extern void CBPDecodeAC(); extern int DecodeDC(); extern void EncodeDC(); /*PRIVATE*/ extern int bit_set_mask[]; extern int Loud; extern int NumberNZ; extern FRAME *CFrame; extern IMAGE *CImage; extern DHUFF *T1DHuff; extern DHUFF *T2DHuff; extern EHUFF *T1EHuff; extern EHUFF *T2EHuff; int extend_mask[] = { 0xFFFFFFFE, 0xFFFFFFFC, 0xFFFFFFF8, 0xFFFFFFF0, 0xFFFFFFE0, 0xFFFFFFC0, 0xFFFFFF80, 0xFFFFFF00, 0xFFFFFE00, 0xFFFFFC00, 0xFFFFF800, 0xFFFFF000, 0xFFFFE000, 0xFFFFC000, 0xFFFF8000, 0xFFFF0000, 0xFFFE0000, 0xFFFC0000, 0xFFF80000, 0xFFF00000 }; int CodedBlockBits=0; int EOBBits=0; /*START*/ /*BFUNC EncodeAC() encodes the quantized coefficient matrix input by the first Huffman table. The index is an offset into the matrix. EFUNC*/ void EncodeAC(index,matrix) int index; int *matrix; { BEGIN("EncodeAC"); int k,r,l,code,retval,Start; Start=swtell(); for(r=0,k=index-1;++k -128)) { code = abs(l) | (r << 8); if (code != HUFFMAN_ESCAPE) { retval=Encode(code,T1EHuff); } else {retval=0;} if (!retval) { Encode(HUFFMAN_ESCAPE,T1EHuff); fputv(6,r); fputv(8,l); } else { if (l < 0){fputb(1);} else {fputb(0);} } } else { Encode(HUFFMAN_ESCAPE,T1EHuff); fputv(6,r); if (l>0) {fputv(8,0x00);} else {fputv(8,0x80);} /* Negative */ fputv(8,l&0xff); } r=0; NumberNZ++; } } CodedBlockBits+=(swtell()-Start); EOBBits+=Encode(0,T1EHuff); } /*BFUNC CBPEncodeAC() encodes the AC block matrix when we know there exists a non-zero coefficient in the matrix. Thus the EOB cannot occur as the first element and we save countless bits... EFUNC*/ void CBPEncodeAC(index,matrix) int index; int *matrix; { BEGIN("CBPEncodeAC"); int k,r,l,code,retval,ovfl,Start; Start=swtell(); for(ovfl=1,r=0,k=index-1;++k -128)) { code = abs(l) | (r << 8); if (code != HUFFMAN_ESCAPE) retval=Encode(code,T2EHuff); else retval=0; if (!retval) { Encode(HUFFMAN_ESCAPE,T2EHuff); fputv(6,r); fputv(8,l); } else { if (l < 0) {fputb(1);} else {fputb(0);} } } else { Encode(HUFFMAN_ESCAPE,T1EHuff); fputv(6,r); if (l>0) {fputv(8,0x00);} else {fputv(8,0x80);} /* Negative */ fputv(8,l&0xff); } ovfl=0; NumberNZ++; break; } } if (ovfl) { WHEREAMI(); printf("CBP block without any coefficients.\n"); return; } for(r=0;++k -128)) { code = abs(l) | (r << 8); if (code != HUFFMAN_ESCAPE) {retval=Encode(code,T1EHuff);} else {retval=0;} if (!retval) { Encode(HUFFMAN_ESCAPE,T1EHuff); fputv(6,r); fputv(8,l); } else { if (l < 0) {fputb(1);} else {fputb(0);} } } else { Encode(HUFFMAN_ESCAPE,T1EHuff); fputv(6,r); if (l>0) {fputv(8,0x00);} else {fputv(8,0x80);} /* Negative */ fputv(8,l&0xff); } r=0; NumberNZ++; } } CodedBlockBits+=(swtell()-Start); EOBBits+=Encode(0,T1EHuff); } /*BFUNC DecodeAC() decodes from the stream and puts the elements into the matrix starting from the value of index. The matrix must be given as input and initialized to a value at least as large as 64. EFUNC*/ void DecodeAC(index,matrix) int index; int *matrix; { BEGIN("DecodeAC"); int k,r,l; int *mptr; for(mptr=matrix+index;mptr> 8; if (fgetb()) {l = -l;} } #ifdef CODEC_DEBUG printf("DecodeAC: k:%d r:%d l:%d\n",k,r,l); #endif k += r; if (k>=BLOCKSIZE) { WHEREAMI(); printf("k greater than blocksize:\n",k); break; } matrix[k++] = l; NumberNZ++; } if (r=Decode(T1DHuff)) { WHEREAMI(); printf("EOB expected, found 0x%x.\n",r); } } /*BFUNC CBPDecodeAC() decodes the stream when we assume the input cannot begin with an EOB Huffman code. Thus we use a different Huffman table. The input index is the offset within the matrix and the matrix must already be defined to be greater than 64 elements of int. EFUNC*/ void CBPDecodeAC(index,matrix) int index; int *matrix; { BEGIN("CBPDecodeAC"); int k,r,l; int *mptr; for(mptr=matrix+index;mptr> 8; if (fgetb()) {l = -l;} } k += r; matrix[k++] = l; NumberNZ++; while(k> 8; if (fgetb()) {l = -l;} } #ifdef CODEC_DEBUG printf("CBPDecodeAC: k:%d r:%d l:%d\n",r,l); #endif if (l & bit_set_mask[7]) l |= extend_mask[7]; k += r; if (k>=BLOCKSIZE) { WHEREAMI(); printf("k greater than blocksize:\n",k); break; } matrix[k++] = l; NumberNZ++; } if (r=Decode(T1DHuff)) { WHEREAMI(); printf("EOB expected, found 0x%x.\n",r); } } /*BFUNC DecodeDC() decodes a dc element from the stream. EFUNC*/ int DecodeDC(LocalDHuff) DHUFF *LocalDHuff; { BEGIN("DecodeDC"); int s,diff; s = Decode(LocalDHuff); #ifdef CODEC_DEBUG printf("DC Decode sig. %d\n",s); #endif if (s) { diff = fgetv(s); s--; /* Align */ #ifdef CODEC_DEBUG printf("Raw DC Decode %d\n",diff); #endif if ((diff & bit_set_mask[s]) == 0) { diff |= extend_mask[s]; diff++; } } else diff=0; return(diff); } /*BFUNC EncodeDC() encodes the coefficient input into the output stream. EFUNC*/ void EncodeDC(coef,LocalEHuff) int coef; EHUFF *LocalEHuff; { int cofac,s,encsize; if (coef) NumberNZ++; cofac = abs(coef); if (cofac < 256) s = csize[cofac]; else { cofac = cofac >> 8; s = csize[cofac] + 8; } #ifdef CODEC_DEBUG printf("DC Encoding Difference %d Size %d\n",coef,s); #endif encsize=Encode(s,LocalEHuff); if (coef < 0) coef--; fputv(s,coef); CodedBlockBits+=(s+encsize); } /*END*/