问题描述:现在因为H264本身的原因,一路需要维护30帧的YUV数据(因为一个I帧循环30帧。)
为了避免当这30帧数据播放完后,程序会卡的问题,其实需要2个30帧的YUV数据(一个当缓冲),
也就是60帧YUV数据。那一路(D1)总共的最大内存为:720×576×1.5 × 60 = 36M,因为要求16
路同时播放,因此需要36 × 16 = 576M。可见分配如此大的一个动态内存,很容易使系统Crash
down。
问题分析:
这么大的内存,如果频繁的调用new/delete,容易产生内存碎片,进而导致分配速度变慢或者内存急剧 膨胀从而Crash
down。
解决方法1:所有YUV数据存于文件中,只维护3-8个YUV数据缓冲,但这样会让硬盘的负荷变大,如果其他
模块也频繁访问硬盘的话,恐怕回放速度会十分缓慢。试想一下,一个通道25帧/s,也就是一个通道一
秒钟需要保存25帧的YUV数据,16个通道一秒钟需要保存400帧YUV数据,如此庞大的数据势必对系统会有
性能上的影响。(这个方法是否可以行,还有待研究。)
解决方法2:用虚拟内存。据研究,虚拟内存只不过是当系统所有进程分配的内存总和太大时,一个不至于让系统Crash down
的策略,如果系统总内存持续处于高占用的情况下的话,那虚拟内存将会导致系统进程运行速度变慢,
因为它会频繁的产生断页中断,每一次断页中断都要访问一次硬盘。所以,它也会让回放速度偶尔变得缓慢。
解决方法3:(1)用顺序内存。如,一次性分配576M的内存,然后,依次把YUV数据存进去,如同磁带。
缺点是:如果是CIF分辨率,则一路浪费了(D1-CIF)这么大的内存。
如果H264视频数据I帧循环未满30帧的话,则浪费了(30-x)帧YUV数据内存。
解决方法4:用内存池。这要求内存容量要足够,最好是2G。
(1)等大内存分配的内存池。每次都分配720 × 576 × 3 / 2大小的内存。
优点:H264视频数据I帧循环未满30帧的话,不会浪费内存。
缺点:如果是CIF分辨率,则一路浪费了(D1-CIF)这么大的内存。
(2)不等大的内存池:
先new出一个大空间A,如果发现该空间不够时,额外增加一些new出来的空间,这些额外空间跟
大空间A是没有联系的。因为如果额外空间不是很大,那么频繁的new、delete不会使系统变慢。
优点:H264视频数据I帧循环未满30帧的话,不会浪费内存。
如果是CIF分辨率,不会浪费太多内存。
缺点是:如果额外内存太大的话,那将要多new出很多空间,又会使系统变慢。也就是说不等大内存池,
会先分配一定大小的内存,如从352 × 288 ×1.5 × 60 × 16 到
720 × 576 ×1.5 × 60 × 16选择一个数来分配内存,选得太大了,可能浪费太多内存,
选得太小了,可能额外内存会很大,导致系统变慢。其实它在“解决方法3和解决方法4(1)”
之间做一个中和。
(3)用虚拟内存实现“(1)”,只有用到的内存才提交给物理存储器。
优点是:H264视频数据I帧循环未满30帧的话,不会浪费内存。
如果是CIF分辨率,不会浪费物理内存。
缺点是:浪费了虚拟内存。
注意:这个方法是我现在能想到的最好的。
解决方法5:用分配非连续虚拟内存的方法。
(1)优点:不会浪费太多内存,以一页为单位,最多浪费一页内存,但是,分配的虚拟内存不是连续的,
这在访问时,不能用memcpy或其它数组操作的方法。(适用性不高,不建议使用。)