📄 countbit.c
字号:
/************************************************* * libr263: fast H.263 encoder library * * Copyright (C) 1996, Roalt Aalmoes, Twente University * SPA multimedia group * * Based on Telenor TMN 1.6 encoder (Copyright (C) 1995, Telenor R&D) * created by Karl Lillevold * * Author encoder: Roalt Aalmoes, <aalmoes@huygens.nl> * * Date: 31-07-96 **************************************************/#include"sim.h"#include"huffman.h"#include"indices.h" /********************************************************************** * * Name: CountBitsMB * Description: counts bits used for MB info * * Input: Mode, COD, CBP, Picture and Bits structures * Returns: * Side effects: * * Date: 941129 Author: Karl.Lillevold@nta.no * ***********************************************************************/
// 计算宏块信息需要的bit数
// COD skip此宏块时为1 ,no skip 为0
// 对宏块的COD,CBPCM,CBPY 编码
void CountBitsMB(int Mode, int COD, int CBP, int CBPB, Pict *pic, Bits *bits){ extern EHUFF *vlc_cbpy, *vlc_cbpcm, *vlc_cbpcm_intra; int cbpy, cbpcm, length; /* COD */ if (trace) { fprintf(tf,"MB-nr: %d",pic->MB); if (pic->picture_coding_type == PCT_INTER) fprintf(tf," COD: %d\n",COD); }
if (pic->picture_coding_type == PCT_INTER) { mputv(1,COD); bits->COD++; } if (COD) return; /* not coded */ /* CBPCM */// 对CBP编码 cbpcm = Mode | ((CBP&3)<<4); // mode intra时3,inter时0 CBP的后两位,表示U和V块是否需要编码 cbp为60时,UV处为00,则cbpc为3, 编码时 3,1,1,编1位的1 // uv处00,cbpcm 3(1,1); 10 , 35(3,2); 01 , 19(3,1) ; 11, 51(3,3); if (trace) { fprintf(tf,"CBPCM (CBP=%d) (cbpcm=%d): ",CBP,cbpcm); }
// 对cbpcm编码,返回编码长度 if (pic->picture_coding_type == PCT_INTRA) { length = Encode(cbpcm,vlc_cbpcm_intra); // 对cbpcm编码,写入 } else { length = Encode(cbpcm,vlc_cbpcm); } bits->CBPCM += length; /* CBPY */ cbpy = CBP>>2; //亮度块Y1~Y4是否编码的标志位, if (Mode == MODE_INTRA || Mode == MODE_INTRA_Q) /* Intra */ cbpy = cbpy^15; //帧内 异或(相减) if (trace) { fprintf(tf,"CBPY (CBP=%d) (cbpy=%d): ",CBP,cbpy); }
// cbpy编码 length = Encode(cbpy, vlc_cbpy); bits->CBPY += length; return;}/********************************************************************** * * Name: CountBitsSlice * Description: couonts bits used for slice (GOB) info * * Input: slice no., quantizer * * Date: 94???? Author: Karl.Lillevold@nta.no * ***********************************************************************/int CountBitsSlice(int slice, int quant){ int bits = 0; /* Picture Start Code */ if (trace) fprintf(tf,"GOB sync (GBSC): "); mputv(PSC_LENGTH,PSC); /* PSC */ bits += PSC_LENGTH; /* Group Number */ if (trace) fprintf(tf,"GN: "); mputv(5,slice); bits += 5; /* GOB Sub Bitstream Indicator */ /* if CPM == 1: read 2 bits GSBI */ /* not supported in this version */ /* GOB Frame ID */ if (trace) fprintf(tf,"GFID: "); mputv(2, 0); /* NB: in error-prone environments this value should change if PTYPE in picture header changes. In this version of the encoder PTYPE only changes when PB-frames are used in the following cases: (i) after the first intra frame (ii) if the distance between two P-frames is very large Therefore I haven't implemented this GFID change */ /* GFID is not allowed to change unless PTYPE changes */ bits += 2; /* Gquant */ if (trace) fprintf(tf,"GQUANT: "); mputv(5,quant); bits += 5; return bits;}/********************************************************************** * * Name: CountBitsCoeff * Description: counts bits used for coeffs * * Input: qcoeff, coding mode CBP, bits structure, no. of * coeffs * * Returns: struct with no. of bits used * Side effects: * * Date: 940111 Author: Karl.Lillevold@nta.no * ***********************************************************************///16*16宏块, 对qcoeff编码,写入bit流,并将写入bit数加入到 bits->Y,和 bits->U中
// ncoeffs 取值为64 void CountBitsCoeff(int *qcoeff, int Mode, int CBP, Bits *bits, int ncoeffs){ int i; //intra if (Mode == MODE_INTRA) { for (i = 0; i < 4; i++) {//对qcoeff编码,写入比特流, 返回写入bit的个数 bits->Y += CodeCoeff(Mode, qcoeff,i,ncoeffs); } for (i = 4; i < 6; i++) { bits->C += CodeCoeff(Mode, qcoeff,i,ncoeffs); //uv处为0时,只编码DC值,8位 } } else {//inter for (i = 0; i < 4; i++) { if ((i==0 && CBP&32) || (i==1 && CBP&16) || (i==2 && CBP&8) || (i==3 && CBP&4) || (i==4 && CBP&2) || (i==5 && CBP&1)) { bits->Y += CodeCoeff(Mode, qcoeff, i, ncoeffs); } } for (i = 4; i < 6; i++) { if ((i==0 && CBP&32) || (i==1 && CBP&16) || (i==2 && CBP&8) || (i==3 && CBP&4) || (i==4 && CBP&2) || (i==5 && CBP&1)) { bits->C += CodeCoeff(Mode, qcoeff, i, ncoeffs); } } } return;}
// 对dct变换的系数编码
// mode 区分帧内帧间模式,qcoeff dct变换量化后系数, block 第block个8*8小块, 共ncoeffs个系数,取值为64
// 编码后写入码流,返回写入的bit数目
//????????????????????int CodeCoeff(int Mode, int *qcoeff, int block, int ncoeffs) //prev_level 上一个不为0的值{ int j, bits; int prev_run, run, prev_level, level, first; int prev_ind, ind, prev_s, s, length; extern EHUFF *vlc_3d; run = bits = 0; first = 1; prev_run = prev_level = prev_ind = level = s = prev_s = ind = 0; for (j = block*ncoeffs; j< (block + 1)*ncoeffs; j++)// 8*8 的小块的64个值
{ /* DC */ if (!(j%ncoeffs) && (Mode == MODE_INTRA))
{ /* DC coeff */ if (qcoeff[block*ncoeffs] != 128) mputv(8,qcoeff[block*ncoeffs]); // 写入DC的值 else mputv(8,255); bits += 8; } else
{ /* AC coeff */ s = 0; /* Increment run if coeff is zero */ if ((level = qcoeff[j]) == 0)
{ run++; // run 当前位置到前一个非零值中,0的个数 } else
{ /* code run & level and count bits */ if (level < 0)
{ s = 1; //qcoeff[j]值为负, s符号位, s=1 level = -level; } ind = level | run<<4; // ind值为level的?????????????????(一般为level) // ind 为level值加run左4位,
ind = ind | 0<<12; /* Not last coeff */
if (!first)
{ /* Encode the previous ind */ if (prev_level < 13 && prev_run < 64) // level值小于13,length=0;
{
//!!!!!!!! length = Encode(prev_ind,vlc_3d); //编码为0时 }
else length = 0; if (length == 0) /* Escape coding *///length为0时 ,64个AC的最后一个系数
{ if (prev_s == 1) {prev_level = (prev_level^0xff)+1;} // ?????????
// 最后一位 Encode(ESCAPE,vlc_3d); // 7167时, 写入7位,3值 mputv(1,0); mputv(6,prev_run); mputv(8,prev_level); bits += 22; //共22位 } else
{ mputv(1,prev_s); //1位,系数>0, 为0; 系数<0,为1 bits += length + 1; } }
prev_run = run; prev_s = s; prev_level = level; prev_ind = ind; // level为实际值,ind为level加上前面0个数(run<<4)的值 编码为prev_ind,为0时重新编 run = first = 0; }//end of level = qcoeff[j]) == 0 }//end of if intra } // end of for
/* Encode the last coeff *///编码最后一位 if (!first)
{ prev_ind = prev_ind | 1<<12; /* last coeff */ if (prev_level < 13 && prev_run < 64)
{ length = Encode(prev_ind,vlc_3d); }
else length = 0; if (length == 0)
{ /* Escape coding */ if (prev_s == 1)
{
prev_level = (prev_level^0xff)+1;} Encode(ESCAPE,vlc_3d); // 7167为vlc_3d表中最大值 mputv(1,1); mputv(6,prev_run); mputv(8,prev_level); bits += 22; } else
{ mputv(1,prev_s); bits += length + 1; } } return bits;} /********************************************************************** * * Name: FindCBP * Description: Finds the CBP for a macroblock * * Input: qcoeff and mode * * Returns: CBP * Side effects: * * Date: 940829 Author: Karl.Lillevold@nta.no * ***********************************************************************///整个宏块中,从量化系数中,得到CBP的值int FindCBP(int *qcoeff, int Mode, int ncoeffs){ int i,j; int CBP = 0; /* IF INTRABLOCK then intra =1 else 0 */ int intra = (Mode == MODE_INTRA); /* Set CBP for this Macroblock */ for (i = 0; i < 6; i++)
{ /* First time i = 0: j = 0 ..64-1 set bit 5 if coeff != 0 Sec. time i = 1; j = 64..128-1 set bit 4 if coeff != 0 */ /* OPTIMIZE: I think for i can be removed and only values i=0 must be proessed */ for (j = i*ncoeffs + intra; j < (i+1)*ncoeffs; j++)
{ if (qcoeff[j])
{ if (i == 0) {CBP |= 32;} else if (i == 1) {CBP |= 16;} else if (i == 2) {CBP |= 8;} else if (i == 3) {CBP |= 4;} else if (i == 4) {CBP |= 2;} else if (i == 5) {CBP |= 1;} else { fprintf(stderr,"Error in CBP assignment\n"); exit(-1); } break;
} } } return CBP;}//MV_ptr整帧图像宏块的mv, 当前为x,y宏块, newgob是否为新片,void CountBitsVectors(MotionVector *MV_ptr, Bits *bits, int x, int y, int Mode, int newgob, Pict *pic){ int y_vec, x_vec; extern EHUFF *vlc_mv; int pmv0, pmv1; int start,stop,block; MotionVector *MV_xy; start = 0; stop = 0; MV_xy = MV_ptr + y*mbc + x; for (block = start; block <= stop; block++)
{ FindPMV(MV_ptr,x,y,&pmv0,&pmv1, block, newgob, 1);//1,使用半象素 x_vec = (2*(*MV_xy).x + (*MV_xy).x_half) - pmv0; y_vec = (2*(*MV_xy).y + (*MV_xy).y_half) - pmv1; if (!long_vectors)
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -