--- decoder.c 2004/12/05 13:56:13 1.68 +++ decoder.c 2005/05/23 09:29:43 1.71 @@ -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.68 2004/12/05 13:56:13 syskin Exp $ + * $Id: decoder.c,v 1.71 2005/05/23 09:29:43 Skal 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; } @@ -1155,7 +1123,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, @@ -1384,7 +1352,13 @@ coding_type = BitstreamReadHeaders(&bs, dec, &rounding, &quant, &fcode_forward, &fcode_backward, &intra_dc_threshold, &gmc_warp); - DPRINTF(XVID_DEBUG_HEADER, "coding_type=%i, packed=%i, time=%lli, time_pp=%i, time_bp=%i\n", + DPRINTF(XVID_DEBUG_HEADER, "coding_type=%i, packed=%i, time=%" +#if defined(_MSC_VER) + "I64" +#else + "ll" +#endif + "i, time_pp=%i, time_bp=%i\n", coding_type, dec->packed_mode, dec->time, dec->time_pp, dec->time_bp); if (coding_type == -1) { /* nothing */ @@ -1511,19 +1485,22 @@ 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 */ + /* if we reach here without outputing anything _and_ + the calling application has specified low_delay_default, + we *must* output something. + this always occurs on the first call to decode() call + when bframes are present in the bitstream. it may also + occur if no vops were seen in the bitstream + + if packed_mode is enabled, then we output the recently + decoded frame (the very first ivop). otherwise we have + nothing to display, and therefore output a black screen. + */ + if (dec->low_delay_default && output == 0) { + if (dec->packed_mode && seen_something) { decoder_output(dec, &dec->refn[0], dec->last_mbs, frame, stats, dec->last_coding_type, quant); - } else { + } 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, stats, P_VOP, quant); if (stats) stats->type = XVID_TYPE_NOTHING; }