codes在最下面的

重要的几个命令和网址
https://blog.csdn.net/weixin_42030297/article/details/119676409

最开始的网址是:
https://stackoverflow.com/questions/47396372/write-opencv-frames-into-gstreamer-rtsp-server-pipeline/60580247#60580247%3E

https://forums.developer.nvidia.com/t/jetson-nano-faq/82953

gstreamer命令,就是管道的,从左到右依次按照命令处理,一个命令处理完了,下一条命令继续处理的,还可以做配置

gstreamer和ffmpeg类似,都是多媒体的处理库,不过ffmpeg更加常用的

命令之间的分隔符就是!,和Linux的管道类似,Linux的管道连接符是 |

gstreamer里面也有信号和槽的概念,下面的C++和PYthon codes就是用了信号和槽,绑定起来的,这个和QT类似的

将图片推流到rtsp服务器,需要准备好rtsp服务器,rtsp服务器网上有很多,像是:

推流的工具很多,像:FFmpegGStreamer
OBS StudioOpenCV浏览器

https://github.com/EasyDarwin/EasyDarwinhttps://github.com/bluenviron/mediamtx
https://github.com/ZLMediaKit/ZLMediaKit

流媒体服务器也很多,像:mediamtxEasyDarwinnginx-rtmp-modulesrs
流媒体服务器强烈推荐这个:mediamtx

收流客户端:vue3-video-playerFFmpegGStreamerVLC浏览器

重要vue3 + obs + nginx-rtmp-module + hls.js 推流开启个人直播

RTSP server

https://forums.developer.nvidia.com/t/jetson-nano-faq/82953

Q: Is there any example of running RTSP streaming?
There is an ease-to-use gstreamer sample to run RTSP server. The steps:

Download test-launch.c
gst-rtsp-server/examples/test-launch.c at 1.14.5 · GStreamer/gst-rtsp-server · GitHub

Build the sample

sudo apt-get install libgstrtspserver-1.0 libgstreamer1.0-dev
gcc test-launch.c -o test-launch $(pkg-config --cflags --libs gstreamer-1.0 gstreamer-rtsp-server-1.0)
Launch the server
$ ./test-launch "videotestsrc is-live=1 ! nvvidconv ! nvv4l2h264enc ! h264parse ! rtph264pay name=pay0 pt=96"
At client side, if the device is a PC with Windows OS, you can open network stream rtsp://<SERVER_IP_ADDRESS>:8554/test via VLC. If it is a Jetson device, you can run the command:

$ gst-launch-1.0 uridecodebin uri=rtsp://<SERVER_IP_ADDRESS>:8554/test ! nvoverlaysink

https://forums.developer.nvidia.com/t/rtsp-streaming-out-from-jetson-xavier/252262

https://forums.developer.nvidia.com/t/jetson-nano-faq/82953

https://github.com/GStreamer/gst-rtsp-server/blob/1.14.5/examples/test-launch.c

 * g++ rtspserver.cpp -o test-launch $(pkg-config --cflags --libs gstreamer-1.0 gstreamer-rtsp-server-1.0)
 * 
 * ./test-launch "videotestsrc is-live=1 ! nvvidconv ! nvv4l2h264enc ! h264parse ! rtph264pay name=pay0 pt=96"
 * ./test-launch "filesrc location=/home/jiahan/Desktop/SceneVideo/people.mp4 ! qtdemux ! h264parse ! rtph264pay name=pay0 pt=96"
 * 
 * https://forums.developer.nvidia.com/t/test-launch-rtsp-issue/211375
 * ./test-launch 'multifilesrc location="%07d_0.png" caps="image/png,framerate=13/1" ! pngdec ! videoconvert ! x264enc ! rtph264pay name=pay0 pt=96'
 * ./test-launch 'multifilesrc location="%07d_0.png" caps="image/png,framerate=13/1" ! pngdec ! nvvidconv ! nvv4l2h264enc ! h264parse ! rtph264pay name=pay0 pt=96'

 rtspsrc location=rtsp://192.168.1.34:8554/test    https://forums.developer.nvidia.com/t/live-streaming-on-the-nano-via-rtsp-test-launch-server/83505/3
