decoder.cpp
来自「gaca源码」· C++ 代码 · 共 1,447 行 · 第 1/4 页
CPP
1,447 行
//----------------------------
// for P_VOP set gmc_warp to NULL
void S_decoder::P_Frame(Bitstream *bs, int rounding, bool reduced_resolution, int quant, int fcode,
int intra_dc_threshold, const WARPPOINTS *gmc_warp){
//dword mb_width = mb_width;
//dword mb_height = mb_height;
if(reduced_resolution){
mb_width = (width + 31) / 32;
mb_height = (height + 31) / 32;
}
SetEdges(refn[0]);
if(gmc_warp){
//accuracy: 0==1/2, 1=1/4, 2=1/8, 3=1/16
generate_GMCparameters(sprite_warping_points, sprite_warping_accuracy, gmc_warp, width, height, &new_gmc_data);
//image warping is done block-based in decoder_mbgmc(), now
}
PROF_S(PROF_FRM_P);
dword bound = 0;
for(dword y = 0; y < mb_height; y++){
//int cp_mb = 0, st_mb = 0;
for(dword x = 0; x < mb_width; x++){
//skip stuffing
while(bs->ShowBits(10) == 1)
bs->Skip(10);
if(bs->check_resync_marker(fcode - 1)){
bound = read_video_packet_header(bs, fcode - 1, &quant, &fcode, NULL, &intra_dc_threshold);
x = bound % mb_width;
y = bound / mb_width;
}
MACROBLOCK *mb = &mbs[y * mb_width + x];
//DPRINTF(XVID_DEBUG_MB, "macroblock (%i,%i) %08x\n", x, y, bs->ShowBits(32));
if(!(bs->GetBit())){
//block _is_ coded
int mcsel = 0; //mcsel: '0'=local motion, '1'=GMC
//cp_mb++;
dword mcbpc = bs->GetMcbpcInter();
mb->mode = mcbpc & 7;
dword cbpc = (mcbpc >> 4);
DPRINTF(XVID_DEBUG_MB, "mode %i\n", mb->mode);
DPRINTF(XVID_DEBUG_MB, "cbpc %i\n", cbpc);
dword intra = (mb->mode == MODE_INTRA || mb->mode == MODE_INTRA_Q);
dword acpred_flag = 0;
if(gmc_warp && (mb->mode == MODE_INTER || mb->mode == MODE_INTER_Q))
mcsel = bs->GetBit();
else
if(intra)
acpred_flag = bs->GetBit();
dword cbpy = bs->GetCbpy(intra);
//DPRINTF(XVID_DEBUG_MB, "cbpy %i mcsel %i \n", cbpy,mcsel);
dword cbp = (cbpy << 2) | cbpc;
if(mb->mode == MODE_INTER_Q || mb->mode == MODE_INTRA_Q){
int dquant = dquant_table[bs->GetBits(2)];
DPRINTF(XVID_DEBUG_MB, "dquant %i\n", dquant);
quant += dquant;
if (quant > 31) {
quant = 31;
} else if (quant < 1) {
quant = 1;
}
DPRINTF(XVID_DEBUG_MB, "quant %i\n", quant);
}
mb->quant = quant;
if(interlacing){
if((cbp || intra) && !mcsel){
mb->field_dct = bs->GetBit();
DPRINTF(XVID_DEBUG_MB,"decp: field_dct: %i\n", mb->field_dct);
}
if(mb->mode == MODE_INTER || mb->mode == MODE_INTER_Q){
mb->field_pred = bs->GetBit();
DPRINTF(XVID_DEBUG_MB, "decp: field_pred: %i\n", mb->field_pred);
if(mb->field_pred){
mb->field_for_top = bs->GetBit();
DPRINTF(XVID_DEBUG_MB,"decp: field_for_top: %i\n", mb->field_for_top);
mb->field_for_bot = bs->GetBit();
DPRINTF(XVID_DEBUG_MB,"decp: field_for_bot: %i\n", mb->field_for_bot);
}
}
}
if(mcsel){
mbgmc(mb, x, y, fcode, cbp, bs, rounding);
PROF_E(PROF_0);
continue;
}else
if(mb->mode == MODE_INTER || mb->mode == MODE_INTER_Q){
if(interlacing && mb->field_pred){
GetMotionVector(bs, x, y, 0, &mb->mvs[0], fcode, bound);
GetMotionVector(bs, x, y, 0, &mb->mvs[1], fcode, bound);
}else{
GetMotionVector(bs, x, y, 0, &mb->mvs[0], fcode, bound);
mb->mvs[1] = mb->mvs[2] = mb->mvs[3] = mb->mvs[0];
}
}else
if(mb->mode == MODE_INTER4V){
GetMotionVector(bs, x, y, 0, &mb->mvs[0], fcode, bound);
GetMotionVector(bs, x, y, 1, &mb->mvs[1], fcode, bound);
GetMotionVector(bs, x, y, 2, &mb->mvs[2], fcode, bound);
GetMotionVector(bs, x, y, 3, &mb->mvs[3], fcode, bound);
}else{ /* MODE_INTRA, MODE_INTRA_Q */
mb->mvs[0].x = mb->mvs[1].x = mb->mvs[2].x = mb->mvs[3].x = 0;
mb->mvs[0].y = mb->mvs[1].y = mb->mvs[2].y = mb->mvs[3].y = 0;
MBIntra(mb, x, y, acpred_flag, cbp, bs, quant, intra_dc_threshold, bound, reduced_resolution);
continue;
}
PROF_S(PROF_5);
DecodeInterMacroBlock(mb, x, y, cbp, bs, rounding, reduced_resolution, 0);
PROF_E(PROF_5);
}else
if(gmc_warp){
//a not coded S(GMC)-VOP macroblock
mb->mode = MODE_NOT_CODED_GMC;
mbgmc(mb, x, y, fcode, 0x00, bs, rounding);
/*
#ifdef XVID_CSP_SLICE
if(out_frm && cp_mb > 0) {
output_slice(&cur, edged_width,width,out_frm,st_mb,y,cp_mb);
cp_mb = 0;
}
st_mb = x+1;
#endif
*/
}else{
//not coded P_VOP macroblock
mb->mode = MODE_NOT_CODED;
mb->mvs[0].x = mb->mvs[1].x = mb->mvs[2].x = mb->mvs[3].x = 0;
mb->mvs[0].y = mb->mvs[1].y = mb->mvs[2].y = mb->mvs[3].y = 0;
DecodeInterMacroBlock(mb, x, y, 0, bs, rounding, reduced_resolution, 0);
/*
#ifdef XVID_CSP_SLICE
if(out_frm && cp_mb > 0) {
output_slice(&cur, edged_width,width,out_frm,st_mb,y,cp_mb);
cp_mb = 0;
}
st_mb = x+1;
#endif
*/
}
}
/*
#ifdef XVID_CSP_SLICE
if(out_frm && cp_mb > 0)
output_slice(&cur, edged_width,width,out_frm,st_mb,y,cp_mb);
#endif
*/
}
PROF_E(PROF_FRM_P);
}
//----------------------------
/* decode B-frame motion vector */
static void get_b_motion_vector(Bitstream * bs, VECTOR * mv, int fcode, const VECTOR pmv){
const int scale_fac = 1 << (fcode - 1);
const int high = (32 * scale_fac) - 1;
const int low = ((-32) * scale_fac);
const int range = (64 * scale_fac);
int mv_x = bs->GetMoveVector(fcode);
int mv_y = bs->GetMoveVector(fcode);
mv_x += pmv.x;
mv_y += pmv.y;
if (mv_x < low)
mv_x += range;
else if (mv_x > high)
mv_x -= range;
if (mv_y < low)
mv_y += range;
else if (mv_y > high)
mv_y -= range;
mv->x = mv_x;
mv->y = mv_y;
}
//----------------------------
/* decode an B-frame direct & interpolate macroblock */
void S_decoder::BFrameInterpolateMBInter(const IMAGE &forward, const IMAGE &backward, const MACROBLOCK *pMB, dword x_pos, dword y_pos, Bitstream *bs, int direct){
PROF_S(PROF_BINT_MBI);
dword stride = edged_width;
dword stride2 = stride / 2;
int uv_dx, uv_dy;
int b_uv_dx, b_uv_dy;
byte *pY_Cur, *pU_Cur, *pV_Cur;
const dword cbp = pMB->cbp;
pY_Cur = cur.y + (y_pos << 4) * stride + (x_pos << 4);
pU_Cur = cur.u + (y_pos << 3) * stride2 + (x_pos << 3);
pV_Cur = cur.v + (y_pos << 3) * stride2 + (x_pos << 3);
if(!direct){
uv_dx = pMB->mvs[0].x;
uv_dy = pMB->mvs[0].y;
b_uv_dx = pMB->b_mvs[0].x;
b_uv_dy = pMB->b_mvs[0].y;
if(quarterpel){
uv_dx /= 2;
uv_dy /= 2;
b_uv_dx /= 2;
b_uv_dy /= 2;
}
uv_dx = (uv_dx >> 1) + roundtab_79[uv_dx & 0x3];
uv_dy = (uv_dy >> 1) + roundtab_79[uv_dy & 0x3];
b_uv_dx = (b_uv_dx >> 1) + roundtab_79[b_uv_dx & 0x3];
b_uv_dy = (b_uv_dy >> 1) + roundtab_79[b_uv_dy & 0x3];
}else{
if(quarterpel) {
uv_dx = (pMB->mvs[0].x / 2) + (pMB->mvs[1].x / 2) + (pMB->mvs[2].x / 2) + (pMB->mvs[3].x / 2);
uv_dy = (pMB->mvs[0].y / 2) + (pMB->mvs[1].y / 2) + (pMB->mvs[2].y / 2) + (pMB->mvs[3].y / 2);
b_uv_dx = (pMB->b_mvs[0].x / 2) + (pMB->b_mvs[1].x / 2) + (pMB->b_mvs[2].x / 2) + (pMB->b_mvs[3].x / 2);
b_uv_dy = (pMB->b_mvs[0].y / 2) + (pMB->b_mvs[1].y / 2) + (pMB->b_mvs[2].y / 2) + (pMB->b_mvs[3].y / 2);
} else {
uv_dx = pMB->mvs[0].x + pMB->mvs[1].x + pMB->mvs[2].x + pMB->mvs[3].x;
uv_dy = pMB->mvs[0].y + pMB->mvs[1].y + pMB->mvs[2].y + pMB->mvs[3].y;
b_uv_dx = pMB->b_mvs[0].x + pMB->b_mvs[1].x + pMB->b_mvs[2].x + pMB->b_mvs[3].x;
b_uv_dy = pMB->b_mvs[0].y + pMB->b_mvs[1].y + pMB->b_mvs[2].y + pMB->b_mvs[3].y;
}
uv_dx = (uv_dx >> 3) + roundtab_76[uv_dx & 0xf];
uv_dy = (uv_dy >> 3) + roundtab_76[uv_dy & 0xf];
b_uv_dx = (b_uv_dx >> 3) + roundtab_76[b_uv_dx & 0xf];
b_uv_dy = (b_uv_dy >> 3) + roundtab_76[b_uv_dy & 0xf];
}
if(quarterpel){
if(!direct){
interpolate16x16_quarterpel(cur.y, forward.y, qtmp.y, qtmp.y + 64, qtmp.y + 128, 16*x_pos, 16*y_pos, pMB->mvs[0].x, pMB->mvs[0].y, stride, 0);
}else{
interpolate8x8_quarterpel(cur.y, forward.y, qtmp.y, qtmp.y + 64, qtmp.y + 128, 16*x_pos, 16*y_pos, pMB->mvs[0].x, pMB->mvs[0].y, stride, 0);
interpolate8x8_quarterpel(cur.y, forward.y, qtmp.y, qtmp.y + 64, qtmp.y + 128, 16*x_pos + 8, 16*y_pos, pMB->mvs[1].x, pMB->mvs[1].y, stride, 0);
interpolate8x8_quarterpel(cur.y, forward.y, qtmp.y, qtmp.y + 64, qtmp.y + 128, 16*x_pos, 16*y_pos + 8, pMB->mvs[2].x, pMB->mvs[2].y, stride, 0);
interpolate8x8_quarterpel(cur.y, forward.y, qtmp.y, qtmp.y + 64, qtmp.y + 128, 16*x_pos + 8, 16*y_pos + 8, pMB->mvs[3].x, pMB->mvs[3].y, stride, 0);
}
}else{
interpolate8x8_switch(cur.y, forward.y, 16 * x_pos, 16 * y_pos, pMB->mvs[0].x, pMB->mvs[0].y, stride, 0);
interpolate8x8_switch(cur.y, forward.y, 16 * x_pos + 8, 16 * y_pos, pMB->mvs[1].x, pMB->mvs[1].y, stride, 0);
interpolate8x8_switch(cur.y, forward.y, 16 * x_pos, 16 * y_pos + 8, pMB->mvs[2].x, pMB->mvs[2].y, stride, 0);
interpolate8x8_switch(cur.y, forward.y, 16 * x_pos + 8, 16 * y_pos + 8, pMB->mvs[3].x, pMB->mvs[3].y, stride, 0);
}
interpolate8x8_switch(cur.u, forward.u, 8 * x_pos, 8 * y_pos, uv_dx, uv_dy, stride2, 0);
interpolate8x8_switch(cur.v, forward.v, 8 * x_pos, 8 * y_pos, uv_dx, uv_dy, stride2, 0);
if(quarterpel){
if(!direct){
interpolate16x16_quarterpel(tmp.y, backward.y, qtmp.y, qtmp.y + 64, qtmp.y + 128, 16*x_pos, 16*y_pos, pMB->b_mvs[0].x, pMB->b_mvs[0].y, stride, 0);
}else{
interpolate8x8_quarterpel(tmp.y, backward.y, qtmp.y, qtmp.y + 64, qtmp.y + 128, 16*x_pos, 16*y_pos, pMB->b_mvs[0].x, pMB->b_mvs[0].y, stride, 0);
interpolate8x8_quarterpel(tmp.y, backward.y, qtmp.y, qtmp.y + 64, qtmp.y + 128, 16*x_pos + 8, 16*y_pos, pMB->b_mvs[1].x, pMB->b_mvs[1].y, stride, 0);
interpolate8x8_quarterpel(tmp.y, backward.y, qtmp.y, qtmp.y + 64, qtmp.y + 128, 16*x_pos, 16*y_pos + 8, pMB->b_mvs[2].x, pMB->b_mvs[2].y, stride, 0);
interpolate8x8_quarterpel(tmp.y, backward.y, qtmp.y, qtmp.y + 64, qtmp.y + 128, 16*x_pos + 8, 16*y_pos + 8, pMB->b_mvs[3].x, pMB->b_mvs[3].y, stride, 0);
}
}else{
interpolate8x8_switch(tmp.y, backward.y, 16 * x_pos, 16 * y_pos, pMB->b_mvs[0].x, pMB->b_mvs[0].y, stride, 0);
interpolate8x8_switch(tmp.y, backward.y, 16 * x_pos + 8, 16 * y_pos, pMB->b_mvs[1].x, pMB->b_mvs[1].y, stride, 0);
interpolate8x8_switch(tmp.y, backward.y, 16 * x_pos, 16 * y_pos + 8, pMB->b_mvs[2].x, pMB->b_mvs[2].y, stride, 0);
interpolate8x8_switch(tmp.y, backward.y, 16 * x_pos + 8, 16 * y_pos + 8, pMB->b_mvs[3].x, pMB->b_mvs[3].y, stride, 0);
}
interpolate8x8_switch(tmp.u, backward.u, 8 * x_pos, 8 * y_pos, b_uv_dx, b_uv_dy, stride2, 0);
interpolate8x8_switch(tmp.v, backward.v, 8 * x_pos, 8 * y_pos, b_uv_dx, b_uv_dy, stride2, 0);
interpolate8x8_avg2(cur.y + (16 * y_pos * stride) + 16 * x_pos, cur.y + (16 * y_pos * stride) + 16 * x_pos,
tmp.y + (16 * y_pos * stride) + 16 * x_pos, stride, 1, 8);
interpolate8x8_avg2(cur.y + (16 * y_pos * stride) + 16 * x_pos + 8, cur.y + (16 * y_pos * stride) + 16 * x_pos + 8,
tmp.y + (16 * y_pos * stride) + 16 * x_pos + 8, stride, 1, 8);
interpolate8x8_avg2(cur.y + ((16 * y_pos + 8) * stride) + 16 * x_pos, cur.y + ((16 * y_pos + 8) * stride) + 16 * x_pos,
tmp.y + ((16 * y_pos + 8) * stride) + 16 * x_pos, stride, 1, 8);
interpolate8x8_avg2(cur.y + ((16 * y_pos + 8) * stride) + 16 * x_pos + 8, cur.y + ((16 * y_pos + 8) * stride) + 16 * x_pos + 8,
tmp.y + ((16 * y_pos + 8) * stride) + 16 * x_pos + 8, stride, 1, 8);
interpolate8x8_avg2(cur.u + (8 * y_pos * stride2) + 8 * x_pos, cur.u + (8 * y_pos * stride2) + 8 * x_pos,
tmp.u + (8 * y_pos * stride2) + 8 * x_pos, stride2, 1, 8);
interpolate8x8_avg2(cur.v + (8 * y_pos * stride2) + 8 * x_pos, cur.v + (8 * y_pos * stride2) + 8 * x_pos,
tmp.v + (8 * y_pos * stride2) + 8 * x_pos, stride2, 1, 8);
if(cbp)
mb_decode(cbp, bs, pY_Cur, pU_Cur, pV_Cur, 0, pMB);
PROF_E(PROF_BINT_MBI);
}
//----------------------------
/* for decode B-frame dbquant */
static int get_dbquant(Bitstream * bs){
if (!bs->GetBit()) /* '0' */
return (0);
else if (!bs->GetBit()) /* '10' */
return (-2);
else /* '11' */
return (2);
}
//----------------------------
/*
* decode B-frame mb_type
* bit ret_value
* 1 0
* 01 1
* 001 2
* 0001 3
*/
static int get_mbtype(Bitstream * bs){
int mb_type;
for (mb_type = 0; mb_type <= 3; mb_type++)
if (bs->GetBit())
return (mb_type);
return -1;
}
//----------------------------
void S_decoder::B_Frame(Bitstream *bs, int quant, int fcode_forward, int fcode_backward){
dword x, y;
VECTOR mv;
const VECTOR zeromv = {0,0};
const int64_t TRB = time_pp - time_bp, TRD = time_pp;
int i;
PROF_S(PROF_FRM_B);
SetEdges(refn[0]);
SetEdges(refn[1]);
for(y = 0; y < mb_height; y++){
//initialize Pred Motion Vector
p_fmv = p_bmv = zeromv;
for(x = 0; x < mb_width; x++){
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?