AVOption提供一个通用系统,用于在任意结构体里声明选项。一个选项可以有帮忙文本,类型和可能的值范围。选项可以枚举,读写。 AVOption结构体如下:AVOptiontypedefstructAVOption{constcharname;shortEnglishhelptexttodoWhataboutotherlanguages?constcharhelp;Theoffsetrelativetothecontextstructurewheretheoptionvalueisstored。Itshouldbe0fornamedconstants。intoffset;enumAVOptionTypetype;thedefaultvalueforscalaroptionsunion{int64ti64;doubledbl;constcharstr;TODOthoseareunusednowAVRationalq;}defaultval;doublemin;minimumvalidvaluefortheoptiondoublemax;maximumvalidvaluefortheoptionintflags;标记宏被我省略了。。。Thelogicalunittowhichtheoptionbelongs。Nonconstantoptionsandcorrespondingnamedconstantssharethesameunit。MaybeNULL。constcharunit;}AVOption; AVClass结构体如下:DescribetheclassofanAVClasscontextstructure。ThatisanarbitrarystructofwhichthefirstfieldisapointertoanAVClassstruct(e。g。AVCodecContext,AVFormatContextetc。)。typedefstructAVClass{Thenameoftheclass;usuallyitisthesamenameasthecontextstructuretypetowhichtheAVClassisassociated。constcharclassname;Apointertoafunctionwhichreturnsthenameofacontextinstancectxassociatedwiththeclass。constchar(itemname)(voidctx);apointertothefirstoptionspecifiedintheclassifanyorNULLseeavsetdefaultoptions()conststructAVOptionoption;LIBAVUTILVERSIONwithwhichthisstructurewascreated。Thisisusedtoallowfieldstobeaddedwithoutrequiringmajorversionbumpseverywhere。intversion;Offsetinthestructurewherelogleveloffsetisstored。0meansthereisnosuchvariableintlogleveloffsetoffset;Offsetinthestructurewhereapointertotheparentcontextforloggingisstored。ForexampleadecodercouldpassitsAVCodecContexttoevalassuchaparentcontext,whichanavlog()implementationcouldthenleveragetodisplaytheparentcontext。TheoffsetcanbeNULL。intparentlogcontextoffset;Categoryusedforvisualization(likecolor)Thisisonlysetifthecategoryisequalforallobjectsusingthisclass。availablesinceversion(5116568100)AVClassCategorycategory;Callbacktoreturnthecategory。availablesinceversion(5116598100)AVClassCategory(getcategory)(voidctx);Callbacktoreturnthesupportedallowedranges。availablesinceversion(52。12)int(queryranges)(structAVOptionRanges,voidobj,constcharkey,intflags);ReturnnextAVOptionsenabledchildorNULLvoid(childnext)(voidobj,voidprev);IterateovertheAVClassescorrespondingtopotentialAVOptionsenabledchildren。paramiterpointertoopaqueiterationstate。ThecallermustinitializeitertoNULLbeforethefirstcall。returnAVClassforthenextAVOptionsenabledchildorNULLiftherearenomoresuchchildren。noteThedifferencebetweenchildnextandthisisthatchildnextiteratesoveralreadyexistingobjects,whilechildclassiterateiteratesoverallpossiblechildren。conststructAVClass(childclassiterate)(voiditer);}AVClass;AVOption实现 这部分描述如何向一个结构体添加AVOption支持。 所有和AVOption相关的信息存储在一个叫AVClass的结构体中。因此结构体的第一个成员应该是指向AVClass的指针。AVClass的option成员必须指向一个静态的AVOption数组,数组以NULL结尾。 每个AVOption选项必须有一个非空的名字,一个类型,一个默认的值;对于值类型的AVOption也必须有一个允许的值范围;包含一个偏移量,指定结构体中和这个选项关联的字段的位置;AVOption中其他字段不是必须的,按情况赋值。 下面的例子展示了带AVOption支持的结构体:typedefstructteststruct{constAVClassclass;intintopt;charstropt;uint8tbinopt;intbinlen;}teststruct;staticconstAVOptiontestoptions〔〕{{testint,Thisisatestoptionofinttype。,offsetof(teststruct,intopt),AVOPTTYPEINT,{。i641},INTMIN,INTMAX},{teststr,Thisisatestoptionofstringtype。,offsetof(teststruct,stropt),AVOPTTYPESTRING},{testbin,Thisisatestoptionofbinarytype。,offsetof(teststruct,binopt),AVOPTTYPEBINARY},{NULL},};staticconstAVClasstestclass{。classnametestclass,。itemnameavdefaultitemname,。optiontestoptions,。versionLIBAVUTILVERSIONINT,}; 当你分配结构体时,要确保AVClass指针指向正确的值,avoptsetdefaults函数可以用来初始化。之后,该结构体就可以与AVOptionAPI一起使用了。 继续上面的例子,我们展示结构体的构造和释放:teststructallocteststruct(void){teststructretavmallocz(sizeof(ret));retclasstestclass;avoptsetdefaults(ret);returnret;}voidfreeteststruct(teststructfoo){avoptfree(foo);avfreep(foo);}AVOption嵌套 可能存在支持AVOption的结构体包含另一个支持AVOption的结构体 (比如AVCodecContext可以导出通用选项,然而它的privdata字段可以导出codec相关的选项)。在这种情况下,可以设置父结构体导出一个子结构体的选项,为了实现这个功能,只要在父结构体的AVClass中实现AVClass。childnext()函数和AVClass。childclassiterate函数。 假设上面的teststruct结构体现在包含一个childstruct成员:typedefstructchildstruct{AVClassclass;intflagsopt;}childstruct;staticconstAVOptionchildopts〔〕{{testflags,Thisisatestoptionofflagstype。,offsetof(childstruct,flagsopt),AVOPTTYPEFLAGS,{。i640},INTMIN,INTMAX},{NULL},};staticconstAVClasschildclass{。classnamechildclass,。itemnameavdefaultitemname,。optionchildopts,。versionLIBAVUTILVERSIONINT,};voidchildnext(voidobj,voidprev){teststructtobj;if(!prevtchildstruct)returntchildstruct;returnNULL;}constAVClasschildclassiterate(voiditer){constAVClassciter?NULL:childclass;iter(void)(uintptrt)c;returnc;} 将childnext和childclassiterate放入testclass中:staticconstAVClasstestclass{。classnametestclass,。itemnameavdefaultitemname,。optiontestoptions,。childnextchildnext,。childclassiteratechildclassiterate,。versionLIBAVUTILVERSIONINT,}; 现在可以通过teststruct访问childstruct的选项。 从上面的例子中,可能不清楚为什么同时需要childnext和childclassiterate,区别是childnext会遍历实际存在的对象,而childclassiterate会遍历所有可能的子类。比如如果AVCodecContext被初始化为使用具有私有选项的编解码器,那么它的childnext会返回AVCodecContext。privdata并结束遍历。而AVCodecContext。avclass中的childclassiterate会遍历所有具有私有选项的可用编解码器。命名常量 可以为选项创建命名常量。 只需设置选项的unit字段,并将常量本身创建为AVOPTTYPECONST类型的选项,其unit字段设置为相同的字符串。它们的defaultval字段应该包含命名常量的值。 例如,要为上面的testflags选项添加一些命名常量,请将以下内容放入childopts数组中:{testflags,Thisisatestoptionofflagstype。,offsetof(childstruct,flagsopt),AVOPTTYPEFLAGS,{。i640},INTMIN,INTMAX,。unittestunit},{flag1,Thisisaflagwithvalue16,0,AVOPTTYPECONST,{。i6416},0,0,。unittestunit},AVOption使用 本节讨论如何在支持AVOption的结构体中访问选项。支持AVOption的结构体有libavcodec模块的AVCodecContext以及libavformat模块的AVFormatContext等。检查AVOption 检查选项的基本函数是avoptnext()和avoptfind(),前者遍历一个对象定义的所有选项,后者搜索具有给定名称的选项。 嵌套的情况会更复杂一些。一个支持AVOption的结构体可能包含另一个支持AVOption的结构体。将AVOPTSEARCHCHILDREN标志传递给avoptfind()将使函数递归地搜索包含的结构体。 对于枚举,基本上有两种情况。第一种情况是当你想要获得结构及其子结构上可能存在的所有选项时(例如在构造文档时)。在这种情况下,你应该在父结构的AVClass上递归调用avoptchildclassiterate()。第二种情况是,当你有一个已经初始化的结构,你想要从它获得所有可以实际写入或读取的选项。在这种情况下,您应该递归调用avoptchildnext(),并在结果上调用avoptnext()。读写AVOption 在设置选项时,通常会直接从用户处读取字符串。在这种情况下,简单地将其传递给avoptset()就足够了。对于非字符串类型的选项,avoptset()将根据选项类型解析字符串。 类似地,avoptget()将读取任何选项类型并将其转换为字符串并返回。别忘了字符串是已分配的,所以你必须用avfree()释放它。 在某些情况下,将所有选项放入AVDictionary并在其上调用avoptsetdict()可能更方便。 一个具体的例子是lavflavc中的formatcodecopen函数,它以一个填充options的字典作为参数。