parent
							
								
									0f7da1da13
								
							
						
					
					
						commit
						e2f8fd4a18
					
				| @ -0,0 +1,320 @@ | ||||
| AVCodec是存储编解码器信息的结构体。下面我们来分析一下该结构体里重要变量的含义和作用。 | ||||
| 
 | ||||
| # 一、源码整理 | ||||
| 
 | ||||
| 首先我们先看一下结构体AVCodec的定义的结构体源码(位于libavcodec/avcodec.h): | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| ``` | ||||
| /* 雷霄骅  | ||||
|  * 中国传媒大学/数字电视技术  | ||||
|  * leixiaohua1020@126.com  | ||||
|  *  | ||||
|  */ | ||||
|  /** | ||||
|  * AVCodec. | ||||
|  */ | ||||
| typedef struct AVCodec { | ||||
|     /** | ||||
|      * Name of the codec implementation. | ||||
|      * The name is globally unique among encoders and among decoders (but an | ||||
|      * encoder and a decoder can share the same name). | ||||
|      * This is the primary way to find a codec from the user perspective. | ||||
|      */ | ||||
|     const char *name; | ||||
|     /** | ||||
|      * Descriptive name for the codec, meant to be more human readable than name. | ||||
|      * You should use the NULL_IF_CONFIG_SMALL() macro to define it. | ||||
|      */ | ||||
|     const char *long_name; | ||||
|     enum AVMediaType type; | ||||
|     enum CodecID id; | ||||
|     /** | ||||
|      * Codec capabilities. | ||||
|      * see CODEC_CAP_* | ||||
|      */ | ||||
|     int capabilities; | ||||
|     const AVRational *supported_framerates; ///< array of supported framerates, or NULL if any, array is terminated by {0,0} | ||||
|     const enum PixelFormat *pix_fmts;       ///< array of supported pixel formats, or NULL if unknown, array is terminated by -1 | ||||
|     const int *supported_samplerates;       ///< array of supported audio samplerates, or NULL if unknown, array is terminated by 0 | ||||
|     const enum AVSampleFormat *sample_fmts; ///< array of supported sample formats, or NULL if unknown, array is terminated by -1 | ||||
|     const uint64_t *channel_layouts;         ///< array of support channel layouts, or NULL if unknown. array is terminated by 0 | ||||
|     uint8_t max_lowres;                     ///< maximum value for lowres supported by the decoder | ||||
|     const AVClass *priv_class;              ///< AVClass for the private context | ||||
|     const AVProfile *profiles;              ///< array of recognized profiles, or NULL if unknown, array is terminated by {FF_PROFILE_UNKNOWN} | ||||
|   | ||||
|     /***************************************************************** | ||||
|      * No fields below this line are part of the public API. They | ||||
|      * may not be used outside of libavcodec and can be changed and | ||||
|      * removed at will. | ||||
|      * New public fields should be added right above. | ||||
|      ***************************************************************** | ||||
|      */ | ||||
|     int priv_data_size; | ||||
|     struct AVCodec *next; | ||||
|     /** | ||||
|      * @name Frame-level threading support functions | ||||
|      * @{ | ||||
|      */ | ||||
|     /** | ||||
|      * If defined, called on thread contexts when they are created. | ||||
|      * If the codec allocates writable tables in init(), re-allocate them here. | ||||
|      * priv_data will be set to a copy of the original. | ||||
|      */ | ||||
|     int (*init_thread_copy)(AVCodecContext *); | ||||
|     /** | ||||
|      * Copy necessary context variables from a previous thread context to the current one. | ||||
|      * If not defined, the next thread will start automatically; otherwise, the codec | ||||
|      * must call ff_thread_finish_setup(). | ||||
|      * | ||||
|      * dst and src will (rarely) point to the same context, in which case memcpy should be skipped. | ||||
|      */ | ||||
|     int (*update_thread_context)(AVCodecContext *dst, const AVCodecContext *src); | ||||
|     /** @} */ | ||||
|   | ||||
|     /** | ||||
|      * Private codec-specific defaults. | ||||
|      */ | ||||
|     const AVCodecDefault *defaults; | ||||
|   | ||||
|     /** | ||||
|      * Initialize codec static data, called from avcodec_register(). | ||||
|      */ | ||||
|     void (*init_static_data)(struct AVCodec *codec); | ||||
|   | ||||
|     int (*init)(AVCodecContext *); | ||||
|     int (*encode)(AVCodecContext *, uint8_t *buf, int buf_size, void *data); | ||||
|     /** | ||||
|      * Encode data to an AVPacket. | ||||
|      * | ||||
|      * @param      avctx          codec context | ||||
|      * @param      avpkt          output AVPacket (may contain a user-provided buffer) | ||||
|      * @param[in]  frame          AVFrame containing the raw data to be encoded | ||||
|      * @param[out] got_packet_ptr encoder sets to 0 or 1 to indicate that a | ||||
|      *                            non-empty packet was returned in avpkt. | ||||
|      * @return 0 on success, negative error code on failure | ||||
|      */ | ||||
|     int (*encode2)(AVCodecContext *avctx, AVPacket *avpkt, const AVFrame *frame, | ||||
|                    int *got_packet_ptr); | ||||
|     int (*decode)(AVCodecContext *, void *outdata, int *outdata_size, AVPacket *avpkt); | ||||
|     int (*close)(AVCodecContext *); | ||||
|     /** | ||||
|      * Flush buffers. | ||||
|      * Will be called when seeking | ||||
|      */ | ||||
|     void (*flush)(AVCodecContext *); | ||||
| } AVCodec; | ||||
| ``` | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| # 二、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定义如下: | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| ``` | ||||
| enum AVMediaType { | ||||
|     AVMEDIA_TYPE_UNKNOWN = -1,  ///< Usually treated as AVMEDIA_TYPE_DATA | ||||
|     AVMEDIA_TYPE_VIDEO, | ||||
|     AVMEDIA_TYPE_AUDIO, | ||||
|     AVMEDIA_TYPE_DATA,          ///< Opaque data information usually continuous | ||||
|     AVMEDIA_TYPE_SUBTITLE, | ||||
|     AVMEDIA_TYPE_ATTACHMENT,    ///< Opaque data information usually sparse | ||||
|     AVMEDIA_TYPE_NB | ||||
| }; | ||||
| ``` | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| ### 2.enum AVCodecID id | ||||
| 
 | ||||
| AVCodecID定义如下: | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| ``` | ||||
| enum AVCodecID { | ||||
|     AV_CODEC_ID_NONE, | ||||
|   | ||||
|     /* video codecs */ | ||||
|     AV_CODEC_ID_MPEG1VIDEO, | ||||
|     AV_CODEC_ID_MPEG2VIDEO, ///< preferred ID for MPEG-1/2 video decoding | ||||
|     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定义如下: | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| ``` | ||||
| enum AVPixelFormat { | ||||
|     AV_PIX_FMT_NONE = -1, | ||||
|     AV_PIX_FMT_YUV420P,   ///< planar YUV 4:2:0, 12bpp, (1 Cr & Cb sample per 2x2 Y samples) | ||||
|     AV_PIX_FMT_YUYV422,   ///< packed YUV 4:2:2, 16bpp, Y0 Cb Y1 Cr | ||||
|     AV_PIX_FMT_RGB24,     ///< packed RGB 8:8:8, 24bpp, RGBRGB... | ||||
|     AV_PIX_FMT_BGR24,     ///< packed RGB 8:8:8, 24bpp, BGRBGR... | ||||
|     AV_PIX_FMT_YUV422P,   ///< planar YUV 4:2:2, 16bpp, (1 Cr & Cb sample per 2x1 Y samples) | ||||
|     AV_PIX_FMT_YUV444P,   ///< planar YUV 4:4:4, 24bpp, (1 Cr & Cb sample per 1x1 Y samples) | ||||
|     AV_PIX_FMT_YUV410P,   ///< planar YUV 4:1:0,  9bpp, (1 Cr & Cb sample per 4x4 Y samples) | ||||
|     AV_PIX_FMT_YUV411P,   ///< planar YUV 4:1:1, 12bpp, (1 Cr & Cb sample per 4x1 Y samples) | ||||
|     AV_PIX_FMT_GRAY8,     ///<        Y        ,  8bpp | ||||
|     AV_PIX_FMT_MONOWHITE, ///<        Y        ,  1bpp, 0 is white, 1 is black, in each byte pixels are ordered from the msb to the lsb | ||||
|     AV_PIX_FMT_MONOBLACK, ///<        Y        ,  1bpp, 0 is black, 1 is white, in each byte pixels are ordered from the msb to the lsb | ||||
|     AV_PIX_FMT_PAL8,      ///< 8 bit with PIX_FMT_RGB32 palette | ||||
|     AV_PIX_FMT_YUVJ420P,  ///< planar YUV 4:2:0, 12bpp, full scale (JPEG), deprecated in favor of PIX_FMT_YUV420P and setting color_range | ||||
|     AV_PIX_FMT_YUVJ422P,  ///< planar YUV 4:2:2, 16bpp, full scale (JPEG), deprecated in favor of PIX_FMT_YUV422P and setting color_range | ||||
|     AV_PIX_FMT_YUVJ444P,  ///< planar YUV 4:4:4, 24bpp, full scale (JPEG), deprecated in favor of PIX_FMT_YUV444P and setting color_range | ||||
|     AV_PIX_FMT_XVMC_MPEG2_MC,///< XVideo Motion Acceleration via common packet passing | ||||
|     AV_PIX_FMT_XVMC_MPEG2_IDCT, | ||||
|     ...(代码太长,略) | ||||
| } | ||||
| ``` | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| ### 4.const enum AVSampleFormat *sample_fmts | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| ``` | ||||
| enum AVSampleFormat { | ||||
|     AV_SAMPLE_FMT_NONE = -1, | ||||
|     AV_SAMPLE_FMT_U8,          ///< unsigned 8 bits | ||||
|     AV_SAMPLE_FMT_S16,         ///< signed 16 bits | ||||
|     AV_SAMPLE_FMT_S32,         ///< signed 32 bits | ||||
|     AV_SAMPLE_FMT_FLT,         ///< float | ||||
|     AV_SAMPLE_FMT_DBL,         ///< double | ||||
|   | ||||
|     AV_SAMPLE_FMT_U8P,         ///< unsigned 8 bits, planar | ||||
|     AV_SAMPLE_FMT_S16P,        ///< signed 16 bits, planar | ||||
|     AV_SAMPLE_FMT_S32P,        ///< signed 32 bits, planar | ||||
|     AV_SAMPLE_FMT_FLTP,        ///< float, planar | ||||
|     AV_SAMPLE_FMT_DBLP,        ///< double, planar | ||||
|   | ||||
|     AV_SAMPLE_FMT_NB           ///< Number of sample formats. DO NOT USE if linking dynamically | ||||
| }; | ||||
| ``` | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
|  每一个编解码器对应一个该结构体,查看一下ffmpeg的源代码,我们可以看一下H.264解码器的结构体如下所示(h264.c): | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| ``` | ||||
| AVCodec ff_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-4 AVC / MPEG-4 part 10"), | ||||
|     .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): | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| ``` | ||||
| AVCodec ff_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("JPEG 2000"), | ||||
|     .pix_fmts = | ||||
|         (const enum PixelFormat[]) {PIX_FMT_GRAY8, PIX_FMT_RGB24, PIX_FMT_NONE} | ||||
| }; | ||||
| ``` | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 下面简单介绍一下遍历ffmpeg中的解码器信息的方法(这些解码器以一个链表的形式存储):  | ||||
| 
 | ||||
| 1.注册所有编解码器:av_register_all(); | ||||
| 
 | ||||
| 2.声明一个AVCodec类型的指针,比如说AVCodec* first_c; | ||||
| 
 | ||||
| 3.调用av_codec_next()函数,即可获得指向链表下一个解码器的指针,循环往复可以获得所有解码器的信息。注意,如果想要获得指向第一个解码器的指针,则需要将该函数的参数设置为NULL。 | ||||
					Loading…
					
					
				
		Reference in new issue