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

相关文章

C#连接SQL server数据库命令的基本步骤

《C#连接SQLserver数据库命令的基本步骤》文章讲解了连接SQLServer数据库的步骤,包括引入命名空间、构建连接字符串、使用SqlConnection和SqlCommand执行SQL操作,... 目录建议配合使用:如何下载和安装SQL server数据库-CSDN博客1. 引入必要的命名空间2.

MySQL中的LENGTH()函数用法详解与实例分析

《MySQL中的LENGTH()函数用法详解与实例分析》MySQLLENGTH()函数用于计算字符串的字节长度,区别于CHAR_LENGTH()的字符长度,适用于多字节字符集(如UTF-8)的数据验证... 目录1. LENGTH()函数的基本语法2. LENGTH()函数的返回值2.1 示例1:计算字符串

Android kotlin中 Channel 和 Flow 的区别和选择使用场景分析

《Androidkotlin中Channel和Flow的区别和选择使用场景分析》Kotlin协程中,Flow是冷数据流,按需触发,适合响应式数据处理;Channel是热数据流,持续发送,支持... 目录一、基本概念界定FlowChannel二、核心特性对比数据生产触发条件生产与消费的关系背压处理机制生命周期

Java通过驱动包(jar包)连接MySQL数据库的步骤总结及验证方式

《Java通过驱动包(jar包)连接MySQL数据库的步骤总结及验证方式》本文详细介绍如何使用Java通过JDBC连接MySQL数据库,包括下载驱动、配置Eclipse环境、检测数据库连接等关键步骤,... 目录一、下载驱动包二、放jar包三、检测数据库连接JavaJava 如何使用 JDBC 连接 mys

Qt使用QSqlDatabase连接MySQL实现增删改查功能

《Qt使用QSqlDatabase连接MySQL实现增删改查功能》这篇文章主要为大家详细介绍了Qt如何使用QSqlDatabase连接MySQL实现增删改查功能,文中的示例代码讲解详细,感兴趣的小伙伴... 目录一、创建数据表二、连接mysql数据库三、封装成一个完整的轻量级 ORM 风格类3.1 表结构

怎样通过分析GC日志来定位Java进程的内存问题

《怎样通过分析GC日志来定位Java进程的内存问题》:本文主要介绍怎样通过分析GC日志来定位Java进程的内存问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录一、GC 日志基础配置1. 启用详细 GC 日志2. 不同收集器的日志格式二、关键指标与分析维度1.

MySQL中的表连接原理分析

《MySQL中的表连接原理分析》:本文主要介绍MySQL中的表连接原理分析,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录1、背景2、环境3、表连接原理【1】驱动表和被驱动表【2】内连接【3】外连接【4编程】嵌套循环连接【5】join buffer4、总结1、背景

python中Hash使用场景分析

《python中Hash使用场景分析》Python的hash()函数用于获取对象哈希值,常用于字典和集合,不可变类型可哈希,可变类型不可,常见算法包括除法、乘法、平方取中和随机数哈希,各有优缺点,需根... 目录python中的 Hash除法哈希算法乘法哈希算法平方取中法随机数哈希算法小结在Python中,

MySQL中的索引结构和分类实战案例详解

《MySQL中的索引结构和分类实战案例详解》本文详解MySQL索引结构与分类,涵盖B树、B+树、哈希及全文索引,分析其原理与优劣势,并结合实战案例探讨创建、管理及优化技巧,助力提升查询性能,感兴趣的朋... 目录一、索引概述1.1 索引的定义与作用1.2 索引的基本原理二、索引结构详解2.1 B树索引2.2

Java Stream的distinct去重原理分析

《JavaStream的distinct去重原理分析》Javastream中的distinct方法用于去除流中的重复元素,它返回一个包含过滤后唯一元素的新流,该方法会根据元素的hashcode和eq... 目录一、distinct 的基础用法与核心特性二、distinct 的底层实现原理1. 顺序流中的去重