ffmpeg-结构体介绍

作者: 石丘 | 来源:发表于2015-06-19 20:13 被阅读1126次

    本篇博客在雷神的结构体介绍基础上按自己的喜好整理的 后面根据自己工作中所需有所增改

    AVStream


    存储每一个视频/音频流信息的结构体 AVStream重要的变量如下

    int index:标识该视频/音频流
    AVCodecContext *codec:指向该视频/音频流的AVCodecContext(它们是一一对应的关系)
    AVRational time_base:时基。通过该值可以把PTS,DTS转化为真正的时间。FFMPEG其他结构体中也有这个字段,但是根据我的经验,只有AVStream中的time_base是可用的。PTS*time_base=真正的时间
    AVDictionary *metadata:元数据信息
    AVRational avg_frame_rate:帧率(注:对视频来说,这个挺重要的)
    AVPacket attached_pic:附带的图片。比如说一些MP3,AAC音频文件附带的专辑封面。
    int64_t duration:该视频/音频流长度

    AVIOContext


    FFMPEG管理输入输出数据的结构体 里面中有以下几个变量比较重要:

    unsigned char *buffer:缓存开始位置
    int buffer_size:缓存大小(默认32768)
    unsigned char *buf_ptr:当前指针读取到的位置
    unsigned char *buf_end:缓存结束的位置
    void *opaque:URLContext结构体

    在解码的情况下,buffer用于存储ffmpeg读入的数据。例如打开一个视频文件的时候,先把数据从硬盘读入buffer,然后在送给解码器用于解码。

    其中opaque指向了URLContext。注意,这个结构体并不在FFMPEG提供的头文件中,而是在FFMPEG的源代码中。URLContext结构体中还有一个结构体URLProtocol。在这个结构体中,除了一些回调函数接口之外,有一个变量const char *name,该变量存储了协议的名称。每一种输入协议都对应这样一个结构体。

    AVCodecContext


    挑一些关键的变量来看看(这里只考虑解码)。

    enum AVMediaType codec_type:编解码器的类型(视频,音频...)
    struct AVCodec *codec:采用的解码器AVCodec(H.264,MPEG2...)
    int bit_rate:平均比特率
    uint8_t *extradata; int extradata_size:针对特定编码器包含的附加信息(例如对于H.264解码器来说,存储SPS,PPS等)
    AVRational time_base:根据该参数,可以把PTS转化为实际的时间(单位为秒s)
    int width, height:如果是视频的话,代表宽和高
    int refs:运动估计参考帧的个数(H.264的话会有多帧,MPEG2这类的一般就没有了)
    int sample_rate:采样率(音频)
    int channels:声道数(音频)
    enum AVSampleFormat sample_fmt:采样格式
    int profile:型(H.264里面就有,其他编码标准应该也有)
    int level:级(和profile差不太多)

    在这里需要注意:AVCodecContext中很多的参数是编码的时候使用的,而不是解码的时候使用的。

    AVFormatContext:


    在使用FFMPEG进行开发的时候,AVFormatContext是一个贯穿始终的数据结构,很多函数都要用到它作为参数。它是FFMPEG解封装(flv,mp4,rmvb,avi)功能的结构体。下面看几个主要变量的作用(在这里考虑解码的情况):

    struct AVInputFormat *iformat:输入数据的封装格式
    AVIOContext *pb:输入数据的缓存
    unsigned int nb_streams:视音频流的个数
    AVStream **streams:视音频流
    char filename[1024]:文件名
    int64_t duration:时长(单位:微秒ms,转换为秒需要除以1000000)
    int bit_rate:比特率(单位bps,转换为kbps需要除以1000)
    AVDictionary *metadata:元数据

    视频的时长可以转换成HH:MM:SS的形式,示例代码如下:
    <code>
    AVFormatContext *pFormatCtx;
    CString timelong;
    //duration是以微秒为单位
    //转换成hh:mm:ss形式
    int tns, thh, tmm, tss;
    tns = (pFormatCtx->duration)/1000000;
    thh = tns / 3600;
    tmm = (tns % 3600) / 60;
    tss = (tns % 60);
    timelong.Format("%02d:%02d:%02d",thh,tmm,tss);
    </code>

    AVFrame


    AVFrame结构体一般用于存储原始数据(即非压缩数据,例如对视频来说是YUV,RGB,对音频来说是PCM),此外还包含了一些相关的信息。比如说,解码的时候存储了宏块类型表,QP表,运动矢量表等数据。编码的时候也存储了相关的数据。因此在使用FFMPEG进行码流分析的时候,AVFrame是一个很重要的结构体。
    下面看几个主要变量的作用(在这里考虑解码的情况)

    uint8_t *data[AV_NUM_DATA_POINTERS]:解码后原始数据(对视频来说是YUV,RGB,对音频来说是PCM)
    int linesize[AV_NUM_DATA_POINTERS]:data中“一行”数据的大小。注意:未必等于图像的宽,一般大于图像的宽。
    int width, height:视频帧宽和高(1920x1080,1280x720...)
    int nb_samples:音频的一个AVFrame中可能包含多个音频帧,在此标记包含了几个
    int format:解码后原始数据类型(YUV420,YUV422,RGB24...)
    int key_frame:是否是关键帧
    enum AVPictureType pict_type:帧类型(I,B,P...)
    AVRational sample_aspect_ratio:宽高比(16:9,4:3...)
    int64_t pts:显示时间戳
    int coded_picture_number:编码帧序号
    int display_picture_number:显示帧序号
    int8_t *qscale_table:QP表
    uint8_t *mbskip_table:跳过宏块表
    int16_t (*motion_val[2])[2]:运动矢量表
    uint32_t *mb_type:宏块类型表
    short\*dct_coeff:DCT系数,这个没有提取过
    int8_t \*ref_index[2]:运动估计参考帧列表(貌似H.264这种比较新的标准才会涉及到多参考帧)
    int interlaced_frame:是否是隔行扫描
    uint8_t motion_subsample_log2:一个宏块中的运动矢量采样个数,取log的

    AVPacket


    存储压缩编码数据相关信息的结构体 在AVPacket结构体中,重要的变量有以下几个

    uint8_t *data:压缩编码的数据 接收数据流就是由这个变量接收。
    例如对于H.264来说。1个AVPacket的data通常对应一个NAL。
    注意:在这里只是对应,而不是一模一样。他们之间有微小的差别:使用FFMPEG类库分离出多媒体文件中的H.264码流
    因此在使用FFMPEG进行视音频处理的时候,常常可以将得到的AVPacket的data数据直接写成文件,从而得到视音频的码流文件。
    int size:data的大小
    int64_t pts:显示时间戳
    int64_t dts:解码时间戳
    int stream_index:标识该AVPacket所属的视频/音频流。

    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:私有数据的大小

    每一个编解码器对应一个该结构体,查看一下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,
    };
    

    AVPixelFormat定义如下


    <code>
    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,
    ...(代码太长,略)
    }
    </code>

    AVDictionary


    #define AV_DICT_MATCH_CASE      1
    #define AV_DICT_IGNORE_SUFFIX   2
    #define AV_DICT_DONT_STRDUP_KEY 4    
    #define AV_DICT_DONT_STRDUP_VAL 8   
    #define AV_DICT_DONT_OVERWRITE 16    
    #define AV_DICT_APPEND         32   
    
    
    typedef struct {
        char *key;
        char *value;
    } AVDictionaryEntry;
    
    
    struct AVDictionary {
        int count;
        AVDictionaryEntry *elems;
    };
    
    从字面上看这是一个键值对, 更宏观一些则为键值对数组, 嗯, 动态数组
    这就能构建我们通常所说的字典?
    这个数据结构有4个操作, 读(查找)/写(创建)/拷贝, 释放
    
    里面有几个操作标志, 记录下
    AV_DICT_MATCH_CASE     查找时是否比较大小, 不比较大小则全部转化为大写来比较
    AV_DICT_IGNORE_SUFFIX  查找时是否忽略后缀, 这里的后缀指字典里key 超过查找key 部分
                           如果设置了改参数则, 查找"abc", 可能会找到"abcde" 这样的key
    AV_DICT_DONT_STRDUP_KEY 设置key时, 是否把key 字符串复制一份
    AV_DICT_DONT_STRDUP_VAL 设置value时, 是否把value 字符串复制一份
    AV_DICT_DONT_OVERWRITE  写入时不要覆盖原来存在的key(存在key 则不设置), 否则把原来的key/value 释放重建
    AV_DICT_APPEND    如果已经存在key/value, 把将新的value 值连到旧的后面 
    
    

    从这里copy的

    相关文章

      网友评论

      • applixy:收藏
      • 张鑫说保:大神,方便给个QQ号吗?我现在在搞ffmpeg这块,想咨询您点问题~~
        张鑫说保:@石丘 我这块也只是基本的编码就行,方便的话留个QQ号吧,或者您加一下我884752972
        石丘:@唯我独鑫 :flushed: 本来就没够深入 又放了半年没做 忘光了 ···

      本文标题:ffmpeg-结构体介绍

      本文链接:https://www.haomeiwen.com/subject/mlmsqttx.html