本文禁止转载
前言
继上次完成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 自带视频硬解码。。。。