Android使用RenderScript转换原始视频帧到Bitmap

最近做一个安卓的视频帧处理的项目,需要在onPreviewFrame回调中快速的把YUV格式的原始数据帧转换为Bitmap。

最开始在网上找了个使用YuvImage.compressToJpeg,然后BitmapFactory.decodeByteArray解码成Bitmap的函数,实测速度还不错。

实现函数如下:

 

机器是RK3288,2GB RAM。大约40~50 ms可以转换完成。就在感觉解决了问题时,发现程序大约每隔10小时,就会自动挂掉。

logcat翻了几页日志,发现几台设备全部都是因为程序内存占用过大导致被系统杀死。而程序正常占用内存不过40~50 MB而已。

日志中显示程序被杀死前,大约占用了1.8GB的内存,明显是哪里有内存泄漏。

好在Android Studio 3.0开始有了Android Profiler,用这个抓Memory的分配记录。

最终定位到,就是在使用将视频帧原始数据压缩为Jpeg然后解码为Bitmap时出现的内存泄漏:

反复修改了几遍代码,并且返回后的Bitmap也有回收掉,但还是会出现内存泄漏。

只能找其它的解决方案,一开始找了个纯Java实现的解码YUV到RGB数据,然后根据RGB数据解码出Bitmap的函数。

可惜速度太慢,测试时,大约200~300 ms才能完成转换。

后来终于找到个使用RanderScript实现解码YUV数据到Bitmap的函数,测试发现速度大约20~30 ms,比用YuvImage.compressToJpeg还要快一些。

整理后,实现的代码如下:

要编译通过上面的函数,需要在build.gradle文件的android->defaultConfig中加入2行:

然后在相关Java文件引入:

即可。

 

更换为这种转换方式,程序跑了几天几夜都没有挂掉。

参考链接:

How to use ScriptIntrinsicYuvToRGB (converting byte[] yuv to byte[] rgba)

Print Friendly, PDF & Email

留下评论

2 + 1 =

*

此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据

%d 博主赞过: