【ffmpeg数据结构 1】 AVFormatContext

86 阅读8分钟

3.0 数据结构

学习文档

数据结构用途
AVIOContext自定义读取文件
AVFormatContext封装格式上下文,记录打开一个封装音频的所有信息
AVInputFormat解封装格式信息
AVoutputFormat封装格式信息
AVStream标识视频/音频流
AVCodecContext编码器格式上下文
AVCodec编码器信息
AVSampleFormat枚举类型,包含编码器所支持的所有的音频采样格式
AVPacket压缩数据包(AAC/AVC)
AVFrame原始数据包(PCM/YUV)
AVCodecParameters
AVBSFContext比特率过滤器上下文
AVBitStreamFilter比特流过滤器,用于从MP4中分离H264文件
AVRational分数形式,常用 time_base、sample_rate等属性的表示

3.1 AVFormatContext

AVFormatContextAVPacket 是 FFmpeg 中用于处理音视频数据的两个关键结构体。

  1. AVFormatContext:

    • AVFormatContext 主要用于存储整个音视频文件的格式相关信息,包括文件的封装格式、音视频流的详细信息、文件的全局元数据等。其主要字段包括:
      • streams: 一个指针数组,包含了文件中每个音视频流的信息,每个元素是一个 AVStream 结构体。
      • nb_streams: 表示流的个数。
      • duration: 表示文件的总时长。
      • metadata: 包含文件的全局元数据,如标题、作者等信息。

    通过 AVFormatContext,你可以访问和操作文件级别的信息,例如确定文件中有多少个音视频流、获取文件的时长等。

  2. AVPacket:

    • AVPacket 用于存储编解码器产生的压缩后的音视频数据(帧)。 通过 AVPacket,你可以访问和操作音视频数据的压缩包,其中包括数据本身以及与播放顺序和时间轴相关的时间戳信息。

总的来说,AVFormatContext 存储了整个文件的格式和元数据信息,而 AVPacket 存储了压缩后的音视频数据以及与时间相关的信息。这两个结构体在 FFmpeg 中一起协同工作,用于解析和处理音视频文件。

3.1.1 内置属性

  • 保存一个完整封装的音频(MP4,FLV),将其压缩的音频流和视频流分开
