在做音视频数据分析的时候,经常会遇到这样的需求,每隔5分钟抽取一帧数据进行分析。

在做播放器开发的时候,也会遇到这种情况,就是拖动进度条跳转到某个位置进行播放。

如果直接用 av_read_frame() 不断读数据,读到第 5 分钟的 AVPacket 才开始处理,其他读出来的 AVPacket 丢弃,这样做会带来非常大的磁盘IO。

其实上面两种场景,都可以用同一个函数解决,那就是 avformat_seek_file(),这个函数类似于 Linux 的 lseek() ,设置文件的读取位置

只不过 avformat_seek_file() 是用于音视频文件的。


avformat_seek_file() 函数的定义如下:

int avformat_seek_file(AVFormatContext *s, int stream_index, int64_t min_ts, int64_t ts, int64_t max_ts, int flags);

参数解释如下:

1,AVFormatContext *s,已经打开的容器示例。

2,int stream_index,流索引,但是只有在 flags 包含 AVSEEK_FLAG_FRAME 的时候才是 设置某个流的读取位置。其他情况都只是把这个流的 time_base (时间基)作为参考。

3,int64_t min_ts,跳转到的最小的时间,但是这个变量不一定是时间单位,也有可能是字节单位,也可能是帧数单位(第几帧)。

4,int64_t ts,要跳转到的读取位置,单位同上。

5,int64_t max_ts,跳转到的最大的时间,单位同上,通常填 INT64_MAX 即可。

6,int flags,跳转的方式,有 4 个 flags,如下:

  • AVSEEK_FLAG_BYTE,按字节大小进行跳转。
  • AVSEEK_FLAG_FRAME,按帧数大小进行跳转。
  • AVSEEK_FLAG_ANY,可以跳转到非关键帧的读取位置,但是解码会出现马赛克。
  • AVSEEK_FLAG_BACKWARD,往 ts 的后面找关键帧,默认是往 ts 的前面找关键帧。

avformat_seek_file() 函数默认是把文件的读取位置,设置到离 ts 参数最近的关键帧的地方。

而且默认情况,是容器里面所有流的读取位置都会被设置,包括 音频流,视频流,字幕流。

只要流的 discard 属性小于 AVDISCARD_ALL 就会被设置。

AVStream.discard < AVDISCARD_ALL

min_ts 跟 max_ts 变量有一些设置的技巧。

如果是快进的时候min_ts 可以设置得比 当前位置 大一点,例如加 2。 而 max_ts 可以填 INT64_MAX

min_ts = 当前位置 + 2
max_ts = INT64_MAX

+2 是为了防止某些情况,avformat_seek_file() 会把读取位置往后挪一点

如果是后退的时候min_ts 可以填 INT64_MIN,max_ts 可以设置得比 当前位置 小一点,例如减 2。

min_ts = INT64_MIN
max_ts = 当前位置 - 2

-2 是为了防止某些情况,avformat_seek_file() 会把读取位置往前挪一点


当 flags 为 0 的时候,默认情况,是按时间来 seek 的,而时间基是根据 stream_index 来确定的。

如果 stream_index 为 -1 ,那 ts 的时间基就是 AV_TIME_BASE

如果stream_index 不等于 -1 ,那 ts 的时间基就是 stream_index 对应的流的时间基。

这种情况,avformat_seek_file() 会导致容器里面所有流的读取位置都发生跳转,包括音频流,视频流,字幕流。


当 flags 包含 AVSEEK_FLAG_BYTEts 参数就是字节大小,代表 avformat_seek_file() 会把读取位置设置到第几个字节。用 av_read_frame() 读出来的 pkt 里面有一个字段 pos,代表当前读取的字节位置。可以用pkt->pos 辅助设置 ts 参数,

AVSEEK_FLAG_BYTE 是否是对所有流都生效,我后面测试一下再补充。


当 flags 包含 AVSEEK_FLAG_FRAMEts 参数就是帧数大小,代表 avformat_seek_file() 会把读取位置设置到第几帧。这时候 stream_index 可以指定只设置某个流的读取位置,如果 stream_index 为 -1 ,代表设置所有的流。


当 flags 包含 AVSEEK_FLAG_ANY,那就代表 seek 可以跳转到非关键帧的位置,但是非关键帧解码会出现马赛克。如果不设置 AVSEEK_FLAG_ANY, 默认是跳转到离 ts 最近的关键帧的位置的。


当 flags 包含 AVSEEK_FLAG_BACKWARD,代表 avformat_seek_file() 在查找里 ts 最近的关键帧的时候,会往 ts 的后面找,默认是往 ts 的前面找关键帧。

提醒:AVSEEK_FLAG_BYTE ,AVSEEK_FLAG_FRAMEAVSEEK_FLAG_ANY 这 3 种方式,有些封装格式是不支持的。


下面通过一个例子来演示 avformat_seek_file() 函数的用法。代码下载地址:GitHb,编译环境是 Qt 5.15.2 跟 MSVC2019_64bit 。

运行结果如下:

可以看到,跳转之后,后面 av_read_frame() 读取到的 AVPacket 的 pts 跟 pos 都有很大的偏移了。

avformat_seek_file() 函数介绍完毕。

扩展知识:avformat_seek_file() 对应的旧版函数是 av_seek_frame()


