iOS 倍速播放渲染慢、暂停后还在继续播放等问题.md
本文围绕 iOS 端录像倍速播放的各类异常问题展开,先列举了 8 倍速渲染偏慢、画面时间与进度不同步、频繁跳帧、播放结束后时间未对齐、暂停后画面与进度仍继续播放、内存堆积易被系统杀掉等现象;再分析原因:固件未做倍速跳帧处理,视频获取帧率远超屏幕刷新率,导致倍速异常,且暂停时未停止取流线程,引发续播问题;最后给出方案:App 端按计算的跳帧间隔手动跳帧,暂停时立刻停止取流线程。
问题
没有按实际倍速渲染
尤其是 8 倍速下,和 Android 对比,可以看到明显慢了很多。
画面上时间和进度不同步
画面上的时间每隔 1 秒播放,播放进度的时间每隔 3 秒播放。
跳帧
通过和 Android 对比,明显 Android 渲染要快很多。
以下为同一个录像,多次播放。
播放第一次:
47:14 跳到 24,画面有移动,再跳到 29。
47:38 跳到 49,画面有移动。
47:54 跳到 48:24,画面有变化。
48:34 跳到 45,画面无明显变化。
48:55 跳到 49:15,画面有变化。
播放第二次:
45:34 -> 39
46:05 -> 14 -> 29
46:44 -> 49
47:27 -> 29
47:40 -> 48:50
49:09 -> 49:15 -> 55
播放第三次:
46:44 -> 49
46:54 -> 47:09 -> 19
47:31 -> 44
47:53 -> 48:14 -> 24
48:56 -> 49:10
49:15 -> 49:45
录像播放完,当前播放时间小于总时间,画面时间小于最后时间


暂停后,画面还在播放,进度还在继续
可能被系统杀掉
可能几个偶现的问题,也是由此引起。因为由于渲染过慢,会堆积大量的视频流没有释放,占用内存过大,就会被系统杀死。
原因
没有倍速显示
固件没有对倍速进行跳帧处理,App 获取到的帧是视频的每一帧,在不渲染视频时(不调用 presentRenderbuffer),4 倍速时帧率大概为 100fps,8 倍速时帧率大概为 200fps,帧率都超出了 iPhone 屏幕刷新率 60Hz,手机最多只能每秒显示 60 帧(即每秒执行 60 次 presentRenderbuffer),在获取和处理视频流的 while 循环中,是执行完 presentRenderbuffer 后,才能调用 avRecvFrameData2,因此剩下的 40 帧或 140 帧将在 1 秒后显示,所以导致没有按照倍速显示。
解决
合理的解决办法应该是固件在倍速时,进行跳帧处理,但固件连合适的倍速调整方案都没有,下面为固件开发的原话:
@Jason 我这试了下,没找到好一点的丢帧策略呢。如果间隔丢P帧会无法播放,只有I帧视频;如果连续丢后续P帧,太多的话,跳帧比较多,而且夜视P帧间隔时间较长,会有画面暂停的现象
那目前只能跳帧只能通过 App 来处理了。
在 8 倍速时,要按照传输帧率 200fps 显示(即渲染帧率为 200fps),那么需要每隔 1000/200=5ms 渲染一次,但刷新率如果只有 60Hz,那只能 1000/60=16.7ms 渲染一次。
通过间隔 16.7ms 渲染一次视频帧,即可实现视频以 60fps 帧率播放,因此 16.7ms 内共有 16.7/5=3.34 帧,1 秒内可以跳过 3*60=180 帧。
但是为了能够 1 秒内通过跳帧渲染 200 帧,并且以 60fps 显示,那么跳帧间隔应为 4(200/60=3.33333333333) 帧,即间隔 5ms * 4 = 20 ms 跳帧可实现播放传输帧率为 200fps 的视频。
暂停后还在继续播放
即使收到暂停的成功响应后,也能继续调用 avRecvFrameData2 获取到帧数据。倍速越大收到次数越多,8 倍速至少能收到 2 秒钟。
由于暂停时,代码并没有停止获取视频流的线程,因此暂停后还在一直调用 avRecvFrameData2,所以暂停后,视频还能播放几秒或几十秒。
解决
暂停时,立即停止获取视频流的线程即可解决此问题。
iOS 倍速播放渲染慢、暂停后还在继续播放等问题.md

