龙芯爱好者的日常!
返回

Guee 录屏机 开发日记

2020-09-15 70 0

程序及使用说明下载


# GueeRecorder (Guee 录屏机) 前言

这是一个为了学习Linux下的应用程序开发,而编写的一个实验性的对屏幕和摄像头录像,然后保存为视频文件或直播到网络的软件。

这是我第一次在Linux上开发的软件,在此之前我从未实践过Linux下的软件开发,甚至于在购买基于国产CPU龙芯3A4000的电脑之前,我对Linux系统的累计的使用时间大概也只有几天。

2020春节期间,在快递把龙芯3A4000送到之后,尝试编译了一款名为“SimpleScreenRecorder”的软件,但它的功能太简单,并且由于源码中对x86有大量SIMD汇编优化,但龙芯却只能使用兼容的C++代码,在龙芯CPU上的性能表现也就有些不堪。我数年前开发过Windows平台下的录屏软件,不过那是公司的产品,各种功能实现与Windows及x86也关联得较深,无法直接移植,于是我就萌生了在直接龙芯平台上重新开发一款录屏软件的想法。只是我也知道最大的性能瓶颈是视频编码库没有优化,可我能力有限,能够控制的只是把图像送入视频编码库之前的代码。但我还是想要尝试一下,性能优化有困难,但是在功能方面做得比它完善一些,应该不难。虽然我知道同类软件中有个大名鼎鼎的OBS,我预计要完成的功能只是OBS的子集,但作为第一次在Linux上开发的程序,只要能把预计的功能完成,并且在龙芯平台上的运行效率能稍高于SimpleScreenRecorder,那就是胜利。

然后一边学一边做大约花了半个月时间写了一些基础的代码,只是由于众所周知的原因,不久后孩子开始上网课,公司也要求远程工作,于是每天疲于奔命,就中断了开发。后来虽然稍有了一些空闲时间,但每天琐事仍然很多,自造轮子这种不太紧要的事情也就一直没有重新拾起。在连续的繁忙之后,每天颓废得连上网水帖看新闻都没有精力,开发中断之后,龙芯的电脑我都有半年没有开过机。

本来很怀疑这个软件又会像我以往的众多半成品一样,一旦开发过程被打断,就会永远躺在硬盘里成为一个归档文件。但这毕竟是我第一次在龙芯电脑上开发软件,还是不愿就这么半途而废。即使只是为了熟悉Linux下应用软件开发,我也应该把它完成。近期工作生活都逐渐像疫情前那样按步就班有了条理,因此我决定继续开发这个软件。由于这个软件总体上算是学习过程中的实验品,无论功能、界面还是代码等都感觉有点凌乱,因此打算在把它完成之后,再重写所有的代码,继续提高软件的性能和完善软件功能,还需重新设计软件界面。大概,未来计划中的2.0版才会是令我自己基本满意的作品。



# 开发日记(日期逆序):

2020-09-25

现在选窗口时,窗口外框的绘制不会闪了,我两三天的空闲时间居然都在改这个小bug。XWindows的API真难理解,数量很多,文档却不如MSDN详尽,遇到问题想找个例程参考参考都很难找到。不同的窗口管理器有不同的实现,一点儿也不统一,难怪Linux上的桌面程序远远不如Windows上花哨——常规窗口都可能不兼容,玩花活太容易死翘翘。直到现在为止,我取窗口标题文字都还没有完全成功,试了几种API,仍然有些窗口莫名其妙取不到。

层管理窗口放在预览界面中似乎有点影响操作,我把它移出来了。

周末打算看看Xcomposite,又是一个靠谱的例程都没有找到,大概得去翻OBS的源码了。

今天暂时不打测试包,等把 Xcomposite 搞定了再一起打包。


2020-09-21

这个周末修改的bug有点多,所以改完之后就我直接把版本号改成 beta 了。接下来重点要修改的bug,是选取屏幕窗口时绘图闪烁的问题。之后继续测试看看还有没有其它bug,然后就可以继续添加功能了。

