嵌入式爱好者

嵌入式爱好者 门户 知识库 查看内容

OK3588适配ffmpeg6.1及编解码器插件

2024-8-30 17:39| 发布者: C.S151| 查看: 69| 评论: 0|原作者: 程帅

类目:  >  知识库     文档编号: 1508

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
       bool "Rockchip Platform"

if BR2_PACKAGE_ROCKCHIP

config BR2_PACKAGE_ROCKCHIP_HAS_ISP1
       bool
       help
         Has Rockchip ISP1

config BR2_PACKAGE_ROCKCHIP_HAS_ISP2
       bool
       help
         Has Rockchip ISP2

config BR2_PACKAGE_ROCKCHIP_HAS_ISP3
       bool
       help
         Has Rockchip ISP3

choice
       default BR2_PACKAGE_RK3588
       prompt "Rockchip SoC"

config BR2_PACKAGE_RK3399
       bool "rk3399 chip"
       select BR2_ROCKCHIP_HAS_ISP1
       help
         Use Rockchip's rk3399 SoC

config BR2_PACKAGE_RK356X
       bool "rk356x chip"
       select BR2_ROCKCHIP_HAS_ISP2
       help
         Use Rockchip's rk356x SoC

config BR2_PACKAGE_RK3588
       bool "rk3588"
       select BR2_PACKAGE_ROCKCHIP_HAS_ISP3
       help
         Use Rockchip's rk3588 SoC

endchoice

# Camera Engine packages

rockchip.mk


include $(sort $(wildcard package/rockchip/*/*.mk))

接下来分析rockchip-mpp包的配置

首先介绍下命名规则

软件包名称、配置入口名称及makefile变量之间的关系

在Buildroot中,它们之间存在一些关系:

  • 软件包名称,即软件包目录名称,也是.mk文件名称。

  • 配置入口名称为Config.in中声明的名称。

  • makefile变量前缀。

必须使用以下规则确保这些元素之间的一致性:

  • 软件包目录和.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 #软件包构建过程中会对比hash校验值,校验不通过则退出构建,一般存放下载的压缩包和许可证的sha256值
└── rockchip-mpp.mk

rockchip-mpp.mk


################################################################################
#
# rockchip-mpp
#
################################################################################

#ROCKCHIP_MPP_SITE = $(TOPDIR)/../external/mpp
ROCKCHIP_MPP_SITE = $(TOPDIR)/../../../tools/rkmpp #配置源码下载路径
ROCKCHIP_MPP_VERSION = develop#配置源码版本,在build目录下创建rockchip-mpp-$(ROCKCHIP_MPP_VERSION)目录
ROCKCHIP_MPP_SITE_METHOD = local  #本地方式下载



ROCKCHIP_MPP_LICENSE = Apache-2.0  #许可证类型
ROCKCHIP_MPP_LICENSE_FILES = LICENSE.md  #许可证文件

ROCKCHIP_MPP_CONF_OPTS = "-DRKPLATFORM=ON" #编译选项 CONF_OPTS 最后会添加到Cmake等构建工具的构建选项中

ROCKCHIP_MPP_DEPENDENCIES += libdrm

ROCKCHIP_MPP_INSTALL_STAGING = YES #是否在starg空间中安装,当该库需要作为依赖库时,设置YES,最后会放到staging目录下

#根据config.in编译选项添加CMake编译选项
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
# 在rsync阶段进行git仓库操作
define ROCKCHIP_MPP_LINK_GIT  
       rm -rf $(@D)/.git
       ln -s $(SRCDIR)/.git $(@D)/
endef
ROCKCHIP_MPP_POST_RSYNC_HOOKS += ROCKCHIP_MPP_LINK_GIT #HOOK操作添加 见下文PS

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   #本来这些patch在上层目录,但是由于修改了ffmpeg的包源和版本,这些patch不再适用,放到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_VERSION = 4.4.1
#FFMPEG_SOURCE = ffmpeg-$(FFMPEG_VERSION).tar.xz
#FFMPEG_SITE = http://ffmpeg.org/releases
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 #实际上就是去检测ROCKCHIP_MPP这个包编好了吗
endif
···
# Override FFMPEG_CONFIGURE_CMDS: FFmpeg does not support --target and others
#阶段+_CMDS的变量表示对该阶段的操作覆写,此时CONFIGURE阶段的命令会执行下面定义的操作
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一背刺是提供了兼容方案的。


// AVStream.codec deprecated in favor of AVStream.codecpar
// https://github.com/FFmpeg/FFmpeg/blob/b6af56c034759b81985f8ea094e41cbd5f7fecfb/doc/APIchanges#L1039-L1040
#if LIBAVFORMAT_BUILD >= CALC_FFMPEG_VERSION(59, 16, 100)
//#if LIBAVFORMAT_BUILD >= CALC_FFMPEG_VERSION(57, 33, 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即可


#改一下version,然后针对不同版本编译选项做修改即可
#OPENCV4_VERSION = 4.5.4
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

# Disabled features (mostly because they are not available in Buildroot), but
# - eigen: OpenCV does not use it, not take any benefit from it.
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=OFF
      -DWITH_OPENCL=ON \  #添加OpenCL支持
      -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包


################################################################################
#
# rockchip-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
#
################################################################################

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
# needed to get utils/qv4l link flags right
LIBV4L_AUTORECONF = YES
# add host-gettext for AM_ICONV macro
LIBV4L_DEPENDENCIES += host-gettext

# fix uclibc-ng configure/compile
LIBV4L_CONF_ENV = ac_cv_prog_cc_c99='-std=gnu99'

# v4l-utils components have different licences, see v4l-utils.spec for details
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)

# IR BPF decoder support needs toolchain with linux-headers >= 3.18
# libelf and clang support
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
# protect against host version detection of moc-qt5/rcc-qt5/uic-qt5
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
# qt5 needs c++11 (since qt-5.7)
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是怎么编译的。


已解决

未解决

只是看看

最新评论

QQ|小黑屋| 飞凌嵌入式 ( 冀ICP备12004394号-1 )

GMT+8, 2024-12-27 11:34

Powered by Discuz! X3.4

© 2001-2013 Comsenz Inc.

返回顶部