首页 > 最新资讯 > Jetson Nano 2GB 系列文章36:加入USB输入与RTSP输出
Jetson Nano 2GB 系列文章36:加入USB输入与RTSP输出

Jetson Nano 2GB 系列文章36:加入USB输入与RTSP输出

2021-10-13 09:32

#人工智能 #深度学习


本文以上一期 Python 版的 deepstream-test1 为基础,在输入与输出添加功能的两个扩展应用:deepstream-teat1-usbcamdeepstream-teat1-rtsp-out 中,分别将输入源从视频文件变成 USB 摄像头,以及将输出从显示屏变成 RTSP 视频流。接下去同样从代码内容来看看这两个部分需要进行怎样的修改。

将输入源从视频文件修改成 USB 摄像头

文件路径:

/sources/deepstream_python_apps/apps的deepstream-test1-usbcam/deepstream_test_1_usb.py 

范例功能:将 deepstream-test1 的视频文件输入改成 USB 摄像头

插件流:v4l2src --> videoconvert--> nvvideoconvert --> nvstreammux --> nvinfer --> nvvideoconvert --> nvdsosd --> nvegltransform --> nveglglessink

修改重点:

将原本数据源插件从 filesrc 改成 v4l2src

将原本格式转换插件从 h264 相关的,改成符合 USB 摄像头原始数据格式相关的

现在进去看看 deepstream_test_1_usb.py 与前面 deepstream_test_1.py 有那些修改的地方。

首先在创建阶段的修改,原本用 H264 视频文件输入的部分,需要以下四个元件:

source = Gst.ElementFactory.make("filesrc", "file-source")h264parser = Gst.ElementFactory.make("h264parse", "h264-parser")decoder = Gst.ElementFactory.make("nvv4l2decoder", "nvv4l2-decoder")streammux = Gst.ElementFactory.make("nvstreammux", "Stream-muxer")

如今要改成USB摄像头输入时,就需要把输入的元件改成以下六个元件:

source = Gst.ElementFactory.make("v4l2src","usb-cam-source")caps_v4l2src = Gst.ElementFactory.make("capsfilter","v4l2src_caps")vidconvsrc = Gst.ElementFactory.make("videoconvert","convertor_src1")nvvidconvsrc=Gst.ElementFactory.make("nvvideoconvert","convertor_src2")caps_vidconvsrc = Gst.ElementFactory.make("capsfilter","nvmm_caps")streammux = Gst.ElementFactory.make("nvstreammux","Stream-muxer")

这里面的第 3~4 行添加 videoconvert->nvvideoconvert 的元件,最主要是因为 nvvideoconvert 并不支持所有原始格式,例如某些品牌 USB 摄像头常用的 YUYV 这种格式,但是我们需要获得 nvvideoconvert 所能支持的摄像头原始格式,于是 GStreamer 的 videoconvert 就能起到调节的作用。

Videoconvert 插件确保提供支持原始格式的超集,然后再由 nvvideoconvert 插件调用 NvBufSurface API 将传入的原始缓冲区,转换格式存到 NVMM Mem 里。

接下去在设置 caps_v4l2src 与 caps_vidconvsrc 元件参数的部分,并将输入源设定为程式所接受的第一个参数指,最后还设置“sync=false”以避免在显示接收器处出现延迟帧下降,其他设定指与 test1 的内容一致:

caps_v4l2src.set_property('caps',Gst.Caps.from_string("video/x-raw, framerate=30/1"))caps_vidconvsrc.set_property('caps', \ Gst.Caps.from_string("video/x-raw(memory:NVMM)"))source.set_property('device',args[1])。。。。sink.set_property('sync',False)

后面的元件添加、元件连接、创建事件循环、播放并收听事件等部分的代码,则与 deepstream_test_1.py 是一致的,甚至 osd_sink_pad_buffer_probe 的代码也是完全一样的,这表示我们只要简单地将输入阶段的插件进行合适的替换,就能修改输入源的变更,十分简单。

请先将 USB 摄像头连接到设备上,然后执行以代码: 

cd根目录>/sources/deepstream_python_apps/appcd deepstream-test1-usbcampython3 deepstream_test_1_usb.py

下面截屏就是打开 USB 摄像头,对着屏幕上播放的视频进行识别的结果:

 

总的来说,大约就修改不到 10 行的内容,就将原本视频文件输入的功能改成 USB 输入的方式,里面最关键的重点就在于需要加入 videoconvert 这个插件,来适应各个摄像头硬件厂家所支持的原始格式。

您可以照此自行尝试将输入源修改成 CSI 摄像头或 IP 摄像头输入,或者可以在多种输入源中任选一种作为输入的方式。

将输出从显示屏转成 RTSP 视频流

文件路径:/sources/deepstream_python_apps/apps的deepstream-test1-rtsp-out/deepstream_test1_rtsp_out.py

范例功能:将 deepstream-test1 的输出透过 RTSP 协议转向其他电脑

修改重点:在 nvdsosd 之后添加将格式转成符合 RSTP 协议的 H264 格式,主要如下:

nvvideoconvert:将视频颜色格式从 RGBA 转换成 I420

CapsFilter:对数据实施限制(无数据修改)

nvv4l2h264enc:将 I420 格式的原始数据转成 H264 编码

RtpH264Pay:将 H264 编码的有效负载转换为 RFC 3984 格式的 RTP 数据包

UDPSink:向网络发送 UDP 数据包,当 rtph264pay 数据包与 RTP 有效负载配对时,就会生成 RTP 视频流。

