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

本文以上一期Python版的deepstream-teat1为基础,分别在输入与输出添加功能的两个扩展应用:deepstream-teat1-usbcam与deepstream-teat1-rtsp-out,分别将输入源从视频文件变成USB摄像头,以及将输出从显示屏变成RTSP视频流。

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

  • 将输入源从视频文件修改成USB摄像头
  • 文件路径:<DeepStream>/sources/deepstream_python_apps/appsdeepstream-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")

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

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

接下去在设置caps_v4l2srccaps_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 <DeepStream根目录>/sources/deepstream_python_apps/apps

cd deepstream-test1-usbcam

python3 deepstream_test_1_usb.py

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

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

 

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

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

  • 将输出从显示屏转成RTSP视频流
  • 文件路径:<DeepStream>/sources/deepstream_python_apps/appsdeepstream-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 update

 sudo apt-get install libgstrtspserver-1.0-0 gstreamer1.0-rtsp

 sudo apt-get install libgirepository1.0-dev

 sudo apt-get install gobject-introspection gir1.2-gst-rtsp-server-1.0

这个项目的输入部分还是使用deepstream-test1H264视频文件,唯一改变的地方就是输出的方式,也就是在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"))

 

# 根据输入参数选择使用的编码器,预设为H264

if 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 = 5400

sink = 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 顺序,将元件依序进行连接。

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

# Start streaming

rtsp_port_num = 8554  # 设定端口值

   

server = GstRtspServer.RTSPServer.new()

server.props.service = "%d" % rtsp_port_num

server.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://<IP_OF_DEVICE>:8554/ds-test”,到此就完成将推理计算的结果透过RTSP服务向外推送的工作。

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

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

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

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

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

# DeepStream设备(如Jetson Nano 2GB

cd <DeepStream根目录>/sources/deepstream_python_apps/apps

cd deepstream-test1-rtsp-out

ln -s ../../../../samples/streams/sample_720p.h264 sample_720.h264

python3 deepstream_test_1_usb.py -i sample_720.h264

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

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

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

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

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

来源:业界供稿

0赞

好文章,需要你的鼓励

2021

11/02

11:36

分享

点赞

邮件订阅
白皮书