--- decoder.c 2002/12/09 10:47:05 1.37.2.17 +++ decoder.c 2002/12/13 11:26:41 1.37.2.20 @@ -55,7 +55,7 @@ * 22.12.2001 lock based interpolation * 01.12.2001 inital version; (c)2001 peter ross * - * $Id: decoder.c,v 1.37.2.17 2002/12/09 10:47:05 suxen_drol Exp $ + * $Id: decoder.c,v 1.37.2.20 2002/12/13 11:26:41 suxen_drol Exp $ * *************************************************************************/ @@ -80,6 +80,7 @@ #include "utils/mem_transfer.h" #include "image/interpolate8x8.h" #include "image/reduced.h" +#include "image/font.h" #include "bitstream/mbcoding.h" #include "prediction/mbprediction.h" @@ -216,7 +217,7 @@ // add by chenm001 // for support B-frame to save reference frame's time - dec->frames = -1; + dec->frames = 0; dec->time = dec->time_base = dec->last_time_base = 0; dec->low_delay = 0; dec->packed_mode = 0; @@ -389,24 +390,6 @@ // decode an inter macroblock -static void -rrv_mv_scaleup(VECTOR * mv) -{ - if (mv->x > 0) { - mv->x = 2*mv->x - 1; - } else if (mv->x < 0) { - mv->x = 2*mv->x + 1; - } - - if (mv->y > 0) { - mv->y = 2*mv->y - 1; - } else if (mv->y < 0) { - mv->y = 2*mv->y + 1; - } -} - - - void decoder_mbinter(DECODER * dec, const MACROBLOCK * pMB, @@ -431,26 +414,22 @@ uint8_t *pY_Cur, *pU_Cur, *pV_Cur; int uv_dx, uv_dy; - VECTOR mv[4]; - - for (i = 0; i < 4; i++) - { - mv[i] = pMB->mvs[i]; - //DPRINTF(DPRINTF_MB, "mv[%i] orig=%i,%i local=%i", i, pMB->mvs[i].x, pMB->mvs[i].y, mv[i].x, mv[i].y); - } + VECTOR mv[4]; /* local copy of mvs */ if (reduced_resolution) { pY_Cur = dec->cur.y + (y_pos << 5) * stride + (x_pos << 5); pU_Cur = dec->cur.u + (y_pos << 4) * stride2 + (x_pos << 4); pV_Cur = dec->cur.v + (y_pos << 4) * stride2 + (x_pos << 4); - rrv_mv_scaleup(&mv[0]); - rrv_mv_scaleup(&mv[1]); - rrv_mv_scaleup(&mv[2]); - rrv_mv_scaleup(&mv[3]); + for (i = 0; i < 4; i++) { + mv[i].x = RRV_MV_SCALEUP(pMB->mvs[i].x); + mv[i].y = RRV_MV_SCALEUP(pMB->mvs[i].y); + } }else{ 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); + for (i = 0; i < 4; i++) + mv[i] = pMB->mvs[i]; } if (pMB->mode == MODE_INTER || pMB->mode == MODE_INTER_Q) { @@ -1627,6 +1606,7 @@ *mb2 = temp; } + int decoder_decode(DECODER * dec, XVID_DEC_FRAME * frame, XVID_DEC_STATS * stats) @@ -1642,9 +1622,13 @@ VECTOR gmc_mv[5]; uint32_t vop_type; int success = 0; + int output = 0; + int seen_something = 0; start_global_timer(); + dec->low_delay_default = (frame->general & XVID_DEC_LOWDELAY); + dec->out_frm = (frame->colorspace == XVID_CSP_EXTERN) ? frame->image : NULL; BitstreamInit(&bs, frame->bitstream, frame->length); @@ -1664,17 +1648,20 @@ start: // add by chenm001 // for support B-frame to reference last 2 frame - dec->frames++; xxx: vop_type = BitstreamReadHeaders(&bs, dec, &rounding, &reduced_resolution, &quant, &fcode_forward, &fcode_backward, &intra_dc_threshold, gmc_mv); - //DPRINTF(DPRINTF_HEADER, "vop_type=%i", vop_type); + DPRINTF(DPRINTF_HEADER, "vop_type=%i, packed=%i, time=%i, time_pp=%i, time_bp=%i", + vop_type, dec->packed_mode, dec->time, dec->time_pp, dec->time_bp); - if (vop_type == -1 && success) - goto done; + if (vop_type == - 1) + { + if (success) goto done; + return XVID_ERR_FAIL; + } if (vop_type == -2 || vop_type == -3) { @@ -1700,180 +1687,138 @@ dec->p_bmv.x = dec->p_bmv.y = dec->p_fmv.y = dec->p_fmv.y = 0; // init pred vector to 0 - switch (vop_type) { - case P_VOP: - decoder_pframe(dec, &bs, rounding, reduced_resolution, quant, - fcode_forward, intra_dc_threshold, NULL); -#ifdef BFRAMES_DEC - DEBUG1("P_VOP Time=", dec->time); -#endif - break; - - case I_VOP: - decoder_iframe(dec, &bs, reduced_resolution, quant, intra_dc_threshold); -#ifdef BFRAMES_DEC - DEBUG1("I_VOP Time=", dec->time); -#endif - break; - case B_VOP: -#ifdef BFRAMES_DEC - if (dec->time_pp > dec->time_bp) { - DEBUG1("B_VOP Time=", dec->time); - decoder_bframe(dec, &bs, quant, fcode_forward, fcode_backward); - } else { - DEBUG("broken B-frame!"); + /* packed_mode: special-N_VOP treament */ + if (dec->packed_mode && vop_type == N_VOP) + { + if (dec->low_delay_default) + { + image_output(&dec->refn[0], dec->width, dec->height, + dec->edged_width, frame->image, frame->stride, + frame->colorspace, dec->interlacing); + output = 1; } -#else - image_copy(&dec->cur, &dec->refn[0], dec->edged_width, dec->height); -#endif - break; - - case S_VOP : - decoder_pframe(dec, &bs, rounding, reduced_resolution, quant, - fcode_forward, intra_dc_threshold, gmc_mv); - break; - - case N_VOP: // vop not coded - // when low_delay==0, N_VOP's should interpolate between the past and future frames - image_copy(&dec->cur, &dec->refn[0], dec->edged_width, dec->height); -#ifdef BFRAMES_DEC - DEBUG1("N_VOP Time=", dec->time); -#endif - break; - - default: - if (stats) - stats->notify = 0; - - emms(); - return XVID_ERR_FAIL; + /* ignore otherwise */ } - - - /* reduced resolution deblocking filter */ - - if (reduced_resolution) + else if (vop_type != B_VOP) { - const int rmb_width = (dec->width + 31) / 32; - const int rmb_height = (dec->height + 31) / 32; - const int edged_width2 = dec->edged_width /2; - int i,j; - - /* horizontal deblocking */ - - for (j = 1; j < rmb_height*2; j++) // luma: j,i in block units - for (i = 0; i < rmb_width*2; i++) + switch(vop_type) { - if (dec->mbs[(j-1)/2*dec->mb_width + (i/2)].mode != MODE_NOT_CODED || - dec->mbs[(j+0)/2*dec->mb_width + (i/2)].mode != MODE_NOT_CODED) - { - xvid_HFilter_31_C(dec->cur.y + (j*16 - 1)*dec->edged_width + i*16, - dec->cur.y + (j*16 + 0)*dec->edged_width + i*16, 2); - } + case I_VOP : + decoder_iframe(dec, &bs, reduced_resolution, quant, intra_dc_threshold); + break; + case P_VOP : + decoder_pframe(dec, &bs, rounding, reduced_resolution, quant, + fcode_forward, intra_dc_threshold, NULL); + break; + case S_VOP : + decoder_pframe(dec, &bs, rounding, reduced_resolution, quant, + fcode_forward, intra_dc_threshold, gmc_mv); + break; + case N_VOP : + image_copy(&dec->cur, &dec->refn[0], dec->edged_width, dec->height); + break; } - for (j = 1; j < rmb_height; j++) // chroma - for (i = 0; i < rmb_width; i++) + if (reduced_resolution) { - if (dec->mbs[(j-1)*dec->mb_width + i].mode != MODE_NOT_CODED || - dec->mbs[(j+0)*dec->mb_width + i].mode != MODE_NOT_CODED) - { - hfilter_31(dec->cur.u + (j*16 - 1)*edged_width2 + i*16, - dec->cur.u + (j*16 + 0)*edged_width2 + i*16, 2); - hfilter_31(dec->cur.v + (j*16 - 1)*edged_width2 + i*16, - dec->cur.v + (j*16 + 0)*edged_width2 + i*16, 2); - } + image_deblock_rrv(&dec->cur, dec->edged_width, dec->mbs, + (dec->width + 31) / 32, (dec->height + 31) / 32, dec->mb_width); } - /* vertical deblocking */ - - for (j = 0; j < rmb_height*2; j++) // luma: i,j in block units - for (i = 1; i < rmb_width*2; i++) + /* note: for packed_mode, output is performed when the special-N_VOP is decoded */ + if (!(dec->low_delay_default && dec->packed_mode)) { - if (dec->mbs[(j/2)*dec->mb_width + (i-1)/2].mode != MODE_NOT_CODED || - dec->mbs[(j/2)*dec->mb_width + (i+0)/2].mode != MODE_NOT_CODED) + if (dec->low_delay) { - vfilter_31(dec->cur.y + (j*16)*dec->edged_width + i*16 - 1, - dec->cur.y + (j*16)*dec->edged_width + i*16 + 0, - dec->edged_width, 2); + image_output(&dec->cur, dec->width, dec->height, + dec->edged_width, frame->image, frame->stride, + frame->colorspace, dec->interlacing); + output = 1; } - } - - for (j = 0; j < rmb_height; j++) // chroma - for (i = 1; i < rmb_width; i++) - { - if (dec->mbs[j*dec->mb_width + i - 1].mode != MODE_NOT_CODED || - dec->mbs[j*dec->mb_width + i + 0].mode != MODE_NOT_CODED) + else if (dec->frames > 0) /* is the reference frame valid? */ { - vfilter_31(dec->cur.u + (j*16)*edged_width2 + i*16 - 1, - dec->cur.u + (j*16)*edged_width2 + i*16 + 0, - edged_width2, 2); - vfilter_31(dec->cur.v + (j*16)*edged_width2 + i*16 - 1, - dec->cur.v + (j*16)*edged_width2 + i*16 + 0, - edged_width2, 2); - } - } - } - - BitstreamByteAlign(&bs); - -#ifdef BFRAMES_DEC - // test if no B_VOP - if (dec->low_delay || dec->frames == 0 || ((dec->packed_mode) && !(frame->length > BitstreamPos(&bs) / 8))) { -#endif - image_output(&dec->cur, dec->width, dec->height, dec->edged_width, - frame->image, frame->stride, frame->colorspace, dec->interlacing); - -#ifdef BFRAMES_DEC - } else { - if (dec->frames >= 1 && !(dec->packed_mode)) { - start_timer(); - if ((vop_type == I_VOP || vop_type == P_VOP || vop_type == S_VOP)) { image_output(&dec->refn[0], dec->width, dec->height, dec->edged_width, frame->image, frame->stride, frame->colorspace, dec->interlacing); - } else if (vop_type == B_VOP) { - image_output(&dec->cur, dec->width, dec->height, - dec->edged_width, frame->image, frame->stride, - frame->colorspace, dec->interlacing); + output = 1; } - stop_conv_timer(); } - } -#endif - if (vop_type == I_VOP || vop_type == P_VOP || vop_type == S_VOP) { image_swap(&dec->refn[0], &dec->refn[1]); image_swap(&dec->cur, &dec->refn[0]); + mb_swap(&dec->mbs, &dec->last_mbs); - // swap MACROBLOCK - // 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); + dec->frames++; + seen_something = 1; + + }else{ /* B_VOP */ + + if (dec->low_delay) + { + DPRINTF(DPRINTF_ERROR, "warning: bvop found in low_delay==1 stream"); + dec->low_delay = 1; + } + + if (dec->time_pp <= dec->time_bp) { + /* this occurs when dx50_bvop_compatibility==0 sequences are + decoded in vfw. */ + image_printf(&dec->cur, dec->edged_width, dec->height, 16, 16, + "broken b-frame, tpp=%i tbp=%i", dec->time_pp, dec->time_bp); + }else{ + decoder_bframe(dec, &bs, quant, fcode_forward, fcode_backward); + } + + image_output(&dec->cur, dec->width, dec->height, + dec->edged_width, frame->image, frame->stride, + frame->colorspace, dec->interlacing); + output = 1; + dec->frames++; } + emms(); + + BitstreamByteAlign(&bs); - if (success == 0 && dec->packed_mode) + /* low_delay_default mode: repeat in packed_mode */ + if (dec->low_delay_default && dec->packed_mode && output == 0 && success == 0) { success = 1; - // if (frame->length > BitstreamPos(&bs) / 8) // multiple vops packed together goto start; } done : + /* low_delay_default mode: if we've gotten here without outputting anything, + then output the recently decoded frame, or print an error message */ + if (dec->low_delay_default && output == 0) + { + if (dec->packed_mode && seen_something) + { + /* output the recently decoded frame */ + image_output(&dec->refn[0], dec->width, dec->height, + dec->edged_width, frame->image, frame->stride, + frame->colorspace, dec->interlacing); + } + else + { + image_printf(&dec->cur, dec->edged_width, dec->height, 16, 16, + "warning: nothing to output"); + image_printf(&dec->cur, dec->edged_width, dec->height, 16, 64, + "bframe decoder lag"); + + image_output(&dec->cur, dec->width, dec->height, + dec->edged_width, frame->image, frame->stride, + frame->colorspace, dec->interlacing); + } + output = 1; + } + frame->length = BitstreamPos(&bs) / 8; if (stats) { - stats->notify = XVID_DEC_VOP; + stats->notify = output ? XVID_DEC_VOP : XVID_DEC_NOTHING; stats->data.vop.time_base = (int)dec->time_base; stats->data.vop.time_increment = 0; //XXX: todo }