
本文禁止转载
前言
  继上次完成FFmpeg的交叉编译之后,遂将交叉编译库移植到了全志A40开发板中,在Qt5 Demo中测试发现,RTSP 视频流无法播放,报一堆Qt 库错误,真是无语了。但是在Linux环境下,用FFmpeg 编译出来的测试样例却可以直接播放RTSP 视频流。经过一番查找资料发现,原来...第三方解码库编译时,需要加入QT 模块路径,这样在Qt环境中运行时,才能找到对应的库。了解了这个之后,我便放弃了重新编译FFmpeg的想法,因为有个更合适的图像、视觉解码库——OpenCV ,并且它自带了FFmpeg。
这篇文章,主要记录的是OpenCV-Qt5的交叉编译实现,过程可谓非常艰辛曲折,坑太多了。。。
前期准备
环境
- 宿主机环境:windows7 专业版
 - 宿主机环境: Windows7 64位 专业版
 - Ubuntu环境:Ubuntu 12.04
 - 内核版本: Linux 3.10
 - 交叉编译器:arm-linux-gnueabihf-
 - Ubuntu gcc/g++ : gcc version 4.8.4
 - cmake版本:cmake version 3.18.1
 
提前编译
一、交叉编译Qt5源码
这一步是必须的,因为后面填写OpenCV-Qt 模块路径的时候,一定要指向这里,并且,务必注意是交叉编译,Ubuntu下若未指定编译器和平台,默认是编译Linux-x86版本的。这里交叉编译的篇幅很长,就不展开讲,google/百度很多教程,按照教程自行编译完成。
编译完成之后,需要建立一个Qt 环境的文件系统,我这里使用的是buildroot 来做的。不然后面OpenCV 环境依赖没法通过。
二、编译cmake-gui
  必须从源代码构建cmake-gui,在cmake源代码中其被打包为cmake-qt-gui,所以构建时须加入关键参数:--qt-gui
这里以cmake-3.18.1.tar.gz源码为例:
tar xvf cmake-3.18.1.tar.gz
cd cmake-3.18.1
./bootstrap
make
make install
先运行./bootstrap 进行一次预编译,并安装生成cmake,然后重启Ubuntu,返回刚才cmake目录,执行二次编译,这次是生成cmake-gui
cd cmake-3.18.1
./configure --qt-gui
make
make install
这里编译生成cmake-gui 的目的,是为了OpenCV 配置时,可以使用可视化界面进行配置参数,当然,也可以不进行这一步,但是不使用可视化界面的话,cmake 后面携带的参数会非常多,不过,也可以将参数整在一起写成一个脚本。
三、交叉编译zlib
zlib是提供数据压缩用的函式库,OpenCV 中,libpng 和FFmpeg 模块都会用到这个库,所以要提前交叉编译,不然编译时会卡在unchar  到 char转换失败的错误,这里非常地莫名奇妙,明明未修改任何源码,可是未将这个库加入编译路径的话,转换失败的错误就会一直存在。
如下图所示:

编译方法:
1、这里以zlib-1.2.11.tar.gz 源码包为例:
tar xvf zlib-1.2.11.tar.gz
cd zlib-1.2.11
mkdir build
export CC=arm-linux-gnueabihf-gcc
./configure --prefix=$PWD/build
make
make install
编译完成之后,会在build目录下生成libz.so、libz.so.1、libz.so.1.2.11 这三个库。
编译OpenCV
首先去下载OpenCV 源码,这里以opencv-4.3.0.zip为例
tar xvf opencv-4.3.0.zip
cd opencv-4.3.0
mkdir build
cmake-gui
出现cmake-gui界面,分别填入源码路径和输出路径,然后点击Configure,在弹出的窗口中,选择Unix MakeFiles,并勾选指定交叉编译链进行编译。
如图:
然后单击Next ,进入交叉编译链的配置。Operating System 填写为:Linux,而非 arm-linux,网上很多人写的是arm-linux,这里也是坑。C Compilers 选择Qt 库中的 arm-linux-gnueabihf-gcc,C++ Compilers 选择arm-linux-gnueabihf-g++。这里一定要使用Qt 环境中的交叉编译器,而非ubuntu 本地的gcc/g++编译器。
Target Root 选择 Qt 文件系统的程序执行路径,其路径在:~/buildroot/host/usr/bin 目录下。这里需要注意的是:除了先前的Qt交叉编译,还需要事先建立一个Qt环境的文件系统,不然这一步中的Target Root你没法填,这里坑惨了我...

