ffmpeg中filter_query_formats函数解析

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;  

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

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Feign远程调用如何携带form url

这是一个需要携带参数在form url上的请求&#xff0c;正常调用方式是这样的 响应&#xff1a; 在Feign中&#xff0c;应该怎么调用呢?? 定义OpenFeignClient接口 FeignClient(value "client-service", url "http://127.0.0.1/api") public interface…

pytorch工具——认识pytorch

目录 pytorch的基本元素操作创建一个没有初始化的矩阵创建一个有初始化的矩阵创建一个全0矩阵并可指定数据元素类型为long直接通过数据创建张量通过已有的一个张量创建相同尺寸的新张量利用randn_like方法得到相同尺寸张量&#xff0c;并且采用随机初始化的方法为其赋值采用.si…

记一次简单的MySql注入试验

试验环境&#xff1a; 1.已经搭建好的php服务器&#xff0c;并可以通过访问到localhost/index.php&#xff1b; 2.已经安装好数据库&#xff0c;并创建表test&#xff0c;表内有name、age等字段&#xff0c;并随便创建几个假数据用于测试&#xff1b;如图&#xff1a; 开始测…

万向节死锁

要理解万向节死锁的产生原因&#xff0c;首先要理解欧拉角变换&#xff0c;欧拉角变换是基于最初始的坐标进行变换而非变换后的坐标进行变换。 欧拉角变换需要空间中的三个角&#xff08;即变换后每个轴的偏移量&#xff09;&#xff0c;另外还有每个轴的变换顺序。值得注意的…

安装:【vue】npm install -g @vue/cli出现错误

安装Vue脚手架&#xff0c;cli就是Command Line Interface 命令行接口 工具 进行到npm install -g vue/cli这一步出现错误&#xff0c;操作步骤如下&#xff1a; 1.通过 wins打开开始栏的搜索框&#xff0c;输入cmd&#xff0c;管理员身份运行 2.先下载node.js 不知道有没有…

应用案例 | 实现第三方控制系统下HART智能设备的集中管理与维护

一 背景 在过程工业向数字化转型的过程中&#xff0c;设备管理系统扮演者着关键的角色——帮助企业集中管理和监控现场设备&#xff0c;并实现全面的设备管理和维护。通过实时监测和控制设备的运行状态、性能和健康状况&#xff0c;设备管理系统能够提前发现设备故障、减少生产…

Transformer+医学图像最新进展【2023】

Transformer主要用于自然语言处理领域。近年来,它在计算机视觉(CV)领域得到了广泛的应用。医学图像分析(MIA,Medical image analysis)作为机器视觉(CV,Computer Vision)的一个重要分支,也极大地受益于这一最先进的技术。 机构:新加坡国立大学机械工程系、中山大学智能系…

链动2+1营销系统开发模式深度解析

链动21模式其实是一种针对快消品行业的营销模式&#xff0c;主要逻辑就是用薄利多销丰厚返利的方式来吸引客户&#xff0c;同时快速裂变团队。 这个模式的玩法也很简单&#xff0c;只有代理和老板两种身份&#xff0c;代理身份是用户购买499元产品可以解锁&#xff0c;同时享受…

es通过rest接口_search、_delete_by_query查询与删除数据

1、rest接口查询数据 rest查询: http://localhost:9200/index_name/_search 查询表达式&#xff1a; {"query": {"wildcard": {"accountID": {"value": "v*"}}} }postman请求截图&#xff1a; 2、使用Rest接口删除数据 …

Mysql表的查找进阶

重点细节知识&#xff1a;NULL是表示表里这个格子是空着的&#xff0c;NULL参与各种运算都是->false&#xff0c;但是只有这个才是可以用NULL等于NULL成功的 <>。,看一下&#xff0c;下图的区别&#xff0c;下面的是连空也算上了 补充一个is 用法&#xff0c;和上面语…

python实现远程服务器的操作

