查看原文
其他

10bit YUV 数据在内存中的存储格式

张晖 字节流动 2022-04-23

我们知道为了获得更好的动态范围,除了常见的 8bit yuv 外,还有 10bit,16bit 这样的yuv 数据。


8bit 的 yuv 数据还好理解,每一个像素 8bit ,在内存中自然也就是一个字节一个字节的存储咯,16bit 的也类似,每一个像素对应两个字节,在内存中存起来也非常方便,那么10bit 呢?


在不做任何调查的情况下,我们可以凭直觉猜想有两种存储方式:


  • 1.每个像素依然占用 16bit 两个字节,但是其中 6 个 bit 是 padding ,补 0 ;

  • 2.每个像素实打实地占用 10bit ,各个像素交织在一起,没法整齐地分布在字节中。


第一种方式便于运算处理,但是有存储冗余,第二种方式则没有冗余,但是计算起来就很麻烦了


事实上,10bit是采用第一种方式存储在内存中的,也就是说,为了高动态范围,牺牲了一点压缩效率,但也获得了运算性能的加成,大概就是多媒体技术里无处不在的 trade off了。


下面来详细说说是如何存储的,并且以实例进行验证。


参考这里的文档:

Google 搜索:10-bit and 16-bit YUV Video Formats


可以得知10bit yuv数据在内存中的存储格式如下图所示



而8bit像素数据是如何转换为10bit像素数据的呢,根据SMPTE 274M标准,就是乘上一个系数2^(n-8),这里的n就是位深,也就是10或者16,所以如果要把8bit yuv数据转成10bit,就是乘4,即左移两位。


下面验证一下:

使用如下命令将8bit yuv转为10bit


ffmpeg -s 240x120 -i test.yuv -pix_fmt yuv420p10be test10.yuv


这里的 yuv420p10be 即10bit yuv420p 大端 格式。各种像素格式可以用如下命令列出


ffmpeg -pix_fmts


首先我们发现的一件有意思的事情就是原来的 test.yuv 文件大小为 1055KB,转出来的test10.yuv 的大小正好是它的 2 倍,2110KB。验证了每像素16bit的说法。


再用UltraEdit看看每个像素的2进制数据

在test.yuv中的第一个Y的2进制数据如下


1001 0010


在 test10.yuv 中对应的样点的 2 进制数据如下


0000 0010 0100 1000


可以看到,在原来的基础上左移两位,后面补上两个 0,这是实际的 10bit 数据,前面再补上 6 个 0 ,是 padding 位。


最后介绍一个可以播放10bit yuv流的播放器YUV Player:

https://sourceforge.net/projects/raw-yuvplayer/


最后需要说明的是,以上都是软件解码时的情况,硬件解码时的情况可能有所不同。


————————————————

版权声明:本文为CSDN博主「zhanghui_cuc」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。

原文链接:https://blog.csdn.net/nonmarking/article/details/64173611


-- END --


进技术交流群,扫码添加我的微信:Byte-Flow



获取视频教程和源码


推荐:

Android FFmpeg 实现带滤镜的微信小视频录制功能

全网最全的 Android 音视频和 OpenGL ES 干货,都在这了

一文掌握 YUV 图像的基本处理

您可能也对以下帖子感兴趣

文章有问题?点此查看未经处理的缓存