属性解释
nb_streans流个数
streams遍历循环AVStreams[]数组,得到准确的视频流/音频流的index
duration微秒,除以100w变为秒,duration / AV_TIME_BASE
url媒体路径
bit_rate码率
metadata包含文件的全局元数据,如标题、作者等信息
AVIOContext *pb用于存放通过IO打开文件的上下文信息
AVInputFormat *iformatdemuxing only
AVOutputFormat *oformatmuxing only,包含封装时所需要的信息
typedef struct AVFormatContext {
    const AVClass *av_class;  // 类型信息
    struct AVInputFormat *iformat;  // 输入格式
    struct AVOutputFormat *oformat;  // 输出格式
    void *priv_data;  // 私有数据
    AVIOContext *pb;  // I/O 上下文
    int ctx_flags;  // 上下文标志
    unsigned int nb_streams;  // 流的数量
    AVStream **streams;  // 流数组
    char filename[1024];  // 文件名或流的 URL
    int64_t start_time;  // 媒体流的起始时间
    int64_t duration;  // 媒体流的总时长
    int bit_rate;  // 比特率
    unsigned int packet_size;  // 数据包的大小
    int max_delay;  // 最大延迟
    int flags;  // 标志
    int probesize;  // 探测大小
    int max_analyze_duration;  // 最大分析时长
    const uint8_t *key;  // 解密密钥
    int keylen;  // 解密密钥长度
    unsigned int nb_programs;  // 节目数量
    AVProgram **programs;  // 节目数组
    int video_codec_id;  // 视频编解码器 ID
    int audio_codec_id;  // 音频编解码器 ID
    int subtitle_codec_id;  // 字幕编解码器 ID
    int max_index_size;  // 最大索引大小
    int max_picture_buffer;  // 最大图片缓冲
    int nb_chapters;  // 章节数量
    AVChapter **chapters;  // 章节数组
    AVDictionary *metadata;  // 元数据
    int64_t start_time_realtime;  // 实际起始时间
    int fps_probe_size;  // 探测帧率的大小
    int error_recognition;  // 错误识别
    AVIOInterruptCB interrupt_callback;  // 中断回调
    int debug;  // 调试信息
    int64_t max_interleave_delta;  // 最大交叉差值
    int strict_std_compliance;  // 严格标准兼容性
    int event_flags;  // 事件标志
    int max_ts_probe;  // 最大时间戳探测
    int avoid_negative_ts;  // 避免负时间戳
    int ts_id;  // 时间戳 ID
    int audio_preload;  // 音频预加载
    int max_chunk_duration;  // 最大块时长
    int max_chunk_size;  // 最大块大小
    int use_wallclock_as_timestamps;  // 使用壁钟作为时间戳
    int avio_flags;  // I/O 标志
    int duration_estimation_method;  // 时长估算方法
    int skip_initial_bytes;  // 跳过初始字节
    int correct_ts_overflow;  // 修正时间戳溢出
    int seek2any;  // 允许在任何地方定位
    int flush_packets;  // 刷新数据包
    int probe_score;  // 探测分数
    int format_probesize;  // 格式探测大小
    AVCodecParameters *audio_codecpar;  // 音频编解码器参数
    AVCodecParameters *video_codecpar;  // 视频编解码器参数
    AVCodecParameters *subtitle_codecpar;  // 字幕编解码器参数
    AVFormatInternal *internal;  // 内部数据结构
    int io_repositioned;  // I/O 重定位
    AVCodec *video_codec;  // 视频编解码器
    AVCodec *audio_codec;  // 音频编解码器
    AVCodec *subtitle_codec;  // 字幕编解码器
    AVCodec *data_codec;  // 数据编解码器
    AVOpenCallback open_cb;  // 打开回调
    AVReadHeaderCallback read_header;  // 读取头部回调
    AVReadPacketCallback read_packet;  // 读取数据包回调
    AVReadCloseCallback read_close;  // 读取关闭回调
    AVReadPauseCallback read_pause;  // 读取暂停回调
    AVReadPlayCallback read_play;  // 读取播放回调
    AVSeekCallback seek2;  // 定位回调
    AVWriteHeaderCallback write_header;  // 写入头部回调
    AVWritePacketCallback write_packet;  // 写入数据包回调
    AVWriteTrailerCallback write_trailer;  // 写入尾部回调
    int64_t pb_pos;  // I/O 位置
    int64_t pb_duration;  // I/O 时长
    AVPacketList *packet_buffer;  // 数据包缓冲
    AVPacketList *packet_buffer_end;  // 数据包缓冲尾部
    int64_t data_offset;  // 数据偏移
    int raw_packet_buffer_size;  // 原始数据包缓冲大小
    AVPacketList *raw_packet_buffer;  // 原始数据包缓冲
    AVPacketList *raw_packet_buffer_end;  // 原始数据包缓冲尾部
    AVPacketList *parse_queue;  // 解析队列
    AVPacketList *parse_queue_end;  // 解析队列尾部
    int raw_packet_buffer_remaining_size;  // 原始数据包缓冲剩余大小
    AVIndexEntry *index_entries;  // 索引条目
    int nb_index_entries;  // 索引条目数量
    unsigned int index_entries_allocated_size;  // 分配的索引条目大小
    int init_range;  // 初始化范围
    int update_initial_durations_done;  // 更新初始时长标志
    int fps_probe_failed;  // 帧率探测失败标志
    int64_t fps_probe_size;  // 帧率探测大小
    int64_t fps_probe_count;  // 帧率探测数量
    int64_t last_duration;  // 上一个时长
    int64_t last_dts;  // 上一个 DTS
    int probe_packets;  // 探测数据包
    int codec_whitelist_depth;  // 编解码器白名单深度
    AVPacket *flush_packets;  // 刷新数据包
    AVPacket *flush_packets_end;  // 刷新数据包尾部
    int64_t first_dts;  // 第一个 DTS
    int probesize2;  // 第二探测大小
    int max_analyze_duration2;  // 第二最大分析时长
    const char *protocol_whitelist;  // 协议白名单
    int io_flags;  // I/O 标志
    int event_flags;  // 事件标志
    int max_ts_probe2;  // 第二最大时间戳探测
    int max_size;  // 最大大小
    int use_wallclock_as_timestamps;  // 使用壁钟作为时间戳
    int avio_flags;  // I/O 标志
    int duration_estimation_method;  // 时长估算方法
    int skip_initial_bytes;  // 跳过初始字节
    int correct_ts_overflow;  // 修正时间戳溢出
    int seek2any;  // 允许在任何地方定位
    int flush_packets;  // 刷新数据包
    int probe_score;  // 探测分数
    int format_probesize;  // 格式探测大小
    AVCodecParameters *audio_codecpar;  // 音频编解码器参数
    AVCodecParameters *video_codecpar;  // 视频编解码器参数
    AVCodecParameters *subtitle_codecpar;  // 字幕编解码器参数
    AVFormatInternal *internal;  // 内部数据结构
    int io_repositioned;  // I/O 重定位
    AVCodec *video_codec;  // 视频编解码器
    AVCodec *audio_codec;  // 音频编解码器
    AVCodec *subtitle_codec;  // 字幕编解码器
    AVCodec *data_codec;  // 数据编解码器
    AVOpenCallback open_cb;  // 打开回调
    AVReadHeaderCallback read_header;  // 读取头部回调
    AVReadPacketCallback read_packet;  // 读取数据包回调
    AVReadCloseCallback read_close;  // 读取关闭回调
    AVReadPauseCallback read_pause;  // 读取暂停回调
    AVReadPlayCallback read_play;  // 读取播放回调
    AVSeekCallback seek2;  // 定位回调
    AVWriteHeaderCallback write_header;  // 写入头部回调
    AVWritePacketCallback write_packet;  // 写入数据包回调
    AVWriteTrailerCallback write_trailer;  // 写入尾部回调
    int64_t pb_pos;  // I/O 位置
    int64_t pb_duration;  // I/O 时长
    AVPacketList *packet_buffer;  // 数据包缓冲
    AVPacketList *packet_buffer_end;  // 数据包缓冲尾部
    int64_t data_offset;  // 数据偏移
    int raw_packet_buffer_size;  // 原始数据包缓冲大小
    AVPacketList *raw_packet_buffer;  // 原始数据包缓冲
    AVPacketList *raw_packet_buffer_end;  // 原始数据包缓冲尾部
    AVPacketList *parse_queue;  // 解析队列
    AVPacketList *parse_queue_end;  // 解析队列尾部
    int raw_packet_buffer_remaining_size;  // 原始数据包缓冲剩余大小
    AVIndexEntry *index_entries;  // 索引条目
    int nb_index_entries;  // 索引条目数量
    unsigned int index_entries_allocated_size;  // 分配的索引条目大小
    int init_range;  // 初始化范围
    int update_initial_durations_done;  // 更新初始时长标志
    int fps_probe_failed;  // 帧率探测失败标志
    int64_t fps_probe_size;  // 帧率探测大小
    int64_t fps_probe_count;  // 帧率探测数量
    int64_t last_duration;  // 上一个时长
    int64_t last_dts;  // 上一个 DTS
    int probe_packets;  // 探测数据包
    int codec_whitelist_depth;  // 编解码器白名单深度
    AVPacket *flush_packets;  // 刷新数据包
    AVPacket *flush_packets_end;  // 刷新数据包尾部
    int64_t first_dts;  // 第一个 DTS
    int probesize2;  // 第二探测大小
    int max_analyze_duration2;  // 第二最大分析时长
    const char *protocol_whitelist;  // 协议白名单
    int io_flags;  // I/O 标志
    int event_flags;  // 事件标志
    int max_ts_probe2;  // 第二最大时间戳探测
    int max_size;  // 最大大小
} AVFormatContext;

3.1.2 接口函数

// 打开本地/网络视频文件
int avformat_open_input(AVFormatContext **ps, 
                        const char *url, 
                        ff_const59 AVInputFormat *fmt, 
                        AVDictionary **options);
// ps:格式上下文呢
// url:本地/网络 视频路径
// fmt:NULL
// options:NULL
int ret = avformat_open_input(&ifmt_ctx, in_filename, NULL, NULL);
// 读取音/视频流信息到packet
// 通过packet的stream_id 判断是音/视频
int av_read_frame(AVFormatContext *s, AVPacket *pkt);

AVPacket *pkt = av_packet_alloc();
ret = av_read_frame(ifmt_ctx, pkt);
// 查找音视频流的id
audio_index = av_find_best_stream(ifmt_ctx, AVMEDIA_TYPE_AUDIO, -1, -1, NULL, 0);

// 或者遍历streams[]查询