3. 野火demo 运行

前两章讲了野火demo的几种编译方式和野火demo的打包发布,这里讲讲野火demo的运行和运行环境。

野火demo主要是为LubanCat提供的关于Qt的应用示例,主要的运行环境还是ARM平台。

野火官方会提供能在ARM平台运行的debian系统,每个版本的系统镜像,又有两个小本版,一个是纯镜像,一个带了野火的Qtdemo。

版本命名和区分如下:

  • xxx-lubancat-carp-console-armhf-xxx.img

  • xxx-lubancat-carp-qt-armhf-xxx.img

第一个是纯镜像,第二个是带野火demo的镜像,镜像里包含了裁剪过的Qt库。

3.1. Linux中的图形显示

LubanCat运行的系统是linux的一个分支,图形图像的显示也是一脉相承。

我们先谈谈Linux中图形图像的显示所涉及的知识。整个框图如下所示:

display001
display002

如上图所示,所涉及到知识非常的庞杂,所以我也只能点到为止。 更多的图形相关的知识还有待补充,笔者也还在学习。

3.2. Debian 环境处理

LubanCat的系统属于 Debian 系统的buster发行版, buster 发行版是 Debian 最新的版本, Debian 拥有最多数量的已安装软件包(当前为 59000)。其软件包使用 deb 格式,该格式以其高质量著称。 我们可以通过 apt install 来安装我们需要的软件包。

野火demo 是使用 Qt5开发的,其运行势必会依赖Qt5的库,demo会使用到触摸屏和声卡,所以相关的库也是必须的。 像上面图形图像所提及的Wayland和eglfs,或者音视频相关的ffmpeg和gstreamer则又会依赖其他的软件包。

我们就以一个纯净的Debian系统作为示例来演示野火demo运行环境的搭建(这个纯净的Debian要适配LubanCat)。

3.2.1. 手动搭建

以下过程以使用EMMC核心板的开发板和使用lubancat-carp-console镜像时为例。

第二章,我们已经打包出来一个野火demo的deb安装包:ebf-qtdemo_1.0.0.0_armhf.deb。 我们将该安装包拷贝到纯净的Debian系统中,使用命令安装。

sudo dpkg -i ebf-qtdemo_1.0.0.0_armhf.deb

等待安装结束,我们会得到如下提示,由于是本地安装,无法补全依赖。

install_ebfdemo002

所以我们可以使用命令强制补全依赖,这样apt包管理工具,会自动将野火demo依赖的软件安装完。

sudo apt-get -f -y install
install_ebfdemo003

同样,我们也可以使用apt命令逐一安装依赖的软件包。

Qt5依赖

sudo apt-get install qt5-default

Qt5媒体库依赖

sudo apt-get install libqt5multimedia5
sudo apt-get install libqt5multimedia5-plugins

Gstreamer依赖

注意

  • 当使用上面描述的自动补全或者使用的是lubancat-carp-qt镜像时,默认安装的是ebf-gst库包,此为裁剪的gstreamer库,与下面命令安装的完整gstreamer冲突,不要再次安装下面,如果需要安装,先sudo apt remove ebf-gst。

  • 当使用NAND核心板的开发板时,存储容量小,使用ebf-gst库,不适合安装下面。

sudo apt-get install gstreamer1.0-plugins-base gstreamer1.0-tools gstreamer1.0-plugins-bad gstreamer1.0-plugins-good gstreamer1.0-alsa gstreamer1.0-libav

其他的一些依赖,其中devscan是用来扫描触摸屏的,检测当前触摸屏的类型,以便用于后面野火demo的启动配置;libts则是触摸屏相关的功能,alsa则是声卡相关的功能。

sudo apt-get install devscan,libts-bin,alsa-utils

等待上面的内容全部安装完毕,我们就可以尝试启动野火demo。 野火demo默认安装在usr/local/qt-app/这个目录,该目录下有个run.sh。 我们执行野火demo启动脚本。

sudo /usr/local/qt-app/run.sh

上面所安装的软件包是野火demo运行必要的依赖,也有可能会存在其他的问题,上面只做参考。

3.2.2. 在线安装

