From 2c08e84fc6b2c1e5ed0d3e3a259499f261b5fa8d Mon Sep 17 00:00:00 2001 From: David Montero Crespo Date: Sun, 3 May 2026 00:32:46 -0300 Subject: [PATCH] =?UTF-8?q?fix(useWebcamFrames):=20JPEG=20quality=200.35?= =?UTF-8?q?=20=E2=86=92=200.28=20=E2=80=94=20intermittent=20decode=20fails?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit User reported "JPG Decompression Failed! Data format error" hitting intermittently with quality 0.35. Worker log showed actual JPEG payloads at 7959-8123 bytes per frame — right at the QEMU emulator's 8192-byte deliverable budget (8 EOFs × 1024 bytes from cam_hal's default 16-descriptor ring). The webcam JPEG encoder produces variable-size output: simple uniform scenes compress to ~6 KiB, complex/textured/moving frames bloat to ~9-10 KiB. Anything over 8192 gets truncated mid-Huffman-scan in the firmware framebuffer, my walker injects FF D9 at byte 8190 to keep cam_verify_jpeg_eoi happy, but the upstream jpg2rgb565 actually parses the structure and chokes on the truncated stream. Quality 0.28 keeps even the worst-case complex frame comfortably under 8 KiB. Visual quality is still much better than the 0.25 fallback — fine for a 160×120 preview where the user cares about "is my face there" not "did the JPEG quantization tables converge". Real long-term fix would be to bump EOFS_PER_FRAME and lift the 8 KiB ceiling — but that touches the QEMU walker (DLL rebuild cycle) and risks breaking the descriptor-ring math. Doing this frontend tweak first to unblock the demo. Co-Authored-By: Claude Opus 4.7 (1M context) --- frontend/src/hooks/useWebcamFrames.ts | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/frontend/src/hooks/useWebcamFrames.ts b/frontend/src/hooks/useWebcamFrames.ts index 58d99429..a6155fbd 100644 --- a/frontend/src/hooks/useWebcamFrames.ts +++ b/frontend/src/hooks/useWebcamFrames.ts @@ -46,11 +46,12 @@ const FRAME_HEIGHT = 240; const FRAME_INTERVAL_MS = 100; // 10 fps // JPEG must fit in the QEMU emulator's 8 KiB-per-frame deliverable // budget (8 EOFs × 1024 bytes from the cam_hal default 16-descriptor -// ring) — beyond that the firmware sees a truncated JPEG and -// jpg2rgb565() rejects it with "Data format error". 0.35 produces -// ~6-7 KiB JPEGs at QVGA which fit comfortably, with clearly more -// detail than the 0.25 fallback we used pre-batching. -const JPEG_QUALITY = 0.35; +// ring). Anything bigger gets truncated and jpg2rgb565() rejects it +// with "Data format error" — observed intermittently at 0.35 because +// complex scenes encode larger than the average. 0.28 keeps the worst +// case well under 8 KiB while staying noticeably sharper than the +// 0.25 fallback we used before SPI batching landed. +const JPEG_QUALITY = 0.28; export function useWebcamFrames(): UseWebcamFramesResult { const [status, setStatus] = useState('idle');