热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

ffmpeg源代码:ffmpeg_parse_options()函数

ftools/ffmpeg.c文件,包含ffmpeg指令信息,其主函数如下:intmain(intargc,char**argv){i

ftools/ffmpeg.c 文件,包含ffmpeg指令信息,其主函数如下:

int main(int argc, char **argv)
{int i, ret;BenchmarkTimeStamps ti;init_dynload();register_exit(ffmpeg_cleanup);setvbuf(stderr,NULL,_IONBF,0); /* win32 runtime needs this */av_log_set_flags(AV_LOG_SKIP_REPEATED);parse_loglevel(argc, argv, options);if(argc>1 && !strcmp(argv[1], "-d")){run_as_daemon=1;av_log_set_callback(log_callback_null);argc--;argv++;}#if CONFIG_AVDEVICEavdevice_register_all();
#endifavformat_network_init();show_banner(argc, argv, options);/* parse options and open all input/output files */ret &#61; f(argc, argv);if (ret <0)exit_program(1);if (nb_output_files <&#61; 0 && nb_input_files &#61;&#61; 0) {show_usage();av_log(NULL, AV_LOG_WARNING, "Use -h to get full help or, even better, run &#39;man %s&#39;\n", program_name);exit_program(1);}/* file converter / grab */if (nb_output_files <&#61; 0) {av_log(NULL, AV_LOG_FATAL, "At least one output file must be specified\n");exit_program(1);}for (i &#61; 0; i ctx->oformat->name, "rtp"))want_sdp &#61; 0;}current_time &#61; ti &#61; get_benchmark_time_stamps();if (transcode() <0)exit_program(1);if (do_benchmark) {int64_t utime, stime, rtime;current_time &#61; get_benchmark_time_stamps();utime &#61; current_time.user_usec - ti.user_usec;stime &#61; current_time.sys_usec - ti.sys_usec;rtime &#61; current_time.real_usec - ti.real_usec;av_log(NULL, AV_LOG_INFO,"bench: utime&#61;%0.3fs stime&#61;%0.3fs rtime&#61;%0.3fs\n",utime / 1000000.0, stime / 1000000.0, rtime / 1000000.0);}av_log(NULL, AV_LOG_DEBUG, "%"PRIu64" frames successfully decoded, %"PRIu64" decoding errors\n",decode_error_stat[0], decode_error_stat[1]);if ((decode_error_stat[0] &#43; decode_error_stat[1]) * max_error_rate }

主函数中包含ffmpeg_parse_options()函数&#xff0c;主要用于解析命令行参数&#xff0c;其基本调用结构如下&#xff1a;

解析过程中主要起作用的函数为split_commandline()函数&#xff1a;

ret &#61; split_commandline(&octx, argc, argv, options, groups,FF_ARRAY_ELEMS(groups));

OptionParseContext octx&#xff0c;用来存储被解析后的数据&#xff0c;全局参数&#xff0c;输入输出参数 

typedef struct OptionParseContext {OptionGroup global_opts;OptionGroupList *groups;int nb_groups;/* parsing state */OptionGroup cur_group;
} OptionParseContext;

options参数定义在ffmpeg_opt.c中&#xff0c;以下为其部分定义&#xff1a;

const OptionDef options[] &#61; {/* main options */CMDUTILS_COMMON_OPTIONS{ "f", HAS_ARG | OPT_STRING | OPT_OFFSET |OPT_INPUT | OPT_OUTPUT, { .off &#61; OFFSET(format) },"force format", "fmt" },{ "y", OPT_BOOL, { &file_overwrite },"overwrite output files" },{ "n", OPT_BOOL, { &no_file_overwrite },"never overwrite output files" },{ "ignore_unknown", OPT_BOOL, { &ignore_unknown_streams },"Ignore unknown stream types" },{ "copy_unknown", OPT_BOOL | OPT_EXPERT, { ©_unknown_streams },"Copy unknown stream types" },{ "c", HAS_ARG | OPT_STRING | OPT_SPEC |OPT_INPUT | OPT_OUTPUT, { .off &#61; OFFSET(codec_names) },"codec name", "codec" },{ "codec", HAS_ARG | OPT_STRING | OPT_SPEC |OPT_INPUT | OPT_OUTPUT, { .off &#61; OFFSET(codec_names) },"codec name", "codec" },{ "pre", HAS_ARG | OPT_STRING | OPT_SPEC |OPT_OUTPUT, { .off &#61; OFFSET(presets) },"preset name", "preset" },

typedef struct OptionDef {const char *name;int flags;
#define HAS_ARG 0x0001
#define OPT_BOOL 0x0002
#define OPT_EXPERT 0x0004
#define OPT_STRING 0x0008
#define OPT_VIDEO 0x0010
#define OPT_AUDIO 0x0020
#define OPT_INT 0x0080
#define OPT_FLOAT 0x0100
#define OPT_SUBTITLE 0x0200
#define OPT_INT64 0x0400
#define OPT_EXIT 0x0800
#define OPT_DATA 0x1000
#define OPT_PERFILE 0x2000 /* the option is per-file (currently ffmpeg-only).implied by OPT_OFFSET or OPT_SPEC */
#define OPT_OFFSET 0x4000 /* option is specified as an offset in a passed optctx */
#define OPT_SPEC 0x8000 /* option is to be stored in an array of SpecifierOpt.Implies OPT_OFFSET. Next element after the offset isan int containing element count in the array. */
#define OPT_TIME 0x10000
#define OPT_DOUBLE 0x20000
#define OPT_INPUT 0x40000
#define OPT_OUTPUT 0x80000union {void *dst_ptr;int (*func_arg)(void *, const char *, const char *);size_t off;} u;const char *help;const char *argname;
} OptionDef;

groups参数为输入输出参数

static const OptionGroupDef groups[] &#61; {[GROUP_OUTFILE] &#61; { "output url", NULL, OPT_OUTPUT },[GROUP_INFILE] &#61; { "input url", "i", OPT_INPUT },
};

typedef struct OptionGroupDef {/**} OptionGroupDef;

通过代码来分析split_commandline()函数的执行过程&#xff1a;

/*** 解析命令行参数* &#64;param octx: 用来将命令行中的参数通过分析分别存入此结构对应变量中* &#64;param options: 默认参数的定义 (具体参见ffmpeg_opt.c文件中的 const OptionDef options[] 定义)* &#64;param groups: 存储输入文件和输出文件相关参数* &#64;param nb_groups: 2*/
int split_commandline(OptionParseContext *octx, int argc, char *argv[],const OptionDef *options,const OptionGroupDef *groups, int nb_groups)
{int optindex &#61; 1;int dashdash &#61; -2;/* perform system-dependent conversions for arguments list */prepare_app_arguments(&argc, &argv);/* 基本的内存分配&#xff0c;OptionGroupDef 与 OptionParseContext 建立联系 */init_parse_context(octx, groups, nb_groups, data);av_log(NULL, AV_LOG_DEBUG, "Splitting the commandline.\n");/* 循环取出参数 */while (optindex cur_group数组的值以及专属参数&#xff0c;存储到 * octx->groups[0]结构体中,并清空 octx->cur_group 数组的值*/finish_group(octx, 0, opt);av_log(NULL, AV_LOG_DEBUG, " matched as %s.\n", groups[0].name);continue;}/* 排除以 -- 开头 & 输出文件定义&#xff0c;剩下的就是标准参数形式将参数的类型指针 &#43;1&#xff0c;把 - 去掉 */opt&#43;&#43;;#define GET_ARG(arg) \
do { \arg &#61; argv[optindex&#43;&#43;]; \if (!arg) { \av_log(NULL, AV_LOG_ERROR, "Missing argument for option &#39;%s&#39;.\n", opt);\return AVERROR(EINVAL); \} \
} while (0)/* 参数格式是否为“-i xxx”&#xff0c;如果匹配&#xff0c;返回1 */if ((ret &#61; match_group_separator(groups, nb_groups, opt)) >&#61; 0) {// 获取参数对应的值GET_ARG(arg);/** * 将输入的路径、octx->cur_group数组的值以及专属参数&#xff0c;存储到 * octx->groups[0]结构体中,并清空 octx->cur_group 数组的值*/finish_group(octx, ret, arg);av_log(NULL, AV_LOG_DEBUG, " matched as %s with argument &#39;%s&#39;.\n",groups[ret].name, arg);continue;}// 判断此 opt 是否为 options 中定义的参数po &#61; find_option(options, opt);if (po->name) {if (po->flags & OPT_EXIT) {arg &#61; argv[optindex&#43;&#43;];} else if (po->flags & HAS_ARG) {/* 获取参数 */GET_ARG(arg);} else {// 允许参数后面的值缺失&#xff0c;直接设置为1arg &#61; "1";}/*** 判断参数类型(opt->flags)&#xff0c;存入 octx->global_opts(全局参数) 或 * octx->cur_group(临时数组)*/add_opt(octx, po, opt, arg);av_log(NULL, AV_LOG_DEBUG, " matched as option &#39;%s&#39; (%s) with ""argument &#39;%s&#39;.\n", po->name, po->help, arg);continue;}if (argv[optindex]) {/*** 在 avcodec_options、avformat_options、avresample_options、 * swscale_options、swresample 中的 options 参数中不断查找&#xff0c;查找专属 * 并存入 AVDictionary*/ret &#61; opt_default(NULL, opt, argv[optindex]);if (ret >&#61; 0) {av_log(NULL, AV_LOG_DEBUG, " matched as AVOption &#39;%s&#39; with ""argument &#39;%s&#39;.\n", opt, argv[optindex]);optindex&#43;&#43;;continue;} else if (ret !&#61; AVERROR_OPTION_NOT_FOUND) {// 参数格式错误av_log(NULL, AV_LOG_ERROR, "Error parsing option &#39;%s&#39; ""with argument &#39;%s&#39;.\n", opt, argv[optindex]);return ret;}}/* 处理 “-noxx" 格式参数 */if (opt[0] &#61;&#61; &#39;n&#39; && opt[1] &#61;&#61; &#39;o&#39; &&(po &#61; find_option(options, opt &#43; 2)) &&po->name && po->flags & OPT_BOOL) {// 存入默认值 ”0“add_opt(octx, po, opt, "0");av_log(NULL, AV_LOG_DEBUG, " matched as option &#39;%s&#39; (%s) with ""argument 0.\n", po->name, po->help);continue;}// 没有匹配的参数&#xff0c;返回错误av_log(NULL, AV_LOG_ERROR, "Unrecognized option &#39;%s&#39;.\n", opt);return AVERROR_OPTION_NOT_FOUND;}// 循环结束后&#xff0c;临时参数及专属参数还存在值&#xff0c;没有存储到输入&输出相关参数数组中if (octx->cur_group.nb_opts || codec_opts || format_opts || resample_opts)av_log(NULL, AV_LOG_WARNING, "Trailing options were found on the ""commandline.\n");av_log(NULL, AV_LOG_DEBUG, "Finished splitting the commandline.\n");return 0;
}

总结&#xff1a;跳过“--”开头的参数&#xff0c;分别解析“-”、“-no”、“-i”开头的参数以及输出参数&#xff0c;存入OptionParseContext *octx中。


推荐阅读
  • VScode格式化文档换行或不换行的设置方法
    本文介绍了在VScode中设置格式化文档换行或不换行的方法,包括使用插件和修改settings.json文件的内容。详细步骤为:找到settings.json文件,将其中的代码替换为指定的代码。 ... [详细]
  • 本文介绍了设计师伊振华受邀参与沈阳市智慧城市运行管理中心项目的整体设计,并以数字赋能和创新驱动高质量发展的理念,建设了集成、智慧、高效的一体化城市综合管理平台,促进了城市的数字化转型。该中心被称为当代城市的智能心脏,为沈阳市的智慧城市建设做出了重要贡献。 ... [详细]
  • Linux重启网络命令实例及关机和重启示例教程
    本文介绍了Linux系统中重启网络命令的实例,以及使用不同方式关机和重启系统的示例教程。包括使用图形界面和控制台访问系统的方法,以及使用shutdown命令进行系统关机和重启的句法和用法。 ... [详细]
  • CF:3D City Model(小思维)问题解析和代码实现
    本文通过解析CF:3D City Model问题,介绍了问题的背景和要求,并给出了相应的代码实现。该问题涉及到在一个矩形的网格上建造城市的情景,每个网格单元可以作为建筑的基础,建筑由多个立方体叠加而成。文章详细讲解了问题的解决思路,并给出了相应的代码实现供读者参考。 ... [详细]
  • 本文介绍了三种方法来实现在Win7系统中显示桌面的快捷方式,包括使用任务栏快速启动栏、运行命令和自己创建快捷方式的方法。具体操作步骤详细说明,并提供了保存图标的路径,方便以后使用。 ... [详细]
  • Go Cobra命令行工具入门教程
    本文介绍了Go语言实现的命令行工具Cobra的基本概念、安装方法和入门实践。Cobra被广泛应用于各种项目中,如Kubernetes、Hugo和Github CLI等。通过使用Cobra,我们可以快速创建命令行工具,适用于写测试脚本和各种服务的Admin CLI。文章还通过一个简单的demo演示了Cobra的使用方法。 ... [详细]
  • python3 nmap函数简介及使用方法
    本文介绍了python3 nmap函数的简介及使用方法,python-nmap是一个使用nmap进行端口扫描的python库,它可以生成nmap扫描报告,并帮助系统管理员进行自动化扫描任务和生成报告。同时,它也支持nmap脚本输出。文章详细介绍了python-nmap的几个py文件的功能和用途,包括__init__.py、nmap.py和test.py。__init__.py主要导入基本信息,nmap.py用于调用nmap的功能进行扫描,test.py用于测试是否可以利用nmap的扫描功能。 ... [详细]
  • ShiftLeft:将静态防护与运行时防护结合的持续性安全防护解决方案
    ShiftLeft公司是一家致力于将应用的静态防护和运行时防护与应用开发自动化工作流相结合以提升软件开发生命周期中的安全性的公司。传统的安全防护方式存在误报率高、人工成本高、耗时长等问题,而ShiftLeft提供的持续性安全防护解决方案能够解决这些问题。通过将下一代静态代码分析与应用开发自动化工作流中涉及的安全工具相结合,ShiftLeft帮助企业实现DevSecOps的安全部分,提供高效、准确的安全能力。 ... [详细]
  • 使用C++编写程序实现增加或删除桌面的右键列表项
    本文介绍了使用C++编写程序实现增加或删除桌面的右键列表项的方法。首先通过操作注册表来实现增加或删除右键列表项的目的,然后使用管理注册表的函数来编写程序。文章详细介绍了使用的五种函数:RegCreateKey、RegSetValueEx、RegOpenKeyEx、RegDeleteKey和RegCloseKey,并给出了增加一项的函数写法。通过本文的方法,可以方便地自定义桌面的右键列表项。 ... [详细]
  • 本文介绍了Java调用Windows下某些程序的方法,包括调用可执行程序和批处理命令。针对Java不支持直接调用批处理文件的问题,提供了一种将批处理文件转换为可执行文件的解决方案。介绍了使用Quick Batch File Compiler将批处理脚本编译为EXE文件,并通过Java调用可执行文件的方法。详细介绍了编译和反编译的步骤,以及调用方法的示例代码。 ... [详细]
  • 初识java关于JDK、JRE、JVM 了解一下 ... [详细]
  • Matlab 中的一些小技巧(2)
    1.Ctrl+D打开子程序  在MATLAB的Editor中,将输入光标放到一个子程序名称中间,然后按Ctrl+D可以打开该子函数的m文件。当然这个子程序要在路径列表中(或在当前工作路径中)。实际上 ... [详细]
  • 本文讨论了在Windows 8上安装gvim中插件时出现的错误加载问题。作者将EasyMotion插件放在了正确的位置,但加载时却出现了错误。作者提供了下载链接和之前放置插件的位置,并列出了出现的错误信息。 ... [详细]
  • 《数据结构》学习笔记3——串匹配算法性能评估
    本文主要讨论串匹配算法的性能评估,包括模式匹配、字符种类数量、算法复杂度等内容。通过借助C++中的头文件和库,可以实现对串的匹配操作。其中蛮力算法的复杂度为O(m*n),通过随机取出长度为m的子串作为模式P,在文本T中进行匹配,统计平均复杂度。对于成功和失败的匹配分别进行测试,分析其平均复杂度。详情请参考相关学习资源。 ... [详细]
  • Linux环境变量函数getenv、putenv、setenv和unsetenv详解
    本文详细解释了Linux中的环境变量函数getenv、putenv、setenv和unsetenv的用法和功能。通过使用这些函数,可以获取、设置和删除环境变量的值。同时给出了相应的函数原型、参数说明和返回值。通过示例代码演示了如何使用getenv函数获取环境变量的值,并打印出来。 ... [详细]
author-avatar
jone
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有