野火提供demo已经发布到我们维护的软件源,添加我们的源,即可通过apt安装。步骤如下:

更新软件源,让系统能够找到野火demo。

sudo vi /etc/apt/sources.list

在最后添加如下内容,这两个是野火维护的软件源地址。

deb [arch=armhf] https://cloud.embedfire.com/mirrors/ebf-debian buster main
deb [arch=armhf] https://cloud.embedfire.com/mirrors/ebf-debian carp-imx6 main

保存推出,并执行如下命令更新源

sudo apt-get update

安装野火demo

sudo apt-get install ebf-qtdemo ebf-gst
install_ebfdemo001

安装野火demo的时候,apt包管理工具会自动补全依赖。

这里安装了两个包,ebf-qtdemo和ebf-gst, 其中ebf-qtdemo包含了野火demo的主体程序和相关资源文件,还包括了我们有yocto构建出来的Qt库, ebf-get则包含我们用yocto构建出来的gstreamer相关的库。

ebf-qtdemo主体程序安装在目录 /usr/local/qt-app/ 裁剪安装的qt库在 /usr/lib/ ,qt用到的插件在 /usr/lib/plugins 裁剪安装的gst库在 /usr/lib/ /usr/bin/ 等等文件夹

使用apt安装的完整qt库在 /usr/lib/arm-linux-gnueabihf/qt5/ 插件在 /usr/lib/arm-linux-gnueabihf/qt5/plugins 由于两个版本的Qt安装在不同的位置,所以两个版本的Qt可以共存,使用某个版本Qt和Qt插件可通过环境变量指定。

而使用apt安装的gst库的安装位置会和我们的编译的gst冲突,所以两者只能选择其一(如果需要另外安装gstreamer库,需要先sudo apt remove ebf-gst),不过两者都能够正常工作, 只是自己编译的gst占用空间比较小。

3.2.3. 裁剪Qt库

通过apt的方式安装环境,最终镜像会比较大,安装的这些依赖大概在500M左右。

install_ebfdemo004

对于我们编写的应用程序来说,并不一定使用到了上述全部的依赖,大多时候只是一部分。比如我们可以通过ldd和strace这两个命令来查询依赖的库和文件。

ldd /usr/local/qt-app/App

执行这个命令就会得到下面的结果,如果列出来的库都存在,那么App就能运行。

install_ebfdemo005

在一些存储空间较小的设备我们就可以只要上述命令列出来的库,只要满足App运行即可,这便是库的裁剪。

库的裁剪,我们可以使用前面交叉编译的Qt库,拷贝我们需要的库到开发板。除此也推荐使用yocto。

Yocto项目(YP)是一个开源协作项目,可帮助开发人员创建基于Linux的自定义系统,而无需考虑其硬件体系结构。 该项目提供了一套灵活的工具和空间,全世界的嵌入式开发人员可以在其中共享技术,软件堆栈,配置和最佳实践,这些技术, 可用于为嵌入式和IOT设备或需要定制Linux OS的地方创建量身定制的Linux映像。

yocto在构建过程中会编译相关的库,我们只需要在最终的rootf里面挑选我们需要的库即可,yocto涉及的东西也比较庞杂,就不做展开。

3.2.4. 屏幕旋转

屏幕旋转的方法非常多。

从硬件来说,我们可以直接让显示屏驱动支持屏幕旋转; 从软件层的架构来说,我们可以让Qt的启动方式来支持屏幕旋转; 从应用来说,可以让应用支持屏幕旋转。

再鲁班猫上,我们通过软件层来实现屏幕旋转。

3.2.4.1. linuxfb

我们通过修改linuxfb插件驱动,让这种启动方式支持屏幕旋转。 只需要在最后加上旋转角度(0,90,180,270)即可。

具体参见 启动脚本 run.sh

rotation=0
export QT_QPA_PLATFORM=linuxfb:fb=/dev/fb0:rotation=$rotation

rotation 为我们的旋转角度。 同时我们还需要重新校准触摸屏,使用下面的命令校准。

#重新校准触摸屏
ts_calibrate -r x
x为 0-1-2-3 分别指角度 0-90-180-270

3.2.4.2. eglfs

