--- decoder.c 2002/12/09 10:47:05 1.37.2.17 +++ decoder.c 2003/01/03 16:25:14 1.37.2.25 @@ -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.25 2003/01/03 16:25:14 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" @@ -96,11 +97,11 @@ { /* free existing */ + image_destroy(&dec->cur, dec->edged_width, dec->edged_height); image_destroy(&dec->refn[0], dec->edged_width, dec->edged_height); image_destroy(&dec->refn[1], dec->edged_width, dec->edged_height); - image_destroy(&dec->refn[2], dec->edged_width, dec->edged_height); - image_destroy(&dec->refh, dec->edged_width, dec->edged_height); - image_destroy(&dec->cur, dec->edged_width, dec->edged_height); + image_destroy(&dec->tmp, dec->edged_width, dec->edged_height); + image_destroy(&dec->qtmp, dec->edged_width, dec->edged_height); if (dec->last_mbs) xvid_free(dec->last_mbs); @@ -134,7 +135,7 @@ xvid_free(dec); return XVID_ERR_MEMORY; } - if (image_create(&dec->refn[2], dec->edged_width, dec->edged_height)) { + if (image_create(&dec->tmp, dec->edged_width, dec->edged_height)) { image_destroy(&dec->cur, dec->edged_width, dec->edged_height); image_destroy(&dec->refn[0], dec->edged_width, dec->edged_height); image_destroy(&dec->refn[1], dec->edged_width, dec->edged_height); @@ -142,11 +143,11 @@ return XVID_ERR_MEMORY; } - if (image_create(&dec->refh, dec->edged_width, dec->edged_height)) { + if (image_create(&dec->qtmp, dec->edged_width, dec->edged_height)) { image_destroy(&dec->cur, dec->edged_width, dec->edged_height); image_destroy(&dec->refn[0], dec->edged_width, dec->edged_height); image_destroy(&dec->refn[1], dec->edged_width, dec->edged_height); - image_destroy(&dec->refn[2], dec->edged_width, dec->edged_height); + image_destroy(&dec->tmp, dec->edged_width, dec->edged_height); xvid_free(dec); return XVID_ERR_MEMORY; } @@ -158,8 +159,8 @@ image_destroy(&dec->cur, dec->edged_width, dec->edged_height); image_destroy(&dec->refn[0], dec->edged_width, dec->edged_height); image_destroy(&dec->refn[1], dec->edged_width, dec->edged_height); - image_destroy(&dec->refn[2], dec->edged_width, dec->edged_height); - image_destroy(&dec->refh, dec->edged_width, dec->edged_height); + image_destroy(&dec->tmp, dec->edged_width, dec->edged_height); + image_destroy(&dec->qtmp, dec->edged_width, dec->edged_height); xvid_free(dec); return XVID_ERR_MEMORY; } @@ -175,8 +176,8 @@ image_destroy(&dec->cur, dec->edged_width, dec->edged_height); image_destroy(&dec->refn[0], dec->edged_width, dec->edged_height); image_destroy(&dec->refn[1], dec->edged_width, dec->edged_height); - image_destroy(&dec->refn[2], dec->edged_width, dec->edged_height); - image_destroy(&dec->refh, dec->edged_width, dec->edged_height); + image_destroy(&dec->tmp, dec->edged_width, dec->edged_height); + image_destroy(&dec->qtmp, dec->edged_width, dec->edged_height); xvid_free(dec); return XVID_ERR_MEMORY; } @@ -206,8 +207,8 @@ image_null(&dec->cur); image_null(&dec->refn[0]); image_null(&dec->refn[1]); - image_null(&dec->refn[2]); - image_null(&dec->refh); + image_null(&dec->tmp); + image_null(&dec->qtmp); dec->mbs = NULL; dec->last_mbs = NULL; @@ -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; @@ -237,8 +238,8 @@ xvid_free(dec->mbs); image_destroy(&dec->refn[0], dec->edged_width, dec->edged_height); image_destroy(&dec->refn[1], dec->edged_width, dec->edged_height); - image_destroy(&dec->refn[2], dec->edged_width, dec->edged_height); - image_destroy(&dec->refh, dec->edged_width, dec->edged_height); + image_destroy(&dec->tmp, dec->edged_width, dec->edged_height); + image_destroy(&dec->qtmp, dec->edged_width, dec->edged_height); image_destroy(&dec->cur, dec->edged_width, dec->edged_height); xvid_free(dec); @@ -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) { @@ -480,8 +459,8 @@ else { if(dec->quarterpel) { - interpolate16x16_quarterpel(dec->cur.y, dec->refn[0].y, dec->refh.y, dec->refh.y + 64, - dec->refh.y + 128, 16*x_pos, 16*y_pos, + interpolate16x16_quarterpel(dec->cur.y, dec->refn[0].y, dec->qtmp.y, dec->qtmp.y + 64, + dec->qtmp.y + 128, 16*x_pos, 16*y_pos, mv[0].x, mv[0].y, stride, rounding); } else { @@ -534,17 +513,17 @@ else { if(dec->quarterpel) { - interpolate8x8_quarterpel(dec->cur.y, dec->refn[0].y, dec->refh.y, dec->refh.y + 64, - dec->refh.y + 128, 16*x_pos, 16*y_pos, + interpolate8x8_quarterpel(dec->cur.y, dec->refn[0].y, dec->qtmp.y, dec->qtmp.y + 64, + dec->qtmp.y + 128, 16*x_pos, 16*y_pos, mv[0].x, mv[0].y, stride, rounding); - interpolate8x8_quarterpel(dec->cur.y, dec->refn[0].y, dec->refh.y, dec->refh.y + 64, - dec->refh.y + 128, 16*x_pos + 8, 16*y_pos, + interpolate8x8_quarterpel(dec->cur.y, dec->refn[0].y, dec->qtmp.y, dec->qtmp.y + 64, + dec->qtmp.y + 128, 16*x_pos + 8, 16*y_pos, mv[1].x, mv[1].y, stride, rounding); - interpolate8x8_quarterpel(dec->cur.y, dec->refn[0].y, dec->refh.y, dec->refh.y + 64, - dec->refh.y + 128, 16*x_pos, 16*y_pos + 8, + interpolate8x8_quarterpel(dec->cur.y, dec->refn[0].y, dec->qtmp.y, dec->qtmp.y + 64, + dec->qtmp.y + 128, 16*x_pos, 16*y_pos + 8, mv[2].x, mv[2].y, stride, rounding); - interpolate8x8_quarterpel(dec->cur.y, dec->refn[0].y, dec->refh.y, dec->refh.y + 64, - dec->refh.y + 128, 16*x_pos + 8, 16*y_pos + 8, + interpolate8x8_quarterpel(dec->cur.y, dec->refn[0].y, dec->qtmp.y, dec->qtmp.y + 64, + dec->qtmp.y + 128, 16*x_pos + 8, 16*y_pos + 8, mv[3].x, mv[3].y, stride, rounding); } else { @@ -640,8 +619,8 @@ { uint32_t bound; uint32_t x, y; - int mb_width = dec->mb_width; - int mb_height = dec->mb_height; + uint32_t mb_width = dec->mb_width; + uint32_t mb_height = dec->mb_height; if (reduced_resolution) { @@ -699,7 +678,7 @@ if (dec->interlacing) { mb->field_dct = BitstreamGetBit(bs); - DEBUG1("deci: field_dct: ", mb->field_dct); + DPRINTF(DPRINTF_MB,"deci: field_dct: %i", mb->field_dct); } decoder_mbintra(dec, mb, x, y, acpred_flag, cbp, bs, quant, @@ -789,8 +768,8 @@ uint32_t x, y; uint32_t bound; int cp_mb, st_mb; - int mb_width = dec->mb_width; - int mb_height = dec->mb_height; + uint32_t mb_width = dec->mb_width; + uint32_t mb_height = dec->mb_height; if (reduced_resolution) { @@ -877,18 +856,18 @@ if (dec->interlacing) { if (cbp || intra) { mb->field_dct = BitstreamGetBit(bs); - DEBUG1("decp: field_dct: ", mb->field_dct); + DPRINTF(DPRINTF_MB,"decp: field_dct: %i", mb->field_dct); } if (mb->mode == MODE_INTER || mb->mode == MODE_INTER_Q) { mb->field_pred = BitstreamGetBit(bs); - DEBUG1("decp: field_pred: ", mb->field_pred); + DPRINTF(DPRINTF_MB, "decp: field_pred: %i", mb->field_pred); if (mb->field_pred) { mb->field_for_top = BitstreamGetBit(bs); - DEBUG1("decp: field_for_top: ", mb->field_for_top); + DPRINTF(DPRINTF_MB,"decp: field_for_top: %i", mb->field_for_top); mb->field_for_bot = BitstreamGetBit(bs); - DEBUG1("decp: field_for_bot: ", mb->field_for_bot); + DPRINTF(DPRINTF_MB,"decp: field_for_bot: %i", mb->field_for_bot); } } } @@ -936,7 +915,7 @@ } else if (gmc_mv) /* not coded S_VOP macroblock */ { - mb->mode = MODE_NOT_CODED; + mb->mode = MODE_NOT_CODED_GMC; mb->mvs[0].x = mb->mvs[1].x = mb->mvs[2].x = mb->mvs[3].x = gmc_sanitize(gmc_mv[0].x, dec->quarterpel, fcode); mb->mvs[0].y = mb->mvs[1].y = mb->mvs[2].y = mb->mvs[3].y = gmc_sanitize(gmc_mv[0].y, dec->quarterpel, fcode); decoder_mbinter(dec, mb, x, y, 0, 0, bs, quant, rounding, reduced_resolution); @@ -1101,8 +1080,8 @@ start_timer(); if(dec->quarterpel) { - interpolate16x16_quarterpel(dec->cur.y, dec->refn[ref].y, dec->refh.y, dec->refh.y + 64, - dec->refh.y + 128, 16*x_pos, 16*y_pos, + interpolate16x16_quarterpel(dec->cur.y, dec->refn[ref].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 { @@ -1256,21 +1235,21 @@ start_timer(); if(dec->quarterpel) { if((pMB->mode == MODE_INTER || pMB->mode == MODE_INTER_Q)) - interpolate16x16_quarterpel(dec->cur.y, forward.y, dec->refh.y, dec->refh.y + 64, - dec->refh.y + 128, 16*x_pos, 16*y_pos, + 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->refh.y, dec->refh.y + 64, - dec->refh.y + 128, 16*x_pos, 16*y_pos, + 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->refh.y, dec->refh.y + 64, - dec->refh.y + 128, 16*x_pos + 8, 16*y_pos, + 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->refh.y, dec->refh.y + 64, - dec->refh.y + 128, 16*x_pos, 16*y_pos + 8, + 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->refh.y, dec->refh.y + 64, - dec->refh.y + 128, 16*x_pos + 8, 16*y_pos + 8, + 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); } } @@ -1294,71 +1273,71 @@ if(dec->quarterpel) { if((pMB->mode == MODE_INTER || pMB->mode == MODE_INTER_Q)) - interpolate16x16_quarterpel(dec->refn[2].y, backward.y, dec->refh.y, dec->refh.y + 64, - dec->refh.y + 128, 16*x_pos, 16*y_pos, + interpolate16x16_quarterpel(dec->tmp.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_quarterpel(dec->refn[2].y, backward.y, dec->refh.y, dec->refh.y + 64, - dec->refh.y + 128, 16*x_pos, 16*y_pos, + interpolate8x8_quarterpel(dec->tmp.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_quarterpel(dec->refn[2].y, backward.y, dec->refh.y, dec->refh.y + 64, - dec->refh.y + 128, 16*x_pos + 8, 16*y_pos, + interpolate8x8_quarterpel(dec->tmp.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_quarterpel(dec->refn[2].y, backward.y, dec->refh.y, dec->refh.y + 64, - dec->refh.y + 128, 16*x_pos, 16*y_pos + 8, + interpolate8x8_quarterpel(dec->tmp.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_quarterpel(dec->refn[2].y, backward.y, dec->refh.y, dec->refh.y + 64, - dec->refh.y + 128, 16*x_pos + 8, 16*y_pos + 8, + interpolate8x8_quarterpel(dec->tmp.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_switch(dec->refn[2].y, backward.y, 16 * x_pos, 16 * y_pos, + interpolate8x8_switch(dec->tmp.y, backward.y, 16 * x_pos, 16 * y_pos, pMB->b_mvs[0].x, pMB->b_mvs[0].y, stride, 0); - interpolate8x8_switch(dec->refn[2].y, backward.y, 16 * x_pos + 8, + interpolate8x8_switch(dec->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(dec->refn[2].y, backward.y, 16 * x_pos, + interpolate8x8_switch(dec->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(dec->refn[2].y, backward.y, 16 * x_pos + 8, + interpolate8x8_switch(dec->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(dec->refn[2].u, backward.u, 8 * x_pos, 8 * y_pos, + interpolate8x8_switch(dec->tmp.u, backward.u, 8 * x_pos, 8 * y_pos, b_uv_dx, b_uv_dy, stride2, 0); - interpolate8x8_switch(dec->refn[2].v, backward.v, 8 * x_pos, 8 * y_pos, + interpolate8x8_switch(dec->tmp.v, backward.v, 8 * x_pos, 8 * y_pos, b_uv_dx, b_uv_dy, stride2, 0); interpolate8x8_avg2(dec->cur.y + (16 * y_pos * stride) + 16 * x_pos, dec->cur.y + (16 * y_pos * stride) + 16 * x_pos, - dec->refn[2].y + (16 * y_pos * stride) + 16 * x_pos, + dec->tmp.y + (16 * y_pos * stride) + 16 * x_pos, stride, 1, 8); interpolate8x8_avg2(dec->cur.y + (16 * y_pos * stride) + 16 * x_pos + 8, dec->cur.y + (16 * y_pos * stride) + 16 * x_pos + 8, - dec->refn[2].y + (16 * y_pos * stride) + 16 * x_pos + 8, + dec->tmp.y + (16 * y_pos * stride) + 16 * x_pos + 8, stride, 1, 8); interpolate8x8_avg2(dec->cur.y + ((16 * y_pos + 8) * stride) + 16 * x_pos, dec->cur.y + ((16 * y_pos + 8) * stride) + 16 * x_pos, - dec->refn[2].y + ((16 * y_pos + 8) * stride) + 16 * x_pos, + dec->tmp.y + ((16 * y_pos + 8) * stride) + 16 * x_pos, stride, 1, 8); interpolate8x8_avg2(dec->cur.y + ((16 * y_pos + 8) * stride) + 16 * x_pos + 8, dec->cur.y + ((16 * y_pos + 8) * stride) + 16 * x_pos + 8, - dec->refn[2].y + ((16 * y_pos + 8) * stride) + 16 * x_pos + 8, + dec->tmp.y + ((16 * y_pos + 8) * stride) + 16 * x_pos + 8, stride, 1, 8); interpolate8x8_avg2(dec->cur.u + (8 * y_pos * stride2) + 8 * x_pos, dec->cur.u + (8 * y_pos * stride2) + 8 * x_pos, - dec->refn[2].u + (8 * y_pos * stride2) + 8 * x_pos, + dec->tmp.u + (8 * y_pos * stride2) + 8 * x_pos, stride2, 1, 8); interpolate8x8_avg2(dec->cur.v + (8 * y_pos * stride2) + 8 * x_pos, dec->cur.v + (8 * y_pos * stride2) + 8 * x_pos, - dec->refn[2].v + (8 * y_pos * stride2) + 8 * x_pos, + dec->tmp.v + (8 * y_pos * stride2) + 8 * x_pos, stride2, 1, 8); stop_comp_timer(); @@ -1488,7 +1467,9 @@ 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 ? + // skip if the co-located P_VOP macroblock is not coded + // note: gmc+not_coded isn't skipped + if (last_mb->mode == MODE_NOT_CODED) { //DEBUG2("Skip MB in B-frame at (X,Y)=!",x,y); mb->cbp = 0; @@ -1602,7 +1583,7 @@ break; default: - DEBUG1("Not support B-frame mb_type =", mb->mb_type); + DPRINTF(DPRINTF_ERROR,"Not support B-frame mb_type = %i", mb->mb_type); } } // end of FOR @@ -1627,6 +1608,28 @@ *mb2 = temp; } + +/* perform post processing if necessary, and output the image */ +void decoder_output(DECODER * dec, IMAGE * img, MACROBLOCK * mbs, + const XVID_DEC_FRAME * frame, int pp_disable) +{ + + if ((frame->general & (XVID_DEC_DEBLOCKY|XVID_DEC_DEBLOCKUV)) && !pp_disable) /* post process */ + { + /* note: image is stored to tmp */ + image_copy(&dec->tmp, img, dec->edged_width, dec->height); + image_deblock_rrv(&dec->tmp, dec->edged_width, + mbs, dec->mb_width, dec->mb_height, dec->mb_width, + 8, frame->general); + img = &dec->tmp; + } + + image_output(img, dec->width, dec->height, + dec->edged_width, frame->image, frame->stride, + frame->colorspace, dec->interlacing); +} + + int decoder_decode(DECODER * dec, XVID_DEC_FRAME * frame, XVID_DEC_STATS * stats) @@ -1642,15 +1645,45 @@ 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; + if ((frame->general & XVID_DEC_DISCONTINUITY)) + dec->frames = 0; + + if (frame->length < 0) /* decoder flush */ + { + /* if not decoding "low_delay/packed", and this isn't low_delay and + we have a reference frame, then outout the reference frame */ + if (!(dec->low_delay_default && dec->packed_mode) && !dec->low_delay && dec->frames>0) + { + decoder_output(dec, &dec->refn[0], dec->mbs, frame, dec->last_reduced_resolution); + output = 1; + } + + frame->length = 0; + if (stats) + { + 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 + } + + emms(); + + stop_global_timer(); + return XVID_ERR_OK; + } + BitstreamInit(&bs, frame->bitstream, frame->length); // XXX: 0x7f is only valid whilst decoding vfw xvid/divx5 avi's - if(frame->length == 1 && BitstreamShowBits(&bs, 8) == 0x7f) + if(dec->low_delay_default && frame->length == 1 && BitstreamShowBits(&bs, 8) == 0x7f) { if (stats) stats->notify = XVID_DEC_VOP; @@ -1661,20 +1694,20 @@ return XVID_ERR_OK; } -start: - // add by chenm001 - // for support B-frame to reference last 2 frame - dec->frames++; +repeat: -xxx: - vop_type = - BitstreamReadHeaders(&bs, dec, &rounding, &reduced_resolution, + 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; + emms(); + return XVID_ERR_FAIL; + } if (vop_type == -2 || vop_type == -3) { @@ -1693,191 +1726,145 @@ stats->data.vol.par_width = dec->par_width; stats->data.vol.par_height = dec->par_height; frame->length = BitstreamPos(&bs) / 8; + emms(); return XVID_ERR_OK; } - goto xxx; + goto repeat; } 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 && dec->frames > 0) + { + decoder_output(dec, &dec->refn[0], dec->last_mbs, frame, dec->last_reduced_resolution); + 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, + 16, XVID_DEC_DEBLOCKY|XVID_DEC_DEBLOCKUV); } - /* 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); + decoder_output(dec, &dec->cur, dec->mbs, frame, reduced_resolution); + 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); + /* output the reference frame */ + decoder_output(dec, &dec->refn[0], dec->last_mbs, frame, dec->last_reduced_resolution); + output = 1; } } - } - BitstreamByteAlign(&bs); + image_swap(&dec->refn[0], &dec->refn[1]); + image_swap(&dec->cur, &dec->refn[0]); + mb_swap(&dec->mbs, &dec->last_mbs); + dec->last_reduced_resolution = reduced_resolution; -#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); + dec->frames++; + seen_something = 1; -#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); - } - stop_conv_timer(); + }else{ /* B_VOP */ + + if (dec->low_delay) + { + DPRINTF(DPRINTF_ERROR, "warning: bvop found in low_delay==1 stream"); + dec->low_delay = 1; } - } -#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]); + if (dec->frames < 2) + { + /* attemping to decode a bvop without atleast 2 reference frames */ + image_printf(&dec->cur, dec->edged_width, dec->height, 16, 16, + "broken b-frame, mising ref frames"); + }else 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); + } - // 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); + decoder_output(dec, &dec->cur, dec->mbs, frame, reduced_resolution); + output = 1; + dec->frames++; } + 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; + goto repeat; } 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 */ + decoder_output(dec, &dec->refn[0], dec->last_mbs, frame, dec->last_reduced_resolution); + output = 1; + } + else + { + image_clear(&dec->cur, dec->width, dec->height, dec->edged_width, 0, 128, 128); + 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"); + + decoder_output(dec, &dec->cur, NULL, frame, 1 /*disable pp*/); + } + } + 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 } - + emms(); stop_global_timer();