2 changed files with 101 additions and 3 deletions
			
			
		| @ -0,0 +1,91 @@ | |||||
|  | import cv2 | ||||
|  | import gi | ||||
|  | import threading | ||||
|  | import numpy as np | ||||
|  | 
 | ||||
|  | gi.require_version('Gst', '1.0') | ||||
|  | gi.require_version('GstRtspServer', '1.0') | ||||
|  | from gi.repository import Gst, GstRtspServer, GLib | ||||
|  | 
 | ||||
|  | 
 | ||||
|  | class VideoStream(GstRtspServer.RTSPMediaFactory): | ||||
|  |     def __init__(self, fps=30, width=640, height=480): | ||||
|  |         super(VideoStream, self).__init__() | ||||
|  |         self.fps = fps | ||||
|  |         self.width = width | ||||
|  |         self.height = height | ||||
|  |         self.frame = np.zeros((height, width, 3), dtype=np.uint8)  # Black frame initially | ||||
|  |         self.lock = threading.Lock() | ||||
|  | 
 | ||||
|  |     def update_frame(self, frame): | ||||
|  |         """Externally updates the current frame.""" | ||||
|  |         with self.lock: | ||||
|  |             self.frame = cv2.resize(frame, (self.width, self.height))  # Resize if necessary | ||||
|  | 
 | ||||
|  |     def on_need_data(self, src, length): | ||||
|  |         """Provides frames when the pipeline requests data.""" | ||||
|  |         with self.lock: | ||||
|  |             frame_rgb = cv2.cvtColor(self.frame, cv2.COLOR_BGR2RGB)  # Convert BGR to RGB | ||||
|  |             data = frame_rgb.tobytes()  # Convert to bytes | ||||
|  | 
 | ||||
|  |         buf = Gst.Buffer.new_allocate(None, len(data), None) | ||||
|  |         buf.fill(0, data) | ||||
|  |         buf.duration = Gst.SECOND // self.fps | ||||
|  |         buf.pts = buf.dts = Gst.CLOCK_TIME_NONE | ||||
|  |         src.emit("push-buffer", buf) | ||||
|  | 
 | ||||
|  |     def do_create_element(self, url): | ||||
|  |         """Creates the GStreamer pipeline for RTSP streaming.""" | ||||
|  |         pipeline_str = ( | ||||
|  |             "appsrc name=source is-live=true format=GST_FORMAT_TIME " | ||||
|  |             "caps=video/x-raw,format=RGB,width={},height={},framerate={}/1 " | ||||
|  |             "! videoconvert ! video/x-raw,format=I420 " | ||||
|  |             "! x264enc tune=zerolatency bitrate=500 speed-preset=ultrafast " | ||||
|  |             "! rtph264pay config-interval=1 name=pay0 pt=96" | ||||
|  |         ).format(self.width, self.height, self.fps) | ||||
|  | 
 | ||||
|  |         pipeline = Gst.parse_launch(pipeline_str) | ||||
|  |         src = pipeline.get_by_name("source") | ||||
|  |         src.connect("need-data", self.on_need_data) | ||||
|  |         return pipeline | ||||
|  | 
 | ||||
|  | 
 | ||||
|  | class RTSPServer: | ||||
|  |     def __init__(self, ip="0.0.0.0", port=8554, mount_point="/stream"): | ||||
|  |         Gst.init(None) | ||||
|  |         self.server = GstRtspServer.RTSPServer() | ||||
|  |         self.server.set_address(ip) | ||||
|  |         self.server.set_service(str(port)) | ||||
|  | 
 | ||||
|  |         self.video_stream = VideoStream() | ||||
|  |         self.server.get_mount_points().add_factory(mount_point, self.video_stream) | ||||
|  |         self.server.attach(None) | ||||
|  | 
 | ||||
|  |     def start(self): | ||||
|  |         print(f"RTSP Server running at rtsp://{self.server.get_address()}:{self.server.get_service()}/stream") | ||||
|  |         loop = GLib.MainLoop() | ||||
|  |         loop.run() | ||||
|  | 
 | ||||
|  |     def update_frame(self, frame): | ||||
|  |         """Externally updates the current frame for streaming.""" | ||||
|  |         self.video_stream.update_frame(frame) | ||||
|  | 
 | ||||
|  | # Global server instance | ||||
|  | rtsp_server = RTSPServer("192.168.0.196",41231) | ||||
|  | 
 | ||||
|  | def run_server(): | ||||
|  |     rtsp_server.start() | ||||
|  | 
 | ||||
|  | def stream_webcam(): | ||||
|  |     cap = cv2.VideoCapture("/home/mht/Downloads/bcd2890d71caaf0e095b95c9b525973f61186656-360p.mp4")  # Open webcam | ||||
|  |     while cap.isOpened(): | ||||
|  |         ret, frame = cap.read() | ||||
|  |         if ret: | ||||
|  |             rtsp_server.update_frame(frame)  # Send frame to RTSP server | ||||
|  | 
 | ||||
|  | if __name__ == "__main__": | ||||
|  |     # Start RTSP server in a separate thread | ||||
|  |     threading.Thread(target=run_server, daemon=True).start() | ||||
|  | 
 | ||||
|  |     # Stream webcam frames | ||||
|  |     stream_webcam() | ||||
						Write
						Preview
					
					
					Loading…
					
					Cancel
						Save
					
		Reference in new issue