eglfs本身支持屏幕旋转,通过参数QT_QPA_EGLFS_ROTATION来设置旋转角度。

#界面旋转角度 0,90,180,270
export QT_QPA_EGLFS_ROTATION=-90

具体参见 启动脚本 run_eglfs.sh

3.3. LubanCat运行demo

3.3.1. lubancat-carp-console

这个镜像除了底层的硬件驱动和必要的依赖,大致和Debian官方系统无异。

直接安装野火demo

sudo apt-get update
sudo apt-get install ebf-qtdemo

安装依赖,在线安装会自动安装依赖的软件包。

sudo apt-get install qt5-default

sudo apt-get install libqt5multimedia5
sudo apt-get install libqt5multimedia5-plugins

sudo apt-get install gstreamer1.0-plugins-base gstreamer1.0-tools gstreamer1.0-plugins-bad gstreamer1.0-plugins-good gstreamer1.0-alsa gstreamer1.0-libav

运行野火demo

sudo /usr/local/qt-app/run.sh

我们来看看run.sh这个脚本实现了什么样的功能。

#! /bin/bash

#设置屏幕旋转角度 默认不旋转
rotation=0
#检测屏幕设备文件 MIPI屏幕自动旋转90度
if [ -e "/sys/bus/platform/devices/5a000000.dsi/5a000000.dsi.0" ]; then
    rotation=90
fi

type devscan
#判断devscan是否存在,不存在提示安装
if [ $? -eq 0 ]; then
    #未检查到触摸屏则一直检测不启动app
    timeout=0
    while [ ! $eventx ]
    do
        #寻找名叫goodix-ts的触摸屏驱动
        eventx=$(devscan "goodix-ts")
        #没有找到则寻找Goodix Capacitive TouchScreen
        if [ ! $eventx ]; then
                eventx=$(devscan "Goodix Capacitive TouchScreen")
        fi
        #没有找到则寻找iMX6UL Touchscreen Controller
        if [ ! $eventx ]; then
                eventx=$(devscan "iMX6UL Touchscreen Controller")
        fi
        ########################################################
        # 添加你自己的显示屏驱动
        # 首先 sudo evtest  查看是否存在显示屏驱动
        # 存在添加类似于上面的判断 改为你自己的显示屏驱动名称
        ########################################################
        if [ $timeout -ge 5 ]; then
            break
        fi
        let timeout=$timeout+1
        sleep 1
    done
    #输出当前触摸屏驱动
    echo "eventx=$eventx"
    if [ "$eventx " != " " ]; then
        #指定触摸屏设备
        export TSLIB_TSDEVICE=/dev/input/$eventx
        #判断触摸屏校准文件是否存在,不存在则校准触摸屏,/etc/pointercal为触摸屏校准文件
        if [ ! -f "/etc/pointercal" ]; then
            type ts_calibrate
            if [ $? -eq 0 ]; then
                if [ $rotation -eq 0 ]; then
                    ts_calibrate -r 0
                elif [ $rotation -eq 90 ]; then
                    ts_calibrate -r 1
                elif [ $rotation -eq 180 ]; then
                    ts_calibrate -r 2
                elif [ $rotation -eq 270 ]; then
                    ts_calibrate -r 2
                else
                    ts_calibrate
                fi
            fi
        fi
        #同步QT默认的坐标轴和触摸屏的坐标轴
        #export QT_QPA_EVDEV_TOUCHSCREEN_PARAMETERS=/dev/input/$eventx:rotate=90:invertx
        export QT_QPA_EVDEV_TOUCHSCREEN_PARAMETERS=/dev/input/$eventx:rotate=$rotation
    else
        echo "eventx is null"
    fi
else
    echo "please install devscan"
    echo
    echo "sudo apt-get install devscan"
    exit
fi

#导出qtdemo的安装目录
export APP_DIR=/usr/local/qt-app
#指定qt插件路径
export QT_QPA_PLATFORM_PLUGIN_PATH=/usr/lib/plugins
#指定qt库路径
#export LD_LIBRARY_PATH=/lib:/usr/lib
#指定字体库
export QT_QPA_FONTDIR=/usr/share/fonts
#qt命令路径
#export PATH=$PATH:$QT_DIR/libexec
#指定显示终端
export QT_QPA_PLATFORM=linuxfb:fb=/dev/fb0:rotation=$rotation

