将danser-go移植至树莓派的arm linux平台,并且使用树莓派的硬件加速编码视频

幼刀之小丛雨 发布于 2025-02-11 4 次阅读


介绍

Wieku/danser-go: Dancing visualizer of osu! standard maps and custom osu! client written in Go. Also a generator for osu! videos.是由Wieku基于go语言开发的一款为了osu!standard的可视化的多功能的演奏工具,同时可以渲染为视频。与osr2mp4不同,danser-go使用了硬件加速功能来提供更好的观感,要求显卡至少支持OpenGL3以上版本,并且支持视频的硬件编码。同时它也是一款跨平台的应用程序,同时支持Windows和Linux平台。

树莓派在Debian12的更新中升级了GPU驱动程序,初步的支持了OpenGL3,这使得运行danser-go成为了可能。并且树莓派的GPU也支持硬件编码视频。这让我有了移植danser-go到arm平台上的想法。

本项目的灵感来源于基于如下讨论:ARM64 support? issue #332 Wieku/danser-go

我向其添加了树莓派的V4L2编码器的支持,可以在我的fork版本nianweb-dev/danser-go at arm64获取我的详细修改。

安装和构建

前往Release · nianweb-dev/danser-go获取我构建的二进制文件,你也可以使用arm64分支里面的dist脚本手动进行编译。

已知问题

  • 由于缺少链接符号,cimgui无法工作,我回滚到了使用cimgui之前的版本。
  • 和2x分辨率的某些皮肤存在兼容性问题,使用2x皮肤可能会遇到黑屏的图形错误,疑似树莓派的显存工作不正常,需要手动修改树莓派的显存分配。
  • OpenMAX和MMAL需要32位操作系统,我不是很想构建32位版本。在64位操作系统上可以通过Video4Linux2访问硬件编码器。
  • 树莓派在某个版本的linux内核破坏了编码器,需要降级到特定版本的内核才能正常使用硬件视频编码。

故障排除

OpenGL版本

运行danser-cli或danser时,提示OpenGL版本号不正确。

Launcher crashed with message:
VersionUnavailable: GLX: Failed to create context: GLXBadFBConfig

解决方案:使用MESA_GL_VERSION_OVERRIDE环境变量改写OpenGL版本号以绕过版本检测,注意:即使绕过版本号检测,硬件渲染仍然是可用的,因为树莓派的GPU已经实现了OpenGL3。

export MESA_GL_VERSION_OVERRIDE=3.3 
./danser

视频编码故障

由于树莓派上游代码升级,使用1080p硬件编码,可能会遇到如下错误:

