ffmpeg中filter_query_formats函数解析

news2024/11/27 22:27:42

ffmpeg中filter_query_formats主要起一个pix fmt引用指定的功能。
下下结论:
在这里插入图片描述

先看几个结构体定义:

//删除了一些与本次分析不必要的成员
struct AVFilterLink {
    AVFilterContext *src;       ///< source filter
    AVFilterPad *srcpad;        ///< output pad on the source filter

    AVFilterContext *dst;       ///< dest filter
    AVFilterPad *dstpad;        ///< input pad on the dest filter

    enum AVMediaType type;      ///< filter media type

    /* These parameters apply only to video */
    int w;                      ///< agreed upon image width
    int h;                      ///< agreed upon image height
    AVRational sample_aspect_ratio; ///< agreed upon sample aspect ratio
    /* These parameters apply only to audio */
    uint64_t channel_layout;    ///< channel layout of current buffer (see libavutil/channel_layout.h)
    int sample_rate;            ///< samples per second

    int format;                 ///< agreed upon media format

    /*****************************************************************
     * All fields below this line are not part of the public API. They
     * may not be used outside of libavfilter and can be changed and
     * removed at will.
     * New public fields should be added right above.
     *****************************************************************
     */

    /**
     * Lists of supported formats / etc. supported by the input filter.
     */
    AVFilterFormatsConfig incfg;

    /**
     * Graph the filter belongs to.
     */
    struct AVFilterGraph *graph;
    ...
};

结构体:AVFilterFormatsConfig

typedef struct AVFilterFormatsConfig {

    /**
     * List of supported formats (pixel or sample).
     */
    AVFilterFormats *formats;

    /**
     * Lists of supported sample rates, only for audio.
     */
    AVFilterFormats  *samplerates;

    /**
     * Lists of supported channel layouts, only for audio.
     */
    AVFilterChannelLayouts  *channel_layouts;

} AVFilterFormatsConfig;

再来看函数:

static int filter_query_formats(AVFilterContext *ctx)
{
    int ret, i;
    AVFilterFormats *formats;
    AVFilterChannelLayouts *chlayouts;
    AVFilterFormats *samplerates;
    enum AVMediaType type = ctx->inputs  && ctx->inputs [0] ? ctx->inputs [0]->type :
                            ctx->outputs && ctx->outputs[0] ? ctx->outputs[0]->type :
                            AVMEDIA_TYPE_VIDEO;

    if ((ret = ctx->filter->query_formats(ctx)) < 0) {
        if (ret != AVERROR(EAGAIN))
            av_log(ctx, AV_LOG_ERROR, "Query format failed for '%s': %s\n",
                   ctx->name, av_err2str(ret));
        return ret;
    }
    ret = filter_check_formats(ctx);
    if (ret < 0)
        return ret;

    for (i = 0; i < ctx->nb_inputs; i++)
        sanitize_channel_layouts(ctx, ctx->inputs[i]->outcfg.channel_layouts);
    for (i = 0; i < ctx->nb_outputs; i++)
        sanitize_channel_layouts(ctx, ctx->outputs[i]->incfg.channel_layouts);
//如果query_formats函数有,那么这里其实什么也不做
    formats = ff_all_formats(type);
    if ((ret = ff_set_common_formats(ctx, formats)) < 0)
        return ret;
    if (type == AVMEDIA_TYPE_AUDIO) {
        samplerates = ff_all_samplerates();
        if ((ret = ff_set_common_samplerates(ctx, samplerates)) < 0)
            return ret;
        chlayouts = ff_all_channel_layouts();
        if ((ret = ff_set_common_channel_layouts(ctx, chlayouts)) < 0)
            return ret;
    }
    return 0;
}

核心函数:ff_set_common_formats

int ff_set_common_formats(AVFilterContext *ctx, AVFilterFormats *formats)
{
    SET_COMMON_FORMATS(ctx, formats,
                       ff_formats_ref, ff_formats_unref);
}

看宏定义:

#define SET_COMMON_FORMATS(ctx, fmts, ref_fn, unref_fn)             \
    int count = 0, i;                                               \
                                                                    \
    if (!fmts)                                                      \
        return AVERROR(ENOMEM);                                     \
                                                                    \
    for (i = 0; i < ctx->nb_inputs; i++) {                          \
        if (ctx->inputs[i] && !ctx->inputs[i]->outcfg.fmts) {       \
            int ret = ref_fn(fmts, &ctx->inputs[i]->outcfg.fmts);   \
            if (ret < 0) {                                          \
                return ret;                                         \
            }                                                       \
            count++;                                                \
        }                                                           \
    }                                                               \
    for (i = 0; i < ctx->nb_outputs; i++) {                         \
        if (ctx->outputs[i] && !ctx->outputs[i]->incfg.fmts) {      \
            int ret = ref_fn(fmts, &ctx->outputs[i]->incfg.fmts);   \
            if (ret < 0) {                                          \
                return ret;                                         \
            }                                                       \
            count++;                                                \
        }                                                           \
    }                                                               \
                                                                    \
    if (!count) {                                                   \
        unref_fn(&fmts);                                            \
    }                                                               \
                                                                    \
    return 0;

