前言:
RK3399Pro拥有六路1080P30帧解码能力,很多开发者不知道如何快速搭建这么一个Demo,这里我们社区开发者团队编写了一套Toybrick简单上手的python库,可以让大家快速上手编写各种demo。
该库目前还在非常早期的测试版本阶段,还未正式发布。并且需要注意以下几点:
- 该python模块仅用于快速开发调试,方便同学们将注意力放在神经网络上,但是不建议用于正式项目。
- 该python模块仅授权Toybrick开发版使用,包含Toybrick 3399Pro和Toybrick 1808计算棒,其他产品我们无法提供支持。
- 该python模块不开源。所有代码在各个模块的demo中都有,正式做项目还请参看RK的各个模块的demo来改。
- 该python模块是为了让开发者专注于神经网络应用的调试,抽象的比较高层,不会提供太多底层控制接口。
- 有Bug和需求反馈,直接回在帖子里,但是可能修改更新不会很及时,请见谅。
思路分析:
RK3399Pro的VPU支持多路编解码,主控想完成多路编解码并显示,需要有一些开发技巧:
- 使用多线程处理不同的通路,避免时间被卡在相互等待上。
- 显示建议用GPU OpenGL来做,速度快,也避免GPU在整个项目中被闲置。
- Demo主要利用Rtsp获取数据,每个线程做的事基本就是 : Rtsp获取数据 - 解码 - 显示
逻辑代码:
#!/usr/bin/env python3.6
import os
import toybrick as toy
import time
import threading
def func_rtspdisplay(gl, index, url, usr, pwd):
rtsp = toy.input.createRtspClient(url, usr, pwd)
rtsp.connect()
last = time.time()
while rtsp.is_opened():
frame = rtsp.read_rgb(640, 360)
now = time.time()
gl.show(index, frame)
print("> [%d] got frame. use = %f s" % (index, now - last))
last = now
print('# End of Thread %d' % (index))
if name == 'main':
os.system('iptables -F') # Disable Firewall
gl = toy.output.createGLDrmDisplay(toy.DisplayPort.HDMI_A)
idx0 = gl.add_view(0, 180, 640, 360)
idx1 = gl.add_view(640, 180, 640, 360)
idx2 = gl.add_view(1280, 180, 640, 360)
idx3 = gl.add_view(0, 540, 640, 360)
idx4 = gl.add_view(640, 540, 640, 360)
idx5 = gl.add_view(1280, 540, 640, 360)
t0 = threading.Thread(target=func_rtspdisplay, args = (gl, idx0, "rtsp://192.168.169.13/cam/realmonitor?channel=1&subtype=0", "admin", "admin123"))
t1 = threading.Thread(target=func_rtspdisplay, args = (gl, idx1, "rtsp://192.168.169.16/cam/realmonitor?channel=1&subtype=0", "admin", "admin123"))
t2 = threading.Thread(target=func_rtspdisplay, args = (gl, idx2, "rtsp://192.168.169.13/cam/realmonitor?channel=1&subtype=0", "admin", "admin123"))
t3 = threading.Thread(target=func_rtspdisplay, args = (gl, idx3, "rtsp://192.168.169.16/cam/realmonitor?channel=1&subtype=0", "admin", "admin123"))
t4 = threading.Thread(target=func_rtspdisplay, args = (gl, idx4, "rtsp://192.168.169.13/cam/realmonitor?channel=1&subtype=0", "admin", "admin123"))
t5 = threading.Thread(target=func_rtspdisplay, args = (gl, idx5, "rtsp://192.168.169.16/cam/realmonitor?channel=1&subtype=0", "admin", "admin123"))
t0.start()
t1.start()
t2.start()
t3.start()
t4.start()
t5.start()
t0.join()
t1.join()
t2.join()
t3.join()
t4.join()
t5.join()
代码解析:
- main函数首先创建了一个OpenGL via DRM的显示接口,输出目的地是HDMI-A
- 然后该接口允许我们在屏幕上新建6个不同位置的显示窗口
- 完成后新建了6个线程,每个线程都执行同样的一个函数 func_rtspdisplay
- func_rtspdisplay函数都通过传入参数获取rtsp码流,然后直接显示在第二步建立的gl窗口上。
该套库的特点:
- 自动使用VPU硬件进行解码
- 解码到缩放到显示全部是硬件连续地址,没有mmap虚拟地址,完全0拷贝,速度很快。
- 使用GPU绘制6路显示接口,不占用CPU资源。
原作者:jefferyzhang