x264_param_default_preset()源码分析

https://www.jianshu.com/p/567fe9b0de72

 

x264编码示例

源码分析

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_reference
    2 : 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_reference
    2 : 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
來源:简书
简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
module_param是一个宏,它定义了一个静态变量,并自动生成了相关的get/set函数和show函数。下面是module_param的代码实现: ``` #define module_param(name, type, perm) \ module_param_named(name, name, type, perm) #define module_param_named(name, value, type, perm) \ static type __param_ ## name ## _val = value; \ module_param_call(name, &param_ops_##type, &__param_ ## name ## _val, perm) #define module_param_call(name, ops, arg, perm) \ param_check_##ops(&(ops), &(arg)); \ __module_param_call(name, &(ops), (arg), sizeof(*(arg)), perm) #define __module_param_call(name, ops, arg, size, perm) \ __setup_param_call(setup_param_##name, ops, arg); \ __param_check_##name##_##ops((arg)); \ static struct kernel_param __param_arr_##name \ __used \ __attribute__((section(".param"), aligned(sizeof(void *)))) \ = { \ .name = __stringify(name), \ .ops = ops, \ .arg = (void *)arg, \ .size = size, \ .perm = perm, \ }; \ __setup_param(setup_param_##name, __param_arr_##name.ops, __param_arr_##name.arg); #define __setup_param_call(fn, ops, arg) \ static int __init fn(void) \ { \ param_array_ops(ops, arg); \ return 0; \ } #define __setup_param(fn, ops, arg) \ core_param(fn, ops, arg, sizeof(*(arg))) #define __param_check(name, p) \ __param_check_##name(p) #define __param_check_string(name, p) \ __param_check_string_##name(p) #define __param_check_charp(name, p) \ __param_check_charp_##name(p) #define __param_check_bool(name, p) \ __param_check_bool_##name(p) #define __param_check_invbool(name, p) \ __param_check_invbool_##name(p) #define __param_check_invbool_y(name, p) \ __param_check_invbool_y_##name(p) #define __param_check_invbool_n(name, p) \ __param_check_invbool_n_##name(p) #define __param_check_int(name, p) \ __param_check_int_##name(p) #define __param_check_long(name, p) \ __param_check_long_##name(p) #define __param_check_ulong(name, p) \ __param_check_ulong_##name(p) #define __param_check_byte(name, p) \ __param_check_byte_##name(p) #define __param_check_short(name, p) \ __param_check_short_##name(p) #define __param_check_ushort(name, p) \ __param_check_ushort_##name(p) #define __param_check_uint(name, p) \ __param_check_uint_##name(p) #define __param_check_intvec(name, p) \ __param_check_intvec_##name(p) #define __param_check_charpvec(name, p) \ __param_check_charpvec_##name(p) #define __param_check_boolvec(name, p) \ __param_check_boolvec_##name(p) ... ``` module_param宏的实现是比较复杂的,其中包含了大量的宏定义和函数调用。在使用module_param宏时,实际上只需要了解其基本用法,而不需要了解其详细实现。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值