关于ffmpeg中的AV_CLASS 和 priv_data的设计技巧

news/2024/7/10 19:12:07 标签: ffmpeg

AVClass 和 priv_data 是 FFmpeg 中实现封装和多态的关键设计技巧,下面我将分别介绍它们的设计原理和使用方法。

一、AVClass 的设计原理

AVClass 是一个类似于 C++ 中虚基类(virtual base class)的结构体,用于实现多继承的功能。它定义了一系列函数指针,这些函数指针可以被子类所覆盖,从而实现子类对父类的重载(override)。AVClass 结构体中的函数指针通常都是静态的,也就是说,它们并不依赖于具体的对象实例,从而避免了在运行时动态绑定的成本。

AVClass 在 FFmpeg 中的具体应用有很多,其中比较重要的是作为 AVCodecContext 的一个成员变量,用于表示编解码器的类型信息和参数设置。对于每个 AVCodecContext 实例,都会有一个 AVClass 结构体与之对应。这样,每个编解码器都可以通过 AVClass 中的函数指针来访问对应的解码和编码函数,从而实现多态性。

二、使用 AVClass 的方法

下面给出一个使用 AVClass 的示例:

  1. 定义一个继承了 AVClass 的结构体:
    typedef struct MyAVCodecContext {
        const AVClass *class;
        int my_param;
    } MyAVCodecContext;

  2. 实现 MyAVCodecContext 的构造函数和析构函数:
    static void my_codec_context_init(MyAVCodecContext *ctx)
    {
        ctx->my_param = 42;
    }
    
    static void my_codec_context_free(MyAVCodecContext *ctx)
    {
        // do some cleanup work
    }

  3. 定义一个子类,继承自 MyAVCodecContext:
    typedef struct MyAVCodecContext2 {
        MyAVCodecContext parent;
        int my_param2;
    } MyAVCodecContext2;

  4. 实现 MyAVCodecContext2 的构造函数和析构函数:
    static void my_codec_context_2_init(MyAVCodecContext2 *ctx)
    {
        my_codec_context_init((MyAVCodecContext *) ctx);
        ctx->my_param2 = 24;
    }
    
    static void my_codec_context_2_free(MyAVCodecContext2 *ctx)
    {
        my_codec_context_free((MyAVCodecContext *) ctx);
        // do some additional cleanup work
    }

  5. 实现 AVClass 中的函数指针:
    static const AVClass my_av_class = {
        .class_name = "MyAVCodecContext",
        .item_name  = av_default_item_name,
        .option     = my_codec_context_option,
        .version    = LIBAVUTIL_VERSION_INT,
    };
    
    static int my_codec_context_option(void *obj, const char *key, const char *val)
    {
        MyAVCodecContext *ctx = obj;
    
        if (!strcmp(key, "my_param")) {
            ctx->my_param = atoi(val);
            return 0;
        }
    
        return AVERROR_OPTION_NOT_FOUND;
    }

  6. 在创建时设置类指针:
    MyAVCodecContext2 *ctx2 = av_mallocz(sizeof(MyAVCodecContext2));
    ctx2->parent.class = &my_av_class;
    my_codec_context_2_init(ctx2);

    三、priv_data 的设计原理

    在 FFmpeg 中,很多数据结构都有私有数据(priv_data),私有数据是指某个结构体中仅该结构体所包含、外部无法直接访问的成员变量。使用私有数据的主要目的是为了实现数据的封装和隐藏,从而保护内部的属性和操作不受外部的干扰。

    在 FFmpeg 中,私有数据通常是通过 void 类型的指针来实现的。对于每个数据结构,都有一个指向私有数据的指针,在创建时会动态地分配内存,并将指针赋值给该数据结构的 priv_data 成员变量。这样,外部代码就不能直接访问数据结构中的私有数据,只能通过公共的操作函数来访问或修改私有数据。

    四、使用 priv_data 的方法

    下面给出一个使用 priv_data 的示例:

  1. 定义一个包含私有数据的结构体:
    typedef struct MyAVCodecContext {
        int my_public_param;
        void *priv_data;
    } MyAVCodecContext;

  2. 定义私有数据的结构体:
    typedef struct MyAVCodecContextPriv {
        int my_private_param;
    } MyAVCodecContextPriv;

  3. 实现操作私有数据的函数:
    static void my_codec_context_priv_init(MyAVCodecContextPriv *priv)
    {
        priv->my_private_param = 42;
    }
    
    static void my_codec_context_priv_free(MyAVCodecContextPriv *priv)
    {
        // do some cleanup work
    }

  4. 实现公共的操作函数:
    static void my_codec_context_init(MyAVCodecContext *ctx)
    {
        ctx->priv_data = av_mallocz(sizeof(MyAVCodecContextPriv));
        my_codec_context_priv_init(ctx->priv_data);
        ctx->my_public_param = 24;
    }
    
    static void my_codec_context_free(MyAVCodecContext *ctx)
    {
        my_codec_context_priv_free(ctx->priv_data);
        av_free(ctx->priv_data);
        // do some additional cleanup work
    }

  5. 在创建时设置私有数据的指针:
    MyAVCodecContext *ctx = av_mallocz(sizeof(MyAVCodecContext));
    my_codec_context_init(ctx);

    通过使用 priv_data,可以有效地实现数据的封装和隐藏,从而保护内部的属性和操作不受外部的干扰。


