|
@ -1,8 +1,8 @@ |
|
|
import cv2 |
|
|
|
|
|
import gi |
|
|
import gi |
|
|
import threading |
|
|
import threading |
|
|
import numpy as np |
|
|
import numpy as np |
|
|
import socket |
|
|
import socket |
|
|
|
|
|
import cv2 |
|
|
|
|
|
|
|
|
gi.require_version('Gst', '1.0') |
|
|
gi.require_version('Gst', '1.0') |
|
|
gi.require_version('GstRtspServer', '1.0') |
|
|
gi.require_version('GstRtspServer', '1.0') |
|
@ -51,7 +51,7 @@ class VideoStream(GstRtspServer.RTSPMediaFactory): |
|
|
"appsrc name=source is-live=true format=GST_FORMAT_TIME " |
|
|
"appsrc name=source is-live=true format=GST_FORMAT_TIME " |
|
|
"caps=video/x-raw,format=RGB,width={},height={},framerate={}/1 " |
|
|
"caps=video/x-raw,format=RGB,width={},height={},framerate={}/1 " |
|
|
"! videoconvert ! video/x-raw,format=I420 " |
|
|
"! videoconvert ! video/x-raw,format=I420 " |
|
|
"! nvh264enc preset=low-latency rc-mode=cbr bitrate=2500 gop-size=7 zerolatency=true " |
|
|
|
|
|
|
|
|
"! x264enc tune=zerolatency bitrate=500 speed-preset=ultrafast " |
|
|
"! h264parse ! rtph264pay config-interval=1 name=pay0 pt=96" |
|
|
"! h264parse ! rtph264pay config-interval=1 name=pay0 pt=96" |
|
|
).format(self.width, self.height, self.fps) |
|
|
).format(self.width, self.height, self.fps) |
|
|
|
|
|
|
|
@ -69,14 +69,15 @@ class RTSPServer: |
|
|
self.mount_point = mount_point |
|
|
self.mount_point = mount_point |
|
|
|
|
|
|
|
|
self.video_stream = None |
|
|
self.video_stream = None |
|
|
self.server.attach(None) |
|
|
|
|
|
self.current_fps = None |
|
|
self.current_fps = None |
|
|
self.current_width = None |
|
|
self.current_width = None |
|
|
self.current_height = None |
|
|
self.current_height = None |
|
|
self.lock = threading.Lock() |
|
|
self.lock = threading.Lock() |
|
|
|
|
|
|
|
|
|
|
|
self.server.attach(None) |
|
|
|
|
|
|
|
|
def create_stream(self, fps, width, height): |
|
|
def create_stream(self, fps, width, height): |
|
|
"""Create a new streaming channel with the given size & FPS.""" |
|
|
|
|
|
|
|
|
"""Create a new RTSP stream with the given resolution and FPS.""" |
|
|
with self.lock: |
|
|
with self.lock: |
|
|
# Check if we need to recreate the stream |
|
|
# Check if we need to recreate the stream |
|
|
if (self.video_stream and |
|
|
if (self.video_stream and |
|
@ -106,7 +107,7 @@ class RTSPServer: |
|
|
return |
|
|
return |
|
|
|
|
|
|
|
|
height, width, _ = frame.shape |
|
|
height, width, _ = frame.shape |
|
|
fps = 30 # Default FPS, can be adjusted dynamically if needed |
|
|
|
|
|
|
|
|
fps = 30 # Default FPS |
|
|
|
|
|
|
|
|
# Ensure we have a valid stream for the given resolution |
|
|
# Ensure we have a valid stream for the given resolution |
|
|
self.create_stream(fps, width, height) |
|
|
self.create_stream(fps, width, height) |
|
@ -116,11 +117,11 @@ class RTSPServer: |
|
|
self.video_stream.update_frame(frame) |
|
|
self.video_stream.update_frame(frame) |
|
|
|
|
|
|
|
|
# Global RTSP server instance |
|
|
# Global RTSP server instance |
|
|
rtsp_server = RTSPServer(get_local_ip(), 41231) |
|
|
|
|
|
|
|
|
# rtsp_server = RTSPServer(get_local_ip(), 41231) |
|
|
|
|
|
|
|
|
def run_server(): |
|
|
|
|
|
|
|
|
def run_server(server): |
|
|
"""Start the RTSP server loop.""" |
|
|
"""Start the RTSP server loop.""" |
|
|
print(f"RTSP Server running at rtsp://{rtsp_server.server.get_address()}:{rtsp_server.server.get_service()}/stream") |
|
|
|
|
|
|
|
|
print(f"RTSP Server running at rtsp://{server.server.get_address()}:{server.server.get_service()}/stream") |
|
|
loop = GLib.MainLoop() |
|
|
loop = GLib.MainLoop() |
|
|
loop.run() |
|
|
loop.run() |
|
|
|
|
|
|
|
|