buildroot-package分析与ffmpeg添加rkmpp插件示例目标平台:OK3588 获取源码: git clone -b jellyfin-mpp --depth=1 https://github.com/nya**aka/mpp.git rkmpp git clone -b jellyfin-rga --depth=1 https://github.com/nya**aka/rk-mirrors.git rkrga git clone --depth=1 https://github.com/nya**aka/ffmpeg-rockchip.git ffmpeg 参考链接:Compilation · nya**aka/ffmpeg-rockchip Wiki (github.com) 修改的package:rockchip-mpp,rockchip-rga,opencv4,ffmpeg 1. buildroot基础知识 Buildroot是一个可以使用交叉编译简单且自动化地为嵌入式系统构建完整Linux系统的工具。 为了实现这一目标,Buildroot能够为你的系统生成交叉编译工具链、根文件系统、Linux内核镜像和引导加载程序。BuildRoot可以独立地用于这些选项的任意组合(例如,你可以使用已有的交叉编译工具链,并且仅编译根文件系统)。Buildroot主要用于使用嵌入式系统的开发者。嵌入式系统通常使用的处理器不是PC上使用的常规x86处理器,他们可以是PowerPC处理器、MIPS处理器或者ARM处理器等。 原文参考:Buildroot中文用户手册_the buildroot user manual 中文-CSDN博客 2. 将软件包添加到Buildroot参考中文手册17.1章节,本小节针对ffmpeg.mk与rockchip-mpp.mk做修改来适配ffmpeg的rkmpp插件 2.1 添加rockchip-mpp包进入到buildroot目录中,查看./package/rockchip/ tree -L 1 . ├── Config.in ├── rockchip.mk Config.in 可以看的出来,Config.in的语法与KConfig几乎一模一样,只不过CONFIG_ 变成了BR2_PACKAGE_,实际上这是buildroot通过自身一系列的工具和脚本衍生的命名规则,在下文有描述。 menuconfig BR2_PACKAGE_ROCKCHIP if BR2_PACKAGE_ROCKCHIP config BR2_PACKAGE_ROCKCHIP_HAS_ISP1 config BR2_PACKAGE_ROCKCHIP_HAS_ISP2 config BR2_PACKAGE_ROCKCHIP_HAS_ISP3 choice config BR2_PACKAGE_RK3399 config BR2_PACKAGE_RK356X config BR2_PACKAGE_RK3588 endchoice
rockchip.mk include $(sort $(wildcard package/rockchip/*/*.mk))
接下来分析rockchip-mpp包的配置 首先介绍下命名规则 软件包名称、配置入口名称及makefile变量之间的关系在Buildroot中,它们之间存在一些关系: 必须使用以下规则确保这些元素之间的一致性: 软件包目录和.mk文件名即为软件包名称本身,如package/foo-bar_boo/foo-bar_boo.mk。 make目录名称是软件包名称本身,如foo-bar_boo。 配置入口名称是软件包名称大写,其中-替换为,并以BR2_PACKAGE开头,如BR2_PACKAGE_FOO_BAR_BOO。 .mk文件变量前缀是软件包名称大写,其中-替换为_,如FOO_BAR_BOO_VERSION。
tree -L 1 ├── Config.in ├── rockchip-mpp.hash └── rockchip-mpp.mk
rockchip-mpp.mk
ROCKCHIP_MPP_SITE = $(TOPDIR)/../../../tools/rkmpp ROCKCHIP_MPP_VERSION = develop ROCKCHIP_MPP_SITE_METHOD = local ROCKCHIP_MPP_LICENSE = Apache-2.0 ROCKCHIP_MPP_LICENSE_FILES = LICENSE.md ROCKCHIP_MPP_CONF_OPTS = "-DRKPLATFORM=ON" ROCKCHIP_MPP_DEPENDENCIES += libdrm ROCKCHIP_MPP_INSTALL_STAGING = YES
ifeq ($(BR2_PACKAGE_ROCKCHIP_MPP_ALLOCATOR_DRM),y) ROCKCHIP_MPP_CONF_OPTS += "-DHAVE_DRM=ON" endif ifeq ($(BR2_PACKAGE_ROCKCHIP_MPP_TESTS),y) ROCKCHIP_MPP_CONF_OPTS += "-DBUILD_TEST=ON" endif
define ROCKCHIP_MPP_LINK_GIT rm -rf $(@D)/.git ln -s $(SRCDIR)/.git $(@D)/ endef ROCKCHIP_MPP_POST_RSYNC_HOOKS += ROCKCHIP_MPP_LINK_GIT define ROCKCHIP_MPP_REMOVE_NOISY_LOGS sed -i -e "/pp_enable %d/d" \ $(@D)/mpp/hal/vpu/jpegd/hal_jpegd_vdpu2.c || true sed -i -e "/reg size mismatch wr/i if (0)" \ $(@D)/osal/driver/vcodec_service.c || true endef ROCKCHIP_MPP_POST_RSYNC_HOOKS += ROCKCHIP_MPP_REMOVE_NOISY_LOGS $(eval $(cmake-package))
PS:HOOK操作介绍在官方手册17.22章节 通用基础结构(以及基于此派生出的基于autotools和cmake构建系统的基础结构)允许软件包指定hook钩子。这些钩子定义了执行完相应步骤后要执行的其他操作。大多数hook钩子对于通用软件包并不是真正有用,因为该.mk文件已经完全控制了软件包在构建过程每个步骤中执行的操作。 HOOK操作针对软件包的所有构建步骤都有可以执行自定义命令的操作空间 DOWNLOAD、EXTRACT、RSYNC、PATCH、CONFIGURE、BUILD、INSTALL、INSTALL_STAGING、INSTALL_TARGET、INSTALL_IMAGES、LEGAL_INFO 2.2 添加ffmpeg包 tree -L 1 ├── Config.in ├── ffmpeg.hash ├── ffmpeg.mk └── patch ├── 0001-swscale-x86-yuv2rgb-Fix-build-without-SSSE3.patch ├── 0002-avcodec-vaapi_h264-skip-decode-if-pic-has-no-slices.patch ├── 0003-libavutil-Fix-mips-build.patch └── 0004-configure-add-extralibs-to-extralibs_**.patch
ffmpeg.mk
FFMPEG_SITE = $(TOPDIR)/../../../tools/ffmpeg-rockchip-master FFMPEG_VERSION = master FFMPEG_SITE_METHOD = local FFMPEG_INSTALL_STAGING = YES ··· ifeq ($(BR2_PACKAGE_ROCKCHIP_MPP),y) FFMPEG_CONF_OPTS += --enable-rkmpp --enable-version3 --enable-rkrga FFMPEG_DEPENDENCIES += rockchip-mpp rockchip-rga endif ···
define FFMPEG_CONFIGURE_CMDS (cd $(FFMPEG_SRCDIR) && rm -rf config.cache && \ $(TARGET_CONFIGURE_OPTS) \ $(TARGET_CONFIGURE_ARGS) \ $(FFMPEG_CONF_ENV) \ ./configure \ --enable-cross-compile \ --cross-prefix=$(TARGET_CROSS) \ --sysroot=$(STAGING_DIR) \ --host-cc="$(HOSTCC)" \ --arch=$(BR2_ARCH) \ --target-os="linux" \ --disable-stripping \ --pkg-config="$(PKG_CONFIG_HOST_BINARY)" \ $(SHARED_STATIC_LIBS_OPTS) \ $(FFMPEG_CONF_OPTS) \ ) endef define FFMPEG_REMOVE_EXAMPLE_SRC_FILES rm -rf $(TARGET_DIR)/usr/share/ffmpeg/examples endef FFMPEG_POST_INSTALL_TARGET_HOOKS += FFMPEG_REMOVE_EXAMPLE_SRC_FILES $(eval $(autotools-package))
2.3 OpenCV包的升级 在buildroot中,任何第三方工具包的版本升级与适配都是需要谨慎的,在更改完上述软件包的配置后,我们可能会遇到大量基于ffmpeg的软件版本不适配的问题,这也是为什么我们不直接交叉编译后移植到板子上的原因。 OpenCV 4.5.4的videoio模块在编译时由于缺少ffmpeg4.4.1中AVStream提供的结构体AVCodec codec导致编译不通过,实际上,基于ffmpeg的工具出什么问题都不奇怪,因为我们使用的是6.1版本的ffmpeg。 所幸,通过对比ffmpeg的源码与不同版本的opencv源码,可以发现,4.7.0版本的源码针对这ffmpeg一背刺是提供了兼容方案的。
#if LIBAVFORMAT_BUILD >= CALC_FFMPEG_VERSION(59, 16, 100)
# define CV_FFMPEG_CODECPAR # define CV_FFMPEG_CODEC_FIELD codecpar #4.1.1版本的codec在6.1版本变成了codecpar #else # define CV_FFMPEG_CODEC_FIELD codec #endif
接下来就是升级opencv4.7.0即可
OPENCV4_VERSION = 4.7.0 OPENCV4_SITE = $(call github,opencv,opencv,$(OPENCV4_VERSION)) OPENCV4_INSTALL_STAGING = YES OPENCV4_LICENSE = Apache-2.0 OPENCV4_LICENSE_FILES = LICENSE OPENCV4_CPE_ID_VENDOR = opencv OPENCV4_CPE_ID_PRODUCT = opencv OPENCV4_SUPPORTS_IN_SOURCE_BUILD = NO
OPENCV4_CONF_OPTS += \ -DWITH_1394=OFF \ -DWITH_CLP=OFF \ -DWITH_EIGEN=OFF \ -DWITH_GDAL=OFF \ -DWITH_GPHOTO2=OFF \ -DWITH_GSTREAMER_0_10=OFF \ -DWITH_LAPACK=OFF \ -DWITH_MATLAB=OFF \ -DWITH_OPENCL=ON \ -DWITH_OPENCL_SVM=OFF \ -DWITH_OPENEXR=OFF \ -DWITH_OPENNI2=OFF \ -DWITH_OPENNI=OFF \ -DWITH_UNICAP=OFF \ -DWITH_VA=OFF \ -DWITH_VA_INTEL=OFF \ -DWITH_VTK=OFF \ -DWITH_XINE=OFF
2.4 添加RGA包
//changed ROCKCHIP_RGA_SITE = $(TOPDIR)/../../package_update/rkrga ROCKCHIP_RGA_VERSION = master ROCKCHIP_RGA_SITE_METHOD = local ROCKCHIP_RGA_LICENSE = Apache-2.0 ROCKCHIP_RGA_LICENSE_FILES = COPYING ROCKCHIP_RGA_INSTALL_STAGING = YES ifeq ($(BR2_PACKAGE_LIBDRM),y) ROCKCHIP_RGA_DEPENDENCIES += libdrm ROCKCHIP_RGA_CONF_OPTS += -Dlibdrm=true endif $(eval $(meson-package))
2.5 升级 libv4l先看下mk文件
LIBV4L_VERSION = 1.20.0 LIBV4L_SOURCE = v4l-utils-$(LIBV4L_VERSION).tar.bz2 LIBV4L_SITE = https://linuxtv.org/downloads/v4l-utils LIBV4L_INSTALL_STAGING = YES LIBV4L_DEPENDENCIES = host-pkgconf LIBV4L_CONF_OPTS = --disable-doxygen-doc --disable-qvidcap
LIBV4L_AUTORECONF = YES
LIBV4L_DEPENDENCIES += host-gettext
LIBV4L_CONF_ENV = ac_cv_prog_cc_c99='-std=gnu99'
LIBV4L_LICENSE = GPL-2.0+ (utilities), LGPL-2.1+ (libraries) LIBV4L_LICENSE_FILES = COPYING COPYING.libv4l lib/libv4l1/libv4l1-kernelcode-license.txt ifeq ($(BR2_PACKAGE_ALSA_LIB),y) LIBV4L_DEPENDENCIES += alsa-lib endif ifeq ($(BR2_PACKAGE_ARGP_STANDALONE),y) LIBV4L_DEPENDENCIES += argp-standalone LIBV4L_LIBS += -largp endif LIBV4L_DEPENDENCIES += $(if $(BR2_PACKAGE_LIBICONV),libiconv) ifeq ($(BR2_PACKAGE_JPEG),y) LIBV4L_DEPENDENCIES += jpeg LIBV4L_CONF_OPTS += --with-jpeg else LIBV4L_CONF_OPTS += --without-jpeg endif ifeq ($(BR2_PACKAGE_HAS_LIBGL),y) LIBV4L_DEPENDENCIES += libgl endif ifeq ($(BR2_PACKAGE_HAS_UDEV),y) LIBV4L_CONF_OPTS += --with-udevdir=/usr/lib/udev LIBV4L_DEPENDENCIES += udev endif ifeq ($(BR2_PACKAGE_LIBGLU),y) LIBV4L_DEPENDENCIES += libglu endif ifeq ($(BR2_PACKAGE_LIBV4L_UTILS),y) LIBV4L_CONF_OPTS += --enable-v4l-utils LIBV4L_DEPENDENCIES += $(TARGET_NLS_DEPENDENCIES)
LIBV4L_CONF_OPTS += --disable-bpf ifeq ($(BR2_PACKAGE_QT5BASE)$(BR2_PACKAGE_QT5BASE_GUI)$(BR2_PACKAGE_QT5BASE_WIDGETS),yyy) LIBV4L_CONF_OPTS += --enable-qv4l2 LIBV4L_DEPENDENCIES += qt5base
LIBV4L_CONF_ENV += \ ac_cv_prog_MOC=$(HOST_DIR)/bin/moc \ ac_cv_prog_RCC=$(HOST_DIR)/bin/rcc \ ac_cv_prog_UIC=$(HOST_DIR)/bin/uic
LIBV4L_CONF_ENV += CXXFLAGS="$(TARGET_CXXFLAGS) -std=c++11" else LIBV4L_CONF_OPTS += --disable-qv4l2 endif else LIBV4L_CONF_OPTS += --disable-v4l-utils endif ifeq ($(BR2_PACKAGE_LIBV4L_BUILTIN_PLUGINS),y) LIBV4L_CONF_OPTS += --enable-builtin-plugins endif ifeq ($(BR2_PACKAGE_SDL2_IMAGE),y) LIBV4L_DEPENDENCIES += sdl2_image endif LIBV4L_CONF_ENV += LIBS="$(LIBV4L_LIBS)" $(eval $(autotools-package))
可以看到,目前libv4l用的是autotools 也就是configure脚本去构建makefile的,而我们需要升级到最新版,是用meson构建,ninja编译的,这就需要看下meson是怎么编译的。 |