Initial commit
This commit is contained in:
134
orin/scripts/rtsp_server.py
Normal file
134
orin/scripts/rtsp_server.py
Normal file
@@ -0,0 +1,134 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
RTSP Server для стриминга с CSI камеры на Jetson Orin.
|
||||
Использует GStreamer RTSP Server.
|
||||
"""
|
||||
|
||||
import os
|
||||
import gi
|
||||
gi.require_version('Gst', '1.0')
|
||||
gi.require_version('GstRtspServer', '1.0')
|
||||
from gi.repository import Gst, GstRtspServer, GLib
|
||||
|
||||
# Инициализация GStreamer
|
||||
Gst.init(None)
|
||||
|
||||
# Параметры из environment
|
||||
WIDTH = os.environ.get('CAMERA_WIDTH', '1920')
|
||||
HEIGHT = os.environ.get('CAMERA_HEIGHT', '1080')
|
||||
FPS = os.environ.get('CAMERA_FPS', '30')
|
||||
RTSP_PORT = os.environ.get('RTSP_PORT', '8554')
|
||||
|
||||
|
||||
def create_pipeline():
|
||||
"""
|
||||
Создаёт GStreamer pipeline для CSI камеры.
|
||||
Пробуем разные источники в порядке приоритета.
|
||||
"""
|
||||
|
||||
# Вариант 1: nvarguscamerasrc (CSI камера на Jetson) с NVIDIA hardware encoder
|
||||
# Используем nvv4l2h264enc для аппаратного кодирования без EGL
|
||||
csi_pipeline = (
|
||||
f'nvarguscamerasrc ! '
|
||||
f'video/x-raw(memory:NVMM),width={WIDTH},height={HEIGHT},framerate={FPS}/1,format=NV12 ! '
|
||||
f'nvv4l2h264enc bitrate=4000000 preset-level=1 insert-sps-pps=true ! '
|
||||
f'h264parse ! '
|
||||
f'rtph264pay name=pay0 pt=96'
|
||||
)
|
||||
|
||||
# Вариант 2: v4l2src (USB камера) с NVIDIA hardware encoder
|
||||
v4l2_pipeline = (
|
||||
f'v4l2src device=/dev/video0 ! '
|
||||
f'video/x-raw,width={WIDTH},height={HEIGHT},framerate={FPS}/1 ! '
|
||||
f'nvvidconv ! video/x-raw(memory:NVMM),format=NV12 ! '
|
||||
f'nvv4l2h264enc bitrate=4000000 preset-level=1 insert-sps-pps=true ! '
|
||||
f'h264parse ! '
|
||||
f'rtph264pay name=pay0 pt=96'
|
||||
)
|
||||
|
||||
# Вариант 3: тестовый источник с software encoder (fallback)
|
||||
test_pipeline = (
|
||||
f'videotestsrc is-live=true ! '
|
||||
f'video/x-raw,width={WIDTH},height={HEIGHT},framerate={FPS}/1 ! '
|
||||
f'videoconvert ! '
|
||||
f'x264enc tune=zerolatency bitrate=4000 speed-preset=ultrafast ! '
|
||||
f'rtph264pay name=pay0 pt=96'
|
||||
)
|
||||
|
||||
# Пробуем CSI камеру сначала
|
||||
try:
|
||||
test = Gst.parse_launch(csi_pipeline.replace('rtph264pay name=pay0 pt=96', 'fakesink'))
|
||||
test.set_state(Gst.State.PLAYING)
|
||||
# Даём время на инициализацию
|
||||
import time
|
||||
time.sleep(2)
|
||||
state = test.get_state(Gst.CLOCK_TIME_NONE)
|
||||
test.set_state(Gst.State.NULL)
|
||||
if state[1] == Gst.State.PLAYING:
|
||||
print("Using CSI camera (nvarguscamerasrc)")
|
||||
return csi_pipeline
|
||||
except Exception as e:
|
||||
print(f"CSI camera not available: {e}")
|
||||
|
||||
# Пробуем USB камеру
|
||||
if os.path.exists('/dev/video0'):
|
||||
print("Using USB camera (v4l2src)")
|
||||
return v4l2_pipeline
|
||||
|
||||
# Fallback на тестовый источник
|
||||
print("No camera found, using test source")
|
||||
return test_pipeline
|
||||
|
||||
|
||||
class RTSPServer:
|
||||
def __init__(self):
|
||||
self.server = GstRtspServer.RTSPServer()
|
||||
self.server.set_service(RTSP_PORT)
|
||||
|
||||
# Создаём factory для стрима
|
||||
factory = GstRtspServer.RTSPMediaFactory()
|
||||
pipeline = create_pipeline()
|
||||
print(f"Pipeline: {pipeline}")
|
||||
factory.set_launch(f'( {pipeline} )')
|
||||
factory.set_shared(True)
|
||||
|
||||
# Добавляем mount point
|
||||
mount_points = self.server.get_mount_points()
|
||||
mount_points.add_factory('/stream', factory)
|
||||
|
||||
# Запускаем сервер
|
||||
self.server.attach(None)
|
||||
|
||||
print(f"\n{'='*50}")
|
||||
print(f"RTSP Server started!")
|
||||
print(f"Stream URL: rtsp://<device-ip>:{RTSP_PORT}/stream")
|
||||
print(f"{'='*50}\n")
|
||||
|
||||
|
||||
def main():
|
||||
import signal
|
||||
import sys
|
||||
|
||||
server = RTSPServer()
|
||||
loop = GLib.MainLoop()
|
||||
|
||||
def signal_handler(sig, frame):
|
||||
print("Shutting down...")
|
||||
loop.quit()
|
||||
sys.exit(0)
|
||||
|
||||
signal.signal(signal.SIGINT, signal_handler)
|
||||
signal.signal(signal.SIGTERM, signal_handler)
|
||||
|
||||
print("RTSP server running. Waiting for connections...")
|
||||
sys.stdout.flush()
|
||||
|
||||
try:
|
||||
loop.run()
|
||||
except Exception as e:
|
||||
print(f"Error in main loop: {e}")
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
Reference in New Issue
Block a user