另外我测试了一下OBS在龙芯上的表现,在龙梦Fedora28上,仅仅把屏幕加入了预览画面,它就占满了一个CPU核,预览画面的绘制帧率只有5fps,说明不但没有对龙芯优化,实际表现甚至是负数。我的程序本身也没有对任何CPU进行针对性优化,但至少性能表现还算是正常水平吧,目前稍稍领先于也没有针对性优化的SimpleScreenRecorder。不过我从OBS中的窗口捕获中学了个新名词:Xcomposite,捕获的窗口画面不会被桌面其它窗口覆盖,目前我还不知道这是什么,不过相信过一段时间我也会使用这种方式捕获窗口画面,抛弃掉现在通过桌面区域捕获窗口画面的方式。

下面是这两天修改的内容:

  1. 改进了内部的数据处理,降低了从GPU取出图像耗时对编码帧率的影响;

  2. 改进了屏幕截图的时间控制,时间戳更均匀,播放效果更流畅;

  3. 修改了写成mp4文件时,有几率造成某些播放器播放视频时旋转了一定角度显示的bug;

  4. 排除了录制鼠标时的内存泄露,以及视频帧缓冲时的内存泄露;

  5. 增加了对视频编码的B帧支持,以及相关设置界面;

  6. 修改了码率控制方面的bug,以及相关设置界面;

  7. 设置界面中改进了分辨率设置,增加了"-"/"+"两个接钮,每按一次就自动贴近常见的标准分辨率。

  8. 视频编码设置界面中增加了部分Tooltips文字,鼠标移上去显示相关说明。


2020-09-18

前两天在 loongnix 下测试了龙芯优化过的 x264 编码库,确实能提高近一倍的编码性能。但是由于它是在 loongnix 上的,在 UOS 并没有。我试过直接复制二进制文件到 UOS 中动态加载,但并不能很好地运行,编码出的视频数据有错误,如果想在 UOS 上正常使用,可能必须要用龙芯优化过的源码在 UOS 上重新编译。

另外修改了一些 bug,比如在 loongnix 上录音时程序会崩溃,然后发现是某处内存访问越界造成的,而在 UOS 这个问题没有暴露出来,说不定什么会崩溃。还有一处线程同步死锁,还有编码 B 帧会导致写入视频文件的时间戳顺序错误等问题,测试次数太少还真不容易发觉。现在程序应该是比较稳定了,毕竟我这几天并没有白折腾。


2020-09-14

目前程序功能已经基本完成,还有一些已知的bug没有修改。后续的其它功能添加,还有些问题需要考虑。

今天先学学在Linux下怎么给应用程序打包,先发出去找人用一用再说。


2020-09-13

为了解决昨天发现的录制麦克风时,数据的真实采样率不正确的问题,简单写了段重采样代码,然后发现问题又变了。实际采样率变成了设置值的2倍,正在调试的时候,情况再变,只是重启了一下电脑,这个bug就不复现了。我发誓我真遇了这种诡异的系统级bug,我的代码没有问题,用其它的录音软件甚至无法录音,Qt的录音库也应该没有问题,但它就是发生了,然后又消失了!!!

……数小时之后,音频采样的数据只有900Hz左右的问题又莫名出现了,重采样代码还是用上了。另外,当音频的实际采样率是设置值的两倍时,并不存在有效数据,此时在UOS系统的音频设置中也检测不到麦克风的音量。由于通过时间和数据量计算采样率并不是十分准确,我的重采样代码也是简单的线性插值,因此当麦克风异常时,录音效果并不好。等把各种功能的逻辑调通了,没有其它问题了,再来改进音频重采样的算法。


2020-09-12

写完了录音代码后,自我感觉代码逻辑没有问题,但录音只能录电脑播放的声音,录麦克风总是不对。然后发现一个天坑……估计这也是我测试几款软件在UOS@Loongson(龙梦A1901主板)上都录不到音原因。

在龙芯上,录Micphone时,获得的音频数据有问题。比如设置为 11025Hz 采样时,实际获得的音频数据只有 900Hz 采样。设置为 22050Hz 时,则是 1800Hz 采样……44100Hz 的实际采样率就是 3600Hz 了。但是,也不是总是这样,偶尔又能得到正确的采样率的数据,这令我很迷茫!!!

