FFmpeg源代码简单分析 结构体成员管理系统-AVClass

               

=====================================================

FFmpeg的库函数源代码分析文章列表:

【架构图】

FFmpeg源代码结构图 - 解码

FFmpeg源代码结构图 - 编码

【通用】

FFmpeg 源代码简单分析:av_register_all()

FFmpeg 源代码简单分析:avcodec_register_all()

FFmpeg 源代码简单分析:内存的分配和释放(av_malloc()、av_free()等)

FFmpeg 源代码简单分析:常见结构体的初始化和销毁(AVFormatContext,AVFrame等)

FFmpeg 源代码简单分析:avio_open2()

FFmpeg 源代码简单分析:av_find_decoder()和av_find_encoder()

FFmpeg 源代码简单分析:avcodec_open2()

FFmpeg 源代码简单分析:avcodec_close()

【解码】

图解FFMPEG打开媒体的函数avformat_open_input

FFmpeg 源代码简单分析:avformat_open_input()

FFmpeg 源代码简单分析:avformat_find_stream_info()

FFmpeg 源代码简单分析:av_read_frame()

FFmpeg 源代码简单分析:avcodec_decode_video2()

FFmpeg 源代码简单分析:avformat_close_input()

【编码】

FFmpeg 源代码简单分析:avformat_alloc_output_context2()

FFmpeg 源代码简单分析:avformat_write_header()

FFmpeg 源代码简单分析:avcodec_encode_video()

FFmpeg 源代码简单分析:av_write_frame()

FFmpeg 源代码简单分析:av_write_trailer()

【其它】

FFmpeg源代码简单分析:日志输出系统(av_log()等)

FFmpeg源代码简单分析:结构体成员管理系统-AVClass

FFmpeg源代码简单分析:结构体成员管理系统-AVOption

FFmpeg源代码简单分析:libswscale的sws_getContext()

FFmpeg源代码简单分析:libswscale的sws_scale()

FFmpeg源代码简单分析:libavdevice的avdevice_register_all()

FFmpeg源代码简单分析:libavdevice的gdigrab

【脚本】

FFmpeg源代码简单分析:makefile

FFmpeg源代码简单分析:configure

【H.264】

FFmpeg的H.264解码器源代码简单分析:概述

=====================================================


 打算写两篇文章记录FFmpeg中和AVOption有关的源代码。AVOption用于在FFmpeg中描述结构体中的成员变量。它最主要的作用可以概括为两个字:“赋值”。一个AVOption结构体包含了变量名称,简短的帮助,取值等等信息。

 所有和AVOption有关的数据都存储在AVClass结构体中。如果一个结构体(例如AVFormatContext或者AVCodecContext)想要支持AVOption的话,它的第一个成员变量必须是一个指向AVClass结构体的指针。该AVClass中的成员变量option必须指向一个AVOption类型的静态数组。


何为AVOption?

 AVOption是用来设置FFmpeg中变量的值的结构体。可能说到这个作用有的人会奇怪:设置系统中变量的值,直接使用等于号“=”就可以,为什么还要专门定义一个结构体呢?其实AVOption的特点就在于它赋值时候的灵活性。AVOption可以使用字符串为任何类型的变量赋值。传统意义上,如果变量类型为int,则需要使用整数来赋值;如果变量为double,则需要使用小数来赋值;如果变量类型为char *,才需要使用字符串来赋值。而AVOption将这些赋值“归一化”了,统一使用字符串赋值。例如给int型变量qp设定值为20,通过AVOption需要传递进去一个内容为“20”的字符串。
 此外,AVOption中变量的名称也使用字符串来表示。结合上面提到的使用字符串赋值的特性,我们可以发现使用AVOption之后,传递两个字符串(一个是变量的名称,一个是变量的值)就可以改变系统中变量的值。
 上文提到的这种方法的意义在哪里?我个人感觉对于直接使用C语言进行开发的人来说,作用不是很明显:完全可以使用等于号“=”就可以进行各种变量的赋值。但是对于从外部系统中调用FFmpeg的人来说,作用就很大了:从外部系统中只可以传递字符串给内部系统。比如说对于直接调用ffmpeg.exe的人来说,他们是无法修改FFmpeg内部各个变量的数值的,这种情况下只能通过输入“名称”和“值”这样的字符串,通过AVOption改变FFmpeg内部变量的值。由此可见,使用AVOption可以使FFmpeg更加适应多种多样的外部系统。

 突然想到了JavaEE开发中也有这种类似的机制。互联网上只可以传输字符串,即是没有方法传输整形、浮点型这种的数据。而Java系统中却包含整形、浮点型等各种数据类型。因此开发JSP中的Servlet的时候经常需要将整数字符串手工转化成一个整型的变量。使用最多的一个函数就是Integer.parseInt()方法。例如下面代码可以将字符串“123”转化成整数123。

int a=Integer.parseInt("123");

 而在使用JavaEE中的Struts2进行开发的时候,就不需要进行手动转换处理了。Struts2中包含了类似AVOption的这种数据类型自动转换机制,可以将互联网上收到的字符串“名称”和“值”的组合自动赋值给相应名称的变量。
 由此发现了一个结论:编程语言之间真的是相通的!


 现在回到AVOption。其实除了可以对FFmpeg常用结构体AVFormatContext,AVCodecContext等进行赋值之外,还可以对它们的私有数据priv_data进行赋值。这个字段里通常存储了各种编码器特有的结构体。而这些结构体的定义在FFmpeg的SDK中是找不到的。例如使用libx264进行编码的时候,通过AVCodecContext的priv_data字段可以对X264Context结构体中的变量进行赋值,设置preset,profile等。使用libx265进行编码的时候,通过AVCodecContext的priv_data字段可以对libx265Context结构体中的变量进行赋值,设置preset,tune等。

何为AVClass?

 AVClass最主要的作用就是给结构体(例如AVFormatContext等)增加AVOption功能的支持。换句话说AVClass就是AVOption和目标结构体之间的“桥梁”。AVClass要求必须声明为目标结构体的第一个变量。

 AVClass中有一个option数组用于存储目标结构体的所有的AVOption。举个例子,AVFormatContext结构体,AVClass和AVOption之间的关系如下图所示。


 图中AVFormatContext结构体的第一个变量为AVClass类型的指针av_class,它在AVFormatContext结构体初始化的时候,被赋值指向了全局静态变量av_format_context_class结构体(定义位于libavformat\options.c)。而AVClass类型的av_format_context_class结构体中的option变量指向了全局静态数组avformat_options(定义位于libavformat\options_table.h)。

AVOption

 下面开始从代码的角度记录AVOption。AVOption结构体的定义如下所示。
