Cattura: rimuovi videorate e limita la coda all'ultimo frame
La pipeline GStreamer non forza più la frequenza con videorate e usa un appsink con max-buffers=1, drop e enable-last-sample=false: si elabora solo il frame più recente invece di duplicare frame o accumulare ritardo. Il demone rinnova inoltre l'ultimo frame inviato ogni 10 s quando la sorgente a frequenza variabile non produce nuovi campioni (schermata statica), evitando il timeout del firmware Adalight, e usa time.monotonic per il pacing di invio al posto di time.time.
This commit is contained in:
@@ -79,10 +79,9 @@ class Capture:
|
||||
self.gw = leds * sub
|
||||
self.gh = rows
|
||||
desc = (f"pipewiresrc path={node} do-timestamp=true ! "
|
||||
f"videoconvert ! videoscale ! videorate ! "
|
||||
f"video/x-raw,format=RGB,width={self.gw},height={self.gh},"
|
||||
f"framerate={int(fps)}/1 ! "
|
||||
f"appsink name=sink emit-signals=false max-buffers=2 drop=true sync=false")
|
||||
f"videoconvert ! videoscale ! "
|
||||
f"video/x-raw,format=RGB,width={self.gw},height={self.gh} ! "
|
||||
f"appsink name=sink emit-signals=false max-buffers=1 drop=true sync=false enable-last-sample=false")
|
||||
self.pipe = Gst.parse_launch(desc)
|
||||
self.sink = self.pipe.get_by_name("sink")
|
||||
|
||||
|
||||
+12
-4
@@ -208,6 +208,7 @@ def capture_loop(state, strip):
|
||||
last_write = 0.0
|
||||
t_log = time.time()
|
||||
n_none = 0
|
||||
last_frame = None
|
||||
while True:
|
||||
cfg = state.snapshot()
|
||||
if not cfg["running"]:
|
||||
@@ -215,6 +216,7 @@ def capture_loop(state, strip):
|
||||
cap.stop()
|
||||
cap = None
|
||||
prev = None
|
||||
last_frame = None
|
||||
time.sleep(0.15)
|
||||
continue
|
||||
|
||||
@@ -239,10 +241,15 @@ def capture_loop(state, strip):
|
||||
|
||||
frame = cap.frame(200)
|
||||
if frame is None:
|
||||
# Una sorgente a frequenza variabile può fermarsi su una schermata
|
||||
# statica; rinnova il frame per il timeout del firmware Adalight.
|
||||
if last_frame is not None and time.monotonic() - last_write >= 10:
|
||||
if strip.write(last_frame):
|
||||
last_write = time.monotonic()
|
||||
n_none += 1
|
||||
time.sleep(0.005)
|
||||
if time.time() - t_log >= 10:
|
||||
log(f"diagnostica: 10 s senza frame (timeout={n_none}), "
|
||||
log(f"diagnostica: attese cattura negli ultimi 10 s (timeout={n_none}), "
|
||||
f"fps={state.fps} sent={sent}")
|
||||
t_log, n_none = time.time(), 0
|
||||
continue
|
||||
@@ -270,12 +277,13 @@ def capture_loop(state, strip):
|
||||
frame_bits = (6 + 3 * cfg["leds"]) * 10
|
||||
min_interval = max(1.0 / max(1, cfg["target_fps"]),
|
||||
1.7 * frame_bits / max(9600, cfg["baud"]))
|
||||
wait = min_interval - (time.time() - last_write)
|
||||
wait = min_interval - (time.monotonic() - last_write)
|
||||
if wait > 0:
|
||||
time.sleep(wait)
|
||||
ok = strip.write(adalight_frame(px))
|
||||
last_frame = adalight_frame(px)
|
||||
ok = strip.write(last_frame)
|
||||
if ok:
|
||||
last_write = time.time()
|
||||
last_write = time.monotonic()
|
||||
sent += 1
|
||||
now = time.time()
|
||||
if now - t_win >= 1.0:
|
||||
|
||||
Reference in New Issue
Block a user