接着看ref

int ff_formats_ref(AVFilterFormats *f, AVFilterFormats **ref)
{
    FORMATS_REF(f, ref, ff_formats_unref);
}

#define FORMATS_REF(f, ref, unref_fn)                                           \
    void *tmp;                                                                  \
                                                                                \
    if (!f)                                                                     \
        return AVERROR(ENOMEM);                                                 \
                                                                                \
    tmp = av_realloc_array(f->refs, sizeof(*f->refs), f->refcount + 1);         \
    if (!tmp) {                                                                 \
        unref_fn(&f);                                                           \
        return AVERROR(ENOMEM);                                                 \
    }                                                                           \
    f->refs = tmp;                                                              \
    f->refs[f->refcount++] = ref;                                               \
    *ref = f;                                                                   \
    return 0

主要看关键的三行代码:

    f->refs = tmp;                                                              \
    f->refs[f->refcount++] = ref;                                               \
    *ref = f;  

这就是最开始图片指示的互相引用。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/777978.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

C语言程序运行需要的两大环境《C语言进阶》

目录 程序的翻译环境和执行环境 翻译环境分为两部分&#xff0c;编译链接 第一步&#xff1a;预编译&#xff08;预处理&#xff09; 第二步&#xff0c;编译 第三步&#xff1a;汇编 关于运行环境分为四点&#xff1a; 关于链接库 程序的翻译环境和执行环境 在 ANSI C(标…

三十章:Segmenter:Transformer for Semantic Segmentation ——分割器:用于语义分割的Transformer

0.摘要 图像分割在单个图像块的级别上经常存在歧义&#xff0c;并需要上下文信息来达到标签一致性。在本文中&#xff0c;我们介绍了一种用于语义分割的Transformer模型- Segmenter。与基于卷积的方法相比&#xff0c;我们的方法允许在第一层和整个网络中对全局上下文进行建模。…

C语言 与 C++ 通讯录对比实现(附源码)

目录 1.通讯录的基本框架 C语言版 C版 2.增加联系人 C语言版 C版 3.删除联系人 C语言版 C版 4.查找与打印联系人 C语言版 C版 5.修改联系人 C语言版 C版 6.排序联系人 C语言版 C版 7.其他 8.总结 本文章将对C语言、C版本的通讯录进行对比实现。其中C版本引入大量C语言没有的特性…

macOS 源码编译 Percona XtraBackup

percona-xtrabackup-2.4.28.tar.gz安装依赖 ╰─➤ brew install cmake ╰─➤ cmake --version cmake version 3.27.0brew 安装 ╰─➤ brew update╰─➤ brew search xtrabackup > Formulae percona-xtrabackup╰─➤ brew install percona-xtrabackup╰─➤ xtr…

提升 API 可靠性的五种方法

API 在我们的数字世界中发挥着关键的作用&#xff0c;使各种不同的应用能够相互通信。然而&#xff0c;这些 API 的可靠性是保证依赖它们的应用程序功能正常、性能稳定的关键因素。本文&#xff0c;我们将探讨提高 API 可靠性的五种主要策略。 1.全面测试 要确保 API 的可靠性…

Kubernetes 入门

Kubernetes 入门 文章目录 Kubernetes 入门一、Kubernetes 环境部署1. 环境准备2. 测试部署 Nginx3. 在任意节点使用 kubectl 二、深入 pod1. 使用配置文件部署引用2. 探针 三、资源调度1.标签与选择器2.Deployment3.StatefulSet4.DaemonSet5.HPA6. Service7. Ingress8. 配置管…

【Unity】为角色添加动画

如何添加动画 在Animations的AnimationClips文件夹下自己为角色创建一个文件夹 为角色添加Animator 然后选中上面创建的文件夹&#xff0c;拖动到上图中的Controller中 点击最上方任务栏的Window>Animation>Animation&#xff0c;这会弹出一个Animation窗口 该窗口存在时…

算法leetcode|63. 不同路径 II(rust重拳出击)

文章目录 63. 不同路径 II&#xff1a;样例 1&#xff1a;样例 2&#xff1a;提示&#xff1a; 分析&#xff1a;题解&#xff1a;rust&#xff1a;go&#xff1a;c&#xff1a;python&#xff1a;java&#xff1a; 63. 不同路径 II&#xff1a; 一个机器人位于一个 m x n 网格…

SQL_SQL_常见面试问题

