21 мая 2018 г.

Собираем OpenCV с поддержкой ffmpeg под ARM

Понадобилось мне недавно собрать OpenCV под ZedBoard. Для тех, кто не в курсе, ZedBoard это отладочная плата, на основе чипа Zynq от Xilinx. На чипах Zynq совмещены процессор общего назначения и программируемая логика, на которой оптимально делать разные сопроцессоры. Если вспомнить тему статьи, то можно сказать, что задача не совсем разумна, потому что обрабатывать видео на CPU, когда рядом есть программируемая логика, да еще и поддерживаемая в "расширении" ReVision от Xilinx, где реализованы многие примитивы из OpenCV. И это действительно так, поэтому просто обобщим, что OpenCV собирался под Cortex A9.


Прежде, чем начать "угар" сборки, стоит отметить, что Xilinx в своей wiki рассказывает, как надо делать, но мы уже понимаем, что это не сработает. Гугление по StackOverflow тоже не навело меня на прямую инструкцию по сборке, лишь более-менее полные наводящие инструкции.
Еще надо сказать, что собирать будем в среде Linux. Под Windows у меня получилось собрать OpenCV под ARM, но подружить его с ffmpeg не вышло - слишком много проблем вскрывалось с обработкой путей в Windows и дописываниями ".exe" к исполняемым файлам кросс-компилятора.
Итак, первым делом убеждаемся, что у нас есть toolchain для сборки под нужный процессор. Его обычно можно найти с BSP (Board Support Package), скачать с сайта производителя процессора или собрать самому. Я выбрал второй путь, немного проклиная Xilinx за то, что он не дает скачать чисто toolchain, а еще качает мне 6 гигов ненужного эклипса. Прописываем в $PATH наш toolchain.
$ export PATH=$HOME/cross/xilinx/zedboard/original/gcc-arm-linux-gnueabi/bin/:$PATH
Теперь качаем исходники OpenCV и ffmpeg. Работаем в директории $HOME, кому не нравится, меняйте пути на свои.
$ cd src
$ mkdir opencv
$ cd opencv
$ git clone https://github.com/opencv/opencv.git
$ git clone https://github.com/opencv/opencv_contrib.git
$ cd ..
$ git clone https://git.ffmpeg.org/ffmpeg.git
После скачивания принимаемся за ffmpeg.
$ ./configure --enable-shared --disable-static --enable-avresample --cross-prefix=arm-linux-gnueabihf- --arch=armv7l --target-os=linux --prefix=$HOME/build-cross/ffmpeg/
Настоятельно рекомендую указывать прямые пути в параметре --prefix, а не относительные. Также OpenCV требует наличия deprecated библиотеки libavresample.
Создаем директории для результатов.
$ mkdir -p $HOME/build-cross/ffmpeg
$ mkdir $HOME/build-cross/opencv
Из папки исходников запускаем make
$ make -j5
$ make install
Проверяем, появились ли в $HOME/build-cross/ffmpeg/lib/ нужные библиотеки. Особо пристально смотрим на правильность содержимого папки pkgconfig. Пути должны быть абсолютными.
Теперь говорим, системе, где искать либы и файлы для pkg-config. Также указываем на пути к новым include-файлам.
$ export LD_LIBRARY_PATH=$HOME/build-cross/ffmpeg/lib:$LD_LIBRARY_PATH
$ export PKG_CONFIG_PATH=$HOME/build-cross/ffmpeg/lib/pkgconfig/:$PKG_CONFIG_PATH
$ export PKG_CONFIG_LIBDIR=$HOME/build-cross/ffmpeg/lib/:$PKG_CONFIG_LIBDIR
$ export C_INCLUDE_PATH=$HOME/build-cross/ffmpeg/include/:$C_INCLUDE_PATH
$ export CPLUS_INCLUDE_PATH=$HOME/build-cross/ffmpeg/include/:$CPLUS_INCLUDE_PATH
Приступаем к сборке OpenCV.
Создадим toolchain-файл.
$ cd $HOME/src/opencv/opencv/platform/linux
$ cp arm-gnueabi.toolchain.cmake zedboard.toolchain.cmake
Правим toolchain-файл. Дописываем в него следующее.
set( CMAKE_SYSTEM_NAME Linux )
set( CMAKE_SYSTEM_PROCESSOR arm )
set( CMAKE_C_COMPILER arm-linux-gnueabihf-gcc )
set( CMAKE_CXX_COMPILER arm-linux-gnueabihf-g++ )
set( CMAKE_INSTALL_PREFIX ${HOME}/build-cross/opencv )
set( CMAKE_FIND_ROOT_PATH ${HOME}/build-cross/opencv )
Идем в корень исходников OpenCV и правим cmake/OpenCVCompilerOptions.cmake
Нужно выставить дополнительные флаги для линкера. Они хранятся в переменной OPENCV_EXTRA_EXE_LINKER_FLAGS. В указанном выше файле ищем строчку
set(OPENCV_EXTRA_EXE_LINKER_FLAGS "${OPENCV_EXTRA_EXE_LINKER_FLAGS} -Wl,--gc-sections")
И заменяем ее на
set(OPENCV_EXTRA_EXE_LINKER_FLAGS "${OPENCV_EXTRA_EXE_LINKER_FLAGS} -Wl,-rpath-link,/home/aldaris/build-cross/ffmpeg/lib,--gc-sections")
Да, костыльно. Да, можно по-нормальному сделать, но не нужно. Почему-то не подцепляется переменная $HOME в этой строчке. По этому поводу я тоже не проводил расследование.
Дальше я люблю запускать cmake-gui. В нем гораздо удобнее искать ключи для сборки, чем это делать... Даже не знаю как это можно быстро делать в консоли.
Так вот запускаем, выбираем папку с исходниками OpenCV ($HOME/src/opencv/opencv), выбираем, куда билдить ($HOME/build-src/opencv), жмем "Configure", выбираем в качестве генератора "Unix Makefiles" и выбираем toolchain файл для кросс-компиляции (который zedboard.toolchain.cmake).
После конфигурации в логе в группе Video I/O должно отобразиться что-то типа такого:
  Video I/O:
    FFMPEG:                      YES
      avcodec:                   YES (ver 58.19.102)
      avformat:                  YES (ver 58.15.100)
      avutil:                    YES (ver 56.18.102)
      swscale:                   YES (ver 5.2.100)
      avresample:                YES (ver 4.0.0)
Обратите внимание, что напротив FFMPEG обязательно должен быть YES. Если либы помечены как YES, а сам FFMPEG нет, то, вероятно не собрался тестовый пример. Надо лезть в файл cmake/OpenCVFindLibsVideo.cmake и смотреть, с какими параметрами build-система пытается собрать тестовое приложение. Если даже либы помечены как NO, значит либо они не собраны, либо pkg-config не может прочитать их параметры.
Что касается параметров сборки (что включать, что выключать). Я обычно делаю примерно следующее.

  • Отключаю все со словом test, opencv_ts, build_examples тоже не нужно
  • Отключаю v4l, gstreamer, gphoto
  • Отключаю все, что относится к OpenCL (даже для x86 версии - однажды я пострадал от использования OpenCL в многопоточном режиме)
  • Отключаю CUDA - ее все равно не видно в embedded
  • Можно отключить поддержку всяких tiff, если не собираемся использовать
  • В OPENCV_EXTRA_MODULES_PATH прописываем путь к opencv_contrib/modules
  • NONFREE включаем - там хороший-полезный SURF есть например

Короче, как-то так. На момент написания инструкции OpenCV был версии 3.4.1, а ffmpeg смотрите в листинге выше.

Комментариев нет:

Отправить комментарий