ffmpeg split_commandline流程解析

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;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值