Seek 策略以及在有 B 帧情况下的处理
在知识星球分享的文章,顺便也在公众号发表一下,不足之处,欢迎指正。
一个关于音视频领域专业问答的小圈子!!
最近在做 Seek 相关功能时遇到的问题排查,顺便也学到了一些新的东西,和大家分享下。
在视频播放时执行 Seek 到任意点的操作,一般都是 Seek 到任意点往前最近的 I 帧,然后再逐帧解码到指定时间点。
这里可以优化,假设当前时间和指定时间在一个 GOP 内,就可以不用 seek ,直接顺序向下解码就好。
而正是这个优化出现了一点问题,现象如下:
已经判断播放点 A 和 Seek 点 B 不在一个 GOP 内,然后执行 av_seek_frame 方法还是把时间点 A 所在 GOP 全部解码了,导致播放上出现了卡顿。
这里就很奇怪了,明明判断不在一个 GOP ,那 Seek 时就应该从时间点 B 所在 GOP 的 I 帧开始解码, 但执行时还是解码了上一个 GOP 的内容。
到底是判断是否同一个 GOP 的函数出问题了还是 Seek 方法有问题呢?
带着疑问开始深入源码探索。
FFmpeg 没有直接提供判断两帧是否同一个 GOP 的方法,所以通过 av_index_search_timestamp 方法得到传入时间点最近的 I 帧的 index 索引,如果两个时间点的索引相同则表示为同一个 GOP 内,因为最近的 I 帧相同。
然而 av_index_search_timestamp 方法是通过 AVIndexEntry 中的 timestamp 来判断的,它是一个 DTS 值,通过二分查找得到最近的索引。
在没有 B 帧的情况下,I 帧的 PTS 等于 DTS ,所以判断不会出问题。然而正是有了 B 帧,如果 I 帧的 PTS 和 DTS 不相等的话,那么上面的判断相当于是拿一个 PTS 值和 I 帧的 DTS 比较是否同一个 GOP 了。
如果将错就错,判断 GOP 时得到结论是非同一个 GOP ,那么 Seek 也应该是非同一个 GOP ,但现实恰恰相反,Seek 当做了同一个 GOP ,这里面肯定有计算出问题了,继续深入源码。
通过在 mov.c 源码中看到了如下的操作:
static int mov_seek_stream(AVFormatContext *s, AVStream *st, int64_t timestamp, int flags)
{MOVStreamContext *sc = st->priv_data;FFStream *const sti = ffstream(st);int sample, time_sample, ret;unsigned int i;// Here we consider timestamp to be PTS, hence try to offset it so that we// can search over the DTS timeline.timestamp -= (sc->min_corrected_pts + sc->dts_shift);ret = mov_seek_fragment(s, st, timestamp);if (ret < 0)return ret;sample = av_index_search_timestamp(st, timestamp, flags);av_log(s, AV_LOG_TRACE, "stream %d, timestamp %"PRId64", sample %d\n", st->index, timestamp, sample);// 省略部分代码
注意到如下一行代码:
timestamp -= (sc->min_corrected_pts + sc->dts_shift);
也就是说我们传入的时间都会被减上一个值,然后再执行 av_index_search_timestamp 方法,而这个值导致判断 GOP 和 Seek 之间的关键帧索引出问题了。
正如代码中的注释所示,假设传入的时间是 PTS 值,然后给它减去偏移以得到 DTS 值,因为 av_index_search_timestamp 方法就通过 DTS 进行比较的嘛。
出现问题的原因就是 seek 的时间点正好在 I 帧的 PTS 和 DTS 范围之间了,执行 seek 时减去偏差值就小于 DTS 了,所以变成了同一个 GOP 。
现在要解决问题就是如何得到 sc->min_corrected_pts + sc->dts_shif 之和,然后判断 GOP 时减去它以修正得到 DTS 值。
还好通过遍历源码发现它的值是不会运行时改变的,一旦决定了就定下来了。另外我们可以用第一个 I 帧的 DTS 值作为偏移值。
auto indexEntry = avStream->index_entries;auto nbIndexEntry = avStream->nb_index_entries;for (int i = 0; i < nbIndexEntry; ++i) {if (indexEntry[i].flags == AVINDEX_KEYFRAME) {DTSOffset = indexEntry[i].timestamp;return;}}
如果没有 B 帧,DTS 值为 0 ,有 B 帧,那么首帧的 DTS 值就可以用来做偏差值进行计算了。
一个音视频领域专业问答的小圈子!
推荐阅读:
音视频开发工作经验分享 || 视频版
OpenGL ES 学习资源分享
开通专辑 | 细数那些年写过的技术文章专辑
Android NDK 免费视频在线学习!!!
你想要的音视频开发资料库来了
推荐几个堪称教科书级别的 Android 音视频入门项目
觉得不错,点个在看呗~
Seek 策略以及在有 B 帧情况下的处理相关推荐
- 如何在不影响网络的情况下构建边缘计算策略
阅读本文之前先问一下自己这个问题:"为什么我需要使用边缘计算?" 随着越来越多的科技公司宣称他们提供"边缘智能"的能力,边缘计算吸引了众多公司高管们的关注.哪个 ...
- 【数据竞赛】99%情况下都有效的特征筛选策略--Null Importance。
作者:杰少 Null Importance特征筛选 简介 目前数据量越来越大,数据特征维度也越来越高,这不仅对我们的计算存储带来了较大的挑战,与此同时,还会对模型的效果带来较大的损益. 如何既能节省内 ...
- enti下载器_短跑enti策略:如何在不破坏软件的情况下改进软件
enti下载器 我们的代码已被破坏了几个星期. 编译器错误,测试失败,行为错误困扰着我们的团队. 为什么? 因为我们被盲目蛙跳打了. 通过对关键组件进行多次并发更改以希望对其进行改进,我们已经从其丑陋 ...
- 短跑enti策略:如何在不破坏软件的情况下改进软件
我们的代码已被破坏了几个星期. 编译器错误,测试失败,错误行为困扰着我们的团队. 为什么? 因为我们被盲目蛙跳打了. 通过对关键组件进行多次并发更改以希望对其进行改进,我们已经从其丑陋但稳定且可工作的 ...
- 在不同的库存情况下,亚马逊CPC广告的投放策略会有什么改变呢?
说到开广告之于库存的意义,很多亚马逊卖家第一反应就是开广告可以处理库存,盘活库存,提升资金周转率,当你库存太多的时候,可以通过广告引流和低价甩掉库存:在不同的库存情况下,亚马逊CPC广告的投放策略会不 ...
- 三网融合情况下,实时语音通信技术的研究
随着技术和标准的不断成熟,伴随着"三网合一"的大潮,VoIP可望成为下一代电信基础设施结构的杨心,使未来各电信业务综合统一在IP网络上成为可能,导致数据的融合和未来电信市场的重组, ...
- 三网融合情况下,实时语音通信技术解决之道
随着技术和标准的不断成熟,伴随着"三网合一"的大潮,VoIP可望成为下一代电信基础设施结构的杨心,使未来各电信业务综合统一在IP网络上成为可能,导致数据的融合和未来电信市场的重组, ...
- 1.什么情况下发生GC
目录 一:jvm运行时数据区的划分 二:堆区的划分(where) 三:什么情况下发生GC(when) 四:哪些内存需要回收(垃圾对象who) 五:GC如何回收(how) 六:jvm的内存回收过程 七: ...
- ⽬标⾏动及稠密环境未知情况下,⽆⼈机跟踪的系统解决⽅案
点击上方"3D视觉工坊",选择"星标" 干货第一时间送达 本文是对<Fast-Tracker:A Robust Aerial System for Tra ...
- 园艺智慧_园艺日:如何在完全远程的情况下运行技术债务清理日
园艺智慧 Just like financial debt, you have to be wise about the technical debt you are building up over ...
最新文章
- python3 asyncio loop 使用线程池原理
- 阿里云首发Dubbo3.0 + Nacos2.0
- C++11 并发指南三(Lock 详解)
- Shell脚本IF条件判断和判断条件总结
- iPhone 12开启5G续航锐减 苹果官方回应了!
- cms是什么意思啊_美团面试官问我:ZGC 的 Z 是什么意思?
- 数据安全的四个新挑战有哪些
- java2wsdl_Java2WSDL之java实现
- oracle strsplit函数,oracle splitstr 函数
- 百度搜索引擎推出“熊掌号”,保护原创作者权益
- java安装教程(eclipse)
- 爬虫爬出来的数据不全_Web Scraper教程(二)爬虫入门之当当畅销书爬取
- TGA文件转YUV文件
- Day03-JavaScript01
- 英语作文模板句型,考试必背!
- 简易的本地音乐播放器 适用于Java初学者
- python的invalid syntax是什么意思_python 中 出现 invalid syntax 是什么意思 我是新手 求告知。...
- 看完秒懂ICA(含MATLAB和python代码)
- (王爽)汇编语言-课程设计二完整版
- python气象绘图速成_Python气象绘图Day-By-Day