iOS (socket+H264+videoToolbox)视频内存增长与播放速度控制
视频播放的时候 控制视频的内存在这张图的消耗速度上

录像是存储在某台服务器里面的,服务端一般看客户端要多少数据 ,就会开个while循环,一次读取多少字节的数据。然后几乎没有时间间隔的把数据送出去。这时候在播放端就需要做好播放速度的控制,因为接收速度完全取决于网速,如果没有做这段,那么视频的播放速度就和网速一样,网速快的时候 ,视频呈现快进的效果。网速慢的时候会出现卡帧的效果。直播的时候,由于录像采集方控制了采集的速度,所以传输给播放端的时候不需要处理播放速度。
按照标准的H264来说,应该每一帧都有pts时间戳 ,这样就可以做视频的同步来解决问题。
但就有奇葩的没有pts的H264流,该怎么处理这种流呢?
把流下载下来存文件,放到VLC里面 也能够正常播放,那么VLC是怎么做到流速控制,他怎么在没有pts的情况下知道间隔多少毫秒播放呢。用ffmpeg打印文件信息,ffprose就能什么都打印出来,拿到avformat里面的帧率 是1/25 那么就是每秒25帧,就是每隔40毫秒需要渲染一帧视频画面。
如果不是标准的25帧的帧率,那么可以通过avopeninput多等几帧来尝试解析文件,让ffmpeg
帮你猜测帧率,然后再写好等待函数的具体毫秒时间。
至于流播放的过慢应该怎么控制,可以通过一个视频缓冲区来控制,比如我们一秒钟能够保证视频
的流畅体验,那么小于25帧 就不应该播放,应该继续拉流把缓冲区至少填充到25帧,再以间隔40毫秒的速度
播放下去。而缓冲区也不能够无限的大,当视频比如说已经5秒(125帧)了。那就不要再继续拉流了。
这样可以做到流量节省,同时保证流畅的播放体验,也不会造成缓冲区过大的问题。
从上面的内容,我们知道要实现两个东西
视频缓冲区,播放间隔速度控制
在实际编码的过程中
出现了两个比较严重的问题,一个是内存增长过快,到一定程度就会被苹果杀掉了。
一个是数据拷贝的时候数据已经被其他线程释放了,导致读写的时候出现越界崩溃的问题。
还有播放速度无法控制。
针对内存增长过快,原因是拉流缓冲区释放不及时,接收速度远超过播放速度,高人提供了一个解决方案,
就是提前预分配内存,首先分配一个大概2M大小的内存,拉流收到的视频帧直接存到这个内存里面去
控制一个读写的位置,每次的新帧就会一直拼在后面,这样write的位置就会一直往后,read的位置则每读取
一包数据,就向后移动一个位置,当write写到了内存长度的最后的时候,又从头开始写,因为read已经读过了
的部分,就可以覆盖写了,这样包装所有的数据都是在这2M内的,当播放结束的时候,再把2M的内存完全释放。
这样就不用反复分配释放某个内存,而苹果是ARC的,什么时候释放也不是我们能控制的,因此这段代码就C
代码的实现,需要分配和释放成对出现,当然这从某种角度讲,也叫内存池。这里有一套java的实现,
翻译成C的就好了。
package com.temobi.util;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class VideoBuffer {
private static final int HEADLEN = 8;
private static final int MAGIC = 0xabababab;
private Lock lockWrite = new ReentrantLock(); // buffer write lock
private int writePos; // write position
private int readPos; // read position
private int dataLength; // data length of the buffer
private int bufferSize; // buffer size
private byte[] buffer; // buffer
public VideoBuffer(int size) {
writePos = 0;
readPos = 0;
dataLength = 0;
bufferSize = size;
buffer = new byte[bufferSize];
}
public boolean isHasData() {
return dataLength > HEADLEN ? true : false;
}
public int getFreeSpaceSize() {
return bufferSize - dataLength;
}
//splice the buffer to tailed
public boolean spliceBuffe

本文探讨了iOS环境下视频流的内存管理和播放速度控制问题,包括如何使用内存池和固定大小缓冲区来避免内存泄露,以及在无时间戳H264流中实现稳定播放速度的方法。
最低0.47元/天 解锁文章
292

被折叠的 条评论
为什么被折叠?



