x264源代码简单分析 x264命令行工具(x264 exe)

               

=====================================================

H.264源代码分析文章列表:

【编码 - x264】

x264源代码简单分析:概述

x264源代码简单分析:x264命令行工具(x264.exe)

x264源代码简单分析:编码器主干部分-1

x264源代码简单分析:编码器主干部分-2

x264源代码简单分析:x264_slice_write()

x264源代码简单分析:滤波(Filter)部分

x264源代码简单分析:宏块分析(Analysis)部分-帧内宏块(Intra)

x264源代码简单分析:宏块分析(Analysis)部分-帧间宏块(Inter)

x264源代码简单分析:宏块编码(Encode)部分

x264源代码简单分析:熵编码(Entropy Encoding)部分

FFmpeg与libx264接口源代码简单分析

【解码 - libavcodec H.264 解码器

FFmpeg的H.264解码器源代码简单分析:概述

FFmpeg的H.264解码器源代码简单分析:解析器(Parser)部分

FFmpeg的H.264解码器源代码简单分析:解码器主干部分

FFmpeg的H.264解码器源代码简单分析:熵解码(EntropyDecoding)部分

FFmpeg的H.264解码器源代码简单分析:宏块解码(Decode)部分-帧内宏块(Intra)

FFmpeg的H.264解码器源代码简单分析:宏块解码(Decode)部分-帧间宏块(Inter)

FFmpeg的H.264解码器源代码简单分析:环路滤波(Loop Filter)部分

=====================================================


本文简单分析x264项目中的命令行工具(x264.exe)的源代码。该命令行工具可以调用libx264将YUV格式像素数据编码为H.264码流。



函数调用关系图

X264命令行工具的源代码在x264中的位置如下图所示。



X264命令行工具的源代码的调用关系如下图所示。
 

从图中可以看出,X264命令行工具调用了libx264的几个API完成了H.264编码工作。使用libx264的API进行编码可以参考《 最简单的视频编码器:基于libx264(编码YUV为H.264)》,这个流程中最关键的API包括:
x264_param_default():设置参数集结构体x264_param_t的缺省值。
x264_encoder_open():打开编码器。
x264_encoder_headers():输出SPS,PPS,SEI等信息。
x264_encoder_encode():编码输出一帧图像。
x264_encoder_close():关闭编码器。

在X264命令行工具中,main()首先调用parse()解析输入的命令行参数,然后调用encode()进行编码。parse()首先调用x264_param_default()为存储参数的结构体x264_param_t赋默认值;然后在一个大循环中调用getopt_long()逐个解析输入的参数,并作相应的处理;最后调用select_input()和select_output()解析输入文件格式(例如yuv,y4m…)和输出文件格式(例如raw,flv,MP4…)。encode()首先调用x264_encoder_open()打开H.264编码器,然后调用x264_encoder_headers()输出H.264码流的头信息(例如SPS、PPS、SEI),接着进入一个循环并且调用encode_frame()逐帧编码视频,最后调用x264_encoder_close()关闭解码器。其中encode_frame()中又调用了x264_encoder_encode()完成了具体的编码工作。下文将会对上述流程展开分析。



main()

main()是x264控制台程序的入口函数,定义如下所示。
//主函数int main( int argc, char **argv )//参数集    x264_param_t param;    cli_opt_t opt = {
   0};    int ret = 0;    FAIL_IF_ERROR( x264_threading_init(), "unable to initialize threading\n" )#ifdef _WIN32    FAIL_IF_ERROR( !get_argv_utf8( &argc, &argv ), "unable to convert command line to UTF-8\n" )    GetConsoleTitleW( org_console_title, CONSOLE_TITLE_SIZE );    _setmode( _fileno( stdin ),  _O_BINARY );    _setmode( _fileno( stdout ), _O_BINARY );    _setmode( _fileno( stderr ), _O_BINARY );#endif    /* Parse command line */    //解析命令行输入    if( parse( argc, argv, ¶m, &opt ) < 0 )        ret = -1;#ifdef _WIN32    /* Restore title; it can be changed by input modules */    SetConsoleTitleW( org_console_title );#endif    /* Control-C handler */    signal( SIGINT, sigint_handler );    //编码    if( !ret )        ret = encode( ¶m, &opt );    /* clean up handles */    if( filter.free )        filter.free( opt.hin );    else if( opt.hin )        cli_input.close_file( opt.hin );    if( opt.hout )        cli_output.close_file( opt.hout, 0, 0 );    if( opt.tcfile_out )        fclose( opt.tcfile_out );    if( opt.qpfile )        fclose( opt.qpfile );#ifdef _WIN32    SetConsoleTitleW( org_console_title );    free( argv );#endif    return ret;}

