You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
807 lines
17 KiB
807 lines
17 KiB
/* File: sv_h261_huffman.c */
|
|
/*****************************************************************************
|
|
** Copyright (c) Digital Equipment Corporation, 1995, 1997 **
|
|
** **
|
|
** All Rights Reserved. Unpublished rights reserved under the copyright **
|
|
** laws of the United States. **
|
|
** **
|
|
** The software contained on this media is proprietary to and embodies **
|
|
** the confidential technology of Digital Equipment Corporation. **
|
|
** Possession, use, duplication or dissemination of the software and **
|
|
** media is authorized only pursuant to a valid written license from **
|
|
** Digital Equipment Corporation. **
|
|
** **
|
|
** RESTRICTED RIGHTS LEGEND Use, duplication, or disclosure by the U.S. **
|
|
** Government is subject to restrictions as set forth in Subparagraph **
|
|
** (c)(1)(ii) of DFARS 252.227-7013, or in FAR 52.227-19, as applicable. **
|
|
******************************************************************************/
|
|
/*************************************************************
|
|
This file contains the Huffman routines.
|
|
*************************************************************/
|
|
|
|
/*
|
|
#define _SLIBDEBUG_
|
|
*/
|
|
|
|
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include "SV.h"
|
|
#include "sv_intrn.h"
|
|
#include "sv_h261.h"
|
|
#include "proto.h"
|
|
|
|
#ifdef _SLIBDEBUG_
|
|
#define _DEBUG_ 0 /* detailed debuging statements */
|
|
#define _VERBOSE_ 0 /* show progress */
|
|
#define _VERIFY_ 1 /* verify correct operation */
|
|
#define _WARN_ 0 /* warnings about strange behavior */
|
|
#endif
|
|
|
|
static DHUFF *MakeDhuff();
|
|
static EHUFF *MakeEhuff(int n);
|
|
static void LoadETable(int *array, EHUFF *table);
|
|
static void LoadDTable(int *array, DHUFF *table);
|
|
static int GetNextState(DHUFF *huff);
|
|
static void DestroyDhuff(DHUFF **huff);
|
|
static void DestroyEhuff(EHUFF **huff);
|
|
static void AddCode(int n, int code, int value, DHUFF *huff);
|
|
|
|
/* Actual Tables */
|
|
#define GetLeft(sval,huff) ((huff->state[(sval)] >> 16) & 0xffff)
|
|
#define GetRight(sval,huff) (huff->state[(sval)] & 0xffff)
|
|
|
|
#define SetLeft(number,sval,huff) huff->state[(sval)]=\
|
|
(((huff->state[(sval)]) & 0xffff)|(number<<16));
|
|
#define SetRight(number,sval,huff) huff->state[(sval)]=\
|
|
(((huff->state[(sval)]) & 0xffff0000)|(number));
|
|
|
|
#define EmptyState 0xffff
|
|
#define Numberp(value) ((value & 0x8000) ? 1 : 0)
|
|
#define MakeHVal(value) (value | 0x8000)
|
|
#define GetHVal(value) (value & 0x7fff)
|
|
|
|
int MTypeCoeff[] = {
|
|
0,4,1,
|
|
1,7,1,
|
|
2,1,1,
|
|
3,5,1,
|
|
4,9,1,
|
|
5,8,1,
|
|
6,10,1,
|
|
7,3,1,
|
|
8,2,1,
|
|
9,6,1,
|
|
-1,-1};
|
|
|
|
int MBACoeff[] = {
|
|
1,1,1,
|
|
2,3,3,
|
|
3,3,2,
|
|
4,4,3,
|
|
5,4,2,
|
|
6,5,3,
|
|
7,5,2,
|
|
8,7,7,
|
|
9,7,6,
|
|
10,8,11,
|
|
11,8,10,
|
|
12,8,9,
|
|
13,8,8,
|
|
14,8,7,
|
|
15,8,6,
|
|
16,10,23,
|
|
17,10,22,
|
|
18,10,21,
|
|
19,10,20,
|
|
20,10,19,
|
|
21,10,18,
|
|
22,11,35,
|
|
23,11,34,
|
|
24,11,33,
|
|
25,11,32,
|
|
26,11,31,
|
|
27,11,30,
|
|
28,11,29,
|
|
29,11,28,
|
|
30,11,27,
|
|
31,11,26,
|
|
32,11,25,
|
|
33,11,24,
|
|
34,11,15, /* Stuffing */
|
|
35,16,1, /* Start */
|
|
-1,-1};
|
|
|
|
int MVDCoeff[] = {
|
|
16,11,25,
|
|
17,11,27,
|
|
18,11,29,
|
|
19,11,31,
|
|
20,11,33,
|
|
21,11,35,
|
|
22,10,19,
|
|
23,10,21,
|
|
24,10,23,
|
|
25,8,7,
|
|
26,8,9,
|
|
27,8,11,
|
|
28,7,7,
|
|
29,5,3,
|
|
30,4,3,
|
|
31,3,3,
|
|
0,1,1,
|
|
1,3,2,
|
|
2,4,2,
|
|
3,5,2,
|
|
4,7,6,
|
|
5,8,10,
|
|
6,8,8,
|
|
7,8,6,
|
|
8,10,22,
|
|
9,10,20,
|
|
10,10,18,
|
|
11,11,34,
|
|
12,11,32,
|
|
13,11,30,
|
|
14,11,28,
|
|
15,11,26,
|
|
-1,-1};
|
|
|
|
int CBPCoeff[] = {
|
|
60,3,7,
|
|
4,4,13,
|
|
8,4,12,
|
|
16,4,11,
|
|
32,4,10,
|
|
12,5,19,
|
|
48,5,18,
|
|
20,5,17,
|
|
40,5,16,
|
|
28,5,15,
|
|
44,5,14,
|
|
52,5,13,
|
|
56,5,12,
|
|
1,5,11,
|
|
61,5,10,
|
|
2,5,9,
|
|
62,5,8,
|
|
24,6,15,
|
|
36,6,14,
|
|
3,6,13,
|
|
63,6,12,
|
|
5,7,23,
|
|
9,7,22,
|
|
17,7,21,
|
|
33,7,20,
|
|
6,7,19,
|
|
10,7,18,
|
|
18,7,17,
|
|
34,7,16,
|
|
7,8,31,
|
|
11,8,30,
|
|
19,8,29,
|
|
35,8,28,
|
|
13,8,27,
|
|
49,8,26,
|
|
21,8,25,
|
|
41,8,24,
|
|
14,8,23,
|
|
50,8,22,
|
|
22,8,21,
|
|
42,8,20,
|
|
15,8,19,
|
|
51,8,18,
|
|
23,8,17,
|
|
43,8,16,
|
|
25,8,15,
|
|
37,8,14,
|
|
26,8,13,
|
|
38,8,12,
|
|
29,8,11,
|
|
45,8,10,
|
|
53,8,9,
|
|
57,8,8,
|
|
30,8,7,
|
|
46,8,6,
|
|
54,8,5,
|
|
58,8,4,
|
|
31,9,7,
|
|
47,9,6,
|
|
55,9,5,
|
|
59,9,4,
|
|
27,9,3,
|
|
39,9,2,
|
|
-1,-1};
|
|
|
|
int TCoeff1[] = {
|
|
0,2,2, /* EOF */
|
|
1,2,3, /* Not First Coef */
|
|
2,4,4,
|
|
3,5,5,
|
|
4,7,6,
|
|
5,8,38,
|
|
6,8,33,
|
|
7,10,10,
|
|
8,12,29,
|
|
9,12,24,
|
|
10,12,19,
|
|
11,12,16,
|
|
12,13,26,
|
|
13,13,25,
|
|
14,13,24,
|
|
15,13,23,
|
|
257,3,3,
|
|
258,6,6,
|
|
259,8,37,
|
|
260,10,12,
|
|
261,12,27,
|
|
262,13,22,
|
|
263,13,21,
|
|
513,4,5,
|
|
514,7,4,
|
|
515,10,11,
|
|
516,12,20,
|
|
517,13,20,
|
|
769,5,7,
|
|
770,8,36,
|
|
771,12,28,
|
|
772,13,19,
|
|
1025,5,6,
|
|
1026,10,15,
|
|
1027,12,18,
|
|
1281,6,7,
|
|
1282,10,9,
|
|
1283,13,18,
|
|
1537,6,5,
|
|
1538,12,30,
|
|
1793,6,4,
|
|
1794,12,21,
|
|
2049,7,7,
|
|
2050,12,17,
|
|
2305,7,5,
|
|
2306,13,17,
|
|
2561,8,39,
|
|
2562,13,16,
|
|
2817,8,35,
|
|
3073,8,34,
|
|
3329,8,32,
|
|
3585,10,14,
|
|
3841,10,13,
|
|
4097,10,8,
|
|
4353,12,31,
|
|
4609,12,26,
|
|
4865,12,25,
|
|
5121,12,23,
|
|
5377,12,22,
|
|
5633,13,31,
|
|
5889,13,30,
|
|
6145,13,29,
|
|
6401,13,28,
|
|
6657,13,27,
|
|
6913,6,1, /* Escape */
|
|
-1,-1
|
|
};
|
|
|
|
/* Excludes EOB */
|
|
|
|
int TCoeff2[] = {
|
|
1,1,1, /* First Coef */
|
|
2,4,4,
|
|
3,5,5,
|
|
4,7,6,
|
|
5,8,38,
|
|
6,8,33,
|
|
7,10,10,
|
|
8,12,29,
|
|
9,12,24,
|
|
10,12,19,
|
|
11,12,16,
|
|
12,13,26,
|
|
13,13,25,
|
|
14,13,24,
|
|
15,13,23,
|
|
257,3,3,
|
|
258,6,6,
|
|
259,8,37,
|
|
260,10,12,
|
|
261,12,27,
|
|
262,13,22,
|
|
263,13,21,
|
|
513,4,5,
|
|
514,7,4,
|
|
515,10,11,
|
|
516,12,20,
|
|
517,13,20,
|
|
769,5,7,
|
|
770,8,36,
|
|
771,12,28,
|
|
772,13,19,
|
|
1025,5,6,
|
|
1026,10,15,
|
|
1027,12,18,
|
|
1281,6,7,
|
|
1282,10,9,
|
|
1283,13,18,
|
|
1537,6,5,
|
|
1538,12,30,
|
|
1793,6,4,
|
|
1794,12,21,
|
|
2049,7,7,
|
|
2050,12,17,
|
|
2305,7,5,
|
|
2306,13,17,
|
|
2561,8,39,
|
|
2562,13,16,
|
|
2817,8,35,
|
|
3073,8,34,
|
|
3329,8,32,
|
|
3585,10,14,
|
|
3841,10,13,
|
|
4097,10,8,
|
|
4353,12,31,
|
|
4609,12,26,
|
|
4865,12,25,
|
|
5121,12,23,
|
|
5377,12,22,
|
|
5633,13,31,
|
|
5889,13,30,
|
|
6145,13,29,
|
|
6401,13,28,
|
|
6657,13,27,
|
|
6913,6,1, /* Escape */
|
|
-1,-1
|
|
};
|
|
|
|
|
|
/*
|
|
* Function: inithuff()
|
|
* Purpose: Initializes all of the Huffman structures to the
|
|
* appropriate values. It must be called before any of
|
|
* the tables are used.
|
|
*/
|
|
void sv_H261HuffInit(SvH261Info_t *H261)
|
|
{
|
|
H261->NumberBitsCoded = 0;
|
|
H261->MBADHuff = MakeDhuff();
|
|
H261->MVDDHuff = MakeDhuff();
|
|
H261->CBPDHuff = MakeDhuff();
|
|
H261->T1DHuff = MakeDhuff();
|
|
H261->T2DHuff = MakeDhuff();
|
|
H261->T3DHuff = MakeDhuff();
|
|
H261->MBAEHuff = MakeEhuff(40);
|
|
H261->MVDEHuff = MakeEhuff(40);
|
|
H261->CBPEHuff = MakeEhuff(70);
|
|
H261->T1EHuff = MakeEhuff(8192);
|
|
H261->T2EHuff = MakeEhuff(8192);
|
|
H261->T3EHuff = MakeEhuff(20);
|
|
LoadDTable(MBACoeff,H261->MBADHuff);
|
|
LoadETable(MBACoeff,H261->MBAEHuff);
|
|
LoadDTable(MVDCoeff,H261->MVDDHuff);
|
|
LoadETable(MVDCoeff,H261->MVDEHuff);
|
|
LoadDTable(CBPCoeff,H261->CBPDHuff);
|
|
LoadETable(CBPCoeff,H261->CBPEHuff);
|
|
LoadDTable(TCoeff1,H261->T1DHuff);
|
|
LoadETable(TCoeff1,H261->T1EHuff);
|
|
LoadDTable(TCoeff2,H261->T2DHuff);
|
|
LoadETable(TCoeff2,H261->T2EHuff);
|
|
LoadDTable(MTypeCoeff,H261->T3DHuff);
|
|
LoadETable(MTypeCoeff,H261->T3EHuff);
|
|
}
|
|
|
|
/*
|
|
* Function: freehuff()
|
|
* Purpose: Frees all memory allocated for the Huffman structures.
|
|
*/
|
|
void sv_H261HuffFree(SvH261Info_t *H261)
|
|
{
|
|
DestroyDhuff(&H261->MBADHuff);
|
|
DestroyDhuff(&H261->MVDDHuff);
|
|
DestroyDhuff(&H261->CBPDHuff);
|
|
DestroyDhuff(&H261->T1DHuff);
|
|
DestroyDhuff(&H261->T2DHuff);
|
|
DestroyDhuff(&H261->T3DHuff);
|
|
DestroyEhuff(&H261->MBAEHuff);
|
|
DestroyEhuff(&H261->MVDEHuff);
|
|
DestroyEhuff(&H261->CBPEHuff);
|
|
DestroyEhuff(&H261->T1EHuff);
|
|
DestroyEhuff(&H261->T2EHuff);
|
|
DestroyEhuff(&H261->T3EHuff);
|
|
}
|
|
|
|
|
|
/*
|
|
** Function: MakeDhuff()
|
|
** Purpose: Constructs a decoder Huffman table and returns
|
|
** the structure.
|
|
*/
|
|
static DHUFF *MakeDhuff()
|
|
{
|
|
int i;
|
|
DHUFF *temp;
|
|
_SlibDebug(_DEBUG_, printf("MakeDhuff()\n") );
|
|
|
|
temp = (DHUFF *)ScAlloc(sizeof(DHUFF));
|
|
temp->NumberStates=1;
|
|
for(i=0; i<512; i++)
|
|
temp->state[i] = -1;
|
|
return(temp);
|
|
}
|
|
|
|
static void DestroyDhuff(DHUFF **huff)
|
|
{
|
|
if (huff)
|
|
{
|
|
ScFree(*huff);
|
|
*huff=NULL;
|
|
}
|
|
}
|
|
|
|
/*
|
|
** Function: MakeEhuff()
|
|
** Purpose: Constructs an encoder huff with a designated table-size.
|
|
** This table-size, n, is used for the lookup of Huffman values,
|
|
** and must represent the largest positive Huffman value.
|
|
*/
|
|
static EHUFF *MakeEhuff(int n)
|
|
{
|
|
int i;
|
|
EHUFF *temp;
|
|
_SlibDebug(_DEBUG_, printf("MakeEhuff()\n") );
|
|
|
|
temp = (EHUFF *)ScAlloc(sizeof(EHUFF));
|
|
temp->n = n;
|
|
temp->Hlen = (int *)ScAlloc(n*sizeof(int));
|
|
temp->Hcode = (int *)ScAlloc(n*sizeof(int));
|
|
for(i=0; i<n; i++)
|
|
{
|
|
temp->Hlen[i] = -1;
|
|
temp->Hcode[i] = -1;
|
|
}
|
|
return(temp);
|
|
}
|
|
|
|
static void DestroyEhuff(EHUFF **huff)
|
|
{
|
|
if (huff)
|
|
{
|
|
if ((*huff)->Hlen)
|
|
ScFree((*huff)->Hlen);
|
|
if ((*huff)->Hcode)
|
|
ScFree((*huff)->Hcode);
|
|
ScFree(*huff);
|
|
*huff=NULL;
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
** Function: LoadETable()
|
|
** Purpose: Used to load an array into an encoder table. The
|
|
** array is grouped in triplets and the first negative value
|
|
** signals the end of the table.
|
|
*/
|
|
static void LoadETable(int *array, EHUFF *table)
|
|
{
|
|
_SlibDebug(_DEBUG_, printf("LoadETable()\n") );
|
|
|
|
while(*array>=0)
|
|
{
|
|
if (*array>table->n)
|
|
{
|
|
printf("Table overflow.\n");
|
|
}
|
|
table->Hlen[*array] = array[1];
|
|
table->Hcode[*array] = (int )array[2];
|
|
array+=3;
|
|
}
|
|
}
|
|
|
|
/*
|
|
** Function: LoadDHUFF()
|
|
** Purpose: Used to load an array into the DHUFF structure. The
|
|
** array consists of trios of Huffman definitions, the
|
|
** first one the value, the next one the size, and the
|
|
** third one the code.
|
|
*/
|
|
static void LoadDTable(int *array, DHUFF *table)
|
|
{
|
|
_SlibDebug(_DEBUG_, printf("LoadDTable()\n") );
|
|
|
|
while(*array>=0)
|
|
{
|
|
AddCode(array[1],array[2],array[0],table);
|
|
array+=3;
|
|
}
|
|
}
|
|
|
|
/*
|
|
** Function: GetNextState()
|
|
** Returns the next free state of the decoder Huffman
|
|
** structure. It no longer exits an error upon overflow.
|
|
*/
|
|
static int GetNextState(DHUFF *huff)
|
|
{
|
|
_SlibDebug(_DEBUG_, printf("GetNextState()\n") );
|
|
/*
|
|
if (huff->NumberStates==512)
|
|
{
|
|
_SlibDebug(_DEBUG_, printf("Overflow\n") );
|
|
exit(ERROR_BOUNDS);
|
|
}
|
|
*/
|
|
return(huff->NumberStates++);
|
|
}
|
|
|
|
/*
|
|
** Function: sv_H261HuffEncode()
|
|
** Purpose: Encodes a value according to a designated encoder Huffman
|
|
** table out to the stream. It returns the number of bits
|
|
** written to the stream and a zero on error.
|
|
*/
|
|
int sv_H261HuffEncode(SvH261Info_t *H261, ScBitstream_t *bs, int val, EHUFF *huff)
|
|
{
|
|
_SlibDebug(_DEBUG_, printf("Encode(val=%d)\n", val) );
|
|
if (val < 0)
|
|
{
|
|
_SlibDebug(_DEBUG_, printf("Encode() Out of bounds val: %d.\n",val) );
|
|
return(0);
|
|
}
|
|
else if (val>=huff->n)
|
|
return(0); /* No serious error, can occur with some values */
|
|
else if (huff->Hlen[val]<0)
|
|
return(0); /* No serious error: can pass thru by alerting routine.*/
|
|
else
|
|
{
|
|
_SlibDebug(_DEBUG_,
|
|
printf("Encode() Value: %d|%x Length: %d Code: %d\n",
|
|
val,val,huff->Hlen[val],huff->Hcode[val]) );
|
|
H261->NumberBitsCoded+=huff->Hlen[val];
|
|
ScBSPutBits(bs, huff->Hcode[val], huff->Hlen[val]);
|
|
return(huff->Hlen[val]);
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
** Function: sv_H261HuffDecode()
|
|
** Purpose: Returns an integer read off the stream using the designated
|
|
** Huffman structure.
|
|
*/
|
|
#if 1
|
|
int sv_H261HuffDecode(SvH261Info_t *H261, ScBitstream_t *bs, DHUFF *huff)
|
|
{
|
|
register int State=0, bits;
|
|
register unsigned short cb;
|
|
_SlibDebug(_DEBUG_, printf("Decode()\n") );
|
|
|
|
cb = (unsigned short)ScBSPeekBits(bs, 16);
|
|
if (bs->EOI)
|
|
return(0);
|
|
if ((State = nextstate(huff, State, 0x8000)) & 0x8000) {
|
|
bits=1;
|
|
State = (State == 0xffff) ? 0 : State & 0x7fff;
|
|
} else if ((State = nextstate(huff, State, 0x4000)) & 0x8000) {
|
|
bits=2;
|
|
State = (State == 0xffff) ? 0 : State & 0x7fff;
|
|
} else if ((State = nextstate(huff, State, 0x2000)) & 0x8000) {
|
|
bits=3;
|
|
State = (State == 0xffff) ? 0 : State & 0x7fff;
|
|
} else if ((State = nextstate(huff, State, 0x1000)) & 0x8000) {
|
|
bits=4;
|
|
State = (State == 0xffff) ? 0 : State & 0x7fff;
|
|
} else if ((State = nextstate(huff, State, 0x0800)) & 0x8000) {
|
|
bits=5;
|
|
State = (State == 0xffff) ? 0 : State & 0x7fff;
|
|
} else if ((State = nextstate(huff, State, 0x0400)) & 0x8000) {
|
|
bits=6;
|
|
State = (State == 0xffff) ? 0 : State & 0x7fff;
|
|
} else if ((State = nextstate(huff, State, 0x0200)) & 0x8000) {
|
|
bits=7;
|
|
State = (State == 0xffff) ? 0 : State & 0x7fff;
|
|
} else if ((State = nextstate(huff, State, 0x0100)) & 0x8000) {
|
|
bits=8;
|
|
State = (State == 0xffff) ? 0 : State & 0x7fff;
|
|
} else if ((State = nextstate(huff, State, 0x0080)) & 0x8000) {
|
|
bits=9;
|
|
State = (State == 0xffff) ? 0 : State & 0x7fff;
|
|
} else if ((State = nextstate(huff, State, 0x0040)) & 0x8000) {
|
|
bits=10;
|
|
State = (State == 0xffff) ? 0 : State & 0x7fff;
|
|
} else if ((State = nextstate(huff, State, 0x0020)) & 0x8000) {
|
|
bits=11;
|
|
State = (State == 0xffff) ? 0 : State & 0x7fff;
|
|
} else if ((State = nextstate(huff, State, 0x0010)) & 0x8000) {
|
|
bits=12;
|
|
State = (State == 0xffff) ? 0 : State & 0x7fff;
|
|
} else if ((State = nextstate(huff, State, 0x0008)) & 0x8000) {
|
|
bits=13;
|
|
State = (State == 0xffff) ? 0 : State & 0x7fff;
|
|
} else if ((State = nextstate(huff, State, 0x0004)) & 0x8000) {
|
|
bits=14;
|
|
State = (State == 0xffff) ? 0 : State & 0x7fff;
|
|
} else if ((State = nextstate(huff, State, 0x0002)) & 0x8000) {
|
|
bits=15;
|
|
State = (State == 0xffff) ? 0 : State & 0x7fff;
|
|
} else if ((State = nextstate(huff, State, 0x0001)) & 0x8000) {
|
|
bits=16;
|
|
State = (State == 0xffff) ? 0 : State & 0x7fff;
|
|
}
|
|
|
|
ScBSSkipBits(bs, bits);
|
|
return(State);
|
|
}
|
|
#else
|
|
int sv_H261HuffDecode(SvH261Info_t *H261, ScBitstream_t *bs, DHUFF *huff)
|
|
{
|
|
int Next,cb;
|
|
int CurrentState=0;
|
|
_SlibDebug(_DEBUG_, printf("Decode()\n") );
|
|
|
|
while(1)
|
|
{
|
|
cb = ScBSGetBit(bs);
|
|
if (bs->EOI)
|
|
return(0);
|
|
Next = cb ? GetLeft(CurrentState,huff) : GetRight(CurrentState,huff);
|
|
if (Next == EmptyState)
|
|
return(0);
|
|
else if (Numberp(Next))
|
|
return(GetHVal(Next));
|
|
else
|
|
CurrentState = Next;
|
|
}
|
|
}
|
|
#endif
|
|
|
|
/*
|
|
** Function: AddCode()
|
|
** Purpose: Adds a Huffman code to the decoder structure. It is called
|
|
** everytime a new Huffman code is to be defined. This function
|
|
** exits when an invalid code is attempted to be placed in
|
|
** the structure.
|
|
*/
|
|
static void AddCode(int n, int code, int value, DHUFF *huff)
|
|
{
|
|
int i,Next;
|
|
int CurrentState=0;
|
|
_SlibDebug(_DEBUG_, printf("AddCode()\n") );
|
|
|
|
if (value < 0)
|
|
return;
|
|
|
|
for(i=n-1;i>0;i--)
|
|
{
|
|
if (code & (1 << i))
|
|
{
|
|
Next = GetLeft(CurrentState,huff);
|
|
if (Next == EmptyState)
|
|
{
|
|
Next = GetNextState(huff);
|
|
SetLeft(Next,CurrentState,huff);
|
|
CurrentState = Next;
|
|
}
|
|
else /* if (Numberp(Next))
|
|
{
|
|
printf("Bad Value/State match:\n");
|
|
printf("Length: %d Code: %d Value: %d\n",
|
|
n,code,value);
|
|
exit(ERROR_BOUNDS);
|
|
}
|
|
else
|
|
*/
|
|
{
|
|
CurrentState = Next;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
Next = GetRight(CurrentState,huff);
|
|
if (Next == EmptyState)
|
|
{
|
|
Next = GetNextState(huff);
|
|
SetRight(Next,CurrentState,huff);
|
|
CurrentState = Next;
|
|
}
|
|
else /* if (Numberp(Next))
|
|
{
|
|
printf("Bad Value/State match:\n");
|
|
printf("Length: %d Code: %d Value: %d\n",
|
|
n,code,value);
|
|
exit(ERROR_BOUNDS);
|
|
}
|
|
else
|
|
*/
|
|
{
|
|
CurrentState = Next;
|
|
}
|
|
}
|
|
}
|
|
if (code & 1)
|
|
{
|
|
Next = GetLeft(CurrentState,huff);
|
|
/* if (Next != EmptyState)
|
|
{
|
|
printf("Overflow on Huffman Table: Nonunique prefix.\n");
|
|
printf("Length: %d Code: %d|%x Value: %d|%x\n",
|
|
n,code,code,value,value);
|
|
exit(ERROR_BOUNDS);
|
|
}
|
|
*/
|
|
SetLeft(MakeHVal(value),CurrentState,huff);
|
|
}
|
|
else
|
|
{
|
|
Next = GetRight(CurrentState,huff);
|
|
/* if (Next != EmptyState)
|
|
{
|
|
printf("Overflow on Huffman Table: Nonunique prefix.\n");
|
|
printf("Length: %d Code: %d|%x Value: %d|%x\n",
|
|
n,code,code,value,value);
|
|
exit(ERROR_BOUNDS);
|
|
}
|
|
*/
|
|
SetRight(MakeHVal(value),CurrentState,huff);
|
|
}
|
|
}
|
|
|
|
/*
|
|
** Function: PrintDHUFF()
|
|
** Purpose: Prints out the decoder Huffman structure that is passed
|
|
** into it.
|
|
*/
|
|
void PrintDhuff(DHUFF *huff)
|
|
{
|
|
int i;
|
|
|
|
printf("Modified Huffman Decoding Structure: %p\n",huff);
|
|
printf("Number of states %d\n",huff->NumberStates);
|
|
for(i=0;i<huff->NumberStates;i++)
|
|
{
|
|
printf("State: %d Left State: %x Right State: %x\n",
|
|
i,
|
|
GetLeft(i,huff),
|
|
GetRight(i,huff));
|
|
}
|
|
}
|
|
|
|
/*
|
|
** Function: PrintEhuff()
|
|
** Purpose: Prints the encoder Huffman structure passed into it.
|
|
*/
|
|
void PrintEhuff(EHUFF *huff)
|
|
{
|
|
BEGIN("PrintEhuff");
|
|
int i;
|
|
|
|
printf("Modified Huffman Encoding Structure: %p\n",huff);
|
|
printf("Number of values %d\n",huff->n);
|
|
for(i=0;i<huff->n;i++)
|
|
{
|
|
if (huff->Hlen[i]>=0)
|
|
{
|
|
printf("Value: %x Length: %d Code: %x\n",
|
|
i,huff->Hlen[i],huff->Hcode[i]);
|
|
}
|
|
}
|
|
}
|
|
|
|
/*
|
|
** Function: PrintTable()
|
|
** Purpose: Prints out 256 elements in a nice byte ordered fashion.
|
|
*/
|
|
void PrintTable(int *table)
|
|
{
|
|
int i,j;
|
|
|
|
for(i=0;i<16;i++)
|
|
{
|
|
for(j=0;j<16;j++)
|
|
{
|
|
printf("%2x ",*(table++));
|
|
}
|
|
printf("\n");
|
|
}
|
|
}
|
|
|
|
|