FFmpeg结构体分析:AVFormatContext连接FFmpeg的桥梁

2024-06-15 10:38

本文主要是介绍FFmpeg结构体分析:AVFormatContext连接FFmpeg的桥梁,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

AVFormatContext对开发者开放,是连接开发者与FFmpeg内部的桥梁。结构体内部包含有AVInputFormat、AVOutputFormat、AVCodec、AVStream、AVDictionary 、AVClass等。支持设置自定义IO、监听网络中断状态、设置options、直播秒开调优等。

AVFormatContext结构体的源码位于libavformat/avformat.h,具体代码如下:

typedef struct AVFormatContext {// 用于打印日志和设置选项的类const AVClass *av_class;// 输入容器格式ff_const59 struct AVInputFormat *iformat;// 输出容器格式ff_const59 struct AVOutputFormat *oformat;// 私有数据void *priv_data;/*** I/O 上下文** - demuxing: avformat_open_input()之前设置* - muxing: avformat_write_header()之前设置*/AVIOContext *pb;// 关于stream属性的Flagsint ctx_flags;// 码流的数量unsigned int nb_streams;// 码流数组AVStream **streams;// 输入或输出的URLchar *url;// 第一帧的开始时间int64_t start_time;// 码流的时长int64_t duration;// 码流的码率,单位为bit/sint64_t bit_rate;unsigned int packet_size;int max_delay;int flags;
#define AVFMT_FLAG_GENPTS       0x0001 ///< Generate missing pts
#define AVFMT_FLAG_IGNIDX       0x0002 ///< Ignore index.
#define AVFMT_FLAG_NONBLOCK     0x0004 ///< Do not block when reading packets from input.
#define AVFMT_FLAG_IGNDTS       0x0008 ///< Ignore DTS on frames
#define AVFMT_FLAG_NOFILLIN     0x0010 ///< Do not infer any values from other values
#define AVFMT_FLAG_NOPARSE      0x0020 ///< Do not use AVParsers
#define AVFMT_FLAG_NOBUFFER     0x0040 ///< Do not buffer frames when possible
#define AVFMT_FLAG_CUSTOM_IO    0x0080 ///< The caller has supplied a custom AVIOContext
#define AVFMT_FLAG_DISCARD_CORRUPT  0x0100 ///< Discard frames marked corrupted
#define AVFMT_FLAG_FLUSH_PACKETS    0x0200 ///< Flush the AVIOContext every packet.
#define AVFMT_FLAG_BITEXACT         0x0400
#if FF_API_LAVF_MP4A_LATM
#define AVFMT_FLAG_MP4A_LATM    0x8000 ///< Deprecated, does nothing.
#endif
#define AVFMT_FLAG_SORT_DTS    0x10000 ///< try to interleave outputted packets by dts 
#if FF_API_LAVF_PRIV_OPT
#define AVFMT_FLAG_PRIV_OPT    0x20000 ///< Enable use of private options by delaying codec open (deprecated, will do nothing once av_demuxer_open() is removed)
#endif
#if FF_API_LAVF_KEEPSIDE_FLAG
#define AVFMT_FLAG_KEEP_SIDE_DATA 0x40000 ///< Deprecated, does nothing.
#endif
#define AVFMT_FLAG_FAST_SEEK   0x80000 ///< Enable fast, but inaccurate seeks for some formats
#define AVFMT_FLAG_SHORTEST   0x100000 ///< Stop muxing when the shortest stream stops.
#define AVFMT_FLAG_AUTO_BSF   0x200000 ///< Add bitstream filters as requested by the muxer// 从输入流探测数据包的大小int64_t probesize;// 最大的分析时长,单位为AV_TIME_BASEint64_t max_analyze_duration;const uint8_t *key;int keylen;unsigned int nb_programs;AVProgram **programs;enum AVCodecID video_codec_id;enum AVCodecID audio_codec_id;enum AVCodecID subtitle_codec_id;unsigned int max_index_size;unsigned int max_picture_buffer;unsigned int nb_chapters;AVChapter **chapters;// 文件元数据媒体信息AVDictionary *metadata;int64_t start_time_realtime;int fps_probe_size;int error_recognition;// 自定义的I/O层中断回调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;
#define AVFMT_AVOID_NEG_TS_AUTO             -1 ///< Enabled when required by target format
#define AVFMT_AVOID_NEG_TS_MAKE_NON_NEGATIVE 1 ///< Shift timestamps so they are non negative
#define AVFMT_AVOID_NEG_TS_MAKE_ZERO         2 ///< Shift timestamps so that they start at 0int ts_id;int audio_preload;int max_chunk_duration;int max_chunk_size;int use_wallclock_as_timestamps;int avio_flags;enum AVDurationEstimationMethod duration_estimation_method;int64_t skip_initial_bytes;unsigned int correct_ts_overflow;// 强制seek到任意帧,包括非关键帧位置int seek2any;int flush_packets;// 格式探测分数int probe_score;int format_probesize;// codec的白名单char *codec_whitelist;// format的白名单char *format_whitelist;AVFormatInternal *internal;int io_repositioned;// 视频codecAVCodec *video_codec;// 音频codecAVCodec *audio_codec;// 字幕codecAVCodec *subtitle_codec;// 数据codecAVCodec *data_codec;int metadata_header_padding;// 用户数据void *opaque;av_format_control_message control_message_cb;int64_t output_ts_offset;uint8_t *dump_separator;enum AVCodecID data_codec_id;// 协议白名单char *protocol_whitelist;// 打开新IO流的回调int (*io_open)(struct AVFormatContext *s, AVIOContext **pb, const char *url,int flags, AVDictionary **options);// 关闭IO流的回调void (*io_close)(struct AVFormatContext *s, AVIOContext *pb);// 协议黑名单char *protocol_blacklist;int max_streams;int skip_estimate_duration_from_pts;int max_probe_packets;
} AVFormatContext;

