一:介绍
AVOptions是ffmpeg中实现的一种赋值机制,目的是可以方便地给结构体中的成员赋值。其实现类似于一种接口(虽然c语言没有接口概念但我们姑且这么叫)。为了实现这个接口,则结构体必须定义一个AVClass的结构为它的第一个变量,AVClass wrap了相应的Options数组。这只是一种实现机制罢了,类似于java的 implements ,c++的继承基类。
AVOptions 接口的详细介绍可参考:http://ffmpeg.org/doxygen/3.1/group__avoptions.html官方文档。
和 http://blog.csdn.net/leixiaohua1020/article/details/44268323 雷神的博客(在此缅怀下雷神)。
另外,为了方便操作Options ,可以将要设置的参数放入 AVDictionary 集合中,之后一并设置。
二:实例分析
以 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;
/**
* Format private data. This is an AVOptions-enabled struct
* if and only if iformat/oformat.priv_class is not NULL.
*
* - muxing: set by avformat_write_header()
* - demuxing: set by avformat_open_input()
*/
void *priv_data;
/**
* I/O context.
*
* - demuxing: either set by the user before avformat_open_input() (then
* the user must close it manually) or set by avformat_open_input().
* - muxing: set by the user before avformat_write_header(). The caller must
* take care of closing / freeing the IO context.
*
* Do NOT set this field if AVFMT_NOFILE flag is set in
* iformat/oformat.flags. In such a case, the (de)muxer will handle
* I/O in some other way and this field will be NULL.
*/
AVIOContext *pb;
/* stream info */
/**
* Flags signalling stream properties. A combination of AVFMTCTX_*.
* Set by libavformat.
*/
int ctx_flags;
/**
* Number of elements in AVFormatContext.streams.
*
* Set by avformat_new_stream(), must not be modified by any other code.
*/
unsigned int nb_streams;
/**
* A list of all streams in the file. New streams are created with
* avformat_new_stream().
*
* - demuxing: streams are created by libavformat in avformat_open_input().
* If AVFMTCTX_NOHEADER is set in ctx_flags, then new streams may also
* appear in av_read_frame().
* - muxing: streams are created by the user before avformat_write_header().
*
* Freed by libavformat in avformat_free_context().
*/
AVStream **streams;
/**
* input or output filename
*
* - demuxing: set by avformat_open_input()
* - muxing: may be set by the caller before avformat_write_header()
*/
char filename[1024];
/**
* Position of the first frame of the component, in
* AV_TIME_BASE fractional seconds. NEVER set this value directly:
* It is deduced from the AVStream values.
*
* Demuxing only, set by libavformat.
*/
int64_t start_time;
... ...
}
AVFormatContext 结构体的第一个成员为:const AVClass *av_class ,是为了实现AVClass接口。这个AVClass在
libavformat/options.c中定义:
static const AVClass av_format_context_class = {
.class_name = "AVFormatContext",
.item_name = format_to_name,
.option = avformat_options,
.version = LIBAVUTIL_VERSION_INT,
.child_next = format_child_next,
.child_class_next = format_child_class_next,
.category = AV_CLASS_CATEGORY_MUXER,
.get_category = get_category,
};
可见其包含了Options数组:avformat_options 。这个数组在 libavformat/options_table.h 中定义,options数组指定了 AVFormatContext 结构中变量的信息,偏移量等,可以说是一一对应的关系,这样就可以根据Options来设置 AVFormatContext 结构体中的变量。
当 AVFormatContext 实现了AVClass接口之后,就可以使用Options的API来对 AVFormatContext 结构体中变量进行操作了,具体的有 查询,修改等。可参见上述链接。总而言之,AVClass接口实现了用接口设置方式取代 “=” 赋值的方式。