📄 decoder.c
字号:
mvf1.y = 2*(mvf1.y+pmv.y/2); /* It's multiple of 2 */
if (mvf1.x < low) {
mvf1.x += range;
} else if (mvf1.x > high) {
mvf1.x -= range;
}
if (mvf1.y < low) {
mvf1.y += range;
} else if (mvf1.y > high) {
mvf1.y -= range;
}
mvf2.x = get_mv(bs, fcode);
mvf2.y = get_mv(bs, fcode);
mvf2.x += pmv.x;
mvf2.y = 2*(mvf2.y+pmv.y/2); /* It's multiple of 2 */
if (mvf2.x < low) {
mvf2.x += range;
} else if (mvf2.x > high) {
mvf2.x -= range;
}
if (mvf2.y < low) {
mvf2.y += range;
} else if (mvf2.y > high) {
mvf2.y -= range;
}
pMB->mvs[0]=mvf1;
pMB->mvs[1]=mvf2;
pMB->mvs[2].x=pMB->mvs[3].x=0;
pMB->mvs[2].y=pMB->mvs[3].y=0;
/* Calculate average for as it is field predicted */
pMB->mvs_avg.x=DIV2ROUND(pMB->mvs[0].x+pMB->mvs[1].x);
pMB->mvs_avg.y=DIV2ROUND(pMB->mvs[0].y+pMB->mvs[1].y);
}
}
/* for P_VOP set gmc_warp to NULL */
static void
decoder_pframe(DECODER * dec,
Bitstream * bs,
int rounding,
int quant,
int fcode,
int intra_dc_threshold,
const WARPPOINTS *const gmc_warp)
{
uint32_t x, y;
uint32_t bound;
int cp_mb, st_mb;
const uint32_t mb_width = dec->mb_width;
const uint32_t mb_height = dec->mb_height;
if (!dec->is_edged[0]) {
start_timer();
image_setedges(&dec->refn[0], dec->edged_width, dec->edged_height,
dec->width, dec->height, dec->bs_version);
dec->is_edged[0] = 1;
stop_edges_timer();
}
if (gmc_warp) {
/* accuracy: 0==1/2, 1=1/4, 2=1/8, 3=1/16 */
generate_GMCparameters( dec->sprite_warping_points,
dec->sprite_warping_accuracy, gmc_warp,
dec->width, dec->height, &dec->new_gmc_data);
/* image warping is done block-based in decoder_mbgmc(), now */
}
bound = 0;
for (y = 0; y < mb_height; y++) {
cp_mb = st_mb = 0;
for (x = 0; x < mb_width; x++) {
MACROBLOCK *mb;
/* skip stuffing */
while (BitstreamShowBits(bs, 10) == 1)
BitstreamSkip(bs, 10);
if (check_resync_marker(bs, fcode - 1)) {
bound = read_video_packet_header(bs, dec, fcode - 1,
&quant, &fcode, NULL, &intra_dc_threshold);
x = bound % mb_width;
y = bound / mb_width;
}
mb = &dec->mbs[y * dec->mb_width + x];
DPRINTF(XVID_DEBUG_MB, "macroblock (%i,%i) %08x\n", x, y, BitstreamShowBits(bs, 32));
if (!(BitstreamGetBit(bs))) { /* block _is_ coded */
uint32_t mcbpc, cbpc, cbpy, cbp;
uint32_t intra, acpred_flag = 0;
int mcsel = 0; /* mcsel: '0'=local motion, '1'=GMC */
cp_mb++;
mcbpc = get_mcbpc_inter(bs);
mb->mode = mcbpc & 7;
cbpc = (mcbpc >> 4);
DPRINTF(XVID_DEBUG_MB, "mode %i\n", mb->mode);
DPRINTF(XVID_DEBUG_MB, "cbpc %i\n", cbpc);
intra = (mb->mode == MODE_INTRA || mb->mode == MODE_INTRA_Q);
if (gmc_warp && (mb->mode == MODE_INTER || mb->mode == MODE_INTER_Q))
mcsel = BitstreamGetBit(bs);
else if (intra)
acpred_flag = BitstreamGetBit(bs);
cbpy = get_cbpy(bs, intra);
DPRINTF(XVID_DEBUG_MB, "cbpy %i mcsel %i \n", cbpy,mcsel);
cbp = (cbpy << 2) | cbpc;
if (mb->mode == MODE_INTER_Q || mb->mode == MODE_INTRA_Q) {
int dquant = dquant_table[BitstreamGetBits(bs, 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;
mb->field_pred=0;
if (dec->interlacing) {
if (cbp || intra) {
mb->field_dct = BitstreamGetBit(bs);
DPRINTF(XVID_DEBUG_MB,"decp: field_dct: %i\n", mb->field_dct);
}
if ((mb->mode == MODE_INTER || mb->mode == MODE_INTER_Q) && !mcsel) {
mb->field_pred = BitstreamGetBit(bs);
DPRINTF(XVID_DEBUG_MB, "decp: field_pred: %i\n", mb->field_pred);
if (mb->field_pred) {
mb->field_for_top = BitstreamGetBit(bs);
DPRINTF(XVID_DEBUG_MB,"decp: field_for_top: %i\n", mb->field_for_top);
mb->field_for_bot = BitstreamGetBit(bs);
DPRINTF(XVID_DEBUG_MB,"decp: field_for_bot: %i\n", mb->field_for_bot);
}
}
}
if (mcsel) {
decoder_mbgmc(dec, mb, x, y, fcode, cbp, bs, rounding);
continue;
} else if (mb->mode == MODE_INTER || mb->mode == MODE_INTER_Q) {
if(dec->interlacing) {
/* Get motion vectors interlaced, field_pred is handled there */
get_motion_vector_interlaced(dec, bs, x, y, 0, mb, fcode, bound);
} else {
get_motion_vector(dec, 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 ) {
/* interlaced missing here */
get_motion_vector(dec, bs, x, y, 0, &mb->mvs[0], fcode, bound);
get_motion_vector(dec, bs, x, y, 1, &mb->mvs[1], fcode, bound);
get_motion_vector(dec, bs, x, y, 2, &mb->mvs[2], fcode, bound);
get_motion_vector(dec, 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;
decoder_mbintra(dec, mb, x, y, acpred_flag, cbp, bs, quant,
intra_dc_threshold, bound);
continue;
}
/* See how to decode */
if(!mb->field_pred)
decoder_mbinter(dec, mb, x, y, cbp, bs, rounding, 0, 0);
else
decoder_mbinter_field(dec, mb, x, y, cbp, bs, rounding, 0, 0);
} else if (gmc_warp) { /* a not coded S(GMC)-VOP macroblock */
mb->mode = MODE_NOT_CODED_GMC;
mb->quant = quant;
decoder_mbgmc(dec, mb, x, y, fcode, 0x00, bs, rounding);
if(dec->out_frm && cp_mb > 0) {
output_slice(&dec->cur, dec->edged_width,dec->width,dec->out_frm,st_mb,y,cp_mb);
cp_mb = 0;
}
st_mb = x+1;
} else { /* not coded P_VOP macroblock */
mb->mode = MODE_NOT_CODED;
mb->quant = quant;
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;
mb->field_pred=0; /* (!) */
decoder_mbinter(dec, mb, x, y, 0, bs,
rounding, 0, 0);
if(dec->out_frm && cp_mb > 0) {
output_slice(&dec->cur, dec->edged_width,dec->width,dec->out_frm,st_mb,y,cp_mb);
cp_mb = 0;
}
st_mb = x+1;
}
}
if(dec->out_frm && cp_mb > 0)
output_slice(&dec->cur, dec->edged_width,dec->width,dec->out_frm,st_mb,y,cp_mb);
}
}
/* decode B-frame motion vector */
static void
get_b_motion_vector(Bitstream * bs,
VECTOR * mv,
int fcode,
const VECTOR pmv,
const DECODER * const dec,
const int x, const int y)
{
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 = get_mv(bs, fcode);
int mv_y = get_mv(bs, 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 */
static void
decoder_bf_interpolate_mbinter(DECODER * dec,
IMAGE forward,
IMAGE backward,
MACROBLOCK * pMB,
const uint32_t x_pos,
const uint32_t y_pos,
Bitstream * bs,
const int direct)
{
uint32_t stride = dec->edged_width;
uint32_t stride2 = stride / 2;
int uv_dx, uv_dy;
int b_uv_dx, b_uv_dy;
uint8_t *pY_Cur, *pU_Cur, *pV_Cur;
const uint32_t cbp = pMB->cbp;
pY_Cur = dec->cur.y + (y_pos << 4) * stride + (x_pos << 4);
pU_Cur = dec->cur.u + (y_pos << 3) * stride2 + (x_pos << 3);
pV_Cur = dec->cur.v + (y_pos << 3) * stride2 + (x_pos << 3);
validate_vector(pMB->mvs, x_pos, y_pos, dec);
validate_vector(pMB->b_mvs, x_pos, y_pos, dec);
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 (dec->quarterpel) {
if (dec->bs_version <= BS_VERSION_BUGGY_CHROMA_ROUNDING) {
uv_dx = (uv_dx>>1) | (uv_dx&1);
uv_dy = (uv_dy>>1) | (uv_dy&1);
b_uv_dx = (b_uv_dx>>1) | (b_uv_dx&1);
b_uv_dy = (b_uv_dy>>1) | (b_uv_dy&1);
}
else {
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 (dec->quarterpel) { /* for qpel the /2 shall be done before summation. We've done it right in the encoder in the past. */
/* TODO: figure out if we ever did it wrong on the encoder side. If yes, add some workaround */
if (dec->bs_version <= BS_VERSION_BUGGY_CHROMA_ROUNDING) {
int z;
uv_dx = 0; uv_dy = 0;
b_uv_dx = 0; b_uv_dy = 0;
for (z = 0; z < 4; z++) {
uv_dx += ((pMB->mvs[z].x>>1) | (pMB->mvs[z].x&1));
uv_dy += ((pMB->mvs[z].y>>1) | (pMB->mvs[z].y&1));
b_uv_dx += ((pMB->b_mvs[z].x>>1) | (pMB->b_mvs[z].x&1));
b_uv_dy += ((pMB->b_mvs[z].y>>1) | (pMB->b_mvs[z].y&1));
}
}
else {
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];
}
start_timer();
if(dec->quarterpel) {
if(!direct) {
interpolate16x16_quarterpel(dec->cur.y, forward.y, dec->qtmp.y, dec->qtmp.y + 64,
dec->qtmp.y + 128, 16*x_pos, 16*y_pos,
pMB->mvs[0].x, pMB->mvs[0].y, stride, 0);
} else {
interpolate8x8_quarterpel(dec->cur.y, forward.y, dec->qtmp.y, dec->qtmp.y + 64,
dec->qtmp.y + 128, 16*x_pos, 16*y_pos,
pMB->mvs[0].x, pMB->mvs[0].y, stride, 0);
interpolate8x8_quarterpel(dec->cur.y, forward.y, dec->qtmp.y, dec->qtmp.y + 64,
dec->qtmp.y + 128, 16*x_pos + 8, 16*y_pos,
pMB->mvs[1].x, pMB->mvs[1].y, stride, 0);
interpolate8x8_quarterpel(dec->cur.y, forward.y, dec->qtmp.y, dec->qtmp.y + 64,
dec->qtmp.y + 128, 16*x_pos, 16*y_pos + 8,
pMB->mvs[2].x, pMB->mvs[2].y, stride, 0);
interpolate8x8_quarterpel(dec->cur.y, forward.y, dec->qtmp.y, dec->qtmp.y + 64,
dec->qtmp.y + 128, 16*x_pos + 8, 16*y_pos + 8,
pMB->mvs[3].x, pMB->mvs[3].y, stride, 0);
}
} else {
interpolate8x8_switch(dec->cur.y, forward.y, 16 * x_pos, 16 * y_pos,
pMB->mvs[0].x, pMB->mvs[0].y, stride, 0);
interpolate8x8_switch(dec->cur.y, forward.y, 16 * x_pos + 8, 16 * y_pos,
pMB->mvs[1].x, pMB->mvs[1].y, stride, 0);
interpolate8x8_switch(dec->cur.y, forward.y, 16 * x_pos, 16 * y_pos + 8,
pMB->mvs[2].x, pMB->mvs[2].y, stride, 0);
interpolate8x8_switch(dec->cur.y, forward.y, 16 * x_pos + 8, 16 * y_pos + 8,
pMB->mvs[3].x, pMB->mvs[3].y, stride, 0);
}
interpolate8x8_switch(dec->cur.u, forward.u, 8 * x_pos, 8 * y_pos, uv_dx,
uv_dy, stride2, 0);
interpolate8x8_switch(dec->cur.v, forward.v, 8 * x_pos, 8 * y_pos, uv_dx,
uv_dy, stride2, 0);
if(dec->quarterpel) {
if(!direct) {
interpolate16x16_add_quarterpel(dec->cur.y, backward.y, dec->qtmp.y, dec->qtmp.y + 64,
dec->qtmp.y + 128, 16*x_pos, 16*y_pos,
pMB->b_mvs[0].x, pMB->b_mvs[0].y, stride, 0);
} else {
interpolate8x8_add_quarterpel(dec->cur.y, backward.y, dec->qtmp.y, dec->qtmp.y + 64,
dec->qtmp.y + 128, 16*x_pos, 16*y_pos,
pMB->b_mvs[0].x, pMB->b_mvs[0].y, stride, 0);
interpolate8x8_add_quarterpel(dec->cur.y, backward.y, dec->qtmp.y, dec->qtmp.y + 64,
dec->qtmp.y + 128, 16*x_pos + 8, 16*y_pos,
pMB->b_mvs[1].x, pMB->b_mvs[1].y, stride, 0);
interpolate8x8_add_quarterpel(dec->cur.y, backward.y, dec->qtmp.y, dec->qtmp.y + 64,
dec->qtmp.y + 128, 16*x_pos, 16*y_pos + 8,
pMB->b_mvs[2].x, pMB->b_mvs[2].y, stride, 0);
interpolate8x8_add_quarterpel(dec->cur.y, backward.y, dec->qtmp.y, dec->qtmp.y + 64,
dec->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_add_switch(dec->cur.y, backward.y, 16 * x_pos, 16 * y_pos,
pMB->b_mvs[0].x, pMB->b_mvs[0].y, stride, 0);
interpolate8x8_add_switch(dec->cur.y, backward.y, 16 * x_pos + 8,
16 * y_pos, pMB->b_mvs[1].x, pMB->b_mvs[1].y, stride, 0);
interpolate8x8_add_switch(dec->cur.y, backward.y, 16 * x_pos,
16 * y_pos + 8, pMB->b_mvs[2].x, pMB->b_mvs[2].y, stride, 0);
interpolate8x8_add_switch(dec->cur.y, backward.y, 16 * x_pos + 8,
16 * y_pos + 8, pMB->b_mvs[3].x, pMB->b_mvs[3].y, stride, 0);
}
interpolate8x8_add_switch(dec->cur.u, backward.u, 8 * x_pos, 8 * y_pos,
b_uv_dx, b_uv_dy, stride2, 0);
interpolate8x8_add_switch(dec->cur.v, backward.v, 8 * x_pos, 8 * y_pos,
b_uv_dx, b_uv_dy, stride2, 0);
stop_comp_timer();
if (cbp)
decoder_mb_decode(dec, cbp, bs, pY_Cur, pU_Cur, pV_Cur, pMB);
}
/* for decode B-frame dbquant */
static __inline int32_t
get_dbquant(Bitstream * bs)
{
if (!BitstreamGetBit(bs)) /* '0' */
return (0);
else if (!BitstreamGetBit(bs)) /* '10' */
return (-2);
else /* '11' */
return (2);
}
/*
* decode B-frame mb_type
* bit ret_value
* 1 0
* 01 1
* 001 2
* 0001 3
*/
static int32_t __inline
get_mbtype(Bitstream * bs)
{
int32_t mb_type;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -