rtsp

 

import sys
import cv2
import numpy as np
from PyQt5.QtCore import QThread, pyqtSignal, Qt
from PyQt5.QtGui import QImage, QPixmap
from PyQt5.QtWidgets import (QApplication, QMainWindow,
                           QLabel, QVBoxLayout,
                           QWidget, QPushButton,
                           QStatusBar, QSpinBox)
import socket
import threading

class RTSPServer:
    def __init__(self, port=8554):
        self.port = port
        self.running = False
        self.frame = None
        self.lock = threading.Lock()
        
    def start(self):
        self.running = True
        threading.Thread(target=self._run_server, daemon=True).start()
        
    def _run_server(self):
        with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
            s.bind(('0.0.0.0', self.port))
            s.listen(1)
            while self.running:
                conn, addr = s.accept()
                threading.Thread(target=self._handle_client, args=(conn,)).start()
                
    def _handle_client(self, conn):
        try:
            conn.send(b'RTSP/1.0 200 OK\r\n')
            while self.running:
                with self.lock:
                    if self.frame is not None:
                        _, jpeg = cv2.imencode('.jpg', self.frame)
                        data = jpeg.tobytes()
                        header = f"Content-Length: {len(data)}\r\n\r\n".encode()
                        conn.send(header + data)
        except Exception as e:
            print(f"Client error: {e}")
        finally:
            conn.close()
            
    def update_frame(self, frame):
        with self.lock:
            self.frame = frame
            
    def stop(self):
        self.running = False

class CameraThread(QThread):
    frame_ready = pyqtSignal(np.ndarray)
    
    def __init__(self, src=0):
        super().__init__()
        self.cap = cv2.VideoCapture(src)
        self.running = False
        self.set_resolution(1280, 720)
        
    def set_resolution(self, width, height):
        self.cap.set(cv2.CAP_PROP_FRAME_WIDTH, width)
        self.cap.set(cv2.CAP_PROP_FRAME_HEIGHT, height)
        self.cap.set(cv2.CAP_PROP_FPS, 30)
        
    def run(self):
        self.running = True
        while self.running:
            ret, frame = self.cap.read()
            if ret:
                self.frame_ready.emit(frame)
                
    def stop(self):
        self.running = False
        self.wait()
        self.cap.release()

class MainWindow(QMainWindow):
    def __init__(self):
        super().__init__()
        self.init_ui()
        self.init_camera()
        self.init_rtsp()
        
    def init_ui(self):
        self.setWindowTitle('USB摄像头RTSP服务')
        self.setGeometry(100, 100, 800, 600)
        
        central_widget = QWidget()
        self.setCentralWidget(central_widget)
        
        self.video_label = QLabel()
        self.video_label.setAlignment(Qt.AlignCenter)
        
        self.btn_start = QPushButton('启动服务')
        self.btn_stop = QPushButton('停止服务')
        
        self.port_spin = QSpinBox()
        self.port_spin.setRange(1024, 65535)
        self.port_spin.setValue(8554)
        
        layout = QVBoxLayout()
        layout.addWidget(self.video_label)
        layout.addWidget(QLabel("RTSP端口:"))
        layout.addWidget(self.port_spin)
        layout.addWidget(self.btn_start)
        layout.addWidget(self.btn_stop)
        central_widget.setLayout(layout)
        
        self.status_bar = QStatusBar()
        self.setStatusBar(self.status_bar)
        
        self.btn_start.clicked.connect(self.start_service)
        self.btn_stop.clicked.connect(self.stop_service)
        
    def init_camera(self):
        self.camera_thread = CameraThread(0)
        self.camera_thread.frame_ready.connect(self.process_frame)
        
    def init_rtsp(self):
        self.rtsp_server = RTSPServer()
        
    def process_frame(self, frame):
        rgb_frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
        h, w, ch = rgb_frame.shape
        q_img = QImage(rgb_frame.data, w, h, 
                      ch * w, QImage.Format_RGB888)
        self.video_label.setPixmap(
            QPixmap.fromImage(q_img).scaled(
                self.video_label.width(),
                self.video_label.height(),
                Qt.KeepAspectRatio
            ))
        
        if hasattr(self, 'streaming') and self.streaming:
            self.rtsp_server.update_frame(frame)
        
    def start_service(self):
        self.rtsp_server.port = self.port_spin.value()
        self.rtsp_server.start()
        self.camera_thread.start()
        self.streaming = True
        self.status_bar.showMessage(
            f"RTSP服务已启动: rtsp://{socket.gethostbyname(socket.gethostname())}:{self.rtsp_server.port}"
        )
        
    def stop_service(self):
        self.streaming = False
        self.rtsp_server.stop()
        self.camera_thread.stop()
        self.status_bar.showMessage("服务已停止")
        
    def closeEvent(self, event):
        self.stop_service()
        event.accept()

if __name__ == '__main__':
    app = QApplication(sys.argv)
    window = MainWindow()
    window.show()
    sys.exit(app.exec_())

 

 

 

###############

posted @ 2025-06-12 22:46  西北逍遥  阅读(13)  评论(0)    收藏  举报