RIoTBoard开发板系列笔记—— gstreamer + vpu实现视频硬件解码播放

Posted 倾我一生来读

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了RIoTBoard开发板系列笔记—— gstreamer + vpu实现视频硬件解码播放相关的知识,希望对你有一定的参考价值。

i.mx6 solo芯片中包含一个VPU (video processing unit),可以进行视频硬件编解码加速,之前RIoTBoard开发板系列笔记(四)—— 使用VPU硬件解码文章简单的记录了使用VPU解码的过程,没有render也没有播放控制。一般音视频开发需要一个框架来实现demux 、decoder、render以及基本的播放控制,linux平台首选的多媒体框架就是GStreamer 。GStreamer 是 GNOME 桌面环境下用来构建流媒体应用的多媒体框架,,详细的内容可以自行去查阅资料,本篇主要记录RIoTBoard使用gstreamer实现视频硬件解码以及播放渲染的过程。

1 multimedia 系统构建

因为要使用 VPU等硬件,还得需要使用Yocto构建系统,系统构建是基于上一篇博客的基础,使用X11作为图形显示库:

DISTRO=fsl-imx-x11 MACHINE=imx6dl-riotboard source  fsl-setup-release.sh -b build-x11

构建系统时需要选择fsl-image-multimedia-full,这样才能把gstreamer 和gst-imx编译进去。

bitbake -k fsl-image-multimedia-full

编译uboot过程中遇到的error可以参考上一篇博客。

2 系统烧写测试

编译完成后将SD card iamge烧写到TF卡中,烧写方法参见上一篇博客。

2.1 gstreamer video sink plugin 测试

系统启动后输入root登陆到console,检查一下imx提供的gstreamer plugin:

gst-inspect-1.0 | grep IMX

结果如下所示,vpudec就是imx提供的支持video硬件解码的plugin。

root@imx6dl-riotboard:~# gst-inspect-1.0 | grep IMX
imxcompositor:  imxcompositor_ipu: IMX ipu Video Compositor
imxcompositor:  imxcompositor_g2d: IMX g2d Video Compositor
imxv4l2:  imxv4l2sink: IMX Video (video4linux2) Sink
imxv4l2:  imxv4l2src: IMX Video (video4linux2) Source
aiurdemux:  aiurdemux: IMX Aiur universal demuxer
beepdec:  beepdec: IMX Beep universal decoder
overlaysink:  overlaysink: IMX Video (video compositor) Sink
imxvideoconvert:  imxvideoconvert_ipu: IMX ipu Video Converter
imxvideoconvert:  imxvideoconvert_g2d: IMX g2d Video Converter
vpu:  vpuenc_h264: IMX VPU-based AVC/H264 video encoder
vpu:  vpuenc_mpeg4: IMX VPU-based MPEG4 video encoder
vpu:  vpuenc_h263: IMX VPU-based H263 video encoder
vpu:  vpuenc_jpeg: IMX VPU-based JPEG video encoder
vpu:  vpudec: IMX VPU-based video decoder

video sink plugin有以下几种可用:

ximagesink:  ximagesink: Video sink
fbdevsink:  fbdevsink: fbdev video sink

ximagesink是基于X11的video 显示plugin,因此需要先配置好X11。系统启动后需要修改/etc/X11/xorg.conf 配置文件,修改内容如下:

Section "Device"
    Identifier  "Kernel Framebuffer Device"
    Driver      "vivante"
    Option      "fbdev" "/dev/fb0"
EndSection

Section "ServerFlags"
    Option "BlankTime"  "0"
    Option "StandbyTime"  "0"
    Option "SuspendTime"  "0"
    Option "OffTime"  "0"
EndSection

Section "Module"
 Load "vivante"
 Load "shadow"
EndSection

然后设置DISPLAY环境变量,将图形显示到当前窗口:

export DISPLAY=:0

然后启动 X Window System:

startx

执行成功后会有如下log:


使用gstreamer videotestsrc测试一下ximagesink显示是否正常:

GST_DEBUG=*:4  gst-launch-1.0 -v videotestsrc ! ximagesink

显示效果图:

fbdevsink可以也直接使用以下命令测试:

GST_DEBUG=*:4  gst-launch-1.0 -v videotestsrc ! fbdevsink

