认识 YUV
什么是 YUV
YUV是一种颜色编码格式,可以说YUV流媒体是原始流数据,大部分的视频领域都在使用。与RGB类似,但RGB更多的用于渲染时,而YUV则用在数据传输,因为它占用更少的频宽。当然,实时通讯为了降低带宽都会采用H264/H265编码。YUV的含义:Y代表亮度信息(灰度),UV分别代表色彩信息。YUV的常用名称有许多,例如YUV422、YUV420、YUV444等。
采样格式
YUV 后面常带着三个数字,其含义代表 YUV 信息在像素点中的分布状况,也就是采样格式:
YUV444 代表每个 Y 对应一组 UV,每个像素占3个字节。
存放码流:Y0 U0 V0 Y1 U1 V1 Y2 U2 V2 Y3 U3 V3YUV422 代表每 2 个 Y 对应一组 UV
存放码流:Y0 U0 Y1 V1 Y2 U2 Y3 V3YUV411 代表每 4 个 Y 对应一组 UI
存放码流:Y0 U0 Y1 Y2 V2 Y3YUV420 代表每个像素独有一个 Y,每四个像素共享一个 U,每四个像素共享一个 V
以 YUV420 为例,Y 数据有效字节数为=Height×Width;U数据有效字节数=(Height/2)×(Width/2);V数据有效字节数=(Height/2)×(Width/2);
YUV420 是一类格式的集合,包含 I420、NV21 等不同格式,格式不同,YUV 的排列顺序也不同(Y 的顺序是一样的,UV 不一样)。官方将 YUV 三个平面都称为颜色平面(color plane)。Android 中使用 ImageProxy
的 getPlanes()
方法可得三个平面。
NV21 是,planes[1] 是 UVU,planes[2] 是 VUV。
NV21 存储的 UV 数据是有冗余的,取 planes[1] 每一排的奇数字节可得所有 U 数据,取 planes[2] 每一排的偶数字节可得所有 V 数据。
存储方式
上面提到的 planes 是平面的,YUV 存储在三个独立的数组中。还有另外一种存储方式:packed(打包的),YUV 是连续交错存储的。
例如 YUY2 就属于 packed 类型,数据以第一个字节存放 Y0,第二个字节存放 U0,再 Y1、V0、Y1 等等,每四个字节,Y0 和 Y1 共用 U0、V0 分量,依次类推。
YUV 图像显示
显示 YUV 图像需要使用 OpenGl 库调用 GPU 资源。或者先将 YUV 图像转换为 RGB 图像。Android 提供了 YuvImage
将 YUV 数据转换成 jpeg 的方法,目前只支持 NV21 和 YUY2。这里编写一段测试代码眼见为实。
先使用 ffmpeg 将 jpeg 图片转为 NV21 格式用于测试:
ffmpeg -i icon.jpg -s 960x960 -pix_fmt nv12 nv12.yuv
得到 yuv 格式图片 后,存放到手机目录下,然后编写测试代码:
val file = File(Environment.getExternalStorageDirectory().path + "/1dev/nv21.yuv")
if (file.exists()) {
try {
//从本地读取 yuv 图片字节数据
val fileInputStream = FileInputStream(file)
var data = ByteArray(fileInputStream.available())
fileInputStream.read(data)
fileInputStream.close()
//测试图片分辨率
val width = 960
val height = 960
//将 yuv 图片字节数据存放到 YuvImage 中
var yuvImage = YuvImage(data, ImageFormat.NV21, width, height, null)
val out = ByteArrayOutputStream()
//使用 compressToJpeg 将存储的 yuv 数据转化为 RGB 图像
yuvImage.compressToJpeg(Rect(0, 0, width, height), 50, out)
val imageBytes = out.toByteArray()
val bitmap = BitmapFactory.decodeByteArray(imageBytes, 0, imageBytes.size)
iv.setImageBitmap(bitmap)
} catch (e: FileNotFoundException) {
e.printStackTrace()
}
}
获得 bitmap 后就可以使用 ImageView 显示了。
到这里其实还只是 api 层面的使用,后续还应该深入了解 YUV 到 RGB 的转换原理。另外 YUV 视频渲染、OpenGL es 的使用等,后续再学习记录~
最新文章
- ActiveMQ(li)
- org.apache.catalina.LifecycleException: Failed to start component [StandardEngine[Catalina].StandardHost[localhost].StandardContext[/pcisv7]]
- videoconverter转换
- ASP.NET IIS设置 Session时间
- MySQL OnlineDDL
- React入门1
- hdu2125(数学)
- 搭建属于你自己的RAMOS系统 – WIN7+VHD+GURB map方式
- hdu_1030(数学题+找规律)
- hi3531的i2c部分
- springboot情操陶冶-web配置(三)
- #8 Python网络编程(一)
- mysql常用的统计类sql ,以及批量循环插入数据
- git命令设置简写(别名)
- 3. Tensorflow生成TFRecord
- Codeforces Round #265 (Div. 2) E. Substitutes in Number
- Hibernate与MyBatis的对比
- 微信redirect_uri 回调错误,scope权限错误
- hdu 5035 指数分布无后效性
- Linux服务器快速安装可视化桌面且可以远程RDP远程连接
热门文章
- 手撕HashMap
- VS Code C++ 项目快速配置模板
- 软件安全----警惕缓冲区溢出(C中那些不安全的库函数)
- Asp.NetCore之AutoMapper基础篇
- JZOJ2020年8月11日提高组T4 景点中心
- 重要消息:MoviePy v2.0.0.dev1预发布版本已经可以下载安装使用
- moviepy音视频剪辑:音视频的加载和输出
- PyQt(Python+Qt)学习随笔:布局控件layoutStretch属性
- HBase的基本使用(安装配置、启动关闭、hbash shell的基本操作、phoenix、实战)
- c++如何按照map的value进行排序?