--- decoder.c 2002/07/09 01:37:22 1.26 +++ decoder.c 2002/08/03 05:36:18 1.36 @@ -32,9 +32,14 @@ * * History: * + * 15.07.2002 fix a bug in B-frame decode at DIRECT mode + * MinChen + * 10.07.2002 added BFRAMES_DEC_DEBUG support + * Fix a little bug for low_delay flage + * MinChen * 28.06.2002 added basic resync support to iframe/pframe_decode() - * 22.06.2002 added primative N_VOP support - * #define BFRAMES_DEC now enables Minchenm's bframe decoder + * 22.06.2002 added primative N_VOP support + * #define BFRAMES_DEC now enables Minchen's bframe decoder * 08.05.2002 add low_delay support for B_VOP decode * MinChen * 05.05.2002 fix some B-frame decode problem @@ -50,13 +55,17 @@ * 22.12.2001 lock based interpolation * 01.12.2001 inital version; (c)2001 peter ross * - * $Id: decoder.c,v 1.26 2002/07/09 01:37:22 chenm001 Exp $ + * $Id: decoder.c,v 1.36 2002/08/03 05:36:18 chenm001 Exp $ * *************************************************************************/ #include #include +#ifdef BFRAMES_DEC_DEBUG + #define BFRAMES_DEC +#endif + #include "xvid.h" #include "portab.h" @@ -339,36 +348,58 @@ uv_dx = pMB->mvs[0].x; uv_dy = pMB->mvs[0].y; + if (dec->quarterpel) + { + uv_dx = (uv_dx >> 1) | (uv_dx & 1); + uv_dy = (uv_dy >> 1) | (uv_dy & 1); + } + uv_dx = (uv_dx & 3) ? (uv_dx >> 1) | 1 : uv_dx / 2; uv_dy = (uv_dy & 3) ? (uv_dy >> 1) | 1 : uv_dy / 2; } else { int sum; - sum = pMB->mvs[0].x + pMB->mvs[1].x + pMB->mvs[2].x + pMB->mvs[3].x; - uv_dx = - (sum == - 0 ? 0 : SIGN(sum) * (roundtab[ABS(sum) % 16] + - (ABS(sum) / 16) * 2)); + + if (dec->quarterpel) + { + sum /= 2; + } + + uv_dx = (sum == 0 ? 0 : SIGN(sum) * (roundtab[ABS(sum) % 16] + (ABS(sum) / 16) * 2)); sum = pMB->mvs[0].y + pMB->mvs[1].y + pMB->mvs[2].y + pMB->mvs[3].y; - uv_dy = - (sum == - 0 ? 0 : SIGN(sum) * (roundtab[ABS(sum) % 16] + - (ABS(sum) / 16) * 2)); + + if (dec->quarterpel) + { + sum /= 2; + } + + uv_dy = (sum == 0 ? 0 : SIGN(sum) * (roundtab[ABS(sum) % 16] + (ABS(sum) / 16) * 2)); } start_timer(); - interpolate8x8_switch(dec->cur.y, dec->refn[0].y, 16 * x_pos, 16 * y_pos, - pMB->mvs[0].x, pMB->mvs[0].y, stride, rounding); - interpolate8x8_switch(dec->cur.y, dec->refn[0].y, 16 * x_pos + 8, - 16 * y_pos, pMB->mvs[1].x, pMB->mvs[1].y, stride, - rounding); - interpolate8x8_switch(dec->cur.y, dec->refn[0].y, 16 * x_pos, - 16 * y_pos + 8, pMB->mvs[2].x, pMB->mvs[2].y, stride, - rounding); - interpolate8x8_switch(dec->cur.y, dec->refn[0].y, 16 * x_pos + 8, - 16 * y_pos + 8, pMB->mvs[3].x, pMB->mvs[3].y, stride, - rounding); + if(dec->quarterpel) { + DEBUG("QUARTERPEL"); + interpolate8x8_quarterpel(dec->cur.y, dec->refn[0].y, 16*x_pos, 16*y_pos, + pMB->mvs[0].x, pMB->mvs[0].y, stride, rounding); + interpolate8x8_quarterpel(dec->cur.y, dec->refn[0].y, 16*x_pos + 8, 16*y_pos, + pMB->mvs[1].x, pMB->mvs[1].y, stride, rounding); + interpolate8x8_quarterpel(dec->cur.y, dec->refn[0].y, 16*x_pos, 16*y_pos + 8, + pMB->mvs[2].x, pMB->mvs[2].y, stride, rounding); + interpolate8x8_quarterpel(dec->cur.y, dec->refn[0].y, 16*x_pos + 8, 16*y_pos + 8, + pMB->mvs[3].x, pMB->mvs[3].y, stride, rounding); + } + else { + interpolate8x8_switch(dec->cur.y, dec->refn[0].y, 16*x_pos, 16*y_pos, + pMB->mvs[0].x, pMB->mvs[0].y, stride, rounding); + interpolate8x8_switch(dec->cur.y, dec->refn[0].y, 16*x_pos + 8, 16*y_pos, + pMB->mvs[1].x, pMB->mvs[1].y, stride, rounding); + interpolate8x8_switch(dec->cur.y, dec->refn[0].y, 16*x_pos, 16*y_pos + 8, + pMB->mvs[2].x, pMB->mvs[2].y, stride, rounding); + interpolate8x8_switch(dec->cur.y, dec->refn[0].y, 16*x_pos + 8, 16*y_pos + 8, + pMB->mvs[3].x, pMB->mvs[3].y, stride, rounding); + } + interpolate8x8_switch(dec->cur.u, dec->refn[0].u, 8 * x_pos, 8 * y_pos, uv_dx, uv_dy, stride2, rounding); interpolate8x8_switch(dec->cur.v, dec->refn[0].v, 8 * x_pos, 8 * y_pos, @@ -471,6 +502,10 @@ } } mb->quant = quant; + mb->mvs[0].x = mb->mvs[0].y = + mb->mvs[1].x = mb->mvs[1].y = + mb->mvs[2].x = mb->mvs[2].y = + mb->mvs[3].x = mb->mvs[3].y =0; if (dec->interlacing) { mb->field_dct = BitstreamGetBit(bs); @@ -480,6 +515,9 @@ decoder_mbintra(dec, mb, x, y, acpred_flag, cbp, bs, quant, intra_dc_threshold, bound); } + if(dec->out_frm) + output_slice(&dec->cur, dec->edged_width,dec->width,dec->out_frm,0,y,dec->mb_width); + } } @@ -543,6 +581,7 @@ uint32_t x, y; uint32_t bound; + int cp_mb, st_mb; start_timer(); image_setedges(&dec->refn[0], dec->edged_width, dec->edged_height, @@ -552,6 +591,7 @@ bound = 0; for (y = 0; y < dec->mb_height; y++) { + cp_mb = st_mb = 0; for (x = 0; x < dec->mb_width; x++) { MACROBLOCK *mb; @@ -579,6 +619,7 @@ uint32_t cbp; uint32_t intra; + cp_mb++; mcbpc = get_mcbpc_inter(bs); mb->mode = mcbpc & 7; cbpc = (mcbpc >> 4); @@ -642,8 +683,8 @@ mb->mvs[1].y = mb->mvs[2].y = mb->mvs[3].y = mb->mvs[0].y; } - } else if (mb->mode == - MODE_INTER4V /* || mb->mode == MODE_INTER4V_Q */ ) { + } else if (mb->mode == MODE_INTER4V ) { + 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); @@ -663,7 +704,7 @@ rounding); } else // not coded { - //DEBUG2("P-frame MB at (X,Y)=",x,y); + DEBUG2("P-frame MB at (X,Y)=",x,y); 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; @@ -705,10 +746,16 @@ dec->refn[0].v + (8 * y) * dec->edged_width / 2 + (8 * x), dec->edged_width / 2); - stop_transfer_timer(); + 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); } } @@ -786,6 +833,7 @@ pU_Cur = dec->cur.u + (y_pos << 3) * stride2 + (x_pos << 3); pV_Cur = dec->cur.v + (y_pos << 3) * stride2 + (x_pos << 3); + if (!(pMB->mode == MODE_INTER || pMB->mode == MODE_INTER_Q)) { uv_dx = pMB->mvs[0].x; uv_dy = pMB->mvs[0].y; @@ -879,7 +927,6 @@ const MACROBLOCK * pMB, const uint32_t x_pos, const uint32_t y_pos, - const uint32_t cbp, Bitstream * bs) { @@ -894,11 +941,13 @@ int b_uv_dx, b_uv_dy; uint32_t i; 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); + if ((pMB->mode == MODE_INTER || pMB->mode == MODE_INTER_Q)) { uv_dx = pMB->mvs[0].x; uv_dy = pMB->mvs[0].y; @@ -988,7 +1037,6 @@ stride2); interpolate8x8_c(dec->cur.v, dec->refn[2].v, 8 * x_pos, 8 * y_pos, stride2); - stop_comp_timer(); for (i = 0; i < 6; i++) { @@ -1079,40 +1127,57 @@ int fcode_forward, int fcode_backward) { - uint32_t x, y; - VECTOR mv, zeromv; + VECTOR mv; + const VECTOR zeromv = {0,0}; +#ifdef BFRAMES_DEC_DEBUG + FILE *fp; + static char first=0; +#define BFRAME_DEBUG if (!first && fp){ \ + fprintf(fp,"Y=%3d X=%3d MB=%2d CBP=%02X\n",y,x,mb->mb_type,mb->cbp); \ + } +#endif start_timer(); image_setedges(&dec->refn[0], dec->edged_width, dec->edged_height, dec->width, dec->height, dec->interlacing); - //image_setedges(&dec->refn[1], dec->edged_width, dec->edged_height, dec->width, dec->height, dec->interlacing); + image_setedges(&dec->refn[1], dec->edged_width, dec->edged_height, + dec->width, dec->height, dec->interlacing); stop_edges_timer(); +#ifdef BFRAMES_DEC_DEBUG + if (!first){ + fp=fopen("C:\\XVIDDBG.TXT","w"); + } +#endif for (y = 0; y < dec->mb_height; y++) { // Initialize Pred Motion Vector - dec->p_fmv.x = dec->p_fmv.y = dec->p_bmv.x = dec->p_bmv.y = 0; + dec->p_fmv = dec->p_bmv = zeromv; for (x = 0; x < dec->mb_width; x++) { MACROBLOCK *mb = &dec->mbs[y * dec->mb_width + x]; MACROBLOCK *last_mb = &dec->last_mbs[y * dec->mb_width + x]; - mb->mvs[0].x = mb->mvs[0].y = zeromv.x = zeromv.y = mv.x = mv.y = - 0; + mv = + mb->b_mvs[0] = mb->b_mvs[1] = mb->b_mvs[2] = mb->b_mvs[3] = + mb->mvs[0] = mb->mvs[1] = mb->mvs[2] = mb->mvs[3] = zeromv; // the last P_VOP is skip macroblock ? if (last_mb->mode == MODE_NOT_CODED) { //DEBUG2("Skip MB in B-frame at (X,Y)=!",x,y); - mb->mb_type = MODE_FORWARD; mb->cbp = 0; - mb->mvs[1].x = mb->mvs[2].x = mb->mvs[3].x = mb->mvs[0].x; - mb->mvs[1].y = mb->mvs[2].y = mb->mvs[3].y = mb->mvs[0].y; - mb->quant = 8; +#ifdef BFRAMES_DEC_DEBUG + mb->mb_type = MODE_NOT_CODED; + BFRAME_DEBUG +#endif + mb->mb_type = MODE_FORWARD; + mb->quant = last_mb->quant; + //mb->mvs[1].x = mb->mvs[2].x = mb->mvs[3].x = mb->mvs[0].x; + //mb->mvs[1].y = mb->mvs[2].y = mb->mvs[3].y = mb->mvs[0].y; - decoder_bf_mbinter(dec, mb, x, y, mb->cbp, bs, quant, 1); + decoder_bf_mbinter(dec, mb, x, y, mb->cbp, bs, mb->quant, 1); continue; } - //t=BitstreamShowBits(bs,32); if (!BitstreamGetBit(bs)) { // modb=='0' const uint8_t modb2 = BitstreamGetBit(bs); @@ -1132,81 +1197,70 @@ } else if (quant < 1) { quant = 1; } - } else { - quant = 8; } - mb->quant = quant; } else { mb->mb_type = MODE_DIRECT_NONE_MV; mb->cbp = 0; } - mb->mode = MODE_INTER; + mb->quant = quant; + mb->mode = MODE_INTER4V; //DEBUG1("Switch bm_type=",mb->mb_type); +#ifdef BFRAMES_DEC_DEBUG + BFRAME_DEBUG +#endif + switch (mb->mb_type) { case MODE_DIRECT: - get_b_motion_vector(dec, bs, x, y, &mb->mvs[0], 1, zeromv); + get_b_motion_vector(dec, bs, x, y, &mv, 1, zeromv); case MODE_DIRECT_NONE_MV: - { // Because this file is a C file not C++ so I use '{' to define var - const int64_t TRB = dec->time_pp - dec->time_bp, TRD = - dec->time_pp; + { + const int64_t TRB = dec->time_pp - dec->time_bp, TRD = dec->time_pp; int i; for (i = 0; i < 4; i++) { - mb->mvs[i].x = - (int32_t) ((TRB * last_mb->mvs[i].x) / TRD + - mb->mvs[0].x); - mb->b_mvs[i].x = - (int32_t) ((mb->mvs[0].x == - 0) ? ((TRB - - TRD) * last_mb->mvs[i].x) / - TRD : mb->mvs[i].x - last_mb->mvs[i].x); - mb->mvs[i].y = - (int32_t) ((TRB * last_mb->mvs[i].y) / TRD + - mb->mvs[0].y); - mb->b_mvs[i].y = - (int32_t) ((mb->mvs[0].y == - 0) ? ((TRB - - TRD) * last_mb->mvs[i].y) / - TRD : mb->mvs[i].y - last_mb->mvs[i].y); + mb->mvs[i].x = (int32_t) ((TRB * last_mb->mvs[i].x) + / TRD + mv.x); + mb->b_mvs[i].x = (int32_t) ((mv.x == 0) + ? ((TRB - TRD) * last_mb->mvs[i].x) + / TRD + : mb->mvs[i].x - last_mb->mvs[i].x); + mb->mvs[i].y = (int32_t) ((TRB * last_mb->mvs[i].y) + / TRD + mv.y); + mb->b_mvs[i].y = (int32_t) ((mv.y == 0) + ? ((TRB - TRD) * last_mb->mvs[i].y) + / TRD + : mb->mvs[i].y - last_mb->mvs[i].y); } //DEBUG("B-frame Direct!\n"); } - mb->mode = MODE_INTER4V; decoder_bf_interpolate_mbinter(dec, dec->refn[1], dec->refn[0], - mb, x, y, mb->cbp, bs); + mb, x, y, bs); break; case MODE_INTERPOLATE: get_b_motion_vector(dec, bs, x, y, &mb->mvs[0], fcode_forward, dec->p_fmv); - dec->p_fmv.x = mb->mvs[1].x = mb->mvs[2].x = mb->mvs[3].x = - mb->mvs[0].x; - dec->p_fmv.y = mb->mvs[1].y = mb->mvs[2].y = mb->mvs[3].y = - mb->mvs[0].y; + dec->p_fmv = mb->mvs[1] = mb->mvs[2] = mb->mvs[3] = mb->mvs[0]; get_b_motion_vector(dec, bs, x, y, &mb->b_mvs[0], fcode_backward, dec->p_bmv); - dec->p_bmv.x = mb->b_mvs[1].x = mb->b_mvs[2].x = - mb->b_mvs[3].x = mb->b_mvs[0].x; - dec->p_bmv.y = mb->b_mvs[1].y = mb->b_mvs[2].y = - mb->b_mvs[3].y = mb->b_mvs[0].y; + dec->p_bmv = mb->b_mvs[1] = mb->b_mvs[2] = + mb->b_mvs[3] = mb->b_mvs[0]; decoder_bf_interpolate_mbinter(dec, dec->refn[1], dec->refn[0], - mb, x, y, mb->cbp, bs); + mb, x, y, bs); //DEBUG("B-frame Bidir!\n"); break; case MODE_BACKWARD: get_b_motion_vector(dec, bs, x, y, &mb->mvs[0], fcode_backward, dec->p_bmv); - dec->p_bmv.x = mb->mvs[1].x = mb->mvs[2].x = mb->mvs[3].x = - mb->mvs[0].x; - dec->p_bmv.y = mb->mvs[1].y = mb->mvs[2].y = mb->mvs[3].y = - mb->mvs[0].y; + dec->p_bmv = mb->mvs[1] = mb->mvs[2] = mb->mvs[3] = mb->mvs[0]; + mb->mode = MODE_INTER; decoder_bf_mbinter(dec, mb, x, y, mb->cbp, bs, quant, 0); //DEBUG("B-frame Backward!\n"); break; @@ -1214,11 +1268,9 @@ case MODE_FORWARD: get_b_motion_vector(dec, bs, x, y, &mb->mvs[0], fcode_forward, dec->p_fmv); - dec->p_fmv.x = mb->mvs[1].x = mb->mvs[2].x = mb->mvs[3].x = - mb->mvs[0].x; - dec->p_fmv.y = mb->mvs[1].y = mb->mvs[2].y = mb->mvs[3].y = - mb->mvs[0].y; + dec->p_fmv = mb->mvs[1] = mb->mvs[2] = mb->mvs[3] = mb->mvs[0]; + mb->mode = MODE_INTER; decoder_bf_mbinter(dec, mb, x, y, mb->cbp, bs, quant, 1); //DEBUG("B-frame Forward!\n"); break; @@ -1229,6 +1281,13 @@ } // end of FOR } +#ifdef BFRAMES_DEC_DEBUG + if (!first){ + first=1; + if (fp) + fclose(fp); + } +#endif } // swap two MACROBLOCK array @@ -1257,6 +1316,8 @@ start_global_timer(); + dec->out_frm = (frame->colorspace == XVID_CSP_EXTERN) ? frame->image : NULL; + BitstreamInit(&bs, frame->bitstream, frame->length); // add by chenm001 @@ -1306,17 +1367,24 @@ return XVID_ERR_FAIL; } +#ifdef BFRAMES_DEC_DEBUG + if (frame->length != BitstreamPos(&bs) / 8){ + DEBUG2("InLen/UseLen",frame->length, BitstreamPos(&bs) / 8); + } +#endif frame->length = BitstreamPos(&bs) / 8; + #ifdef BFRAMES_DEC // test if no B_VOP - if (dec->low_delay) { + if (dec->low_delay || dec->frames == 0) { #endif - image_output(&dec->cur, dec->width, dec->height, dec->edged_width, + image_output(&dec->cur, dec->width, dec->height, dec->edged_width, frame->image, frame->stride, frame->colorspace); + #ifdef BFRAMES_DEC } else { - if (dec->frames >= 1) { + if (dec->frames >= 1) { start_timer(); if ((vop_type == I_VOP || vop_type == P_VOP)) { image_output(&dec->refn[0], dec->width, dec->height, @@ -1335,8 +1403,16 @@ if (vop_type == I_VOP || vop_type == P_VOP) { image_swap(&dec->refn[0], &dec->refn[1]); image_swap(&dec->cur, &dec->refn[0]); + // swap MACROBLOCK - if (dec->low_delay && vop_type == P_VOP) + // the Divx will not set the low_delay flage some times + // so follow code will wrong to not swap at that time + // this will broken bitstream! so I'm change it, + // But that is not the best way! can anyone tell me how + // to do another way? + // 18-07-2002 MinChen + //if (!dec->low_delay && vop_type == P_VOP) + if (vop_type == P_VOP) mb_swap(&dec->mbs, &dec->last_mbs); }