【FFmpeg】AVCodec结构体
- 1. AVCodec的定义
- 2. AVCodec内结构体嵌套
- 2.1 enum AVMediaType type
- 2.2 enum AVCodecID id
- 2.3 const AVRational *supported_framerates
- 2.4 const enum AVPixelFormat *pix_fmts
- 2.5 const AVClass *priv_class
- 2.6 const AVProfile *profiles
参考:
FFMPEG结构体分析:AVCodec
示例工程:
【FFmpeg】调用ffmpeg库实现264软编
【FFmpeg】调用ffmpeg库实现264软解
【FFmpeg】调用ffmpeg库进行RTMP推流和拉流
【FFmpeg】调用ffmpeg库进行SDL2解码后渲染
流程分析:
【FFmpeg】编码链路上主要函数的简单分析
【FFmpeg】解码链路上主要函数的简单分析
本文参考了雷博士的文章,但不同之处在于记录的FFmpeg版本为7.0,由于FFmpeg有些更新,所以部分内容有些不太一样
1. AVCodec的定义
AVCodec是FFmpeg中最重要的结构体之一,它记录了编解码器中的重要信息,其定义位于libavcodec\codec.h中,如下所示
/*** 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; // 类型,指明是视频、音频还是字幕(如AVMEDIA_TYPE_VIDEO)enum AVCodecID id; // Codec的ID(如AV_CODEC_ID_H264)/*** Codec capabilities.* see AV_CODEC_CAP_**/// capabilities表示了codec的能力,例如配置为AV_CODEC_CAP_ENCODER_RECON_FRAME// 编码器能够输出重构的帧数据,即通过解码编码的比特流产生的原始帧。重构帧输出由AV_CODEC_FLAG_RECON_FRAME标志启用int capabilities; // 解码器支持的最大的低分辨率uint8_t max_lowres; ///< maximum value for lowres supported by the decoder// 【视频】支持的帧率,有多个支持的帧率,则为数组 AVRational = {int num, int den}const AVRational *supported_framerates; ///< array of supported framerates, or NULL if any, array is terminated by {0,0}// 【视频】支持的像素格式,有多个支持的格式,则为数组(如AV_PIX_FMT_YUV420P)const enum AVPixelFormat *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// 描述AVClass上下文结构的类。这是一个任意结构体,其第一个字段是指向AVClass结构体的指针(例如AVCodecContext, AVFormatContext等)// 这里应该是替代了早期的priv_data_sizeconst AVClass *priv_class; ///< AVClass for the private context// 被识别的配置文件数组,如果未知则为NULL,数组以{AV_PROFILE_UNKNOWN}终止const AVProfile *profiles; ///< array of recognized profiles, or NULL if unknown, array is terminated by {AV_PROFILE_UNKNOWN}/*** Group name of the codec implementation.* This is a short symbolic name of the wrapper backing this codec. A* wrapper uses some kind of external implementation for the codec, such* as an external library, or a codec implementation provided by the OS or* the hardware.* If this field is NULL, this is a builtin, libavcodec native codec.* If non-NULL, this will be the suffix in AVCodec.name in most cases* (usually AVCodec.name will be of the form "<codec_name>_<wrapper_name>").*/// 编解码器实现的组名称// 这是支持此编解码器的包装器的简短符号名称。包装器为编解码器使用某种外部实现,// 例如外部库,或者由操作系统或硬件提供的编解码器实现。如果该字段为NULL,// 则这是一个内置的libavcodec本机编解码器。如果非null,在大多数情况下,// 这将是AVCodec.name中的后缀(通常AVCodec.name将具有“<codec_name>_<wrapper_name>”的形式)const char *wrapper_name;/*** Array of supported channel layouts, terminated with a zeroed layout.*/// 【音频】支持的声道数,如果有多个,则维数组const AVChannelLayout *ch_layouts;
} AVCodec;
2. AVCodec内结构体嵌套
2.1 enum AVMediaType type
AVMediaType的声明位于libavutil/avutil.h,定义了媒体的类型,例如视频、音频,其余的不太理解,如下所示
/*** @addtogroup lavu_media Media Type* @brief Media Type*/enum AVMediaType {AVMEDIA_TYPE_UNKNOWN = -1, ///< Usually treated as AVMEDIA_TYPE_DATAAVMEDIA_TYPE_VIDEO,AVMEDIA_TYPE_AUDIO,AVMEDIA_TYPE_DATA, ///< Opaque data information usually continuousAVMEDIA_TYPE_SUBTITLE,AVMEDIA_TYPE_ATTACHMENT, ///< Opaque data information usually sparseAVMEDIA_TYPE_NB
};
2.2 enum AVCodecID id
AVCodecID的声明位于libavcodec\codec_id.h,标识了codec使用的类型
/*** Identify the syntax and semantics of the bitstream.* The principle is roughly:* Two decoders with the same ID can decode the same streams.* Two encoders with the same ID can encode compatible streams.* There may be slight deviations from the principle due to implementation* details.** If you add a codec ID to this list, add it so that* 1. no value of an existing codec ID changes (that would break ABI),* 2. it is as close as possible to similar codecs** After adding new codec IDs, do not forget to add an entry to the codec* descriptor list and bump libavcodec minor version.*/
// 确定位流的语法和语义
// 原则大致为:
// (1)两个具有相同ID的解码器能够解码出来相同的码流
// (2)两个具有相同ID的编码器能够编码出来兼容的码流
// 由于实现细节的原因,可能会与原则有轻微的偏差
// 如果将编解码器ID添加到此列表中,则添加它以便
// (1)现有编解码器ID的值不会改变(这会破坏ABI),
// (2)它尽可能接近类似的编解码器
// 在添加新的编解码器id之后,不要忘记在编解码器描述符列表中添加一个条目,并将libavcodec的次要版本升级
enum AVCodecID {AV_CODEC_ID_NONE,/* video codecs */AV_CODEC_ID_MPEG1VIDEO,AV_CODEC_ID_MPEG2VIDEO, ///< preferred ID for MPEG-1/2 video decodingAV_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, // H264标准// ...
2.3 const AVRational *supported_framerates
AVRational的声明位于libavutil\avutil.c中,常用于表示一些计数
/*** Rational number (pair of numerator and denominator).*/
typedef struct AVRational{// 分子int num; ///< Numerator// 分母int den; ///< Denominator
} AVRational;
2.4 const enum AVPixelFormat *pix_fmts
AVPixelFormat的定义位于libavutil\pixfmt.h中,描述了pixel的格式,其中最为常见的应该是YUV420P
/*** Pixel format.** @note* AV_PIX_FMT_RGB32 is handled in an endian-specific manner. An RGBA* color is put together as:* (A << 24) | (R << 16) | (G << 8) | B* This is stored as BGRA on little-endian CPU architectures and ARGB on* big-endian CPUs.** @note* If the resolution is not a multiple of the chroma subsampling factor* then the chroma plane resolution must be rounded up.** @par* When the pixel format is palettized RGB32 (AV_PIX_FMT_PAL8), the palettized* image data is stored in AVFrame.data[0]. The palette is transported in* AVFrame.data[1], is 1024 bytes long (256 4-byte entries) and is* formatted the same as in AV_PIX_FMT_RGB32 described above (i.e., it is* also endian-specific). Note also that the individual RGB32 palette* components stored in AVFrame.data[1] should be in the range 0..255.* This is important as many custom PAL8 video codecs that were designed* to run on the IBM VGA graphics adapter use 6-bit palette components.** @par* For all the 8 bits per pixel formats, an RGB32 palette is in data[1] like* for pal8. This palette is filled in automatically by the function* allocating the picture.*/
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 CrAV_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 , 8bppAV_PIX_FMT_MONOWHITE, ///< Y , 1bpp, 0 is white, 1 is black, in each byte pixels are ordered from the msb to the lsbAV_PIX_FMT_MONOBLACK, ///< Y , 1bpp, 0 is black, 1 is white, in each byte pixels are ordered from the msb to the lsbAV_PIX_FMT_PAL8, ///< 8 bits with AV_PIX_FMT_RGB32 palette// ...
2.5 const AVClass *priv_class
结构体的定义位于libavutil\log.h
/*** 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.).*/
// 描述AVClass上下文结构的类。这是一个任意结构体,
// 其第一个字段是指向AVClass结构体的指针(例如AVCodecContext, AVFormatContext等)
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.*/// 类的名称;通常它与AVClass所关联的上下文结构类型相同const char* class_name;/*** A pointer to a function which returns the name of a context* instance ctx associated with the class.*/// 指向一个函数的指针,该函数返回与类关联的上下文实例ctx的名称const char* (*item_name)(void* ctx);/*** a pointer to the first option specified in the class if any or NULL** @see av_set_default_options()*/// 指向类中指定的第一个选项的指针(如果有的话)或NULLconst struct AVOption *option;/*** LIBAVUTIL_VERSION with which this structure was created.* This is used to allow fields to be added without requiring major* version bumps everywhere.*/// LIBAVUTIL_VERSION,用来创建这个结构// 这是为了允许添加字段,而不需要到处出现重大版本颠簸。int version;/*** Offset in the structure where log_level_offset is stored.* 0 means there is no such variable*/// 存储log_level_offset的结构中的偏移量// 0表示没有这样的变量int log_level_offset_offset;/*** Offset in the structure where a pointer to the parent context for* logging is stored. For example a decoder could pass its AVCodecContext* to eval as such a parent context, which an av_log() implementation* could then leverage to display the parent context.* The offset can be NULL.*/// 结构中的偏移量,其中存储指向用于日志记录的父上下文的指针// 例如,解码器可以将其AVCodecContext作为父上下文传递给eval,然后av_log()实现可以利用它来显示父上下文// 偏移量可以为NULLint parent_log_context_offset;/*** Category used for visualization (like color)* This is only set if the category is equal for all objects using this class.* available since version (51 << 16 | 56 << 8 | 100)*/// 用于可视化的类别(如颜色)// 只有当使用该类的所有对象的类别相等时,才会设置此属性。版本(51 << 16 | 56 << 8 | 100)AVClassCategory category;/*** Callback to return the category.* available since version (51 << 16 | 59 << 8 | 100)*/// 回调返回类别。版本(51 << 16 | 59 << 8 | 100)AVClassCategory (*get_category)(void* ctx);/*** Callback to return the supported/allowed ranges.* available since version (52.12)*/// 回调返回支持/允许的范围。从版本(52.12)开始可用int (*query_ranges)(struct AVOptionRanges **, void *obj, const char *key, int flags);/*** Return next AVOptions-enabled child or NULL*/// 返回下一个启用avoptions的子节点或NULLvoid* (*child_next)(void *obj, void *prev);/*** Iterate over the AVClasses corresponding to potential AVOptions-enabled* children.** @param iter pointer to opaque iteration state. The caller must initialize* *iter to NULL before the first call.* @return AVClass for the next AVOptions-enabled child or NULL if there are* no more such children.** @note The difference between child_next and this is that child_next* iterates over _already existing_ objects, while child_class_iterate* iterates over _all possible_ children.*/// 迭代AVClasses对应于潜在的avoptions启用子类// @param Iter指针指向不透明的迭代状态。调用者必须在第一次调用之前将*iter初始化为NULL// @return AVClass用于下一个AVOptions-enabled的子节点,如果没有这样的子节点,则为NULL// @note child_next和this的区别在于,child_next迭代的是已经存在的对象,而child_class_iterate迭代的是所有可能的子对象const struct AVClass* (*child_class_iterate)(void **iter);
} AVClass;
2.6 const AVProfile *profiles
profile表示了视频编码的复杂度与压缩效率的等级,例如Baseline、Main Profile、High Profile等,不同的profile会使用不同的编码工具
/*** AVProfile.*/
typedef struct AVProfile {// profile levelint profile;// profile nameconst char *name; ///< short name for the profile
} AVProfile;
CSDN : https://blog.csdn.net/weixin_42877471
Github : https://github.com/DoFulangChen