另外测试了USB麦克风,这个采样是正常的。写代码初步测试时没有发现这个问题,当时只检测了有没有声音数据,后来发现录下的声音总是不正常,才去统计了数据长度。为了确认集成声卡录音是采样率的问题,我把声音写成 wav 文件,然后用音频编辑工具更改回放速率,然后听到了基本正常的声音,说明确实是获得的录音数据采样率不对,这么低的声音采样率,居然以正确的速率回放时还基本清晰,我也觉得很神奇。

看来这至少是个系统级的bug,我无能为力,只是尽量在应用层面进行改善,之前我以为不需要做的声音重采样需要加上了,而且必须先计算录音数据的真实采样率再重新采样。


2020-09-10

做完了录音功能相关的设置及控制界面,已经可以录到声音,但没有完成时间同步和音频编码。我想要分别录制电脑回环声音和麦克风输入的声音,进行混音后再进行AAC编码,并且录像过程中可以随时对两路录音单独进行开关,对音频流的时间同步控制就会比较麻烦。从实验结果来看,声音重采样似乎不需要做,混音也可以做得比较简单。只是白天上班,晚上暴肝,开发效率低于预计,希望明天能把录音功能做完。


2020-09-07

决定把编码画面时间戳误差较大的问题放到以后再改善,先把录音的功能加上。今天用SimpleScreenRecorder测试了ALSA、PulseAudio、JACK几种接口的录音,发现UOS@AMD64上默认情况下只有ALSA能录到声音,而在龙芯上则什么声音都录不到。Qt中应该也是用的ALSA的录音方案,于是翻看Qt的例子代码,打算就直接用Qt的库做录音功能了。但是录音如果采样率与音频编码库及视频文件格式的要求不匹配,还是要自己写一段音频重采样的代码。


2020-09-06

今天继续修改昨天没改完的问题,目前剩下的最严重的问题是画面运动不平顺。由于程序设计为屏幕截图只是画面来源之一,可以随时添加删除,因此画面渲染线程和屏幕截图线程都有独立的帧率控制,以渲染线程的时间作为视频帧的时间戳,而渲染线程只有在图像来源的内容有变化后,且在帧间时间间隔到达后,才会绘制一帧画面送到编码器,这样帧时间戳就与实际的截图时间不一致,并且每帧的时间差距都可能不同。由于帧间时间不平均,造成看起来视频不流畅。可是由于画面内容可以随时增删,帧时间就不能以屏幕截图时间为准备,可能需要对内部的流程做些调整。

今天还和SimpleScreenRecorder简单对比了一下性能。虽然我的程序对图像的处理流程要复杂很多,但在龙芯平台上我的程序效率仍然略高一点。但在x86(i5-4460@3.2GHzx4) UOS上SimpleScreenRecorder的CPU占用率要比我的程序低十个百分点。因为两者使用相同的x264库文件,编码参数也尽量一致,性能差距就只发生在视频编码之前。证实了我以前的判断,因为它对龙芯CPU没有任何优化,所以即使简单的颜色空间转换,也比我更复杂的处理流程消耗了更多的CPU时间。我以前测试过用SSE计算1080@30fps的RGB to YUV 转换,i5级别的CPU消耗在1%~2%之间,未优化的C++直接计算则需要10倍甚至更多的CPU时间。另外还有x264编码库的性能更是瓶颈,代码优化和未优化达到几倍的性能差距很常见,取决于优化的程度,有的程序达到几十倍的性能差距也不罕见。我在龙芯开发者社区看到Loongnix系统中有龙芯优化过的x264库文件,可惜作为Linux新手的我没能在Loongnix成功配置Qt的开发环境,暂时试验不了龙芯优化过的x264编码库有多少性能提升。


2020-09-05

之前对 QWaitCondition 的理解有误,造成编码线程偶尔出现一直 wait 的情况,用惯了 Windows 的 SetEvent 造成了认知障。

设置界面初步搭建完成,然后暴露出许多bug,比如修改分辨率造成重新计算图像绘制坐标时出现混乱,以及预览区域绘制错误。然后发现编码生成的视频文件也有许多问题,时间戳计算有误,画面运动不平滑。还有之前设计的用OpenGL把RGB转换到YUV420也发现结果不正确,是因为奇数分辨率没有处理好,以及行字节没有对齐的原因。


