diff --git a/encoder/encoder.c b/encoder/encoder.c index d991a5e..2809bb5 100644 --- a/encoder/encoder.c +++ b/encoder/encoder.c @@ -667,6 +667,11 @@ x264_t *x264_encoder_open ( x264_param_t *param ) if( x264_cqm_init( h ) < 0 ) { + x264_cqm_delete( h ); //Call it because x264_cqm_init doesn't release allocated resources when fail + 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 ); x264_free( h ); return NULL; } @@ -746,11 +751,39 @@ 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 ) + { + 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 ); + for( ; i >= 0; i-- ) + { + x264_frame_delete( h->thread[i]->fdec ); + x264_macroblock_cache_end( h->thread[i] ); //Does it OK to call this on the first pass (when x264_macroblock_cache_init fail)? + x264_free( h->thread[i]->out.p_bitstream ); + x264_free( h->thread[i] ); + } return NULL; + } } if( x264_ratecontrol_new( h ) < 0 ) + { + 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 ); + 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 ); + x264_free( h->thread[i] ); + } return NULL; + } if( h->param.psz_dump_yuv ) { @@ -761,7 +794,18 @@ 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 ); + 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 ); + 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 ); + x264_free( h->thread[i] ); + } return NULL; } } @@ -1347,7 +1391,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 28ca1be..f269a4f 100644 --- a/encoder/ratecontrol.c +++ b/encoder/ratecontrol.c @@ -283,6 +283,8 @@ 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"); + x264_free( rc ); + h->rc = NULL; return -1; } if( h->param.rc.i_vbv_buffer_size ) @@ -379,6 +381,10 @@ int x264_ratecontrol_new( x264_t *h ) if( parse_zones( h ) < 0 ) { x264_log( h, X264_LOG_ERROR, "failed to parse zones\n" ); + x264_free( rc->pred ); + x264_free( rc->pred_b_from_p ); + x264_free( rc ); + h->rc = NULL; return -1; } @@ -393,6 +399,19 @@ int x264_ratecontrol_new( x264_t *h ) if( !stats_buf ) { x264_log(h, X264_LOG_ERROR, "ratecontrol_init: can't open stats file\n"); + 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 ); + } + x264_free( rc->pred ); + x264_free( rc->pred_b_from_p ); + x264_free( rc ); + h->rc = NULL; return -1; } @@ -403,7 +422,22 @@ int x264_ratecontrol_new( x264_t *h ) char *opts = stats_buf; stats_in = strchr( stats_buf, '\n' ); if( !stats_in ) + { + 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 ); + } + x264_free( rc->pred ); + x264_free( rc->pred_b_from_p ); + x264_free( rc ); + h->rc = NULL; return -1; + } *stats_in = '\0'; stats_in++; @@ -412,6 +446,19 @@ 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 ); + 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 ); + } + x264_free( rc->pred ); + x264_free( rc->pred_b_from_p ); + x264_free( rc ); + h->rc = NULL; return -1; } @@ -436,6 +483,19 @@ int x264_ratecontrol_new( x264_t *h ) if(i==0) { x264_log(h, X264_LOG_ERROR, "empty stats file\n"); + 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 ); + } + x264_free( rc->pred ); + x264_free( rc->pred_b_from_p ); + x264_free( rc ); + h->rc = NULL; return -1; } rc->num_entries = i; @@ -449,6 +509,19 @@ 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 ); + 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 ); + } + x264_free( rc->pred ); + x264_free( rc->pred_b_from_p ); + x264_free( rc ); + h->rc = NULL; return -1; } @@ -490,6 +563,20 @@ 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); + x264_free( rc->entry ); + 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 ); + } + x264_free( rc->pred ); + x264_free( rc->pred_b_from_p ); + x264_free( rc ); + h->rc = NULL; return -1; } rce = &rc->entry[frame_number]; @@ -512,6 +599,20 @@ 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); + x264_free( rc->entry ); + 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 ); + } + x264_free( rc->pred ); + x264_free( rc->pred_b_from_p ); + x264_free( rc ); + h->rc = NULL; return -1; } rce->qscale = qp2qscale(qp); @@ -522,7 +623,24 @@ 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) + { + x264_free( rc->entry ); + 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 ); + } + x264_free( rc->pred ); + x264_free( rc->pred_b_from_p ); + x264_free( rc ); + h->rc = NULL; + return -1; + } } /* else we're using constant quant, so no need to run the bitrate allocation */ } @@ -541,6 +659,21 @@ 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"); + x264_free( rc->psz_stat_file_tmpname ); + x264_free( rc->entry ); + 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 ); + } + x264_free( rc->pred ); + x264_free( rc->pred_b_from_p ); + x264_free( rc ); + h->rc = NULL; return -1; } @@ -594,6 +727,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; @@ -619,7 +754,14 @@ static int parse_zones( x264_t *h ) { tok = strtok_r( p, "/", &saveptr ); if( !tok || parse_zone( h, &h->param.rc.zones[i], tok ) ) + { + for( ; i>=0; i-- ) //Maybe start from i-1? + x264_free( h->param.rc.zones[i].param ); + x264_free( h->param.rc.zones ); + h->param.rc.zones = NULL; + x264_free( psz_zones ); return -1; + } p = NULL; } x264_free( psz_zones ); @@ -634,12 +776,22 @@ 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 ); + 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; return -1; } 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 ); + 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; return -1; } }