453 lines
12 KiB
C
453 lines
12 KiB
C
/*
|
|
* @DEC_COPYRIGHT@
|
|
*/
|
|
/*
|
|
* HISTORY
|
|
* $Log: sv_h261_cdenc.c,v $
|
|
* Revision 1.1.4.3 1995/12/18 21:39:02 Karen_Dintino
|
|
* Porting to NT - added casting, removed unused vars, fixed includes
|
|
* [1995/12/18 21:36:50 Karen_Dintino]
|
|
*
|
|
* Revision 1.1.4.2 1995/09/13 14:52:04 Hans_Graves
|
|
* Some code optimizations.
|
|
* [1995/09/13 14:33:22 Hans_Graves]
|
|
*
|
|
* Revision 1.1.2.7 1995/08/15 19:14:01 Karen_Dintino
|
|
* fix reentrant problem
|
|
* [1995/08/15 18:35:32 Karen_Dintino]
|
|
*
|
|
* Revision 1.1.2.6 1995/08/04 16:32:32 Karen_Dintino
|
|
* Return approp errors on end of stream
|
|
* [1995/08/04 16:27:06 Karen_Dintino]
|
|
*
|
|
* Revision 1.1.2.5 1995/08/03 18:02:13 Karen_Dintino
|
|
* Fix error handling
|
|
* [1995/08/03 17:58:43 Karen_Dintino]
|
|
*
|
|
* Revision 1.1.2.4 1995/07/17 16:12:25 Hans_Graves
|
|
* Switched compression to ScBS* bitstreaming routines.
|
|
* [1995/07/17 15:45:50 Hans_Graves]
|
|
*
|
|
* Revision 1.1.2.3 1995/07/11 22:11:41 Karen_Dintino
|
|
* Start to clean up prototypes
|
|
* [1995/07/11 22:01:21 Karen_Dintino]
|
|
*
|
|
* Revision 1.1.2.2 1995/06/19 20:31:26 Karen_Dintino
|
|
* H.261 slib codec
|
|
* [1995/06/19 19:49:18 Karen_Dintino]
|
|
*
|
|
* $EndLog$
|
|
*/
|
|
/*
|
|
**++
|
|
** FACILITY: Workstation Multimedia (WMM) v1.0
|
|
**
|
|
** FILE NAME: sv_h261_cdenc.c
|
|
** MODULE NAME:
|
|
**
|
|
** MODULE DESCRIPTION:
|
|
**
|
|
** DESIGN OVERVIEW:
|
|
**
|
|
**--
|
|
*/
|
|
/*****************************************************************************
|
|
** Copyright (c) Digital Equipment Corporation, 1994, 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. **
|
|
******************************************************************************/
|
|
/* Some Modifications were done to incorporate a scaled IDCT scheme
|
|
on the DecodeXXX routines. These modifications are to
|
|
improve the performance -S.I.S. September 29, 1993.
|
|
*/
|
|
/*************************************************************
|
|
This file contains the routines to run-length encode the ac and dc
|
|
coefficients.
|
|
*************************************************************/
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <math.h>
|
|
|
|
#include "sv_intrn.h"
|
|
#include "SC_err.h"
|
|
#include "sv_h261.h"
|
|
#include "proto.h"
|
|
|
|
#define fgetv mgetv
|
|
#define fgetb mgetb
|
|
#define fputvb mputvb
|
|
#define fputbb mputbb
|
|
|
|
#define MYPI 3.1415926535897931
|
|
#define RSQ2 0.7071067811865
|
|
#define COSM1P3 1.3065629648764
|
|
#define COS1M3 0.5411961001462
|
|
#define COS3 0.3826834323651
|
|
#define sround(x) ( (x >= 0) ? (int) (x+0.5) : (int) (x-0.5) )
|
|
#define SCLAMP(x) ( (x>127) ? 127 : ((x<-128) ? -128 : x) )
|
|
#define Abs(value) ( (value < 0) ? (-value) : value)
|
|
/*PUBLIC*/
|
|
|
|
|
|
const unsigned int tdzz[64] = {
|
|
0, 1, 5, 6, 14, 15, 27, 28,
|
|
2, 4, 7, 13, 16, 26, 29, 42,
|
|
3, 8, 12, 17, 25, 30, 41, 43,
|
|
9, 11, 18, 24, 31, 40, 44, 53,
|
|
10, 19, 23, 32, 39, 45, 52, 54,
|
|
20, 22, 33, 38, 46, 51, 55, 60,
|
|
21, 34, 37, 47, 50, 56, 59, 61,
|
|
35, 36, 48, 49, 57, 58, 62, 63};
|
|
|
|
const unsigned int tzz[64] = {
|
|
0, 1, 8, 16, 9, 2, 3, 10,
|
|
17, 24, 32, 25, 18, 11, 4, 5,
|
|
12, 19, 26, 33, 40, 48, 41, 34,
|
|
27, 20, 13, 6, 7, 14, 21, 28,
|
|
35, 42, 49, 56, 57, 50, 43, 36,
|
|
29, 22, 15, 23, 30, 37, 44, 51,
|
|
58, 59, 52, 45, 38, 31, 39, 46,
|
|
53, 60, 61, 54, 47, 55, 62, 63};
|
|
float static qscale[32][64];
|
|
float static qs[64], invq[32];
|
|
float DCIscale;
|
|
|
|
/*PRIVATE*/
|
|
|
|
extern int bit_set_mask[];
|
|
/*
|
|
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
|
|
};
|
|
|
|
|
|
/*START*/
|
|
|
|
void GenScaleMat()
|
|
{
|
|
BEGIN("GenScaleMat");
|
|
double dbli, dblj;
|
|
float dij;
|
|
int i, j, k, quantindex;
|
|
|
|
for(quantindex=1;quantindex<32;quantindex++) {
|
|
k=0;
|
|
invq[quantindex] = (float) 1.0/(float)(2.0*quantindex);
|
|
for(i=0;i<8;i++) {
|
|
for(j=0;j<8;j++) {
|
|
dbli = MYPI*i/16.0;
|
|
dblj = MYPI*j/16.0;
|
|
dij = (float)(16.0*(float)(cos(dbli)*cos(dblj)));
|
|
if(i==0) dij = (float)(dij/sqrt(2.0));
|
|
if(j==0) dij = (float)(dij/sqrt(2.0));
|
|
qs[k] = (float)(1.0/dij);
|
|
qscale[quantindex][k] = (float)(1.0/(2.0*quantindex*dij));
|
|
k++;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
** Function: EncodeAC()
|
|
** Purpose: Encodes the quantized coefficient matrix input by the first
|
|
** Huffman table. The index is an offset into the matrix.
|
|
*/
|
|
SvStatus_t EncodeAC(SvH261Info_t *H261, ScBitstream_t *bs, int index,
|
|
int *matrix)
|
|
{
|
|
BEGIN("EncodeAC");
|
|
int k,r,l,code,retval;
|
|
ScBSPosition_t Start;
|
|
int tempbits;
|
|
|
|
Start=ScBSBitPosition(bs); /* swtellb(H261); */
|
|
for(r=0,k=index-1;++k<H261_BLOCKSIZE;)
|
|
{
|
|
l = matrix[k];
|
|
if (!l) {r++;}
|
|
else
|
|
{
|
|
code = Abs(l) | (r << 8);
|
|
if (code != HUFFMAN_ESCAPE) {retval=sv_H261HuffEncode(H261,bs,code,H261->T1EHuff);}
|
|
else {retval=0;}
|
|
if (!retval)
|
|
{
|
|
sv_H261HuffEncode(H261,bs,HUFFMAN_ESCAPE,H261->T1EHuff);
|
|
ScBSPutBits(bs,r,6); /* fputvb(H261,6,r); */
|
|
ScBSPutBits(bs,l,8); /* fputvb(H261,8,l); */
|
|
}
|
|
else
|
|
{
|
|
if (l < 0)
|
|
ScBSPutBit(bs,1); /* fputbb(H261,1); */
|
|
else
|
|
ScBSPutBit(bs,0); /* fputbb(H261,0); */
|
|
}
|
|
r=0;
|
|
H261->NumberNZ++;
|
|
}
|
|
}
|
|
H261->CurrentBlockBits = ScBSBitPosition(bs)-Start; /* swtellb(H261)-Start */
|
|
H261->CodedBlockBits+=H261->CurrentBlockBits;
|
|
tempbits = sv_H261HuffEncode(H261,bs,0,H261->T1EHuff);
|
|
H261->EOBBits += tempbits;
|
|
H261->CurrentBlockBits += tempbits;
|
|
return (NoErrors);
|
|
}
|
|
|
|
|
|
/*
|
|
** Function: CBPEncodeAC()
|
|
** Purpose: 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...
|
|
*/
|
|
SvStatus_t CBPEncodeAC(SvH261Info_t *H261, ScBitstream_t *bs,
|
|
int index, int *matrix)
|
|
{
|
|
int k,r,l,code,ovfl;
|
|
ScBSPosition_t Start;
|
|
int tempbits;
|
|
_SlibDebug(_DEBUG_, printf("CBPEncodeAC()") );
|
|
|
|
Start=ScBSBitPosition(bs); /* Start=swtellb(H261); */
|
|
for (ovfl=1, r=0, k=index-1; ++k<H261_BLOCKSIZE; )
|
|
{
|
|
l = matrix[k];
|
|
if (!l)
|
|
r++;
|
|
else
|
|
{
|
|
code = Abs(l) | (r << 8);
|
|
if (code == HUFFMAN_ESCAPE || !sv_H261HuffEncode(H261,bs,code,H261->T2EHuff))
|
|
{
|
|
sv_H261HuffEncode(H261,bs,HUFFMAN_ESCAPE,H261->T2EHuff);
|
|
ScBSPutBits(bs,r,6); /* fputvb(H261,6,r); */
|
|
ScBSPutBits(bs,l,8); /* fputvb(H261,8,l); */
|
|
}
|
|
else if (l < 0)
|
|
ScBSPutBit(bs,1); /* fputbb(H261,1); */
|
|
else
|
|
ScBSPutBit(bs,0); /* fputbb(H261,0); */
|
|
ovfl=0;
|
|
H261->NumberNZ++;
|
|
break;
|
|
}
|
|
}
|
|
if (ovfl)
|
|
{
|
|
_SlibDebug(_VERIFY_, printf("CBP block without any coefficients.\n") );
|
|
return(SvErrorVideoInput);
|
|
}
|
|
for(r=0; ++k<H261_BLOCKSIZE; )
|
|
{
|
|
l = matrix[k];
|
|
if (!l)
|
|
r++;
|
|
else
|
|
{
|
|
code = Abs(l) | (r << 8);
|
|
if (code == HUFFMAN_ESCAPE || !sv_H261HuffEncode(H261,bs,code,H261->T1EHuff))
|
|
{
|
|
sv_H261HuffEncode(H261,bs,HUFFMAN_ESCAPE,H261->T1EHuff);
|
|
ScBSPutBits(bs, r, 6); /* fputvb(H261,6,r); */
|
|
ScBSPutBits(bs, l, 8); /* fputvb(H261,8,l); */
|
|
}
|
|
else if (l < 0)
|
|
ScBSPutBit(bs,1); /* fputbb(H261,1); */
|
|
else
|
|
ScBSPutBit(bs,0); /* fputbb(H261,0); */
|
|
r=0;
|
|
H261->NumberNZ++;
|
|
}
|
|
}
|
|
H261->CurrentBlockBits = ScBSBitPosition(bs)-Start; /* swtellb(H261)-Start;*/
|
|
H261->CodedBlockBits+=H261->CurrentBlockBits;
|
|
tempbits = sv_H261HuffEncode(H261,bs,0,H261->T1EHuff);
|
|
H261->EOBBits += tempbits;
|
|
H261->CurrentBlockBits += tempbits;
|
|
return (NoErrors);
|
|
}
|
|
|
|
|
|
/*
|
|
** Function: EncodeDC()
|
|
** Purpose: Encodes the coefficient input into the output stream.
|
|
*/
|
|
void EncodeDC(SvH261Info_t *H261, ScBitstream_t *bs, int coef)
|
|
{
|
|
_SlibDebug(_DEBUG_, printf("EncodeDC()") );
|
|
if (coef > 254)
|
|
{
|
|
ScBSPutBits(bs, 254, 8);
|
|
H261->NumberNZ++;
|
|
}
|
|
else if (coef <= 1)
|
|
ScBSPutBits(bs, 1, 8);
|
|
else if (coef==128)
|
|
{
|
|
ScBSPutBits(bs, 255, 8);
|
|
H261->NumberNZ++;
|
|
}
|
|
else
|
|
{
|
|
ScBSPutBits(bs, coef, 8);
|
|
H261->NumberNZ++;
|
|
}
|
|
H261->CodedBlockBits+=8;
|
|
}
|
|
|
|
|
|
void InterQuant(float *tdct, int *dct, int mq)
|
|
{
|
|
int i;
|
|
float *pqs=qscale[mq];
|
|
_SlibDebug(_DEBUG_, printf("InterQuant()") );
|
|
|
|
for(i=H261_BLOCKSIZE; i; i--)
|
|
*dct++ = (int)((*tdct++)*(*pqs++));
|
|
}
|
|
|
|
void IntraQuant(float *tdct, int *dct, int mq)
|
|
{
|
|
int i,temp;
|
|
float *pqs=&qscale[mq][1];
|
|
_SlibDebug(_DEBUG_, printf("IntraQuant()") );
|
|
|
|
if (tdct[0] > 0)
|
|
i = (int) (tdct[0] * qscale[4][0] + 0.5);
|
|
else
|
|
i = (int) (tdct[0] * qscale[4][0] - 0.5);
|
|
if (i>254)
|
|
*dct = 254;
|
|
else if (i<1)
|
|
*dct = 1;
|
|
else
|
|
*dct = i;
|
|
|
|
for(i=1, dct++, tdct++; i<H261_BLOCKSIZE; i++){
|
|
if(mq < 3){
|
|
temp = (int)((*tdct++)*(*pqs++));
|
|
if(temp > 127) *dct++ = 127;
|
|
else if (temp < -127) *dct++ = -127;
|
|
else *dct++ = temp;
|
|
}
|
|
else *dct++ = (int)((*tdct++)*(*pqs++));
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
** Function: ZigzagMatrix()
|
|
** Purpose: Performs a zig-zag translation on the input imatrix
|
|
** and puts the output in omatrix.
|
|
*/
|
|
void ZigzagMatrix(int *imatrix, int *omatrix)
|
|
{
|
|
const unsigned int *ptdzz=tdzz;
|
|
int k;
|
|
_SlibDebug(_DEBUG_, printf("ZigzagMatrix") );
|
|
|
|
for(k=H261_BLOCKSIZE; k; k--)
|
|
omatrix[*ptdzz++] = *imatrix++;
|
|
}
|
|
|
|
|
|
void Inv_Quant(int *matrix, int QuantUse, int BlockType, float *fmatrix)
|
|
{
|
|
int k, l, temp;
|
|
float *pqs=qs+1;
|
|
_SlibDebug(_DEBUG_, printf("Inv_Quant()") );
|
|
|
|
/* for(mptr=fmatrix;mptr<fmatrix+H261_BLOCKSIZE;mptr++) {*mptr = 0.0;}*/
|
|
|
|
if (matrix[0])
|
|
{
|
|
if (BlockType==1)
|
|
fmatrix[0] = (float)matrix[0];
|
|
else
|
|
{
|
|
l = matrix[0];
|
|
if (QuantUse&1)
|
|
temp = (l>0) ? (((l*2)+1)*QuantUse):(((l*2)-1)*QuantUse);
|
|
else
|
|
temp = (l>0) ? (((l*2)+1)*QuantUse-1):(((l*2)-1)*QuantUse+1);
|
|
fmatrix[0] = temp*qs[0];
|
|
}
|
|
}
|
|
else
|
|
fmatrix[0] = (float)0.0;
|
|
|
|
matrix++;
|
|
fmatrix++;
|
|
if (QuantUse&1)
|
|
{
|
|
for (k=1; k<64; k++)
|
|
{
|
|
if ((l=*matrix++)>0)
|
|
*fmatrix++ = (((l<<1)+1)*QuantUse) * (*pqs++);
|
|
else if (l)
|
|
*fmatrix++ = (((l<<1)-1)*QuantUse) * (*pqs++);
|
|
else
|
|
{
|
|
*fmatrix++ = (float)0.0;
|
|
pqs++;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
for (k=1; k<64; k++)
|
|
{
|
|
if ((l=*matrix++)>0)
|
|
*fmatrix++ = (((l<<1)+1)*QuantUse-1) * (*pqs++);
|
|
else if (l)
|
|
*fmatrix++ = (((l<<1)-1)*QuantUse+1) * (*pqs++);
|
|
else
|
|
{
|
|
*fmatrix++ = (float)0.0;
|
|
pqs++;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|