--- decoder.c 2005/03/27 03:59:41 1.69 +++ decoder.c 2005/08/01 18:37:46 1.72 @@ -20,7 +20,7 @@ * along with this program ; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * - * $Id: decoder.c,v 1.69 2005/03/27 03:59:41 suxen_drol Exp $ + * $Id: decoder.c,v 1.72 2005/08/01 18:37:46 Isibaar Exp $ * ****************************************************************************/ @@ -73,12 +73,20 @@ image_destroy(&dec->gmc, dec->edged_width, dec->edged_height); - if (dec->last_mbs) - xvid_free(dec->last_mbs); - if (dec->mbs) - xvid_free(dec->mbs); - if (dec->qscale) - xvid_free(dec->qscale); + image_null(&dec->cur); + image_null(&dec->refn[0]); + image_null(&dec->refn[1]); + image_null(&dec->tmp); + image_null(&dec->qtmp); + image_null(&dec->gmc); + + + xvid_free(dec->last_mbs); + xvid_free(dec->mbs); + xvid_free(dec->qscale); + dec->last_mbs = NULL; + dec->mbs = NULL; + dec->qscale = NULL; /* realloc */ dec->mb_width = (dec->width + 15) / 16; @@ -87,80 +95,27 @@ dec->edged_width = 16 * dec->mb_width + 2 * EDGE_SIZE; dec->edged_height = 16 * dec->mb_height + 2 * EDGE_SIZE; - if (image_create(&dec->cur, dec->edged_width, dec->edged_height)) { - xvid_free(dec); - return XVID_ERR_MEMORY; - } - - if (image_create(&dec->refn[0], dec->edged_width, dec->edged_height)) { - image_destroy(&dec->cur, dec->edged_width, dec->edged_height); - xvid_free(dec); - return XVID_ERR_MEMORY; - } - - /* Support B-frame to reference last 2 frame */ - if (image_create(&dec->refn[1], 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); - xvid_free(dec); - return XVID_ERR_MEMORY; - } - 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); - xvid_free(dec); - return XVID_ERR_MEMORY; - } - - 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->tmp, dec->edged_width, dec->edged_height); - xvid_free(dec); - return XVID_ERR_MEMORY; - } - - if (image_create(&dec->gmc, 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); - 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->tmp, dec->edged_width, dec->edged_height); - xvid_free(dec); - return XVID_ERR_MEMORY; - } + if ( image_create(&dec->cur, dec->edged_width, dec->edged_height) + || image_create(&dec->refn[0], dec->edged_width, dec->edged_height) + || image_create(&dec->refn[1], dec->edged_width, dec->edged_height) /* Support B-frame to reference last 2 frame */ + || image_create(&dec->tmp, dec->edged_width, dec->edged_height) + || image_create(&dec->qtmp, dec->edged_width, dec->edged_height) + || image_create(&dec->gmc, dec->edged_width, dec->edged_height) ) + goto memory_error; dec->mbs = xvid_malloc(sizeof(MACROBLOCK) * dec->mb_width * dec->mb_height, CACHE_LINE); - if (dec->mbs == NULL) { - 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->tmp, dec->edged_width, dec->edged_height); - image_destroy(&dec->qtmp, dec->edged_width, dec->edged_height); - xvid_free(dec); - return XVID_ERR_MEMORY; - } + if (dec->mbs == NULL) + goto memory_error; memset(dec->mbs, 0, sizeof(MACROBLOCK) * dec->mb_width * dec->mb_height); /* For skip MB flag */ dec->last_mbs = xvid_malloc(sizeof(MACROBLOCK) * dec->mb_width * dec->mb_height, CACHE_LINE); - if (dec->last_mbs == NULL) { - xvid_free(dec->mbs); - 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->tmp, dec->edged_width, dec->edged_height); - image_destroy(&dec->qtmp, dec->edged_width, dec->edged_height); - xvid_free(dec); - return XVID_ERR_MEMORY; - } - + if (dec->last_mbs == NULL) + goto memory_error; memset(dec->last_mbs, 0, sizeof(MACROBLOCK) * dec->mb_width * dec->mb_height); /* nothing happens if that fails */ @@ -171,6 +126,19 @@ memset(dec->qscale, 0, sizeof(int) * dec->mb_width * dec->mb_height); return 0; + +memory_error: + /* Most structures were deallocated / nullifieded, so it should be safe */ + /* decoder_destroy(dec) minus the write_timer */ + xvid_free(dec->mbs); + 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->tmp, dec->edged_width, dec->edged_height); + image_destroy(&dec->qtmp, dec->edged_width, dec->edged_height); + + xvid_free(dec); + return XVID_ERR_MEMORY; } @@ -475,6 +443,10 @@ CHECK_MV(mv[3]); } +/* Up to this version, chroma rounding was wrong with qpel. + * So we try to be backward compatible to avoid artifacts */ +#define BS_VERSION_BUGGY_CHROMA_ROUNDING 1 + /* decode an inter macroblock */ static void decoder_mbinter(DECODER * dec, @@ -510,8 +482,14 @@ uv_dx = mv[0].x; uv_dy = mv[0].y; if (dec->quarterpel) { - uv_dx /= 2; - uv_dy /= 2; + 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); + } + else { + uv_dx /= 2; + uv_dy /= 2; + } } uv_dx = (uv_dx >> 1) + roundtab_79[uv_dx & 0x3]; uv_dy = (uv_dy >> 1) + roundtab_79[uv_dy & 0x3]; @@ -527,8 +505,18 @@ } else { /* MODE_INTER4V */ if(dec->quarterpel) { - uv_dx = (mv[0].x / 2) + (mv[1].x / 2) + (mv[2].x / 2) + (mv[3].x / 2); - uv_dy = (mv[0].y / 2) + (mv[1].y / 2) + (mv[2].y / 2) + (mv[3].y / 2); + if (dec->bs_version <= BS_VERSION_BUGGY_CHROMA_ROUNDING) { + int z; + uv_dx = 0; uv_dy = 0; + for (z = 0; z < 4; z++) { + uv_dx += ((mv[z].x>>1) | (mv[z].x&1)); + uv_dy += ((mv[z].y>>1) | (mv[z].y&1)); + } + } + else { + uv_dx = (mv[0].x / 2) + (mv[1].x / 2) + (mv[2].x / 2) + (mv[3].x / 2); + uv_dy = (mv[0].y / 2) + (mv[1].y / 2) + (mv[2].y / 2) + (mv[3].y / 2); + } } else { uv_dx = mv[0].x + mv[1].x + mv[2].x + mv[3].x; uv_dy = mv[0].y + mv[1].y + mv[2].y + mv[3].y; @@ -980,10 +968,18 @@ b_uv_dy = pMB->b_mvs[0].y; if (dec->quarterpel) { - uv_dx /= 2; - uv_dy /= 2; - b_uv_dx /= 2; - b_uv_dy /= 2; + 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]; @@ -998,10 +994,18 @@ b_uv_dy = pMB->b_mvs[0].y + pMB->b_mvs[1].y + pMB->b_mvs[2].y + pMB->b_mvs[3].y; if (dec->quarterpel) { - uv_dx /= 2; - uv_dy /= 2; - b_uv_dx /= 2; - b_uv_dy /= 2; + 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 >> 3) + roundtab_76[uv_dx & 0xf]; @@ -1155,7 +1159,7 @@ MACROBLOCK *mb = &dec->mbs[y * dec->mb_width + x]; MACROBLOCK *last_mb = &dec->last_mbs[y * dec->mb_width + x]; const int fcode_max = (fcode_forward>fcode_backward) ? fcode_forward : fcode_backward; - uint32_t intra_dc_threshold; /* fake variable */ + int32_t intra_dc_threshold; /* fake variable */ if (check_resync_marker(bs, fcode_max - 1)) { int bound = read_video_packet_header(bs, dec, fcode_max - 1, &quant,