Compiling OpenCV 4.7.0 - Problems and Solution

Problem

When using Ubuntu Server 20.04 installed by OOWOW and trying to compile OpenCV 4.7.0 from source the build fails with errors like;

[ 55%] Linking CXX shared library ../../lib/libopencv_videoio.so
/usr/bin/ld: CMakeFiles/opencv_videoio.dir/src/cap_ffmpeg.cpp.o: in function `CvCapture_FFMPEG::close()':
cap_ffmpeg.cpp:(.text._ZN16CvCapture_FFMPEG5closeEv+0x24): undefined reference to `av_frame_free'
/usr/bin/ld: cap_ffmpeg.cpp:(.text._ZN16CvCapture_FFMPEG5closeEv+0x40): undefined reference to `avformat_close_input'
/usr/bin/ld: cap_ffmpeg.cpp:(.text._ZN16CvCapture_FFMPEG5closeEv+0x4c): undefined reference to `av_frame_unref'
/usr/bin/ld: cap_ffmpeg.cpp:(.text._ZN16CvCapture_FFMPEG5closeEv+0x5c): undefined reference to `av_packet_unref'
/usr/bin/ld: cap_ffmpeg.cpp:(.text._ZN16CvCapture_FFMPEG5closeEv+0x80): undefined reference to `av_packet_unref'
/usr/bin/ld: cap_ffmpeg.cpp:(.text._ZN16CvCapture_FFMPEG5closeEv+0x94): undefined reference to `av_bsf_free'

These errors are a result of linking problems to the ffmpeg libraries such as libavcodec-dev libavformat-dev libswscale-dev.

The cmake configure process correctly links to the Ubuntu apt install of the above libraries

--   Video I/O:
--     DC1394:                      YES (2.2.5)
--     FFMPEG:                      YES
--       avcodec:                   YES (58.54.100)
--       avformat:                  YES (58.29.100)
--       avutil:                    YES (56.31.100)
--       swscale:                   YES (5.5.100)
--       avresample:                NO
--     GStreamer:                   NO
--     v4l/v4l2:                    YES (linux/videodev2.h)

The conflict is due to Khadas Ubuntu image coming preinstalled with ffmpeg libraries which I suspect are compiled from source and NOT from the standard deb/apt repositories. eg:

/usr/lib/libavformat.so.53
/usr/lib/libavcodec.so.53 
/usr/lib/libavdevice.so.53.1.1

Question for Khadas

@numbqq and @Frank
Can someone from Khadas explain why this has been done as it breaks all package management processes that have been long established? I would have thought if you were to install self complied libraries with the OS image then a best practice would be to setup your own PPA repository to manage these extras?

Solution

So for those who want to compile OpenCV 4.7.0 the following steps works around this conflict.

Remove all Khadas ffmpeg libraries

mkdir -p /root/conflict/usr/lib
mkdir -p /root/conflict/usr/include
mkdir -p /root/conflict/usr/lib/pkgconfig

mv /usr/lib/libavformat.so.53 /usr/lib/libavformat.so /usr/lib/libavformat.so.53.4.0 /root/conflict/usr/lib/
mv /usr/lib/pkgconfig/libavformat.pc /root/conflict/usr/lib/pkgconfig/
mv /usr/include/libavformat /root/conflict/usr/include/

mv /usr/lib/libavcodec.so.53 /usr/lib/libavcodec.so /usr/lib/libavcodec.so.53.7.0 /root/conflict/usr/lib/
mv /usr/lib/pkgconfig/libavcodec.pc /root/conflict/usr/lib/pkgconfig/
mv /usr/include/libavcodec /root/conflict/usr/include/

mv /usr/lib/libswscale.so /usr/lib/libswscale.so.2 /usr/lib/libswscale.so.2.0.0 /root/conflict/usr/lib/
mv /usr/lib/pkgconfig/libswscale.pc /root/conflict/usr/lib/pkgconfig/
mv /usr/include/libswscale /root/conflict/usr/include/

mv /usr/lib/libavdevice.so.53.1.1 /usr/lib/libavutil.so /usr/lib/libavfilter.so.2.23.0 /usr/lib/libavutil.so.51.9.1 /usr/lib/libavfilter.so /root/conflict/usr/lib/
mv /usr/lib/pkgconfig/libavdevice.pc /usr/lib/pkgconfig/libavutil.pc /usr/lib/pkgconfig/libavfilter.pc /root/conflict/usr/lib/pkgconfig/
mv /usr/include/libavfilter /usr/include/libavdevice /usr/include/libavutil /root/conflict/usr/include/

Install dependencies

apt-get -y install unzip wget build-essential cmake curl git libgtk2.0-dev pkg-config libavcodec-dev libavformat-dev libswscale-dev libtbb2 libtbb-dev libjpeg-dev libpng-dev libtiff-dev libdc1394-22-dev

Download OpenCV sources and Contrib files

mkdir /tmp/opencv
cd /tmp/opencv
curl -Lo opencv.zip https://github.com/opencv/opencv/archive/refs/tags/4.7.0.zip
unzip -q opencv.zip
curl -Lo opencv_contrib.zip https://github.com/opencv/opencv_contrib/archive/refs/tags/4.7.0.zip
unzip -q opencv_contrib.zip
rm opencv.zip opencv_contrib.zip
cd opencv-4.7.0
mkdir build
cd build

Configure OpenCV - note I am using this with Golang so have removed Python and Java stuff so edit this line for your needs.

cmake -D CMAKE_BUILD_TYPE=RELEASE -D CMAKE_INSTALL_PREFIX=/usr/local -D BUILD_SHARED_LIBS=ON -D OPENCV_EXTRA_MODULES_PATH=/tmp/opencv/opencv_contrib-4.7.0/modules -D BUILD_DOCS=OFF -D BUILD_EXAMPLES=OFF -D BUILD_TESTS=OFF -D BUILD_PERF_TESTS=OFF -D BUILD_opencv_java=NO -D BUILD_opencv_python=NO -D BUILD_opencv_python2=NO -D BUILD_opencv_python3=NO -D WITH_JASPER=OFF -D WITH_TBB=ON -DOPENCV_GENERATE_PKGCONFIG=ON ..

Then compile and install

make -j6
make install

Alternative Workaround

If you don’t require manipulation of video files in OpenCV then you can disable ffmpeg support with the -DWITH_FFMPEG=OFF flag on the cmake/configure line.