最初在项目中做实时视频流的时候,采用的方案是,设置Camera Preview格式是NV21,最终MediaCodec需要的格式是I420,由于之前对YUV一无所知,所以一些旋转算法也是在网上淘的,导致有部分是在NV21的时候进行旋转,有部分则是在I420的时候进行旋转,最终还是实现了功能。
最近时间比较多,也要在视频流上增加水印,决定对这部分性能进行优化,所以着重学习了解了一下YUV格式。
在Android文档,Camera里面有这样一句话
If this is never called, the default format will beNV21, which uses the NV21 encoding format.
UsegetSupportedPreviewFormats()to get a list of the available preview formats.
It is strongly recommended that eitherNV21orYV12is used, since they are supported by all camera devices.
在Camera中推荐使用NV21和YV12,因为这两种格式支持所有的相机设备。
但是在Camera2中,推荐使用的格式则是YUV_420_888。
总的来说,在Android里面YUV用得比较多的应该是I420, YV12, NV12和NV21,其中I420和YV12都是Y420P,NV12和NV21都是Y420SP。
这几种格式相同点和区别呢可以这样看:
YUV420SP格式
YUV420SP:图中Y1,Y2,Y9,Y10共用一对UV:U1和V1
YUV420P格式
YUV420P:图中Y1,Y2,Y9,Y10共用一对UV:U1和V1
I420: YYYYYYYY UU VV =>YUV420P
YV12: YYYYYYYY VV UU =>YUV420P
NV12: YYYYYYYY UVUV =>YUV420SP
NV21: YYYYYYYY VUVU =>YUV420SP
他们的共同点是一个Y代表一个像素点,Y的大小就等于width * height,由于它们都说420格式,所以UV总长位width * height / 2,其中U和V各占一般长度。所以在代码中新建一个byte[]的时候长度为 width * height * 3 / 2。
YV12:
YV12 is a 4:2:0 YCrCb planar format comprised of a WxH Y plane followed by (W/2) x (H/2) Cr and Cb planes.
所以我针对之前项目的改进方案就是,预览输出使用YV12格式,通过转换和旋转转成I420格式。
因为YV12和I420的结构很相似,只需要调换UV分量的位置即可,更方便在同一个循环中同时进行旋转和转换,相比之前的方案旋转和转换是两个循环,这样效率更高。
最终实测,各个方向分别统计了几百帧的数据求算术平均值,YV12->I420比NV21->I420的旋转+转换,每帧少花3ms左右,不管各位看管觉得怎么样,对我来说是个不错的鼓舞。
我的YV12转NV21的代码,虽然是Java层的,速度还不错,每帧耗时小于1ms
下一步优化的目标就是把耗时算法放到JNI层去做。
参考:blog.csdn.net/jefry_xdz/article/details/7931018
www.cnblogs.com/samaritan/p/YUV.html
作者:黄河远去楼依在
链接:http://www.jianshu.com/p/102b8b0797b7
來源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。