设置完成,点击 Finsh 会自动寻找依赖。此时中间界面是一片爆红的,再次点击 Configure , cmake会逐项进行查找,并罗列未找到的依赖项目。
接下来,按需勾选需要用到的OpenCV 模块,我这里勾选了以下这些模块,非全部罗列
BUILD:
BUILD_JPEG
BUILD_PNG
BUILD_PACKAGE
BUILD_SHARED_LIBS
BUILD_TESTS
BUILD_opencv_apps
BUILD_opencvcalib3d
BUILD_opencv_core
BUILD_opencv_dnn
BUILD_opencv_features2d
BUILD_opencv_gapi
BUILD_opencv_highgui
BUILD_opencv_imgproc
BUILD_opencv_imgcodecs
BUILD_opencv_photo
BUILD_opencv_video
WITH:
WITH_FFMPEG
WITH_GSTREAMER
WITH_QT
WITH_JPEG
WITH_PNG
WITH_OPENCL
WITH_LAPACK
WITH_V4L
在勾选了WITH_QT 之后,还需将QT 的库执行路径填到到OpenCV 的编译依赖中,分别需要添加以下库路径执行选项:
- Qt5_DIR
 - Qt5Core_DIR
 - Qt5Gui_DIR
 - Qt5Test_DIR
 - QT_MAKE_EXECUTABLE
 - QT5Network_DIR
 - QT5NetworkAuth_DIR
 - Qt5Concurrent_DIR
 - Qt5Widgets_DIR
 - QT5Multimedia_DIR
 - QT5MultimediaWidgets_DIR
 - Qt5OpenGL_DIR
 
这里的库路径是根据你的Qt 程序来选择对应的库,比如:我需要在Qt 程序中,调用OpenCV 库来播放一段RTSP 视频流,那么它就一定会用到 QT5Network、QT5Widgets、QT5Core、Qt5Gui等模块,其他同理。
Qt 库路径示例:~/buildroot/qt-everywhere-opensource-src-5.9.0/Qt-5.9.0/lib
 
待全部配置完成之后,点击 Configure ,并逐步排查依赖项的路径,以及相关参数的设置。直到不出现报错为止,如下图所示,显示Configration done 即表示初步配置没错。然后就可以点击 Generate ,生成 MakeFile 文件了。

以下是我的 Configure 配置生成的日志,供参考
========General configuration for OpenCV 4.3.0 ============
  Version control:               unknown
  Platform:
    Timestamp:                   2020-09-08T02:03:50Z
    Host:                        Linux 3.13.0-117-generic x86_64
    Target:                      Linux
    CMake:                       3.18.1
    CMake generator:             Unix Makefiles
    CMake build tool:            /usr/bin/make
    Configuration:               Release
  CPU/HW features:
    Baseline:
      requested:                 DETECT
  C/C++:
    Built as dynamic libs?:      YES
    C++ standard:                11
    C++ Compiler:                /你的Qt交叉编译链路径/buildroot/host/opt/ext-toolchain/bin/arm-linux-gnueabihf-g++  (ver 5.3.1)
    C++ flags (Release):         -fsigned-char -W -Wall -Werror=return-type -Werror=non-virtual-dtor -Werror=address -Werror=sequence-point -Wformat -Werror=format-security -Wmissing-declarations -Wundef -Winit-self -Wpointer-arith -Wshadow -Wsign-promo -Wuninitialized -Winit-self -Wsuggest-override -Wno-delete-non-virtual-dtor -Wno-comment -fdiagnostics-show-option -pthread -fomit-frame-pointer -ffunction-sections -fdata-sections  -fvisibility=hidden -fvisibility-inlines-hidden -O3 -DNDEBUG  -DNDEBUG
    C++ flags (Debug):           -fsigned-char -W -Wall -Werror=return-type -Werror=non-virtual-dtor -Werror=address -Werror=sequence-point -Wformat -Werror=format-security -Wmissing-declarations -Wundef -Winit-self -Wpointer-arith -Wshadow -Wsign-promo -Wuninitialized -Winit-self -Wsuggest-override -Wno-delete-non-virtual-dtor -Wno-comment -fdiagnostics-show-option -pthread -fomit-frame-pointer -ffunction-sections -fdata-sections  -fvisibility=hidden -fvisibility-inlines-hidden -g  -O0 -DDEBUG -D_DEBUG
    C Compiler:                  /你的Qt交叉编译链路径/buildroot/host/opt/ext-toolchain/bin/arm-linux-gnueabihf-gcc
    C flags (Release):           -fsigned-char -W -Wall -Werror=return-type -Werror=non-virtual-dtor -Werror=address -Werror=sequence-point -Wformat -Werror=format-security -Wmissing-declarations -Wmissing-prototypes -Wstrict-prototypes -Wundef -Winit-self -Wpointer-arith -Wshadow -Wuninitialized -Winit-self -Wno-comment -fdiagnostics-show-option -pthread -fomit-frame-pointer -ffunction-sections -fdata-sections  -fvisibility=hidden -O3 -DNDEBUG  -DNDEBUG
    C flags (Debug):             -fsigned-char -W -Wall -Werror=return-type -Werror=non-virtual-dtor -Werror=address -Werror=sequence-point -Wformat -Werror=format-security -Wmissing-declarations -Wmissing-prototypes -Wstrict-prototypes -Wundef -Winit-self -Wpointer-arith -Wshadow -Wuninitialized -Winit-self -Wno-comment -fdiagnostics-show-option -pthread -fomit-frame-pointer -ffunction-sections -fdata-sections  -fvisibility=hidden -g  -O0 -DDEBUG -D_DEBUG
    Linker flags (Release):      -Wl,--gc-sections -Wl,--as-needed  
    Linker flags (Debug):        -Wl,--gc-sections -Wl,--as-needed  
    ccache:                      YES
    Precompiled headers:         NO
    Extra dependencies:          dl m pthread rt
    3rdparty dependencies:
  OpenCV modules:
    To be built:                 calib3d core dnn features2d flann gapi highgui imgcodecs imgproc objdetect photo stitching video
    Disabled:                    java_bindings_generator ml videoio world
    Disabled by dependency:      ts
    Unavailable:                 java js python2 python3
    Applications:                apps
    Documentation:               NO
    Non-free algorithms:         NO
  GUI: 
    QT:                          YES (ver ..)
      QT OpenGL support:         NO
    GTK+:                        NO
    OpenGL support:              NO
  Media I/O: 
    ZLib:                        build (ver 1.2.11)
    JPEG:                        build-libjpeg-turbo (ver 2.0.4-62)
    PNG:                         build (ver 1.6.37)
    JPEG 2000:                   build Jasper (ver 1.900.1)
    HDR:                         YES
    SUNRASTER:                   YES
    PXM:                         YES
    PFM:                         YES
  Video I/O:
    FFMPEG:                      NO
      avcodec:                   NO
      avformat:                  NO
      avutil:                    NO
      swscale:                   NO
      avresample:                NO
    GStreamer:                   NO
    v4l/v4l2:                    YES (linux/videodev2.h)
  Parallel framework:            pthreads
  Trace:                         YES (built-in)
  Other third-party libraries:
    Lapack:                      NO
    Custom HAL:                  NO
    Protobuf:                    build (3.5.1)
  OpenCL:                        YES (no extra features)
    Include path:                /root/opencv/opencv-4.3.0/3rdparty/include/opencl/1.2
    Link libraries:              Dynamic load
  Python (for build):            /usr/bin/python2.7
  Install to:                    /root/opencv/opencv-4.3.0/out
