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

608 lines
18 KiB
C

/* File: sv_h261_init.c */
/*****************************************************************************
** 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. **
******************************************************************************/
/*
#define _SLIBDEBUG_
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "SC_err.h"
#include "sv_intrn.h"
#include "sv_h261.h"
#include "proto.h"
#include "sv_proto.h"
#ifdef WIN32
#include <mmsystem.h>
#endif
#ifdef _SLIBDEBUG_
#define _DEBUG_ 0 /* detailed debuging statements */
#define _VERBOSE_ 0 /* show progress */
#define _VERIFY_ 1 /* verify correct operation */
#define _WARN_ 1 /* warnings about strange behavior */
#endif
/*
** Name: sv_InitH261
** Purpose: Initalize fields for compression or decompression.
**
** Note: XXX - This version is hardcode to handle 4:2:2 subsampling
** eg. the calculation of numMCU
*/
SvStatus_t svH261Init(SvCodecInfo_t *Info)
{
SvH261Info_t *H261;
if (!Info || !Info->h261)
return (SvErrorMemory);
H261=Info->h261;
if (H261->inited)
return(SvErrorNone);
H261->YWidth = Info->Width;
H261->YHeight = Info->Height;
H261->PICSIZE = Info->Width*Info->Height;
H261->PICSIZEBY4 = Info->h261->PICSIZE>>2;
/* common - compression & decompression */
H261->C_U_Frames=0;
H261->CodedFrames=0;
H261->TemporalReference=1;
H261->TemporalOffset = 0;
H261->PType=0x0;
H261->Type2=0x0;
H261->MType=0x0;
H261->GQuant=8;
H261->MQuant=8;
H261->ParityEnable=0;
H261->PSpareEnable=0;
H261->GSpareEnable=0;
H261->Parity=0;
H261->PSpare=0;
H261->GSpare=0;
H261->NumberMDU=0;
H261->CurrentMDU=0;
H261->NumberGOB=0;
H261->CurrentGOB=0;
H261->CurrentFrame=0;
H261->StartFrame = 0;
H261->LastFrame=0;
H261->PreviousFrame = 0;
H261->NumberFrames=0;
H261->TransmittedFrames=0;
H261->InitialQuant=0;
/* compression */
H261->MVDH=0;
H261->MVDV=0;
H261->CBP=0x3f;
H261->CBPThreshold = 1;
H261->VAR = 0;
H261->VAROR = 0;
H261->MWOR=0;
H261->LastMVDV=0;
H261->LastMVDH=0;
H261->GRead=0;
H261->MBA=0;
H261->LastMBA=0;
H261->LastMType=0;
H261->FrameSkip=1;
/* these are initialized by sv_api.c */
/* H261->ME_search = 5;
H261->ME_method = ME_FASTEST;
H261->ME_threshold = 600;
H261->frame_rate=(float)30.0F;
H261->bit_rate=0;
*/
H261->FileSizeBits=0;
H261->BufferOffset=0;
H261->QDFact=1;
H261->QUpdateFrequency=11;
H261->QUse=0;
H261->QSum=0;
H261->CBPThreshold=1;
H261->ForceCIF=0;
H261->NumberNZ=0;
H261->FirstFrameBits=0;
H261->NumberOvfl=0;
H261->YCoefBits=0;
H261->UCoefBits=0;
H261->VCoefBits=0;
H261->ForceCIF = 1;
/* decompression */
H261->NumberNZ = 0;
H261->TemporalReference=1;
H261->TemporalOffset=0;
H261->PType=0x0;
H261->Type2=0x0;
H261->MType=0x0;
H261->GQuant=8;
H261->MQuant=8;
H261->MVDH=0;
H261->MVDV=0;
H261->VAR=0;
H261->VAROR=0;
H261->MWOR=0;
H261->LastMVDV=0;
H261->LastMVDH=0;
H261->CBP=0x3f;
H261->GRead=0;
H261->MBA=0;
H261->LastMBA=0;
H261->ImageType=IT_NTSC;
H261->LastMType=0;
H261->CBPThreshold=1; /* abs threshold before we use CBP */
/* H261->ErrorValue=0;*/
/* H261->Trace=NULL;*/
H261->ForceCIF=0;
H261->UseQuant = 8;
if ((Info->h261->workloc=(unsigned int *)ScAlloc(512*sizeof(int)))
==NULL)
return(SvErrorMemory);
sv_H261HuffInit(Info->h261); /* Put Huffman tables on */
H261->makekey = 0; /* disable key-frame trigger */
H261->inited=TRUE;
return (NoErrors);
}
/*
** Name: sv_InitH261Encoder
** Purpose: Prepare the encoder by loading default values
**
*/
SvStatus_t svH261CompressInit(SvCodecInfo_t *Info)
{
SvH261Info_t *H261;
SvStatus_t status;
int i;
if (!Info || !Info->h261)
return (SvErrorMemory);
H261=Info->h261;
if (H261->inited)
return(SvErrorNone);
/* init common stuff */
status=svH261Init(Info);
if (status!=SvErrorNone)
return(status);
/*
* Initialize size-related paramters
*/
H261->YWidth = Info->Width;
H261->YHeight = Info->Height;
if (H261->YWidth == CIF_WIDTH && H261->YHeight == CIF_HEIGHT)
{
H261->ImageType = IT_CIF;
H261->NumberGOB = 12; /* Parameters for CIF design */
H261->NumberMDU = 33;
H261->PType=0x04;
}
else if (H261->YWidth == QCIF_WIDTH && H261->YHeight == QCIF_HEIGHT)
{
H261->ImageType = IT_QCIF;
H261->NumberGOB = 3; /* Parameters for QCIF design */
H261->NumberMDU = 33;
H261->PType=0x00;
}
else if (H261->YWidth == NTSC_WIDTH && H261->YHeight == NTSC_HEIGHT)
{
H261->ImageType = IT_NTSC;
H261->NumberGOB = 10; /* Parameters for NTSC design */
H261->NumberMDU = 33;
H261->PType=0x04;
H261->PSpareEnable=1;
H261->PSpare=0x8c;
}
else
{
H261->ImageType = 0;
return (SvErrorUnrecognizedFormat);
}
H261->CWidth = H261->YWidth/2;
H261->CHeight = H261->YHeight/2;
H261->YW4 = H261->YWidth/4;
H261->CW4 = H261->CWidth/4;
H261->PICSIZE = H261->YWidth*H261->YHeight;
H261->PICSIZEBY4 = H261->PICSIZE>>2;
/*
* Allocate memory
*/
if ((H261->LastIntra = (unsigned char **)
ScAlloc(H261->NumberGOB*sizeof(unsigned char *)))==NULL)
return(SvErrorMemory);
for(i=0; i<H261->NumberGOB; i++)
{
H261->LastIntra[i] = (unsigned char *)ScAlloc(H261->NumberMDU);
if (H261->LastIntra[i]==NULL)
return(SvErrorMemory);
memset(H261->LastIntra[i],0,H261->NumberMDU);
}
if ((H261->YREF=(unsigned char *)ScAlloc(H261->PICSIZE))==NULL)
return(SvErrorMemory);
if ((H261->YRECON=(unsigned char *)ScAlloc(H261->PICSIZE))==NULL)
return(SvErrorMemory);
if ((H261->UREF=(unsigned char *)ScAlloc(H261->PICSIZEBY4))==NULL)
return(SvErrorMemory);
if ((H261->URECON=(unsigned char *)ScAlloc(H261->PICSIZEBY4))==NULL)
return(SvErrorMemory);
if ((H261->VREF=(unsigned char *)ScAlloc(H261->PICSIZEBY4))==NULL)
return(SvErrorMemory);
if ((H261->VRECON=(unsigned char *)ScAlloc(H261->PICSIZEBY4))==NULL)
return (SvErrorMemory);
if ((H261->Y=(unsigned char *)ScAlloc(H261->PICSIZE))==NULL)
return(SvErrorMemory);
if ((H261->U=(unsigned char *)ScAlloc(H261->PICSIZEBY4))==NULL)
return(SvErrorMemory);
if ((H261->V=(unsigned char *)ScAlloc(H261->PICSIZEBY4))==NULL)
return(SvErrorMemory);
if ((H261->YDEC=(unsigned char *)ScAlloc(H261->PICSIZE))==NULL)
return(SvErrorMemory);
if ((H261->UDEC=(unsigned char *)ScAlloc(H261->PICSIZEBY4))==NULL)
return(SvErrorMemory);
if ((H261->VDEC=(unsigned char *)ScAlloc(H261->PICSIZEBY4))==NULL)
return(SvErrorMemory);
if (H261->extbitstream)
{
H261->RTPInfo = (SvH261RTPInfo_t *) ScAlloc(sizeof(SvH261RTPInfo_t));
if (H261->RTPInfo==NULL)
return(SvErrorMemory);
memset(H261->RTPInfo, 0, sizeof(SvH261RTPInfo_t)) ;
}
H261->PBUFF = 3;
H261->PBUFF_Factor = 3;
H261->CodeLength = 100;
H261->TotalByteOffset = 0;
H261->TotalMB[0] = 0;
H261->TotalMB[1] = 0;
H261->SkipMB = 0;
H261->MBBits[0] = 0;
H261->MBBits[1] = 0;
if (H261->frame_rate>0)
H261->NBitsPerFrame = (int)((float)H261->bit_rate/H261->frame_rate);
else
H261->NBitsPerFrame = 0;
H261->Buffer_All = H261->PBUFF*H261->NBitsPerFrame;
H261->BitsLeft = H261->Buffer_All;
H261->MAX_MQUANT = 31;
H261->MIN_MQUANT = 4;
H261->alpha1 = 4.5;
H261->alpha2 = 2.5;
H261->LowerQuant = 0;
H261->LowerQuant_FIX = 0;
H261->FineQuant = 0;
H261->ZBDecide = 30.0;
H261->MSmooth = 1;
if(H261->frame_rate==30)
H261->MIN_MQUANT += 2;
H261->ActThr2 = ACTIVE_THRESH;
H261->ActThr = ACTIVE_THRESH;
H261->ActThr5 = H261->ActThr2;
H261->ActThr6 = H261->ActThr;
#if 0
if (H261->bit_rate > 300000)
#else
if ((H261->bit_rate > 300000) || /* for VBR */
(H261->bit_rate == 0 && H261->QP < 10))
#endif
{
H261->ActThr4 = ACTIVE_THRESH*24/32;
H261->ActThr2 = H261->ActThr4;
H261->ActThr = H261->ActThr2;
H261->LowerQuant_FIX=12;
H261->FineQuant = 0;
H261->ZBDecide = 30.0;
H261->CBPThreshold = 2;
H261->MSmooth = 2;
H261->PBUFF=3;
}
#if 0
if (H261->frame_rate < 20)
#else
if ((H261->frame_rate < 20) || /* for VBR */
(H261->bit_rate == 0 && H261->QP > 30))
#endif
{
H261->ActThr3 = ACTIVE_THRESH*23/40;
H261->LowerQuant_FIX=12;
}
#if 0
if (H261->bit_rate<128001)
#else
if ((H261->bit_rate<128001) || /* for VBR */
(H261->bit_rate == 0 && H261->QP > 20))
#endif
{
H261->ActThr2 = ACTIVE_THRESH;
H261->ActThr = ACTIVE_THRESH;
H261->ActThr5 = H261->ActThr2;
H261->ActThr6 = H261->ActThr;
H261->ZBDecide = 32.0;
H261->PBUFF=3;
H261->FineQuant = 0;
H261->MSmooth = 3;
H261->CBPThreshold = 1;
}
#if 0
if(H261->bit_rate<70001)
#else
if ((H261->bit_rate<70001) || /* for VBR */
(H261->bit_rate == 0 && H261->QP > 28))
#endif
{
H261->ActThr2 = ACTIVE_THRESH;
H261->ActThr = ACTIVE_THRESH;
H261->ActThr5 = H261->ActThr2;
H261->ActThr6 = H261->ActThr;
H261->ZBDecide = 36.0;
H261->FineQuant = 0;
H261->PBUFF=4;
H261->PBUFF_Factor=4;
H261->MSmooth = 4;
H261->CBPThreshold = 1;
}
/* ndef WIN32 */
if(H261->bit_rate) { /* CBR */
if(H261->NBitsPerFrame < 31000)
H261->GQuant = (31 - (int)H261->NBitsPerFrame/1000);
else
H261->GQuant = 1;
}
else
H261->GQuant = H261->QPI; /* VBR */
H261->InitialQuant = H261->GQuant;
memset(H261->CBPFreq, 0, sizeof(H261->CBPFreq));
GenScaleMat();
if (H261->FileSizeBits) /* Rate is determined by bits/second. */
H261->bit_rate=(int)(H261->FileSizeBits*H261->frame_rate)/
(H261->FrameSkip*(H261->LastFrame-H261->CurrentFrame+1));
if (H261->bit_rate)
{
H261->QDFact = (H261->bit_rate/320);
H261->QOffs = 1;
}
H261->GQuant=H261->MQuant=H261->InitialQuant;
H261->BufferOffset=0;
H261->TotalBits=0;
H261->NumberOvfl=0;
H261->FirstFrameBits=0;
H261->TransmittedFrames=0;
H261->QDFact = 1;
H261->QOffs= 1;
H261->QUpdateFrequency = 11;
return (NoErrors);
}
SvStatus_t svH261SetParamInt(SvHandle_t Svh, SvParameter_t param,
qword value)
{
SvCodecInfo_t *Info = (SvCodecInfo_t *)Svh;
if (!Svh)
return(SvErrorCodecHandle);
if (Info->mode == SV_H261_DECODE)
switch (param)
{
case SV_PARAM_QUALITY:
if (value>99)
Info->h261->quality=99;
else if (value<0)
Info->h261->quality=0;
else
Info->h261->quality=(int)value;
break;
case SV_PARAM_DEBUG:
Info->h261->dbg=(void *)value;
break;
}
else if (Info->mode == SV_H261_ENCODE)
switch (param)
{
case SV_PARAM_MOTIONALG:
Info->h261->ME_method=(int)value;
return(SvErrorNone);
case SV_PARAM_MOTIONSEARCH:
Info->h261->ME_search=(int)value;
break;
case SV_PARAM_MOTIONTHRESH:
Info->h261->ME_threshold=(int)value;
break;
case SV_PARAM_BITRATE:
if (value>=0)
Info->h261->bit_rate = (int)value;
break;
case SV_PARAM_QUALITY:
if (value>99)
Info->h261->quality=99;
else if (value<0)
Info->h261->quality=0;
else
Info->h261->quality=(int)value;
break;
case SV_PARAM_DEBUG:
Info->h261->dbg=(void *)value;
break;
case SV_PARAM_FORMATEXT:
Info->h261->extbitstream = (int)value;
return(SvErrorNone);
case SV_PARAM_PACKETSIZE:
Info->h261->packetsize = (int)value * 8;
break;
case SV_PARAM_QUANTI: /* for VBR */
Info->h261->QPI = (int)value;
break;
case SV_PARAM_QUANTP: /* for VBR */
Info->h261->QP = (int)value;
break;
case SV_PARAM_KEYSPACING:
break;
case SV_PARAM_FRAMETYPE:
if (value==FRAME_TYPE_I)
Info->h261->makekey = 1; /* send key-frame */
return(SvErrorNone);
}
return(SvErrorNone);
}
SvStatus_t svH261SetParamFloat(SvHandle_t Svh, SvParameter_t param,
float value)
{
SvCodecInfo_t *Info = (SvCodecInfo_t *)Svh;
if (!Svh)
return(SvErrorCodecHandle);
if (Info->mode == SV_H261_ENCODE)
switch (param)
{
case SV_PARAM_FPS:
if (value<1.0)
Info->h261->frame_rate = 1.0F;
else if (value>30.0)
Info->h261->frame_rate = 30.0F;
else
Info->h261->frame_rate = value;
Info->h261->FrameRate_Fix=(int)(Info->h261->frame_rate+0.5);
_SlibDebug(_DEBUG_,
printf("frame_rate = %f\n", Info->h261->frame_rate) );
return(SvErrorNone);
}
return(svH261SetParamInt(Svh, param, (long)value));
}
qword svH261GetParamInt(SvHandle_t Svh, SvParameter_t param)
{
SvCodecInfo_t *Info = (SvCodecInfo_t *)Svh;
if (!Svh)
return((qword)0);
if (Info->mode == SV_H261_ENCODE)
switch (param)
{
case SV_PARAM_BITRATE:
return((qword)Info->h261->bit_rate);
case SV_PARAM_FPS:
return((qword)svH261GetParamFloat(Svh, param));
case SV_PARAM_QUALITY:
return((qword)Info->h261->quality);
case SV_PARAM_NATIVEFORMAT:
return((qword)BI_YU12SEP);
case SV_PARAM_FINALFORMAT:
return((qword)BI_YU12SEP);
case SV_PARAM_ALGFLAGS:
{
qword flags=0;
/* flags|=Info->h261->extbitstream ? PARAM_ALGFLAG_EXTBS : 0; */
return(flags);
}
break;
case SV_PARAM_PACKETSIZE:
return((qword)Info->h261->packetsize/8);
case SV_PARAM_MOTIONALG:
return((qword)Info->h261->ME_method);
case SV_PARAM_MOTIONSEARCH:
return((qword)Info->h261->ME_search);
case SV_PARAM_MOTIONTHRESH:
return((qword)Info->h261->ME_threshold);
}
else if (Info->mode == SV_H261_DECODE)
switch (param)
{
case SV_PARAM_BITRATE:
return((qword)Info->h261->bit_rate);
case SV_PARAM_FPS:
return((qword)svH261GetParamFloat(Svh, param));
case SV_PARAM_WIDTH:
return((qword)Info->h261->YWidth);
case SV_PARAM_HEIGHT:
return((qword)Info->h261->YHeight);
case SV_PARAM_FRAME:
return((qword)Info->h261->CurrentFrame);
case SV_PARAM_NATIVEFORMAT:
return((qword)BI_YU12SEP);
case SV_PARAM_FINALFORMAT:
return((qword)BI_YU12SEP);
case SV_PARAM_QUALITY:
return((qword)Info->h261->quality);
}
return((qword)0);
}
float svH261GetParamFloat(SvHandle_t Svh, SvParameter_t param)
{
SvCodecInfo_t *Info = (SvCodecInfo_t *)Svh;
if (!Svh)
return((float)0.0);
if (Info->mode == SV_H261_ENCODE)
switch (param)
{
case SV_PARAM_FPS:
return((float)Info->h261->frame_rate);
}
else if (Info->mode == SV_H261_DECODE)
switch (param)
{
case SV_PARAM_FPS:
return((float)Info->h261->frame_rate);
}
return((float)svH261GetParamInt(Svh, param));
}
SvStatus_t svH261SetParamBoolean(SvHandle_t Svh, SvParameter_t param,
ScBoolean_t value)
{
SvCodecInfo_t *Info = (SvCodecInfo_t *)Svh;
if (!Svh)
return(0);
#if 0
if (Info->mode == SV_H261_ENCODE)
switch (param)
{
}
#endif
return(SvErrorNone);
}
ScBoolean_t svH261GetParamBoolean(SvHandle_t Svh, SvParameter_t param)
{
SvCodecInfo_t *Info = (SvCodecInfo_t *)Svh;
if (!Svh)
return(0);
if (Info->mode == SV_H261_ENCODE)
switch (param)
{
case SV_PARAM_BITSTREAMING:
return(TRUE);
}
else if (Info->mode == SV_H261_DECODE)
switch (param)
{
case SV_PARAM_BITSTREAMING:
return(TRUE);
}
return(FALSE);
}