//{ mb_analyse_int //{ mb_analyse_int //{ mb_analyse_int //{ mb_analyse_int static void dull_mb_analyse_init_P( x264_t *h, x264_mb_analysis_t *a ) { x264_mb_analyse_init_qp( h, a, h->mb.i_qp ); h->mb.b_transform_8x8 = 0; h->mb.b_noise_reduction = 0; /* I: Intra part */ a->i_satd_i16x16 = a->i_satd_i8x8 = a->i_satd_i4x4 = a->i_satd_i8x8chroma = COST_MAX; a->b_fast_intra = 0; a->b_avoid_topright = 0; h->mb.i_skip_intra = h->mb.b_lossless ? 0 : a->i_mbrd ? 2 : !h->param.analyse.i_trellis && !h->param.analyse.i_noise_reduction; /* II: Inter part P/B frame */ if( h->sh.i_type != SLICE_TYPE_I ) { int i; int i_fmv_range = 4 * h->param.analyse.i_mv_range; // limit motion search to a slightly smaller range than the theoretical limit, // since the search may go a few iterations past its given range int i_fpel_border = 6; // umh: 1 for diamond, 2 for octagon, 2 for hpel /* Calculate max allowed MV range */ #define CLIP_FMV(mv) x264_clip3( mv, -i_fmv_range, i_fmv_range-1 ) h->mb.mv_min[0] = 4*( -16*h->mb.i_mb_x - 24 ); h->mb.mv_max[0] = 4*( 16*( h->sps->i_mb_width - h->mb.i_mb_x - 1 ) + 24 ); h->mb.mv_min_spel[0] = CLIP_FMV( h->mb.mv_min[0] ); h->mb.mv_max_spel[0] = CLIP_FMV( h->mb.mv_max[0] ); if( h->param.b_intra_refresh && h->sh.i_type == SLICE_TYPE_P ) { int max_x = (h->fref0[0]->i_pir_end_col * 16 - 3)*4; /* 3 pixels of hpel border */ int max_mv = max_x - 4*16*h->mb.i_mb_x; /* If we're left of the refresh bar, don't reference right of it. */ if( max_mv > 0 && h->mb.i_mb_x < h->fdec->i_pir_start_col ) h->mb.mv_max_spel[0] = X264_MIN( h->mb.mv_max_spel[0], max_mv ); } h->mb.mv_min_fpel[0] = (h->mb.mv_min_spel[0]>>2) + i_fpel_border; h->mb.mv_max_fpel[0] = (h->mb.mv_max_spel[0]>>2) - i_fpel_border; if( h->mb.i_mb_x == 0 ) { int mb_y = h->mb.i_mb_y; int mb_height = h->sps->i_mb_height; int thread_mvy_range = i_fmv_range; h->mb.mv_min[1] = 4*( -16*mb_y - 24 ); h->mb.mv_max[1] = 4*( 16*( mb_height - mb_y - 1 ) + 24 ); h->mb.mv_min_spel[1] = x264_clip3( h->mb.mv_min[1], -i_fmv_range, i_fmv_range ); h->mb.mv_max_spel[1] = CLIP_FMV( h->mb.mv_max[1] ); h->mb.mv_max_spel[1] = X264_MIN( h->mb.mv_max_spel[1], thread_mvy_range*4 ); h->mb.mv_min_fpel[1] = (h->mb.mv_min_spel[1]>>2) + i_fpel_border; h->mb.mv_max_fpel[1] = (h->mb.mv_max_spel[1]>>2) - i_fpel_border; }
float x264_pixel_ssim_wxh( x264_pixel_function_t *pf, uint8_t *pix1, int stride1, uint8_t *pix2, int stride2, int width, int height ) { int x, y, z; float ssim = 0.0; int (*sum0)[4] = x264_malloc(4 * (width/4+3) * sizeof(int)); int (*sum1)[4] = x264_malloc(4 * (width/4+3) * sizeof(int)); width >>= 2; height >>= 2; z = 0; for( y = 1; y < height; y++ ) { for( ; z <= y; z++ ) { XCHG( void*, sum0, sum1 ); for( x = 0; x < width; x+=2 ) pf->ssim_4x4x2_core( &pix1[4*(x+z*stride1)], stride1, &pix2[4*(x+z*stride2)], stride2, &sum0[x] ); } for( x = 0; x < width-1; x += 4 ) ssim += pf->ssim_end4( sum0+x, sum1+x, X264_MIN(4,width-x-1) ); } x264_free(sum0); x264_free(sum1); return ssim / ((width-1) * (height-1)); }
static void fill_cache( cache_hnd_t *h, int frame ) { /* shift frames out of the cache as the frame request is beyond the filled cache */ int shift = frame - LAST_FRAME; /* no frames to shift or no frames left to read */ if( shift <= 0 || h->eof ) return; /* the next frames to read are either * A) starting at the end of the current cache, or * B) starting at a new frame that has the end of the cache at the desired frame * and proceeding to fill the entire cache */ int cur_frame = X264_MAX( h->first_frame + h->cur_size, frame - h->max_size + 1 ); /* the new starting point is either * A) the current one shifted the number of frames entering/leaving the cache, or * B) at a new frame that has the end of the cache at the desired frame. */ h->first_frame = X264_MIN( h->first_frame + shift, cur_frame ); h->cur_size = X264_MAX( h->cur_size - shift, 0 ); while( h->cur_size < h->max_size ) { cli_pic_t temp; /* the old front frame is going to shift off, overwrite it with the new frame */ cli_pic_t *cache = h->cache[0]; if( h->prev_filter.get_frame( h->prev_hnd, &temp, cur_frame ) || x264_cli_pic_copy( cache, &temp ) || h->prev_filter.release_frame( h->prev_hnd, &temp, cur_frame ) ) { h->eof = cur_frame; return; } /* the read was successful, shift the frame off the front to the end */ x264_frame_push( (void*)h->cache, x264_frame_shift( (void*)h->cache ) ); cur_frame++; h->cur_size++; } }
static void *x264_lookahead_thread( x264_t *h ) { while( !h->lookahead->b_exit_thread ) { x264_pthread_mutex_lock( &h->lookahead->ifbuf.mutex ); x264_pthread_mutex_lock( &h->lookahead->next.mutex ); int shift = X264_MIN( h->lookahead->next.i_max_size - h->lookahead->next.i_size, h->lookahead->ifbuf.i_size ); x264_lookahead_shift( &h->lookahead->next, &h->lookahead->ifbuf, shift ); x264_pthread_mutex_unlock( &h->lookahead->next.mutex ); if( h->lookahead->next.i_size <= h->lookahead->i_slicetype_length + h->param.b_vfr_input ) { while( !h->lookahead->ifbuf.i_size && !h->lookahead->b_exit_thread ) x264_pthread_cond_wait( &h->lookahead->ifbuf.cv_fill, &h->lookahead->ifbuf.mutex ); x264_pthread_mutex_unlock( &h->lookahead->ifbuf.mutex ); } else { x264_pthread_mutex_unlock( &h->lookahead->ifbuf.mutex ); x264_lookahead_slicetype_decide( h ); } } /* end of input frames */ x264_pthread_mutex_lock( &h->lookahead->ifbuf.mutex ); x264_pthread_mutex_lock( &h->lookahead->next.mutex ); x264_lookahead_shift( &h->lookahead->next, &h->lookahead->ifbuf, h->lookahead->ifbuf.i_size ); x264_pthread_mutex_unlock( &h->lookahead->next.mutex ); x264_pthread_mutex_unlock( &h->lookahead->ifbuf.mutex ); while( h->lookahead->next.i_size ) x264_lookahead_slicetype_decide( h ); x264_pthread_mutex_lock( &h->lookahead->ofbuf.mutex ); h->lookahead->b_thread_active = 0; x264_pthread_cond_broadcast( &h->lookahead->ofbuf.cv_fill ); x264_pthread_mutex_unlock( &h->lookahead->ofbuf.mutex ); return NULL; }
int x264_threadpool_init( x264_threadpool_t **p_pool, int threads, void (*init_func)(void *), void *init_arg ) { if( threads <= 0 ) return -1; x264_threadpool_t *pool; CHECKED_MALLOCZERO( pool, sizeof(x264_threadpool_t) ); *p_pool = pool; pool->init_func = init_func; pool->init_arg = init_arg; pool->threads = X264_MIN( threads, X264_THREAD_MAX ); CHECKED_MALLOC( pool->thread_handle, pool->threads * sizeof(x264_pthread_t) ); if( x264_sync_frame_list_init( &pool->uninit, pool->threads ) || x264_sync_frame_list_init( &pool->run, pool->threads ) || x264_sync_frame_list_init( &pool->done, pool->threads ) ) goto fail; for( int i = 0; i < pool->threads; i++ ) { x264_threadpool_job_t *job; CHECKED_MALLOC( job, sizeof(x264_threadpool_job_t) ); x264_sync_frame_list_push( &pool->uninit, (void*)job ); } for( int i = 0; i < pool->threads; i++ ) if( x264_pthread_create( pool->thread_handle+i, NULL, (void*)x264_threadpool_thread, pool ) ) goto fail; return 0; fail: return -1; }
static void x264_lookahead_thread( x264_t *h ) { int shift; #ifdef HAVE_MMX if( h->param.cpu&X264_CPU_SSE_MISALIGN ) x264_cpu_mask_misalign_sse(); #endif while( !h->lookahead->b_exit_thread ) { x264_pthread_mutex_lock( &h->lookahead->ifbuf.mutex ); x264_pthread_mutex_lock( &h->lookahead->next.mutex ); shift = X264_MIN( h->lookahead->next.i_max_size - h->lookahead->next.i_size, h->lookahead->ifbuf.i_size ); x264_lookahead_shift( &h->lookahead->next, &h->lookahead->ifbuf, shift ); x264_pthread_mutex_unlock( &h->lookahead->next.mutex ); if( h->lookahead->next.i_size <= h->lookahead->i_slicetype_length ) { while( !h->lookahead->ifbuf.i_size && !h->lookahead->b_exit_thread ) x264_pthread_cond_wait( &h->lookahead->ifbuf.cv_fill, &h->lookahead->ifbuf.mutex ); x264_pthread_mutex_unlock( &h->lookahead->ifbuf.mutex ); } else { x264_pthread_mutex_unlock( &h->lookahead->ifbuf.mutex ); x264_lookahead_slicetype_decide( h ); } } /* end of input frames */ #ifdef ERR1 x264_pthread_mutex_lock( &h->lookahead->next.mutex ); x264_pthread_mutex_lock( &h->lookahead->ifbuf.mutex ); #else x264_pthread_mutex_lock( &h->lookahead->ifbuf.mutex ); x264_pthread_mutex_lock( &h->lookahead->next.mutex ); #endif x264_lookahead_shift( &h->lookahead->next, &h->lookahead->ifbuf, h->lookahead->ifbuf.i_size ); #ifdef ERR1 x264_pthread_mutex_unlock( &h->lookahead->ifbuf.mutex ); x264_pthread_mutex_unlock( &h->lookahead->next.mutex ); #else x264_pthread_mutex_unlock( &h->lookahead->next.mutex ); x264_pthread_mutex_unlock( &h->lookahead->ifbuf.mutex ); #endif while( h->lookahead->next.i_size ) x264_lookahead_slicetype_decide( h ); x264_pthread_mutex_lock( &h->lookahead->ofbuf.mutex ); h->lookahead->b_thread_active = 0; x264_pthread_cond_broadcast( &h->lookahead->ofbuf.cv_fill ); x264_pthread_mutex_unlock( &h->lookahead->ofbuf.mutex ); }
void x264_sps_init( x264_sps_t *sps, int i_id, x264_param_t *param ) { int csp = param->i_csp & X264_CSP_MASK; sps->i_id = i_id; sps->i_mb_width = ( param->i_width + 15 ) / 16; sps->i_mb_height= ( param->i_height + 15 ) / 16; sps->i_chroma_format_idc = csp >= X264_CSP_I444 ? CHROMA_444 : csp >= X264_CSP_I422 ? CHROMA_422 : CHROMA_420; sps->b_qpprime_y_zero_transform_bypass = param->rc.i_rc_method == X264_RC_CQP && param->rc.i_qp_constant == 0; if( sps->b_qpprime_y_zero_transform_bypass || sps->i_chroma_format_idc == CHROMA_444 ) sps->i_profile_idc = PROFILE_HIGH444_PREDICTIVE; else if( sps->i_chroma_format_idc == CHROMA_422 ) sps->i_profile_idc = PROFILE_HIGH422; else if( BIT_DEPTH > 8 ) sps->i_profile_idc = PROFILE_HIGH10; else if( param->analyse.b_transform_8x8 || param->i_cqm_preset != X264_CQM_FLAT ) sps->i_profile_idc = PROFILE_HIGH; else if( param->b_cabac || param->i_bframe > 0 || param->b_interlaced || param->b_fake_interlaced || param->analyse.i_weighted_pred > 0 ) sps->i_profile_idc = PROFILE_MAIN; else sps->i_profile_idc = PROFILE_BASELINE; sps->b_constraint_set0 = sps->i_profile_idc == PROFILE_BASELINE; /* x264 doesn't support the features that are in Baseline and not in Main, * namely arbitrary_slice_order and slice_groups. */ sps->b_constraint_set1 = sps->i_profile_idc <= PROFILE_MAIN; /* Never set constraint_set2, it is not necessary and not used in real world. */ sps->b_constraint_set2 = 0; sps->b_constraint_set3 = 0; sps->i_level_idc = param->i_level_idc; if( param->i_level_idc == 9 && ( sps->i_profile_idc == PROFILE_BASELINE || sps->i_profile_idc == PROFILE_MAIN ) ) { sps->b_constraint_set3 = 1; /* level 1b with Baseline or Main profile is signalled via constraint_set3 */ sps->i_level_idc = 11; } /* Intra profiles */ if( param->i_keyint_max == 1 && sps->i_profile_idc > PROFILE_HIGH ) sps->b_constraint_set3 = 1; sps->vui.i_num_reorder_frames = param->i_bframe_pyramid ? 2 : param->i_bframe ? 1 : 0; /* extra slot with pyramid so that we don't have to override the * order of forgetting old pictures */ sps->vui.i_max_dec_frame_buffering = sps->i_num_ref_frames = X264_MIN(X264_REF_MAX, X264_MAX4(param->i_frame_reference, 1 + sps->vui.i_num_reorder_frames, param->i_bframe_pyramid ? 4 : 1, param->i_dpb_size)); sps->i_num_ref_frames -= param->i_bframe_pyramid == X264_B_PYRAMID_STRICT; if( param->i_keyint_max == 1 ) { sps->i_num_ref_frames = 0; sps->vui.i_max_dec_frame_buffering = 0; } /* number of refs + current frame */ int max_frame_num = sps->vui.i_max_dec_frame_buffering * (!!param->i_bframe_pyramid+1) + 1; /* Intra refresh cannot write a recovery time greater than max frame num-1 */ if( param->b_intra_refresh ) { int time_to_recovery = X264_MIN( sps->i_mb_width - 1, param->i_keyint_max ) + param->i_bframe - 1; max_frame_num = X264_MAX( max_frame_num, time_to_recovery+1 ); } sps->i_log2_max_frame_num = 4; while( (1 << sps->i_log2_max_frame_num) <= max_frame_num ) sps->i_log2_max_frame_num++; sps->i_poc_type = param->i_bframe || param->b_interlaced || param->i_avcintra_class ? 0 : 2; if( sps->i_poc_type == 0 ) { int max_delta_poc = (param->i_bframe + 2) * (!!param->i_bframe_pyramid + 1) * 2; sps->i_log2_max_poc_lsb = 4; while( (1 << sps->i_log2_max_poc_lsb) <= max_delta_poc * 2 ) sps->i_log2_max_poc_lsb++; } sps->b_vui = 1; sps->b_gaps_in_frame_num_value_allowed = 0; sps->b_frame_mbs_only = !(param->b_interlaced || param->b_fake_interlaced); if( !sps->b_frame_mbs_only ) sps->i_mb_height = ( sps->i_mb_height + 1 ) & ~1; sps->b_mb_adaptive_frame_field = param->b_interlaced; sps->b_direct8x8_inference = 1; sps->crop.i_left = param->crop_rect.i_left; sps->crop.i_top = param->crop_rect.i_top; sps->crop.i_right = param->crop_rect.i_right + sps->i_mb_width*16 - param->i_width; sps->crop.i_bottom = (param->crop_rect.i_bottom + sps->i_mb_height*16 - param->i_height) >> !sps->b_frame_mbs_only; sps->b_crop = sps->crop.i_left || sps->crop.i_top || sps->crop.i_right || sps->crop.i_bottom; sps->vui.b_aspect_ratio_info_present = 0; if( param->vui.i_sar_width > 0 && param->vui.i_sar_height > 0 ) { sps->vui.b_aspect_ratio_info_present = 1; sps->vui.i_sar_width = param->vui.i_sar_width; sps->vui.i_sar_height= param->vui.i_sar_height; } sps->vui.b_overscan_info_present = param->vui.i_overscan > 0 && param->vui.i_overscan <= 2; if( sps->vui.b_overscan_info_present ) sps->vui.b_overscan_info = ( param->vui.i_overscan == 2 ? 1 : 0 ); sps->vui.b_signal_type_present = 0; sps->vui.i_vidformat = ( param->vui.i_vidformat >= 0 && param->vui.i_vidformat <= 5 ? param->vui.i_vidformat : 5 ); sps->vui.b_fullrange = ( param->vui.b_fullrange >= 0 && param->vui.b_fullrange <= 1 ? param->vui.b_fullrange : ( csp >= X264_CSP_BGR ? 1 : 0 ) ); sps->vui.b_color_description_present = 0; sps->vui.i_colorprim = ( param->vui.i_colorprim >= 0 && param->vui.i_colorprim <= 9 ? param->vui.i_colorprim : 2 ); sps->vui.i_transfer = ( param->vui.i_transfer >= 0 && param->vui.i_transfer <= 15 ? param->vui.i_transfer : 2 ); sps->vui.i_colmatrix = ( param->vui.i_colmatrix >= 0 && param->vui.i_colmatrix <= 10 ? param->vui.i_colmatrix : ( csp >= X264_CSP_BGR ? 0 : 2 ) ); if( sps->vui.i_colorprim != 2 || sps->vui.i_transfer != 2 || sps->vui.i_colmatrix != 2 ) { sps->vui.b_color_description_present = 1; } if( sps->vui.i_vidformat != 5 || sps->vui.b_fullrange || sps->vui.b_color_description_present ) { sps->vui.b_signal_type_present = 1; } /* FIXME: not sufficient for interlaced video */ sps->vui.b_chroma_loc_info_present = param->vui.i_chroma_loc > 0 && param->vui.i_chroma_loc <= 5 && sps->i_chroma_format_idc == CHROMA_420; if( sps->vui.b_chroma_loc_info_present ) { sps->vui.i_chroma_loc_top = param->vui.i_chroma_loc; sps->vui.i_chroma_loc_bottom = param->vui.i_chroma_loc; } sps->vui.b_timing_info_present = param->i_timebase_num > 0 && param->i_timebase_den > 0; if( sps->vui.b_timing_info_present ) { sps->vui.i_num_units_in_tick = param->i_timebase_num; sps->vui.i_time_scale = param->i_timebase_den * 2; sps->vui.b_fixed_frame_rate = !param->b_vfr_input; } sps->vui.b_vcl_hrd_parameters_present = 0; // we don't support VCL HRD sps->vui.b_nal_hrd_parameters_present = !!param->i_nal_hrd; sps->vui.b_pic_struct_present = param->b_pic_struct; // NOTE: HRD related parts of the SPS are initialised in x264_ratecontrol_init_reconfigurable sps->vui.b_bitstream_restriction = param->i_keyint_max > 1; if( sps->vui.b_bitstream_restriction ) { sps->vui.b_motion_vectors_over_pic_boundaries = 1; sps->vui.i_max_bytes_per_pic_denom = 0; sps->vui.i_max_bits_per_mb_denom = 0; sps->vui.i_log2_max_mv_length_horizontal = sps->vui.i_log2_max_mv_length_vertical = (int)log2f( X264_MAX( 1, param->analyse.i_mv_range*4-1 ) ) + 1; } }
void x264_sps_init( x264_sps_t *sps, int i_id, x264_param_t *param ) { sps->i_id = i_id; sps->b_qpprime_y_zero_transform_bypass = param->rc.i_rc_method == X264_RC_CQP && param->rc.i_qp_constant == 0; if( sps->b_qpprime_y_zero_transform_bypass ) sps->i_profile_idc = PROFILE_HIGH444; else if( param->analyse.b_transform_8x8 || param->i_cqm_preset != X264_CQM_FLAT ) sps->i_profile_idc = PROFILE_HIGH; else if( param->b_cabac || param->i_bframe > 0 ) sps->i_profile_idc = PROFILE_MAIN; else sps->i_profile_idc = PROFILE_BASELINE; sps->i_level_idc = param->i_level_idc; sps->b_constraint_set0 = sps->i_profile_idc == PROFILE_BASELINE; /* x264 doesn't support the features that are in Baseline and not in Main, * namely arbitrary_slice_order and slice_groups. */ sps->b_constraint_set1 = sps->i_profile_idc <= PROFILE_MAIN; /* Never set constraint_set2, it is not necessary and not used in real world. */ sps->b_constraint_set2 = 0; sps->i_log2_max_frame_num = 4; /* at least 4 */ while( (1 << sps->i_log2_max_frame_num) <= param->i_keyint_max ) { sps->i_log2_max_frame_num++; } sps->i_log2_max_frame_num++; /* just in case */ sps->i_poc_type = 0; if( sps->i_poc_type == 0 ) { sps->i_log2_max_poc_lsb = sps->i_log2_max_frame_num + 1; /* max poc = 2*frame_num */ } else if( sps->i_poc_type == 1 ) { int i; /* FIXME */ sps->b_delta_pic_order_always_zero = 1; sps->i_offset_for_non_ref_pic = 0; sps->i_offset_for_top_to_bottom_field = 0; sps->i_num_ref_frames_in_poc_cycle = 0; for( i = 0; i < sps->i_num_ref_frames_in_poc_cycle; i++ ) { sps->i_offset_for_ref_frame[i] = 0; } } sps->b_vui = 1; sps->b_gaps_in_frame_num_value_allowed = 0; sps->i_mb_width = ( param->i_width + 15 ) / 16; sps->i_mb_height= ( param->i_height + 15 ) / 16; if( param->b_interlaced ) sps->i_mb_height = ( sps->i_mb_height + 1 ) & ~1; sps->b_frame_mbs_only = ! param->b_interlaced; sps->b_mb_adaptive_frame_field = param->b_interlaced; sps->b_direct8x8_inference = param->analyse.i_direct_8x8_inference || ! sps->b_frame_mbs_only || !(param->analyse.inter & X264_ANALYSE_PSUB8x8); sps->crop.i_left = 0; sps->crop.i_top = 0; sps->crop.i_right = sps->i_mb_width*16 - param->i_width; sps->crop.i_bottom = (sps->i_mb_height*16 - param->i_height) >> param->b_interlaced; sps->b_crop = sps->crop.i_left || sps->crop.i_top || sps->crop.i_right || sps->crop.i_bottom; sps->vui.b_aspect_ratio_info_present = 0; if( param->vui.i_sar_width > 0 && param->vui.i_sar_height > 0 ) { sps->vui.b_aspect_ratio_info_present = 1; sps->vui.i_sar_width = param->vui.i_sar_width; sps->vui.i_sar_height= param->vui.i_sar_height; } sps->vui.b_overscan_info_present = ( param->vui.i_overscan ? 1 : 0 ); if( sps->vui.b_overscan_info_present ) sps->vui.b_overscan_info = ( param->vui.i_overscan == 2 ? 1 : 0 ); sps->vui.b_signal_type_present = 0; sps->vui.i_vidformat = ( param->vui.i_vidformat <= 5 ? param->vui.i_vidformat : 5 ); sps->vui.b_fullrange = ( param->vui.b_fullrange ? 1 : 0 ); sps->vui.b_color_description_present = 0; sps->vui.i_colorprim = ( param->vui.i_colorprim <= 9 ? param->vui.i_colorprim : 2 ); sps->vui.i_transfer = ( param->vui.i_transfer <= 11 ? param->vui.i_transfer : 2 ); sps->vui.i_colmatrix = ( param->vui.i_colmatrix <= 9 ? param->vui.i_colmatrix : 2 ); if( sps->vui.i_colorprim != 2 || sps->vui.i_transfer != 2 || sps->vui.i_colmatrix != 2 ) { sps->vui.b_color_description_present = 1; } if( sps->vui.i_vidformat != 5 || sps->vui.b_fullrange || sps->vui.b_color_description_present ) { sps->vui.b_signal_type_present = 1; } /* FIXME: not sufficient for interlaced video */ sps->vui.b_chroma_loc_info_present = ( param->vui.i_chroma_loc ? 1 : 0 ); if( sps->vui.b_chroma_loc_info_present ) { sps->vui.i_chroma_loc_top = param->vui.i_chroma_loc; sps->vui.i_chroma_loc_bottom = param->vui.i_chroma_loc; } sps->vui.b_timing_info_present = 0; if( param->i_fps_num > 0 && param->i_fps_den > 0) { sps->vui.b_timing_info_present = 1; sps->vui.i_num_units_in_tick = param->i_fps_den; sps->vui.i_time_scale = param->i_fps_num * 2; sps->vui.b_fixed_frame_rate = 1; } sps->vui.i_num_reorder_frames = param->b_bframe_pyramid ? 2 : param->i_bframe ? 1 : 0; /* extra slot with pyramid so that we don't have to override the * order of forgetting old pictures */ sps->vui.i_max_dec_frame_buffering = sps->i_num_ref_frames = X264_MIN(16, X264_MAX(param->i_frame_reference, 1 + sps->vui.i_num_reorder_frames)); sps->vui.b_bitstream_restriction = 1; if( sps->vui.b_bitstream_restriction ) { sps->vui.b_motion_vectors_over_pic_boundaries = 1; sps->vui.i_max_bytes_per_pic_denom = 0; sps->vui.i_max_bits_per_mb_denom = 0; sps->vui.i_log2_max_mv_length_horizontal = sps->vui.i_log2_max_mv_length_vertical = (int)(log(param->analyse.i_mv_range*4-1)/log(2)) + 1; } }
void x264_sps_init( x264_sps_t *sps, int i_id, x264_param_t *param ) { sps->i_id = i_id; sps->b_qpprime_y_zero_transform_bypass = !param->rc.b_cbr && param->rc.i_qp_constant == 0; if( sps->b_qpprime_y_zero_transform_bypass ) sps->i_profile_idc = PROFILE_HIGH444; else if( param->analyse.b_transform_8x8 || param->i_cqm_preset != X264_CQM_FLAT ) sps->i_profile_idc = PROFILE_HIGH; else if( param->b_cabac || param->i_bframe > 0 ) sps->i_profile_idc = PROFILE_MAIN; else sps->i_profile_idc = PROFILE_BASELINE; sps->i_level_idc = param->i_level_idc; sps->b_constraint_set0 = 0; sps->b_constraint_set1 = 0; sps->b_constraint_set2 = 0; sps->i_log2_max_frame_num = 4; /* at least 4 */ while( (1 << sps->i_log2_max_frame_num) <= param->i_keyint_max ) { sps->i_log2_max_frame_num++; } sps->i_log2_max_frame_num++; /* just in case */ sps->i_poc_type = 0; if( sps->i_poc_type == 0 ) { sps->i_log2_max_poc_lsb = sps->i_log2_max_frame_num + 1; /* max poc = 2*frame_num */ } else if( sps->i_poc_type == 1 ) { int i; /* FIXME */ sps->b_delta_pic_order_always_zero = 1; sps->i_offset_for_non_ref_pic = 0; sps->i_offset_for_top_to_bottom_field = 0; sps->i_num_ref_frames_in_poc_cycle = 0; for( i = 0; i < sps->i_num_ref_frames_in_poc_cycle; i++ ) { sps->i_offset_for_ref_frame[i] = 0; } } sps->vui.i_num_reorder_frames = param->b_bframe_pyramid ? 2 : param->i_bframe ? 1 : 0; sps->vui.i_max_dec_frame_buffering = sps->i_num_ref_frames = X264_MIN(16, param->i_frame_reference + sps->vui.i_num_reorder_frames); sps->b_gaps_in_frame_num_value_allowed = 0; sps->i_mb_width = ( param->i_width + 15 ) / 16; sps->i_mb_height= ( param->i_height + 15 )/ 16; sps->b_frame_mbs_only = 1; sps->b_mb_adaptive_frame_field = 0; sps->b_direct8x8_inference = 0; if( sps->b_frame_mbs_only == 0 || !(param->analyse.inter & X264_ANALYSE_PSUB8x8) ) { sps->b_direct8x8_inference = 1; } if( param->i_width % 16 != 0 || param->i_height % 16 != 0 ) { sps->b_crop = 1; sps->crop.i_left = 0; sps->crop.i_right = ( 16 - param->i_width % 16)/2; sps->crop.i_top = 0; sps->crop.i_bottom = ( 16 - param->i_height % 16)/2; } else { sps->b_crop = 0; sps->crop.i_left = 0; sps->crop.i_right = 0; sps->crop.i_top = 0; sps->crop.i_bottom = 0; } sps->b_vui = 0; sps->vui.b_aspect_ratio_info_present = 0; if( param->vui.i_sar_width > 0 && param->vui.i_sar_height > 0 ) { sps->vui.b_aspect_ratio_info_present = 1; sps->vui.i_sar_width = param->vui.i_sar_width; sps->vui.i_sar_height= param->vui.i_sar_height; } sps->b_vui |= sps->vui.b_aspect_ratio_info_present; if( param->i_fps_num > 0 && param->i_fps_den > 0) { sps->vui.b_timing_info_present = 1; /* The standard is confusing me, but this seems to work best with other encoders */ sps->vui.i_num_units_in_tick = param->i_fps_den; sps->vui.i_time_scale = param->i_fps_num; sps->vui.b_fixed_frame_rate = 1; } sps->b_vui |= sps->vui.b_timing_info_present; sps->vui.b_bitstream_restriction = param->i_bframe > 0; if( sps->vui.b_bitstream_restriction ) { sps->vui.b_motion_vectors_over_pic_boundaries = 1; sps->vui.i_max_bytes_per_pic_denom = 0; sps->vui.i_max_bits_per_mb_denom = 0; sps->vui.i_log2_max_mv_length_horizontal = sps->vui.i_log2_max_mv_length_vertical = (int)(log(param->analyse.i_mv_range*4-1)/log(2)) + 1; } sps->b_vui |= sps->vui.b_bitstream_restriction; }
static int init( hnd_t *handle, cli_vid_filter_t *filter, video_info_t *info, x264_param_t *param, char *opt_string ) { selvry_hnd_t *h = malloc( sizeof(selvry_hnd_t) ); if( !h ) return -1; h->pattern_len = 0; h->step_size = 0; int offsets[MAX_PATTERN_SIZE]; for( char *tok, *p = opt_string; (tok = strtok( p, "," )); p = NULL ) { int val = x264_otoi( tok, -1 ); if( p ) { FAIL_IF_ERROR( val <= 0, "invalid step `%s'\n", tok ) h->step_size = val; continue; } FAIL_IF_ERROR( val < 0 || val >= h->step_size, "invalid offset `%s'\n", tok ) FAIL_IF_ERROR( h->pattern_len >= MAX_PATTERN_SIZE, "max pattern size %d reached\n", MAX_PATTERN_SIZE ) offsets[h->pattern_len++] = val; } FAIL_IF_ERROR( !h->step_size, "no step size provided\n" ) FAIL_IF_ERROR( !h->pattern_len, "no offsets supplied\n" ) h->pattern = malloc( h->pattern_len * sizeof(int) ); if( !h->pattern ) return -1; memcpy( h->pattern, offsets, h->pattern_len * sizeof(int) ); /* determine required cache size to maintain pattern. */ intptr_t max_rewind = 0; int min = h->step_size; for( int i = h->pattern_len-1; i >= 0; i-- ) { min = X264_MIN( min, offsets[i] ); if( i ) max_rewind = X264_MAX( max_rewind, offsets[i-1] - min + 1 ); /* reached maximum rewind size */ if( max_rewind == h->step_size ) break; } if( x264_init_vid_filter( "cache", handle, filter, info, param, (void*)max_rewind ) ) return -1; /* done initing, overwrite properties */ if( h->step_size != h->pattern_len ) { info->num_frames = (uint64_t)info->num_frames * h->pattern_len / h->step_size; info->fps_den *= h->step_size; info->fps_num *= h->pattern_len; x264_reduce_fraction( &info->fps_num, &info->fps_den ); if( info->vfr ) { info->timebase_den *= h->pattern_len; info->timebase_num *= h->step_size; x264_reduce_fraction( &info->timebase_num, &info->timebase_den ); } } h->pts = 0; h->vfr = info->vfr; h->prev_filter = *filter; h->prev_hnd = *handle; *filter = select_every_filter; *handle = h; return 0; }
void x264_sps_init( x264_sps_t *sps, int i_id, x264_param_t *param ) { sps->i_id = i_id; int max_frame_num; sps->b_qpprime_y_zero_transform_bypass = param->rc.i_rc_method == X264_RC_CQP && param->rc.i_qp_constant == 0; if( sps->b_qpprime_y_zero_transform_bypass ) sps->i_profile_idc = PROFILE_HIGH444_PREDICTIVE; else if( BIT_DEPTH > 8 ) sps->i_profile_idc = PROFILE_HIGH10; else if( param->analyse.b_transform_8x8 || param->i_cqm_preset != X264_CQM_FLAT ) sps->i_profile_idc = PROFILE_HIGH; else if( param->b_cabac || param->i_bframe > 0 || param->b_interlaced || param->b_fake_interlaced || param->analyse.i_weighted_pred > 0 ) sps->i_profile_idc = PROFILE_MAIN; else sps->i_profile_idc = PROFILE_BASELINE; sps->i_level_idc = param->i_level_idc; sps->b_constraint_set0 = sps->i_profile_idc == PROFILE_BASELINE; /* x264 doesn't support the features that are in Baseline and not in Main, * namely arbitrary_slice_order and slice_groups. */ sps->b_constraint_set1 = sps->i_profile_idc <= PROFILE_MAIN; /* Never set constraint_set2, it is not necessary and not used in real world. */ sps->b_constraint_set2 = 0; sps->vui.i_num_reorder_frames = param->i_bframe_pyramid ? 2 : param->i_bframe ? 1 : 0; /* extra slot with pyramid so that we don't have to override the * order of forgetting old pictures */ sps->vui.i_max_dec_frame_buffering = sps->i_num_ref_frames = X264_MIN(X264_REF_MAX, X264_MAX4(param->i_frame_reference, 1 + sps->vui.i_num_reorder_frames, param->i_bframe_pyramid ? 4 : 1, param->i_dpb_size)); sps->i_num_ref_frames -= param->i_bframe_pyramid == X264_B_PYRAMID_STRICT; /* number of refs + current frame */ max_frame_num = sps->vui.i_max_dec_frame_buffering * (!!param->i_bframe_pyramid+1) + 1; sps->i_log2_max_frame_num = 4; while( (1 << sps->i_log2_max_frame_num) <= max_frame_num ) sps->i_log2_max_frame_num++; sps->i_poc_type = 0; if( sps->i_poc_type == 0 ) { int max_delta_poc = (param->i_bframe + 2) * (!!param->i_bframe_pyramid + 1) * 2; sps->i_log2_max_poc_lsb = 4; while( (1 << sps->i_log2_max_poc_lsb) <= max_delta_poc * 2 ) sps->i_log2_max_poc_lsb++; } else if( sps->i_poc_type == 1 ) { int i; /* FIXME */ sps->b_delta_pic_order_always_zero = 1; sps->i_offset_for_non_ref_pic = 0; sps->i_offset_for_top_to_bottom_field = 0; sps->i_num_ref_frames_in_poc_cycle = 0; for( i = 0; i < sps->i_num_ref_frames_in_poc_cycle; i++ ) { sps->i_offset_for_ref_frame[i] = 0; } } sps->b_vui = 1; sps->b_gaps_in_frame_num_value_allowed = 0; sps->i_mb_width = ( param->i_width + 15 ) / 16; sps->i_mb_height= ( param->i_height + 15 ) / 16; sps->b_frame_mbs_only = !(param->b_interlaced || param->b_fake_interlaced); if( !sps->b_frame_mbs_only ) sps->i_mb_height = ( sps->i_mb_height + 1 ) & ~1; sps->b_mb_adaptive_frame_field = param->b_interlaced; sps->b_direct8x8_inference = 1; sps->crop.i_left = 0; sps->crop.i_top = 0; sps->crop.i_right = sps->i_mb_width*16 - param->i_width; sps->crop.i_bottom = (sps->i_mb_height*16 - param->i_height) >> !sps->b_frame_mbs_only; sps->b_crop = sps->crop.i_left || sps->crop.i_top || sps->crop.i_right || sps->crop.i_bottom; sps->vui.b_aspect_ratio_info_present = 0; if( param->vui.i_sar_width > 0 && param->vui.i_sar_height > 0 ) { sps->vui.b_aspect_ratio_info_present = 1; sps->vui.i_sar_width = param->vui.i_sar_width; sps->vui.i_sar_height= param->vui.i_sar_height; } sps->vui.b_overscan_info_present = ( param->vui.i_overscan ? 1 : 0 ); if( sps->vui.b_overscan_info_present ) sps->vui.b_overscan_info = ( param->vui.i_overscan == 2 ? 1 : 0 ); sps->vui.b_signal_type_present = 0; sps->vui.i_vidformat = ( param->vui.i_vidformat <= 5 ? param->vui.i_vidformat : 5 ); sps->vui.b_fullrange = ( param->vui.b_fullrange ? 1 : 0 ); sps->vui.b_color_description_present = 0; sps->vui.i_colorprim = ( param->vui.i_colorprim <= 9 ? param->vui.i_colorprim : 2 ); sps->vui.i_transfer = ( param->vui.i_transfer <= 11 ? param->vui.i_transfer : 2 ); sps->vui.i_colmatrix = ( param->vui.i_colmatrix <= 9 ? param->vui.i_colmatrix : 2 ); if( sps->vui.i_colorprim != 2 || sps->vui.i_transfer != 2 || sps->vui.i_colmatrix != 2 ) { sps->vui.b_color_description_present = 1; } if( sps->vui.i_vidformat != 5 || sps->vui.b_fullrange || sps->vui.b_color_description_present ) { sps->vui.b_signal_type_present = 1; } /* FIXME: not sufficient for interlaced video */ sps->vui.b_chroma_loc_info_present = ( param->vui.i_chroma_loc ? 1 : 0 ); if( sps->vui.b_chroma_loc_info_present ) { sps->vui.i_chroma_loc_top = param->vui.i_chroma_loc; sps->vui.i_chroma_loc_bottom = param->vui.i_chroma_loc; } sps->vui.b_timing_info_present = param->i_timebase_num > 0 && param->i_timebase_den > 0; if( sps->vui.b_timing_info_present ) { sps->vui.i_num_units_in_tick = param->i_timebase_num; sps->vui.i_time_scale = param->i_timebase_den * 2; sps->vui.b_fixed_frame_rate = !param->b_vfr_input; } sps->vui.b_vcl_hrd_parameters_present = 0; // we don't support VCL HRD sps->vui.b_nal_hrd_parameters_present = !!param->i_nal_hrd; sps->vui.b_pic_struct_present = param->b_pic_struct; // NOTE: HRD related parts of the SPS are initialised in x264_ratecontrol_init_reconfigurable sps->vui.b_bitstream_restriction = 1; if( sps->vui.b_bitstream_restriction ) { sps->vui.b_motion_vectors_over_pic_boundaries = 1; sps->vui.i_max_bytes_per_pic_denom = 0; sps->vui.i_max_bits_per_mb_denom = 0; sps->vui.i_log2_max_mv_length_horizontal = sps->vui.i_log2_max_mv_length_vertical = (int)log2f( X264_MAX( 1, param->analyse.i_mv_range*4-1 ) ) + 1; } }
/**************************************************************************** * block_residual_write_cavlc: ****************************************************************************/ static void block_residual_write_cavlc( x264_t *h, bs_t *s, int i_idx, int *l, int i_count ) { int level[16], run[16]; int i_total, i_trailing; int i_total_zero; int i_last; unsigned int i_sign; int i; int i_zero_left; int i_suffix_length; /* first find i_last */ i_last = i_count - 1; while( i_last >= 0 && l[i_last] == 0 ) { i_last--; } i_sign = 0; i_total = 0; i_trailing = 0; i_total_zero = i_last + 1; if( i_last >= 0 ) { int idx = 0; /* level and run and total */ while( i_last >= 0 ) { level[idx] = l[i_last--]; run[idx] = 0; while( i_last >= 0 && l[i_last] == 0 ) { run[idx]++; i_last--; } idx++; } i_total = idx; i_total_zero -= idx; i_trailing = X264_MIN(3, idx); for( idx = 0; idx < i_trailing; idx++ ) { if( abs(level[idx]) > 1 ) { i_trailing = idx; break; } i_sign <<= 1; i_sign |= level[idx] < 0; } } /* total/trailing */ if( i_idx == BLOCK_INDEX_CHROMA_DC ) { bs_write_vlc( s, x264_coeff_token[4][i_total*4+i_trailing] ); } else { /* x264_mb_predict_non_zero_code return 0 <-> (16+16+1)>>1 = 16 */ static const int ct_index[17] = {0,0,1,1,2,2,2,2,3,3,3,3,3,3,3,3,3 }; int nC = x264_mb_predict_non_zero_code( h, i_idx == BLOCK_INDEX_LUMA_DC ? 0 : i_idx ); bs_write_vlc( s, x264_coeff_token[ct_index[nC]][i_total*4+i_trailing] ); } if( i_total <= 0 ) { return; } i_suffix_length = i_total > 10 && i_trailing < 3 ? 1 : 0; if( i_trailing > 0 ) { bs_write( s, i_trailing, i_sign ); } for( i = i_trailing; i < i_total; i++ ) { unsigned int i_level_code; /* calculate level code */ if( level[i] < 0 ) { i_level_code = -2*level[i] - 1; } else /* if( level[i] > 0 ) */ { i_level_code = 2 * level[i] - 2; } if( i == i_trailing && i_trailing < 3 ) { i_level_code -= 2; /* as level[i] can't be 1 for the first one if i_trailing < 3 */ } if( ( i_level_code >> i_suffix_length ) < 14 ) { bs_write_vlc( s, x264_level_prefix[i_level_code >> i_suffix_length] ); if( i_suffix_length > 0 ) { bs_write( s, i_suffix_length, i_level_code ); } } else if( i_suffix_length == 0 && i_level_code < 30 ) { bs_write_vlc( s, x264_level_prefix[14] ); bs_write( s, 4, i_level_code - 14 ); } else if( i_suffix_length > 0 && ( i_level_code >> i_suffix_length ) == 14 ) { bs_write_vlc( s, x264_level_prefix[14] ); bs_write( s, i_suffix_length, i_level_code ); } else {
void x264_me_search_ref( x264_t *h, x264_me_t *m, int (*mvc)[2], int i_mvc, int *p_fullpel_thresh ) { const int i_pixel = m->i_pixel; const int i_me_range = h->param.analyse.i_me_range; const int b_chroma_me = h->mb.b_chroma_me && i_pixel <= PIXEL_8x8; int bmx, bmy, bcost; int omx, omy, pmx, pmy; uint8_t *p_fref = m->p_fref[0]; int i, j; int mv_x_min = h->mb.mv_min_fpel[0]; int mv_y_min = h->mb.mv_min_fpel[1]; int mv_x_max = h->mb.mv_max_fpel[0]; int mv_y_max = h->mb.mv_max_fpel[1]; const int16_t *p_cost_mvx = m->p_cost_mv - m->mvp[0]; const int16_t *p_cost_mvy = m->p_cost_mv - m->mvp[1]; if( h->mb.i_me_method == X264_ME_UMH ) { /* clamp mvp to inside frame+padding, so that we don't have to check it each iteration */ p_cost_mvx = m->p_cost_mv - x264_clip3( m->mvp[0], h->mb.mv_min[0], h->mb.mv_max[0] ); p_cost_mvy = m->p_cost_mv - x264_clip3( m->mvp[1], h->mb.mv_min[1], h->mb.mv_max[1] ); } bmx = pmx = x264_clip3( ( m->mvp[0] + 2 ) >> 2, mv_x_min, mv_x_max ); bmy = pmy = x264_clip3( ( m->mvp[1] + 2 ) >> 2, mv_y_min, mv_y_max ); bcost = COST_MAX; COST_MV( bmx, bmy ); /* I don't know why this helps */ bcost -= p_cost_mvx[ bmx<<2 ] + p_cost_mvy[ bmy<<2 ]; /* try extra predictors if provided */ for( i = 0; i < i_mvc; i++ ) { const int mx = x264_clip3( ( mvc[i][0] + 2 ) >> 2, mv_x_min, mv_x_max ); const int my = x264_clip3( ( mvc[i][1] + 2 ) >> 2, mv_y_min, mv_y_max ); if( mx != bmx || my != bmy ) COST_MV( mx, my ); } COST_MV( 0, 0 ); mv_x_max += 8; mv_y_max += 8; mv_x_min -= 8; mv_y_min -= 8; switch( h->mb.i_me_method ) { case X264_ME_DIA: /* diamond search, radius 1 */ #define DIA1_ITER(mx, my)\ {\ omx = mx;\ omy = my;\ COST_MV( omx , omy-1 );\ COST_MV( omx , omy+1 );\ COST_MV( omx-1, omy );\ COST_MV( omx+1, omy );\ } for( i = 0; i < i_me_range; i++ ) { DIA1_ITER( bmx, bmy ); if( bmx == omx && bmy == omy ) break; } break; case X264_ME_HEX: /* hexagon search, radius 2 */ #define HEX2_ITER(mx, my)\ {\ omx = mx;\ omy = my;\ COST_MV( omx-2, omy );\ COST_MV( omx-1, omy+2 );\ COST_MV( omx+1, omy+2 );\ COST_MV( omx+2, omy );\ COST_MV( omx+1, omy-2 );\ COST_MV( omx-1, omy-2 );\ } for( i = 0; i < i_me_range/2; i++ ) { HEX2_ITER( bmx, bmy ); if( bmx == omx && bmy == omy ) break; } /* square refine */ DIA1_ITER( bmx, bmy ); COST_MV( omx-1, omy-1 ); COST_MV( omx-1, omy+1 ); COST_MV( omx+1, omy-1 ); COST_MV( omx+1, omy+1 ); break; case X264_ME_UMH: /* Uneven-cross Multi-Hexagon-grid Search * as in JM, except without early termination */ DIA1_ITER( pmx, pmy ); if( pmx || pmy ) DIA1_ITER( 0, 0 ); DIA1_ITER( bmx, bmy ); if(i_pixel == PIXEL_4x4) goto umh_small_hex; /* cross */ omx = bmx; omy = bmy; for( i = 1; i < i_me_range; i+=2 ) { if( omx + i <= mv_x_max ) COST_MV( omx + i, omy ); if( omx - i >= mv_x_min ) COST_MV( omx - i, omy ); } for( i = 1; i < i_me_range/2; i+=2 ) { if( omy + i <= mv_y_max ) COST_MV( omx, omy + i ); if( omy - i >= mv_y_min ) COST_MV( omx, omy - i ); } /* 5x5 ESA */ omx = bmx; omy = bmy; for( i = 0; i < 24; i++ ) { static const int square2_x[24] = {1,1,0,-1,-1,-1, 0, 1, 2,2,2,2,1,0,-1,-2,-2,-2,-2,-2,-1, 0, 1, 2}; static const int square2_y[24] = {0,1,1, 1, 0,-1,-1,-1,-1,0,1,2,2,2, 2, 2, 1, 0,-1,-2,-2,-2,-2,-2}; COST_MV( omx + square2_x[i], omy + square2_y[i] ); } /* hexagon grid */ omx = bmx; omy = bmy; for( i = 1; i <= i_me_range/4; i++ ) { int bounds_check = 4*i > X264_MIN4( mv_x_max-omx, mv_y_max-omy, omx-mv_x_min, omy-mv_y_min ); for( j = 0; j < 16; j++ ) { static const int hex4_x[16] = {0,-2,-4,-4,-4,-4,-4,-2, 0, 2, 4, 4,4,4,4,2}; static const int hex4_y[16] = {4, 3, 2, 1, 0,-1,-2,-3,-4,-3,-2,-1,0,1,2,3}; int mx = omx + hex4_x[j]*i; int my = omy + hex4_y[j]*i; if( !bounds_check || ( mx >= mv_x_min && mx <= mv_x_max && my >= mv_y_min && my <= mv_y_max ) ) COST_MV( mx, my ); } } umh_small_hex: /* iterative search */ for( i = 0; i < i_me_range; i++ ) { HEX2_ITER( bmx, bmy ); if( bmx == omx && bmy == omy ) break; } for( i = 0; i < i_me_range; i++ ) { DIA1_ITER( bmx, bmy ); if( bmx == omx && bmy == omy ) break; } break; case X264_ME_ESA: { const int min_x = X264_MAX( bmx - i_me_range, mv_x_min); const int min_y = X264_MAX( bmy - i_me_range, mv_y_min); const int max_x = X264_MIN( bmx + i_me_range, mv_x_max); const int max_y = X264_MIN( bmy + i_me_range, mv_y_max); for( omy = min_y; omy <= max_y; omy++ ) for( omx = min_x; omx <= max_x; omx++ ) { COST_MV( omx, omy ); } } break; } /* -> qpel mv */ m->mv[0] = bmx << 2; m->mv[1] = bmy << 2; /* compute the real cost */ m->cost_mv = p_cost_mvx[ m->mv[0] ] + p_cost_mvy[ m->mv[1] ]; m->cost = h->pixf.mbcmp[i_pixel]( m->p_fenc[0], m->i_stride[0], &p_fref[bmy * m->i_stride[0] + bmx], m->i_stride[0] ) + m->cost_mv; if( b_chroma_me ) { const int bw = x264_pixel_size[m->i_pixel].w; const int bh = x264_pixel_size[m->i_pixel].h; uint8_t pix[8*8*2]; h->mc.mc_chroma( m->p_fref[4], m->i_stride[1], pix, 8, m->mv[0], m->mv[1], bw/2, bh/2 ); h->mc.mc_chroma( m->p_fref[5], m->i_stride[1], pix+8*8, 8, m->mv[0], m->mv[1], bw/2, bh/2 ); m->cost += h->pixf.mbcmp[i_pixel+3]( m->p_fenc[1], m->i_stride[1], pix, 8 ) + h->pixf.mbcmp[i_pixel+3]( m->p_fenc[2], m->i_stride[1], pix+8*8, 8 ); } /* subpel refine */ if( h->mb.i_subpel_refine >= 3 ) { int hpel, qpel; /* early termination (when examining multiple reference frames) * FIXME: this can update fullpel_thresh even if the match * ref is rejected after subpel refinement */ if( p_fullpel_thresh ) { if( (m->cost*7)>>3 > *p_fullpel_thresh ) return; else if( m->cost < *p_fullpel_thresh ) *p_fullpel_thresh = m->cost; }
void x264_speedcontrol_frame( x264_t *h ) { x264_speedcontrol_t *sc = h->sc; int64_t t, delta_t, delta_buffer; int delta_f; x264_emms(); // update buffer state after encoding and outputting the previous frame(s) t = x264_mdate(); delta_f = h->i_frame - sc->prev_frame; delta_t = t - sc->timestamp; delta_buffer = delta_f * sc->spf / h->param.sc.f_speed - delta_t; sc->buffer_fill += delta_buffer; sc->prev_frame = h->i_frame; sc->timestamp = t; // update the time predictor if( delta_f ) { int cpu_time = h->param.sc.b_alt_timer ? sc->cpu_time : delta_t; float decay = powf( sc->cplx_decay, delta_f ); sc->cplx_num *= decay; sc->cplx_den *= decay; sc->cplx_num += cpu_time / presets[sc->preset].time; sc->cplx_den += delta_f; sc->stat.avg_preset += sc->preset * delta_f; sc->stat.den += delta_f; } sc->stat.min_buffer = X264_MIN( sc->buffer_fill, sc->stat.min_buffer ); sc->stat.max_buffer = X264_MAX( sc->buffer_fill, sc->stat.max_buffer ); if( sc->buffer_fill > sc->buffer_size ) // oops, cpu was idle { // not really an error, but we'll warn for debugging purposes static int64_t idle_t = 0, print_interval = 0; idle_t += sc->buffer_fill - sc->buffer_size; if( t - print_interval > 1e6 ) { x264_log( h, X264_LOG_WARNING, "speedcontrol idle (%.6f sec)\n", idle_t/1e6 ); print_interval = t; idle_t = 0; } sc->buffer_fill = sc->buffer_size; } else if( sc->buffer_fill < 0 && delta_buffer < 0 ) // oops, we're late { // don't clip fullness to 0; we'll hope the real buffer was bigger than // specified, and maybe we can catch up. if the application had to drop // frames, then it should override the buffer fullness (FIXME implement this). x264_log( h, X264_LOG_WARNING, "speedcontrol underflow (%.6f sec)\n", sc->buffer_fill/1e6 ); } { // pick the preset that should return the buffer to 3/4-full within a time // specified by compensation_period float target = sc->spf / h->param.sc.f_speed * (sc->buffer_fill + sc->compensation_period) / (sc->buffer_size*3/4 + sc->compensation_period); float cplx = sc->cplx_num / sc->cplx_den; float set, t0, t1; float filled = (float) sc->buffer_fill / sc->buffer_size; int i; t0 = presets[0].time * cplx; for( i=1;; i++ ) { t1 = presets[i].time * cplx; if( t1 >= target || i == PRESETS-1 ) break; t0 = t1; } // linear interpolation between states set = i-1 + (target - t0) / (t1 - t0); // Even if our time estimations in the PRESETS array are off // this will push us towards our target fullness set += (20 * (filled-0.75)); set = x264_clip3f(set,0,PRESETS-1); apply_preset( h, dither( sc, set ) ); // FIXME if (h->param.i_log_level >= X264_LOG_DEBUG) { static float cpu, wall, tgt, den; float decay = 1-1/100.; cpu = cpu*decay + sc->cpu_time; wall = wall*decay + delta_t; tgt = tgt*decay + target; den = den*decay + 1; fprintf( stderr, "speed: %.2f %d[%.5f] (t/c/w: %6.0f/%6.0f/%6.0f = %.4f) fps=%.2f\r", set, sc->preset, (float)sc->buffer_fill / sc->buffer_size, tgt/den, cpu/den, wall/den, cpu/wall, 1e6*den/wall ); } } }
/* Result must be freed */ x264_param_t *x264_gtk_param_get (X264_Gtk *x264_gtk) { x264_param_t *param; if (!x264_gtk) return NULL; param = (x264_param_t *)g_malloc (sizeof (x264_param_t)); if (!param) return NULL; x264_param_default (param); /* rate control */ param->rc.f_ip_factor = 1.0 + (double)x264_gtk->keyframe_boost / 100.0; param->rc.f_pb_factor = 1.0 + (double)x264_gtk->bframes_reduction / 100.0; param->rc.f_qcompress = (double)x264_gtk->bitrate_variability / 100.0; param->rc.i_qp_min = x264_gtk->min_qp; param->rc.i_qp_max = x264_gtk->max_qp; param->rc.i_qp_step = x264_gtk->max_qp_step; param->i_scenecut_threshold = x264_gtk->scene_cut_threshold; param->i_keyint_min = x264_gtk->min_idr_frame_interval; param->i_keyint_max = x264_gtk->max_idr_frame_interval; param->rc.i_vbv_max_bitrate = x264_gtk->vbv_max_bitrate; param->rc.i_vbv_buffer_size = x264_gtk->vbv_buffer_size; param->rc.f_vbv_buffer_init = x264_gtk->vbv_buffer_init; /* mb */ param->analyse.b_transform_8x8 = x264_gtk->transform_8x8; param->analyse.inter = 0; if (x264_gtk->pframe_search_8) param->analyse.inter |= X264_ANALYSE_PSUB16x16; if (x264_gtk->bframe_search_8) param->analyse.inter |= X264_ANALYSE_BSUB16x16; if (x264_gtk->pframe_search_4) param->analyse.inter |= X264_ANALYSE_PSUB8x8; if (x264_gtk->inter_search_8) param->analyse.inter |= X264_ANALYSE_I8x8; if (x264_gtk->inter_search_4) param->analyse.inter |= X264_ANALYSE_I4x4; param->b_bframe_pyramid = x264_gtk->bframe_pyramid && x264_gtk->bframe; param->analyse.b_bidir_me = x264_gtk->bidir_me; param->b_bframe_adaptive = x264_gtk->bframe_adaptive; param->analyse.b_weighted_bipred = x264_gtk->weighted_bipred; param->i_bframe = x264_gtk->bframe; param->i_bframe_bias = x264_gtk->bframe_bias; param->analyse.i_direct_mv_pred = x264_gtk->direct_mode; /* param->b_bframe_pyramid = param->b_bframe_pyramid && (param->i_bframe > 1); */ /* more */ param->analyse.i_subpel_refine = x264_gtk->partition_decision + 1; param->analyse.b_bframe_rdo = x264_gtk->bframe_rdo; param->analyse.i_me_method = x264_gtk->me_method; param->analyse.i_me_range = x264_gtk->range; param->analyse.b_chroma_me = x264_gtk->chroma_me; param->analyse.i_trellis = x264_gtk->trellis; param->analyse.i_noise_reduction = x264_gtk->noise_reduction; param->i_frame_reference = x264_gtk->max_ref_frames; param->analyse.b_mixed_references = x264_gtk->mixed_refs; param->analyse.b_fast_pskip = x264_gtk->fast_pskip; param->analyse.b_dct_decimate = x264_gtk->dct_decimate; /* rdo : RD based mode decision for B-frames. Requires subme 6 */ param->vui.i_sar_width = x264_gtk->sample_ar_x; param->vui.i_sar_height = x264_gtk->sample_ar_y; param->i_threads = x264_gtk->threads; param->b_cabac = x264_gtk->cabac; param->b_deblocking_filter = x264_gtk->deblocking_filter; param->i_deblocking_filter_alphac0 = x264_gtk->strength; param->i_deblocking_filter_beta = x264_gtk->threshold; param->i_log_level = x264_gtk->debug_method - 1; /* cqm */ param->i_cqm_preset = x264_gtk->cqm_preset; if (x264_gtk->cqm_file && (x264_gtk->cqm_file[0] != '\0')) param->psz_cqm_file = x264_gtk->cqm_file; memcpy( param->cqm_4iy, x264_gtk->cqm_4iy, 16 ); memcpy( param->cqm_4ic, x264_gtk->cqm_4ic, 16 ); memcpy( param->cqm_4py, x264_gtk->cqm_4py, 16 ); memcpy( param->cqm_4pc, x264_gtk->cqm_4pc, 16 ); memcpy( param->cqm_8iy, x264_gtk->cqm_8iy, 64 ); memcpy( param->cqm_8py, x264_gtk->cqm_8py, 64 ); /* bitrate */ switch (x264_gtk->pass) { case X264_PASS_SINGLE_BITRATE: param->rc.i_rc_method = X264_RC_ABR; param->rc.i_bitrate = x264_gtk->average_bitrate; break; case X264_PASS_SINGLE_QUANTIZER: param->rc.i_rc_method = X264_RC_CQP; param->rc.i_qp_constant = x264_gtk->quantizer; break; case X264_PASS_MULTIPASS_1ST_FAST: param->analyse.i_subpel_refine = X264_MAX( X264_MIN( 3, param->analyse.i_subpel_refine - 1 ), 1 ); param->i_frame_reference = ( param->i_frame_reference + 1 ) >> 1; param->analyse.inter &= ( ~X264_ANALYSE_PSUB8x8 ); param->analyse.inter &= ( ~X264_ANALYSE_BSUB16x16 ); case X264_PASS_MULTIPASS_1ST: param->rc.i_rc_method = X264_RC_ABR; param->rc.i_bitrate = x264_gtk->average_bitrate; param->rc.f_rate_tolerance = 4.0; break; case X264_PASS_MULTIPASS_NTH: param->rc.i_rc_method = X264_RC_ABR; param->rc.i_bitrate = x264_gtk->average_bitrate; param->rc.f_rate_tolerance = 1.0; break; } param->rc.b_stat_write = x264_gtk->stat_write; param->rc.b_stat_read = x264_gtk->stat_read; /* FIXME: potential mem leak... */ param->rc.psz_stat_out = x264_gtk_path (x264_gtk->statsfile_name); return param; }