-----------------------------------------------------------------
Configuring done
Generating done
到这里,如果你全部按照上文指示的步骤,完成了所有的工具、路径的依赖问题,那直接执行 make 应该是不会再报错了
cd /root/opencv/opencv-4.3.0/build
make
make install
编译的时间非常久,我用4核CPU make -j4 编译了大约一上午,3个小时吧,也可能是因为我使用到的库比较多。
最终编译成功如图:
make install 安装成功如图:

最终成功生成了ARM平台的二进制文件,并生成了对应的库,如下图:

如上图所示,生成了bin、include、lib、share四个文件夹,这就是OpenCV交叉编译的库,将其导入到Qt的 buildroot文件系统中,再随系统镜像一起打包,即可以在Qt 开发环境中直接调用OpenCV 的API 接口了。
 
注意:我这里并未列出详细的报错信息,以及解决办法,因为我觉得没必要,每个人的环境,版本可能不一样,报错信息也不一定相同,所以与其浪费篇幅在讲报错信息上,不如把整体的编译思路理清楚,搞清楚编译顺序,相关依赖、变量设置,后面的报错自己一查也能找出来。
 
 
以上。
版权属于:编码书生
本文链接:https://codess.cc/archives/466.html
所有原创文章采用知识共享署名-非商业性使用 4.0 国际许可协议进行许可。
除特别注明,您可以自由的转载和修改,但请务必注明文章来源且不可用于商业目的。
                            
                            
      
5 条评论
想搭一个瑞芯微的opencv环境
方法上大同小异,如果不是基于Qt开发,可将上文Qt部分跳过。另外,瑞芯微有一套MPP 框架,里面自带了FFmpeg,gstreamer,硬件解码,可以很方便地处理视频流。
谢谢大佬
为啥要用全志的方案啊?瑞芯微的方案不是更适合楼主嘛
被销售给忽悠了,太惨了....整了快一个月的视频硬解码,结果发现这货根本处理不了,一堆问题。现已更换瑞芯微RK3399 ,刚拿到开发手册的时候眼泪都留下来了,RK3399 SDK 自带视频硬解码。。。。