/** * AVOption */typedef struct AVOption {
        const char *name;    /**     * short English help text     * @todo What about other languages?     */    const char *help;    /**     * The offset relative to the context structure where the option     * value is stored. It should be 0 for named constants.     */    int offset;    enum AVOptionType type;    /**     * the default value for scalar options     */    union {        int64_t i64;        double dbl;        const char *str;        /* TODO those are unused now */        AVRational q;    } default_val;    double min;                 ///< minimum valid value for the option    double max;                 ///< maximum valid value for the option    int flags;#define AV_OPT_FLAG_ENCODING_PARAM  1   ///< a generic parameter which can be set by the user for muxing or encoding#define AV_OPT_FLAG_DECODING_PARAM  2   ///< a generic parameter which can be set by the user for demuxing or decoding#if FF_API_OPT_TYPE_METADATA#define AV_OPT_FLAG_METADATA        4   ///< some data extracted or inserted into the file like title, comment, ...#endif#define AV_OPT_FLAG_AUDIO_PARAM     8#define AV_OPT_FLAG_VIDEO_PARAM     16#define AV_OPT_FLAG_SUBTITLE_PARAM  32/** * The option is inteded for exporting values to the caller. */#define AV_OPT_FLAG_EXPORT          64/** * The option may not be set through the AVOptions API, only read. * This flag only makes sense when AV_OPT_FLAG_EXPORT is also set. */#define AV_OPT_FLAG_READONLY        128#define AV_OPT_FLAG_FILTERING_PARAM (1<<16) ///< a generic parameter which can be set by the user for filtering//FIXME think about enc-audio, ... style flags    /**     * The logical unit to which the option belongs. Non-constant     * options and corresponding named constants share the same     * unit. May be NULL.     */    const char *unit;} AVOption;

下面简单解释一下AVOption的几个成员变量:
name:名称。
help:简短的帮助。
offset:选项相对结构体首部地址的偏移量(这个很重要)。
type:选项的类型。
default_val:选项的默认值。
min:选项的最小值。
max:选项的最大值。
flags:一些标记。
unit:该选项所属的逻辑单元,可以为空。

 其中,default_val是一个union类型的变量,可以根据选项数据类型的不同,取int,double,char*,AVRational(表示分数)几种类型。type是一个AVOptionType类型的变量。AVOptionType是一个枚举类型,定义如下。

enum AVOptionType{    AV_OPT_TYPE_FLAGS,    AV_OPT_TYPE_INT,    AV_OPT_TYPE_INT64,    AV_OPT_TYPE_DOUBLE,    AV_OPT_TYPE_FLOAT,    AV_OPT_TYPE_STRING,    AV_OPT_TYPE_RATIONAL,    AV_OPT_TYPE_BINARY,  ///< offset must point to a pointer immediately followed by an int for the length    AV_OPT_TYPE_DICT,    AV_OPT_TYPE_CONST = 128,    AV_OPT_TYPE_IMAGE_SIZE = MKBETAG('S','I','Z','E'), ///< offset must point to two consecutive integers    AV_OPT_TYPE_PIXEL_FMT  = MKBETAG('P','F','M','T'),    AV_OPT_TYPE_SAMPLE_FMT = MKBETAG('S','F','M','T'),    AV_OPT_TYPE_VIDEO_RATE = MKBETAG('V','R','A','T'), ///< offset must point to AVRational    AV_OPT_TYPE_DURATION   = MKBETAG('D','U','R',' '),    AV_OPT_TYPE_COLOR      = MKBETAG('C','O','L','R'),    AV_OPT_TYPE_CHANNEL_LAYOUT = MKBETAG('C','H','L','A'),#if FF_API_OLD_AVOPTIONS    FF_OPT_TYPE_FLAGS = 0,    FF_OPT_TYPE_INT,    FF_OPT_TYPE_INT64,    FF_OPT_TYPE_DOUBLE,    FF_OPT_TYPE_FLOAT,    FF_OPT_TYPE_STRING,    FF_OPT_TYPE_RATIONAL,    FF_OPT_TYPE_BINARY,  ///< offset must point to a pointer immediately followed by an int for the length    FF_OPT_TYPE_CONST=128,#endif};


AVClass

 AVClass中存储了AVOption类型的数组option,用于存储选项信息。AVClass有一个特点就是它必须位于其支持的结构体的第一个位置。例如,AVFormatContext和AVCodecContext都支持AVClass,观察它们结构体的定义可以发现他们结构体的第一个变量都是AVClass。截取一小段AVFormatContext的定义的开头部分,如下所示。
typedef struct AVFormatContext {
        /**     * A class for logging and @ref avoptions. Set by avformat_alloc_context().     * Exports (de)muxer private options if they exist.     */    const AVClass *av_class;    /**     * The input container format.     *     * Demuxing only, set by avformat_open_input().     */    struct AVInputFormat *iformat;    /**     * The output container format.     *     * Muxing only, must be set by the caller before avformat_write_header().     */struct AVOutputFormat *oformat;//后文略

 截取一小段AVCodecContext的定义的开头部分,如下所示。
typedef struct AVCodecContext {
        /**     * information on struct for av_log     * - set by avcodec_alloc_context3     */    const AVClass *av_class;    int log_level_offset;    enum AVMediaType codec_type; /* see AVMEDIA_TYPE_xxx */    const struct AVCodec  *codec; //后文略

 下面来看一下AVClass的定义,如下所示。
/** * Describe the class of an AVClass context structure. That is an * arbitrary struct of which the first field is a pointer to an * AVClass struct (e.g. AVCodecContext, AVFormatContext etc.). */typedef struct AVClass {
        /**     * The name of the class; usually it is the same name as the     * context structure type to which the AVClass is associated.     */    const char* class_name;    /**     * A pointer to a function which returns the name of a context     * instance ctx associated wit
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值