http://www.niftyadmin.cn/n/239333.html

相关文章

nginx部署VUE项目

前言 目前公司的前端代码基本都是部署在nginx下,特此来记录一下 开发环境:window10 nginx环境搭建(参考下方文章) window环境安装 mac环境安装 本地我将nginx放置于F盘 前端项目打包 一个nginx服务下可能会放置多个前端包&…

百度发布Apollo城市智驾,距离AI智能驾驶还有多远?

推荐:将NSDT场景编辑器加入你的3D工具链。 工具集:NSDT简石数字孪生 随着人工智能技术的不断发展,智能驾驶已经成为了汽车行业的一个重要领域。智能驾驶可以减少人为驾驶的错误和疲劳驾驶等不安全因素,提高驾驶安全性&#xff0c…

【Jenkins 2.x 实践指南】2.7 pipeline -- 章节小结

目录 一、 pipeline入门 1. pipeline 是什么 2. Jenkinsfile 又是什么 3. pipeline语法 的选择 4. 创建第一个pipeline - helloworld Stage 1: 创建任务 Stage 2: 创建流水线 - Hello World Stage 3: 编写 pipeline 声明 Stage 4: 执行 Stage 5: 点击 #1 查看日志 …

【Linxu网络服务】DHCP

DHCP 一、DHCP工作原理1.1背景1.2优点1.3 DHCP分配方式1.4DHCP工作原理 二、使用DHCP动态配置主机地址2.1实验一:动态配置主机地址2.2给Linux客户机配置动态地址**2.4设置一个外网口,给客户端设置一个固定的ip地址 一、DHCP工作原理 作为服务端负责集中…

【设计模式】深入浅出--外观模式

文章目录 前言一、外观模式介绍二、案例场景三、外观模式优缺点四、外观模式应用场景总结 前言 不知道大家有没有比较过自己泡茶和去茶馆喝茶的区别,如果是自己泡茶需要自行准备茶叶、茶具和开水,而去茶馆喝茶,最简单的方式就是跟茶馆服务员…

【代码随想录】刷题Day1

1.二分边界问题 704. 二分查找 class Solution { public:int search(vector<int>& nums, int target) {int begin 0;int end nums.size()-1;int mid begin(end-begin)/2;while(begin<end){if(nums[mid]<target)beginmid1;else if(nums[mid]>target)end…

javascript支持带样式的excel导出库

zdhsoft/nodexlsx 之前一直使用node-xlsx这个来生成excel文件。大多数的情况下&#xff0c;这个完全胜任。前端时间&#xff0c;要求输出合并单元格&#xff0c;这个支持&#xff0c;然后要求居中&#xff0c;就嗝屁了~。没有办法&#xff0c;只好去找了。 最后找到一个xlsx-j…

低代码开发重要工具:jvs-logic(逻辑引擎)基础原理与功能架构

逻辑引擎介绍 逻辑引擎是一种能够处理逻辑表达式的程序&#xff0c;它能够根据用户输入的表达式计算出表达式的值。在实际应用中&#xff0c;逻辑引擎通常被用于处理规则引擎、决策系统、业务规则配置等领域&#xff0c;具有广泛的应用前景。 原理与核心功能描述 基础原理 …