int split_commandline(OptionParseContext *octx, int argc, char *argv[],
const OptionDef *options,
const OptionGroupDef *groups, int nb_groups)
{
int optindex = 1;
int dashdash = -2;
/* perform system-dependent conversions for arguments list */
prepare_app_arguments(&argc, &argv);
init_parse_context(octx, groups, nb_groups);
av_log(NULL, AV_LOG_DEBUG, "Splitting the commandline.\n");
while (optindex < argc) {
//取参数队列
const char *opt = argv[optindex++], *arg;
const OptionDef *po;
int ret;
av_log(NULL, AV_LOG_DEBUG, "Reading option '%s' ...\n", opt);
//一般的参数格式都是 -xx xxx
//如果不是-xx xxx的形式,那么只有两种情况
//一种是--,我们就跳过
if (opt[0] == '-' && opt[1] == '-' && !opt[2]) {
dashdash = optindex;
continue;
}
//如果不是以 - 开头,另外一种情况,就是定义输出文件
/* unnamed group separators, e.g. output filename */
if (opt[0] != '-' || !opt[1] || dashdash+1 == optindex) {
av_log(NULL, AV_LOG_DEBUG, "******check if finishe group --------------matched as %s.\n\n", groups[0].name);
//把这个输出的路径,设置到输出的octx结构体中。
finish_group(octx, 0, opt);
continue;
}
//当排除了两种特殊情况,剩下的就是标准的参数形式了
//首先,我们要把参数的类型指针加1,这样就把-去掉了
opt++;
#define GET_ARG(arg) \
do { \
arg = argv[optindex++]; \
if (!arg) { \
av_log(NULL, AV_LOG_ERROR, "Missing argument for option '%s'.\n", opt);\
return AVERROR(EINVAL); \
} \
} while (0)
首先,我们解析-i,-i 后面,是必须要跟文件名的
/* named group separators, e.g. -i */
if ((ret = match_group_separator(groups, nb_groups, opt)) >= 0) {
av_log(NULL, AV_LOG_ERROR, "match group separator \n");
//这里调用get_arg,就是为了避免-i后面没有输入的情况
GET_ARG(arg);
//我们从-i后面解析到输入文件路径后,就把它存储到octx的输入部分
av_log(NULL, AV_LOG_DEBUG, "******check if finishe group --------------ret:=%d %s %d \n",ret, __FUNCTION__, __LINE__ );
finish_group(octx, ret, arg);
av_log(NULL, AV_LOG_DEBUG, " matched as %s with argument '%s'.\n",
groups[ret].name, arg);
continue;
}
//当我们处理完上面三种情况: 一个异常,一个输入,一个输出。
//剩下的就是option选项了
//处理opt,流程很简单,
//首先,从argv中拿到opt,看它opt是否合理,同时把argv的下标加1
//然后再次比较argv,因为我们已经把下标加1,这时拿到的是下个argv,即opt的值
//拿到opt的值后,我们再把他们两个成对存起来。
//首先,我们看这个opt是否是ffmpeg默认的参数
//如果是,看它是否允许缺失,如果允许缺失,我们直接设置。
//如果不允许缺失,但是参数后面又没有具体值,就返回err。
/* normal options */
po = find_option(options, opt);
if (po->name) {
if (po->flags & OPT_EXIT) {
/* optional argument, e.g. -h */
arg = argv[optindex++];
} else if (po->flags & HAS_ARG) {
GET_ARG(arg);
} else {
arg = "1";
}
add_opt(octx, po, opt, arg);
av_log(NULL, AV_LOG_DEBUG, " matched as option '%s' (%s) with "
"argument '%s'.\n", po->name, po->help, arg);
continue;
}
//对于ffmpeg中没有的参数
//那么可能是设置错了,也可能是某个具体的解码器才能使用,是专属option,我们设置到AVOptions中
/* AVOptions */
if (argv[optindex]) {
ret = opt_default(NULL, opt, argv[optindex]);
if (ret >= 0) {
av_log(NULL, AV_LOG_DEBUG, " matched as AVOption '%s' with "
"argument '%s'.\n", opt, argv[optindex]);
optindex++;
continue;
} else if (ret != AVERROR_OPTION_NOT_FOUND) {
av_log(NULL, AV_LOG_ERROR, "Error parsing option '%s' "
"with argument '%s'.\n", opt, argv[optindex]);
return ret;
}
}
//具体意义不明,
/* boolean -nofoo options */
if (opt[0] == 'n' && opt[1] == 'o' &&
(po = find_option(options, opt + 2)) &&
po->name && po->flags & OPT_BOOL) {
add_opt(octx, po, opt, "0");
av_log(NULL, AV_LOG_DEBUG, " matched as option '%s' (%s) with "
"argument 0.\n", po->name, po->help);
continue;
}
av_log(NULL, AV_LOG_ERROR, "Unrecognized option '%s'.\n", opt);
return AVERROR_OPTION_NOT_FOUND;
}
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;
}
ffmpeg split_commandline流程解析
最新推荐文章于 2023-07-19 14:00:52 发布