2.2 gstreamer 实现视频播放

gstreamer 视频播放的时候一般选择filesrc + decodebin + sink 这三个plugin就可以实现视频播放,因此可使用以下命令播放视频:

gst-launch-1.0 filesrc location=/home/root/nfs_server/movie1.mp4 !  decodebin !  videoconvert ! ximagesink

其中videoconvert 主要是用于colorspace的转换,因为解码后的数据可能是多种格式的,需要统一转换成video sink支持的colorspace。

root@imx6dl-riotboard:~# gst-inspect-1.0 videoconvert
Factory Details:
  Rank                     none (0)
  Long-name                Colorspace converter
  Klass                    Filter/Converter/Video
  Description              Converts video from one colorspace to another
  Author                   GStreamer maintainers <gstreamer-devel@lists.freedesktop.org>

播放效果如下:

riotboard卡顿

播放过程中发现比较卡,好长时间才render一帧,而且会有如下log印出:

WARNING: from element /GstPipeline:pipeline0/GstXImageSink:ximagesink0: A lot of buffers are being dropped.
Additional debug info:
../../../../git/libs/gst/base/gstbasesink.c(2902): gst_base_sink_is_too_late (): /GstPipeline:pipeline0/GstXImageSink:ximagesink0:
There may be a timestamping problem, or this computer is too slow.

此时说明cpu 处理不过来了,因为使用的是VPU 硬件解码,解码速度应该完全没有问题,而render 也不会有太大问题,唯一可能出问题的就是中间的videoconvert这个处理速度太慢,这个组件完全是软件进行colorspace转换,速度可能满足不了30pfs的要求,后来发现imx 提供了硬件convert,于是改用硬件convert测试一下。

imxvideoconvert:  imxvideoconvert_ipu: IMX ipu Video Converter
imxvideoconvert:  imxvideoconvert_g2d: IMX g2d Video Converter

使用硬件convert的播放命令如下:

gst-launch-1.0 filesrc location=/home/root/nfs_server/movie1.mp4 !  decodebin !  imxvideoconvert_ipu ! ximagesink

果然,播放1920*1080的视频流畅多了,效果如下:

riotboard播放视频流畅

3 参考

1 https://gstreamer-devel.narkive.com/CZ46YRpI/how-to-demux-a-mp4-file-to-a-encoded-264-video-file-by-qtdemux
2 https://community.toradex.com/t/how-to-operate-with-aiurdemux-in-gstreamer-1-0/4726
3 https://community.nxp.com/t5/i-MX-Processors/Playing-multiple-videos-on-mx6/m-p/619326

rIoTboard学习系列

 

刚在咸鱼买了块开发板,比较老了14年的,SOC为imx6solo,内核3.10,uboot2009的,准备先移植一个较新的uboot

到nxp的git下获取他们维护的uboot,网址http://git.freescale.com/git/cgit.cgi/imx/uboot-imx.git

选择imx_v2016.03_4.1.15_2.0_ga的brance,git太慢了,直接下载rel_imx_4.1.15_1.2.0_ga.tar.bz2源码包。

到Makefile中更改CROSS_COMPILE

make riotboard_defconfig

make -j8

出现

