Windows2003-3790/enduser/netmeeting/av/codecs/dec/dech261/decomp.c
2020-09-30 16:53:55 +02:00

532 lines
17 KiB
C

/* File: sv_h261_decompress.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 handle the decompression of an H.261 compressed data source.
*************************************************************/
#include <stdio.h>
#include <stdlib.h>
#ifdef __osf__
#include <sys/time.h>
#else
#include <time.h>
#endif
#include "sv_intrn.h"
#include "sv_h261.h"
#include "proto.h"
#include "sv_proto.h"
#include "SC_err.h"
/*PUBLIC*/
extern int QuantMType[];
extern int CBPMType[];
extern int IntraMType[];
extern int MFMType[];
extern int FilterMType[];
extern int TCoeffMType[];
extern int bit_set_mask[];
static SvStatus_t p64DecodeGOB (SvH261Info_t *H261, ScBitstream_t *bs);
static SvStatus_t SetCCITT(SvH261Info_t *H261);
extern void ReadPictureHeader(SvH261Info_t *H261, ScBitstream_t *bs);
/*
** Read up to the Sequence header and get the image size
*/
SvStatus_t sv_GetH261ImageInfo(int fd, SvImageInfo_t *iminfo)
{
ScBitstream_t *bs;
SvStatus_t stat;
int input;
int GRead;
int PType;
int PSpareEnable;
int TemporalReference;
int PSpare;
int ImageType;
stat=ScBSCreateFromFile(&bs, fd, NULL, 2048);
/* ReadHeaderHeader */
input = (int) ScBSGetBits(bs, 16);
if ((input != 1) || (bs->EOI ))
{
/* not implemented
if (seof()==0)
{*/
/* printf("Illegal GOB Start Code. Read: %d\n",input);
}*/
return(-1);
}
/* ReadHeaderTrailer */
GRead = (int)ScBSGetBits(bs,4)-1;
if (GRead < 0) /* End Of Frame */
{
/* ReadPictureHeader */
TemporalReference = (int) ScBSGetBits(bs,5);
PType = (int) ScBSGetBits(bs,6);
for(PSpareEnable = 0;ScBSGetBit(bs);)
{
PSpareEnable=1;
PSpare = (int)ScBSGetBits(bs,8);
}
}
/* printf ("PType : %d \n",PType);*/
if (PType&0x04)
{
if (PSpareEnable&&PSpare==0x8c)
ImageType=IT_NTSC;
else
ImageType=IT_CIF;
}
else
ImageType=IT_QCIF;
/* printf ("ImageType %d \n", ImageType);*/
/* iminfo->width = (ScBSGetBits(bs,SV_HORIZONTAL_SIZE_LEN)+15) & (~15);
iminfo->height = (ScBSGetBits(bs,SV_VERTICAL_SIZE_LEN)+15) & (~15);
*/
switch(ImageType)
{
case IT_NTSC:
iminfo->width = 352;
iminfo->height = 240;
break;
case IT_CIF:
iminfo->width = 352;
iminfo->height = 288;
break;
case IT_QCIF:
iminfo->width = 176;
iminfo->height = 144;
break;
default:
sc_dprintf("Unknown ImageType: %d\n",ImageType);
return (SvErrorUnrecognizedFormat);
}
ScBSReset(bs); /* insure the file position is at the beginning */
if (bs->EOI)
stat=SvErrorEndBitstream;
ScBSDestroy(bs);
return(stat);
}
/*
** Function: svH261Decompress()
** Purpose: Decodes a single H261 Frame.
*/
SvStatus_t svH261Decompress(SvCodecInfo_t *Info,
u_char *MultiBuf, u_char **ImagePtr)
{
SvStatus_t status;
SvH261Info_t *H261=Info->h261;
ScBitstream_t *bs=Info->BSIn;
ScCallbackInfo_t CB;
unsigned char *dummy_y, *dummy_u, *dummy_v;
if (MultiBuf)
H261->DecompData = MultiBuf;
if (Info->BSIn->EOI)
status = SvErrorEndBitstream;
/* Initialize the read buffer position and general info */
status = ReadHeaderHeader(H261,bs); /* nonzero on error or eof */
if (status != NoErrors)
return (status);
if (H261->CurrentFrame == 0)
{
DGenScaleMat(); /* Generate the scaling matrix - should be done in 'begin' */
if (H261->PICSIZE==0) /* something not initialized correctly */
return(SvErrorBadImageSize);
/* set up current frame pointers */
H261->Y = H261->DecompData;
H261->U = H261->DecompData + H261->PICSIZE;
H261->V = H261->DecompData + H261->PICSIZE + (H261->PICSIZE/4);
/* initialize image buffer with black */
memset(H261->Y, 16, H261->PICSIZE);
memset(H261->U, 128, H261->PICSIZE/4);
memset(H261->V, 128, H261->PICSIZE/4);
/* set up reference frame pointers */
H261->YREF = H261->V + H261->PICSIZE/4;
H261->UREF = H261->YREF + H261->PICSIZE;
H261->VREF = H261->UREF + H261->PICSIZE/4;
/* initialize image buffer with black */
memset(H261->YREF, 16, H261->PICSIZE);
memset(H261->UREF, 128, H261->PICSIZE/4);
memset(H261->VREF, 128, H261->PICSIZE/4);
if (H261->CallbackFunction)
{
CB.Message = CB_SEQ_HEADER;
CB.Data = NULL;
CB.DataSize = 0;
CB.DataUsed = 0;
CB.DataType = CB_DATA_NONE;
CB.Action = CB_ACTION_CONTINUE;
(*H261->CallbackFunction)(Info, &CB, NULL);
sc_dprintf("Callback: CB_SEQ_HEADER. Data=0x%X, Action = %d\n",
CB.Data, CB.Action);
if (CB.Action == CB_ACTION_END)
return (ScErrorClientEnd);
}
}
else
{
/* Switch Y,U,V with YREF, UREF, VREF */
dummy_y = H261->Y;
dummy_u = H261->U;
dummy_v = H261->V;
H261->Y = H261->YREF;
H261->U = H261->UREF;
H261->V = H261->VREF;
H261->YREF = dummy_y;
H261->UREF = dummy_u;
H261->VREF = dummy_v;
memcpy(H261->Y, H261->YREF, H261->PICSIZE);
memcpy(H261->U, H261->UREF, H261->PICSIZEBY4);
memcpy(H261->V, H261->VREF, H261->PICSIZEBY4);
}
while(1)
{
ReadHeaderTrailer(H261,bs); /* Reads the trailer of the PSC or GBSC code...
Determines if GOB or new picture */
if (bs->EOI)
return (SvErrorEndBitstream);
if ((H261->GRead < 0)) /* End Of Frame - Reading new picture */
{
ReadPictureHeader(H261,bs);
if (H261->CallbackFunction)
{
CB.Message = CB_FRAME_FOUND;
CB.Data = NULL;
CB.DataSize = 0;
CB.DataUsed = 0;
CB.DataType = CB_DATA_NONE;
CB.Action = CB_ACTION_CONTINUE;
(*H261->CallbackFunction)(Info, &CB, NULL);
sc_dprintf("Callback: CB_FRAME_FOUND. Data=0x%X, Action=%d\n",
CB.Data, CB.Action);
if (CB.Action == CB_ACTION_END)
return (ScErrorClientEnd);
}
/* This should already be done by begin */
if (H261->CurrentFrame == 0)
{
/* This should already be done by begin */
if (H261->PType&0x04)
{
if (H261->PSpareEnable&&H261->PSpare==0x8c)
H261->ImageType=IT_NTSC;
else
H261->ImageType=IT_CIF;
}
else
H261->ImageType=IT_QCIF;
/* set here */
status = SetCCITT(H261);
if (status != NoErrors)
return (status);
H261->TemporalOffset=(H261->TemporalReference-H261->CurrentFrame)%32;
/* ywidth = H261->YWidth; */
H261->CWidth = (H261->YWidth/2);
H261->YW4 = (H261->YWidth/4);
H261->CW4 = (H261->CWidth/4);
/* yheight = H261->YHeight; */
/* printf("\n Init.. ImageType is %d", H261->ImageType);*/
}/* End of first frame */
else /* already initialized */
{
while (((H261->CurrentFrame+H261->TemporalOffset)%32) !=
H261->TemporalReference)
H261->CurrentFrame++;
}
#if 0 /* def WIN32 */
if (H261->CurrentGOB == 11)
{
H261->CurrentGOB = 0;
memcpy(H261->YREF, H261->Y, H261->PICSIZE);
memcpy(H261->UREF, H261->U, H261->PICSIZEBY4);
memcpy(H261->VREF, H261->V, H261->PICSIZEBY4);
*ImagePtr = H261->Y;
return (NoErrors);
}
#endif
/* Reads the header off of the stream.
This is a precursor to PSC or GOB read.
nonzero on error or eof */
status = ReadHeaderHeader(H261,bs);
/* if true, indicates that this could be EOF */
if (status != NoErrors)
return (status);
continue;
} /* End of Read New Picture Header */
/* printf ("Now doing the DecodeGOB \n");*/
status = p64DecodeGOB(H261,bs); /* Else decode the GOB */
if (H261->CurrentGOB == (H261->NumberGOB-1))
{
H261->CurrentFrame++;
*ImagePtr = H261->Y;
H261->CurrentGOB = 0;
return (NoErrors);
}
if (status != NoErrors)
return (status);
} /* End of while loop */
}
/*
** Function: p64DecodeGOB
** Purpose: Decodes the GOB block of the current frame.
*/
static SvStatus_t p64DecodeGOB (SvH261Info_t *H261, ScBitstream_t *bs)
{
int i, i8, tempmbh;
SvStatus_t status;
unsigned int *y0ptr, *y1ptr, *y2ptr, *y3ptr;
unsigned int *uptr, *vptr;
int Odct[6][64];
int VIndex;
int HIndex;
float ipfloat[64];
/* printf ("bs->EOI %d \n " , bs->EOI);
*/
ReadGOBHeader(H261,bs); /* Read the group of blocks header */
if (bs->EOI)
return (SvErrorEndBitstream);
switch(H261->ImageType)
{
case IT_NTSC:
case IT_CIF:
H261->CurrentGOB = H261->GRead;
break;
case IT_QCIF:
H261->CurrentGOB = (H261->GRead>>1);
break;
default:
return (SvErrorUnrecognizedFormat);
/* printf("Unknown Image Type: %d.\n",H261->ImageType);*/
break;
}
if (H261->CurrentGOB > H261->NumberGOB)
{
return (SvErrorCompBufOverflow);
/*
printf("Buffer Overflow: Current:%d Number:%d\n",
H261->CurrentGOB, H261->NumberGOB);
return;
*/
}
H261->LastMBA = -1; /* Reset the MBA and the other predictors */
H261->LastMVDH = 0;
H261->LastMVDV = 0;
tempmbh = ReadMBHeader(H261, bs);
if (bs->EOI)
return(SvErrorEndBitstream);
while (tempmbh==0)
{
H261->LastMBA = H261->LastMBA + H261->MBA;
H261->CurrentMDU = H261->LastMBA;
if (H261->CurrentMDU > 32)
return (NoErrors);
if (!CBPMType[H261->MType])
H261->CBP = 0x3f;
if (QuantMType[H261->MType])
{
H261->UseQuant=H261->MQuant;
H261->GQuant=H261->MQuant;
}
else
H261->UseQuant=H261->GQuant;
switch (H261->ImageType)
{
case IT_QCIF:
HIndex = ((H261->CurrentMDU % 11) * 16);
VIndex = (H261->CurrentGOB*48) + ((H261->CurrentMDU/11) * 16);
break;
case IT_NTSC:
case IT_CIF:
HIndex = ((((H261->CurrentGOB & 1)*11) + (H261->CurrentMDU%11)) * 16);
VIndex = ((H261->CurrentGOB/2)*48) + ((H261->CurrentMDU/11) * 16);
break;
default:
/* printf("\n Unknown Image Type \n");*/
return (SvErrorUnrecognizedFormat);
}
i = VIndex*H261->YWidth;
H261->VYWH = i + HIndex;
H261->VYWH2 = (((i/2) + HIndex) /2);
i8 = H261->MVDV*H261->YWidth + H261->MVDH;
H261->VYWHMV = H261->VYWH + i8;
H261->VYWHMV2 = H261->VYWH2 + ((H261->MVDV /2)*H261->CWidth) + (H261->MVDH /2);
for(i8=0; i8<6; i8++)
{
if ((H261->CBP & bit_set_mask[5-i8])&&(TCoeffMType[H261->MType]))
{
if (CBPMType[H261->MType])
status = CBPDecodeAC_Scale(H261, bs, 0, H261->UseQuant, IntraMType[H261->MType], ipfloat);
else
{
*ipfloat = DecodeDC_Scale(H261,bs,IntraMType[H261->MType],H261->UseQuant);
status = DecodeAC_Scale(H261,bs,1,H261->UseQuant, ipfloat);
}
ScScaleIDCT8x8(ipfloat, &Odct[i8][0]);
}
else
memset(&Odct[i8][0], 0, 256);
}
y0ptr = (unsigned int *) (H261->Y+H261->VYWH);
y1ptr = y0ptr + 2;
y2ptr = y0ptr + ((H261->YWidth)<<1);
y3ptr = y2ptr + 2;
uptr = (unsigned int *) (H261->U+H261->VYWH2);
vptr = (unsigned int *) (H261->V+H261->VYWH2);
/* printf ("IntraMType[H261->MType] : %d \n",IntraMType[H261->MType]);*/
if (!IntraMType[H261->MType])
{
if (FilterMType[H261->MType])
{
ScCopyMB16(&H261->YREF[H261->VYWHMV], &H261->mbRecY[0], H261->YWidth, 16);
ScCopyMB8(&H261->UREF[H261->VYWHMV2], &H261->mbRecU[0], H261->CWidth, 8);
ScCopyMB8(&H261->VREF[H261->VYWHMV2], &H261->mbRecV[0], H261->CWidth, 8);
ScLoopFilter(&H261->mbRecY[0], H261->workloc, 16);
ScLoopFilter(&H261->mbRecY[8], H261->workloc, 16);
ScLoopFilter(&H261->mbRecY[128], H261->workloc, 16);
ScLoopFilter(&H261->mbRecY[136], H261->workloc, 16);
ScLoopFilter(&H261->mbRecU[0], H261->workloc, 8);
ScLoopFilter(&H261->mbRecV[0], H261->workloc, 8);
}
else if (MFMType[H261->MType])
{
ScCopyMB16(&H261->YREF[H261->VYWHMV], &H261->mbRecY[0], H261->YWidth, 16);
ScCopyMB8(&H261->UREF[H261->VYWHMV2], &H261->mbRecU[0], H261->CWidth, 8);
ScCopyMB8(&H261->VREF[H261->VYWHMV2], &H261->mbRecV[0], H261->CWidth, 8);
}
else
{
ScCopyMB16(&H261->YREF[H261->VYWH], &H261->mbRecY[0], H261->YWidth, 16);
ScCopyMB8(&H261->UREF[H261->VYWH2], &H261->mbRecU[0], H261->CWidth, 8);
ScCopyMB8(&H261->VREF[H261->VYWH2], &H261->mbRecV[0], H261->CWidth, 8);
}
if (H261->CBP & 0x20)
ScCopyAddClip(&H261->mbRecY[0], &Odct[0][0], y0ptr, 16, H261->YW4);
else
ScCopyMV8(&H261->mbRecY[0], y0ptr, 16, H261->YW4);
if (H261->CBP & 0x10)
ScCopyAddClip(&H261->mbRecY[8], &Odct[1][0], y1ptr, 16, H261->YW4);
else
ScCopyMV8(&H261->mbRecY[8], y1ptr, 16, H261->YW4);
if (H261->CBP & 0x08)
ScCopyAddClip(&H261->mbRecY[128], &Odct[2][0], y2ptr, 16, H261->YW4);
else
ScCopyMV8(&H261->mbRecY[128], y2ptr, 16, H261->YW4);
if (H261->CBP & 0x04)
ScCopyAddClip(&H261->mbRecY[136], &Odct[3][0], y3ptr, 16, H261->YW4);
else
ScCopyMV8(&H261->mbRecY[136], y3ptr, 16, H261->YW4);
if (H261->CBP & 0x02)
ScCopyAddClip(&H261->mbRecU[0], &Odct[4][0], uptr, 8, H261->CW4);
else
ScCopyMV8(&H261->mbRecU[0], uptr, 8, H261->CW4);
if (H261->CBP & 0x01)
ScCopyAddClip(&H261->mbRecV[0], &Odct[5][0], vptr, 8, H261->CW4);
else
ScCopyMV8(&H261->mbRecV[0], vptr, 8, H261->CW4);
}
else
{
ScCopyClip(&Odct[0][0], y0ptr, H261->YW4);
ScCopyClip(&Odct[1][0], y1ptr, H261->YW4);
ScCopyClip(&Odct[2][0], y2ptr, H261->YW4);
ScCopyClip(&Odct[3][0], y3ptr, H261->YW4);
ScCopyClip(&Odct[4][0], uptr, H261->CW4);
ScCopyClip(&Odct[5][0], vptr, H261->CW4);
}
if (H261->CurrentMDU >= 32)
{
if (H261->CurrentGOB < (H261->NumberGOB-1))
tempmbh = ReadMBHeader(H261, bs);
return (NoErrors);
}
tempmbh = ReadMBHeader(H261, bs);
if (bs->EOI)
return (SvErrorEndBitstream);
}
return(NoErrors);
}
/*
** Function: SetCCITT()
** Purpose: Sets the CImage and CFrame parameters for CCITT coding.
*/
static SvStatus_t SetCCITT(SvH261Info_t *H261)
{
BEGIN("SetCCITT");
switch(H261->ImageType)
{
case IT_NTSC:
H261->NumberGOB = 10; /* Parameters for NTSC design */
H261->NumberMDU = 33;
H261->YWidth = 352;
H261->YHeight = 240;
break;
case IT_CIF:
H261->NumberGOB = 12; /* Parameters for NTSC design */
H261->NumberMDU = 33;
H261->YWidth = 352;
H261->YHeight = 288;
break;
case IT_QCIF:
H261->NumberGOB = 3; /* Parameters for NTSC design */
H261->NumberMDU = 33;
H261->YWidth = 176;
H261->YHeight = 144;
break;
default:
return (SvErrorUnrecognizedFormat);
/* printf("Unknown ImageType: %d\n",H261->ImageType);*/
/* exit(ERROR_BOUNDS);*/
/* break;*/
}
return (NoErrors);
}
SvStatus_t svH261DecompressFree(SvHandle_t Svh)
{
SvCodecInfo_t *Info = (SvCodecInfo_t *)Svh;
SvH261Info_t *H261 = (SvH261Info_t *) Info->h261;
if (!H261->inited)
return(NoErrors);
sv_H261HuffFree(Info->h261);
if (Info->h261->workloc)
ScFree(Info->h261->workloc);
H261->inited=FALSE;
return (NoErrors);
}