2020-09-04

把OpenGL渲染合成的画面绘制另一个FBO,使用着色器完成了RGB到YUV(I420)的转换,从FBO中取出数据就可以直接送往x264编码器了。

以前在Windows下写过一个从TS/MP4文件提取H.264流,并重新封装为其它文件格式的小工具,现在把写文件相关的代码拿到这个项目中,进行了一些修改,已经整合完成。屏幕、摄像头画面合成->编码为H.264流->保存为FLV/MP4文件的整个流程已经调通,但暂时还是没有音频。

接下来需要完成的是视频编码设置界面,当前连分辨率和帧率都是直接写在代码中,没有设置界面这个软件就没法正常使用。


2020-08-31

把本项目上传到GitHub,并补上日志记录开始过程。

对摄像头数据的处理,是把YUYV数据放入OpenGL纹理,在着色器中转换为RGB再用于渲染,不使用CPU计算。

由于对Linux录音完全不了解,打算先把画面编码为h.264之后再增加录音功能。另外打算把合成的画面渲染到FBO时做一些处理,最好是从FBO取出就是I420的数据,可以直接送到x264编码器编码视频。


2020-08-29

开发环境换回到真机,还是在龙芯3A4000上开发,只是操作系统从Fedora28换成了UOS,不是Fedora28不够好,只是UOS更漂亮,顔值即正义。

验证了Qt支持的数种获取摄像头数据的方法,决定还是取得YUYV原始数据,自己再处理为RGB,我认为这样会有更高的效率。


2020-08-27

实验增加录制摄像头功能。并把较简单的对图像文件的支持加上。

实验录音功能,由于对Linux了解太少,暂时没有头绪,Qt自带的录音类感觉效率有点低。

实践证明在x86+Win10+VMWare+UOS的环境中,摄像头功能和录音功能都跑不通,决定不再尝试在虚拟机中开发。


2020-08-25

注册统信UOS开发者身份成功,下载统信UOS继续折腾操作系统,最后在硬盘上安装了3个操作系统。

在x86笔记本Win10下,尝试在VMWare中安装UOS,然后把项目放入虚拟机,把现有功能调通。


2020-08-23

折腾操作系统,做乱七八糟的实验。反反复复轮流重新安装Fedora28和Loongnix。


2020-08-22

中断了半年的开发继续开始,决定晚上不上网刷帖灌水,尽量抽出时间完成这个软件。

由于上次中断开发时,正在对一些功能进行调试,于是程序重新运行起来什么都不对。梳理了一遍代码,看懂了自己半年前写的东西,重新把已有的功能跑通。


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

开发中断6个月+

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


2020-02-15 左右

公司复工,远程上班,加上孩子网课和作业,精力耗尽,开发中断。

此时完成了在预览界面中编辑图层,以及对其它一些功能的完善。


2020-02-10 左右

开始陪伴孩子上网课,自由时间锐减。

基本完成主界面搭建、选择截图区域的界面、屏幕截图、帧率控制、图像合成和预览、基本的图层管理等。

这段时间的开发,Qt的跨平台特性作用很大。另外就是学习了x11的一些API,完成了屏幕载取相关功能。

虽然使用的截图API与SimpleScreenRecorder这款软件使用的相同,但我对截图数据的缓存和使用方式和它不同,应该更有效率一些。

x11截屏性能不高,可我对Linux还不熟,暂时没有找到其它的截屏相关的技术资料,打算以后读一读OBS的代码,看看它有没有什么不同。


2020-02-01 左右

项目开始。初始开发环境:龙芯3A4000 + 龙梦Fedora28 + Qt5.x。

我把龙芯3A4000电脑原配的AMD R5 230显卡更换成了AMD RX580,龙芯官方的loongnix系统暂时不能驱动它。相对来说龙梦Fedora28对个人用户更友好,虽然对各种办公设备的驱动可能不如loongnix完善,但对个人电脑常见的硬件能够支持得更好一些。


顶部