📄 coder.c
字号:
#include"sim.h"
_inline void MeanMB(MB_Structure *, int mean[6]);
_inline int VarMB(MB_Structure *, int);
/**********************************************************************
*
* Name: CodeOneOrTwo
* Description: code one image normally or two images
* as a PB-frame (CodeTwoPB and CodeOnePred merged)
*
* Input: pointer to image, prev_image, prev_recon, Q
*
* Returns: pointer to reconstructed image
* Side effects: memory is allocated to recon image
*
*
*
***********************************************************************/
void CodeOneOrTwo(PictImage *curr, PictImage _huge *pr, int QP, int frameskip, Bits *bits,
Pict *pic)
{
/*
curr ---- current orignal image to be coded
pr ---- reconstruced image
*/
MotionVector ZERO = {0,0,0,0,0};
int Mode;
int CBP, CBPB=0;
int newgob;
int i,j,k;
/* buffer control vars */
float QP_cumulative = (float)0;
int abs_mb_num = 0, QuantChangePostponed = 0;
int QP_new, QP_prev, dquant, QP_xmitted=QP;
ZeroBits(bits);
/* make edge and interpolate image */
MakeEdgeImage(pr->lum, prev_recon.lum, pels, lines, B<<1);
MakeEdgeImage(pr->Cr, prev_recon.Cr, cpels, lines>>1, B);
MakeEdgeImage(pr->Cb, prev_recon.Cb, cpels, lines>>1, B);
/* mark PMV's outside the frame */
for (i = 1; i < mbc + 1; i++)
{
for (k = 0; k < 6; k++)
{
MarkVec(pMV[k][0][i]);
}
pMV[0][0][i]->Mode = MODE_INTRA;
}
/* zero out PMV's outside the frame */
for (i = 0; i < mbr + 1; i++)
{
for (k = 0; k < 6; k++)
{
ZeroVec(pMV[k][i][0]);
ZeroVec(pMV[k][i][mbc+1]);
}
pMV[0][i][0]->Mode = MODE_INTRA;
pMV[0][i][mbc+1]->Mode = MODE_INTRA;
}
/* Integer and half pel motion estimation */
MotionEstimatePicture(curr->lum,prev_recon.lum,pic->seek_dist,pMV);
/* note: integer pel motion estimation is now based on previous
reconstructed image, not the previous original image. We have
found that this works better for some sequences and not worse for
others. Note that it can not easily be changed back by
substituting prev_recon->lum with orig_lum in the line above,
because SAD for zero vector is not re-calculated in the half
pel search. The half pel search has always been based on the
previous reconstructed image */
QP_new = QP_xmitted = QP_prev = QP; /* Copy the passed value of QP */
dquant = 0;
for ( j = 0; j < mbr; j++)
{
newgob = 0;
/* global block syntax */
if (j == 0)
{
pic->QUANT = QP_new;
bits->header += CountBitsPicture(pic);
QP_xmitted = QP_prev = QP_new;
}
else if (pic->use_gobsync && j%pic->use_gobsync == 0)
{
bits->header += CountBitsSlice(j,QP_new); // insert gob sync
QP_xmitted = QP_prev = QP_new;
newgob = 1;
}
for ( i = 0; i < mbc; i++)
{
// Update of dquant, check and correct its limit
dquant = QP_new - QP_prev;
if (dquant != 0 && i != 0 && pMV[0][j+1][i+1]->Mode == MODE_INTER4V)
{
// It is not possible to change the quantizer and at the same
// time use 8x8 vectors. Turning off 8x8 vectors is not
// possible at this stage because the previous macroblock
// encoded assumed this one should use 8x8 vectors. Therefore
// the change of quantizer is postponed until the first MB
// without 8x8 vectors
dquant = 0;
QP_xmitted = QP_prev;
QuantChangePostponed = 1;
}
else
{
QP_xmitted = QP_new;
QuantChangePostponed = 0;
}
if (dquant > 2) { dquant = 2; QP_xmitted = QP_prev + dquant;}
if (dquant < -2) { dquant = -2; QP_xmitted = QP_prev + dquant;}
pic->DQUANT = dquant;
// modify mode if dquant != 0 (e.g. MODE_INTER -> MODE_INTER_Q)
Mode = ModifyMode(pMV[0][j+1][i+1]->Mode,pic->DQUANT);
pMV[0][j+1][i+1]->Mode = Mode;
pic->MB = i + j * MBC;
if (Mode == MODE_INTER || Mode == MODE_INTER_Q || Mode==MODE_INTER4V)
{
MB_Pred(pr_edge.lum,&prev_recon, recon_data_P, i*MB_SIZE, j*MB_SIZE, pMV);
FillBlock(i*MB_SIZE, j*MB_SIZE, curr, diff);
DiffMB(diff, recon_data_P, 0);
}
else if(Mode == MODE_INTER0)
{
MB_Pred(pr_edge.lum,&prev_recon, recon_data_P, i*MB_SIZE, j*MB_SIZE, pMV);
}
else
FillBlock(i*MB_SIZE, j*MB_SIZE, curr, diff);
// P or INTRA Macroblock
if(Mode == MODE_INTER0)
{
QP_xmitted = QP_prev;
pic->DQUANT = 0;
Mode = MODE_INTER;
if (!syntax_arith_coding)
CountBitsMB(Mode,1,0,0,pic,bits);
else
Count_sac_BitsMB(Mode,1,0,0,pic,bits);
pMV[0][j+1][i+1]->Mode = Mode;
}
else
{
MB_Encode(diff, QP_xmitted, Mode);
CBP = FindCBP(qbase, Mode, 64);
if (CBP == 0 && (Mode == MODE_INTER || Mode == MODE_INTER_Q))
ZeroMBlock(diff);
else
MB_Decode(qbase, diff, QP_xmitted, Mode);
DiffMB(recon_data_P, diff, 1);
Clip(recon_data_P);
if ((CBP==0) && (CBPB==0) && (EqualVec(pMV[0][j+1][i+1],&ZERO)) &&
(Mode == MODE_INTER || Mode == MODE_INTER_Q))
{
// Skipped MB : both CBP and CBPB are zero, 16x16 vector is zero,
// PB delta vector is zero and Mode = MODE_INTER
if (Mode == MODE_INTER_Q)
{
// DQUANT != 0 but not coded anyway
QP_xmitted = QP_prev;
pic->DQUANT = 0;
Mode = MODE_INTER;
}
if (!syntax_arith_coding)
CountBitsMB(Mode,1,CBP,CBPB,pic,bits);
else
Count_sac_BitsMB(Mode,1,CBP,CBPB,pic,bits);
}
else
{
// Normal MB
if (!syntax_arith_coding)
{ // VLC
CountBitsMB(Mode,0,CBP,CBPB,pic,bits);
if (Mode == MODE_INTER || Mode == MODE_INTER_Q)
{
bits->no_inter++;
CountBitsVectors(pMV, bits, i, j, Mode, newgob, pic);
}
else if (Mode == MODE_INTER4V)
{
bits->no_inter4v++;
CountBitsVectors(pMV, bits, i, j, Mode, newgob, pic);
}
else
{
// MODE_INTRA or MODE_INTRA_Q
bits->no_intra++;
if (pic->PB)
CountBitsVectors(pMV, bits, i, j, Mode, newgob, pic);
}
if (CBP || Mode == MODE_INTRA || Mode == MODE_INTRA_Q)
CountBitsCoeff(qbase, Mode, CBP, bits, 64);
} // end VLC
else
{ // SAC
Count_sac_BitsMB(Mode,0,CBP,CBPB,pic,bits);
if (Mode == MODE_INTER || Mode == MODE_INTER_Q)
{
bits->no_inter++;
Count_sac_BitsVectors(pMV, bits, i, j, Mode, newgob, pic);
}
else if (Mode == MODE_INTER4V)
{
bits->no_inter4v++;
Count_sac_BitsVectors(pMV, bits, i, j, Mode, newgob, pic);
}
else
// MODE_INTRA or MODE_INTRA_Q
bits->no_intra++;
if (CBP || Mode == MODE_INTRA || Mode == MODE_INTRA_Q)
Count_sac_BitsCoeff(qbase, Mode, CBP, bits, 64);
} // end SAC
QP_prev = QP_xmitted;
}
}
abs_mb_num++;
QP_cumulative += QP_xmitted;
ReconImage(i,j,recon_data_P, pr);
}
}
pic->QP_mean = QP_cumulative/(float)abs_mb_num;
return;
}
/**********************************************************************
*
* Name: CodeOneIntra
* Description: codes one image intra
*
* Input: pointer to image, QP
*
* Returns: pointer to reconstructed image
* Side effects: memory is allocated to recon image
*
*
*
***********************************************************************/
void CodeOneIntra(PictImage *curr, PictImage *recon, int QP, Bits *bits, Pict *pic)
{
MB_Structure data;
int Mode = MODE_INTRA;
int CBP,COD;
int i,j,k;
int mean, means[6], var;
pic->QUANT = QP;
COD = 0; /* Every block is coded in Intra frame */
pic->MB = 0;
bits->header += CountBitsPicture(pic);
for ( j = 0; j < mbr; j++)
{
/* insert sync in *every* slice if use_gobsync is chosen */
if (pic->use_gobsync && j != 0)
bits->header += CountBitsSlice(j,QP);
for ( i = 0; i < mbc; i++)
{
bits->no_intra++;
FillBlock(i*MB_SIZE, j*MB_SIZE, curr, &data); //to be modified
MeanMB(&data, means);
mean = (means[0] + means[1] + means[2] + means[3])>>2;
var = VarMB(&data, mean);
if(var < 0)
{
for(k = 0; k < 384; k++)
qbase[k] = 0;
qbase[0] = means[0];
qbase[64] = means[1];
qbase[128] = means[2];
qbase[192] = means[3];
qbase[256] = means[4];
qbase[320] = means[5];
}
else
MB_Encode(&data, QP, Mode);
CBP = FindCBP(qbase,Mode,64);
if (!syntax_arith_coding) {
CountBitsMB(Mode,COD,CBP,0,pic,bits);
CountBitsCoeff(qbase, Mode, CBP,bits,64);
} else {
Count_sac_BitsMB(Mode,COD,CBP,0,pic,bits);
Count_sac_BitsCoeff(qbase, Mode, CBP,bits,64);
}
MB_Decode(qbase, &data, QP, Mode);
Clip(&data);
ReconImage(i,j,&data,recon);
pic->MB++;
}
}
pic->QP_mean = (float)QP;
}
/**********************************************************************
*
* Name: MB_Encode
* Description: DCT and quantization of Macroblocks
*
* Input: MB data struct, mquant (1-31, 0 = no quant),
* MB info struct
* Returns: Pointer to quantized coefficients
* Side effects:
*
*
*
*
**********************************************************************/
void MB_Encode(MB_Structure *mb_orig, int QP, int I)
{
int i, j, k, l, row, col;
int fblock[64];
int *qcoeff_ind;
qcoeff_ind = qbase;
for (k=0;k<16;k+=8)
{
for (l=0;l<16;l+=8)
{
for (i=k,row=0;row<64;i++,row+=8)
{
for (j=l,col=0;col<8;j++,col++)
{
*(fblock+row+col) = mb_orig->lum[i][j];
}
}
dct(fblock);
Quant(fblock,qcoeff_ind,QP,I);
qcoeff_ind += 64;
}
}
/* chrominance block */
dct(mb_orig->Cb[0]);
Quant(mb_orig->Cb[0],qcoeff_ind,QP,I);
qcoeff_ind += 64;
dct(mb_orig->Cr[0]);
Quant(mb_orig->Cr[0],qcoeff_ind,QP,I);
}
/**********************************************************************
*
* Name: MB_Decode
* Description: Reconstruction of quantized DCT-coded Macroblocks
*
* Input: Quantized coefficients, MB data
* QP (1-31, 0 = no quant), MB info block
* Returns: int (just 0)
* Side effects:
*
*
*
*
**********************************************************************/
void MB_Decode(int *qcoeff, MB_Structure *mb_recon, int QP, int I)
{
int i, j, k, l, row, col;
int rcoeff[256];
int *qcoeff_ind;
int *rcoeff_ind;
/* For control purposes */
/* Zero data */
qcoeff_ind = qcoeff;
rcoeff_ind = rcoeff;
/*
for (i = 0; i < 16; i++)
for (j = 0; j < 16; j++)
mb_recon->lum[j][i] = 0;
for (i = 0; i < 8; i++)
for (j = 0; j < 8; j++)
{
mb_recon->Cb[j][i] = 0;
mb_recon->Cr[j][i] = 0;
}
*/
for (k=0;k<16;k+=8)
{
for (l=0;l<16;l+=8)
{
Dequant(qcoeff_ind,rcoeff_ind,QP,I);
idct(rcoeff_ind);
for (i=k,row=0;row<64;i++,row+=8)
{
for (j=l,col=0;col<8;j++,col++)
{
mb_recon->lum[i][j] = *(rcoeff_ind+row+col);
}
}
qcoeff_ind += 64;
rcoeff_ind += 64;
}
}
Dequant(qcoeff_ind,mb_recon->Cb[0],QP,I);
idct(mb_recon->Cb[0]);
qcoeff_ind += 64;
Dequant(qcoeff_ind,mb_recon->Cr[0],QP,I);
idct(mb_recon->Cr[0]);
}
/**********************************************************************
* * Name: FillBlock
* Description: Fills the luminance of one block of PictImage
*
* Input: Position, pointer to PictImage, array to fill
* Returns:
* Side effects: fills array
*
*
*
***********************************************************************/
void FillBlock( int x, int y, PictImage *image, MB_Structure *data)
{
int n;
int m;
unsigned char _huge *pi = image->lum + (long)y*pels + x;
unsigned char _huge *pr = image->Cr + (long)(y>>1)*cpels + (x>>1);
unsigned char _huge *pb = image->Cb + (long)(y>>1)*cpels + (x>>1);
int *aa, *bb;
int cmbsize = MB_SIZE >> 1;
aa = data->lum[0];
for (n = 0; n < MB_SIZE; n++)
{
for (m = 0; m < MB_SIZE; m++,aa++)
*aa = (int)(*(pi + m ));
pi += pels;
}
aa = data->Cr[0];
bb = data->Cb[0];
for (n = 0; n < cmbsize; n++)
{
for (m = 0; m < cmbsize; m++,aa++,bb++) {
*aa = (int)(*(pr + m));
*bb = (int)(*(pb + m));
}
pr += cpels;
pb += cpels;
}
return;
}
/**********************************************************************
*
* Name: ZeroMBlock
* Description: Fills one MB with Zeros
*
* Input: MB_Structure to zero out
* Returns:
* Side effects:
*
*
*
*
***********************************************************************/
void ZeroMBlock(MB_Structure *data)
{
memset(data,0,sizeof(MB_Structure));
return;
}
/**********************************************************************
*
* Name: ReconImage
* Description: Puts together reconstructed image
*
* Input: position of curr block, reconstructed
* macroblock, pointer to recontructed image
* Returns:
* Side effects:
*
*
*
*
***********************************************************************/
void ReconImage (int i, int j, MB_Structure *data, PictImage *recon)
{
int n, m, cmbsize = MB_SIZE>>1;
int x_curr, y_curr;
unsigned char _huge *pl, _huge *pr, _huge *pb;
int *dl, *dr, *db;
x_curr = i * MB_SIZE;
y_curr = j * MB_SIZE;
/* Fill in luminance data */
pl = recon->lum + (long)y_curr*pels + x_curr;
pr = recon->Cr + (long)(y_curr>>1)*cpels + (x_curr>>1);
pb = recon->Cb + (long)(y_curr>>1)*cpels + (x_curr>>1);
dl = data->lum[0];
dr = data->Cr[0];
db = data->Cb[0];
for (n = 0; n < MB_SIZE; n++)
{
for (m= 0; m < MB_SIZE; m++,dl++)
*(pl + m) = *dl;
pl += pels;
}
/* Fill in chrominance data */
for (n = 0; n < cmbsize; n++)
{
for (m = 0; m < cmbsize; m++,dr++,db++) {
*(pr + m) = *dr;
*(pb + m) = *db;
}
pr += cpels;
pb += cpels;
}
return;
}
/**********************************************************************
*
* Name: InterpolateImage
* Description: Interpolates a complete image for easier half
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -