注:写了一系列的结构体的分析的文章,在这里列一个列表:
FFMPEG结构体分析:AVStream
FFMPEG结构体分析:AVPacket
FFMPEG有几个最重要的结构体,包含了解协议,解封装,解码操作,此前已经进行过分析:
在此不再详述,其中AVCodec是存储编解码器信息的结构体。本文将会详细分析一下该结构体里每个变量的含义和作用。
首先看一下结构体的定义(位于avcodec.h文件中):
[cpp] view plain copy
/*雷霄骅
*中国传媒大学/数字电视技术
*
*/
/**
*AVCodec.
*/
typedefstructAVCodec{
/**
*Nameofthecodecimplementation.
*Thenameisgloballyuniqueamongencodersandamongdecoders(butan
*encoderandadecodercansharethesamename).
*Thisistheprimarywaytofindacodecfromtheuserperspective.
*/
constchar*name;
/**
*Descriptivenameforthecodec,meanttobemorehumanreadablethanname.
*YoushouldusetheNULL_IF_CONFIG_SMALL()macrotodefineit.
*/
constchar*long_name;
enumAVMediaTypetype;
enumCodecIDid;
/**
*Codeccapabilities.
*seeCODEC_CAP_*
*/
intcapabilities;
constAVRational*supported_framerates;///<arrayofsupportedframerates,orNULLifany,arrayisterminatedby{0,0}
constenumPixelFormat*pix_fmts;///<arrayofsupportedpixelformats,orNULLifunknown,arrayisterminatedby-1
constint*supported_samplerates;///<arrayofsupportedaudiosamplerates,orNULLifunknown,arrayisterminatedby0
constenumAVSampleFormat*sample_fmts;///<arrayofsupportedsampleformats,orNULLifunknown,arrayisterminatedby-1
constuint64_t*channel_layouts;///<arrayofsupportchannellayouts,orNULLifunknown.arrayisterminatedby0
uint8_tmax_lowres;///<maximumvalueforlowressupportedbythedecoder
constAVClass*priv_class;///<AVClassfortheprivatecontext
constAVProfile*profiles;///<arrayofrecognizedprofiles,orNULLifunknown,arrayisterminatedby{FF_PROFILE_UNKNOWN}
/*****************************************************************
*NofieldsbelowthislinearepartofthepublicAPI.They
*maynotbeusedoutsideoflibavcodecandcanbechangedand
*removedatwill.
*Newpublicfieldsshouldbeaddedrightabove.
*****************************************************************
*/
intpriv_data_size;
structAVCodec*next;
/**
*@nameFrame-levelthreadingsupportfunctions
*@{
*/
/**
*Ifdefined,calledonthreadcontextswhentheyarecreated.
*Ifthecodecallocateswritabletablesininit(),re-allocatethemhere.
*priv_datawillbesettoacopyoftheoriginal.
*/
int(*init_thread_copy)(AVCodecContext*);
/**
*Copynecessarycontextvariablesfromapreviousthreadcontexttothecurrentone.
*Ifnotdefined,thenextthreadwillstartautomatically;otherwise,thecodec
*mustcallff_thread_finish_setup().
*
*dstandsrcwill(rarely)pointtothesamecontext,inwhichcasememcpyshouldbeskipped.
*/
int(*update_thread_context)(AVCodecContext*dst,constAVCodecContext*src);
/**@}*/
/**
*Privatecodec-specificdefaults.
*/
constAVCodecDefault*defaults;
/**
*Initializecodecstaticdata,calledfromavcodec_register().
*/
void(*init_static_data)(structAVCodec*codec);
int(*init)(AVCodecContext*);
int(*encode)(AVCodecContext*,uint8_t*buf,intbuf_size,void*data);
/**
*EncodedatatoanAVPacket.
*
*@paramavctxcodeccontext
*@paramavpktoutputAVPacket(maycontainauser-providedbuffer)
*@param[in]frameAVFramecontainingtherawdatatobeencoded
*@param[out]got_packet_ptrencodersetsto0or1toindicatethata
*non-emptypacketwasreturnedinavpkt.
*@return0onsuccess,negativeerrorcodeonfailure
*/
int(*encode2)(AVCodecContext*avctx,AVPacket*avpkt,constAVFrame*frame,
int*got_packet_ptr);
int(*decode)(AVCodecContext*,void*outdata,int*outdata_size,AVPacket*avpkt);
int(*close)(AVCodecContext*);
/**
*Flushbuffers.
*Willbecalledwhenseeking
*/
void(*flush)(AVCodecContext*);
}AVCodec;
下面说一下最主要的几个变量:
const char *name:编解码器的名字,比较短
const char *long_name:编解码器的名字,全称,比较长
enum AVMediaType type:指明了类型,是视频,音频,还是字幕
enum AVCodecID id:ID,不重复
const AVRational *supported_framerates:支持的帧率(仅视频)
const enum AVPixelFormat *pix_fmts:支持的像素格式(仅视频)
const int *supported_samplerates:支持的采样率(仅音频)
const enum AVSampleFormat *sample_fmts:支持的采样格式(仅音频)
const uint64_t *channel_layouts:支持的声道数(仅音频)
int priv_data_size:私有数据的大小
详细介绍几个变量:
1.enum AVMediaType type
AVMediaType定义如下:
[cpp] view plain copy
- enumAVMediaType{
- AVMEDIA_TYPE_UNKNOWN=-1,///<UsuallytreatedasAVMEDIA_TYPE_DATA
- AVMEDIA_TYPE_VIDEO,
- AVMEDIA_TYPE_AUDIO,
- AVMEDIA_TYPE_DATA,///<Opaquedatainformationusuallycontinuous
- AVMEDIA_TYPE_SUBTITLE,
- AVMEDIA_TYPE_ATTACHMENT,///<Opaquedatainformationusuallysparse
- AVMEDIA_TYPE_NB
- };
2.enum AVCodecID id
AVCodecID定义如下:
[cpp] view plain copy
enumAVCodecID{
AV_CODEC_ID_NONE,
/*videocodecs*/
AV_CODEC_ID_MPEG1VIDEO,
AV_CODEC_ID_MPEG2VIDEO,///<preferredIDforMPEG-1/2videodecoding
AV_CODEC_ID_MPEG2VIDEO_XVMC,
AV_CODEC_ID_H261,
AV_CODEC_ID_H263,
AV_CODEC_ID_RV10,
AV_CODEC_ID_RV20,
AV_CODEC_ID_MJPEG,
AV_CODEC_ID_MJPEGB,
AV_CODEC_ID_LJPEG,
AV_CODEC_ID_SP5X,
AV_CODEC_ID_JPEGLS,
AV_CODEC_ID_MPEG4,
AV_CODEC_ID_RAWVIDEO,
AV_CODEC_ID_MSMPEG4V1,
AV_CODEC_ID_MSMPEG4V2,
AV_CODEC_ID_MSMPEG4V3,
AV_CODEC_ID_WMV1,
AV_CODEC_ID_WMV2,
AV_CODEC_ID_H263P,
AV_CODEC_ID_H263I,
AV_CODEC_ID_FLV1,
AV_CODEC_ID_SVQ1,
AV_CODEC_ID_SVQ3,
AV_CODEC_ID_DVVIDEO,
AV_CODEC_ID_HUFFYUV,
AV_CODEC_ID_CYUV,
AV_CODEC_ID_H264,
...(代码太长,略)
}
3.const enum AVPixelFormat *pix_fmts
AVPixelFormat定义如下:
[cpp] view plain copy
- enumAVPixelFormat{
- AV_PIX_FMT_NONE=-1,
- AV_PIX_FMT_YUV420P,///<planarYUV4:2:0,12bpp,(1Cr&Cbsampleper2x2Ysamples)
- AV_PIX_FMT_YUYV422,///<packedYUV4:2:2,16bpp,Y0CbY1Cr
- AV_PIX_FMT_RGB24,///<packedRGB8:8:8,24bpp,RGBRGB...
- AV_PIX_FMT_BGR24,///<packedRGB8:8:8,24bpp,BGRBGR...
- AV_PIX_FMT_YUV422P,///<planarYUV4:2:2,16bpp,(1Cr&Cbsampleper2x1Ysamples)
- AV_PIX_FMT_YUV444P,///<planarYUV4:4:4,24bpp,(1Cr&Cbsampleper1x1Ysamples)
- AV_PIX_FMT_YUV410P,///<planarYUV4:1:0,9bpp,(1Cr&Cbsampleper4x4Ysamples)
- AV_PIX_FMT_YUV411P,///<planarYUV4:1:1,12bpp,(1Cr&Cbsampleper4x1Ysamples)
- AV_PIX_FMT_GRAY8,///<Y,8bpp
- AV_PIX_FMT_MONOWHITE,///<Y,1bpp,0iswhite,1isblack,ineachbytepixelsareorderedfromthemsbtothelsb
- AV_PIX_FMT_MONOBLACK,///<Y,1bpp,0isblack,1iswhite,ineachbytepixelsareorderedfromthemsbtothelsb
- AV_PIX_FMT_PAL8,///<8bitwithPIX_FMT_RGB32palette
- AV_PIX_FMT_YUVJ420P,///<planarYUV4:2:0,12bpp,fullscale(JPEG),deprecatedinfavorofPIX_FMT_YUV420Pandsettingcolor_range
- AV_PIX_FMT_YUVJ422P,///<planarYUV4:2:2,16bpp,fullscale(JPEG),deprecatedinfavorofPIX_FMT_YUV422Pandsettingcolor_range
- AV_PIX_FMT_YUVJ444P,///<planarYUV4:4:4,24bpp,fullscale(JPEG),deprecatedinfavorofPIX_FMT_YUV444Pandsettingcolor_range
- AV_PIX_FMT_XVMC_MPEG2_MC,///<XVideoMotionAccelerationviacommonpacketpassing
- AV_PIX_FMT_XVMC_MPEG2_IDCT,
- ...(代码太长,略)
- }
4.const enum AVSampleFormat *sample_fmts
[cpp] view plain copy
enumAVSampleFormat{
AV_SAMPLE_FMT_NONE=-1,
AV_SAMPLE_FMT_U8,///<unsigned8bits
AV_SAMPLE_FMT_S16,///<signed16bits
AV_SAMPLE_FMT_S32,///<signed32bits
AV_SAMPLE_FMT_FLT,///<float
AV_SAMPLE_FMT_DBL,///<double
AV_SAMPLE_FMT_U8P,///<unsigned8bits,planar
AV_SAMPLE_FMT_S16P,///<signed16bits,planar
AV_SAMPLE_FMT_S32P,///<signed32bits,planar
AV_SAMPLE_FMT_FLTP,///<float,planar
AV_SAMPLE_FMT_DBLP,///<double,planar
AV_SAMPLE_FMT_NB///<Numberofsampleformats.DONOTUSEiflinkingdynamically
};
每一个编解码器对应一个该结构体,查看一下ffmpeg的源代码,我们可以看一下H.264解码器的结构体如下所示(h264.c):
[cpp] view plain copy
- AVCodecff_h264_decoder={
- .name="h264",
- .type=AVMEDIA_TYPE_VIDEO,
- .id=CODEC_ID_H264,
- .priv_data_size=sizeof(H264Context),
- .init=ff_h264_decode_init,
- .close=ff_h264_decode_end,
- .decode=decode_frame,
- .capabilities=/*CODEC_CAP_DRAW_HORIZ_BAND|*/CODEC_CAP_DR1|CODEC_CAP_DELAY|
- CODEC_CAP_SLICE_THREADS|CODEC_CAP_FRAME_THREADS,
- .flush=flush_dpb,
- .long_name=NULL_IF_CONFIG_SMALL("H.264/AVC/MPEG-4AVC/MPEG-4part10"),
- .init_thread_copy=ONLY_IF_THREADS_ENABLED(decode_init_thread_copy),
- .update_thread_context=ONLY_IF_THREADS_ENABLED(decode_update_thread_context),
- .profiles=NULL_IF_CONFIG_SMALL(profiles),
- .priv_class=&h264_class,
- };
JPEG2000解码器结构体(j2kdec.c)
[cpp] view plain copy
- AVCodecff_jpeg2000_decoder={
- .name="j2k",
- .type=AVMEDIA_TYPE_VIDEO,
- .id=CODEC_ID_JPEG2000,
- .priv_data_size=sizeof(J2kDecoderContext),
- .init=j2kdec_init,
- .close=decode_end,
- .decode=decode_frame,
- .capabilities=CODEC_CAP_EXPERIMENTAL,
- .long_name=NULL_IF_CONFIG_SMALL("JPEG2000"),
- .pix_fmts=
- (constenumPixelFormat[]){PIX_FMT_GRAY8,PIX_FMT_RGB24,PIX_FMT_NONE}
- };
下面简单介绍一下遍历ffmpeg中的解码器信息的方法(这些解码器以一个链表的形式存储):
1.注册所有编解码器:av_register_all();
2.声明一个AVCodec类型的指针,比如说AVCodec*first_c;
3.调用av_codec_next()函数,即可获得指向链表下一个解码器的指针,循环往复可以获得所有解码器的信息。注意,如果想要获得指向第一个解码器的指针,则需要将该函数的参数设置为NULL。