riotboard/rel_imx_4.1.15_1.2.0_ga/arch/arm/imx-common/cpu.c:199: undefined reference to `uclass_get_device‘

查看配置文件是没定义CONFIG_DM相关的就是驱动模型,因为这个板子uboot是维护的,所以就换了个版本

仓库地址https://gitlab.denx.de/u-boot/u-boot/tree/v2016.09

这次顺利通过编译,下载到tf卡上启动没有反应,串口无输出。中间反复检查了很多方面,到最终成功启动有两个问题

1.烧写命令dd iflag=dsync oflag=dsync if=u-boot.imx of=/dev/sdb seek=2

seek=blocks:从输出文件开头跳过blocks个块后再开始复制

uboot.imx = ivt + dcd + uboot.bin

imx的soc通过sd启动时,u-boot.imx要有一个0x400的offset,也就是1024字节,sd卡一个扇区512byte,所以跳过2个扇区,从第三个扇区烧写

开始时没搞清seek的定义,一直用的seek=3....

2.拨码开关

使用手册的截图

技术图片

重点来了,这个是背后的SD大卡的启动选项。。。。

发现这点是在网上搜到的一个pdf

技术图片

 

调整后顺利启动

调老板子运气真的挺重要的,这个开发板国内资料真的没多少,而且都是3.x的。

还有个小细节,上面说的u-boot.imx是通过uboot自带的工具./tool/imximage实现的在正常的uboot.bin前加上必要的数据(例如内存初始化等),其中的数据想DCD等都是保存在/board/xxx/xxx.cfg 里的,但是这块开发板下没有 .cfg,而在/configs/riotboard_defconfig中指定了CONFIG_SYS_EXTRA_OPTIONS="IMX_CONFIG=board/boundary/nitrogen6x/nitrogen6s1g.cfg,MX6S,DDR_MB=1024,ENV_IS_IN_MMC"

即nitrogen6s的板子,查看发现其中一句 BOOT_FROM      spi ,修改为sd。后来测试即使是spi也可以正常启动,没有深入研究。

 

 

       最终uboot还是用的rel_imx_4.1.15_2.0.0_ga,就是nxp git下的,make riotboard_defconfig 出现找不到ldo_mode_set这个函数的定义,

因为在board/embest/mx6boards/mx6boards.c中没有实现,在bug信息的xxx/cpu.c中有如下代码

#if defined(CONFIG_LDO_BYPASS_CHECK)
ldo_mode_set(check_ldo_bypass());
#endif

于是在include/configs/embestmx6boards.h 最后 #undef CONFIG_LDO_BYPASS_CHECK

编译通过。

启动后ping不通:

Using FEC device 

ARP Retry count exceeded; starting again
ping failed; host 192.168.0.12 is not alive

 试了网上说的增加TIMEOUT的值,试了也没有效果。后来参考embest维护的3.x的uboot

注释掉board/embest/mx6boards/mx6boards.c中

#if 1
int mx6_rgmii_rework(struct phy_device *phydev)
{
/* from linux/arch/arm/mach-imx/mach-imx6q.c :
* Ar803x phy SmartEEE feature cause link status generates glitch,
* which cause ethernet link down/up issue, so disable SmartEEE
*/
phy_write(phydev, MDIO_DEVAD_NONE, 0xd, 0x7);
phy_write(phydev, MDIO_DEVAD_NONE, 0xe, 0x805d);
phy_write(phydev, MDIO_DEVAD_NONE, 0xd, 0x4003);

return 0;
}
#endif

添加

int mx6_rgmii_rework(struct phy_device *phydev)
{
unsigned short val;

/* To enable AR8031 ouput a 125MHz clk from CLK_25M */
phy_write(phydev, MDIO_DEVAD_NONE, 0xd, 0x7);
phy_write(phydev, MDIO_DEVAD_NONE, 0xe, 0x8016);
phy_write(phydev, MDIO_DEVAD_NONE, 0xd, 0x4007);

val = phy_read(phydev, MDIO_DEVAD_NONE, 0xe);
val &= 0xffe3;
val |= 0x18;
phy_write(phydev, MDIO_DEVAD_NONE, 0xe, val);

/* introduce tx clock delay */
phy_write(phydev, MDIO_DEVAD_NONE, 0x1d, 0x5);
val = phy_read(phydev, MDIO_DEVAD_NONE, 0x1e);
val |= 0x0100;
phy_write(phydev, MDIO_DEVAD_NONE, 0x1e, val);

return 0;

技术图片技术图片技术图片技术图片技术图片技术图片技术图片技术图片技术图片技术图片技术图片技术图片

以上是关于RIoTBoard开发板系列笔记—— gstreamer + vpu实现视频硬件解码播放的主要内容,如果未能解决你的问题,请参考以下文章

iMX6系列应用笔记-iMX6Q开发板QT相关应用讲解

MYD-YA157C系列定制板RM500Q-GL驱动移植笔记

i.MX 8MQuad开发笔记 -01 | i.MX 8MQuad EVK 开发板上手

i.MX 8MQuad开发笔记 -01 | i.MX 8MQuad EVK 开发板上手

Buildroot系统构建学习笔记(以百问网imx6ull开发板为例)

第一章:学习笔记说明!