注:写了一系列的结构体的分析的文章,在这里列一个列表:
FFMPEG结构体分析:AVFrame
FFMPEG结构体分析:AVFormatContext
FFMPEG结构体分析:AVCodecContext
FFMPEG结构体分析:AVIOContext
FFMPEG结构体分析:AVCodec
FFMPEG结构体分析:AVStream
FFMPEG结构体分析:AVPacket
FFMPEG有几个最重要的结构体,包含了解协议,解封装,解码操作,此前已经进行过分析:
FFMPEG中最关键的结构体之间的关系
在此不再详述,其中AVCodec是存储编解码器信息的结构体。本文将会详细分析一下该结构体里每个变量的含义和作用。
首先看一下结构体的定义(位于avcodec.h文件中):
-
-
-
-
-
-
-
-
-
typedef struct AVCodec {
-
-
-
-
-
-
-
const char *name;
-
-
-
-
-
const char *long_name;
-
enum AVMediaType type;
-
enum CodecID id;
-
-
-
-
-
int capabilities;
-
const AVRational *supported_framerates;
-
const enum PixelFormat *pix_fmts;
-
const int *supported_samplerates;
-
const enum AVSampleFormat *sample_fmts;
-
const uint64_t *channel_layouts;
-
uint8_t max_lowres;
-
const AVClass *priv_class;
-
const AVProfile *profiles;
-
-
-
-
-
-
-
-
-
int priv_data_size;
-
struct AVCodec *next;
-
-
-
-
-
-
-
-
-
-
int (*init_thread_copy)(AVCodecContext *);
-
-
-
-
-
-
-
-
int (*update_thread_context)(AVCodecContext *dst, const AVCodecContext *src);
-
-
-
-
-
-
const AVCodecDefault *defaults;
-
-
-
-
-
void (*init_static_data)(struct AVCodec *codec);
-
-
int (*init)(AVCodecContext *);
-
int (*encode)(AVCodecContext *, uint8_t *buf, int buf_size, void *data);
-
-
-
-
-
-
-
-
-
-
-
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 *);
-
-
-
-
-
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定义如下:
-
enum AVMediaType {
-
AVMEDIA_TYPE_UNKNOWN = -1,
-
AVMEDIA_TYPE_VIDEO,
-
AVMEDIA_TYPE_AUDIO,
-
AVMEDIA_TYPE_DATA,
-
AVMEDIA_TYPE_SUBTITLE,
-
AVMEDIA_TYPE_ATTACHMENT,
-
AVMEDIA_TYPE_NB
-
};
2.enum AVCodecID id
AVCodecID定义如下:
-
enum AVCodecID {
-
AV_CODEC_ID_NONE,
-
-
-
AV_CODEC_ID_MPEG1VIDEO,
-
AV_CODEC_ID_MPEG2VIDEO,
-
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,
-
AV_PIX_FMT_YUYV422,
-
AV_PIX_FMT_RGB24,
-
AV_PIX_FMT_BGR24,
-
AV_PIX_FMT_YUV422P,
-
AV_PIX_FMT_YUV444P,
-
AV_PIX_FMT_YUV410P,
-
AV_PIX_FMT_YUV411P,
-
AV_PIX_FMT_GRAY8,
-
AV_PIX_FMT_MONOWHITE,
-
AV_PIX_FMT_MONOBLACK,
-
AV_PIX_FMT_PAL8,
-
AV_PIX_FMT_YUVJ420P,
-
AV_PIX_FMT_YUVJ422P,
-
AV_PIX_FMT_YUVJ444P,
-
AV_PIX_FMT_XVMC_MPEG2_MC,
-
AV_PIX_FMT_XVMC_MPEG2_IDCT,
-
...(代码太长,略)
-
}
4.const enum AVSampleFormat *sample_fmts
-
enum AVSampleFormat {
-
AV_SAMPLE_FMT_NONE = -1,
-
AV_SAMPLE_FMT_U8,
-
AV_SAMPLE_FMT_S16,
-
AV_SAMPLE_FMT_S32,
-
AV_SAMPLE_FMT_FLT,
-
AV_SAMPLE_FMT_DBL,
-
-
AV_SAMPLE_FMT_U8P,
-
AV_SAMPLE_FMT_S16P,
-
AV_SAMPLE_FMT_S32P,
-
AV_SAMPLE_FMT_FLTP,
-
AV_SAMPLE_FMT_DBLP,
-
-
AV_SAMPLE_FMT_NB
-
};
每一个编解码器对应一个该结构体,查看一下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_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。