可以看出main()的定义很简单,它主要调用了两个函数:parse()和encode()。main()首先调用parse()解析输入的命令行参数,然后调用encode()进行编码。下面分别分析这两个函数。



parse()

parse()用于解析命令行输入的参数(存储于argv[]中)。它的定义如下所示。
//解析命令行输入static int parse( int argc, char **argv, x264_param_t *param, cli_opt_t *opt ){    char *input_filename = NULL;    const char *demuxer = demuxer_names[0];    char *output_filename = NULL;    const char *muxer = muxer_names[0];    char *tcfile_name = NULL;    x264_param_t defaults;    char *profile = NULL;    char *vid_filters = NULL;    int b_thread_input = 0;    int b_turbo = 1;    int b_user_ref = 0;    int b_user_fps = 0;    int b_user_interlaced = 0;    cli_input_opt_t input_opt;    cli_output_opt_t output_opt;    char *preset = NULL;    char *tune = NULL;    //初始化参数默认值    x264_param_default( &defaults );    cli_log_level = defaults.i_log_level;    memset( &input_opt, 0, sizeof(cli_input_opt_t) );    memset( &output_opt, 0, sizeof(cli_output_opt_t) );    input_opt.bit_depth = 8;    input_opt.input_range = input_opt.output_range = param->vui.b_fullrange = RANGE_AUTO;    int output_csp = defaults.i_csp;    opt->b_progress = 1;    /* Presets are applied before all other options. */    for( optind = 0;; )    {        int c = getopt_long( argc, argv, short_options, long_options, NULL );        if( c == -1 )            break;        if( c == OPT_PRESET )            preset = optarg;        if( c == OPT_TUNE )            tune = optarg;        else if( c == '?' )            return -1;    }    if( preset && !strcasecmp( preset, "placebo" ) )        b_turbo = 0;    //设置preset,tune    if( x264_param_default_preset( param, preset, tune ) < 0 )        return -1;    /* Parse command line options */    //解析命令行选项    for( optind = 0;; )    {        int b_error = 0;        int long_options_index = -1;        int c = getopt_long( argc, argv, short_options, long_options, &long_options_index );        if( c == -1 )        {            break;        }        //不同的选项做不同的处理        switch( c )        {            case 'h':                help( &defaults, 0 );//"-h"帮助菜单                exit(0);            case OPT_LONGHELP:                help( &defaults, 1 );                exit(0);            case OPT_FULLHELP:                help( &defaults, 2 );                exit(0);            case 'V':                print_version_info();//打印版本信息                exit(0);            case OPT_FRAMES:                param->i_frame_total = X264_MAX( atoi( optarg ), 0 );                break;            case OPT_SEEK:                opt->i_seek = X264_MAX( atoi( optarg ), 0 );                break;            case 'o':                output_filename = optarg;//输出文件路径                break;            case OPT_MUXER:                FAIL_IF_ERROR( parse_enum_name( optarg, muxer_names, &muxer ), "Unknown muxer `%s'\n", optarg )                break;            case OPT_DEMUXER:                FAIL_IF_ERROR( parse_enum_name( optarg, demuxer_names, &demuxer ), "Unknown demuxer `%s'\n", optarg )                break;            case OPT_INDEX:                input_opt.index_file = optarg;                break;            case OPT_QPFILE:                opt->qpfile = x264_fopen( optarg, "rb" );                FAIL_IF_ERROR( !opt->qpfile, "can't open qpfile `%s'\n", optarg )                if( !x264_is_regular_file( opt->qpfile ) )                {                    x264_cli_log( "x264", X264_LOG_ERROR, "qpfile incompatible with non-regular file `%s'\n", optarg );                    fclose( opt->qpfile );                    return -1;                }                break;            case OPT_THREAD_INPUT:                b_thread_input = 1;                break;            case OPT_QUIET:                cli_log_level = param->i_log_level = X264_LOG_NONE;//设置log级别                break;            case 'v':                cli_log_level = param->i_log_level = X264_LOG_DEBUG;//设置log级别                break;            case OPT_LOG_LEVEL:                if( !parse_enum_value( optarg, log_level_names, &cli_log_level ) )                    cli_log_level += X264_LOG_NONE;                else                    cli_log_level = atoi( optarg );                param->i_log_level = cli_log_level;//设置log级别                break;            case OPT_NOPROGRESS:                opt->b_progress = 0;                break;            case OPT_TUNE:            case OPT_PRESET:                break;            case OPT_PROFILE:                profile = optarg;                break;            case OPT_SLOWFIRSTPASS:                b_turbo = 0;                break;            case 'r':                b_user_ref = 1;                goto generic_option;            case OPT_FPS:                b_user_fps = 1;                param->b_vfr_input = 0;                goto generic_option;            case OPT_INTERLACED:                b_user_interlaced = 1;                goto generic_option;            case OPT_TCFILE_
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
WinRAR是一款强大的压缩文件管理器,它提供了RAR和ZIP文件的完整支持,能解压ARJ、CAB、LZH、ACE、TAR、GZ、UUE、BZ2、JAR、ISO格式文件。 WinRAR 从 4.20开始更好地利用了多处理器核心,不过为了加快压缩速度增加了内存占用。另外,RAR常规解压算法的速度稍有提高,恢复卷的创建和处理可以使用多个CPU核心来获得更高的处理速度。 更新日志 版本 5.60 beta 2 1.“设置/常规”中的“超大按钮”选项选择 64×48 工具栏按钮。 2. 在压缩对话框中的“高级/完成后”列表中添加“重新启动”选项。 3. 完成压缩或解压缩后,可使用 -ioff4 开关重新启动电脑。 4. 由于显示大型tar.bz2和tar.gz文件的内容可能需要很长时间,因此 WinRAR 在打开此类压缩文件时会在状态栏中显示完成百分比。 5. 修正了错误: a)上个测试版没有恢复被用户更改的工具栏布局; 版本 5.60 beta 1 1. 我们更新了 WinRAR 图形。 我们感谢 http://weirdsgn.com 和 http://icondesignlab.com 设计师参与了这项工作,并自豪地宣布这一点 WinRAR 使用由 Aditya Nugraha Putra 编写的新图标集 来自 http://weirdsgn.com。 以前的 WinRAR 图标可用作界面主题: https://rarlab.com/themes/WinRAR_Classic_48x36.theme.rar 2. 提高“修复”命令的效率,保护恢复记录 RAR5 文件。现在它可以检测无限大小 的删除和插入,也可以作为混合数据,包括从多个恢复记录保护的压缩包中获取 的数据,并以任意顺序合并到单个文件中。 3.“完成后关闭 PC”选项更改为“完成后”下拉列表,因此您可以在压缩完成后关 闭、休眠或睡眠 PC。 4. 使用 -ioff 或 -ioff1 命令行开关关闭 PC, -ioff2 进入休眠状态,-ioff3 在完成操作后进入睡眠状态。 5. 如果在 -z<文件> 开关中指定的注释文件的编码未使用 -sc 开关定义,则 RAR 会根据字节顺序掩码和数据有效性测试尝试检测 UTF-8,UTF-16LE 和 UTF-16BE 编码。 6. WinRAR 会自动检测 ZIP 压缩文件注释的 ANSI,OEM 和 UTF-8 编码。 7.“设置/查看器”中的“内部查看器/使用 DOS 编码”选项替换为“内部查看器/ 自动检测编码”。 如果启用了“自动检测编码”,内部查看器将尝试检测ANSI(Windows),OEM (DOS),UTF-8 和 UTF-16 编码。 8. 通常情况下,如果右键单击单个压缩文件,Windows 资源管理器关联菜单仅包 含解压缩命令。您可以通过在设置/集成/关联菜单项中的“始终显示压缩项目” 选项中指定一个或多个空格分隔掩码来覆盖此选项,因此即使文件被识别为压 缩文件,始终也会为这些文件类型显示压缩命令。 如果您希望所有文件都存在 压缩和解压缩命令,请在此处放置“*”。 9. 自解压模块“SetupCode”命令接受一个可选的整数型参数,允许控制安装程 序的映射和自解压模块自己的错误代码。 在“高级自解压选项/设置”对话框中也可以通过“退出代码调整”选项进行 访问。 10.新增“显示更多信息”WinRAR 命令行 -im 开关。 它可以与“t”命令一起使用,以便在成功压缩测试结果的情况下发出消息。 如果没有发现错误,没有这个开关“t”则命令会静默地完成。 此开关仅适用于 WinRAR.exe 并被控制台 RAR.exe 忽略。 11.如果在解压 ZIP 文件中的加密文件时输入了错误的密码,WinRAR 建议再次输 入同一文件的有效密码,而不是中止解压缩。 12.如果使用加密文件名打开或解压缩 RAR 压缩文件时输入了错误密码,WinRAR 建议再次输入有效密码而不是中止操作。以前的版本已经为具有加密文件数据 的 RAR 压缩执行了此操作,但是对于使用文件名加密的压缩取消了此操作。 13.WinRAR 可识别具有实际 GZIP 压缩之前的任意数据的 GZIP 文件,例如 .scexe 固件文件。 14.可以在压缩对话框的“要添加的文件”字段中指定 @filelist 参数。 在这种 情况下,WinRAR 将从 “filelist”文件尝试压缩文件列表,该文件应该是纯 文本,每行一个文件名。 15.信息对话框: a)更新压缩率图; b)“加密”字段中显示“名称和数据”,用于加密文件名的文件。 16.如果在操作进度窗口中将鼠标指针放在压缩文件名称上,则会显示完整文件名 称。如果文件名称很长并且不适合可用的窗口空间,它会很有用。 17.如果 -ts1 开关与 -u 或 -f 一起使用,则文件时间比较以 1 秒的精度执行。 以前在这种情况下,我们可能会错误地将添加文件视为比压缩文件更新,这是 因为我们比较了高精度添加文件时间和低精度压缩文件时间。 18.如果没有文件需要更新,“更新”和“刷新”命令(命令行模式下的 ‘u’ 和 ‘f’)会立即退出。以前,他们在退出更新具有恢复记录或快速打开信息的压 缩文件时创建了一个临时文件。 19.在从 WinRAR 图形用户界面外壳创建了 500 个卷之后发出提示,因此用户可 以继续或退出进一步压缩操作。这样做是为了防止在错误输入卷大小的情况下 创建数千个卷。 20.WinRAR 使用兆字节而不是字节作为压缩对话框中卷大小字段的默认单位。 21.修复包含了损坏的恢复记录的 RAR5 文件后,“修复”命令问题“恢复记录已 损坏”消息。 以前,此类消息仅由“测试”命令发出,“修复”以无声方式处理大部分恢复 记录损坏。 22.修正错误: a)在处理损坏的 RAR 文件时修复了潜在的安全问题; b)具有 PAX 扩展标题的 TAR 文件中的非英文字符未正确显示; c)“rar x arcname.rar”命令将文件解压到当前文件夹而不是其上层文件夹; d)将文件从 Windows 资源管理器粘贴到在 WinRAR 中打开的文件,阻止了资 源管理器中的进一步复制和粘贴操作,直到压缩完成; e)一旦输入错误的密码,自解压模块发出“指定的密码不正确”消息,无限 期地不提示输入正确的密码; f)即使解压对话框中的“文件时间”选项被关闭,在解压 ZIP 压缩文件时总 是设置文件夹时间; g)如果在解压时选择了“删除文件:始终”,并且用户在文件覆盖或密码提示 中按下“取消”,即使取消 .zip 和 .7z 格式的解压,也可以删除文件。
提供的源码资源涵盖了安卓应用、小程序、Python应用和Java应用等多个领域,每个领域都包含了丰富的实例和项目。这些源码都是基于各自平台的最新技术和标准编写,确保了在对应环境下能够无缝运行。同时,源码中配备了详细的注释和文档,帮助用户快速理解代码结构和实现逻辑。 适用人群: 这些源码资源特别适合大学生群体。无论你是计算机相关专业的学生,还是对其他领域编程感兴趣的学生,这些资源都能为你提供宝贵的学习和实践机会。通过学习和运行这些源码,你可以掌握各平台开发的基础知识,提升编程能力和项目实战经验。 使用场景及目标: 在学习阶段,你可以利用这些源码资源进行课程实践、课外项目或毕业设计。通过分析和运行源码,你将深入了解各平台开发的技术细节和最佳实践,逐步培养起自己的项目开发和问题解决能力。此外,在求职或创业过程中,具备跨平台开发能力的大学生将更具竞争力。 其他说明: 为了确保源码资源的可运行性和易用性,特别注意了以下几点:首先,每份源码都提供了详细的运行环境和依赖说明,确保用户能够轻松搭建起开发环境;其次,源码中的注释和文档都非常完善,方便用户快速上手和理解代码;最后,我会定期更新这些源码资源,以适应各平台技术的最新发展和市场需求。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值