diff --git a/encoder/encoder.c b/encoder/encoder.c index 0ec21d0..a1f9a3d 100644 --- a/encoder/encoder.c +++ b/encoder/encoder.c @@ -633,17 +633,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 ); @@ -694,10 +688,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; @@ -782,11 +773,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 ) { @@ -797,8 +791,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; } } @@ -809,6 +802,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; } /**************************************************************************** @@ -1402,7 +1414,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 ac677a9..8d19cf3 100644 --- a/encoder/ratecontrol.c +++ b/encoder/ratecontrol.c @@ -292,7 +292,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 ) { @@ -392,7 +392,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 */ @@ -406,7 +406,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 */ @@ -416,7 +416,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++; @@ -425,7 +425,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, @@ -452,7 +452,7 @@ int x264_ratecontrol_new( x264_t *h ) else if( h->param.i_bframe ) { x264_log( h, X264_LOG_ERROR, "b_adapt method specified in stats file not valid\n" ); - return -1; + goto fail3; } if( ( p = strstr( opts, "scenecut=" ) ) && sscanf( p, "scenecut=%d", &i ) && i >= -1 && i <= 100 ) @@ -463,7 +463,7 @@ int x264_ratecontrol_new( x264_t *h ) else { x264_log( h, X264_LOG_ERROR, "scenecut method specified in stats file not valid\n" ); - return -1; + goto fail3; } } @@ -474,7 +474,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; @@ -487,7 +487,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 and frames delayed by multithreading */ @@ -526,7 +526,7 @@ int x264_ratecontrol_new( x264_t *h ) if(frame_number < 0 || frame_number >= rc->num_entries + h->param.i_bframe*4 + X264_THREAD_MAX) { 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; @@ -548,7 +548,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; @@ -558,7 +558,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 */ } @@ -577,7 +578,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 ); @@ -597,6 +598,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 ) @@ -632,6 +655,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; @@ -643,7 +668,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, UNUSED *saveptr; char *psz_zones = x264_malloc( strlen(h->param.rc.psz_zones)+1 ); @@ -657,7 +682,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 ); @@ -672,13 +701,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; } } @@ -701,6 +730,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 )