|
|
/* File: sv_h261_compress.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. ** ******************************************************************************/ /*
#define VIC 1
#define USE_C
#define _SLIBDEBUG_
*/
#include <math.h>
#include "sv_intrn.h"
#include "SC.h"
#include "SC_conv.h"
#include "SC_err.h"
#include "sv_h261.h"
#include "proto.h"
#include "sv_proto.h"
#ifdef WIN32
#include <mmsystem.h>
#endif
#ifdef _SLIBDEBUG_
#include <stdio.h>
#include <stdlib.h>
#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
#define Limit_Alpha(x) ( (x>20.0) ? 20.0 : ((x<0.5) ? 0.5 : x) )
#define Limit_Bits(x) ( (x>250.0) ? 250.0 : ((x<5.0) ? 5.0 : x) )
#define Bpos_Y(h261, g, m) (h261->ImageType==IT_QCIF ? (g * 33) + (m % 33) \
: (g/2)*66 + (m % 11) + (g&1)*11 + (m/11) * 22) static void ExecuteQuantization_GOB(); void CopySubClip_C(); void CopyRev_C(); #define SKIP_THRESH 0.51
#define SKIP_THRESH_INT 2
#define QUANT_CHANGE_THRESH 100.0
#define Intra_Start 1
#define FC 6.6e-9
#define TotalCodedMB_Threshold 2
/* MC Threshold for coding blocks through filter*/
#define D_FILTERTHRESHOLD 1
/* Intra forced every so many blocks */
#define SEQUENCE_INTRA_THRESHOLD 131
extern int bit_set_mask[]; int QuantMType[] = {0,1,0,1,0,0,1,0,0,1}; /* Quantization used */ int CBPMType[] = {0,0,1,1,0,1,1,0,1,1}; /* CBP used in coding */ int IntraMType[] = {1,1,0,0,0,0,0,0,0,0}; /* Intra coded macroblock */ int MFMType[] = {0,0,0,0,1,1,1,1,1,1}; /* Motion forward vector used */ int FilterMType[] = {0,0,0,0,0,0,0,1,1,1}; /* Filter flags */ int TCoeffMType[] = {1,1,1,1,0,1,1,0,1,1}; /* Transform coeff. coded */
struct CodeBook { float AcEnergy; float BitsMB; float QuantClass; } CBook[100] = { (float)3.057549, (float)13.650990, (float)16.000000, (float)2.736564, (float)15.620879, (float)10.000000, (float)3.032565, (float)13.728155, (float)14.000000, (float)2.945122, (float)14.390745, (float)17.000000, (float)4.236328, (float)25.890757, (float)17.000000, (float)2.935733, (float)14.596116, (float)18.000000, (float)2.994938, (float)14.515091, (float)19.000000, (float)3.440835, (float)15.698944, (float)21.000000, (float)3.235103, (float)13.875000, (float)22.000000, (float)3.362380, (float)11.448718, (float)23.000000, (float)4.262544, (float)17.246819, (float)23.000000, (float)3.933512, (float)15.207619, (float)25.000000, (float)3.825050, (float)14.351406, (float)26.000000, (float)3.840182, (float)14.048289, (float)27.000000, (float)3.717020, (float)14.076046, (float)28.000000, (float)3.942766, (float)14.216071, (float)29.000000, (float)3.934838, (float)13.509554, (float)30.000000, (float)3.899720, (float)14.233502, (float)31.000000, (float)2.737911, (float)16.522635, (float)5.000000, (float)2.607979, (float)15.374468, (float)6.000000, (float)2.864391, (float)15.432000, (float)7.000000, (float)2.752342, (float)15.809941, (float)8.000000, (float)2.682438, (float)16.186302, (float)9.000000, (float)3.581855, (float)34.849625, (float)10.000000, (float)2.853593, (float)14.700565, (float)11.000000, (float)2.908124, (float)14.091216, (float)12.000000, (float)3.099578, (float)15.157043, (float)15.000000, (float)3.916690, (float)23.636772, (float)16.000000, (float)5.574149, (float)251.866074, (float) 5.000000, (float)3.964282, (float)25.137724, (float)18.000000, (float)4.080521, (float)24.059999, (float)19.000000, (float)5.759516, (float)37.446808, (float)19.000000, (float)7.210877, (float)58.061539, (float)19.000000, (float)2.878292, (float)13.737089, (float)20.000000, (float)4.076149, (float)22.525490, (float)20.000000, (float)5.269855, (float)24.170732, (float)22.000000, (float)7.206488, (float)30.965218, (float)23.000000, (float)8.118586, (float)40.752293, (float)22.000000, (float)3.133760, (float)12.679641, (float)24.000000, (float)4.624318, (float)18.820961, (float)24.000000, (float)7.050338, (float)30.319149, (float)24.000000, (float)6.955218, (float)28.934525, (float)25.000000, (float)6.830490, (float)24.564627, (float)26.000000, (float)6.244225, (float)22.895706, (float)27.000000, (float)8.060182, (float)32.934959, (float)26.000000, (float)6.349021, (float)23.500000, (float)28.000000, (float)6.514215, (float)23.680555, (float)29.000000, (float)8.116955, (float)36.047619, (float)28.000000, (float)6.143418, (float)19.691589, (float)30.000000, (float)6.238575, (float)20.666666, (float)31.000000, (float)8.063477, (float)28.651785, (float)31.000000, (float)10.753970, (float)45.786884, (float)30.000000, (float)2.728013, (float)14.628572, (float)3.000000, (float)2.851330, (float)14.559524, (float)4.000000, (float)2.524028, (float)28.197674, (float)3.000000, (float)2.218242, (float)38.810001, (float)5.000000, (float)2.457342, (float)53.670456, (float)5.000000, (float)2.437406, (float)33.156628, (float)6.000000, (float)2.861240, (float)33.810810, (float)7.000000, (float)2.996593, (float)46.674419, (float)7.000000, (float)3.321854, (float)60.000000, (float)6.000000, (float)3.035449, (float)35.875000, (float)8.000000, (float)3.199618 , (float)33.715328, (float)9.000000, (float)3.625941, (float)50.168674, (float)9.000000, (float)3.577415, (float)60.454544, (float)8.000000, (float)4.022958, (float)50.719299, (float)10.000000, (float)4.749763, (float)69.863640, (float)10.000000, (float)3.209624, (float)24.840708, (float)11.000000, (float)3.293082, (float)22.490385, (float)12.000000, (float)3.845358, (float)34.169117, (float)12.000000, (float)4.811161, (float)38.609524, (float)13.000000, (float)4.716694, (float)49.273685, (float)11.000000, (float)5.540541, (float)68.905403, (float)11.000000, (float)2.989831, (float)13.654839, (float)13.000000, (float)3.670721, (float)23.812500, (float)13.000000, (float)3.589297, (float)21.033333, (float)14.000000, (float)4.645432, (float)30.153847, (float)14.000000, (float)4.498426, (float)30.930555, (float)15.000000, (float)4.926270, (float)35.812500, (float)16.000000, (float)5.255817, (float)43.228260, (float)14.000000, (float)6.547225, (float)57.948719, (float)14.000000, (float)6.379679, (float)71.934067, (float) 12.000000, (float)7.022222, (float)76.955559, (float)14.000000, (float)6.077474, (float)46.511112, (float)16.000000, (float)7.406376, (float)79.258064, (float)16.000000, (float)2.280469, (float)64.266670, (float)3.000000, (float)2.396216, (float)75.647057, (float)4.000000, (float)3.033032, (float)74.105263, (float)6.000000, (float)3.093046, (float)90.606560, (float)5.000000, (float)3.843145, (float)79.211266, (float)7.000000, (float)4.781610, (float)87.513161, (float)9.000000, (float)3.846819, (float)101.846939, (float)7.000000, (float)4.856852, (float)114.625000, (float)8.000000, (float)5.609015, (float)90.250000, (float)10.000000, (float)7.049340, (float)97.333336, (float)12.000000, (float)6.508484, (float)113.569893, (float) 10.000000, (float)7.099700, (float)136.116272, (float)10.000000, (float)8.087169, (float)100.054344, (float)13.000000, (float)9.193896, (float)135.032974, (float)12.000000, (float)11.427065, (float)162.600006, (float)14.000000 };
#define Abs(value) ( (value < 0) ? (-value) : value)
#define BufferContents() (ScBSBitPosition(bs) + H261->BufferOffset -\
(((H261->CurrentGOB*H261->NumberMDU)+H261->CurrentMDU) \ *H261->bit_rate*H261->FrameSkip\ /(H261->NumberGOB*H261->NumberMDU*H261->FrameRate_Fix)))
#define BufferSize() (H261->bit_rate/1) /*In bits */
/******** For sending RTP info. ************/
static SvStatus_t sv_H261WriteExtBitstream(SvH261Info_t *H261, ScBitstream_t *bs);
extern ScStatus_t ScConvert422ToYUV_char (u_char *RawImage, u_char *Y, u_char *U, u_char *V, int Width, int Height);
/***** forward declarations ******/ static SvStatus_t p64EncodeFrame(SvCodecInfo_t *Info, u_char *InputImage, u_char *CompData); static SvStatus_t p64EncodeGOB(SvH261Info_t *H261, ScBitstream_t *bs); static SvStatus_t p64EncodeMDU (SvH261Info_t *H261, ScBitstream_t *bs); static SvStatus_t p64CompressMDU(SvH261Info_t *H261, ScBitstream_t *bs); static void ExecuteQuantization_GOB(SvH261Info_t *H261); static int findcode(SvH261Info_t *H261, struct CodeBook *lcb); static SvStatus_t ntsc_grab (u_char *RawImage, u_char *Comp1, u_char *Comp2, u_char *Comp3, int Width, int Height); static void VertSubSampleK (unsigned char *Incomp, unsigned char *workloc, int Width, int Height);
#if 0
SvStatus_t SvSetFrameSkip (SvHandle_t Svh, int FrameSkip) { SvCodecInfo_t *Info = (SvCodecInfo_t *)Svh; SvH261Info_t *H261 = (SvH261Info_t *) Info->h261;
H261->FrameSkip = FrameSkip;
return (NoErrors); }
SvStatus_t SvSetFrameCount (SvHandle_t Svh, int FrameCount) { SvCodecInfo_t *Info = (SvCodecInfo_t *)Svh; SvH261Info_t *H261 = (SvH261Info_t *) Info->h261;
H261->LastFrame = FrameCount; return (NoErrors); }
SvStatus_t SvSetSearchLimit (SvHandle_t Svh, int SearchLimit) { SvCodecInfo_t *Info = (SvCodecInfo_t *)Svh; SvH261Info_t *H261 = (SvH261Info_t *) Info->h261;
if ((SearchLimit <= 0) || (SearchLimit > 20)) return (SvErrorBadArgument); H261->search_limit = SearchLimit; return (NoErrors); }
SvStatus_t SvSetMotionEstimationType (SvHandle_t Svh, int MotionEstType) { SvCodecInfo_t *Info = (SvCodecInfo_t *)Svh; SvH261Info_t *H261 = (SvH261Info_t *) Info->h261;
if (MotionEstType < 0) return (SvErrorBadArgument); H261->ME_method = MotionEstType; return (NoErrors); }
SvStatus_t SvSetMotionThreshold (SvHandle_t Svh, int Threshold) { SvCodecInfo_t *Info = (SvCodecInfo_t *)Svh; SvH261Info_t *H261 = (SvH261Info_t *) Info->h261;
if (Threshold < 0) return (SvErrorBadArgument); H261->ME_threshold = Threshold; return (NoErrors); }
SvStatus_t SvSetImageType (SvHandle_t Svh, int ImageType) { SvCodecInfo_t *Info = (SvCodecInfo_t *)Svh; SvH261Info_t *H261 = (SvH261Info_t *) Info->h261; int i;
if (!Info) return (SvErrorCodecHandle);
H261->ImageType = ImageType;
switch(H261->ImageType) { case IT_NTSC: H261->NumberGOB = 10; /* Parameters for NTSC design */ H261->NumberMDU = 33; H261->YWidth = 352; H261->YHeight = 240; H261->CWidth = H261->YWidth/2; H261->CHeight = H261->YHeight/2; break; case IT_CIF: H261->NumberGOB = 12; /* Parameters for CIF design */ H261->NumberMDU = 33; H261->YWidth = 352; H261->YHeight = 288; H261->CWidth = H261->YWidth/2; H261->CHeight = H261->YHeight/2; break; case IT_QCIF: H261->NumberGOB = 3; /* Parameters for QCIF design */ H261->NumberMDU = 33; H261->YWidth = 176; H261->YHeight = 144; H261->CWidth = H261->YWidth/2; H261->CHeight = H261->YHeight/2; break; default: /*WHEREAMI();*/ _SlibDebug(_VERIFY_, printf("Unknown ImageType: %d\n",H261->ImageType) ); return (SvErrorUnrecognizedFormat); } H261->YW4 = H261->YWidth/4; H261->CW4 = H261->CWidth/4; H261->LastIntra = (unsigned char **) ScCalloc(H261->NumberGOB*sizeof(unsigned char *));
for(i=0;i<H261->NumberGOB;i++) { H261->LastIntra[i] = (unsigned char *) ScCalloc(H261->NumberMDU*sizeof(unsigned char)); memset(H261->LastIntra[i],0,H261->NumberMDU); } _SlibDebug(_VERBOSE_, printf("H261->NumberGOB=%d\n",H261->NumberGOB) );
switch(H261->ImageType) { case IT_NTSC: H261->PType=0x04; H261->PSpareEnable=1; H261->PSpare=0x8c; break; case IT_CIF: H261->PType=0x04; break; case IT_QCIF: H261->PType=0x00; break; default: /*WHEREAMI();*/ _SlibDebug(_VERIFY_, printf("Image Type not supported: %d\n", H261->ImageType) ); return (SvErrorUnrecognizedFormat); } return (NoErrors); } #endif
SvStatus_t svH261CompressFree(SvHandle_t Svh) { SvCodecInfo_t *Info = (SvCodecInfo_t *)Svh; SvH261Info_t *H261 = (SvH261Info_t *) Info->h261; if (!H261->inited) return(NoErrors);
if (H261->CurrentFrame > H261->LastFrame+1) H261->CurrentFrame = H261->LastFrame+1; H261->TemporalReference = H261->CurrentFrame % 32; H261->ByteOffset = 0; WritePictureHeader(H261, Info->BSOut);
sv_H261HuffFree(Info->h261); if (Info->h261->LastIntra) { int i; for(i=0; i<Info->h261->NumberGOB; i++) ScFree(Info->h261->LastIntra[i]); ScFree(Info->h261->LastIntra); } if (Info->h261->Y) ScFree(Info->h261->Y); if (Info->h261->U) ScFree(Info->h261->U); if (Info->h261->V) ScFree(Info->h261->V); if (Info->h261->YREF) ScFree(Info->h261->YREF); if (Info->h261->UREF) ScFree(Info->h261->UREF); if (Info->h261->VREF) ScFree(Info->h261->VREF); if (Info->h261->YRECON) ScFree(Info->h261->YRECON); if (Info->h261->URECON) ScFree(Info->h261->URECON); if (Info->h261->VRECON) ScFree(Info->h261->VRECON); if (Info->h261->YDEC) ScFree(Info->h261->YDEC); if (Info->h261->UDEC) ScFree(Info->h261->UDEC); if (Info->h261->VDEC) ScFree(Info->h261->VDEC); if (Info->h261->workloc) ScFree(Info->h261->workloc); if (Info->h261->RTPInfo) ScFree(Info->h261->RTPInfo);
H261->inited=FALSE; return (NoErrors); }
SvStatus_t SvGetFrameNumber (SvHandle_t Svh, u_int *FrameNumber) { SvCodecInfo_t *Info = (SvCodecInfo_t *)Svh; *FrameNumber = Info->h261->CurrentFrame; return (NoErrors); }
/*
** Purpose: Writes the RTP payload info out to the stream. */ static SvStatus_t sv_H261WriteExtBitstream(SvH261Info_t *H261, ScBitstream_t *bs) { ScBSPosition_t NumberBits, i;
/* use this macro to byte reverse words */ #define PutBits32(BS, a) ScBSPutBits(BS, (a) & 0xff, 8); \
ScBSPutBits(BS, (a>>8)&0xff, 8); \ ScBSPutBits(BS, (a>>16)&0xff, 8); \ ScBSPutBits(BS, (a>>24)&0xff, 8);
/* Need to bitstuff here to make sure that these structures are
DWORD aligned */ NumberBits=ScBSBitPosition(bs); if ((NumberBits%32)!=0) ScBSPutBits(bs, 0, 32-((unsigned int)NumberBits % 32)); /* align on a DWORD boundary */
for (i = 0; i < (int)H261->RTPInfo->trailer.dwNumberOfPackets; i++) { ScBSPutBits(bs,0,32) ; /* dwFlags */ PutBits32(bs,H261->RTPInfo->bsinfo[i].dwBitOffset); ScBSPutBits(bs,H261->RTPInfo->bsinfo[i].MBAP,8); ScBSPutBits(bs,H261->RTPInfo->bsinfo[i].Quant,8); ScBSPutBits(bs,H261->RTPInfo->bsinfo[i].GOBN,8); ScBSPutBits(bs,H261->RTPInfo->bsinfo[i].HMV,8); ScBSPutBits(bs,H261->RTPInfo->bsinfo[i].VMV,8); ScBSPutBits(bs,0,8); /* padding0 */ ScBSPutBits(bs,0,16); /* padding1 */ } /* write RTP extension trailer */ PutBits32(bs, H261->RTPInfo->trailer.dwVersion); PutBits32(bs, H261->RTPInfo->trailer.dwFlags); PutBits32(bs, H261->RTPInfo->trailer.dwUniqueCode); PutBits32(bs, (H261->RTPInfo->trailer.dwCompressedSize+7)/8); /*tfm - padded up to whole byte */ PutBits32(bs, H261->RTPInfo->trailer.dwNumberOfPackets);
ScBSPutBits(bs, H261->RTPInfo->trailer.SourceFormat, 8); ScBSPutBits(bs, H261->RTPInfo->trailer.TR, 8); ScBSPutBits(bs, H261->RTPInfo->trailer.TRB, 8); ScBSPutBits(bs, H261->RTPInfo->trailer.DBQ, 8);
return (NoErrors); }
/*
** Function: svH261Compress() ** Purpose: Encodes a single H261 image frame. */ SvStatus_t svH261Compress(SvCodecInfo_t *Info, u_char *InputImage) { SvH261Info_t *H261=Info->h261; ScBitstream_t *bs=Info->BSOut; SvStatus_t status; int i1, i2, tBuff; int iGOB, iMDU, iMBpos, MiniFlag; unsigned char *dummy_y, *dummy_u, *dummy_v; double xValue,yValue;
_SlibDebug(_DEBUG_, printf("p64EncodeFrame(Info=%p, H261=%p)\n",Info, H261) ); if (H261->CurrentFrame == 0) H261->GQuant=H261->MQuant=H261->InitialQuant; H261->ByteOffset = 0;
if((H261->CurrentFrame != H261->StartFrame) && H261->NoSkippedFrame) { dummy_y = H261->YRECON; dummy_u = H261->URECON; dummy_v = H261->VRECON; H261->YRECON = H261->YDEC; H261->URECON = H261->UDEC; H261->VRECON = H261->VDEC; H261->YDEC = dummy_y; H261->UDEC = dummy_u; H261->VDEC = dummy_v; /* memset(H261->YDEC, 0,( H261->PICSIZE ) );
memset(H261->UDEC, 0,( H261->PICSIZEBY4) ); memset(H261->VDEC, 0,( H261->PICSIZEBY4 ) ); */ /*
dummy_y = H261->YREF; dummy_u = H261->UREF; dummy_v = H261->VREF;
H261->YREF = H261->Y; H261->UREF = H261->U; H261->VREF = H261->V;
H261->Y = dummy_y; H261->U = dummy_u; H261->V = dummy_v; */ _SlibDebug(_DEBUG_, printf("LastBits=%d NBitsPerFrame=%d\n", H261->LastBits, H261->NBitsPerFrame) ); if (H261->NBitsPerFrame) { H261->OverFlow = (int)((double) H261->LastBits/ (double) H261->NBitsPerFrame + 0.5); H261->OverFlow -= 1; if(H261->OverFlow >0) { H261->alpha1 += 2.2* H261->OverFlow; H261->alpha2 -= 3.2* H261->OverFlow; H261->MIN_MQUANT += 1; H261->alpha1 = Limit_Alpha(H261->alpha1); H261->alpha2 = Limit_Alpha(H261->alpha2); }
if(H261->OverFlow<0) H261->OverFlow=0; if(H261->OverFlow>2) H261->OverFlow=2; } else H261->OverFlow=0; H261->C_U_Frames += H261->OverFlow; H261->CurrentFrame += H261->OverFlow*H261->FrameSkip; } _SlibDebug(_VERBOSE_, printf("Currently Encoding Frame No. %d\n", H261->CurrentFrame) );
if (IsYUV422Packed(Info->InputFormat.biCompression)) { /* Input is in NTSC format, convert */ if ((Info->InputFormat.biWidth == NTSC_WIDTH) && (Info->InputFormat.biHeight == NTSC_HEIGHT)) status = ntsc_grab ((unsigned char *)InputImage, (unsigned char *)(H261->Y), (unsigned char *)(H261->U), (unsigned char *)(H261->V), (int) Info->Width,(int )Info->Height); else if (((Info->InputFormat.biWidth == CIF_WIDTH) && (Info->InputFormat.biHeight == CIF_HEIGHT)) || ((Info->InputFormat.biWidth == QCIF_WIDTH) && (Info->InputFormat.biHeight == QCIF_HEIGHT))) status = ScConvert422ToYUV_char(InputImage, (unsigned char *)(H261->Y), (unsigned char *)(H261->U), (unsigned char *)(H261->V), Info->Width,Info->Height); if (status != NoErrors) return (status); } else if (IsYUV411Sep(Info->InputFormat.biCompression)) { /*
* If YUV 12 SEP, Not converting, so just copy data to the luminance * and chrominance appropriatelyi */ memcpy (H261->Y, InputImage, H261->PICSIZE ); memcpy (H261->U, InputImage+( H261->PICSIZE), H261->PICSIZE/4 ); memcpy (H261->V, InputImage+(H261->PICSIZE + (H261->PICSIZEBY4)), H261->PICSIZE/4); } else if (IsYUV422Sep(Info->InputFormat.biCompression)) { _SlibDebug(_DEBUG_, printf("ScConvert422PlanarTo411()\n") ); ScConvert422PlanarTo411(InputImage, H261->Y, H261->U, H261->V, Info->Width,Info->Height); } else { _SlibDebug(_WARN_, printf("Unsupported Video format\n") ); return(SvErrorUnrecognizedFormat); }
H261->Global_Avg = 0.0; if ((H261->CodedFrames >= Intra_Start) && !H261->makekey ) { if (H261->ME_method==ME_BRUTE) BruteMotionEstimation(H261, H261->YREF, H261->YRECON, H261->Y); else Logsearch(H261, H261->YREF, H261->YRECON, H261->Y); /*
CrawlMotionEstimation(H261, H261->YREF, H261->YRECON, H261->Y); */ memset(H261->CodedMB, 1, 512); H261->TotalCodedMB_Intra = 0; H261->TotalCodedMB_Inter = 0; H261->ChChange = 0; for(iGOB=0; iGOB < H261->NumberGOB; iGOB++) { _SlibDebug(_DEBUG_, printf("ByteOffset = %d\n",H261->ByteOffset) ); for (iMDU=0; iMDU<H261->NumberMDU; iMDU++) { iMBpos = Bpos_Y(H261, iGOB, iMDU); if(H261->MeOVal[iMBpos] < SKIP_THRESH_INT) { H261->CodedMB[iMBpos] = 0; MiniFlag = 0; } else if (H261->MeOVal[iMBpos] <= H261->MeVal[iMBpos]) { if ((H261->PreviousMeOVal[iMBpos]-H261->ActThr2<H261->MeOVal[iMBpos]) && (H261->MeOVal[iMBpos] < (H261->PreviousMeOVal[iMBpos]+ H261->ActThr2))) { if (((H261->PreviousMeOVal[iMBpos]-H261->ActThr) < H261->MeOVal[iMBpos]) && (H261->MeOVal[iMBpos] < (H261->PreviousMeOVal[iMBpos] + H261->ActThr))) { MiniFlag = 0; H261->CodedMB[iMBpos] = 0; } else { H261->ChChange++; MiniFlag = 1; } } else MiniFlag = 1; } else MiniFlag = 1;
if (MiniFlag) { xValue = (double) H261->MeOVal[iMBpos]; yValue = (double) H261->MeVal[iMBpos]; xValue = xValue/256; yValue = yValue/256; H261->VARF = 3*H261->MeVAR[iMBpos]/(512.); H261->VARORF = 3*H261->MeVAROR[iMBpos]/(512.); H261->VARSQ = H261->VARF*H261->VARF; H261->VARORSQ = H261->VARORF*H261->VARORF; H261->MWOR = H261->MeMWOR[iMBpos]; if ((H261->VARSQ < H261->ZBDecide) || (H261->VARORSQ > H261->VARSQ)) { /* (MC+Inter)mode */ if ( !H261->MeX[iMBpos] && !H261->MeY[iMBpos] && (xValue < 0.75 || (xValue < 2.8 && yValue > (xValue*0.5)) || yValue > (xValue/1.1)) ) { H261->All_MType[iMBpos] = 2; /* Inter mode */ H261->TotalCodedMB_Inter++; H261->Global_Avg += H261->VARF; } else if (H261->VARF < (double) D_FILTERTHRESHOLD) /* MC mode */ { H261->All_MType[iMBpos] = 5; /* No Filter MC */ H261->TotalCodedMB_Inter++; H261->Global_Avg += H261->VARF; } else { H261->All_MType[iMBpos] = 8; /* Filter MC */ H261->TotalCodedMB_Inter++; H261->Global_Avg += H261->VARF; } } else { H261->All_MType[iMBpos] = 0; /*Intramode */ H261->TotalCodedMB_Intra++; H261->Global_Avg += H261->VARORF; } } if (H261->LastIntra[iGOB][iMDU]>SEQUENCE_INTRA_THRESHOLD) { H261->All_MType[iMBpos]=0; /* Code intra every 132 blocks */ H261->TotalCodedMB_Intra++; H261->Global_Avg += H261->VARF; } } } } else { memset(H261->CodedMB, 0, 512); H261->TotalCodedMB_Intra = 0; H261->TotalCodedMB_Inter = 0; if(H261->CodedFrames==0) i1 = 0; else i1 = (H261->NumberGOB/Intra_Start)*H261->CodedFrames; i2 = (H261->NumberGOB/Intra_Start)*(H261->CodedFrames+1);
if(H261->makekey){ i1 = 0; i2 = H261->NumberGOB; }
for(iGOB=i1; iGOB<i2; iGOB++) { _SlibDebug(_DEBUG_, printf("ByteOffset = %d\n", H261->ByteOffset) ); for(iMDU=0; iMDU<H261->NumberMDU; iMDU++) { iMBpos = Bpos_Y(H261, iGOB, iMDU); H261->All_MType[iMBpos] = 0; H261->CodedMB[iMBpos] = 1; H261->TotalCodedMB_Intra++; H261->Global_Avg += H261->VARF; } } } H261->TotalCodedMB = H261->TotalCodedMB_Intra + H261->TotalCodedMB_Inter/2; H261->TT_MB = H261->TotalCodedMB_Intra + H261->TotalCodedMB_Inter - H261->ChChange; if (H261->TT_MB) /* watch out for divide by 0 */ H261->Global_Avg = H261->Global_Avg/H261->TT_MB; _SlibDebug(_DEBUG_, printf("TT_MB = %d Global_Avg=%d\n", H261->TT_MB, H261->Global_Avg) ); H261->Current_CodedMB[0] = 0; H261->Current_CodedMB[1] = 0; if(H261->C_U_Frames==0) H261->BitsLeft = 0; H261->BitsLeft = H261->BitsLeft - H261->Buffer_NowPic; tBuff = H261->PBUFF - (H261->C_U_Frames%H261->PBUFF); if(tBuff >= H261->Pictures_in_Buff) { H261->Pictures_in_Buff = tBuff; if (H261->BitsLeft < - H261->Buffer_All/3) H261->BitsLeft = H261->Buffer_All; else if (H261->BitsLeft > 2*H261->Buffer_All) H261->BitsLeft = H261->Buffer_All; else H261->BitsLeft = H261->BitsLeft + H261->Buffer_All; H261->NBitsCurrentFrame = H261->BitsLeft/H261->Pictures_in_Buff; } H261->Pictures_in_Buff = tBuff; if(H261->BitsLeft > 2*H261->Buffer_All) { _SlibDebug(_DEBUG_, printf("\n Bits Left is %f times more than Buffer_All", (float)H261->BitsLeft/(float) H261->Buffer_All) ); H261->BitsLeft = H261->Buffer_All; if(H261->MIN_MQUANT > 2) H261->MIN_MQUANT -= 1; } H261->NBitsCurrentFrame = H261->BitsLeft/H261->Pictures_in_Buff; H261->LowerQuant = 0; H261->FineQuant = 0; H261->ActThr = H261->ActThr5; H261->ActThr2 = H261->ActThr6;
if (H261->bit_rate < 128001) if (H261->NBitsCurrentFrame > (5*H261->NBitsPerFrame/3)) H261->NBitsCurrentFrame = 5*H261->NBitsPerFrame/4; else if (H261->NBitsCurrentFrame > 5*H261->NBitsPerFrame/4) { if((H261->frame_rate<=15) && (H261->bit_rate > 255000)) { H261->NBitsCurrentFrame = 5*H261->NBitsPerFrame/4; H261->FineQuant = 3; H261->ActThr = H261->ActThr3; H261->ActThr2 = H261->ActThr4; } else if (H261->frame_rate==30) { H261->FineQuant = 0; H261->ActThr = H261->ActThr4; H261->ActThr2 = H261->ActThr4; H261->NBitsCurrentFrame = 5*H261->NBitsPerFrame/4; } }
H261->Buffer_NowPic = 0; H261->MQuant = H261->GQuant;
_SlibDebug(_DEBUG_, printf("GQuant for this picture is %d\n", H261->GQuant) ); H261->TemporalReference = H261->CurrentFrame % 32; if(H261->TotalCodedMB > TotalCodedMB_Threshold) { /* TRAILER information */ if (H261->extbitstream) { /* H261->RTPInfo->trailer.dwSrcVersion = 0; */ H261->RTPInfo->trailer.dwVersion = 0; if(H261->CurrentFrame == H261->StartFrame) H261->RTPInfo->trailer.dwFlags = RTP_H261_INTRA_CODED; else H261->RTPInfo->trailer.dwFlags = 0; H261->RTPInfo->trailer.dwUniqueCode = BI_DECH261DIB; H261->RTPInfo->trailer.dwNumberOfPackets = 0;
if(H261->ImageType == IT_QCIF) H261->RTPInfo->trailer.SourceFormat = 2; else H261->RTPInfo->trailer.SourceFormat = 3; H261->RTPInfo->trailer.TR = (unsigned char)H261->TemporalReference; H261->RTPInfo->trailer.TRB = 0; H261->RTPInfo->trailer.DBQ = 0; H261->RTPInfo->pre_MB_position=H261->RTPInfo->last_packet_position=ScBSBitPosition(bs); H261->RTPInfo->pre_MB_GOB = 0; H261->RTPInfo->pre_MBAP = 0; /* store the picture start pos in dwCompressSize,
we'll subtract from this later */ H261->RTPInfo->trailer.dwCompressedSize = (unsigned dword)ScBSBitPosition(bs); }
H261->CodedFrames++; H261->C_U_Frames++; WritePictureHeader(H261, bs); H261->Buffer_NowPic += 32; for (H261->CurrentGOB=0; H261->CurrentGOB<H261->NumberGOB; H261->CurrentGOB++) { H261->CurrentMDU=0; _SlibDebug(_DEBUG_, printf("p64EncodeGOB() ByteOffset = %d\n", H261->ByteOffset) ); status = p64EncodeGOB(H261, bs); if (status != NoErrors) return (status); } { ScBSPosition_t x = ScBSBitPosition(bs); /* mwtellb(H261); */ H261->LastBits = x - H261->TotalBits; H261->TotalBits = x;
if (H261->extbitstream) H261->RTPInfo->trailer.dwCompressedSize = (unsigned dword)(x-H261->RTPInfo->trailer.dwCompressedSize); }
_SlibDebug(_DEBUG_, printf("after mwtellb() LastBits=%d TotalBits=%d\n", H261->LastBits, H261->TotalBits) ); if (H261->bit_rate) { if (H261->CurrentFrame==H261->StartFrame) { /* Begin Buffer at 0.5 size */ H261->FirstFrameBits = H261->TotalBits; H261->BufferOffset = (BufferSize()/2) - BufferContents(); _SlibDebug(_DEBUG_, printf("First Frame Reset Buffer by delta bits: %d\n", H261->BufferOffset) ); } /* Take off standard deduction afterwards. */ H261->BufferOffset -= (H261->bit_rate*H261->FrameSkip/H261->FrameRate_Fix); } else if (H261->CurrentFrame==H261->StartFrame) H261->FirstFrameBits = H261->TotalBits; H261->CurrentGOB=0;H261->TransmittedFrames++; H261->NoSkippedFrame = 1; H261->CurrentFrame+=H261->FrameSkip;/* Change GOB & Frame at same time */
/* write RTP info. */ if (H261->extbitstream) { SvStatus_t status; status = sv_H261WriteExtBitstream(H261, bs); if (status!=SvErrorNone) return(status); } } else { H261->NoSkippedFrame = 0; H261->CurrentFrame+=H261->FrameSkip; H261->C_U_Frames++; H261->alpha1 -= 1.50; H261->alpha2 += 1.50; H261->MIN_MQUANT -= 1; H261->alpha1 = Limit_Alpha(H261->alpha1); H261->alpha2 = Limit_Alpha(H261->alpha2); }
if(H261->makekey) H261->makekey = 0; /* disable key-frame trigger */
return (NoErrors); } /**** End of Encode Frame ****/
/*
** Function: p64EncodeGOB() ** Pupose: Encodes a group of blocks within a frame. */ static SvStatus_t p64EncodeGOB(SvH261Info_t *H261, ScBitstream_t *bs) { const int CurrentGOB=H261->CurrentGOB; const int YWidth=H261->YWidth, CWidth=H261->CWidth; int CurrentMDU, h, VIndex, HIndex; double error, stepsize; SvStatus_t status;
if (H261->extbitstream) { ScBSPosition_t cur_position;
cur_position = ScBSBitPosition(bs);
/* start a new packet */ if (H261->RTPInfo->trailer.dwNumberOfPackets==0 || (cur_position-H261->RTPInfo->last_packet_position) >= (unsigned)H261->packetsize-128) { SvH261BSInfo_t *bsinfo=&H261->RTPInfo->bsinfo[H261->RTPInfo->trailer.dwNumberOfPackets]; /* breaking packet before GOB boundaries */ H261->RTPInfo->last_packet_position = H261->RTPInfo->pre_MB_position;
H261->RTPInfo->trailer.dwNumberOfPackets++; bsinfo->dwBitOffset = (unsigned dword)H261->RTPInfo->pre_MB_position;
bsinfo->MBAP = (unsigned char)H261->RTPInfo->pre_MBAP; bsinfo->Quant = (unsigned char)H261->UseQuant; bsinfo->GOBN = (unsigned char)H261->RTPInfo->pre_MB_GOB; bsinfo->HMV = 0; bsinfo->VMV = 0; bsinfo->padding0 = 0; bsinfo->padding1 = 0; } H261->RTPInfo->pre_MB_position = cur_position; H261->RTPInfo->pre_MB_GOB = CurrentGOB; H261->RTPInfo->pre_MBAP=0; }
if(H261->bit_rate) { if(CurrentGOB==0){ H261->GQuant =8; H261->MQuant = 8; } else ExecuteQuantization_GOB(H261); } else{ /* for VBR */ if (H261->CurrentFrame==H261->StartFrame) H261->GQuant = H261->MQuant = H261->QPI; else H261->GQuant = H261->MQuant = H261->QP; }
switch (H261->ImageType) { case IT_NTSC: case IT_CIF: H261->GRead=CurrentGOB; break; case IT_QCIF: H261->GRead=CurrentGOB<<1; break; default: _SlibDebug(_VERIFY_, printf("Unknown Image Type: %d\n", H261->ImageType) ); return (SvErrorUnrecognizedFormat); } WriteGOBHeader(H261, bs);
H261->Buffer_NowPic += 26; H261->LastMBA = -1; H261->MType=0; /*
* MAIN LOOP */ for (CurrentMDU=0; CurrentMDU<H261->NumberMDU; CurrentMDU++) { H261->CurrentMDU=CurrentMDU; H261->MBpos = Bpos_Y(H261, CurrentGOB, CurrentMDU); H261->LastMType=H261->MType; H261->MType = H261->All_MType[H261->MBpos]; if((H261->MType>1) && !H261->CodedMB[H261->MBpos]) { H261->SkipMB++; if (H261->ImageType==IT_QCIF) { HIndex = (CurrentMDU % 11) * 16; VIndex = (CurrentGOB*48) + ((CurrentMDU/11) * 16); } else /* IT_CIF or NTSC */ { HIndex = ((((CurrentGOB & 1)*11)+(CurrentMDU%11))*16); VIndex = ((CurrentGOB/2)*48) + ((CurrentMDU/11) * 16); } _SlibDebug(_DEBUG_, printf ("Skipping MB... MType=%d\n", H261->MType) ); h = VIndex*YWidth; H261->VYWH = h + HIndex; H261->VYWH2 = (((h/2) + HIndex) /2); ScCopyMB16(&H261->YRECON[H261->VYWH], &H261->YDEC[H261->VYWH], YWidth, YWidth);
ScCopyMB8 (&H261->URECON[H261->VYWH2], &H261->UDEC[H261->VYWH2], CWidth, CWidth); ScCopyMB8 (&H261->VRECON[H261->VYWH2], &H261->VDEC[H261->VYWH2], CWidth, CWidth); } else { /*
* Encode a MDU - was a call to p64EncodeMDU() */ H261->Current_MBBits=0; status = p64CompressMDU(H261, bs); if (status != NoErrors) return (status);
if (H261->extbitstream) { ScBSPosition_t cur_position;
cur_position = ScBSBitPosition(bs);
/* start a new packet */ if ((cur_position-H261->RTPInfo->last_packet_position) >= (unsigned)H261->packetsize-128) { SvH261BSInfo_t *bsinfo=&H261->RTPInfo->bsinfo[H261->RTPInfo->trailer.dwNumberOfPackets]; H261->RTPInfo->last_packet_position = H261->RTPInfo->pre_MB_position;
H261->RTPInfo->trailer.dwNumberOfPackets++; bsinfo->dwBitOffset = (unsigned dword)H261->RTPInfo->pre_MB_position;
bsinfo->MBAP = (unsigned char)H261->RTPInfo->pre_MBAP; bsinfo->Quant = (unsigned char)H261->UseQuant; bsinfo->GOBN = (unsigned char)H261->RTPInfo->pre_MB_GOB; bsinfo->HMV = 0; bsinfo->VMV = 0; bsinfo->padding0 = 0; bsinfo->padding1 = 0; } H261->RTPInfo->pre_MB_position = cur_position; H261->RTPInfo->pre_MB_GOB = H261->CurrentGOB; H261->RTPInfo->pre_MBAP = H261->LastMBA; }
H261->QUse++; /* Accumulate statistics */ H261->QSum+=H261->UseQuant; if (H261->MType < 10) H261->MacroTypeFrequency[H261->MType]++; else { _SlibDebug(_VERIFY_, printf("Illegal MType: %d\n",H261->MType) ); return (SvErrorIllegalMType); } H261->Buffer_NowPic += H261->Current_MBBits; /*
H261->MyCB[H261->CurrentCBNo].BitsMB += 0.02*(H261->Current_MBBits - H261->MyCB[H261->CurrentCBNo].BitsMB); */ if (H261->MType > 1 && H261->bit_rate > 0) { error = (H261->Current_MBBits - CBook[H261->CurrentCBNo].BitsMB); if (fabs(error) > (0.2*H261->Current_MBBits)) error = CBook[H261->CurrentCBNo].BitsMB * 0.2*error/fabs(error);
if (error > 0) stepsize = 0.005/(H261->Current_MBBits*H261->bit_rate/112000.0); if (error <= 0) stepsize = 0.07/(H261->Current_MBBits*H261->bit_rate/112000.0);
CBook[H261->CurrentCBNo].BitsMB += (float)(stepsize*error); } } } return (NoErrors); } /**** End of p64EncodeGOB ****/
#if 0
/* Now done inline */ /*
** Function: p64EncodeMDU() ** Purpose: Encodes the MDU by read/compressing the MDU, then ** writing it, then decoding it and accumulating statistics. */ static SvStatus_t p64EncodeMDU (SvH261Info_t *H261, ScBitstream_t *bs) { SvStatus_t status;
H261->Current_MBBits=0; status = p64CompressMDU(H261, bs); if (status != NoErrors) return (status); H261->QUse++; /* Accumulate statistics */ H261->QSum+=H261->UseQuant; if (H261->MType < 10) H261->MacroTypeFrequency[H261->MType]++; else { _SlibDebug(_VERIFY_, printf("Illegal MType: %d\n",H261->MType) ); return (SvErrorIllegalMType); } return (NoErrors); } #endif
/* these temporary buffers are used by p64CompressMDU and
should be allocated elsewhere */ static float Idct[6][64]; static int Odct[6][64]; static float TempDct[64]; static int Dct[64];
/*
** Function: p64CompressMDU() ** Pupose: Reads in the MDU, and attempts to compress it. ** If the chosen MType is invalid, it finds the closest match. */ static SvStatus_t p64CompressMDU(SvH261Info_t *H261, ScBitstream_t *bs) { const int CurrentGOB=H261->CurrentGOB, CurrentMDU=H261->CurrentMDU; const int YWidth=H261->YWidth, CWidth=H261->CWidth; const int YW4=H261->YW4, CW4 = H261->CW4; int j, x, tQuant, indQ, VIndex, HIndex, MType; int accum, pmask, CBPFlag, *input; SvStatus_t status; int inputbuf[10][64]; unsigned int *y0ptr, *y1ptr, *y2ptr, *y3ptr; unsigned int *uptr, *vptr; unsigned int *y0ptr_dec, *y1ptr_dec, *y2ptr_dec,*y3ptr_dec; unsigned int *uptr_dec, *vptr_dec;
if (H261->ImageType==IT_QCIF) { HIndex = (CurrentMDU % 11) * 16; VIndex = (CurrentGOB*48) + ((CurrentMDU/11) * 16); } else /* IT_CIF or NTSC */ { HIndex = ((((CurrentGOB & 1)*11)+(CurrentMDU%11))*16); VIndex = ((CurrentGOB/2)*48) + ((CurrentMDU/11) * 16); } H261->MQFlag = 0; if(H261->MType < 2) H261->Avg_AC = H261->MeVAROR[H261->MBpos]/256.0; else H261->Avg_AC = H261->MeVAR[H261->MBpos]/256.0;
H261->MVDH = H261->MeX[H261->MBpos]; H261->MVDV = H261->MeY[H261->MBpos];
H261->VYWH = (VIndex*YWidth) + HIndex; H261->VYWH2 = ((((VIndex*YWidth)/2) + HIndex) /2);
H261->VYWHMV = H261->VYWH + H261->MVDH + (H261->MVDV*YWidth); H261->VYWHMV2 = H261->VYWH2 + ((H261->MVDV/2)*CWidth) + (H261->MVDH/2);
y0ptr = (unsigned int *) (H261->Y + H261->VYWH); y1ptr = y0ptr + 2; y2ptr = y0ptr + (YWidth<<1); y3ptr = y2ptr + 2;
uptr = (unsigned int *) (H261->U + H261->VYWH2); vptr = (unsigned int *) (H261->V + H261->VYWH2);
y0ptr_dec = (unsigned int *) (H261->YDEC + H261->VYWH); y1ptr_dec = y0ptr_dec + 2; y2ptr_dec = y0ptr_dec + (YWidth<<1); y3ptr_dec = y2ptr_dec + 2;
uptr_dec = (unsigned int *) (H261->UDEC + H261->VYWH2); vptr_dec = (unsigned int *) (H261->VDEC + H261->VYWH2); tQuant = H261->MQuant;
if (CurrentMDU==0 || H261->LastMBA==-1) H261->MQuant = H261->GQuant; else { if(H261->bit_rate) ExecuteQuantization_GOB(H261);
indQ = H261->GQuant-tQuant; if (indQ < 0) indQ = indQ*2; if (Abs(indQ) < H261->MSmooth) H261->MQuant = tQuant; else { H261->MQuant = H261->GQuant; H261->MQFlag = 1; } }
if (H261->MQFlag && H261->MType!=4 && H261->MType!=7) { H261->MType++; _SlibDebug(_DEBUG_, printf("H261->MType++ == %d\n", H261->MType) ); } else _SlibDebug(_DEBUG_, printf("H261->MType == %d\n", H261->MType) ); MType=H261->MType;
H261->Current_MBBits = 0;
if (QuantMType[MType]) { if(H261->bit_rate){ /* CBR */ H261->UseQuant = H261->MQuant; H261->GQuant = H261->MQuant; /* Future MB Quant is now MQuant */ } else { /* VBR */ if (H261->CurrentFrame==H261->StartFrame || IntraMType[MType]) H261->UseQuant = H261->GQuant = H261->MQuant = H261->QPI; else H261->UseQuant = H261->GQuant = H261->MQuant = H261->QP; } } else H261->UseQuant = H261->GQuant;
/*
* WRITE */ H261->MBA = CurrentMDU - H261->LastMBA; if (TCoeffMType[MType]) { if (!IntraMType[MType]) { if (FilterMType[MType]) { ScCopyMB16(&H261->YRECON[H261->VYWHMV], &H261->mbRecY[0], YWidth, 16); ScCopyMB8 (&H261->URECON[H261->VYWHMV2],&H261->mbRecU[0], CWidth, 8); ScCopyMB8 (&H261->VRECON[H261->VYWHMV2],&H261->mbRecV[0], 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[MType]) { ScCopyMB16(&H261->YRECON[H261->VYWHMV], &H261->mbRecY[0], YWidth, 16); ScCopyMB8 (&H261->URECON[H261->VYWHMV2],&H261->mbRecU[0], CWidth, 8); ScCopyMB8 (&H261->VRECON[H261->VYWHMV2],&H261->mbRecV[0], CWidth, 8); } else { ScCopyMB16(&H261->YRECON[H261->VYWH], &H261->mbRecY[0], YWidth, 16); ScCopyMB8 (&H261->URECON[H261->VYWH2],&H261->mbRecU[0], CWidth, 8); ScCopyMB8 (&H261->VRECON[H261->VYWH2],&H261->mbRecV[0], CWidth, 8); } _SlibDebug(_DEBUG_, printf("Doing CopySub \n") ); ScCopySubClip(&H261->mbRecY[0], &Idct[0][0], y0ptr, 4, YW4); ScCopySubClip(&H261->mbRecY[8], &Idct[1][0], y1ptr, 4, YW4); ScCopySubClip(&H261->mbRecY[128], &Idct[2][0], y2ptr, 4, YW4); ScCopySubClip(&H261->mbRecY[136], &Idct[3][0], y3ptr, 4, YW4); ScCopySubClip(&H261->mbRecU[0], &Idct[4][0], uptr, 2, CW4); ScCopySubClip(&H261->mbRecV[0], &Idct[5][0], vptr, 2, CW4); } else { _SlibDebug(_DEBUG_, printf("Doing CopyRev \n") ); ScCopyRev(y0ptr, &Idct[0][0], YW4 ); ScCopyRev(y1ptr, &Idct[1][0], YW4); ScCopyRev(y2ptr, &Idct[2][0], YW4); ScCopyRev(y3ptr, &Idct[3][0], YW4); ScCopyRev(uptr, &Idct[4][0], CW4); ScCopyRev(vptr, &Idct[5][0], CW4); } }
/*
* DCT, Quantize, and Zigzag. * Dequantize and IDCT */ if (IntraMType[MType]) { _SlibDebug(_DEBUG_, printf("Doing IntraQuant\n") ); for(j=0; j<6; j++) { /* ScaleDct(&Idct[j][0],TempDct);*/ ScFDCT8x8(&Idct[j][0],TempDct); IntraQuant(TempDct, Dct, H261->UseQuant); ZigzagMatrix(Dct, &inputbuf[j][0]); Inv_Quant(Dct, H261->UseQuant, IntraMType[MType], TempDct); ScScaleIDCT8x8(TempDct, &Odct[j][0]); } } else { _SlibDebug(_DEBUG_, printf("Doing InterQuant\n") ); for(j=0; j<6; j++) { /* ScaleDct(&Idct[j][0],TempDct);*/ ScFDCT8x8(&Idct[j][0],TempDct); InterQuant(TempDct, Dct, H261->UseQuant); ZigzagMatrix(Dct, &inputbuf[j][0]); Inv_Quant(Dct, H261->UseQuant, IntraMType[MType], TempDct); ScScaleIDCT8x8(TempDct, &Odct[j][0]); } }
if (!CBPMType[MType]) { CBPFlag=0; H261->CBP = 0x3f; } else { for(pmask=0, H261->CBP=0, j=0; j<6; j++) { input = &inputbuf[j][0]; for(accum=0, x=0; x<64; x++) accum += (int)Abs(input[x]); if (accum && (pmask==0)) pmask|=bit_set_mask[5-j]; if (accum>H261->CBPThreshold) H261->CBP |= bit_set_mask[5-j]; } if (!H261->CBP) { if (pmask) H261->CBP=pmask; else if (!FilterMType[MType]) { H261->MType=4; MType=4; } else { H261->MType=7; MType=7; } } } _SlibDebug(_DEBUG_,printf("CurrentGOB=%d CurrentMDU=%d LastIntra[%d]=%p\n", CurrentGOB, CurrentMDU,CurrentGOB, H261->LastIntra[CurrentGOB]) ); if (IntraMType[MType]) H261->LastIntra[CurrentGOB][CurrentMDU]=0; else H261->LastIntra[CurrentGOB][CurrentMDU]++;
/*
* Write out the MB */ status = WriteMBHeader(H261, bs); if (status != NoErrors) return (status); H261->LastMBA = CurrentMDU; H261->TotalMB[IntraMType[MType]]++; H261->Current_CodedMB[IntraMType[MType]]++; if (TCoeffMType[MType]) for(j=0; j<6; j++) { if (H261->CBP & bit_set_mask[5-j]) { input = &inputbuf[j][0]; if (j>3) H261->UVTypeFrequency[MType]++; else H261->YTypeFrequency[MType]++; H261->CodedBlockBits=0; if (CBPMType[MType]) status = CBPEncodeAC(H261, bs, 0, input); else { EncodeDC(H261, bs, *input); H261->Current_MBBits += 8; status = EncodeAC(H261, bs, 1, input); } if (status != NoErrors) return (status); H261->Current_MBBits += H261->CurrentBlockBits; H261->MBBits[IntraMType[MType]] += H261->CodedBlockBits; if (j<4) H261->YCoefBits+=H261->CodedBlockBits; else if (j==5) H261->UCoefBits+=H261->CodedBlockBits; else H261->VCoefBits+=H261->CodedBlockBits; } } /*
* Now write it to Frame _dec !! */ if(!IntraMType[MType]) { const unsigned char CBP = (unsigned char)H261->CBP; if (CBP & 0x20) { ScCopyAddClip(&H261->mbRecY[0], &Odct[0][0], y0ptr_dec, 16, YW4); H261->CBPFreq[0]++; } else ScCopyMV8(&H261->mbRecY[0], y0ptr_dec, 16, YW4); if (CBP & 0x10) { ScCopyAddClip(&H261->mbRecY[8], &Odct[1][0],y1ptr_dec, 16, YW4); H261->CBPFreq[1]++; } else ScCopyMV8(&H261->mbRecY[8], y1ptr_dec, 16, YW4); if (CBP & 0x08) { ScCopyAddClip(&H261->mbRecY[128], &Odct[2][0], y2ptr_dec, 16, YW4); H261->CBPFreq[2]++; } else ScCopyMV8(&H261->mbRecY[128], y2ptr_dec, 16, YW4); if (CBP & 0x04) { ScCopyAddClip(&H261->mbRecY[136], &Odct[3][0], y3ptr_dec, 16, YW4); H261->CBPFreq[3]++; } else ScCopyMV8(&H261->mbRecY[136], y3ptr_dec, 16, YW4); if (CBP & 0x02) { ScCopyAddClip(&H261->mbRecU[0], &Odct[4][0], uptr_dec, 8, CW4); H261->CBPFreq[4]++; } else ScCopyMV8(&H261->mbRecU[0], uptr_dec, 8, CW4); if (CBP & 0x01) { ScCopyAddClip(&H261->mbRecV[0], &Odct[5][0], vptr_dec, 8, CW4); H261->CBPFreq[5]++; } else ScCopyMV8(&H261->mbRecV[0], vptr_dec, 8, CW4); } else { ScCopyClip(&Odct[0][0], y0ptr_dec, YW4); ScCopyClip(&Odct[1][0], y1ptr_dec, YW4); ScCopyClip(&Odct[2][0], y2ptr_dec, YW4); ScCopyClip(&Odct[3][0], y3ptr_dec, YW4); ScCopyClip(&Odct[4][0], uptr_dec, CW4); ScCopyClip(&Odct[5][0], vptr_dec, CW4); } return (NoErrors); }
#ifndef Bpos_Y
/* Now a macro */ /*
** Function: Bpos_Y() ** Purpose: Returns the designated MDU number inside of the frame of the ** installed Iob given by the input gob, mdu, horizontal and ** vertical offset. It returns 0 on error. */ static int Bpos_Y(SvH261Info_t *H261, int g, int m) { int tg; BEGIN("Bpos");
switch (H261->ImageType) { case IT_QCIF: tg = (g * 33) + (m % 33); /*
tg = (g/2) * 33 + (m%11) + (m/11)*11; */ return(tg); break; case IT_CIF: case IT_NTSC: tg = (g/2)*66 + (m % 11) + (g&1)*11 + (m/11) * 22; return(tg); break; default: /* WHEREAMI();*/ _SlibDebug(_VERIFY_, printf("Unknown image type: %d.\n",H261->ImageType) ); /* return (SvErrorUnrecognizedFormat);*/ break; } return(0); } #endif
static void ExecuteQuantization_GOB(SvH261Info_t *H261) { double si1, si2;
if(H261->TotalCodedMB) { if(H261->bit_rate) { /* CBR */ si1 = (double) H261->CurrentGOB / (double) H261->NumberGOB; si2 =(double) exp(-4.0*(si1-0.5)*(si1-0.5)) + 0.45;
if (H261->Avg_AC >= H261->Global_Avg) H261->BitsAvailableMB =(float)(si2 * H261->NBitsCurrentFrame/(1.0 *(float) H261->TT_MB) - (H261->Global_Avg - H261->Avg_AC)*2.5) ; else if (H261->Avg_AC < H261->Global_Avg) H261->BitsAvailableMB = (float)( si2* H261->NBitsCurrentFrame/ (1.0*(float) H261->TT_MB) - (H261->Global_Avg - H261->Avg_AC)*2.5 ) ;
if(H261->MType > 0) H261->LowerQuant = H261->LowerQuant_FIX; else H261->LowerQuant = 0; H261->BitsAvailableMB += H261->LowerQuant; H261->BitsAvailableMB =(float)Limit_Bits(H261->BitsAvailableMB); H261->ACE = (float) H261->Avg_AC; H261->GQuant = findcode(H261, CBook);
if(H261->FineQuant) H261->GQuant -= H261->FineQuant; if(H261->CurrentFrame == H261->StartFrame) H261->GQuant = 8; if (H261->GQuant < 1) H261->GQuant = 1; if(H261->GQuant > 28) H261->GQuant = 28; } else /* VBR */ H261->GQuant = H261->QP; } }
static int findcode(SvH261Info_t *H261, struct CodeBook *cb) { const codelength=H261->CodeLength; const float ace=H261->ACE, bmb=H261->BitsAvailableMB; int i, mincb=-1; float distance, mindist, val1, val2; struct CodeBook *lcb=cb;
H261->CurrentCBNo = 15; if((ace <=0.0) || (bmb <=0.0)) return(25); mindist = (float)1000000.0; for(i=0; i<codelength; i++) { val1=lcb->AcEnergy - ace; val2=lcb->BitsMB - bmb; distance = (val1*val1) + (val2*val2); if (distance < mindist) { mindist = distance; mincb = i; } lcb++; }
if (mincb>=0) { H261->CurrentCBNo = mincb; return((int)cb[mincb].QuantClass); } else return(25); }
/*
** Function: ntsc_grab() ** Purpose: Grab a Q/CIF frame from a 4:2:2 NTSC input. We dup every 10th ** pixel horizontally and every 4th line vertically. We also ** discard the chroma on every other line, since CIF wants 4:1:1. */ static SvStatus_t ntsc_grab (u_char *RawImage, u_char *Comp1, u_char *Comp2, u_char *Comp3, int Width, int Height) { int h, w; u_char *yp = Comp1, *up = Comp2, *vp = Comp3; int NTSC_Height = 240; int NTSC_Width = 320;
int stride = Width; int vdup = 5; for (h = 0; h < NTSC_Height; ++h) { int hdup = 10/2; for (w = NTSC_Width; w > 0; w -= 2) { yp[0] = RawImage[0]; yp[1] = RawImage[2]; yp += 2; if ((h & 1) == 0) { *up++ = RawImage[1]; *vp++ = RawImage[3]; } RawImage += 4; if (--hdup <= 0) { hdup = 10/2; yp[0] = yp[-1]; yp += 1; if ((h & 1) == 0) { if ((w & 2) == 0) { up[0] = up[-1]; ++up; vp[0] = vp[-1]; ++vp; } } } } if (--vdup <= 0) { vdup = 5; /* copy previous line */ memcpy((char*)yp, (char*)yp - stride, stride); yp += stride; if ((h & 1) == 0) { int s = stride >> 1; memcpy((char*)up, (char*)up - s, s); memcpy((char*)vp, (char*)vp - s, s); up += s; vp += s; } } } return (NoErrors); } #ifdef USE_C
static void VertSubSampleK (unsigned char *Incomp, unsigned char *workloc, int Width, int Height) { int j, i, temp;
int ByteWidth = Width * 4; for(j=0; j<(Width ); j++) { temp = Incomp[(j * 4)]*3; temp += Incomp[(j * 4)+ByteWidth]*3; temp += Incomp[(j * 4)+ByteWidth*2]; temp = temp/7; workloc[j] = (unsigned char) temp; }
for(i=2; i<(Height-2); i += 2) { for(j=0; j<(Width ); j++) { temp = Incomp[(i-1)*ByteWidth + (j * 4)]; temp += Incomp[i*ByteWidth + (j * 4)]*3; temp += Incomp[(i+1)*ByteWidth + (j * 4)]*3; temp += Incomp[(i+2)*ByteWidth + (j * 4)]; workloc[(i/2)*Width + j] = (unsigned char) (temp >> 3); } } i = Width*(Height/2-1); for(j=0; j<Width; j++) { temp = Incomp[(j * 4) + (Height-3)*ByteWidth]; temp += Incomp[j + (Height-2)*ByteWidth]*3; temp += Incomp[j + (Height-1)*ByteWidth]*3; temp = temp/7; workloc[i+j] = (unsigned char) temp; } } #endif
|