diff --git a/encoder/encoder.c b/encoder/encoder.c index b359e3f..9404652 100644 --- a/encoder/encoder.c +++ b/encoder/encoder.c @@ -625,17 +625,11 @@ x264_t *x264_encoder_open ( x264_param_t *param ) memcpy( &h->param, param, sizeof( x264_param_t ) ); if( x264_validate_parameters( h ) < 0 ) - { - x264_free( h ); - return NULL; - } + goto fail1; if( h->param.psz_cqm_file ) if( x264_cqm_parse_file( h, h->param.psz_cqm_file ) < 0 ) - { - x264_free( h ); - return NULL; - } + goto fail1; if( h->param.rc.psz_stat_out ) h->param.rc.psz_stat_out = strdup( h->param.rc.psz_stat_out ); @@ -686,10 +680,7 @@ x264_t *x264_encoder_open ( x264_param_t *param ) x264_validate_levels( h, 1 ); if( x264_cqm_init( h ) < 0 ) - { - x264_free( h ); - return NULL; - } + goto fail2; h->mb.i_mb_count = h->sps->i_mb_width * h->sps->i_mb_height; @@ -769,11 +760,14 @@ x264_t *x264_encoder_open ( x264_param_t *param ) h->thread[i]->fdec = x264_frame_pop_unused( h ); h->thread[i]->out.p_bitstream = x264_malloc( h->out.i_bitstream ); if( x264_macroblock_cache_init( h->thread[i] ) < 0 ) - return NULL; + { + h->param.i_threads = i + 1; + goto fail3; + } } if( x264_ratecontrol_new( h ) < 0 ) - return NULL; + goto fail3; if( h->param.psz_dump_yuv ) { @@ -784,8 +778,7 @@ x264_t *x264_encoder_open ( x264_param_t *param ) else { x264_log( h, X264_LOG_ERROR, "can't write to fdec.yuv\n" ); - x264_free( h ); - return NULL; + goto fail3; } } @@ -796,6 +789,25 @@ x264_t *x264_encoder_open ( x264_param_t *param ) "High 4:4:4 Predictive", h->sps->i_level_idc/10, h->sps->i_level_idc%10 ); return h; + +fail3: + for( i = h->param.i_threads - 1; i >= 0; i-- ) + { + x264_frame_delete( h->thread[i]->fdec ); + x264_macroblock_cache_end( h->thread[i] ); + x264_free( h->thread[i]->out.p_bitstream ); + if( i ) + x264_free( h->thread[i] ); + } +fail2: + x264_cqm_delete( h ); + if( h->param.rc.psz_stat_out ) + free( h->param.rc.psz_stat_out ); + if( h->param.rc.psz_stat_in ) + free( h->param.rc.psz_stat_in ); +fail1: + x264_free( h ); + return NULL; } /**************************************************************************** @@ -1376,7 +1388,10 @@ int x264_encoder_encode( x264_t *h, x264_frame_t *fenc = x264_frame_pop_unused( h ); if( x264_frame_copy_picture( h, fenc, pic_in ) < 0 ) + { + x264_frame_push_unused( h, fenc ); return -1; + } if( h->param.i_width != 16 * h->sps->i_mb_width || h->param.i_height != 16 * h->sps->i_mb_height ) diff --git a/encoder/ratecontrol.c b/encoder/ratecontrol.c index 2d75471..b4969c7 100644 --- a/encoder/ratecontrol.c +++ b/encoder/ratecontrol.c @@ -253,7 +253,7 @@ int x264_ratecontrol_new( x264_t *h ) if( h->param.rc.i_rc_method == X264_RC_CRF && h->param.rc.b_stat_read ) { x264_log(h, X264_LOG_ERROR, "constant rate-factor is incompatible with 2pass.\n"); - return -1; + goto fail1; } if( h->param.rc.i_vbv_buffer_size ) { @@ -349,7 +349,7 @@ int x264_ratecontrol_new( x264_t *h ) if( parse_zones( h ) < 0 ) { x264_log( h, X264_LOG_ERROR, "failed to parse zones\n" ); - return -1; + goto fail2; } /* Load stat file and init 2pass algo */ @@ -363,7 +363,7 @@ int x264_ratecontrol_new( x264_t *h ) if( !stats_buf ) { x264_log(h, X264_LOG_ERROR, "ratecontrol_init: can't open stats file\n"); - return -1; + goto fail3; } /* check whether 1st pass options were compatible with current options */ @@ -373,7 +373,7 @@ int x264_ratecontrol_new( x264_t *h ) char *opts = stats_buf; stats_in = strchr( stats_buf, '\n' ); if( !stats_in ) - return -1; + goto fail3; *stats_in = '\0'; stats_in++; @@ -382,7 +382,7 @@ int x264_ratecontrol_new( x264_t *h ) { x264_log( h, X264_LOG_ERROR, "different number of B-frames than 1st pass (%d vs %d)\n", h->param.i_bframe, i ); - return -1; + goto fail3; } /* since B-adapt doesn't (yet) take into account B-pyramid, @@ -425,7 +425,7 @@ int x264_ratecontrol_new( x264_t *h ) if(i==0) { x264_log(h, X264_LOG_ERROR, "empty stats file\n"); - return -1; + goto fail3; } rc->num_entries = i; @@ -438,7 +438,7 @@ int x264_ratecontrol_new( x264_t *h ) { x264_log( h, X264_LOG_ERROR, "2nd pass has more frames than 1st pass (%d vs %d)\n", h->param.i_frame_total, rc->num_entries ); - return -1; + goto fail3; } /* FIXME: ugly padding because VfW drops delayed B-frames */ @@ -479,7 +479,7 @@ int x264_ratecontrol_new( x264_t *h ) if(frame_number < 0 || frame_number >= rc->num_entries) { x264_log(h, X264_LOG_ERROR, "bad frame number (%d) at stats line %d\n", frame_number, i); - return -1; + goto fail4; } rce = &rc->entry[frame_number]; rce->direct_mode = 0; @@ -501,7 +501,7 @@ int x264_ratecontrol_new( x264_t *h ) if(e < 10) { x264_log(h, X264_LOG_ERROR, "statistics are damaged at line %d, parser out=%d\n", i, e); - return -1; + goto fail4; } rce->qscale = qp2qscale(qp); p = next; @@ -511,7 +511,8 @@ int x264_ratecontrol_new( x264_t *h ) if(h->param.rc.i_rc_method == X264_RC_ABR) { - if(init_pass2(h) < 0) return -1; + if(init_pass2(h) < 0) + goto fail4; } /* else we're using constant quant, so no need to run the bitrate allocation */ } @@ -530,7 +531,7 @@ int x264_ratecontrol_new( x264_t *h ) if( rc->p_stat_file_out == NULL ) { x264_log(h, X264_LOG_ERROR, "ratecontrol_init: can't open stats file\n"); - return -1; + goto fail5; } p = x264_param2string( &h->param, 1 ); @@ -550,6 +551,28 @@ int x264_ratecontrol_new( x264_t *h ) } return 0; + +fail5: + x264_free( rc->psz_stat_file_tmpname ); +fail4: + x264_free( rc->entry ); +fail3: + if( rc->zones ) + { + x264_free( rc->zones[0].param ); + if( h->param.rc.psz_zones ) + for( i=1; ii_zones; i++ ) + if( rc->zones[i].param != rc->zones[0].param ) + x264_free( rc->zones[i].param ); + x264_free( rc->zones ); + } +fail2: + x264_free( rc->pred ); + x264_free( rc->pred_b_from_p ); +fail1: + x264_free( rc ); + h->rc = NULL; + return -1; } static int parse_zone( x264_t *h, x264_zone_t *z, char *p ) @@ -585,6 +608,8 @@ static int parse_zone( x264_t *h, x264_zone_t *z, char *p ) if( x264_param_parse( z->param, tok, val ) ) { x264_log( h, X264_LOG_ERROR, "invalid zone param: %s = %s\n", tok, val ); + x264_free( z->param ); + z->param = NULL; return -1; } p = NULL; @@ -596,7 +621,7 @@ static int parse_zones( x264_t *h ) { x264_ratecontrol_t *rc = h->rc; int i; - if( h->param.rc.psz_zones && !h->param.rc.i_zones ) + if( h->param.rc.psz_zones ) { char *p, *tok, *saveptr; char *psz_zones = x264_malloc( strlen(h->param.rc.psz_zones)+1 ); @@ -610,7 +635,11 @@ static int parse_zones( x264_t *h ) { tok = strtok_r( p, "/", &saveptr ); if( !tok || parse_zone( h, &h->param.rc.zones[i], tok ) ) - return -1; + { + x264_free( psz_zones ); + h->param.rc.i_zones = i + 1; //Maybe not (i + 1) but simply i? + goto fail; + } p = NULL; } x264_free( psz_zones ); @@ -625,13 +654,13 @@ static int parse_zones( x264_t *h ) { x264_log( h, X264_LOG_ERROR, "invalid zone: start=%d end=%d\n", z.i_start, z.i_end ); - return -1; + goto fail; } else if( !z.b_force_qp && z.f_bitrate_factor <= 0 ) { x264_log( h, X264_LOG_ERROR, "invalid zone: bitrate_factor=%f\n", z.f_bitrate_factor ); - return -1; + goto fail; } } @@ -654,6 +683,17 @@ static int parse_zones( x264_t *h ) } return 0; + +fail: + if( h->param.rc.psz_zones ) + { + for( i=0; iparam.rc.i_zones; i++ ) + x264_free( h->param.rc.zones[i].param ); + x264_free( h->param.rc.zones ); + } + h->param.rc.zones = NULL; + h->param.rc.i_zones = 0; + return -1; } static x264_zone_t *get_zone( x264_t *h, int frame_num )