test sleep zamiast qtimer

This commit is contained in:
2026-05-11 14:39:53 +02:00
parent f317e71899
commit 6f784b4e40
3 changed files with 96 additions and 15 deletions

View File

@@ -12,11 +12,12 @@ class VideoStreamWorker(QObject):
Runs in a separate QThread.
"""
frame_ready = Signal(np.ndarray)
frame_time = Signal(float, float) # (start_time, end_time)
frame_time = Signal(float, float, int) # (start_time, end_time)
error_occurred = Signal(str)
started = Signal(float, tuple) # (fps, (width, height))
stopped = Signal()
source_changed = Signal(object) # Nowy sygnał dla zmiany źródła
_run = Signal() # Sygnał do uruchomienia pętli wątku
def __init__(self):
super().__init__()
@@ -26,6 +27,7 @@ class VideoStreamWorker(QObject):
self._timer = QTimer()
self._timer.timeout.connect(self._process_frame)
self.source_changed.connect(self._on_source_changed) # Łączymy sygnał ze slotem
self._run.connect(self.run) # Łączymy sygnał ze slotem
@Slot(object)
def set_source(self, source):
@@ -69,12 +71,13 @@ class VideoStreamWorker(QObject):
# Using a timer for consistent frame rate and to play nice with the event loop
# For files, we might want to calculate the interval from FPS.
fps = self._cap.get(cv2.CAP_PROP_FPS)
interval = int(1000 / fps) if fps > 0 else 30
interval = int(600 / fps) if fps > 0 else 20
video_res = (int(self._cap.get(cv2.CAP_PROP_FRAME_WIDTH)), int(self._cap.get(cv2.CAP_PROP_FRAME_HEIGHT)))
logger.debug(f"Video opened: {self._source} (fps: {fps}, width: {video_res[0]}, height: {video_res[1]})")
self._timer.start(interval)
# self._timer.start(interval)
self._run.emit() # Uruchamiamy pętlę wątku za pomocą sygnału
self.started.emit(fps, video_res)
@Slot()
@@ -87,6 +90,63 @@ class VideoStreamWorker(QObject):
self._cap = None
self.stopped.emit()
# def run(self):
# while self._is_running:
# self._process_frame()
# time.sleep(0.028) # Krótka przerwa, aby nie zablokować CPU
def run(self):
"""Główna pętla wątku roboczego."""
if self._source is None:
logger.warning("No video source provided")
return
self.cap = cv2.VideoCapture(self._source)
if not self.cap.isOpened():
logger.error(f"Failed to open video source: {self._source}")
return
self.fps = self.cap.get(cv2.CAP_PROP_FPS)
if self.fps <= 0:
self.fps = 30.0
self.width = int(self.cap.get(cv2.CAP_PROP_FRAME_WIDTH))
self.height = int(self.cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
logger.debug(f"Video opened: {self._source} (fps: {self.fps}, size: {self.width}x{self.height})")
frame_interval = 1.0 / (self.fps + 1)
self.running = True
frame_emit_time = time.perf_counter()
read_start_time = 0.0
read_end_time = 0.0
frames_dropped = 0
while self.running:
next_frame_time = frame_emit_time + frame_interval
ret, frame = self.cap.read()
read_end_time = time.perf_counter()
self.frame_time.emit(read_start_time, read_end_time, frames_dropped)
if not ret:
logger.debug("End of video stream or read error")
break
current_time = time.perf_counter()
# self.metrics.last_cap_time = current_time - frame_emit_time
if current_time < next_frame_time:
sleep_time = next_frame_time - current_time
time.sleep(sleep_time)
else:
frames_dropped += 1
logger.debug(f"Frame drops counted: {frames_dropped}")
frame_emit_time = time.perf_counter()
read_start_time = time.perf_counter()
self.frame_ready.emit(frame)
def _process_frame(self):
if not self._is_running:
logger.debug("VideoStreamWorker is not running. Skipping frame processing.")