menu

Multimedia User Guide(Rockchip Linux)

1. Overall

这里主要记录一些常见问题, 主要帮助通过gstreamer来在rockchip平台上做multimedia的开发.

首先介绍rockchip平台上视频编解码大概的流程

 vpu_service  -->  mpp --> gstreamer/ffmpeg --> app
  • vpu_service: 驱动
  • mpp: rockchip平台的视频编解码中间件
  • gstreamer/ffmpeg: 对接app的组件

目前rockchip提供的完整solution是基于gstreamer的,使用gstreamer的好处就是可以比较方便的基于pipeline的方式完整播放器, 编码器这些应用。 对gstreamer不了解的话,也可以看看博客里关于gstreamer的文章。

直接用使用底层的api, 比如通过mpp完成解码,也可以。但复杂应用下会很麻烦,因为你需要直接接触很多底层的概念,我们支持也很麻烦。。。 当然如果只是简单的输入码流,输出画面, 是可以的。 不过对编码来说, 使用Mpp会更好点

1.1. Note

建议先了解清楚graphic,因为客户很多的问题,其实都是关于graphic,可以搜博客里的另一篇Graphic user guide。 这篇其实在讲的也都是graphic。

另外你要很好的理解这块内容,最好接触下下面的概念: v4l2,dmabuf,gstreamer,drm,opengles,gbm 这块的开发,其实都是很灵活的,如果你足够了解这些基础的东西,很容易利用已有的软件做各种组合,如果你不了解的话,能做的事情就不多了。 主要在rockchip linux平台上,主要的关键还是dmabuf,我们所有的graphic和media,都是基于dmabuf来达到zero-copy,和你过去接触的fbmmap的方式会有很大的不一样。

2. Gstreamer-0

Rockchip have provide two gstreamer plugin packages:

