1. 程式人生 > >x264_param_default_preset()原始碼分析

x264_param_default_preset()原始碼分析

原始碼分析

h264編碼原理複雜,引數眾多。為了方便使用無論x264還是其他編碼的實現框架,都封裝了幾種現有的編碼模型,只需要根據編碼速度的要求和視訊質量的要求選擇模型,並修改部分視訊引數即可編碼。 模型的選擇就是通過x264_param_default_preset()實現。int x264_param_default_preset( x264_param_t *param, const char *preset, const char *tune ) { x264_param_default( param ); if( preset && x264_param_apply_preset( param, preset ) < 0 ) return -1; if( tune && x264_param_apply_tune( param, tune )< 0 ) return -1; return 0; }

程式碼可見設定該函式分為三步處理。

  • 第一步為呼叫x264_param_default()為param設定預設值。void x264_param_default( x264_param_t \*param ) { memset( param, 0, sizeof( x264_param_t ) ); // CPU自動檢測 param->cpu = x264_cpu_detect(); param->i_threads = X264_THREADS_AUTO; // 並行編碼執行緒為0 param->b_deterministic = 1; //允許非確定性時執行緒優化 param->i_sync_lookahead = X264_SYNC_LOOKAHEAD_AUTO; //自動選擇執行緒超前緩衝大小-1 // 視訊屬性 param->i_csp = X264_CSP_I420; //設定輸入的視訊取樣的格式0x0001yuv 4:2:0 planar param->i_width = 0; // 寬度 param->i_height = 0; // 高度 param->vui.i_sar_width = 0; param->vui.i_sar_height= 0; //設定長寬比 param->vui.i_overscan = 0; // 過掃描線,預設undef(不設定),可選:show(觀看)crop(去除) param->vui.i_vidformat = 5; //undef視訊格式 param->vui.b_fullrange = 0; //off param->vui.i_colorprim = 2; //undef原始色度格式 param->vui.i_transfer = 2; // undef 轉換方式 param->vui.i_colmatrix = 2; // undef 色度矩陣設定 param->vui.i_chroma_loc= 0; // left center 色度樣本指定,範圍0~5,預設0 param->i_fps_num = 25; //幀率 param->i_fps_den = 1; //用兩個整型的數的比值,來表示幀率 param->i_level_idc = -1; // level值的設定 param->i_slice_max_size = 0; // 每片位元組的最大數,包括預計的NAL開銷. param->i_slice_max_mbs = 0; // 每片巨集塊的最大數,重寫 i_slice_count param->i_slice_count = 0; //每幀的像條數目: 設定矩形像條. //編碼引數 param->i_frame_reference = 3; //參考幀的最大幀數。 param->i_keyint_max = 250; // 在此間隔設定IDR關鍵幀 param->i_keyint_min = 25; // 場景切換少於次值編碼位I, 而不是 IDR. param->i_bframe = 3; //兩個參考幀之間的B幀數目 param->i_scenecut_threshold = 40; //如何積極地插入額外的I幀 param->i_bframe_adaptive = X264_B_ADAPT_FAST; /*自適應B幀判定1 param->i_bframe_bias = 0; //控制插入B幀判定,範圍-100~+100,越高越容易插入B幀 param->b_bframe_pyramid = 0; //允許部分B為參考幀 param->b_deblocking_filter = 1; //去塊效應相關 param->i_deblocking_filter_alphac0 = 0; // [-6, 6] -6 亮度濾波器, 6 強 param->i_deblocking_filter_beta = 0; // [-6, 6] 同上 param->b_cabac = 1; /*cabac的開關 param->i_cabac_init_idc = 0; //位元速率控制 param->rc.i_rc_method = X264_RC_CRF;;//恆定位元速率 param->rc.i_bitrate = 0;//設定平均位元速率大小 param->rc.f_rate_tolerance = 1.0; param->rc.i_vbv_max_bitrate = 0; //平均位元速率模式下,最大瞬時位元速率,預設0(與-B設定相同) param->rc.i_vbv_buffer_size = 0; //位元速率控制緩衝區的大小,單位kbit,預設0 param->rc.f_vbv_buffer_init = 0.9; // 位元速率控制緩衝區資料保留的最大資料量與緩衝區大小之比,範圍0~1.0,預設0.9 param->rc.i_qp_constant = 23;;/最小qp值 param->rc.f_rf_constant = 23; param->rc.i_qp_min = 10; //允許的最小量化值 param->rc.i_qp_max = 51; //允許的最大量化值 param->rc.i_qp_step = 4; //幀間最大量化步長 param->rc.f_ip_factor = 1.4; param->rc.f_pb_factor = 1.3; param->rc.i_aq_mode = X264_AQ_VARIANCE; /* psy adaptive QP. (X264_AQ_\*) param->rc.f_aq_strength = 1.0; param->rc.i_lookahead = 40; param->rc.b_stat_write = 0; //Enable stat writing in psz_stat_out param->rc.psz_stat_out = "x264_2pass.log"; param->rc.b_stat_read = 0; param->rc.psz_stat_in = "x264_2pass.log"; param->rc.f_qcompress = 0.6; /* 0.0 => cbr, 1.0 => constant qp param->rc.f_qblur = 0.5; //時間上模糊量化 param->rc.f_complexity_blur = 20; // 時間上模糊複雜性 param->rc.i_zones = 0; // number of zone_t's param->rc.b_mb_tree = 1; //Macroblock-tree ratecontrol. // 日誌 param->pf_log = x264_log_default; param->p_log_private = NULL; param->i_log_level = X264_LOG_INFO;//預設為“Info” //分析 param->analyse.intra = X264_ANALYSE_I4x4 | X264_ANALYSE_I8x8; param->analyse.inter = X264_ANALYSE_I4x4 | X264_ANALYSE_I8x8 | X264_ANALYSE_PSUB16x16| X264_ANALYSE_BSUB16x16; param->analyse.i_direct_mv_pred = X264_DIRECT_PRED_SPATIAL;//空間預測模式 param->analyse.i_me_method = X264_ME_HEX;//運動估計演算法HEX param->analyse.f_psy_rd = 1.0; param->analyse.b_psy = 1; param->analyse.f_psy_trellis = 0; param->analyse.i_me_range = 16;//運動估計範圍 param->analyse.i_subpel_refine = 7; // 亞畫素運動估計質量 param->analyse.b_mixed_references = 1; //允許每個巨集塊的分割槽在P幀有它自己的參考號 param->analyse.b_chroma_me = 1; // 亞畫素色度運動估計和P幀的模式選擇 param->analyse.i_mv_range_thread = -1; // 執行緒之間的最小空間. -1 = auto, based on number of threads. param->analyse.i_mv_range = -1; //運動向量最大長度set from level_idc param->analyse.i_chroma_qp_offset = 0; //色度量化步長偏移量 param->analyse.b_fast_pskip = 1; //快速P幀跳過檢測 param->analyse.b_weighted_bipred = 1; //為b幀隱式加權 param->analyse.b_dct_decimate = 1; // 在P-frames轉換引數域 param->analyse.b_transform_8x8 = 1; // 幀間分割槽 param->analyse.i_trellis = 1; //Trellis量化,對每個8x8的塊尋找合適的量化值,需要CABAC,預設0 0:關閉1:只在最後編碼時使用2:一直使用 param->analyse.i_luma_deadzone[0] = 21; //幀間亮度量化中使用的無效區大小 param->analyse.i_luma_deadzone[1] = 11; //幀內亮度量化中使用的無效區大小 param->analyse.b_psnr = 0;//是否顯示PSNR param->analyse.b_ssim = 0;//是否顯示SSIM //量化 param->i_cqm_preset = X264_CQM_FLAT; //自定義量化矩陣(CQM),初始化量化模式為flat 0 memset( param->cqm_4iy, 16, 16 ); memset( param->cqm_4ic, 16, 16 ); memset( param->cqm_4py, 16, 16 ); memset( param->cqm_4pc, 16, 16 ); memset( param->cqm_8iy, 16, 64 ); memset( param->cqm_8py, 16, 64 );//開闢空間 param->b_repeat_headers = 1; // 在每個關鍵幀前放置SPS/PPS param->b_aud = 0; //生成訪問單元分隔符 }

    注:以上程式碼和註釋出處

  • 第二部步根據preset值通過x264_param_apply_preset(x264_param_t *param, const char *preset )函式設定設定編碼引數。 preset 接受取值為:x264_preset_names[] = { "ultrafast", "superfast", "veryfast", "faster", "fast", "medium", "slow", "slower", "veryslow", "placebo", 0 }; 此步驟通過速度設定某些引數。

    static int x264_param_apply_preset( x264_param_t *param, const char *preset )
    {
       char *end;
       int i = strtol( preset, &end, 10 );
       if( *end == 0 && i >= 0 && i < sizeof(x264_preset_names)/sizeof(*x264_preset_names)-1 )
           preset = x264_preset_names[i];
      if( !strcasecmp( preset, "ultrafast" ) )
     {
      param->i_frame_reference = 1;//參考幀的最大幀數設為1
      param->i_scenecut_threshold = 0;
      param->b_deblocking_filter = 0;//不使用去塊濾波  
      param->b_cabac = 0;//關閉cabac
      param->i_bframe = 0;//關閉b幀
      param->analyse.intra = 0;
      param->analyse.inter = 0;
      param->analyse.b_transform_8x8 = 0;
      param->analyse.i_me_method = X264_ME_DIA;;////運動估演算法的選擇 
      param->analyse.i_subpel_refine = 0;
      param->rc.i_aq_mode = 0;
      param->analyse.b_mixed_references = 0;
      param->analyse.i_trellis = 0;
      param->i_bframe_adaptive = X264_B_ADAPT_NONE;
      //關閉b幀判定選項
      param->rc.b_mb_tree = 0;
      param->analyse.i_weighted_pred = X264_WEIGHTP_NONE;
      param->analyse.b_weighted_bipred = 0;
      param->rc.i_lookahead = 0;
    }
    else if( !strcasecmp( preset, "superfast" ) )
    {
      param->analyse.inter = X264_ANALYSE_I8x8|X264_ANALYSE_I4x4;
      param->analyse.i_me_method = X264_ME_DIA;;//鑽石模板  
      param->analyse.i_subpel_refine = 1;/亞畫素運動估計質量為1  
      param->i_frame_reference = 1;//參考幀的最大幀數設為1
      param->analyse.b_mixed_references = 0;
      param->analyse.i_trellis = 0;
      param->rc.b_mb_tree = 0;
      param->analyse.i_weighted_pred = X264_WEIGHTP_SIMPLE;
      param->rc.i_lookahead = 0;
    }
    else if( !strcasecmp( preset, "veryfast" ) )
    {
      param->analyse.i_me_method = X264_ME_HEX;
      param->analyse.i_subpel_refine = 2;
      param->i_frame_reference = 1;//參考幀的最大幀數設為1
      param->analyse.b_mixed_references = 0;
      param->analyse.i_trellis = 0;
      param->analyse.i_weighted_pred = X264_WEIGHTP_SIMPLE;
      param->rc.i_lookahead = 10;
    }
    else if( !strcasecmp( preset, "faster" ) )
    {
      param->analyse.b_mixed_references = 0;
      param->i_frame_reference = 2;//參考幀的最大幀數設為2
      param->analyse.i_subpel_refine = 4;
      param->analyse.i_weighted_pred = X264_WEIGHTP_SIMPLE;
      param->rc.i_lookahead = 20;
    }
     else if( !strcasecmp( preset, "fast" ) )
     {
      param->i_frame_reference = 2;//參考幀的最大幀數設為2
      param->analyse.i_subpel_refine = 6;
      param->analyse.i_weighted_pred = X264_WEIGHTP_SIMPLE;
      param->rc.i_lookahead = 30;
      }
      else if( !strcasecmp( preset, "medium" ) )
      {
      /* Default is medium 
         *預設參考 set_param_default();
          */
      }
      else if( !strcasecmp( preset, "slow" ) )
      {
      param->analyse.i_me_method = X264_ME_UMH;//運動估算髮的選擇
      param->analyse.i_subpel_refine = 8;
      param->i_frame_reference = 5;//參考幀的最大幀數設為5
      param->i_bframe_adaptive = X264_B_ADAPT_TRELLIS;
      param->analyse.i_direct_mv_pred = X264_DIRECT_PRED_AUTO;
      param->rc.i_lookahead = 50;
    }
    else if( !strcasecmp( preset, "slower" ) )
    {
      param->analyse.i_me_method = X264_ME_UMH;//運動估算髮的選擇
      param->analyse.i_subpel_refine = 9;
      param->i_frame_reference = 8;//參考幀的最大幀數設為8
      param->i_bframe_adaptive = X264_B_ADAPT_TRELLIS;
      param->analyse.i_direct_mv_pred = X264_DIRECT_PRED_AUTO;
      param->analyse.inter |= X264_ANALYSE_PSUB8x8;
      param->analyse.i_trellis = 2;
      param->rc.i_lookahead = 60;
    }
    else if( !strcasecmp( preset, "veryslow" ) )
    {
      param->analyse.i_me_method = X264_ME_UMH;//運動估算髮的選擇
      param->analyse.i_subpel_refine = 10;
      param->analyse.i_me_range = 24;
      param->i_frame_reference = 16;//參考幀的最大幀數設為16
      param->i_bframe_adaptive = X264_B_ADAPT_TRELLIS;
      param->analyse.i_direct_mv_pred = X264_DIRECT_PRED_AUTO;
      param->analyse.inter |= X264_ANALYSE_PSUB8x8;
      param->analyse.i_trellis = 2;
      param->i_bframe = 8;//兩個參考幀之間b幀為8
      param->rc.i_lookahead = 60;
    }
    else if( !strcasecmp( preset, "placebo" ) )
    {
      param->analyse.i_me_method = X264_ME_TESA;//運動估算髮的選擇
      param->analyse.i_subpel_refine = 11;
      param->analyse.i_me_range = 24;//運動估計範圍設為24
      param->i_frame_reference = 16;//參考幀的最大幀數設為16
      param->i_bframe_adaptive = X264_B_ADAPT_TRELLIS;
      param->analyse.i_direct_mv_pred = X264_DIRECT_PRED_AUTO;
      param->analyse.inter |= X264_ANALYSE_PSUB8x8;
      param->analyse.b_fast_pskip = 0;
      param->analyse.i_trellis = 2;
      param->i_bframe = 16;//參考幀之間b幀為16
      param->rc.i_lookahead = 60;
    }
    else
    {
      x264_log( NULL, X264_LOG_ERROR, "invalid preset '%s'\n", preset );
      return -1;
    }
    return 0;
    }
    

已加入註釋。選用ultrafast會關閉b幀,但是同等質量也會增大位元速率。 veryfast 之後會啟用各種保護質量的演算法, 很大程度上降低編碼速度。

  • 第三步是根據 tune值,通過x264_param_apply_tune()函式設定編碼質量相關值。 static int x264_param_apply_tune( x264_param_t *param, const char *tune ) { char tmp = x264_malloc( strlen( tune ) + 1 ); if( !tmp ) return -1; tmp = strcpy( tmp, tune ); char s = strtok( tmp, ",./-+" ); int psy_tuning_used = 0; while( s ) { if( !strncasecmp( s, "film", 4 ) ) { if( psy_tuning_used++ ) goto psy_failure; param->i_deblocking_filter_alphac0 = -1; param->i_deblocking_filter_beta = -1; param->analyse.f_psy_trellis = 0.15; } else if( !strncasecmp( s, "animation", 9 ) ) { if( psy_tuning_used++ ) goto psy_failure; param->i_frame_reference = param->i_frame_reference > 1 ? param- >i_frame_reference2 : 1; param->i_deblocking_filter_alphac0 = 1; param->i_deblocking_filter_beta = 1; param->analyse.f_psy_rd = 0.4; param->rc.f_aq_strength = 0.6; param->i_bframe += 2;//增加b幀 } else if( !strncasecmp( s, "grain", 5 ) ) { if( psy_tuning_used++ ) goto psy_failure; param->i_deblocking_filter_alphac0 = -2; param->i_deblocking_filter_beta = -2; param->analyse.f_psy_trellis = 0.25; param->analyse.b_dct_decimate = 0; param->rc.f_pb_factor = 1.1; param->rc.f_ip_factor = 1.1; param->rc.f_aq_strength = 0.5; param->analyse.i_luma_deadzone[0] = 6; param->analyse.i_luma_deadzone[1] = 6; param->rc.f_qcompress = 0.8; } else if( !strncasecmp( s, "stillimage", 10 ) ) { if( psy_tuning_used++ ) goto psy_failure; param->i_deblocking_filter_alphac0 = -3; param->i_deblocking_filter_beta = -3; param->analyse.f_psy_rd = 2.0; param->analyse.f_psy_trellis = 0.7; param->rc.f_aq_strength = 1.2; } else if( !strncasecmp( s, "psnr", 4 ) ) { if( psy_tuning_used++ ) goto psy_failure; param->rc.i_aq_mode = X264_AQ_NONE; param->analyse.b_psy = 0; } else if( !strncasecmp( s, "ssim", 4 ) ) { if( psy_tuning_used++ ) goto psy_failure; param->rc.i_aq_mode = X264_AQ_AUTOVARIANCE; param->analyse.b_psy = 0; } else if( !strncasecmp( s, "fastdecode", 10 ) ) { param->b_deblocking_filter = 0; param->b_cabac = 0; param->analyse.b_weighted_bipred = 0; param->analyse.i_weighted_pred = X264_WEIGHTP_NONE; } else if( !strncasecmp( s, "zerolatency", 11 ) )//關閉b幀 { param->rc.i_lookahead = 0; param->i_sync_lookahead = 0; param->i_bframe = 0; // 關閉b幀 param->b_sliced_threads = 1; param->b_vfr_input = 0; param->rc.b_mb_tree = 0; } else if( !strncasecmp( s, "touhou", 6 ) ) { if( psy_tuning_used++ ) goto psy_failure; param->i_frame_reference = param->i_frame_reference > 1 ? param- >i_frame_reference2 : 1; param->i_deblocking_filter_alphac0 = -1; param->i_deblocking_filter_beta = -1; param->analyse.f_psy_trellis = 0.2; param->rc.f_aq_strength = 1.3; if( param->analyse.inter & X264_ANALYSE_PSUB16x16 ) param->analyse.inter |= X264_ANALYSE_PSUB8x8; } else { x264_log( NULL, X264_LOG_ERROR, "invalid tune '%s'\n", s ); x264_free( tmp ); return -1; } if( 0 ) { psy_failure:x264_log( NULL, X264_LOG_WARNING, "only 1 psy tuning can be used: ignoring tune %s\n", s ); } s = strtok( NULL, ",./-+" ); } x264_free( tmp ); return 0; } 使用zerolatency編碼即刻返回編碼後的輸出,不用flush,問題詳細參看:解析ffmpeg 視訊流編解碼末尾丟幀問題

h->frames.i_delay = param->i_sync_lookahead + // 前向考慮幀數 max ( param->i_bframe, // B幀數量 param->rc.i_lookahead) + // 位元速率控制前向考慮幀數 而zerolatency 將所有設定為0; param->rc.i_lookahead = 0; param->i_sync_lookahead = 0; param->i_bframe = 0; // 關閉b幀 param->b_sliced_threads = 1; param->b_vfr_input = 0; param->rc.b_mb_tree = 0;

命令列使用 $x264 --fullhelp 會顯示出對每種模式的說明。 Presets:

  --profile <string>      Force the limits of an H.264 profile
                              Overrides all settings.
                              - baseline:
                                --no-8x8dct --bframes 0 --no-cabac
                                --cqm flat --weightp 0
                                No interlaced.
                                No lossless.
                              - main:
                                --no-8x8dct --cqm flat
                                No lossless.
                              - high:
                                No lossless.
                              - high10:
                                No lossless.
                                Support for bit depth 8-10.
                              - high422:
                                No lossless.
                                Support for bit depth 8-10.
                                Support for 4:2:0/4:2:2 chroma subsampling.
                              - high444:
                                Support for bit depth 8-10.
                                Support for 4:2:0/4:2:2/4:4:4 chroma subsampling.
  --preset <string>       Use a preset to select encoding settings [medium]
                              Overridden by user settings.
                              - ultrafast:
                                --no-8x8dct --aq-mode 0 --b-adapt 0
                                --bframes 0 --no-cabac --no-deblock
                                --no-mbtree --me dia --no-mixed-refs
                                --partitions none --rc-lookahead 0 --ref 1
                                --scenecut 0 --subme 0 --trellis 0
                                --no-weightb --weightp 0
                              - superfast:
                                --no-mbtree --me dia --no-mixed-refs
                                --partitions i8x8,i4x4 --rc-lookahead 0
                                --ref 1 --subme 1 --trellis 0 --weightp 1
                              - veryfast:
                                --no-mixed-refs --rc-lookahead 10
                                --ref 1 --subme 2 --trellis 0 --weightp 1
                              - faster:
                                --no-mixed-refs --rc-lookahead 20
                                --ref 2 --subme 4 --weightp 1
                              - fast:
                                --rc-lookahead 30 --ref 2 --subme 6
                                --weightp 1
                              - medium:
                                Default settings apply.
                              - slow:
                                --b-adapt 2 --direct auto --me umh
                                --rc-lookahead 50 --ref 5 --subme 8
                              - slower:
                                --b-adapt 2 --direct auto --me umh
                                --partitions all --rc-lookahead 60
                                --ref 8 --subme 9 --trellis 2
                              - veryslow:
                                --b-adapt 2 --bframes 8 --direct auto
                                --me umh --merange 24 --partitions all
                                --ref 16 --subme 10 --trellis 2
                                --rc-lookahead 60
                              - placebo:
                                --bframes 16 --b-adapt 2 --direct auto
                                --slow-firstpass --no-fast-pskip
                                --me tesa --merange 24 --partitions all
                                --rc-lookahead 60 --ref 16 --subme 11
                                --trellis 2
  --tune <string>         Tune the settings for a particular type of source
                          or situation
                              Overridden by user settings.
                              Multiple tunings are separated by commas.
                              Only one psy tuning can be used at a time.
                              - film (psy tuning):
                                --deblock -1:-1 --psy-rd <unset>:0.15
                              - animation (psy tuning):
                                --bframes {+2} --deblock 1:1
                                --psy-rd 0.4:<unset> --aq-strength 0.6
                                --ref {Double if >1 else 1}
                              - grain (psy tuning):
                                --aq-strength 0.5 --no-dct-decimate
                                --deadzone-inter 6 --deadzone-intra 6
                                --deblock -2:-2 --ipratio 1.1 
                                --pbratio 1.1 --psy-rd <unset>:0.25
                                --qcomp 0.8
                              - stillimage (psy tuning):
                                --aq-strength 1.2 --deblock -3:-3
                                --psy-rd 2.0:0.7
                              - psnr (psy tuning):
                                --aq-mode 0 --no-psy
                              - ssim (psy tuning):
                                --aq-mode 2 --no-psy
                              - fastdecode:
                                --no-cabac --no-deblock --no-weightb
                                --weightp 0
                              - zerolatency:
                                --bframes 0 --force-cfr --no-mbtree
                                --sync-lookahead 0 --sliced-threads
                                --rc-lookahead 0
  --slow-firstpass        Don't force these faster settings with --pass 1:
                              --no-8x8dct --me dia --partitions none
                              --ref 1 --subme {2 if >2 else unchanged}
                              --trellis 0 --fast-psk

作者:Don_ 連結:https://www.jianshu.com/p/567fe9b0de72 來源:簡書 簡書著作權歸作者所有,任何形式的轉載都請聯絡作者獲得授權並註明出處。