这是一种实用性非常高的应用,很多时候部署在边缘端的 AIOT 计算设备,无法在机器上直接安装显示器去监控现场的状况,这时候用 RTSP 协议发出视频流,我们可以在其他设备上透过 VLC 之类的视频播放器,观看边缘设备上的识别结果,过程中可能会有些许的延迟,但总体来说确实非常方便部署的技术。

由于本实验需要用到 gst-rtsp-server 库,因此需要先进行以下的安装:

sudo apt updatesudo apt-get install libgstrtspserver-1.0-0 gstreamer1.0-rtspsudo apt-get install libgirepository1.0-devsudo apt-get install gobject-introspection gir1.2-gst-rtsp-server-1.0

这个项目的输入部分还是使用 deepstream-test1 的 H264 视频文件,唯一改变的地方就是输出的方式,也就是在 deepstream_test_1.py 管道流 nvdsosd 之前的代码可以不做更动,重点在后面的部分。

在 deepstream_test1_rtsp_out.py 里面,从第 179 行(nvdsosd 之后)才开始产生变化,这里开始添加一些插件元件:

nvvidconv_postosd = Gst.ElementFactory.make("nvvideoconvert", "convertor_postosd")# 创建caps过滤器caps = Gst.ElementFactory.make("capsfilter", "filter")caps.set_property("caps",   Gst.Caps.from_string("video/x-raw(memory:NVMM), format=I420"))# 根据输入参数选择使用的编码器,预设为H264if codec == "H264": encoder = Gst.ElementFactory.make("nvv4l2h264enc", "encoder")elif codec == "H265": encoder = Gst.ElementFactory.make("nvv4l2h265enc", "encoder")encoder.set_property('bitrate', bitrate)# 如果是在 Jetson 设备上,执行下面的设定if is_aarch64(): encoder.set_property('preset-level', 1) encoder.set_property('insert-sps-pps', 1)      encoder.set_property('bufapi-version', 1)       # 使有效负载将视频编码为RTP数据包if codec == "H264": rtppay = Gst.ElementFactory.make("rtph264pay", "rtppay")elif codec == "H265":   rtppay =   Gst.ElementFactory.make("rtph265pay", "rtppay")    # 建立 UDP 接收器updsink_port_num = 5400sink = Gst.ElementFactory.make("udpsink", "udpsink")# 设定接收器的值sink.set_property('host', '224.224.255.255')sink.set_property('port', updsink_port_num)sink.set_property('async', False)sink.set_property('sync', 1)

接下去就是按照 file-source -> h264-parser -> nvh264-decoder -> nvinfer -> nvvidconv -> nvosd -> nvvidconv_postosd -> caps -> encoder -> rtppay -> udpsink  顺序,将元件依序进行连接。

以上部分的操作逻辑与先前所说的都是一致的,最后只剩一个部分,就是在代码第 276~286 行,需要调用 Gstreamer 的 gst-rtsp-server 库的 GstRtspServer 对象,细节请自行参考 https://github.com/GStreamer/gst-rtsp-server

# Start streamingrtsp_port_num = 8554 # 设定端口值server = GstRtspServer.RTSPServer.new()server.props.service = "%d" % rtsp_port_numserver.attach(None)factory = GstRtspServer.RTSPMediaFactory.new()factory.set_launch( "( udpsrc name=pay0 port=%d buffer-size=524288 caps=\"application/x-rtp, media=video, clock-rate=90000, encoding-name=(string)%s, payload=96 \" )" % (updsink_port_num, codec))factory.set_shared(True)server.get_mount_points().add_factory("/ds-test", factory) # 设定加载点

最后面的 mount_points 设定为“/ds-test”,因此将来在其他设备上要读取 RTSP 视频流的完整地址就是“rtsp://:8554/ds-test”,到此就完成将推理计算的结果透过 RTSP 服务向外推送的工作。

最后关于 osd_sink_pad_buffer_probe 的部分,与 deepstream_test_1.py 的内容完全一样,就不重复说明,至于代码最后面有个“def parse_args():”的部分,只是为了解析程式读入的指令参数,很容易就能看懂,这里也不浪费篇幅去讲解。

现在是否可以准备执行这个应用呢?当然是可以的,只不过好像还没有准备好“接收视频”的环境!这个其实也很简单,请找到与本台边缘设备(Jetson Nano 2GB)在相同网段的另一台电脑,可以是 Windows、MacOS、Ubuntu 操作系统,只要能安装 VLC 这个播放软件就可以。

假设是使用 USB 线连接 Jetson Nano 2GB 与 PC 的状态,这时在 PC 上可以透过“192.168.55.1”这个 IP 访问到 Jetson Nano 2GB。现在可以先打开 VLC,选择“打开网路串流”后,输入“rtsp://192.168.55.1:8554/ds-test”(如下图)

 

然后在Jetson Nano 2GB上执行一下指令:

# 在DeepStream设备(如Jetson Nano 2GB)cd根目录>/sources/deepstream_python_apps/appscd deepstream-test1-rtsp-outln -s ../../../../samples/streams/sample_720p.h264 sample_720.h264python3 deepstream_test_1_usb.py -i sample_720.h264

执行前:下图左是用 Nomachine 连接到 Jetson Nano 2GB 的显示,下图右是在 PC 上打开 VLC 之后的画面。

执行后:下图左可以看到 Jetson Nano 2GB 正在执行推理计算,并且将视频流送出,下图右是在 PC 的 VLC 按下“播放”键之后的画面。

这样就完成这个 deepstream-test1-rtsp-out 的范例,建议大家能多花时间将代码修改的部分好好再咀嚼一番。

相关新闻