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

相关文章

Nginx分布式部署流程分析

《Nginx分布式部署流程分析》文章介绍Nginx在分布式部署中的反向代理和负载均衡作用,用于分发请求、减轻服务器压力及解决session共享问题,涵盖配置方法、策略及Java项目应用,并提及分布式事... 目录分布式部署NginxJava中的代理代理分为正向代理和反向代理正向代理反向代理Nginx应用场景

Redis中Set结构使用过程与原理说明

《Redis中Set结构使用过程与原理说明》本文解析了RedisSet数据结构,涵盖其基本操作(如添加、查找)、集合运算(交并差)、底层实现(intset与hashtable自动切换机制)、典型应用场... 目录开篇:从购物车到Redis Set一、Redis Set的基本操作1.1 编程常用命令1.2 集

Redis中的有序集合zset从使用到原理分析

《Redis中的有序集合zset从使用到原理分析》Redis有序集合(zset)是字符串与分值的有序映射,通过跳跃表和哈希表结合实现高效有序性管理,适用于排行榜、延迟队列等场景,其时间复杂度低,内存占... 目录开篇:排行榜背后的秘密一、zset的基本使用1.1 常用命令1.2 Java客户端示例二、zse

Redis中的AOF原理及分析

《Redis中的AOF原理及分析》Redis的AOF通过记录所有写操作命令实现持久化,支持always/everysec/no三种同步策略,重写机制优化文件体积,与RDB结合可平衡数据安全与恢复效率... 目录开篇:从日记本到AOF一、AOF的基本执行流程1. 命令执行与记录2. AOF重写机制二、AOF的

MyBatis Plus大数据量查询慢原因分析及解决

《MyBatisPlus大数据量查询慢原因分析及解决》大数据量查询慢常因全表扫描、分页不当、索引缺失、内存占用高及ORM开销,优化措施包括分页查询、流式读取、SQL优化、批处理、多数据源、结果集二次... 目录大数据量查询慢的常见原因优化方案高级方案配置调优监控与诊断总结大数据量查询慢的常见原因MyBAT

分析 Java Stream 的 peek使用实践与副作用处理方案

《分析JavaStream的peek使用实践与副作用处理方案》StreamAPI的peek操作是中间操作,用于观察元素但不终止流,其副作用风险包括线程安全、顺序混乱及性能问题,合理使用场景有限... 目录一、peek 操作的本质:有状态的中间操作二、副作用的定义与风险场景1. 并行流下的线程安全问题2. 顺

MyBatis/MyBatis-Plus同事务循环调用存储过程获取主键重复问题分析及解决

《MyBatis/MyBatis-Plus同事务循环调用存储过程获取主键重复问题分析及解决》MyBatis默认开启一级缓存,同一事务中循环调用查询方法时会重复使用缓存数据,导致获取的序列主键值均为1,... 目录问题原因解决办法如果是存储过程总结问题myBATis有如下代码获取序列作为主键IdMappe

Java中最全最基础的IO流概述和简介案例分析

《Java中最全最基础的IO流概述和简介案例分析》JavaIO流用于程序与外部设备的数据交互,分为字节流(InputStream/OutputStream)和字符流(Reader/Writer),处理... 目录IO流简介IO是什么应用场景IO流的分类流的超类类型字节文件流应用简介核心API文件输出流应用文

java.sql.SQLTransientConnectionException连接超时异常原因及解决方案

《java.sql.SQLTransientConnectionException连接超时异常原因及解决方案》:本文主要介绍java.sql.SQLTransientConnectionExcep... 目录一、引言二、异常信息分析三、可能的原因3.1 连接池配置不合理3.2 数据库负载过高3.3 连接泄漏

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

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