#禁用QT自带的输入检测
#export QT_QPA_FB_DISABLE_INPUT=1
#TS配置文件
export TSLIB_CONFFILE=/etc/ts.conf
#TS校准文件
export TSLIB_CALIBFILE=/etc/pointercal
#触摸配置
export QT_QPA_GENERIC_PLUGINS=tslib:/dev/input/$eventx
#指定鼠标设备
export QWS_MOUSE_PROTO=tslib
#启用tslib支持而不是依赖于Linux多点触控协议和事件设备
export QT_QPA_EGLFS_TSLIB=1
export QT_QPA_FB_TSLIB=1

echo "start app..."
#运行App
$APP_DIR/App

里面的注释非常明确了,首先是扫描触摸屏设备文件,然后对触摸屏tslib进行配置。 当然里面也有指定Qt库、插件库、字体等等路径,若不使用则为默认路径。

最最重要的一点就是 export QT_QPA_PLATFORM=linuxfb:fb=/dev/fb0, 指定Qt以linuxfb的方式显示,输出设备为/dev/fb0。

最后就是执行App。

除了linuxfb的方式,该目录下还有run_eglfs.sh,这个脚本则是指定Qt程序以eglfs的方式显示。

#! /bin/bash

#设置屏幕旋转角度 默认不旋转
rotation=0
#检测屏幕设备文件 MIPI屏幕自动旋转90度
if [ -e "/sys/bus/platform/devices/5a000000.dsi/5a000000.dsi.0" ]; then
    rotation=90
fi

type devscan

#判断devscan是否存在,不存在提示安装
if [ $? -eq 0 ]; then
    #未检查到触摸屏则一直检测不启动app
    timeout=0
    while [ ! $eventx ]
    do
        #寻找名叫goodix-ts的触摸屏驱动
        eventx=$(devscan "goodix-ts")
        #没有找到则寻找Goodix Capacitive TouchScreen
        if [ ! $eventx ]; then
                eventx=$(devscan "Goodix Capacitive TouchScreen")
        fi
        #没有找到则寻找iMX6UL Touchscreen Controller
        if [ ! $eventx ]; then
                eventx=$(devscan "iMX6UL Touchscreen Controller")
        fi
        ########################################################
        # 添加你自己的显示屏驱动
        # 首先 sudo evtest  查看是否存在显示屏驱动
        # 存在添加类似于上面的判断 改为你自己的显示屏驱动名称
        ########################################################
        if [ $timeout -ge 5 ]; then
            break
        fi
        let timeout=$timeout+1
        sleep 1
    done
    #输出当前触摸屏驱动
    echo "eventx=$eventx"
    if [ "$eventx " != " " ]; then
        #指定触摸屏设备
        export TSLIB_TSDEVICE=/dev/input/$eventx
        #判断触摸屏校准文件是否存在,不存在则校准触摸屏,/etc/pointercal为触摸屏校准文件
        if [ ! -f "/etc/pointercal" ]; then
            type ts_calibrate
            if [ $? -eq 0 ]; then
                if [ $rotation -eq 0 ]; then
                    ts_calibrate -r 0
                elif [ $rotation -eq 90 ]; then
                    ts_calibrate -r 1
                elif [ $rotation -eq 180 ]; then
                    ts_calibrate -r 2
                elif [ $rotation -eq 270 ]; then
                    ts_calibrate -r 2
                else
                    ts_calibrate
                fi
            fi
        fi
        #同步QT默认的坐标轴和触摸屏的坐标轴
        #export QT_QPA_EVDEV_TOUCHSCREEN_PARAMETERS=/dev/input/$eventx:rotate=90:invertx
        export QT_QPA_EVDEV_TOUCHSCREEN_PARAMETERS=/dev/input/$eventx:rotate=$rotation
    else
        echo "eventx is null"
    fi
else
    echo "please install devscan"
    echo
    echo "sudo apt-get install devscan"
    exit
fi