ffmpeg -re -i rtsp://admin:ty135246@192.168.1.60/h264/ch1/main/av_stream -rtsp_transport tcp -vcodec h264 -f rtsp rtsp://192.168.1.3:6001/test
ffmpeg -re -i /home/jiahan/Desktop/SceneVideo/people.mp4 -rtsp_transport tcp -vcodec h264 -f rtsp rtsp://192.168.1.3:9000/test
ffmpeg -i /home/jiahan/Desktop/SceneVideo/people.mp4 -vcodec libx264 -acodec copy -preset:v ultrafast -tune:v zerolatency -vf scale=iw/2:-1 -rtsp_transport tcp -f rtsp rtsp://192.168.1.3:6001/test
ffmpeg -re -i “/dev/video0” -c:v libx264 -preset fast -c:a libfdk_aac -ab 128k -ar 44100 -f rtsp rtsp://localhost:80/live/STREAMNAME

./test-launch "shmsrc socket-path=/tmp/my_h264_sock ! video/x-h264, stream-format=byte-stream, width=640, height=480, framerate=30/1 ! h264parse ! video/x-h264, stream-format=byte-stream ! rtph264pay pt=96 name=pay0 "

cap = cv2.VideoCapture("rtspsrc location=rtsp://wowzaec2demo.streamlock.net/vod/mp4:BigBuckBunny_115k.mov ! rtph264depay ! h264parse ! nvv4l2decoder ! nvvidconv ! video/x-raw, format=(string)BGRx ! videoconvert ! video/x-raw,format=BGR ! appsink ")

    videowriter = cv2.VideoWriter("appsrc ! videoconvert ! video/x-raw,format=BGRx ! identity drop-allocation=true ! v4l2sink device=/dev/video1", 0, fps, sizes)
    # ./test-launch "v4l2src device=/dev/video1 ! nvvidconv ! nvv4l2h265enc ! h265parse ! rtph265pay name=pay0 pt=96 config-interval=1 "
    https://forums.developer.nvidia.com/t/rtsp-streaming-with-cv-videowriter/111686/2

    https://forums.developer.nvidia.com/t/emulate-a-usb-camera-from-computer-vision-output-both-internally-v4l2loopback-and-externally-as-usb-slave-device/165286/20

    https://forums.developer.nvidia.com/t/jetson-tx2-rtsp-streaming-ffmpeg-or-gstreamer/153907/4

https://github.com/EasyDarwin/EasyDarwin

https://stackoverflow.com/questions/69379674/how-to-stream-cv2-videowriter-frames-to-and-rtsp-server

def open_ffmpeg_stream_process(self):
    args = (
        "ffmpeg -re -stream_loop -1 -f rawvideo -pix_fmt "
        "rgb24 -s 1920x1080 -i pipe:0 -pix_fmt yuv420p "
        "-f rtsp rtsp://rtsp_server:8554/stream"
    ).split()
    return subprocess.Popen(args, stdin=subprocess.PIPE)


def capture_loop():
    ffmpeg_process = open_ffmpeg_stream_process()
    capture = cv2.VideoCapture(<video/stream>)    
    while True:
        grabbed, frame = capture.read()
        if not grabbed:
            break
        ffmpeg_process.stdin.write(frame.astype(np.uint8).tobytes())
    capture.release()
    ffmpeg_process.stdin.close()
    ffmpeg_process.wait()

RTSP服务器的调查

system throttled due to over-current
https://github.com/NVIDIA-ISAAC-ROS/isaac_ros_object_detection/issues/34
https://forums.developer.nvidia.com/t/system-throttled-due-to-over-current-on-orin-nx/247300/6?u=aalmusalami
https://forums.developer.nvidia.com/t/about-system-throttled-due-to-over-current/292659/13

jetson orin nano rtsp stream-mediavideo-server apple m3u8

RTSP server media stream server
https://github.com/bluenviron/mediamtx?tab=readme-ov-file#opencv
https://github.com/ZLMediaKit/ZLMediaKit
https://github.com/ZLMediaKit/ZLMediaKit/issues/3680

