提高Jetson AGX中webrtc的Gstreamer管道的性能



我在c++中有一个应用程序,可以使用gstreamer从相机中获取视频,然后通过UDP将视频发送到c++中的另一个应用软件,该应用软件可以获取视频并使用webrct进行重流。一切都在喷气式AGX下。

如果我在H264中从相机获取数据并直接发送,视频在4k:中完美工作

第一个获得视频的管道

pipe_source = "rtspsrc location=rtsp://192.168.1.162/z3-1.mp4 ! application/x-rtp,encoding-name=H264,profile=baseline ! ";
pipe_sink = "udpsink host=224.1.1.1 port=5000 sync=false auto-multicast=true";
launch_pipeline = pipe_source + pipe_sink;

获取视频并通过webrtc 发送的第二个管道

pipeline = "udpsrc multicast-group=224.1.1.1 auto-multicast=true port=5000 ! application/x-rtp,encoding-name=H264,profile=baseline,media=video,clock-rate=90000,payload=96 ! webrtcbin async-handling=true name=sendrecv";

然而,如果我想在输入视频中进行一些进动,我不能在4K中做到这一点,因为我需要在通过udp 发送视频之前解码(然后编码(帧

pipe_source = "rtspsrc location=rtsp://192.168.1.162/z3-1.mp4 ! application/x-rtp,encoding-name=H265 !";
pipe_decode = "rtph265depay ! video/x-h265 ! nvv4l2decoder enable-max-performance=true ! ";
pipe_process = "nvvidconv output-buffers=5 name=myconv ! video/x-raw(memory:NVMM), format=RGBA ! nvvidconv output-buffers=5 ! video/x-raw(memory:NVMM), format=NV12 ! queue max-size-bytes=0 max-size-time=500 !";
pipe_encode ="nvv4l2vp9enc maxperf-enable=true ! video/x-vp9 ! rtpvp9pay !";
pipe_sink = "udpsink host=224.1.1.1 port=5000 sync=false auto-multicast=true";
launch_pipeline = pipe_source + pipe_decode + pipe_process + pipe_encode + pipe_sink;

在这个源代码的管道中,我尝试了h264/h265。此外,对于编码,我尝试使用h264而不是VP9,但看起来h264要慢得多。这就是为什么我在编码部分使用了VP9。

在这种情况下,第二条管道是:

pipeline = "udpsrc multicast-group=224.1.1.1 auto-multicast=true port=5000 ! application/x-rtp,media=video,clock-rate=90000,encoding-name=VP9,payload=96, framerate=25/1 ! queue max-size-bytes=0 max-size-time=0 ! webrtcbin async-handling=true name=sendrecv";

我的问题是,使用这种配置,我无法在4k中获得高质量的视频。我得到了视频,但质量很差,我认为VP9正在改变比特率,以获得连续的视频而不丢失帧。我试过在编码部分给出比特率,这提高了图像的质量,但我丢失了一些帧。

如果我使用1080,那么我得到的视频质量很好,因此我觉得这是硬件(我使用的是jetson AGX(在解码/编码方面的处理能力问题。

有人知道提高管道性能的方法吗?我不确定我是否在做什么";无用的";这使得4k视频的整个过程变得缓慢。

我不确定您的真实用例是什么,但以下内容可能有助于您进一步研究。

我没有4K IP摄像头,所以在这里我将使用CSI摄像头进行模拟1080p@30fps,并升级到3840x2160,流式传输为H265编码,RTSP服务器测试启动:

./test-launch "nvarguscamerasrc ! video/x-raw(memory:NVMM), width=1920, height=1080, framerate=30/1, format=NV12 ! nvvidconv ! video/x-raw(memory:NVMM), width=3840, height=2160, pixel-aspect-ratio=1/1 ! nvv4l2h265enc insert-vui=true insert-sps-pps=1 insert-aud=1 maxperf-enable=1 bitrate=30000000 ! h265parse ! video/x-h265, stream-format=byte-stream ! rtph265pay name=pay0 pt=96 "

请注意,这将以30Mb/s的比特率编码为H265格式。您可以首先检查是否可以从源中获得高质量的图像,并将源比特率调整为最佳。假设您的显示器支持1080p@30:

gst-launch-1.0 rtspsrc location=rtsp://127.0.0.1:8554/test latency=500 ! application/x-rtp,encoding-name=H265 ! rtph265depay ! h265parse ! nvv4l2decoder ! nvvidconv ! video/x-raw,width=1920,height=1080 ! xvimagesink

好的时候,让我们走得更远。

此处解码RTSP H265源并重新编码为VP9/RTP/UDP/

gst-launch-1.0 rtspsrc location=rtsp://127.0.0.1:8554/test latency=500 ! application/x-rtp,encoding-name=H265 ! rtph265depay ! h265parse ! nvv4l2decoder enable-max-performance=1 ! queue ! nvv4l2vp9enc maxperf-enable=true bitrate=30000000 ! video/x-vp9 ! rtpvp9pay ! udpsink host=224.1.1.1 port=5000 auto-multicast=true buffer-size=32000000

注意VP9 30 Mb/s的比特率。你可能也需要调整。

为了进行检查,您可以显示(假设X正在运行(:

gst-launch-1.0 udpsrc multicast-group=224.1.1.1 auto-multicast=true port=5000 buffer-size=32000000 ! application/x-rtp,encoding-name=VP9 ! rtpjitterbuffer latency=500 ! rtpvp9depay ! video/x-vp9 ! nvv4l2decoder ! nvvidconv ! video/x-raw,width=1920,height=1080 ! xvimagesink

2022年1月29日编辑:

您可以进一步尝试以下操作,我的AGX Xavier运行L4T R32.6.1:似乎运行良好

  1. 使用H265视频读取RTSP流、解码、编码到VP9并使用RTP/UDP流式传输到localhost的应用程序:
#include <gst/gst.h>
int main (gint argc, gchar * argv[])
{  
gst_init (&argc, &argv);
GMainLoop *loop = g_main_loop_new (NULL, FALSE);
/* Create the pipeline...this will negociate unspecified caps between plugins */
const gchar *pipeline1 = "rtspsrc location=rtsp://127.0.0.1:8554/test latency=500 ! application/x-rtp,encoding-name=H265 ! rtph265depay ! h265parse ! nvv4l2decoder enable-max-performance=1 ! queue ! nvv4l2vp9enc maxperf-enable=true bitrate=30000000 ! video/x-vp9 ! rtpvp9pay ! udpsink host=127.0.0.1 port=5000 auto-multicast=0 buffer-size=32000000 ";
GstElement *pipeline = gst_parse_launch (pipeline1, NULL);
if (!pipeline) {
g_error ("Failed to create pipelinen");
exit(-1);
}
/* Ok, successfully created the pipeline, now start it */
gst_element_set_state (pipeline, GST_STATE_READY);
gst_element_set_state (pipeline, GST_STATE_PLAYING);
/* wait until it's up and running or failed */
if (gst_element_get_state (pipeline, NULL, NULL, -1) == GST_STATE_CHANGE_FAILURE) {
g_error ("Failed to go into PLAYING state");
exit(-2);
}
g_print ("Running ...n");
g_main_loop_run (loop);
return 0;
}

使用:gcc -Wall -o gst_testlaunch1 -I/usr/include/gstreamer-1.0 -I/usr/include/glib-2.0 -I/usr/lib/aarch64-linux-gnu/glib-2.0/include gst_testlaunch1.cpp -lgstreamer-1.0 -lgobject-2.0 -lglib-2.0构建

  1. 从本地主机上的RTP/UDP读取VP9编码视频的应用程序,解码并重新缩放为1080p nvvidconv,然后在测量fps时以X显示:
#include <gst/gst.h>
int main (gint argc, gchar * argv[])
{  
gst_init (&argc, &argv);
GMainLoop *loop = g_main_loop_new (NULL, FALSE);
/* Create the pipeline...this will negociate unspecified caps between plugins */
const gchar *pipeline2 = "udpsrc auto-multicast=0 port=5000 buffer-size=32000000 ! application/x-rtp,encoding-name=VP9 ! rtpjitterbuffer latency=500 ! rtpvp9depay ! video/x-vp9 ! nvv4l2decoder ! nvvidconv ! video/x-raw,width=1920,height=1080 ! fpsdisplaysink video-sink=xvimagesink text-overlay=0 ";
GstElement *pipeline = gst_parse_launch (pipeline2, NULL);
if (!pipeline) {
g_error ("Failed to create pipelinen");
exit(-1);
}
// This will output changes and is required to display fps in terminal, you may remove it later to make it quiet.
g_signal_connect(pipeline, "deep-notify", G_CALLBACK(gst_object_default_deep_notify), NULL);
/* Ok, successfully created the pipeline, now start it */
gst_element_set_state (pipeline, GST_STATE_READY);
gst_element_set_state (pipeline, GST_STATE_PLAYING);
/* wait until it's up and running or failed */
if (gst_element_get_state (pipeline, NULL, NULL, -1) == GST_STATE_CHANGE_FAILURE) {
g_error ("Failed to go into PLAYING state");
exit(-2);
}
g_print ("Running ...n");
g_main_loop_run (loop);
return 0;
}

使用:gcc -Wall -o gst_testlaunch2 -I/usr/include/gstreamer-1.0 -I/usr/include/glib-2.0 -I/usr/lib/aarch64-linux-gnu/glib-2.0/include gst_testlaunch2.cpp -lgstreamer-1.0 -lgobject-2.0 -lglib-2.0构建

在4K-H265 RTSP源可用的情况下,在终端中首先运行gst_testlaunch1,然后在第二个终端中运行gst_testlaunch2,可以显示具有正确质量的图像,并且保持30fps。

最新更新