Android音视频开发-入门(三):使用 Camera API 采集NV21数据
做过Android开发的人一般都知道,有两种方法能够做到这一点:SufaceView、TextureView。
Android 中Google支持的Camera Preview CallBack的YUV常用格式有两种:一种是NV21,一种是YV12,Android一般默认使用的是YCbCR_420_sp(NV21)
小度在家1c畅想版nv21与小度在家1c有何区别?
小度在家1c畅想和小度在家1c.是有区别的,但不是很大。相比较来讲性价比选择1c畅想不错的,在性能上提高了一个层次,智能性不错,可以遥控家电。外观简洁漂亮,屏幕显示清晰。功能很多,很好玩。平时用来听音乐找东西都挺不错的。音质挺好,价格合理
一、价格方面对比:
1、小度在家1C普通版目前价格行情在¥499.00左右,最新的价格行情建议大家去京东平台查询一下:
2、小度在家1C 4G版目前价格行情在¥699.00,最新这款小度在家1C 4G版报价行情大家可以去京东查询下:
从价格方面对比来看,这款小度在家1C普通版比1C 4G版要便宜200多,下面来看看外观方面对比情况:
二、外观方面对比:
小度在家1C普通版和1C 4G版外观方面,小度在家1C普通版有银色和红色两个颜色,而小度在家1C 4g版只有一个银色,对于喜欢红色的朋友来说,大家可以选择普通版。
三、配置方面对比:
小度在家1C普通版和1C 4G版配置方面,主要区别一是小度在家1C普通版上网方式只能使用wifi功能,而1C 4G版有wifi功能和移动4g无线上网两种方式;二是小度在家1C普通版没有内置电池,只能插电使用;而小度在家1C 4G版内置了电池,断电了依然可以使用,很适合外出携带使用。
四、功能方面对比:
小度在家1C普通版和1C 4G版功能方面对比来说,没有区别的,都支持ai语音,具有触屏功能,一样的分辨率和尺寸大小,支持视频通话和儿童模式。所以,功能方面,小度在家1C普通版和1C 4G版都是一样的。
五、用户体验情况:
小度在家1C个人觉得很好用,小孩正处于十万个为什么的阶段,自从有了小度,再也不烦恼了,不懂得问小度,有了小度,孩子也不缠着我了,家里还有一个比较小的孩子,以前每天都缠着我,现在不缠我了。小度就像一个好朋友一样的陪她,陪她唱歌跳舞,陪她玩游戏,教她不会的知识,我很开心小度的到来。
小度很智能,不管我说啥,它总有回答的,里面海量音乐MV,电视直播,电影大多需要爱奇艺会员,电视剧一般都可以看,儿童模式内容也很丰富,还可以看小品相声,也可以听电台,小说,笑话,搞笑段子。
六、总结:该如何选择?
小度在家1C普通版和1C 4G版这两款从上面价格,外观,配置,功能及用户体验来看,其主要区别是小度在家1C 4G版多一个sim卡和内置电池,其他功能方面都是一样的,主要看个人需求,如果外出携带比较多的,建议小度在家C 4G版,如果在家使用多的,建议小度在家1C普通版 ,更加划算一些。
NV12和NV21的区别?也就是12和21的区别
存储格式不同。
存储格式指对计算机信息以"文件"方式的存储,包括图像,声音,图像等。
内容概述:
计算机信息多种多样,信息的存储格式也多种多样。对用户而言,计算机存储的信息都是以“文件”的形式存在。
用户通过计算机应用程序可以创建并保存文件,这个过程便建立了保存文件和应用程序之间的一个“关联”,该关联链接着文件和应用程序,所谓的“文件格式”是指文件中保存的数据类型和保存的方法,与特定应用程序的文件关联直接相关的便是文件的保存格式(存储格式),文件的扩展名便表征了这种“关联”。
视频存储格式YUV420 NV12 NV21 i420 YV12
1)YUV简介
YUV格式有两大类:planar和packed。
对于planar的YUV格式,先连续存储所有像素点的Y,紧接着存储所有像素点的U,随后是所有像素点的V。
对于packed的YUV格式,每个像素点的Y,U,V是连续交*存储的。
YUV,分为三个分量,“Y”表示明亮度(Luminance或Luma),也就是灰度值;而“U”和“V” 表示的则是色度(Chrominance或Chroma),作用是描述影像色彩及饱和度,用于指定像素的颜色。
与我们熟知的RGB类似,YUV也是一种颜色编码方法,主要用于电视系统以及模拟视频领域,它将亮度信息(Y)与色彩信息(UV)分离,没有UV信息一样可以显示完整的图像,只不过是黑白的,这样的设计很好地解决了彩色电视机与黑白电视的兼容问题。并且,YUV不像RGB那样要求三个独立的视频信号同时传输,所以用YUV方式传送占用极少的频宽。
2)YUV存储格式
YUV码流的存储格式其实与其采样的方式密切相关,主流的采样方式有三种,YUV4:4:4,YUV4:2:2,YUV4:2:0,关于其详细原理,可以通过网上其它文章了解,这里我想强调的是如何根据其采样格式来从码流中还原每个像素点的YUV值,因为只有正确地还原了每个像素点的YUV值,才能通过YUV与RGB的转换公式提取出每个像素点的RGB值,然后显示出来。
用三个图来直观地表示采集的方式吧,以黑点表示采样该像素点的Y分量,以空心圆圈表示采用该像素点的UV分量。
先记住下面这段话,以后提取每个像素的YUV分量会用到。
1. YUV 4:4:4采样,每一个Y对应一组UV分量8+8+8 = 24bits,3个字节。
2. YUV 4:2:2采样,每两个Y共用一组UV分量,一个YUV占8+4+4 = 16bits 2个字节。
3. YUV 4:2:0采样,每四个Y共用一组UV分量一个YUV占8+2+2 = 12bits 1.5个字节。
3)YUV420类型
3.1) YUV420p和YUV420sp区别
因为YUV420比较常用, 在这里就重点介绍YUV420。YUV420分为两种:YUV420p和YUV420sp。
YUV420sp格式如下图:
YUV420p数据格式如下图:
3.2) YUV420p和YUV420sp具体分类和详情
YUV420p:又叫planer平面模式,Y ,U,V分别再不同平面,也就是有三个平面。
YUV420p又分为:他们的区别只是存储UV的顺序不一样而已。
I420:又叫YU12,安卓的模式。存储顺序是先存Y,再存U,最后存V。YYYYUUUVVV
YV12:存储顺序是先存Y,再存V,最后存U。YYYVVVUUU
YUV420sp:又叫bi-planer或two-planer双平面,Y一个平面,UV在同一个平面交叉存储。
YUV420sp又分为:他们的区别只是存储UV的顺序不一样而已。
NV12:IOS只有这一种模式。存储顺序是先存Y,再UV交替存储。YYYYUVUVUV
NV21:安卓的模式。存储顺序是先存Y,再存U,再VU交替存储。YYYYVUVUVU
官方文档如下:
YV12
All of the Y samples appear first in memory as an arr*** of unsigned char values. This arr*** is followed immediately by all of the V (Cr) samples. The stride of the V plane is half the stride of the Y plane, and the V plane contains half as many lines as the Y plane. The V plane is followed immediately by all of the U (Cb) samples, with the same stride and number of lines as the V plane (Figure 12).
大致意思是:先存储完所有的Y,后面紧跟着存V,V的步长(也就是宽)是Y的步长的一半,V的行高是Y的一半。V存储完后面紧跟着存U,所有的U,步长河行高和V相同,也就是都是Y的一半。
Figure 12:
NV12
All of the Y samples are found first in memory as an arr*** of unsigned char values with an even number of lines. The Y plane is followed immediately by an arr*** of unsigned char values that contains packed U (Cb) and V (Cr) samples, as shown in Figure 13. When the combined U-V arr*** is addressed as an arr*** of little-endian WORD values, the LSBs contain the U values, and the MSBs contain the V values. NV12 is the preferred 4:2:0 pixel format for DirectX VA. It is expected to be an intermediate-term requirement for DirectX VA accelerators supporting 4:2:0 video.
Figure 13:
3.3)YUV420的内存计算
width * hight =Y(总和)
U = Y / 4 V = Y / 4
所以YUV420 数据在内存中的长度是 width * hight * 3 / 2(即一个YUV是1.5个字节),所以计算采集的数据大小:width * hight * 1.5*frame*time
以720×488大小图象YUV420 planar为例,
其存储格式是: 共大小为720×480×3 × 1.5字节,
分为三个部分:Y,U和V
Y分量: (720×480)个字节
U(Cb)分量:(720×480 × 1/4)个字节
V(Cr)分量:(720×480 × 1/4)个字节
三个部分内部均是行优先存储,三个部分之间是Y,U,V 顺序存储。
即YUV数据的0--720×480字节是Y分量值,
720×480--720×480×5/4字节是U分量
720×480×5/4 --720×480×3/2字节是V分量。
一般来说,直接采集到的视频数据是RGB24的格式,RGB24一帧的大小size=width×heigth×3 Bit,RGB32的size=width×heigth×4,YUV标准格式4:2:0 的数据量是 size=width×heigth×1.5 Bit。
在采集到RGB24数据后,需要对这个格式的数据进行***次压缩。即将图像的颜色空间由RGB2YUV。因为,X264在进行编码的时候需要标准的YUV(4:2:0)。
经过***次数据压缩后RGB24-YUV(I420)。这样,数据量将减少一半,经过X264编码后,数据量将大大减少。将编码后的数据打包,通过RTP实时传送。到达目的地后,将数据取出,进行解码。完成解码后,数据仍然是YUV格式的,所以,还需要一次转换,就是YUV2RGB24。
3.4)关于IOS
做过iOS硬解码的都知道,创建解码器时,需要指定PixelFormatType。IOS只支持NV12也就是YUV420中的一种,你搜索420,发现有四个,分别如下:
kCVPixelFormatType_420YpCbCr8Planar
kCVPixelFormatType_420YpCbCr8PlanarFullRange
kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange
kCVPixelFormatType_420YpCbCr8BiPlanarFullRange
根据表面意思,可以看出,可以分为两类:planar(平面420p)和 BiPlanar(双平面)。
还有一个办法区分,CVPixelBufferGetPlaneCount(pixel)获取平面数量,发现kCVPixelFormatType_420YpCbCr8Planar和kCVPixelFormatType_420YpCbCr8PlanarFullRange是三个两面,属于420p,iOS不支持。而kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange和kCVPixelFormatType_420YpCbCr8BiPlanarFullRange是两个平面。这就纠结了,到底用哪一个呢?
我查了官网资料,解释如下:
kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange = '420v',
kCVPixelFormatType_420YpCbCr8BiPlanarFullRange = '420f',
感觉除了亮度和颜色的范围不一样,没发现其它不一样的。还是纠结,后来查了神网,有人说WWDC视频有,网址:(大概在25:30‘)
解释如下:
但是我我还是不清楚,清楚的人请告知我一下。
然后我创建的时候分辨使用了kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange和kCVPixelFormatType_420YpCbCr8BiPlanarFullRange,视频播放出来没发现什么不一样,唯一不一样是计算的步长不一样。
比如:480*640
如果是:kCVPixelFormatType_420YpCbCr8BiPlanarFullRange
Y和UV的步长是512(采用了64字节对齐 非对齐的补0) Y的行宽是640,UV行宽是320
如果是:kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange
Y和UV的步长是480(实际长度,未补齐) Y的行宽是640,UV行宽是320
我采集的时候setPreset了,所以按照上面提示(但是我还是不是很理解),最后我项目里面还是选择了kCVPixelFormatType_420YpCbCr8BiPlanarFullRange。
nv21(yuv420sp)左右镜像翻转实现
yuv格式说明参考: 图解YU12、I420、YV12、NV12、NV21、YUV420P、YUV420SP、YUV422P、YUV444P的区别
输入数据是yuv,输出是flipyuv, uv分量是交替存储,uvsize刚好是height/2 * width, 下面的实现没有考虑stride的情况。
下面的实现加上stride参数
因为是nv21, yvu420sp格式,vstride实际上是vu数据一行的宽度(width + stride), ystride就是Y分量一行的宽度(width + stride)
ystride = width + stride
vstride = width + stride;
输入参数h,w是输入图像的实际宽和高,矩阵的rows = h+h/2, cols = ystride,ystride大于等于w.
关于nv21和nv2101的介绍到此就结束了,不知道你从中找到你需要的信息了吗 ?如果你还想了解更多这方面的信息,记得收藏关注本站。