前言 测试过程中经常会遇到需要将本地的文件上传到远程服务器上&#xff0c;或者需要将服务器上的文件拉到本地就行操作&#xff0c;以前安静经常会用到xftp工具。今天介绍一种python库Paramiko&#xff0c;可以帮助我们通过代码的方式进行完成对远程服务器的上传和下载操作。…

OpenCV for Python 实战(一):获取图片拍摄GPS地址并自动添加水印

Hello 我们在OpenCV每天的基础博客当中已经更新了很多了&#xff0c;那么今天我们就来结合前几天的内容。做一个获取属性然后添加对应属性的水印。那让我们赶快开始吧~ 文章目录 图片EXIFPython 获取EXIFexifread库使用方法转换成文字地址 添加水印cv2.putText() 每日总结 图片…

了解应用层

应用层 1. 概述2. 应用程序组织方式2.1 C/S方式2.1 P2P方式 3. 动态主机配置协议DHCP3.1 DHCP工作流程 4. 域名系统DNS4.1 域名结构4.2 域名分类4.3 域名服务器4.3.1 分类 4.4 DNS域名解析过程 5. 文件传输协议FTP5.1 FTP工作流程 6. 电子邮件系统6.1 邮件信息格式6.2 简单邮件…

信息的表示与处理 (深入理解计算机系统第二章)

刚学习这本书没多久&#xff0c;感觉里面讲的东西挺多的&#xff0c;前后的关联性比较强。学着后面的还需要看看前的才可以更好的理解。 2.1信息存储 无符号(unsigned) 编码是基于传统的二进制表示法的&#xff0c;表示大于或者等于零的数字。 二进制补码(twos-complement)编…

存储过程——用户自定义变量、局部变量

1.用户自定义变量 在会话一定义的变量在会话二中是用不了的。 使用set指令定义变量,并为变量赋值&#xff0c;mysql中赋值推荐使用 :&#xff0c;因为在mysql中没有这个比较运算&#xff0c;也带有比较运算的功能&#xff0c;因此赋值运算推荐使用 : set myname itcast; se…

软件测试面试题及答案【史上最全】

以下是软件测试相关的面试题及答案&#xff0c;欢迎大家参考! 1、你的测试职业发展是什么? 测试经验越多&#xff0c;测试能力越高。所以我的职业发展是需要时间积累的&#xff0c;一步步向着高级测试工程师奔去。而且我也有初步的职业规划&#xff0c;前3年积累测试经验&…

边缘提取总结

边缘提取&#xff1a;什么是边缘&#xff1f; 图象的边缘是指图象局部区域亮度变化显著的部分&#xff0c;该区域的灰度剖面一般可以 看作是一个阶跃&#xff0c;既从一个灰度值在很小的缓冲区域内急剧变化到另一个灰度相 差较大的灰度值。 边缘有正负之分&#xff0c;就像…

uni-app:实现账号密码登录,并且实现当页面登录过该账号在下次登录时无需再输入账号密码(本地缓存实现)

效果 前端代码 一、完整代码 <template><view><view class"all"><view class"title"><image :src"title_login" alt"图片损坏" /></view><form class"login-form" submit"fo…

IDEA汉化插件

一、使用IDEA插件功能 重启IDEA 二、下载中文包 手动注入 进官网找自己IDEA对应版本的&#xff0c;下载压缩包&#xff1a;点我进官网 看自己的IDEA版本 把压缩包拖进去&#xff0c;IDEA里打开着文件也没关系 重启IDEA

[算法通关村] 1.2 链表的插入

上一节我们谈到了链表的概念&#xff0c;以及链表的创建方法&#xff0c;忘记的小伙伴可以复习一下&#xff1a; [算法通关村] 1.1 单向链表的创建 今天我们来探究一下链表的插入&#xff0c;链表的插入共有 3 种可能性&#xff0c;分别是在链表的头部插入、在中间插入&#x…