https://rawgit.com/dusty-nv/jetson-inference/master/docs/html/group__network.html#gad453571ec9bbc7fc4e595298a9380e53
https://github.com/dusty-nv/jetson-inference/issues/1859
https://github.com/dusty-nv/jetson-utils/issues/214

https://forums.developer.nvidia.com/t/rtsp-simulator/278125
https://forum.opencv.org/t/how-to-deploy-rtsp-streaming-server-with-videowriter-and-gstreamer/17230
https://forum.opencv.org/t/is-it-possible-to-check-for-errors-warnings-when-writing-to-rtsp-server-using-videowriter/19062
https://forums.developer.nvidia.com/t/jetson-nano-faq/82953
https://forums.developer.nvidia.com/t/how-to-publish-images-to-an-rtsp-server/140058
https://forums.developer.nvidia.com/t/issues-with-rtsp-server-deepstream-pipeline/192091
https://forums.developer.nvidia.com/t/jetson-tx2-rtsp-streaming-ffmpeg-or-gstreamer/153907
https://forums.developer.nvidia.com/t/deepstream-sdk-faq/80236/34

https://forums.developer.nvidia.com/t/web-streaming-rtsp-and-convert-to-m3u8/299950
https://forums.developer.nvidia.com/search?q=jetson%20m3u8
https://forums.developer.nvidia.com/t/deepstream-6-2-rtsp-output-cannot-be-reformat-to-hls/261405
https://forums.developer.nvidia.com/search?q=output%20m3u8
https://github.com/NVIDIA-AI-IOT/deepstream_python_apps/blob/master/apps/deepstream-test1-rtsp-out/deepstream_test1_rtsp_out.py
https://github.com/GStreamer/gst-rtsp-server/tree/1.14.5

重要的codes

 * g++ rtspserver.cpp -o test-launch $(pkg-config --cflags --libs gstreamer-1.0 gstreamer-rtsp-server-1.0)
 * 
 * ./test-launch "videotestsrc is-live=1 ! nvvidconv ! nvv4l2h264enc ! h264parse ! rtph264pay name=pay0 pt=96"
 * ./test-launch "filesrc location=/home/jiahan/Desktop/SceneVideo/people.mp4 ! qtdemux ! h264parse ! rtph264pay name=pay0 pt=96"
 * 
 * https://forums.developer.nvidia.com/t/test-launch-rtsp-issue/211375
 * ./test-launch 'multifilesrc location="%07d_0.png" caps="image/png,framerate=13/1" ! pngdec ! videoconvert ! x264enc ! rtph264pay name=pay0 pt=96'
 * ../test-launch 'multifilesrc location="%07d_0.png" caps="image/png,framerate=13/1" ! pngdec ! nvvidconv ! nvv4l2h264enc ! h264parse ! rtph264pay name=pay0 pt=96'
 * ./test-launch 'multifilesrc location=/home/jiahan/Desktop/scripts/saveimg/%07d_0.jpg caps=image/jpg,framerate=13/1 ! jpgdec ! nvvidconv ! nvv4l2h264enc ! h264parse ! rtph264pay name=pay0 pt=96'
 * 
 * rtspsrc location=rtsp://192.168.1.34:8554/test   https://forums.developer.nvidia.com/t/live-streaming-on-the-nano-via-rtsp-test-launch-server/83505/3
 *
 *  
 *  # https://blog.csdn.net/weixin_42030297/article/details/119676409
 *  # https://stackoverflow.com/questions/47396372/write-opencv-frames-into-gstreamer-rtsp-server-pipeline/60580247#60580247%3E
