| |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
-> 游戏开发 -> Scrcpy源码的阅读及在Ubuntu上的实现(二)——获取手机屏幕yuv数据 -> 正文阅读 |
|
[游戏开发]Scrcpy源码的阅读及在Ubuntu上的实现(二)——获取手机屏幕yuv数据 |
之前在使用scrcpy的时候走了不少弯路,但是也加深了自己对scrcpy的理解吧,那么现在就开始实现功能: 在运行scrcpy的时候可能会遇到这个问题: 先运行这个:
?这一步的编译看似没有什么问题,他会在scrcpy/x中生成如下文件: 但是你们打开后可以发现server文件中是空的,少了一些文件,并且在执行ninja -Cx中会遇到:
可以看到的是,我们在meason的时候并未加入scrcpy-server这个文件,并且本机并没有Android_SDK_ROOT。 由于我是真机调试,我不需要下载安装AndroidSDKROOT,具体安装步骤可以参考:Linux : ubuntu 安装Android SDK_孙战磊的博客-CSDN博客 0x01 重新开始
0x02 通过scrcpy获取手机屏幕的yuv数据先想实现其功能,那么先阅读一下scrcpy的官方文档:https://github.com/Genymobile/scrcpy/blob/master/DEVELOP.md,在下载的源码中也有对应的文档。 摘取要点:
FFmpeg的解码流程:
看到这应该就可以推测出在项目的文件中哪些是获取yuv数据的。回到scrcpy中,所有FFmpeg流程的文件在scrcpy/app/scr文件中。? ?yuv数据都是通过解码器解码后生成的,自然就要从decoder.c文件入手。而且我们也知道解码器解码生成的yuv数据放入了AVFrame中,那就直接在文件中找到有关AVFrame的字眼就可以找到yuv数据了。 ? 在提取yuv数据之前,我们需要去了解yuv数据的存储方式。 YUV和RGB一样,都是像素数据的编码格式,一组YUV渲染屏幕上的一个像素,控制屏幕用色彩的形成将事物表现出来,其中Y表示像素中的亮度,U表示的是色度,V表示的是Chroma。这是一种压缩后的颜色表示方法,占用更少的物理空间,且对颜色的表现失真不明显,所以现在非常常用,很多视频在播放时都是使用这种形式展现的。 YUV的宏观存储方式:planar、packed。
采样方式: 主流有三种采样方式,按照分量比例区分。
因为人的眼睛对色度和饱和度不是特别敏感,所以一定程度上丢失一部分UV并不影响我们分辨颜色,所以为了节省存储空间,在存储时就故意丢掉部分UV分量。
在存储时YUV各占一个字节Byte,如果4:4:4方式,那么一个256 * 256分辨率的图片要占用256 * 256 * 3 = 196608Byte;4:2:2方式要占用256 * 256 * 2 =131072Byte;4:2:0方式要占用256 * 256 * 2/3 = 43690.7Byte,他的存储空间整整少了一半。 YUV与RGB相互转换的公式
在考虑读取yuv文件的时候,还需要考虑一下内存对齐的问题,这样才有利于我们编写读写程序: 内存对齐的原因: 计算机是以字节(Byte)为单位划分的,理论上说CPU是可以访问任一编号的字节数据的,CPU的寻址其实是通过地址总线来访问内存的。CPU又分为32位和64位,在32位的CPU一次可以处理4个字节(Byte)的数据,那么CPU实际寻址的步长就是4个字节,也就是只对编号是4的背书的内存地址进行寻址。那么同理对于64位的CPU的寻址步长是8字节,只对编号是8的倍数的内存地址进行寻址。这么做的好处也就是可以实现最快速的方式寻址且不会遗漏一个字节,也不会重复寻址。 那么为什么要内存对齐? 如果对于一个程序来说,如果一个变量的数据范围是在一个寻址步长范围内的话,那就一次寻址就可以解读完了。那么如果超出了步长范围的数据存储,就需要读取两次寻址再进行数据的拼接,效率明显就是降低了。如果我们的数据类型,没有按照内存规则进行排放,那也会造成资源的浪费以及效率的降低。数据对齐的规则,就是将数据尽量的存储在一个步长内,避免跨步长的存储,这就是内存对齐。在32位编译环境下默认4字节对齐,在64位编译环境下默认8字节对齐。归结下来就是以下这两点: (1)移植原因:不是所有的硬件平台都能访问任意地址上的任意数据的;某些硬件平台只能在某些地址处取某些特定类型的数据,否则抛出硬件异常。 (2)性能原因:数据结构(尤其是栈)应该尽可能地在自然边界上对齐。原因在于,为了访问未对齐的内存,处理器需要作两次内存访问;而对齐的内存访问仅需要一次访问。 内存对齐规则 每个特定平台上的编译器都有自己的默认对齐系数,程序员可以通过预编译指令#pragma pack(n),n=1,2,4,8,16来改变这一系数,其中n就是你要指定的“对齐系数”。
那么当#pragma back的n值等于或超过所有数据成员长度的时候,这个n值的大小将不产生任何效果。 总结的来说,内存对齐就是利用空间去节约时间。 0x03 获取yuv图像我们可以将得到YUV图像的代码进行修改,下面是源代码:
获取yuv图像:
?将这段代码添加到那段代码的前面,再次运行scrcpy的可执行文件。 因为我们修改了app中的scr文件,所以我们要重新按照上面的编译过程进行编译,我就新建了另外一个build_1。 之后我们就可以成功得到我们所需要的yuv数据啦!! |
|
|
上一篇文章 下一篇文章 查看所有文章 |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
360图书馆 购物 三丰科技 阅读网 日历 万年历 2025年1日历 | -2025/1/16 19:07:51- |
|
网站联系: qq:121756557 email:121756557@qq.com IT数码 |