(Note: Please choose debian branch for debian, do not use master or release branch.

这里现在变动了,这样分branch太麻烦,容易有歧义,现在全部使用release tag做基础版本号,做code base,临时的features,bug-fix的东西全部弄成补丁。 现在debian额外的补丁都单独放在这个仓库这里,你可以根据deb的版本号下载相应release tag的代码,然后打上这个目录的补丁。这样会比较清楚。

gstreamer-rockchip includes the following video decoders and encoders:

Elements Type Comments
mppvideodec Video Decoder h264, h265, jpeg, vp8, vp9
mpph264enc Video Encoder h264

gstreamer-rockchip-extra includes the following plugins:
please refer to gstreamer-rockchip-extra README on github for more infos.

Elements Type Comments
rkximagesink Video Render (sink) kmssink + ximagesink
kmssink Video Render (sink) overlay display
rgaconvert Video Converter video colorspace,format,size conversion
rkcamsrc Device Sources rockchip isp camera source

2.1. Pipeline Example

如有变动,以这里为准:
https://github.com/rockchip-linux/rk-rootfs-build/tree/master/overlay-debug/usr/local

Decode with uridecodebin/playbin:

gst-launch-1.0 uridecodebin uri=file:///usr/local/test.mp4  ! kmssink

Decode (JPEG):

gst-launch-1.0 -v videotestsrc  ! "video/x-raw,width=1920,height=1080"  ! queue ! jpegenc ! queue ! jpegparse ! queue ! mppvideodec ! kmssink 

Encode:

gst-launch-1.0 videotestsrc num-buffers=512 ! video/x-raw,format=NV12,width=1920,height= 1080,framerate=30/1 \
    ! queue ! mpph264enc ! queue ! h264parse ! mpegtsmux ! filesink location=/home/linaro/2k.ts

RGA Convert:

gst-launch-1.0 -v videotestsrc ! "video/x-raw,format=BGRA, width=1920,height=1080,framerate=30/1" ! \
 rgaconvert hflip=false vflip=false rotation=90 input-crop=0x0x1920x1080 output-crop=0x0x640x360 \
 output-io-mode=dmabuf capture-io-mode=dmabuf ! \
 "video/x-raw,format=NV12, width=640,height=640x360,framerate=30/1" ! kmssink

2.2. Usage

使用的gstreamer的时候,如果你的应用只是要发起一个编码或者解码过程,那直接参考gst-lauch,集成到应用皆可。 其工作方式就类似于在应用里每次输入一次命令一样

2.2.1. Player

如果是要做player,最好是使用qtmultimedia来做,qtmultimedia可以直接调用到gstreamer。不过要注意qtmultiemdia还涉及到显示问题, 请参考下面的Playback with QT multiemdia is slow。 或者debian下/usr/local/bin/test_dec-qt.sh脚本。

2.2.2. 自己管理Buffer

如果你的应用需要深度化的控制,自己管理buffer,而不是仅仅是在pipeline上开关, 那么可以参考博客里的另一篇gstreamer+opencv。

2.3. 编译

在板子编译,交叉编译请用docker or 自己研究。

./autogen.sh --disable-rkximage --prefix=/usr/
make
make install

3. Mpp

直接使用mpp的例子请看代码下的test/mpi_dec_test

mpp和libdrm结合使用的代码。 注意里面用到了RGA,其实没有必要使用, drm可以自己缩放显示。 sdl的东西也不要管,用的还是fb那套,现在sdl2好像也支持gbm和drm了。

更多的文档可以看mpp下readme。

3.1. 编译

在板子编译,交叉编译请用docker。

本地编译的话:

cmake -DRKPLATFORM=ON -DHAVE_DRM=ON && make

4. FFMpeg

FFMpeg从3.4以后就合并了mpp支持,直接从官网下打开mpp选项就行。
但是除非你比较了解,不然不推荐使用。不是xxx app使用的ffmpeg,我替换一个可以调的mpp的ffmpeg就可以让硬解码工作了,这里涉及到一个format和zero-copy的问题。另外FFMpeg不属于我们官方支持的东西,如果有bug,我们也只能支持到mpp部分。

FFMpeg配套的测试播放器可以用mpv, 不过要注意mpv也要用最新的才行。

4.1. 编译

mpv和ffmpeg的代码和编译选项看yocto里的bitbake文件。

自己配置交叉编译比较麻烦,没研究过,建议使用yocto,选中这两个package就可以了。

4.2. More

都写在meta-rockchip下的readme里了,就不重复了
https://github.com/rockchip-linux/meta-rockchip/tree/master/recipes-multimedia/ffmpeg
https://github.com/rockchip-linux/meta-rockchip/tree/master/recipes-multimedia/mplayer

5. Device Driver

5.1. VPU

rk的私有驱动, 一般不需要有接触, 使用mpp既可.
驱动的位置在drvier/video/rockchip下面, 有很多vpu_service, mpp_service一类的, 主要对应不同版本的驱动, 不用细究, sdk给出来什么就用什么。

5.2. RGA

Source:
https://github.com/rockchip-linux/kernel/tree/release-4.4/drivers/media/platform/rockchip-rga

关键词: v4l2 m2m
Demo: https://github.com/wzyy2/rga-v4l2-demo

rga linux版本的驱动是根据v4l2 m2m的api写出来, 如果需要直接操作v4l2 device, 最好是参考驱动里的rga.c和v4l2 m2m的userspace demo, 目前我们并没有提供任何的wrap lib.

6. FAQ

6.1. I have use mppvideodec/mppvideoenc, however, it is slow.

检查下你是不是用了videoconvert, 如果使用了videoconvert, 如果用了, 那CPU会参与进去转颜色格式, 导致性能下降. 还有检查下你使用的sink, 想xvimagesink这种, 也是CPU直接拷贝的, 速度会很慢的. 可以的话尽量使用glimagesink, wayland(gpu)和kmssink, rkximagesink(drm).其中drm的性能最好.另外要注意使用gpu的话, 在x11上有稍微的性能缺陷.

背景知识: 图像和视频这种的Buffer, 一般为了DMA coherent, 都是uncached, 这种情况下, 如果CPU要操作, 那耗时是很大的.

6.2. Playback with QT multiemdia is slow

同上, 需要指定sink, 具体的方法根据display backend不同而不同, 见:
https://github.com/rockchip-linux/meta-rockchip-extra/tree/master/recipes-rk/autostart/autostart

6.3. How to build

Debian的使用docker, yocto的话本身就是编译工具. 或者你自己想法办法, 这个不是一个应该问的问题.

6.4. 怎么playbin软解的时候用ximagesink, 硬解用rkx

可以修改caps https://github.com/wzyy2/gstreamer-rockchip/commit/6c4672a69fe4fc0aa08853825fb39014a26a8746

这样可以让autovideosink强制mppvideodec输出到rkximagesink上,而没mppvideodec就会走ximagesink:
https://github.com/wzyy2/gstreamer-rockchip/commit/6c4672a69fe4fc0aa08853825fb39014a26a8746

6.5. 如何多路合成

多路合成可以通过rga设置好crop,把所有的影片copy到一个buffer上去,但是这个目前通过gstreamer还没有办法做。
一个可行的办法是用通过3.4以上版本ffmpeg调用mpp解码,或者gstreamer的appsink(参考gstreamer+opencv),得到含有drm_prime的frame,取出dmabuf,通过v4l2的ioctl操作rga,把取出合成到目标buffer上。目标buffer可以通过drm申请,显示也可以通过drm显示。

这个主要的问题是没有写demo,所以需要user根据前面的rga-v4l2-demo和网络上的资料。
也可以看上面那个“mpp和libdrm结合使用的代码”, 里面就使用到了RGA。

6.6. UI overlay 视频

这个其实挺hack的。。等以后看看有没有好的办法吧。

https://github.com/rockchip-linux/meta-rockchip-extra/tree/master/demo/meta-player-qt

http://blog.iotwrt.com/tips/2017/06/04/swap-layer/

6.7. kmssink/rkxiamgesink双屏输出

因为kmssink和rkxiamgesink都是基于屏幕做overlay输出的,所以如果要支持双屏,必须要指定对应的屏幕,不然只会在默认的屏幕上输出。 指定屏幕可以通过设置connector_id property来完成,connector在drm是什么意思,可以看graphic guide。

6.8. 获得uncache的buffer

默认VPU和GPU出来都是UnCache的buffer,要处理的话最好是CPU拷贝下到正常的内存再处理。 用RGA拷到正常内存也可以,但是需要改动内核代码,暂时还没试过(V4L2是支持申请uncache的buffer的)。

但是走DRM的话(也就是我们mpp里用的),应该是没办法直接出cache的buffer的。