音视频开发18 FFmpeg AVCodec 说明,AVCodecContext 说明

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<<"
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值