AVCodec
AVCodec:是音视频编解码器结构体,用于定义特定的编解码器。
它包含了编解码器的类型、名称、支持的音视频格式、编解码函数等。
通过AVCodec结构体,可以查询和获取系统中可用的编解码器,并与AVCodecContext关联以进行音视频编解码操作。
对于音频,一定要知道 采样率,采样格式,声道数
采样率: Sampling Rate 44100. 每秒中采集多少个音频点。 在ffmpeg 中 对应类型为 AVRational *supported_framerates
采样格式:16 bit, 32 bit, 在ffmpeg 中 对应类型为 AVSampleFormat
声道数: 1为单声道,2 为立体声 在ffmpeg 中 对应类型为 AVChannelLayout
对于视频,一定要知道视频的像素,视频的格式-也就是RGB/yuv, fps
像素,1600*780 暂时没有对应的值
RGB/YUV类型,AVPixelFormat AV_PIX_FMT_YUV420P
fps(每秒播放多少个图片) AVRational *supported_framerates
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:私有数据的大小
————————————————
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
原文链接:https://blog.csdn.net/leixiaohua1020/article/details/14215833
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.
*编解码器的描述性名称,意味着比名称更易于阅读。
*您应该使用NULL_IF_CONFIG_SMALL()宏来定义它。
*/
const char *long_name;
//该编解码器的 类型,enum AVMediaType type; 类似 AVMEDIA_TYPE_VIDEO,AVMEDIA_TYPE_AUDIO
enum AVMediaType type;
//类似 AV_CODEC_ID_AAC,AV_CODEC_ID_H264 , AAC 对应的值是十进制是86018,十六进制是15002
enum AVCodecID id;
/**
* Codec capabilities.
* see AV_CODEC_CAP_*
* int capabilities;
* AAC 作为 encoder 的值是98,对应的二进制是 0110 0010,对应的如下的三个值 或 起来
* #define AV_CODEC_CAP_DR1 (1 << 1)
#define AV_CODEC_CAP_DELAY (1 << 5)
#define AV_CODEC_CAP_SMALL_LAST_FRAME (1 << 6)
*/
int capabilities;
///< maximum value for lowres supported by the decoder
/// 视频专用 解码器支持的低分辨率的最大值
uint8_t max_lowres; ///< maximum value for lowres supported by the decoder
// 支持的帧率(仅视频)
const AVRational *supported_framerates; ///< array of supported framerates, or NULL if any, array is terminated by {0,0}
/// 支持的像素格式(仅视频)
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
#if FF_API_OLD_CHANNEL_LAYOUT
/**
* @deprecated use ch_layouts instead
*/
attribute_deprecated
const uint64_t *channel_layouts; ///< array of support channel layouts, or NULL if unknown. array is terminated by 0
#endif
const AVClass *priv_class; ///< AVClass for the private context
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>").
*/
const char *wrapper_name;
/**
* Array of supported channel layouts, terminated with a zeroed layout.
*/
const AVChannelLayout *ch_layouts;
} AVCodec;
视频和音频对应的参数
音频
对于音频,一定要知道 采样率,采样格式,声道数
采样率: Sampling Rate 44100. 每秒中采集多少个音频点。 在ffmpeg 中 对应类型为 AVRational *supported_framerates
采样格式:16 bit, 32 bit, 在ffmpeg 中 对应类型为 AVSampleFormat
声道数: 1为单声道,2 为立体声 在ffmpeg 中 对应类型为 AVChannelLayout
const enum AVSampleFormat *sample_fmts; ///< array of supported sample formats, or NULL if unknown, array is terminated by -1
音频格式,支持的样本格式的数组,如果未知则为NULL,数组以-1终止 AVSampleFormat AV_SAMPLE_FMT_S16,音频格式
const AVChannelLayout *ch_layouts; //Array of supported channel layouts, terminated with a zeroed layout.
音频的声道数
const int *supported_samplerates; ///< array of supported audio samplerates, or NULL if unknown, array is terminated by 0
支持的音频采样率数组,如果未知则为NULL,数组由0终止 int * 所支持的音频采样率 数组 如果有值,应该是44100,48000等
视频
对于视频,一定要知道视频的像素,视频的格式-也就是RGB/yuv, fps
像素,1600*780 暂时没有对应的值,这也很好理解,AVCodec 是编解码器的参数,编解码厂商支持的视频应该是多大的都应该支持
RGB/YUV类型,AVPixelFormat AV_PIX_FMT_YUV420P 对应 pix_fmts
fps(每秒播放多少个图片) AVRational *supported_framerates
// 支持的帧率(仅视频)
const AVRational *supported_framerates; ///< array of supported framerates, or NULL if any, array is terminated by {0,0}
/// 支持的像素格式(仅视频)
const enum AVPixelFormat *pix_fmts; ///< array of supported pixel formats, or NULL if unknown, array is terminated by -1
详细介绍几个变量:
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,
};
下面简单介绍一下遍历ffmpeg中的解码器信息的方法(这些解码器以一个链表的形式存储):
1.注册所有编解码器:av_register_all();
2.声明一个AVCodec类型的指针,比如说AVCodec* first_c;
3.调用av_codec_next()函数,即可获得指向链表下一个解码器的指针,循环往复可以获得所有解码器的信息。注意,如果想要获得指向第一个解码器的指针,则需要将该函数的参数设置为NULL。
————————————————
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
原文链接:https://blog.csdn.net/leixiaohua1020/article/details/14215833
AVCodec 中的 AVClass 中debug 数据:
const AVClass *priv_class = avcodec->priv_class;
AVClass 中的 AVOption 中的关键数据
下面简单解释一下AVOption的几个成员变量:
name:名称。
help:简短的帮助。
offset:选项相对结构体首部地址的偏移量(这个很重要)。
type:选项的类型。
default_val:选项的默认值。
min:选项的最小值。
max:选项的最大值。
flags:一些标记。
unit:该选项所属的逻辑单元,可以为空。
其中,default_val是一个union类型的变量,可以根据选项数据类型的不同,取int,double,char*,AVRational(表示分数)几种类型。type是一个AVOptionType类型的变量。AVOptionType是一个枚举类型.
AVClass中存储了AVOption类型的数组option,用于存储选项信息。AVClass有一个特点就是它必须位于其支持的结构体的第一个位置。例如,AVFormatContext和AVCodecContext都支持AVClass,观察它们结构体的定义可以发现他们结构体的第一个变量都是AVClass。截取一小段AVFormatContext的定义的开头部分,如下所示。
参考如下的
FFmpeg源代码简单分析:结构体成员管理系统-AVClass_ffmepg avclass-CSDN博客
自己打印的 AVCodec的各种数据:
void printfAVCodec(const AVCodec *avcodec){
if(avcodec==nullptr){
cout<<"printfAVCodec error avcodec==nullptr"<<endl;
return ;
}
cout << "avcodec->name = " << avcodec->name << endl;
cout << "avcodec->long_name = " << avcodec->long_name << endl;
//该编解码器的 类型,enum AVMediaType type; 类似 AVMEDIA_TYPE_VIDEO,AVMEDIA_TYPE_AUDIO
cout << "avcodec->type = " << avcodec->type << endl;
//enum AVCodecID id; 类似 AV_CODEC_ID_AAC,AV_CODEC_ID_H264 , AAC 对应的值是十进制是86018,十六进制是15002
cout << "avcodec->id = " << avcodec->id << endl;
/**
* Codec capabilities.
* see AV_CODEC_CAP_*
* int capabilities;
* AAC 作为 encoder 的值是98,对应的二进制是 0110 0010,对应的如下的三个值 或 起来
* #define AV_CODEC_CAP_DR1 (1 << 1)
#define AV_CODEC_CAP_DELAY (1 << 5)
#define AV_CODEC_CAP_SMALL_LAST_FRAME (1 << 6)
*/
cout << "avcodec->capabilities = " << avcodec->capabilities << endl;
///< maximum value for lowres supported by the decoder
/// 视频专用 解码器支持的低分辨率的最大值
// uint8_t max_lowres;
cout << "avcodec->max_lowres = " << avcodec->max_lowres << endl;
///< array of supported framerates, or NULL if any, array is terminated by {0,0}
///const AVRational *supported_framerates;
///支持的帧率(仅视频), 类似 每秒25张图片
if(avcodec->supported_framerates == nullptr){
cout<<"avcodec->supported_framerates = nullptr"<<endl;
} else {
cout<<"avcodec->supported_framerates != nullptr"<<endl;
const AVRational * avr = avcodec->supported_framerates;
int i =0;
while(1){
if(avr[i].den ==0 && avr[i].num == 0){
break;
}
cout<<"avr["<<i <<"].den = "<< avr[i].den << " avr[" << i << "].num = " << avr[i].num << endl;
++i;
}
}
///< array of supported pixel formats, or NULL if unknown, array is terminated by -1
///const enum AVPixelFormat *pix_fmts;
/// 支持的像素格式(仅视频),类似 AV_PIX_FMT_YUV420P
if(avcodec->pix_fmts == nullptr){
cout<<"avcodec->pix_fmts = nullptr"<<endl;
}else{
cout<<"avcodec->pix_fmts != nullptr"<<endl;
const enum AVPixelFormat * avpixelformat = avcodec->pix_fmts;
int i =0;
while(1){
if(avpixelformat[i] == -1){
break;
}else{
cout<<"avpixelformat["<<i<<"] = avpixelformat[i] " <<endl;
++i;
}
}
}
///< array of supported audio samplerates, or NULL if unknown, array is terminated by 0
/// const int *supported_samplerates;
/// 支持的采样率(仅音频)41000,48000
if(avcodec->supported_samplerates == nullptr){
cout<<"avcodec->supported_samplerates = nullptr"<<endl;
}else{
cout<<"avcodec->supported_samplerates != nullptr"<<endl;
const int * support_samplerates = avcodec->supported_samplerates;
int i =0;
while(1){
if(support_samplerates[i] == 0){
break;
}else{
cout<<"support_samplerates["<<i<<"] = " << support_samplerates[i]<<endl;
++i;
}
}
}
///支持的采样格式(仅音频),类似 AV_SAMPLE_FMT_S16,FFMpeg 自带的AAC 只支持 AV_SAMPLE_FMT_FLTP,对应的十进制的值是8
///< array of supported sample formats, or NULL if unknown, array is terminated by -1
/// const enum AVSampleFormat *sample_fmts;
if(avcodec->sample_fmts == nullptr){
cout<<"avcodec->sample_fmts = nullptr"<<endl;
}else{
cout<<"avcodec->sample_fmts != nullptr"<<endl;
const enum AVSampleFormat *sample_fmts = avcodec->sample_fmts;
int i =0;
while(1){
if(sample_fmts[i] == -1){
break;
}else{
cout<<"sample_fmts["<<i<<"] = " << sample_fmts[i]<<endl;
++i;
}
}
}
//#if FF_API_OLD_CHANNEL_LAYOUT
// /**
// * @deprecated use ch_layouts instead
// */
// attribute_deprecated
// const uint64_t *channel_layouts; ///< array of support channel layouts, or NULL if unknown. array is terminated by 0
//#endif
//该编码器支持的声道数量。已经不再使用。可以使用 const AVChannelLayout *ch_layouts; 替代
const uint64_t *channel_layouts = avcodec->channel_layouts;
if(channel_layouts == nullptr){
cout<<"channel_layouts = nullptr"<<endl; //在ffmepg 6.0的时候,使用编码器ffmpeg自带的AAC,这块为nullptr。这不合理。这里baidu了一下,发现 如下的说法: // 不是每个codec都给出支持的channel_layout
}else{
cout<<"channel_layouts != nullptr"<<endl;
int i = 0;
while(1){
if(channel_layouts[i] == 0){
break;
}
cout<<"channel_layouts[<<" << i << "] = " << channel_layouts[i] << endl;
++i;
}
}
///这里为了方便测试 ,将已经废弃的const uint64_t *channel_layouts; 和 const AVChannelLayout *ch_layouts;对比
/**
* Array of supported channel layouts, terminated with a zeroed layout.
*/
///const AVChannelLayout *ch_layouts;
const AVChannelLayout *ch_layouts = avcodec->ch_layouts;
if(ch_layouts == nullptr){
cout<<"ch_layouts = nullptr"<<endl; //在ffmepg 6.0的时候,使用编码器ffmpeg自带的AAC,这块为nullptr。这不合理。 baidu说明如下: // 不是每个codec都给出支持的channel_layout
}else{
cout<<"ch_layouts != nullptr"<<endl;
int i = 0;
while(1){
if(ch_layouts[i].nb_channels == 0 ){
break;
}
cout<<"