'''
/*
 * g++ rtspserver.cpp -o test-launch $(pkg-config --cflags --libs gstreamer-1.0 gstreamer-rtsp-server-1.0)
 * 
 * ./test-launch "videotestsrc is-live=1 ! nvvidconv ! nvv4l2h264enc ! h264parse ! rtph264pay name=pay0 pt=96"
 * ./test-launch "filesrc location=/home/jiahan/Desktop/SceneVideo/people.mp4 ! qtdemux ! h264parse ! rtph264pay name=pay0 pt=96"
 * 
 * https://forums.developer.nvidia.com/t/test-launch-rtsp-issue/211375
 * ./test-launch 'multifilesrc location="%07d_0.png" caps="image/png,framerate=13/1" ! pngdec ! videoconvert ! x264enc ! rtph264pay name=pay0 pt=96'
 * ../test-launch 'multifilesrc location="%07d_0.png" caps="image/png,framerate=13/1" ! pngdec ! nvvidconv ! nvv4l2h264enc ! h264parse ! rtph264pay name=pay0 pt=96'
 * ./test-launch 'multifilesrc location=/home/jiahan/Desktop/scripts/saveimg/%07d_0.jpg caps=image/jpg,framerate=13/1 ! jpgdec ! nvvidconv ! nvv4l2h264enc ! h264parse ! rtph264pay name=pay0 pt=96'
 * 
 * rtspsrc location=rtsp://192.168.1.34:8554/test   https://forums.developer.nvidia.com/t/live-streaming-on-the-nano-via-rtsp-test-launch-server/83505/3
 * 
 */
 
'''