打开输入流的流程比较简单,先分配AVFormatContext,然后再打开输入流:

AVFormatContext *format_ctx = avformat_alloc_context();
int ret = avformat_open_input(&format_ctx, url, NULL, NULL);

如果要设置avoptions,使用av_dict_set()来设置参数键值对:

AVDictionary *options = NULL;
av_dict_set(&options, "video_size", "640x480", 0);
av_dict_set(&options, "pixel_format", "rgb24", 0);
AVFormatContext *format_ctx = avformat_alloc_context();
int ret = avformat_open_input(&format_ctx, url, NULL, &options);

如果要监听网络中断状态,使用AVIOInterruptCB进行监听:

static int custom_interrupt_callback(void *arg) {......
}AVFormatContext *format_ctx = avformat_alloc_context();
format_ctx->interrupt_callback.callback = custom_interrupt_callback;
format_ctx->interrupt_callback.opaque= NULL;
int ret = avformat_open_input(&format_ctx, url, NULL, NULL);

其中AVIOInterruptCB的结构体定义如下,包含callback函数指针和opaque:

typedef struct AVIOInterruptCB {int (*callback)(void*);void *opaque;
} AVIOInterruptCB;

在使用FFmpeg拉流直播时,做直播秒开调优,可以调节probesize和max_analyze_duration。其中probesize表示探测数据包的大小,max_analyze_duration表示最大分析时长,比如这样:

probesize            = 5 * 1024 * 1024;
max_analyze_duration = 500;

如果要自定义IO读取缓冲区数据,使用AVIOContext,分配缓冲区,实现read_packet、write_packet、seek方法:

#define IO_BUFFER_SIZE (4 * 1024 * 1024)uint8_t *io_buffer = av_malloc(IO_BUFFER_SIZE);int read_packet(void *opaque, uint8_t *buf, int buf_size) {......
}int64_t seek(void *opaque, int64_t offset, int whence) {......
}AVIOContext *avio_ctx = avio_alloc_context(io_buffer, IO_BUFFER_SIZE, 0, &user_data, &read_packet, NULL, &seek);
AVFormatContext *format_ctx = avformat_alloc_context();
format_ctx .pb = avio_ctx;
format_ctx->flags |= AVFMT_FLAG_CUSTOM_IO;

这篇关于FFmpeg结构体分析:AVFormatContext连接FFmpeg的桥梁的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1063220

