src.nth.io/

summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--main/stream_server.c14
-rw-r--r--scrypted/scrypted-viewport.ts21
-rw-r--r--sdkconfig.defaults19
3 files changed, 40 insertions, 14 deletions
diff --git a/main/stream_server.c b/main/stream_server.c
index 7876968..10d1e1b 100644
--- a/main/stream_server.c
+++ b/main/stream_server.c
@@ -9,6 +9,7 @@
#include "freertos/task.h"
#include "lwip/netdb.h"
#include "lwip/sockets.h"
+#include "sys/ioctl.h"
#include "display.h"
#include "jpeg_decoder.h"
@@ -132,6 +133,19 @@ static void handle_client(int fd, const char *peer)
continue;
}
+ // "Always paint the latest" — if the socket already has more
+ // bytes queued in the kernel receive buffer, at least one more
+ // header is on the way. The frame we just finished receiving
+ // is no longer the freshest possible; skip its decode+paint
+ // (saves ~6ms per skip) and loop straight to the next header.
+ // This trades some intermediate frames for lower
+ // glass-to-glass latency on the latest one.
+ int queued = 0;
+ if (ioctl(fd, FIONREAD, &queued) == 0 && queued >= HEADER_BYTES) {
+ jpeg_decoder_unlock();
+ continue;
+ }
+
size_t back_size = 0;
void *back = display_back_buffer(&back_size);
uint16_t w = 0, h = 0;
diff --git a/scrypted/scrypted-viewport.ts b/scrypted/scrypted-viewport.ts
index f25f557..fddfd28 100644
--- a/scrypted/scrypted-viewport.ts
+++ b/scrypted/scrypted-viewport.ts
@@ -6,7 +6,7 @@
// short git hash of the commit that added this constant — if the
// hash in the log doesn't match the HEAD this file came from, the
// Scrypted Script editor is still on stale code.
-const SCRIPT_VERSION = "521de7e";
+const SCRIPT_VERSION = "pending";
//
// Architecture
// ------------
@@ -947,12 +947,15 @@ class ScryptedViewportProvider extends ScryptedDeviceBase
workBuf = workBuf.subarray(eoi + 2);
if (frame.length < 4 || frame[0] !== 0xff || frame[1] !== 0xd8) continue;
- // Drop if the socket isn't connected yet (initial
- // open) or if the kernel send buffer is full
- // (firmware can't ingest as fast as ffmpeg emits).
- // Frame is gone forever — TCP doesn't queue what
- // we don't write.
- if (!socketReady || socketBackpressured) {
+ // Drop only when the socket isn't connected yet
+ // (initial-open race) — once it's up we just keep
+ // writing. Node buffers internally if the kernel
+ // send buffer is full; under 16 MB/s ffmpeg output
+ // and ~5-7 MB/s firmware ingest the buffer rarely
+ // exceeds a frame or two. The firmware's FIONREAD-
+ // skip ensures it always paints the LATEST queued
+ // frame, so any backlog gets shed there for free.
+ if (!socketReady) {
droppedFrames++;
continue;
}
@@ -969,7 +972,11 @@ class ScryptedViewportProvider extends ScryptedDeviceBase
if (writeLatencies.length > 200) writeLatencies.shift();
bytesSent += 8 + frame.length;
sentFrames++;
+ // Track but don't gate on backpressure — the metric
+ // is still useful as a "kernel buffer was full"
+ // indicator for diagnostics.
if (!ok) socketBackpressured = true;
+ else socketBackpressured = false;
}
});
diff --git a/sdkconfig.defaults b/sdkconfig.defaults
index 4c50a23..1ba8375 100644
--- a/sdkconfig.defaults
+++ b/sdkconfig.defaults
@@ -29,13 +29,18 @@ CONFIG_LWIP_IPV4=y
CONFIG_LWIP_IPV6=y
CONFIG_MDNS_MAX_INTERFACES=1
-# TCP receive-window tuning attempted (WND/SND_BUF=32k, RECVMBOX=16,
-# SACK on). Measured net-negative on the /frame path: ttfb regressed
-# from ~350µs to ~1.2ms, body unchanged, and periodic 250+ms stalls
-# appeared. Reason: Scrypted's per-frame fetch() opens a fresh TCP
-# socket each time, so the larger window just slows slow-start.
-# Reverted; revisit once we switch to HTTP keep-alive on the Scrypted
-# side. Keeping the lwIP defaults.
+# TCP receive-window + buffer tuning. Earlier attempt under HTTP
+# regressed because every /frame opened a fresh socket and we ate
+# the slow-start cost repeatedly. Under the streaming pivot the
+# socket is long-lived: slow-start happens once, then we run with
+# the full window for the rest of the session — which is exactly
+# the workload these knobs are designed for. Larger WND lets the
+# sender keep more bytes in flight per ACK and pushes our recv
+# throughput ceiling up from ~5.3 MB/s.
+CONFIG_LWIP_TCP_WND_DEFAULT=65535
+CONFIG_LWIP_TCP_SND_BUF_DEFAULT=65535
+CONFIG_LWIP_TCP_RECVMBOX_SIZE=16
+CONFIG_LWIP_TCP_SACK_OUT=y
# HTTP server
CONFIG_HTTPD_MAX_REQ_HDR_LEN=1024