#屏幕旋转
export QT_QPA_EGLFS_ROTATION=$rotation
# 指定显示平台插件
# QT_QPA_PLATFORM 或者-platform命令行选项指定其他设置
export QT_QPA_PLATFORM=eglfs
# 此环境变量强制执行特定的插件
# QT_QPA_EGLFS_INTEGRATION 设置为eglfs_kms将使用KMS / DRM后端
export QT_QPA_EGLFS_INTEGRATION=eglfs_kms
# KMS / DRM后端还通过JSON文件支持自定义配置
# QT_QPA_EGLFS_KMS_CONFIG 指定配置文件的路径
export QT_QPA_EGLFS_KMS_CONFIG=/usr/local/qt-app/conf/cursor.json
# 指定将current选择一种分辨率与当前模式匹配的模式
# QT_QPA_EGLFS_ALWAYS_SET_MODE
export QT_QPA_EGLFS_ALWAYS_SET_MODE=1
# 默认情况下,KMS后端将使用旧版API,但是您可以启用DRM原子API,
# 通过将QT_QPA_EGLFS_KMS_ATOMIC环境变量设置为1。
export QT_QPA_EGLFS_KMS_ATOMIC=1

#指定qt插件路径
export QT_QPA_PLATFORM_PLUGIN_PATH=/usr/lib/plugins
# Qt应用程序将在Qt的lib/fonts目录中查找字体,QT_QPA_FONTDIR环境变量来覆盖此目录
export QT_QPA_FONTDIR=/usr/lib/fonts

# 鼠标设备
# QT_QPA_EVDEV_MOUSE_PARAMETERS
export QT_QPA_EVDEV_MOUSE_PARAMETERS=abs
# 键盘设备
# QT_QPA_EVDEV_KEYBOARD_PARAMETERS
# 触摸屏设备
# QT_QPA_EVDEV_TOUCHSCREEN_PARAMETERS

# eglfs 禁用内置输入处理程序
# QT_QPA_EGLFS_DISABLE_INPUT
# export QT_QPA_EGLFS_DISABLE_INPUT=1
# linuxfb 禁用内置输入处理程序
# QT_QPA_FB_DISABLE_INPUT
# export QT_QPA_FB_DISABLE_INPUT=1

# eglfs 未设置时候,鼠标光标就会出现
# QT_QPA_EGLFS_HIDECURSOR
# linuxfb 未设置时候,鼠标光标就会出现
# QT_QPA_FB_HIDECURSOR

#tslib

#TS配置文件
export TSLIB_CONFFILE=/etc/ts.conf
#TS校准文件
export TSLIB_CALIBFILE=/etc/pointercal
export POINTERCAL_FILE=/etc/pointercal

export TSLIB_CONSOLEDEVICE=none
export TSLIB_TSEVENTTYPE=INPUT

# evdevtablet 插件为Wacom和类似的基于笔的平板​​电脑提供基本支持。
# QT_QPA_GENERIC_PLUGINS
# export QT_QPA_GENERIC_PLUGINS=tslib:/dev/input/$eventx,evdevmouse:/dev/input/$eventx

# eglfs 启用tslib支持
# QT_QPA_EGLFS_TSLIB
export QT_QPA_EGLFS_TSLIB=1
# linuxfb 启用tslib支持
# QT_QPA_FB_TSLIB
export QT_QPA_FB_TSLIB=1

#export DISPLAY=':0.0'
export QT_QPA_FB_DRM=1

# 开启调试
# export QT_LOGGING_RULES=qt.qpa.gl=true
# export QSG_INFO=1
# export QT_DEBUG_PLUGINS=1

#导出qtdemo的安装目录
export APP_DIR=/usr/local/qt-app
$APP_DIR/App

运行上面这个脚本之前我们还需要安装软件包libegl-dev,这个包提供了eglfs相关的组件。

sudo apt-get install libegl*
sudo /usr/local/qt-app/run_eglfs.sh

这时我们会看到同样的效果。

3.3.2. lubancat-carp-qt-armhf

这个镜像已经安装了野火demo运行相关依赖和野火demo,只需要执行run.sh即可。

运行野火demo

sudo /usr/local/qt-app/run.sh