推荐一个零声学院免费公开课程,个人觉得老师讲得不错,分享给大家:

Linux,Nginx,ZeroMQ,MySQL,Redis,fastdfs,MongoDB,ZK,流媒体,CDN,P2P,K8S,Docker,TCP/IP,协程,DPDK等技术内容,立即学习

avformat_seek_file函数介绍相关推荐

  1. python3 转码的函数_python基础3之文件操作、字符编码解码、函数介绍

    内容概要: 一.文件操作 二.字符编码解码 三.函数介绍 一.文件操作 文件操作流程: 打开文件,得到文件句柄并赋值给一个变量 通过句柄对文件进行操作 关闭文件 基本操作: 1 #/usr/bin/e ...

  2. C语言中的scanf()函数介绍

    1.scanf函数:读取从键盘输入的数据 在C语言中,有多个函数可以从键盘获得用户输入: scanf():和 printf() 类似,scanf() 可以输入多种类型的数据 getchar().get ...

  3. 延时函数介绍和呼吸灯的实现

    文章目录 延时函数介绍 呼吸灯原理 杨桃32学习笔记,本文图片文字皆为转述 延时函数介绍 分为delay_s秒,delay_ms毫秒,delay_us微秒延时,最大参数不能超过65535. 呼吸灯原理 ...

  4. ×××S 2012 参照函数 -- 介绍

    ×××S 2012 参照函数 -- 介绍 在×××S中,一张报表内可以同时包含多个数据集,但是一个数据区域就仅限于一个数据集,如果希望同时参考多个数据集,查找函数就能轻松办到,其概念类似JOIN是通过 ...

  5. 【 MATLAB 】rem 函数介绍

    rem函数和mod函数很相似,二者认真看一个,另一个看一下区别即可. mod函数介绍:[ MATLAB ]mod 函数介绍 rem Remainder after division Syntax r ...

  6. 【 MATLAB 】filter 函数介绍 之 Filter Data in Sections

    [ MATLAB ]filter 函数介绍(一维数字滤波器) 在上篇博文中,里面有一个例子,就是过滤部分中的数据,这个部分中的数据的意思是如果有一个向量需要过滤,我们可以把它分为几段,然后分段过滤. ...

  7. swift1.2语言函数和闭包函数介绍

    swift1.2语言函数和闭包函数介绍 在编程中,随着处理问题的越来越复杂,代码量飞速增加.其中,大量的代码往往相互重复或者近似重复.如果不采有效方式加以解决,代码将很难维护. swift1.2语言函 ...

  8. php函数介绍,PHP函数介绍_PHP教程

    PHP函数介绍 基本使用: 函数定义形式: function 函数名(形参1,形参2,...) { //函数体(代码块): } 函数调用形式: 本质上就是使用一个名字来达到执行其中函数中的的作用.通常 ...

  9. Json模块dumps、loads、dump、load函数介绍

    转自:http://blog.csdn.net/mr_evanchen/article/details/77879967 Json模块dumps.loads.dump.load函数介绍 1.json. ...

  10. Numpy中np.mashgri() 函数介绍及2种应用场景

    @[toc](Numpy中np.mashgri() 函数介绍及2种应用场景 文章目录:) 近期在好几个地方都看到meshgrid的使用,虽然之前也注意到meshgrid的用法. 但总觉得印象不深刻,不 ...

最新文章

  1. html 文字倒映效果,HTML图片CSS滤镜—倒影效果
  2. 洛谷.4252.[NOI2006]聪明的导游(提答 直径 随机化)
  3. 有点贵但卖光了!这款旗舰要火了吗...
  4. 从某软件引发的深思总结
  5. 手机怎么安装py thon_Python属性装饰器– Py​​thon @property
  6. [Ubuntu] change mouse scrolling between standard and natural
  7. Unity渐进式GPU烘焙找不到显卡
  8. nginx代理服务器
  9. 天正暖通2013版安装包附带注册机下载
  10. Something's wrong--perhaps a missing \item. \end{thebibliography}
  11. 减去百分之二是怎么用计算机算,百分比换算公式(常见的百分率计算公式)
  12. 去哪下载python项目_Python 项目实践二(下载数据)第三篇
  13. VIO_FUSION
  14. 详解EBS接口开发之采购订单导入(转载)
  15. java ftp 被动模式_ftp 主动模式与被动模式
  16. JavaScript直接通过id获取对象
  17. android 游戏内存,如何「偷」Android 的内存?
  18. 分布式搜索引擎的研究
  19. 07 工程结构及依赖关系
  20. Java程序员面试常见面试题,你了解多少?初步整理简化版

热门文章

  1. 洛谷 P4234 LCT + 排序 + 枚举
  2. 小白学python#Day5#笔耕不辍#每日一句,提高认知
  3. 从微信H5点击保存图片说起-微信图片下载
  4. PDF文件怎么拆分,PDF拆分技巧
  5. 苏嘉杭高速公路收费站升级改造(苏州地区)配电室综合监控系统的设计与应用
  6. Spring Boot 2.1.2配置文件参考配置项官方谷歌翻译版本
  7. 苹果开发者后台,修改付费app中银行账户信息时注意
  8. 小张的个人信息管理系统
  9. 增量学习——文章汇总
  10. Linux显示2015年日历表