[  848.017176] ------------[ cut here ]------------
[  848.017180] WARNING: CPU: 2 PID: 5499 at drivers/media/common/videobuf2/videobuf2-core.c:1613 vb2_start_streaming+0x114/0x170 [videobuf2_common]
[  848.017219] Modules linked in: md5 rfcomm veth nft_masq br_netfilter xfrm_user xfrm_algo xt_addrtype bridge stp llc xt_conntrack xt_tcpudp xt_mark xt_MASQUERADE nft_compat nft_chain_nat nf_nat nf_conntrack nf_defrag_ipv6 nf_defrag_ipv4 vhost_vsock vmw_vsock_virtio_transport_common vhost vhost_iotlb vsock wireguard libchacha20poly1305 chacha_neon poly1305_neon ip6_udp_tunnel udp_tunnel libcurve25519_generic libchacha tun nf_tables nfnetlink overlay cmac algif_hash aes_arm64 aes_generic algif_skcipher af_alg bnep binfmt_misc brcmfmac_wcc brcmfmac joydev hci_uart brcmutil btbcm cfg80211 bcm2835_isp(C) bluetooth bcm2835_codec(C) bcm2835_v4l2(C) rpivid_hevc(C) videobuf2_vmalloc bcm2835_mmal_vchiq(C) v4l2_mem2mem ecdh_generic videobuf2_dma_contig videobuf2_memops videobuf2_v4l2 ecc videodev rfkill libaes videobuf2_common raspberrypi_hwmon mc snd_bcm2835(C) vc_sm_cma(C) raspberrypi_gpiomem nvmem_rmem uio_pdrv_genirq uio tcp_bbr i2c_dev ecryptfs fuse dm_mod nfsd ip_tables x_tables ipv6 hid_logitech ff_memless vc4 v3d
[  848.017407]  snd_soc_hdmi_codec drm_display_helper cec drm_dma_helper gpu_sched drm_shmem_helper i2c_brcmstb drm_kms_helper drm drm_panel_orientation_quirks snd_soc_core snd_compress snd_pcm_dmaengine snd_pcm snd_timer snd backlight
[  848.017459] CPU: 2 PID: 5499 Comm: ffmpeg Tainted: G        WC         6.6.74+rpt-rpi-v8 #1  Debian 1:6.6.74-1+rpt1
[  848.017472] Hardware name: Raspberry Pi 4 Model B Rev 1.2 (DT)
[  848.017477] pstate: 60000005 (nZCv daif -PAN -UAO -TCO -DIT -SSBS BTYPE=--)
[  848.017483] pc : vb2_start_streaming+0x114/0x170 [videobuf2_common]
[  848.017511] lr : vb2_start_streaming+0x74/0x170 [videobuf2_common]
[  848.017526] sp : ffffffc08369bb40
[  848.017529] x29: ffffffc08369bb40 x28: ffffffe01c7bad38 x27: ffffffe01c7490b0
[  848.017541] x26: 0000000000000000 x25: ffffff804372cd30 x24: ffffff805e61b800
[  848.017550] x23: 0000000000000000 x22: 0000000000000000 x21: ffffff804255a470
[  848.017558] x20: ffffff804255a298 x19: 00000000fffffffd x18: 00000000fffffffe
[  848.017567] x17: 6c696146203a676e x16: 696d61657274735f x15: 74726174735f6365
[  848.017576] x14: 646f635f35333832 x13: 332d20746572202c x12: 74726f7020702f69
[  848.017584] x11: 20676e696c62616e x10: ffffffe0946c3a38 x9 : ffffffe093203d10
[  848.017592] x8 : 00000000ffffefff x7 : ffffffe0946c3a38 x6 : 80000000fffff000
[  848.017600] x5 : 0000000000000000 x4 : 0000000000000000 x3 : 0000000000000000
[  848.017608] x2 : 0000000000000000 x1 : ffffffe01c6da000 x0 : 0000000000000001
[  848.017616] Call trace:
[  848.017621]  vb2_start_streaming+0x114/0x170 [videobuf2_common]
[  848.017637]  vb2_core_streamon+0x100/0x1d0 [videobuf2_common]
[  848.017651]  vb2_streamon+0x20/0x78 [videobuf2_v4l2]
[  848.017667]  v4l2_m2m_ioctl_streamon+0x40/0xa8 [v4l2_mem2mem]
[  848.017689]  v4l_streamon+0x2c/0x40 [videodev]
[  848.017751]  __video_do_ioctl+0x170/0x3e0 [videodev]
[  848.017784]  video_usercopy+0x208/0x770 [videodev]
[  848.017817]  video_ioctl2+0x20/0x40 [videodev]
[  848.017850]  v4l2_ioctl+0x48/0x70 [videodev]
[  848.017883]  __arm64_sys_ioctl+0xb4/0x100
[  848.017897]  invoke_syscall+0x50/0x128
[  848.017908]  el0_svc_common.constprop.0+0x48/0xf0
[  848.017914]  do_el0_svc+0x24/0x38
[  848.017921]  el0_svc+0x38/0xd0
[  848.017929]  el0t_64_sync_handler+0x100/0x130
[  848.017934]  el0t_64_sync+0x190/0x198
[  848.017940] ---[ end trace 0000000000000000 ]---
[h264_v4l2m2m @ 0x559dcc0ef0] output set status ON failed: err=No such process
[h264_v4l2m2m @ 0x559dcc0ef0] VIDIOC_STREAMON failed on output context
Error submitting video frame to the encoder

解决方案:在树莓派的终端运行如下命令,降级linux内核到v4l2编码器驱动程序到可以正常工作的内核版本。

sudo rpi-update 8e3a9ee6c24b86128cc71fa8c6bcb3e98f92ec85
sudo reboot

如果有疑问或者问题需要解决,欢迎在本文的讨论区或者我的github issue与我讨论!