首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Jetson中webrtc性能Gstreamer流水线的改进

Jetson中webrtc性能Gstreamer流水线的改进
EN

Stack Overflow用户
提问于 2022-01-18 14:32:19
回答 1查看 1.5K关注 0票数 0

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

如果我从H264中的相机中获取数据,并以肮脏的方式发送数据,那么这些视频在4k内就会运行得非常完美:

第一个获得视频的管道

代码语言:javascript
复制
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发送的第二个管道

代码语言:javascript
复制
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发送视频之前对帧进行解码(然后编码)。

代码语言:javascript
复制
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;

在这个管道的来源,我已经尝试了H 264/H 265。更重要的是,对于我尝试使用h264而不是VP9的编码,但是看起来H264要慢得多。这就是我在编码部分使用VP9的原因。

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

代码语言:javascript
复制
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 )进行解码/编码。

有人知道如何提高管道的性能吗?我不确定我是否在做一些“无用”的事情,这使得整个过程对于4k视频来说是缓慢的。

EN

回答 1

Stack Overflow用户

发布于 2022-01-23 21:27:24

我不确定您真正的用例是什么,但下面的内容可能会帮助您进一步研究。

我没有4K的IP摄像头,所以这里我将模拟使用1080 p@30 fps中的CSI凸轮捕获,并将其升级到3840x2160,并通过RTSP服务器测试启动( H265 )进行流编码:

代码语言:javascript
复制
./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 "

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

代码语言:javascript
复制
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:

代码语言:javascript
复制
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正在运行)显示:

代码语言:javascript
复制
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日:

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

  1. 应用于H265视频读取RTSP流、解码、编码成VP9和使用RTP/UDP:

流到本地主机

代码语言:javascript
复制
#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 pipeline\n");
        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编码视频的应用,解码和重标度到1080 p nvvidconv,然后在X中显示,同时测量fps:

代码语言:javascript
复制
#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 pipeline\n");
        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-H265RTSP源,首先在终端上运行gst_testlaunch1,然后在第二个终端中运行gst_testlaunch2,以正确的质量显示图像,并保持30 fps。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/70757292

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档