注:寫了一系列的結構體的分析的文章,在這裏列一個列表:
FFMPEG結構體分析:AVFrame
FFMPEG結構體分析:AVFormatContext
FFMPEG結構體分析:AVCodecContext
FFMPEG結構體分析:AVIOContext
FFMPEG結構體分析:AVCodec
FFMPEG結構體分析:AVStream
FFMPEG結構體分析:AVPacket
FFMPEG有幾個最重要的結構體,包含了解協議,解封裝,解碼操作,此前已經進行過分析:
在此不再詳述,其中AVCodec是存儲編解碼器信息的結構體。本文將會詳細分析一下該結構體裏每個變量的含義和作用。
首先看一下結構體的定義(位於avcodec.h文件中):
- /* 雷霄驊
- * 中國傳媒大學/數字電視技術
- * [email protected]
- *
- */
- /**
- * 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;
下面說一下最主要的幾個變量:
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。
原文地址:http://blog.csdn.net/leixiaohua1020/article/details/14215833