ZigZag Sin
登 陆
后面没有了 上一篇:从 SPS 中提取信息计算图像的宽高

解码重排序的问题

乔红
2021-5-18 00:37 阅读 4507

本小节由 L。 基情支持~~~

引言

今天群里的小伙伴遇到了一个问题。这个问题是 iOS 的 videoToolbox 硬解视频的问题。对于包含 B 帧的视频来说,其视频帧的解码顺序和播放顺序有可能是不一致的,这就需要解码器在解码之后,要按照播放顺序对视频帧进行重新的排序。大部分的解码器都做了重排序,例如 Android 的 MediaCode (大部分厂家),又例如 FFmpeg 自带的那个软件解码器。唯独有一个比较特殊的,就是 iOS 的 videoToolbox。videoToolbox 不会为你重新排序,他只要解出来一帧就会给你吐出来。所以,对于 videoToolbox,必须由我们手动进行排序。

排序方案

排序方案有很多种,比较简单的就是先缓存,然后再用时间戳进行排序。

queue

如上图,我们可以准备一个链表,链表最长可以放 4 个元素,每解码一帧,我们就把解出来的这一帧放到链表里面去。然后从链表中找出来时间戳最小的一帧进行播放。然后再解码,再防入链表中。

以此类推,我们就可以对其进行重排序了。

但是这里有一个问题,我们这个链表最大长度要设置多长?太长了,我们就需要过多的内存来存放视频帧。但是如果太短了,我们就无法对其进行完全的排序。

缓存最大长度

其实在 SPS 和 PPS 中,是存在一个属性来告诉我们,在这个 GOP 中,最大的参考帧列表的长度的。所以,我们缓存队列的长度,依照这个长度就可以了。

在 PPS 中,有这样两个属性。

num_ref_max

num_ref_idx_l0_default_active_minus1 表示的是参考帧队列 List0 的最大长度减去一。

num_ref_idx_l1_default_active_minus1 表示的是参考帧队列 List1 的最大长度减去一。

P 帧会使用 List0, B 帧会使用 List0 和 List1。所以这两个值里面的最大值,就是我们要缓存的帧的长度。

读取 SPS 和 PPS 的代码请参考这里

后面没有了 上一篇:从 SPS 中提取信息计算图像的宽高
给我买个键盘吧。。。求打赏。。。
欢迎加群,一起交流~~~