问题类型 &#xff1a;SQL优化 问题描述 &#xff1a;用户浏览日志&#xff08;date, user_id, video_id&#xff09;, 统计 2020.03.29 观看不同视频个数的前5名 user_id。 思路 &#xff1a;主要注意预计算&#xff0c;避免直接去重 解决方案 &#xff1a; Hive_HQL_Hive…

【VB6|第20期】遍历Excel单元格的四种方法

日期&#xff1a;2023年7月19日 作者&#xff1a;Commas 签名&#xff1a;(ง •_•)ง 积跬步以致千里,积小流以成江海…… 注释&#xff1a;如果您觉得有所帮助&#xff0c;帮忙点个赞&#xff0c;也可以关注我&#xff0c;我们一起成长&#xff1b;如果有不对的地方&#xf…

架构实战微服务架构拆解

作业内容 拆分电商系统为微服务。 背景&#xff1a;假设你现在是一个创业公司的 CTO&#xff0c;开发团队大约 30 人左右&#xff0c;包括 5 个前端和 25 个后端&#xff0c;后端开发人员 全部都是 Java&#xff0c;现在你们准备从 0 开始做一个小程序电商业务&#xff0c;请你…

2023牛客暑期多校训练营1--K Subdivision(最短路树)

题目描述 You are given a graph with n vertices and m undirected edges of length 1. You can do the following operation on the graph for arbitrary times: Choose an edge (u,v) and replace it by two edges, (u,w) and (w,v), where w is a newly inserted vertex.…

【毕业季】九年程序猿有话说

活动地址&#xff1a;毕业季进击的技术er 九年程序猿有话说 勇敢前行&#xff0c;绽放青春&#xff0c;不负韶华&#xff01;选择IT的原因职场新人如何选择工作工作中&#xff0c;如何快速成长工作中用技术做过的最有成就感的事&#xff1f;程序员三十五岁瓶颈你怎么看&#xf…

445. 两数相加 II

445. 两数相加 II 给你两个 非空 链表来代表两个非负整数。数字最高位位于链表开始位置。它们的每个节点只存储一位数字。将这两数相加会返回一个新的链表。 你可以假设除了数字 0 之外&#xff0c;这两个数字都不会以零开头。 示例1&#xff1a; 输入&#xff1a;l1 [7,2,4,…

RocketMQ教程-(4)-主题(Topic)

本文介绍 Apache RocketMQ 中主题&#xff08;Topic&#xff09;的定义、模型关系、内部属性、行为约束、版本兼容性及使用建议。 定义​ 主题是 Apache RocketMQ 中消息传输和存储的顶层容器&#xff0c;用于标识同一类业务逻辑的消息。 主题的作用主要如下&#xff1a; 定义…

断路器分、合闸线圈直流电阻试验和绝缘电阻试验

断路器分、合闸线圈直流电阻试验 试验目的 对于断路器来说, 分、 合闸线圈是用于控制断路器分合闸状态的重要控制元件。 断路器停电检修时, 可以通过测试分、 合闸线圈的直流电阻来判断其是否正常。 试验设备 万用表 厂家&#xff1a; 湖北众拓高试代销 试验接线 分、 合闸线圈…

Linux系统进程概念详解

这里写目录标题 冯诺依曼体系结构操作系统(Operator System)1.概念2.目的3.管理4.系统调用和库函数概念 进程1.概念2.描述进程-PCB3.查看进程4.通过系统调用获取进程标示符5.通过系统调用创建进程-fork 进程状态1.Linux内核源代码2.进程状态查看 进程优先级1.基本概念2.查看系统…

dxf怎么转换成PDF格式?转换方法其实很简单

PDF文件是一种可靠的文件格式&#xff0c;可以在各种操作系统和软件上打开和查看。而dxf是CAD文件的一种格式&#xff0c;打开它一般都是需要相关的操作软件才能打开&#xff0c;不是特别方便&#xff0c;将dxf文件转换成PDF格式就可以很好的解决这一问题&#xff0c;下面教大家…

python:基于反卷积算法的 GEDI 波形树高特征提取

作者:CSDN @ _养乐多_ 本文将介绍如何对 GEDI(Global Ecosystem Dynamics Investigation)激光雷达数据中所标识激光测高数据点的波形数据使用反卷积算法提取树高特征。 文章目录 一、波形数据提取二、代码详细解释三、完整代码一、波形数据提取 波形数据提取参考博客:《p…

Nodejs+vue+elementui手机电脑产品维修售后服务管理系统

需求分析&#xff0c;也称为软件需求分析、系统需求分析或需求分析工程&#xff0c;是指开发人员经过充分的研究和分析&#xff0c;准确地理解用户和项目在功能、性能、可靠性等方面的具体需求&#xff0c;并将用户的非正式需求表述转化为确定系统必须执行的需求的完整定义的过…