# https://blog.csdn.net/weixin_42030297/article/details/119676409
# https://stackoverflow.com/questions/47396372/write-opencv-frames-into-gstreamer-rtsp-server-pipeline/60580247#60580247%3E
import cv2
import gi
gi.require_version('Gst', '1.0')
gi.require_version('GstRtspServer', '1.0')
from gi.repository import Gst, GstRtspServer, GObject, GLib
 
 
class SensorFactory(GstRtspServer.RTSPMediaFactory):
    def __init__(self, **properties):
        super(SensorFactory, self).__init__(**properties)
        path = r'rtsp://admin:ty135246@192.168.1.60/h264/ch1/main/av_stream'
        self.cap = cv2.VideoCapture(path)
        # self.cap = cv2.VideoCapture(0)
        self.width = int(self.cap.get(cv2.CAP_PROP_FRAME_WIDTH))
        self.height = int(self.cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
        self.number_frames = 0
        self.fps = int(self.cap.get(cv2.CAP_PROP_FPS)) % 100
        self.duration = 1 / self.fps * Gst.SECOND  # duration of a frame in nanoseconds
 
        """
            appsrc:使应用程序能够提供缓冲区写入管道; 
            block: 每块推送buffer块的最大字节;
            is-live:当前推送的是否直播数据;
            caps:过滤器
            rtph264pay:把H264 视频数据编码进RTP包
        """
 
        self.launch_string = 'appsrc name=source is-live=true block=true format=GST_FORMAT_TIME ' \
                             'caps=video/x-raw,format=BGR,width={},height={},framerate={}/1 ' \
                             '! videoconvert ! video/x-raw,format=I420 ' \
                             '! x264enc speed-preset=fast tune=zerolatency threads=4 ' \
                             '! rtph264pay config-interval=1 name=pay0 pt=96'.format(self.width,
                                                                                     self.height,
                                                                                     self.fps)
 
 
    def on_need_data(self, src, lenght):
        if self.cap.isOpened():
            ret, frame = self.cap.read()
            if ret:
                #TODO 自己发挥,做一些图像识别,画框等任务,
                data = frame.tostring()
                buf = Gst.Buffer.new_allocate(None, len(data), None)
                buf.fill(0, data)
                buf.duration = self.duration
                timestamp = self.number_frames * self.duration
                buf.pts = buf.dts = int(timestamp)
                buf.offset = timestamp
                self.number_frames += 1
                retval = src.emit('push-buffer', buf)
                print('pushed buffer, frame {}, duration {} ns, durations {} s'.format(self.number_frames,
                                                                                       self.duration,
                                                                                       self.duration / Gst.SECOND))
                if retval != Gst.FlowReturn.OK:
                    print(retval)
 
    def do_create_element(self, url):
        return Gst.parse_launch(self.launch_string)
 
    def do_configure(self, rtsp_media):
        self.number_frames = 0
        appsrc = rtsp_media.get_element().get_child_by_name('source')
        appsrc.connect('need-data', self.on_need_data)
 
 
class GstServer(GstRtspServer.RTSPServer):
    def __init__(self, **properties):
        super(GstServer, self).__init__(**properties)
        self.set_service("8555")
        self.factory = SensorFactory()
        self.factory.set_shared(True)
        self.get_mount_points().add_factory("/test", self.factory)
        self.attach(None)
 
 
 
if __name__ == "__main__":
 
    GObject.threads_init()
    Gst.init(None)
    server = GstServer()
    loop = GObject.MainLoop()
    loop.run()
/* GStreamer
 * Copyright (C) 2008 Wim Taymans <wim.taymans at gmail.com>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public
 * License along with this library; if not, write to the
 * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
 * Boston, MA 02110-1301, USA.
 */


/*
 * g++ rtspserver.cpp -o test-launch $(pkg-config --cflags --libs gstreamer-1.0 gstreamer-rtsp-server-1.0)
 * 
 * ./test-launch "videotestsrc is-live=1 ! nvvidconv ! nvv4l2h264enc ! h264parse ! rtph264pay name=pay0 pt=96"
 * ./test-launch "filesrc location=/home/jiahan/Desktop/SceneVideo/people.mp4 ! qtdemux ! h264parse ! rtph264pay name=pay0 pt=96"
 * 
 * https://forums.developer.nvidia.com/t/test-launch-rtsp-issue/211375
 * ./test-launch 'multifilesrc location="%07d_0.png" caps="image/png,framerate=13/1" ! pngdec ! videoconvert ! x264enc ! rtph264pay name=pay0 pt=96'
 * ../test-launch 'multifilesrc location="%07d_0.png" caps="image/png,framerate=13/1" ! pngdec ! nvvidconv ! nvv4l2h264enc ! h264parse ! rtph264pay name=pay0 pt=96'
 * ./test-launch 'multifilesrc location=/home/jiahan/Desktop/scripts/saveimg/%07d_0.jpg caps=image/jpg,framerate=13/1 ! jpgdec ! nvvidconv ! nvv4l2h264enc ! h264parse ! rtph264pay name=pay0 pt=96'
 * 
 * rtspsrc location=rtsp://192.168.1.34:8554/test   https://forums.developer.nvidia.com/t/live-streaming-on-the-nano-via-rtsp-test-launch-server/83505/3
 *
 *  
 *  # https://blog.csdn.net/weixin_42030297/article/details/119676409
 *  # https://stackoverflow.com/questions/47396372/write-opencv-frames-into-gstreamer-rtsp-server-pipeline/60580247#60580247%3E
 * 
 */

 #include <gst/gst.h>

 #include <gst/rtsp-server/rtsp-server.h>
 
 typedef struct
 {
   gboolean white;
   GstClockTime timestamp;
 } MyContext;
 
 /* called when we need to give data to appsrc */
 static void
 need_data (GstElement * appsrc, guint unused, MyContext * ctx)
 {
   GstBuffer *buffer;
   guint size;
   GstFlowReturn ret;
 
   size = 385 * 288 * 2;
 
   buffer = gst_buffer_new_allocate (NULL, size, NULL);
 
   /* this makes the image black/white */
//    gst_buffer_memset (buffer, 0, ctx->white ? 0xff : 0x0, size);
   gst_buffer_memset (buffer, 0, 0xff, size);
 
   ctx->white = !ctx->white;
 
   /* increment the timestamp every 1/2 second */
   GST_BUFFER_PTS (buffer) = ctx->timestamp;
   GST_BUFFER_DURATION (buffer) = gst_util_uint64_scale_int (1, GST_SECOND, 2);
   ctx->timestamp += GST_BUFFER_DURATION (buffer);
 
   g_signal_emit_by_name (appsrc, "push-buffer", buffer, &ret);
 }
 
 /* called when a new media pipeline is constructed. We can query the
  * pipeline and configure our appsrc */
 static void
 media_configure (GstRTSPMediaFactory * factory, GstRTSPMedia * media,
     gpointer user_data)
 {
   GstElement *element, *appsrc;
   MyContext *ctx;
 
   /* get the element used for providing the streams of the media */
   element = gst_rtsp_media_get_element (media);
 
   /* get our appsrc, we named it 'mysrc' with the name property */
   appsrc = gst_bin_get_by_name_recurse_up (GST_BIN (element), "mysrc");
 
   /* this instructs appsrc that we will be dealing with timed buffer */
   gst_util_set_object_arg (G_OBJECT (appsrc), "format", "time");
   /* configure the caps of the video */
   g_object_set (G_OBJECT (appsrc), "caps",
       gst_caps_new_simple ("video/x-raw",
           "format", G_TYPE_STRING, "RGB16",
           "width", G_TYPE_INT, 384,
           "height", G_TYPE_INT, 288,
           "framerate", GST_TYPE_FRACTION, 0, 1, NULL), NULL);
 
   ctx = g_new0 (MyContext, 1);
   ctx->white = FALSE;
   ctx->timestamp = 0;
   /* make sure ther datais freed when the media is gone */
   g_object_set_data_full (G_OBJECT (media), "my-extra-data", ctx,
       (GDestroyNotify) g_free);
 
   /* install the callback that will be called when a buffer is needed */
   g_signal_connect (appsrc, "need-data", (GCallback) need_data, ctx);
   gst_object_unref (appsrc);
   gst_object_unref (element);
 }
 
 int
 main (int argc, char *argv[])
 {
   GMainLoop *loop;
   GstRTSPServer *server;
   GstRTSPMountPoints *mounts;
   GstRTSPMediaFactory *factory;
 
   gst_init (&argc, &argv);
 
   loop = g_main_loop_new (NULL, FALSE);
 
   /* create a server instance */
   server = gst_rtsp_server_new ();
 
   /* get the mount points for this server, every server has a default object
    * that be used to map uri mount points to media factories */
   mounts = gst_rtsp_server_get_mount_points (server);
 
   /* make a media factory for a test stream. The default media factory can use
    * gst-launch syntax to create pipelines.
    * any launch line works as long as it contains elements named pay%d. Each
    * element with pay%d names will be a stream */
   factory = gst_rtsp_media_factory_new ();
   // https://stackoverflow.com/questions/71387657/x264-error-baseline-profile-doesnt-support-422
   gst_rtsp_media_factory_set_launch (factory,
       "appsrc name=mysrc ! videoconvert ! video/x-raw,format=I420 ! x264enc ! rtph264pay name=pay0 pt=96");
    //    "( appsrc name=mysrc ! videoconvert ! x264enc ! rtph264pay name=pay0 pt=96 )");
//  'appsrc name=source is-live=true block=true format=GST_FORMAT_TIME ' \
//                              'caps=video/x-raw,format=BGR,width={},height={},framerate={}/1 ' \
//                              '! videoconvert ! video/x-raw,format=I420 ' \
//                              '! x264enc speed-preset=fast tune=zerolatency threads=4 ' \
//                              '! rtph264pay config-interval=1 name=pay0 pt=96'
   /* notify when our media is ready, This is called whenever someone asks for
    * the media and a new pipeline with our appsrc is created */
   g_signal_connect (factory, "media-configure", (GCallback) media_configure,
       NULL);
 
   /* attach the test factory to the /test url */
   gst_rtsp_mount_points_add_factory (mounts, "/test", factory);
 
   /* don't need the ref to the mounts anymore */
   g_object_unref (mounts);
 
   /* attach the server to the default maincontext */
   gst_rtsp_server_attach (server, NULL);
 
   /* start serving */
   g_print ("stream ready at rtsp://127.0.0.1:8554/test\n");
   g_main_loop_run (loop);
 
   return 0;
 }
Logo

中国智能体开发者社区,聚焦智能体与大模型开发,提供前沿资讯、实用工具链、开源项目及行业案例。通过技术沙龙、开发者大赛等活动,促进经验交流与协作,助力开发者快速构建创新智能应用。

更多推荐