相关文章

Vite 打包目录结构自定义配置小结

《Vite打包目录结构自定义配置小结》在Vite工程开发中,默认打包后的dist目录资源常集中在asset目录下,不利于资源管理,本文基于Rollup配置原理,本文就来介绍一下通过Vite配置自定义... 目录一、实现原理二、具体配置步骤1. 基础配置文件2. 配置说明(1)js 资源分离(2)非 JS 资

Mac电脑如何通过 IntelliJ IDEA 远程连接 MySQL

《Mac电脑如何通过IntelliJIDEA远程连接MySQL》本文详解Mac通过IntelliJIDEA远程连接MySQL的步骤,本文通过图文并茂的形式给大家介绍的非常详细,感兴趣的朋友跟... 目录MAC电脑通过 IntelliJ IDEA 远程连接 mysql 的详细教程一、前缀条件确认二、打开 ID

基于Java和FFmpeg实现视频压缩和剪辑功能

《基于Java和FFmpeg实现视频压缩和剪辑功能》在视频处理开发中,压缩和剪辑是常见的需求,本文将介绍如何使用Java结合FFmpeg实现视频压缩和剪辑功能,同时去除数据库操作,仅专注于视频处理,需... 目录引言1. 环境准备1.1 项目依赖1.2 安装 FFmpeg2. 视频压缩功能实现2.1 主要功

Go语言连接MySQL数据库执行基本的增删改查

《Go语言连接MySQL数据库执行基本的增删改查》在后端开发中,MySQL是最常用的关系型数据库之一,本文主要为大家详细介绍了如何使用Go连接MySQL数据库并执行基本的增删改查吧... 目录Go语言连接mysql数据库准备工作安装 MySQL 驱动代码实现运行结果注意事项Go语言执行基本的增删改查准备工作

Java集合中的链表与结构详解

《Java集合中的链表与结构详解》链表是一种物理存储结构上非连续的存储结构,数据元素的逻辑顺序的通过链表中的引用链接次序实现,文章对比ArrayList与LinkedList的结构差异,详细讲解了链表... 目录一、链表概念与结构二、当向单链表的实现2.1 准备工作2.2 初始化链表2.3 打印数据、链表长

python连接sqlite3简单用法完整例子

《python连接sqlite3简单用法完整例子》SQLite3是一个内置的Python模块,可以通过Python的标准库轻松地使用,无需进行额外安装和配置,:本文主要介绍python连接sqli... 目录1. 连接到数据库2. 创建游标对象3. 创建表4. 插入数据5. 查询数据6. 更新数据7. 删除

Android 缓存日志Logcat导出与分析最佳实践

《Android缓存日志Logcat导出与分析最佳实践》本文全面介绍AndroidLogcat缓存日志的导出与分析方法,涵盖按进程、缓冲区类型及日志级别过滤,自动化工具使用,常见问题解决方案和最佳实... 目录android 缓存日志(Logcat)导出与分析全攻略为什么要导出缓存日志?按需过滤导出1. 按

创建springBoot模块没有目录结构的解决方案

《创建springBoot模块没有目录结构的解决方案》2023版IntelliJIDEA创建模块时可能出现目录结构识别错误,导致文件显示异常,解决方法为选择模块后点击确认,重新校准项目结构设置,确保源... 目录创建spChina编程ringBoot模块没有目录结构解决方案总结创建springBoot模块没有目录

在 Spring Boot 中连接 MySQL 数据库的详细步骤

《在SpringBoot中连接MySQL数据库的详细步骤》本文介绍了SpringBoot连接MySQL数据库的流程,添加依赖、配置连接信息、创建实体类与仓库接口,通过自动配置实现数据库操作,... 目录一、添加依赖二、配置数据库连接三、创建实体类四、创建仓库接口五、创建服务类六、创建控制器七、运行应用程序八

SpringBoot利用树形结构优化查询速度

《SpringBoot利用树形结构优化查询速度》这篇文章主要为大家详细介绍了SpringBoot利用树形结构优化查询速度,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录一个真实的性能灾难传统方案为什么这么慢N+1查询灾难性能测试数据对比核心解决方案:一次查询 + O(n)算法解决