YUV420格式学习

最初在项目中做实时视频流的时候,采用的方案是,设置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。

这几种格式相同点和区别呢可以这样看:

YUV420格式学习_第1张图片

YUV420SP格式

YUV420SP:图中Y1,Y2,Y9,Y10共用一对UV:U1和V1

YUV420格式学习_第2张图片

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

來源:

著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

你可能感兴趣的:(YUV420格式学习)