/* 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 #include #include #include "SC_err.h" #include "sv_intrn.h" #include "sv_h261.h" #include "proto.h" #include "sv_proto.h" #ifdef WIN32 #include #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; iNumberGOB; 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); }