zoukankan      html  css  js  c++  java
  • FFmpeg 常用结构体

    0、FFmpeg 中最关键的结构体之间的关系

    FFmpeg 中结构体很多。最关键的结构体可以分成以下几类:

    1)解协议(http, rtsp, rtmp, mms)

    AVIOContext,URLProtocol,URLContext 主要存储音视频使用的协议的类型以及状态。URLProtocol 存储输入音视频使用的封装格式。每种协议都对应一个 URLProtocol 结构。(注意:FFmpeg 中文件也被当做一种协议 “file”)

    2)解封装(flv, avi, rmvb, mp4)

    AVFormatContext 主要存储音视频封装格式中包含的信息;AVInputFormat 存储输入音视频使用的封装格式。每种音视频封装格式都对应一个 AVInputFormat 结构。

    3)解码(h264, mpeg2, aac, mp3)

    每个 AVStream 存储一个视频/音频流的相关数据;每个 AVStream 对应一个 AVCodecContext,存储该视频/音频流使用解码方式的相关数据;每个 AVCodecContext 中对应一个 AVCodec,包含该视频/音频对应的解码器。每种解码器都对应一个 AVCodec 结构。

    4)存数据

    视频的话,每个结构一般是存一帧;音频可能有好几帧。解码前数据:AVPacket;解码后数据:AVFrame。


    它们之间的对应关系如下所示:


    一、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的
    

    如果想了解这些变量具体的含义,请看:FFMPEG结构体分析:AVFrame


    二、AVFormatContext

    AVFormatContext 是存储音视频封装格式中包含的信息的结构体。下面看几个主要变量的作用(在这里考虑解码的情况):

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

    三、AVCodecContext

    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 中很多的参数是编码的时候使用的,而不是解码的时候使用的。如果想了解这些变量具体的含义,请看:FFMPEG结构体分析:AVCodecContext


    四、AVIOContext

    AVIOContext 是 FFmpeg 管理输入输出数据的结构体。其重要的变量如下所示:

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

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


    五、AVCodec

    AVCodec 是存储编码器信息的结构体。其重要的变量如下所示:

    const char *name; // 编解码器的名字的简称
    
    const char *long_name; // 编解码器名字的全称
    
    enum AVMediaType type; // 指明了类型,是视频,音频,还是字幕
    
    enum AVCodecID id; // ID,不重复
    
    const AVRational *supported_framerates; // 支持的帧率(仅视频)
    
    const enum AVPixelFormat *pix_fmts; // 支持的像素格式(仅视频),如RGB24、YUV420P等。
    
    const int *supported_samplerates; // 支持的采样率(仅音频)
    
    const enum AVSampleFormat *sample_fmts; // 支持的采样格式(仅音频)
    
    const uint64_t *channel_layouts; // 支持的声道数(仅音频)
    
    int priv_data_size; // 私有数据的大小
    

    如果想了解这些变量具体的含义,请看:FFMPEG结构体分析:AVCodec


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

    六、AVStream

    AVStream 是存储每一个音频/视频流信息的结构体。其重要的变量如下所示:

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

    七、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所属的视频/音频流。
    

    参考:

    雷霄骅大神的几篇关于 ffmpeg 结构体的文章:

    FFMPEG中最关键的结构体之间的关系

    FFMPEG结构体分析:AVFrame

    FFMPEG结构体分析:AVFormatContext

    FFMPEG结构体分析:AVCodecContext

    FFMPEG结构体分析:AVIOContext

    FFMPEG结构体分析:AVCodec

    FFMPEG结构体分析:AVStream

    FFMPEG结构体分析:AVPacket


  • 相关阅读:
    Codechef EDGEST 树套树 树状数组 线段树 LCA 卡常
    BZOJ4319 cerc2008 Suffix reconstruction 字符串 SA
    Codechef STMINCUT S-T Mincut (CodeChef May Challenge 2018) kruskal
    Codeforces 316G3 Good Substrings 字符串 SAM
    Codechef CHSIGN Change the Signs(May Challenge 2018) 动态规划
    BZOJ1396 识别子串 字符串 SAM 线段树
    CodeForces 516C Drazil and Park 线段树
    CodeForces 516B Drazil and Tiles 其他
    CodeForces 516A Drazil and Factorial 动态规划
    SPOJ LCS2
  • 原文地址:https://www.cnblogs.com/linuxAndMcu/p/12041578.html
Copyright © 2011-2022 走看看