gstreamer调查rtsp将处理以后的图片推流到rtsp的server
codes在最下面的
重要的几个命令和网址
https://blog.csdn.net/weixin_42030297/article/details/119676409
https://forums.developer.nvidia.com/t/jetson-nano-faq/82953
gstreamer命令,就是管道的,从左到右依次按照命令处理,一个命令处理完了,下一条命令继续处理的,还可以做配置
gstreamer和ffmpeg类似,都是多媒体的处理库,不过ffmpeg更加常用的
命令之间的分隔符就是!,和Linux的管道类似,Linux的管道连接符是 |
gstreamer里面也有信号和槽的概念,下面的C++和PYthon codes就是用了信号和槽,绑定起来的,这个和QT类似的
将图片推流到rtsp服务器,需要准备好rtsp服务器,rtsp服务器网上有很多,像是:
推流的工具很多,像:FFmpeg、GStreamer、
OBS Studio、OpenCV、浏览器
https://github.com/EasyDarwin/EasyDarwin,https://github.com/bluenviron/mediamtx
,https://github.com/ZLMediaKit/ZLMediaKit
流媒体服务器也很多,像:mediamtx、EasyDarwin、nginx-rtmp-module、srs
流媒体服务器强烈推荐这个:mediamtx
收流客户端:vue3-video-player、FFmpeg、GStreamer、VLC、浏览器
重要: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;
}
更多推荐
所有评论(0)