Changelog - Lu-Fi/openimp GitHub Wiki

Changelog

Release candidate RC1 (v2026.10.11-rc1) is the newest release entry; work merged into next after RC1 (agg-36 to agg-38, not released) is listed first. Release pages: openimp, open-tx-isp (the same tag exists in the Lu-Fi forks and in the opensensor repositories).

This page contains the complete open-stack changelog: the RC1 summary first, then the state by camera and area, then the full dated log of the test campaign (since 2026-09-30) for OpenIMP, open-tx-isp and the thingino integration. The same text is kept in the repository as docs/OPEN_STACK_CHANGELOG.md (pinned to the RC1 tag).

Cameras are anonymised: cam-A (T31), cam-B (T23), cam-C (T20), cam-D (T21), cam-E (T10), cam-F (T41), cam-G and cam-H (T23, other sensors), cam-I (T20), cam-J (T21), cam-K (T40). Branch names (claude/...) are historic: the branches were merged into next and deleted. Later sections of the log use their own camera letters where stated.

Contents

Status words such as "in branch, not yet in an aggregate" in the dated log are historic and describe the moment of writing. What RC1 contains is defined by the RC1 section below and its "Next" list.

RC2 work in progress (2026-10-17, branches, not in next)

Branches: OpenIMP claude/rc2-t40-t41 (45d8cb8), open-tx-isp claude/t41-boot-oops (a44b5a25), claude/t41-ae-perframe (95f86744) and fable/t40-3a-perframe (patches 0039..0094). Camera naming: the second T41 board (gc5603), the Cinnado D1 T41NQ board (sc5336) and the T40 board. Only items with a device result are listed as done.

Done (device-tested):

  • T41 apitest, rc2 library: sys, fs, enc, osd, ivs, isp, su areas PASS 217, FAIL 0, N/A 30, SKIP 44, no oops. First run (old test binary) had 9 FAILs; causes: two stale test expectations (MaxDelay, GetTimedFrame window), ROI now N/A without OPENIMP_T41_ROI=1, and two real gaps fixed in the library: IMP_ISP_Tuning_GetWdrOutputMode (the open driver refuses 0x08000054; the library accepts the value and reads it back, the vendor functions are empty stubs) and IMP_ISP_GetDefaultBinPath (reports the bin the driver loaded, /etc/sensor/<sensor>-t41.bin).
  • T41 boot oops (exit_creds in the streamer, 2 occurrences) fixed: use-after-free of the isp_fw_process task. A failed first AddSensor closes the device before the worker ran, kthread_stop returns -EINTR, the driver treated that as failure and kept the stale pointer; the retry then stopped a freed task. Fix: clear the pointer first (xchg), -EINTR is a normal early stop. Verified deterministically with a diagnostic module parameter (3/3 cycles, old logic reproduced the stale stop) and 12 clean boots. Open (streamer side): why the first AddSensor fails sporadically (tisp_top_init -16).
  • T41 AE regulates (safe-AE controller): (1) a duplicate knot in the sc5336 target table made the metering return -1 every frame and froze IT/gain at the init values, so the picture stayed black and day/night stayed on day; now non-decreasing knots are accepted and any metering failure falls back to histogram mean; (2) gc5603: the coarse gain LUT plus the deflicker lattice kept AE outside the band, now IT is trimmed off the lattice first; (3) lattice/trim alternation at the gain limit; (4) the sensor frame rate was undone by the sensor module at stream-on (VTS 1800 with max IT 2152 gave black frames), now re-sent after the deferred sensor start. Results: dark room IT 2152 / 32x reached within 4 s; light on back to IT 1620 / 2.9x (zone mean 62, target 63) within about 4 s; 2x target step in under 1 s; gc5603 zone mean 71/70 stable; 0 oops on both boards. Not soaked; AE vendor lift (t41_safe_ae_controller=0) is still the unrepaired mechanical lift.
  • T40 vendor AE per frame (devtest, T40 board): the lift defects were repaired in sequence (divisor shifted twice, anti-flicker IT ladder built from a zero fps rational, module-context structures): AE converges 2-3 frames after the first allocation, zone mean 44 = target 44, IT 1875, gain about 6x, stable, no oops. The vendor stack on the same board uses the same IT regime with gain 1.1-1.3x, so our gain is still 4-5x high for the same luma (stats scaling or devtest pipeline state, open). Anti-flicker: t40_allow_antiflick default 1 and Set/Get fixed (before: the runtime switch oopsed on Get, off it ignored the request); ladder 469/938/1406/1875 at 50 Hz.
  • T40 OpenIMP (rc2): CPUInfo reads the real variant ("T40-XP" on the device), SetAntiFlickerAttr/GetAntiFlickerAttr send CID 0x08000026 (device: Set rc=0, driver logs the request), SetI2dAttr refuses an active rotate/flip/mirror request, CappedVBR/CappedQuality are marked emulated, an AVPU/JPEG failure becomes an error instead of a grey stream (static review only; not provocable in the devtest state).
  • Cinnado D1 T41NQ (thingino profile claude/cinnado-d1-t41): full OTA flashed by programmer: stream, WLAN, IR cut, PTZ and the status LEDs work (new thingino-leds module gives /sys/class/leds/led_* on the 4.4 kernel, LEDs confirmed by eye). Hostname from the overlay honoured.
  • agg-40 (thingino, test cameras) failure explained: /init matched ram anywhere in the command line, so the new ramoops.* bootargs skipped the overlay and the cameras came up without network; init now matches the root= value only (the cameras were restored from agg-39). The pstore/ramoops feature itself was dropped on the same day (the reserved RAM does not survive a reset on the T10; remote syslog already captures crashes).

In progress (branches, not done):

  • T40 module-context inits (gamma, LSC, CCM, BCSH, CLM) default off: gamma/LSC clean, CCM clean without refresh, BCSH/CCM refresh hangs; T40 AE with a real streamer and the anti-flicker start path (streamer applies anti_flicker, no tisp_s_antiflick seen in the kernel log).
  • T41: gc5603 strong blue/cyan cast (AWB/CCM), the day/night detector does not see the moving exposure yet (streamer side), IT-max lattice node and ISP digital gain for the LUT remainder, thinning the one-shot AE diagnostics before merge, light-on recovery to be repeated with a verifiably lit room.
  • Cinnado D1: PTZ tilt blocks at the software limit (no end switch homing), reset button on 4.4 (thingino-userkeys) built and untested, daylight colour test, upstream PR of thingino-leds after approval.
  • T31 "scheduling while atomic" in a short-lived helper after 4.7 days of uptime: analysis points to a preempt count of -1 (an extra unlock or an overwritten thread_info), not a leak; the camera logs were not readable, no conclusion yet.

After RC1: next (agg-36 to agg-38, state of 2026-10-12)

Everything in this section is in next but not in RC1 and not released. The aggregates agg-36, agg-37 and agg-38 were verified by build and host tests only (make check, make release-check, strict export check T10 to T41); no soak has run yet. Where an item says "device-tested" it was run on a camera on its topic branch; everything else is "host/build only, device test pending". Not in next (in progress): the T40 open kernel driver on the T40XP board with the sc830ai sensor delivers real frames, but it is not released and not part of any aggregate.

agg-38 (2026-10-12)

  • AWB statistics with a freshness contract: T23/T31 IMP_ISP_Tuning_GetAwbZone (vendor 675-byte block and scaling) and T40/T41 IMP_ISP_Tuning_GetAwbStatistics (2700-byte planes) return 0 only for statistics of a current frame (the driver answers -EAGAIN for data older than one second or no running stream); capability symbols OpenIMP_Cap_AwbZone / OpenIMP_Cap_AwbStatistics. Device-tested on cam-A (T31), cam-B (T23), cam-K (T40, vendor kernel) and cam-F (T41).
  • T31 CBR under an impossible scene (fix): the rate controller's buffer debt is now bounded (4 buffers), so the QP no longer collapses after about 700 pictures and recovers within about 15 s once the scene is easy again. Host test; device test pending.
  • Thread names: every OpenIMP thread is named (top -H shows which one uses the CPU). No behaviour change.
  • Helix per-frame encode path at -O2 on T10/T20/T21/T23/T30 (per-frame code was slowed by the size-optimised build); exported symbols unchanged; CPU A/B on a device pending.
  • T40 night work: fixes for the getters that failed in the first T40 device run (GetHVFlip, GetBcshHue, GetISPRunningMode, IMP_Encoder_Query), SEI user data, draw attributes, OSD group callback and ISP-drawn regions, digital gain, GetRaw. IMP_ISP_StartNightMode and IMP_ISP_Bypass_Bind are device-tested on cam-K (same return codes as the vendor library, black-and-white picture in night mode); the rest is host-tested.
  • T41 ISP tuning calls of the vendor libimp 1.2.6 (AE/AWB converge step, CT trend offset, EV/AT list, TMO curve, statistics configuration, WaitFrameDone, GetHVFlip) with the matching driver handlers. Seven of them were device-tested on cam-F; WaitFrameDone still returns a constant frame counter and the TMO curve showed no visible effect in that configuration.
  • open-tx-isp:
    • T31/T23 module parameter fcrop_upscale_pct is capped at 100 (2.0x); 150 % (2.5x) hard-hung a T31 until the hardware watchdog reset it.
    • T31 sharpness mapping re-applied on a bank refresh like the stock driver.
    • T41 reload fixes (VIN index bound, module pinned while frame-channel files are open, IRQs freed with their dev_id); 50 load/unload cycles clean on cam-F.
    • Vendor-compatible /proc/jz/sensor file layout (host test only).
    • T23 build fix: the crop cap used READ_ONCE, which the 3.10 kernel lacks.

agg-37 (2026-10-11, host/build only unless stated)

  • Smaller libimp.so and modules: -Os for the library with -O2 kept for per-pixel, per-macroblock, audio and floating-point files (OPENIMP_SIZE_OPT=0 builds all at -O2); Helix SoCs drop the AVPU session code; T31 kernel module exports only the symbols other modules import (about -46 KB), T10/T20 modules about -20 KB each.
  • T23 OEM Helix worker bridge off by default (OPENIMP_T23_HELIX_BRIDGE=0): the native Helix encoder is the only H.264 backend on T23; IMP_Decoder_* fails on T23 unless the bridge is built in again.
  • T10/T20: SetAntiFogAttr (driver preset that cannot hang) and SetMeshShadingScale exported like the vendor 3.12.0 library; IMP_Encoder_SetChnRcTrigLevel.
  • T23 SwitchBin reworked: the new day/night banks are validated in a private buffer and published by pointer; no copy over the live banks. T23/T31 module parameter msca_flip_state (read-only) shows who flips each axis.
  • T40: HEVC FixQP with the vendor lambda tables (4K bit-rate deviation +27 % to -1 %), SetChnMapRoi and SetChnRoiAttr behind OPENIMP_T40_ROI=1, about 22 ISP control functions, quiet kernel log (t40_runtime_trace=1 restores it).
  • T41: IMP_ISP_Set/GetISPBypass (the driver does not serve that ioctl yet), run-time SetChnBitRate regenerates the hardware rate-control thresholds; driver stability fixes (handle counting of /dev/isp-m0, real DMA buffer for IVDC, out-of-object accesses removed, unrecovered WDR fusion body refused unless t41_wdr_fusion_unsafe=1), quiet kernel log, /proc/jz/isp watcher (report only). Of these, the handle counting was device-verified on cam-F in the agg-38 session.
  • SU_Base_Shutdown syncs and then sends init SIGTERM (busybox reboots) by default; OPENIMP_SU_SHUTDOWN=poweroff|vendor selects the other behaviours.
  • Tooling: make release-check (host tests, build of every SoC, strict export check) and make export-check (compares exports with the vendor lists). The matrix was corrected from it (T41 cells, T10/T20/T21 Encoder_Get/SetChnCrop missing, 11 T40 OSD rows exported).

agg-36 (2026-10-11)

  • T40 encoder (device-tested on cam-K on its branch): frame-level rate control (CBR/VBR follow the target; this addresses the "about 20 %" RC1 known issue), AVPU command lists as the vendor library, H.265 with correct PPS and hardware rate control.
  • T40 ISP-drawn OSD, Get/SetMask and SwitchBin: device-tested against the vendor library. T41 SwitchBin, AutoZoom, SetMaskBlock/GetMaskBlock, SetScalerLv: host tests and module builds only.
  • Log level: OPENIMP_LOG_LEVEL (0..7, default 5 = notice); per-frame information lines are silent by default. Build switch OPENIMP_DEBUG (default 0) compiles the developer traces out; stripped .text shrinks by about 24 to 29 % per SoC.
  • IVS: a frame fed right after a result is no longer dropped (OPENIMP_IVS_VENDOR_ORDER=1 restores the vendor order).
  • Vendor-API gaps: T30 317 of 334 vendor exports (was 271, host tests only, no T30 camera); SetbufshareChn value kept and checked like the vendor; vendor return codes for several T10/T20/T21 encoder calls and T23 SetChnROI/GetChnROI.

RC1 (v2026.10.11-rc1)

RC1 v2026.10.11-rc1: openimp claude/rc1 (agg-35 687a68e4 + docs), open-tx-isp 6e464ac7.

Soak evidence: agg-35 ran on 10 cameras from 2026-10-10 18:04 to 2026-10-11 08:00 (about 14 h): 0 kernel oopses, 0 unexplained reboots, 0 application restarts, VA-API decode check 54/54. The soaked images are built on thingino aperto base a4bcc1c86.

Supported SoCs: release: T10, T20, T21, T23, T31. Experimental (not part of the release promise): T30 (no device in the lab, host/build evidence only), T40 (first device run only, see the matrix) and T41 (channel 1 and night colour open).

Known issues (RC1):

  • T41 channel 1 (sub-stream) colour at night differs from channel 0 (picture soak finding); T41 stays experimental.
  • T31, black picture of about 80 s seen once during a day/night probe; not understood yet.
  • T23, dusk flapping: a T23 camera switched between day and night several times at dusk. The day/night decision is made by the application; the library and driver report the sensor values.
  • Day/night in a poorly lit location is likewise decided by the application; the library and driver report the sensor values.
  • T40: CBR delivers only about 20 % of the target rate, H.265 not supported yet. T41: no audio hardware on the test board (API level only).

Next (after RC1, agg-36): work that is not in agg-35 and therefore not part of this release candidate: T40 rate control and H.265, T40 ISP-drawn OSD, further vendor-API gap work (T30, T1x, T23/T31), T41 mask/zoom, log level default, IVS result ordering and review fixes.

Summary of the changes since 2026-10-06 (all contained in RC1 unless marked)

  • Candidates and soaks: agg-28 (2026-10-06) went through agg-32 (soak 43.4 h, 2026-10-07 to 10-09, 0 unplanned reboots and oopses on the cameras without user interaction) and agg-34 to agg-35, the RC1 code. agg-35 soak: 10 cameras, about 14 h, clean (see above).
  • Encoder ROI (region QP): T31 gets an encoder ROI the vendor library does not have (IMP_Encoder_SetChnRoiAttr through the AVPU QP table, up to 10 windows); T21, T23 (native Helix encoder; capability marker OpenIMP_Cap_T23HelixRoi) and T10/T20 SetChnROI act. Streams stay valid H.264 with every ROI: deltas are clamped to -25..+25 (an application should not request -26). Switches OPENIMP_T31_ROI, OPENIMP_T21_ROI, OPENIMP_T23_ROI.
  • Front crop: T31 refuses a window smaller than a running channel's scaler output (-EINVAL) instead of stalling the MSCA, and the crop is now effective on both streams (device-tested in daylight); T23 crop hang fixed; T20/T10 keep the window until a downscaled channel opens; the window is released with the ISP session. Open-tx-isp module parameter fcrop_upscale_pct (T23, T31) also serves as a runtime marker for the safe path. The crop window is in sensor space, before the flip.
  • T20/T10 day/night: isp-m0 reports the analog gain cap the AE really reaches (T20: smaller of sensor maximum and SetMaxAgain ceiling; T10: the reached table step, 142 instead of 144).
  • T31 WDR statistics ring: now persistent across STREAMOFF, DMA engine disabled before the free (100 stop/start cycles and 20 reloads without anomaly).
  • Image controls: T21 SetBrightness acts (exposure compensation) and sepia works; T23 AF statistics on by default; AeComp measured on T20 and T31 (T31 AE needs about 30 s to settle); T21/T20/T10 encoder denoise semantics match the vendor.
  • Audio: AO/AI and EnableAec device-tested on T10, T20, T21, T23, T31 (AECM, mono 16 kHz, ERLE on a speech segment 19 to 25 dB); T41 audio at API level only.
  • T41 (experimental): gamma, CCM, CSC presets, manual exposure readback and module control; driver controls frame drop, sensor register, WDR enable and AF weight; apitest 260 PASS / 9 FAIL (was 167 / 19). MSCA channel-1 latch is opt-in and correct up to 768x432.
  • T40 (experimental): first OpenIMP device run (vendor kernel driver, vendor libimp side by side): FrameSource, H.264 on two channels, OSD, IVS and more pass; open: CBR about 20 % of target, no H.265.
  • Library and API: GetFrame waits like the vendor, IMP_Encoder_GetFd pipe, a JPEG channel feeds itself, two IVS groups, SEI user data, vendor-API gap reclassification (T23 15 gaps, T31 8, T10 41, T20 39, T21 18).
  • Matrix: T30 and T40 columns added (host/build evidence; T40 plus the first device run); see Feature Matrix and Per-SoC Status.
  • Operations findings: T23 errno 5: 0 errors in 6 days since kernel patch 0102 (provisionally closed, still observed); one unexplained silent reboot of a T23 camera under agg-34 (a kernel-log capture is installed to catch the next one).

Highlights by area (state of 2026-10-05, still valid; RC1 additions are in the RC1 section)

OpenIMP

  • Real HEVC on T31; hardware JPEG on T31; native Helix encoder on T23 without vendor code.
  • Capped rate-control modes, Allegro RC core on T31, vendor-identical OEM controllers on T10/T20, eprc on T21/T23.
  • Real motion detection on T20/T21/T30; motion v2 (bounding boxes, strength, suppression after IR/gain jumps) on by default, OPENIMP_MOTION_V2=0 restores the vendor algorithm.
  • OSD on T20/T21 (IPU hook); real AECM echo cancellation on T31; software rotation on T31.
  • Binaries 40-50 % smaller than the vendor library; rmem peak logging and shortfall hints.

open-tx-isp

  • Lifecycle hardening (locking, use-after-free, STREAMOFF races, bounded tuning access) on all SoCs; module reload clean on every SoC including T41.
  • Exposure readback, tuning controls wired (T23 about 45 control IDs), unknown IDs rejected.
  • T21: stock AE and ADR lifted instruction by instruction; T23 vendor AE lifted (default on); T20 simple AE/AWB; T41 gc5603 tuning fix.
  • Modules smaller than the vendor ones on T21, T23 and T31; 8 MB MMAP pool optional on T10/T20.
  • Sensor module pinned while the ISP is open; sensor registry under /proc/jz/sensor.

thingino integration

  • Packages openimp and open-tx-isp are in upstream thingino branch aperto (pull request #1756), pinned to the opensensor repositories (aperto); kernel VPU/rmem stability patches (#1748, #1752), optional boot guard (#1749) and two SC2336 flip fixes (#1750, #1751) are merged there. The guarded fw_setenv for T41 (#1738) is not upstream.

Where each camera stands

All test cameras run the open kernel driver (open-tx-isp), OpenIMP. No Ingenic or neo helper libraries (libalog/libsysutils) remain on the images. Since 2026-10-04 17:39-17:47 every camera runs a full OTA image built from thingino aperto with open-tx-isp next and OpenIMP next (30/30 snapshots, 0 oops, 0 VPU errors); a 24 h soak runs since 17:50 and the first release tag follows after it.

Camera SoC Stack State
cam-A T31 fully open aperto image; H.264, H.265, hardware JPEG, OSD, AEC; rmem 36 MB
cam-B T23 fully open (native encoder, no vendor helper) aperto image; frequent Helix frame drops fixed (residual interrupt); the rare single Helix encode error (errno 5): 0 errors in 6 days on cam-B since the 0102 fix (syslog: 342, 32, 37 and 419 errors on 10-01..10-04, then 0 from 10-05 to 10-10); provisionally closed, still observed
cam-C T20 fully open aperto image with kernel patch 0101; OEM rate controller default; A/B vs vendor measured
cam-D T21 fully open aperto image; reference sharing on; vendor-identical eprc
cam-E T10 fully open aperto image, boot guard auto; ispmem 6 MB
cam-F T41 fully open aperto image (rootfs rev7, rmem 26M); H.264 and H.265; open: flip, night column noise, short IVS gaps
cam-G, cam-H T23 fully open two further T23 cameras (other sensors); cam-H is part of the aperto image run

OpenIMP (userspace libimp)

Area Was Now Branch
ISP tuning Contrast/sharpness started at 0 instead of 0x80 Vendor defaults claude/openimp-quickfixes
ISP tuning T20/T21 T31 control IDs sent; wrong AeLuma ID; TotalGain/RunningMode/FPS without result pointer SDK control IDs, pointer semantics as vendor claude/openimp-quickfixes, claude/exposure-readback, claude/t20-tuning-ptr
Day/night T20/T21 Brightness/contrast/saturation/sharpness not re-sent on switch; sinter/temper sent to rejected IDs Re-sent like vendor; table-based sinter/temper claude/tseries-daynight
ISP tuning T23 GetSensorAttr wrote past the caller's buffer Vendor 20-byte layout via bounce buffer claude/t23-sensorattr
ISP tuning T31 AF IDs wrong; SensorAttr/WaitFrame/ModuleControl cache-only Through the driver with vendor ABI claude/t31-isp-gaps
Encoder rate control CappedVBR/CappedQuality/SMART silently CBR Mapped to VBR with log line claude/openimp-quickfixes
JPEG Quality ignored (fixed 75 or cached only) Configured quality applied claude/openimp-quickfixes
HEVC T31 H.265 accepted but streams empty Real HEVC on the AVPU: VPS/SPS/PPS, slice headers, CABAC init as vendor claude/t31-hevc
Encoder denoise T20/T21 SetChnDenoise stored whatever it got, dnType >= 3 accepted, enable switch of CreateChn ignored Vendor semantics: enable gate from CreateChn, dnType >= 3 is -1, IQp/PQp kept; on T21 dnType reads back 0 as on the vendor T21 (libimp 1.0.33 clears denoise at init: encoder mode from get_cpu_id). T10/T20 two-pass encode not built claude/t21-chn-denoise
Encoder telemetry Channel-stat struct one word short; bitrate not averaged; stack overflow in ChnStatQuery Vendor layout, real average, fixed claude/openimp-quickfixes
T23 encoder Vendor Helix worker only; worker zeroed all of rmem; wrong RPATH Per-worker rmem slices; native Helix encoder without vendor code claude/t23-helix-worker-fixes, claude/t23-native-helix-2
Helix T20/T21/T30 Encoder issues on the Helix path Fixed claude/t30-helix-fixes
OSD Never drawn on T20/T21 (Helix path) IPU OSD hook claude/t20-osd
Motion detection T20/T21/T30 always "no motion" Real frame-diff IVS ported from T31/T23 claude/tseries-ivs
Audio out Volume/mute ignored; partial OSS fragments dropped Applied; whole-fragment writes claude/openimp-quickfixes, claude/t31-ao-fix
Framesource / VBM T21 Idle teardown freed the pool; later allocations failed in 23 MB rmem Pool parking and reuse claude/t21-bringup
T31 HW JPEG Software JPEG only Hardware JPEG path, hardened claude/t31-hwjpeg-default
Audio AEC T31/T23 EnableAec only set a flag (T23) or returned fake success (T31) Real WebRTC AECM (BSD-3) on the driver's speaker reference; errors when it cannot run; OPENIMP_AEC_STATS diagnostics claude/aec
Rotation T31 SetChnRotate 90/270 returned -1 Software rotation like the vendor (32x32 tiles) before OSD/IVS/encoder claude/t31-rotate
Tools No way to exercise T23 tuning on device t23tune (show, max gain, IT max, DRC, defog, sinter, flip, max dgain) claude/t23-tune-tool

open-tx-isp (kernel driver)

T31 (reference SoC)

  • Lifecycle hardening: locking around frame-channel ioctls, STREAMOFF races, buffers freed under a running ISP, last-close use-after-free, bounded tuning register access; rmmod oops fixed (3 clean cycles).
  • Frame-channel DQBUF honours O_NONBLOCK.
  • Tuning gaps: RGB coefficients as int16, AE ROI getter/setters and EXPR setter, AE histogram edges kept, correct isp-m0 gain lines, isp-w02 VIC error counters, SensorAttr, per-frame WaitFrame (claude/t31-tuning-gaps).

T23

  • Exposure readback: Expr/EV/TotalGain were constants; now live values and vendor-format isp-m0 (claude/exposure-readback).
  • Day→night kernel oops: a zeroed array was used as a wait queue; now a real wait queue (claude/t23-tuning-wiring).
  • About 45 control IDs silently returned success; unknown IDs are now rejected; WB, CCM, DRC, defog, DPC, CSC, module control, live WB statistics, flip and anti-flicker wired (claude/t23-tuning-wiring).
  • Night picture stayed purple: the CSC clip register write had lost its argument; night mono restored (claude/t23-tuning-rest).
  • Max analog gain, IT max, SensorAttr, DRC/defog enable, non-compounding sinter (claude/t23-tuning-rest); max ISP digital gain as a new AE stage and Bayer re-sync after sensor flip (claude/t23-flip-dgain); SetSensorFPS.
  • Static memory: oversized decompiler placeholder arrays shrunk; module 1,598 KB → 1,095 KB (claude/t23-bss-shrink).

T20

  • No isp-m0 → vendor-format isp-m0; AE exposure read the table address instead of the value (claude/exposure-readback).
  • Kernel oops on application stop/restart: sensors released without unbind; fixed, 20 clean cycles (claude/t20-stop-oops).
  • Max analog gain applied by the AE; line time reported instead of 0; scene-mode IT limit no longer lost (claude/t20-ae-limits).

T21 (first open bring-up)

  • Exposure readback, unreachable controls (0x2c–0x45), EV in wrong units fixed; day/night decided correctly (claude/t21-exposure).
  • Night flicker (ISP gain cycling 6↔25): now the stock AE itself, lifted instruction-for-instruction from the vendor module, including the second AE stage.
  • Noise: 2DNR read its parameters from a text table; denoise never followed gain; registers written without value; fixed.
  • Night mono, colour blotches (lens-shading gains doubled per channel) and overexposure (fixed ADR curve) fixed; ADR and defog lifted from stock.
  • Control dispatchers lifted from stock: anti-flicker, sensor FPS, readable brightness/contrast/saturation/sharpness, AE ROI/zone/histogram, flip.
  • All on claude/t21-image-fixes.

Robustness: better than the vendor driver (2026-10-02)

Goal: identical image behaviour, but cleaner unload/reload, less memory and checked inputs.

SoC Branch Result on device
T23 claude/t23-robust 10x application stop/start incl. kill -9, 10x rmmod/insmod, 0 oops; two out-of-bounds writes fixed (2 KB and 18 KB past arrays); bss 434 → 180 KB
T20 claude/t20-robust rmmod while streaming correctly refused; 10x stop/start + 10x reload, 0 oops; decompile fixes (1 KB copy to address 0, AE reading a kernel address); all 53 user copies checked
T31 claude/t31-robust 10x reload with kill -9, vmalloc leak (252 KB/cycle) fixed, no stuck firmware thread; module 716 KB vs vendor 829 KB
T21 claude/t21-robust 10x stop/start + rmmod/insmod with a snapshot each time, 0 oops; root cause of the old reload oops: ISP statistics DMA still writing into freed buffers, now the ISP is reset first; sensor GPIO release; bss 259 → 106 KB

OpenIMP: T20 green flicker in the bottom rows fixed by filling the encoder padding rows (claude/t20-bottom-chroma; 0 green pixels in 30 frames). Faster IVS (claude/ivs-opt; T20 application CPU 4.1 % → 2.7 % with motion on).

Aggregates: claude/open-tx-isp-all-4 and claude/openimp-all-4 (pushed); 58 merged single branches removed. claude/open-tx-isp-all-5 adds t21-robust and t31-robust-2 (T31: sensor flip with shvflip=1, unload leaks, lazy WDR buffers; MemFree drift per reload 460 → 45 KB); all four cameras flashed with -all-5 images.

2026-10-10: results of the day (all code items "in branch, not yet in an aggregate")

Status key: in branch = committed on a claude/... branch, built and device-tested as noted, not yet in an aggregate and not in next.

Area Result Status
T23 encoder ROI IMP_Encoder_SetChnROI on the native Helix encoder (the vendor 1.3.0 encoder writes the same registers). Device-tested on cam-B: the QP map shows the window, relative QP saturates at -12/+13 around the slice QP (like T21), bit rate +10 % at delta -15 and -4 % at +20 / absolute 51, streams valid in VA-API (0 errors) and strict ffmpeg. OPENIMP_T23_ROI=0 switches it off. Matrix row 45: T23 is now supported (was a vendor no-op). Details: docs/ROI.md in branch claude/t23-roi (1f1f7d1 docs, 8e44d3c code)
T23 runtime capability marker libimp exports the const symbol OpenIMP_Cap_T23HelixRoi; older libimps drop T23 ROI regions silently, so an application probes it with a weak extern or dlsym (docs/OPENIMP_BEYOND_VENDOR.md) in branch claude/t23-roi (c271c07)
T21 / T20 / T10 encoder denoise The vendor T21 libimp (1.0.33) disables the encoder denoise internally (encoder mode 4 from the CPU id), so GetChnDenoise reads back type 0. OpenIMP T21 matches these semantics (enable gate, dnType >= 3 is -1); A/B against the vendor stack equal. T10/T20 vendor two-pass denoise encode is not built in branch claude/t21-chn-denoise (aaeb2d1)
T10 max analog gain open-tx-isp isp-m0 now reports the gain step the AE really reaches (T10: 142 instead of 144; exact steps and the sensor maximum unchanged); device-tested on T10, reported equals the measured plateau in branch open-tx-isp claude/t10-gaincap (d86533ee)
T40/T41 API apitest on T41: 260 PASS / 9 FAIL (was 167 / 19). Remaining: 4 driver, 4 audio mute (driver ioctl), 1 tool. New in the library: FrameSource delay cache and I2D attributes, ISP sensor register / frame drop / AF weight / WDR enable via the vendor control numbers (the driver must implement them), IMP_Encoder_SetChnMapRoi on the experimental T41 ROI table (OPENIMP_T41_ROI=1, host test only) in branch claude/t40-t41-api (4ee16ea)
T41 tuning Gamma restore, CCM, CSC presets 0 to 4 (CSC wire-order fix: the swapped offset/clip order made the kernel refuse user tables), manual exposure readback, module control, module ratios. Device-tested. Matrix cells for these T41 functions are not yet moved to "dev" (done together with the T41 aggregate) in branch claude/t41-tuning (OpenIMP 8b98b38; open-tx-isp 3561edd5, f0356bd4)
Gap reclassification Vendor export check of the remaining gap functions (host-only): T23 gaps 22 to 15, T31 29 to 8, T10 48 to 41, T20 46 to 39, T21 23 to 18 (with the denoise change); includes T23 Encoder_Get/SetH265TransCfg as the vendor, T31 ISP_SetFixedContraster with the attr pointer (host test) docs from claude/gaps-t23-t31, claude/gaps-t1x; the two code commits are in those branches, not yet in an aggregate
Front crop vs flip (application integration notes) Device-tested on all SoCs (cam-A to cam-F). The crop window is in sensor space, before the flip; the window in picture coordinates is what an application mirrors afterwards. T23, T21, T31: both axes. T20, T10: vertical only (the horizontal flip is the ISP top mirror before the crop, the vertical flip is in DMA after it). T23 detail: with image hflip/vflip both the sensor (reg 0x3221) and the MSCA (0xd050) flip; shvflip=1 only flips the LSC mesh. The vendor does no transform (T23/T31 stock); T10/T20/T21 have no vendor SetFrontCrop. See docs/OPENIMP_BEYOND_VENDOR.md device-tested
Front-crop capability marker, T31 crop effective An application can detect at runtime whether the driver has the safe front-crop path: /sys/module/tx_isp_t23/parameters/fcrop_upscale_pct (T23) or /sys/module/tx_isp_t31/parameters/fcrop_upscale_pct (T31) exists only in fixed drivers. T31 front crop is now effective: the picture effect is proven on both streams in daylight (cam-A) device-tested (agg-34 drivers)
AeComp (IMP_ISP_Tuning_SetAeComp) T20 / T31 T20 (cam-C): works and is monotonic; measured luma 56 / 105 / 245 for comp 0 / 128 / 255. T31 (cam-A): works with the OEM formula; luma 55 / 100 / 160 for 0 / 128 / 255. The T31 AE is slow: about 6 s dead time and 25 to 30 s to settle, so a test (or an application reacting to a comp change) must allow at least 30 s device-tested
open-tx-isp agg-34.1 (56981169): T31 WDR statistics ring agg-34.1 = agg-34 + a T31 fix: the WDR statistics ring was kfreed at every STREAMOFF while its DMA engine (reg 0x2024) was still running. The ring now stays persistent, the engine is disabled before the free, and the IRQ window is closed. Device (cam-A): 100 stop/start cycles and 20 module reloads, no anomaly. The original corruption was not reproducible, so this is a regression-safety fix only. T21, T23, T20 and T10 were checked and are not affected device-tested (regression only); open-tx-isp agg-34.1
T41 (experimental, cam-F) MSCA channel-1 latch (cfg_update=2, opt-in) is correct up to 768x432; a channel 1 of 960x540 or more started mid-stream can hang the SoC (also on a fresh boot), so the recommendation is a T41 sub-stream of at most 768x432. A module-parameter heap overwrite occurs only across rmmod/insmod (not in 30 stop/start cycles without a reload). Driver controls added and device-tested: FrameDrop, SensorRegister, WDR enable, AF weight. OpenIMP request-layout fixes: FrameDrop is 40 bytes, SensorRegister offsets corrected. WdrOutputMode has no stock handler (stays -1, explained, not a defect) in branch, not yet in an aggregate: open-tx-isp claude/t41-driver-gaps (bf2a6a5c), OpenIMP 0997f0b

New gap counts (functions, per-vendor-function counting, see the matrix): T10 41, T20 39, T21 18, T23 15, T31 8, T41 187. Done share: T10 86.5 %, T20 87.7 %, T21 92.0 %, T23 93.8 %, T31 96.4 %, T41 58.0 %.

Operations findings (no branch):

  • cam-B (T23) rebooted silently once at 05:12 under agg-34. A hard hang is suspected; there is no Helix error before it and the cause is unexplained. Netconsole is impossible on its WiFi adapter (atbm driver), so a kernel-log capture to the SD card is installed to catch the next one.
  • T23 errno 5 (single Helix encode error): central syslog of cam-B "run failed errno=5": 342 (10-01), 32 (10-02), 37 (10-03), 419 (10-04), then 0 from 10-05 to 10-10. Kernel patch 0102 (residual interrupt 0x100) landed in between. A second T23 camera had 0 since boot. Status: 0 errors in 6 days since the 0102 fix, provisionally closed, still observed.
  • The vendor T21 driver oopses when /proc/jz/isp/isp-m0 is read with no ISP session (not fixed in the vendor driver).
  • A vendor-stack reference T21 camera now exists for A/B tests (used for the denoise comparison above).
  • T20/T21 encoder ROI QA flake: timing only. A ROI change applies at the next IDR, so a check taken before that IDR sees the old QP map; no driver issue.
  • T30 and T40 columns added to the matrix (host/build evidence; T40 device test running).
  • AEC device-tested on 2026-10-10 (OpenIMP AECM, mono 16 kHz, EnableAec returns 0): ERLE on a speech segment T10 25 dB, T20 24 dB, T21 20 dB (vendor stack on the same model 16 dB), T23 19 dB, T31 25 dB; T41 not measurable (microphone shows no response to playback). AECM does not cancel pure tones; on T21 a microphone gain above 0 raises the noise floor to -11..-32 dBFS (hardware, open and vendor alike). Matrix row 33 updated.

T40 device run, T41 and audio results (evening 2026-10-10)

Area Result Status
T40 first OpenIMP device run (cam-K) T40XP board, vendor kernel driver tx_isp_t40, vendor libimp 1.3.0; OpenIMP via LD_LIBRARY_PATH; every result is OpenIMP vs vendor. PASS/dev: AddSensor/EnableSensor; FrameSource ch0 3840x2160 + ch1 640x360 with GetFrame (timestamps monotonic, non-zero); H.264 on ch0 + ch1 (10 s, clean strict decode); OSD PIC + COVER (OpenIMP draws COVER on NV12, the vendor library fails with "COVER cannot support this format"); IVS move (20 s); FrameSource_SnapFrame; JPEG on ch1 (software JPEG since 257ba9d); ISP GetSensorAttr, Gamma get, CCM get, ModuleControl get, AeScenceAttr get/set; GetCameraInputMode. The matrix cells for exactly these functions are dev, the rest of T40 stays host device-tested 2026-10-10, code in agg-35
T40 fixes during the run The stream timestamp was 0: now copied from the frame record at 0x28 (a5d9b03). JPEG was a grey placeholder: snapshot channels now encode the captured NV12 with the software baseline encoder (257ba9d) in agg-35
T40 open CBR delivers only about 20 % of the target bit rate (rate control); H.265 not supported by OpenIMP T40 yet; GetBrightness returns -1; the pixel-format enum is reported as 10 (vendor 0); frame size is 16-line aligned (353280 B vs 345600 B); P1_INNER traces always go to stderr; JPEG at 4K not tested (out of memory in the test process, 60 MB RAM). Vendor note: GetAeExpList hung the vendor kernel driver; the magenta cast seen with the application stopped was the IR cut left open, not the library open
T41 audio mute (API level) AI_SetVolMute, AO_SetVolMute, AO_Soft_Mute/UNMute are a software mute as in the vendor library (no ioctl); tested at API level without playback (rc 0, invalid argument -1). The T41 test board has no microphone and no speaker, so all T41 audio results are API-level only (matrix: host; AO and AEC rows —) in agg-35
T41 driver controls FrameDrop, SensorRegister, ISP_WDR_ENABLE/_GET and AfWeight device-tested (claude/t41-driver-gaps, in agg-35). Get/SetWdrOutputMode: the driver has no stock handler (explained, vendor no-op). AutoZoom, SetMaskBlock, SetScalerLv deferred (live MSCA reprogramming carries a hang risk) in agg-35 / deferred
Audio T10/T20/T21/T23/T31 AEC device test: IMP_AO enable/SendFrame and SetVol played a known signal at several volumes that was recorded back; IMP_AI enable/GetFrame, SetVol/SetGain, mono 16 kHz recorded it; EnableAec returns 0. AO/AI rows and function cells are now dev for these SoCs. T21: a microphone gain above 0 drives the noise floor up (hardware, open and vendor stack alike) device-tested 2026-10-10
Build agg-35 (openimp 687a68e4, open-tx-isp 6e464ac7) built 2026-10-10; soak 2026-10-10 18:04 to 2026-10-11 08:00 clean (10 cameras) built

2026-10-07 to 2026-10-10: agg-32 soak and release candidate agg-34

Camera letters in this section follow the soak table below (they differ from the table at the top of this file); where it matters the SoC is named instead. No picture of any camera is part of this log.

State of the candidate

Repository Branch Commit Contents
OpenIMP agg-34 838f8147 agg-32 (8980cae) + T31 ROI clamp (fec3e69, 8545fb9) + reviewed DeepSeek patches (11abe42 and 17 patches)
open-tx-isp agg-34 da9baf1e agg-32 (3cf9bdac) + front-crop fixes T31/T23/T20/T10 (d940ba20 to 10bac52f, 164225e5) + T20 isp-m0 gain cap (da9baf1e)

make check is green on all SoCs and the cross-builds pass. After the review fixes (S1 T31 front crop survives the ISP session, S2 T31 zoom only with a scaled main stream, S3 Helix absolute ROI no longer worse than the slice QP) agg-34 is OpenIMP 2a1b1cd and open-tx-isp b15ef235; test images with these run on all 10 test cameras since the night of 2026-10-09/10. The individual fixes were device-tested as listed below; the mandatory device tests of that night are summarised under "Device results of the night 2026-10-09/10".

agg-32 soak (2026-10-07 16:07 to 2026-10-09 11:31, 43.4 h)

The soak was planned until 19:00 and stopped early by the user. Stack: OpenIMP 8980cae, open-tx-isp 3cf9bdac. Ten cameras: T21 x2 (one is the 720p case), T23 x2, T31, T20 x2, T10, a further Ingenic camera and a T41 (experimental, rootfs only).

Monitoring: a read-only poll every 5 min (uptime, application pid, wide oops grep, MemFree, guard state, snapshots of both channels), CPU/memory every 60 s, a numeric picture check every 15 min (decode, luma, flat blocks, colour cast, frozen frame), application memory every 2 h on three cameras. Load: one MJPEG sub-channel consumer per application camera, 30 min on / 2 min off.

Result Value
Unplanned kernel reboots, oopses, guard trips, snapshot failures, unreachable periods on the seven application cameras without interaction 0 on all, each ran about 44 h on one application PID
T10 1 planned OTA (reboot), 38 unreachable polls during the OTA
T31 2 reboots from the front-crop crash (below) plus 2 planned reflashes; out of scoring from 2026-10-09 08:45
T20 (one camera) one application restart: the user saved a config while trying crop on several cameras; not a crash
Application memory no steady growth: +148 kB in 34 h on the first camera (flat in the last 12 h), 0 on the second, +1.9 MB step on the third coinciding with the user's crop attempts, flat afterwards; threads and fds constant
CPU per stream (each alone) RTSP, MP4 and MJPEG on the sub-channel about +5 to 10 % each; MJPEG on the main channel is the expensive stream: 14 to 33 % total, up to 30 % of capacity on the T41 and 25 % on a T20, scaling with the JPEG size (a 1080p daylight frame is up to about 770 kB, about 31 Mbit/s at 5 fps)
Picture check (310 rounds per camera) no frozen frame and no decode error anywhere; see the findings below

Findings of the picture check:

  • T20 day/night regression (release relevant): both T20 cameras stayed in Day mode in the dark (integration pinned at 1967 of 2246 lines, no day/night log line after start), black pictures at night; under agg-30 the switch worked. Cause (analysis): the driver reports an analog gain cap of 158 in isp-m0, the AE stops at 128, so the application's "cap reached" rule never fires. Fixed in the driver in agg-34 (da9baf1e, below).
  • T10: 6 bad rounds, the camera sometimes switches to Day in the dark and delivers a black frame (3 events in 44 h, once flapping). Open.
  • T41 (experimental): 13 bad rounds, channel 1 only: green or flat frames at every day/night switch, colour cast for about 1 h in night mode, channel 1 brightness does not follow channel 0 (luma 63 vs 110 to 130); channel 0 always fine. Open, not part of the release.
  • 720p main stream shows only the top-left corner (seen on a T21 and a T20): /proc/jz/sensor/sensor0/width|height|fps are filled only while the application has the sensor started; an application that reads them earlier falls back to the video0 size. The T20/T10 driver also kept the crop window across application restarts (fixed in agg-34).

Front crop (open-tx-isp, device-tested 2026-10-09)

SoC Problem Fix Commit
T31 Enabling image.fcrop live (320x180, later 732x412) stalled the stream and rebooted the camera twice without an oops; the persisted crop hung the next boot after about 3 min and tripped the isp-guard. Cause: the MSCA cannot upscale; a front-crop window smaller than any channel output stalls every MSCA output until reboot (same class as the T23 hang) The kernel refuses such a window with -EINVAL and one log line ; the set-time check covers only running channels (a stale 2560x1440 register no longer vetoes a crop re-applied at start); a scaler output larger than an active window is refused; scaler steps and latch are written so a valid window zooms; the crop survives idle off/on; module parameter fcrop_upscale_pct (default 0) to measure the upscale limit. Beyond stock d940ba20, f8ae7457, b9be16fb, 27dc8be4
T23 Crop off kept the picture cropped (stock only clears the enable bit; the window stays locked until module reload); returning to a 1080p main stream then hung the MSCA and the watchdog rebooted the camera. An application restart without crop kept the old window Crop off unlocks every channel record, restores the full sensor window and reloads the running channels; a set-format that does not fit a locked window drops the crop (warning) and is checked again; the lock is released at the last close of the ISP device; fcrop_upscale_pct (default 0). Beyond stock 25b1d8c7, 164225e5
T20, T10 A window was refused while no downscaled channel was open (an application closes an idle sub-stream), and a window survived application restarts so the picture stayed zoomed while the UI showed crop off The window is stored while no downscaled channel is open and applied at stream on; it is released with the tuning session 10bac52f, b9381941

Device results: T23 passed an 18-case matrix (crop off with a 1080p main stream, flip, day/night, fast changes with many application restarts, corner windows, sub-stream, reboot with a persisted crop); it upscales up to 2.0, at 2.2 the MSCA stalled briefly and the crop was dropped without a reboot. T31 passed an 18-case matrix and a 30 min run with a 960x540 crop; the refusal works. On T31 a crop window can only work when every stream is smaller than or equal to the window, or is scaled down.

Device results of the night 2026-10-09/10 (agg-34 mandatory tests, OpenIMP 2a1b1cd, open-tx-isp b15ef235)

  • T31 front crop: a valid window zooms both streams (proven). Too-small windows are rejected without a hang; the window survives a restart and a flip.
  • T31 ROI: 20 phases, valid in VA-API and in strict ffmpeg (-err_detect). Known deviation: under FixQP 42 an absolute 5 or relative -25 window drives the P-frames to QP about 14 almost frame-wide (bit rate about x4, stream valid).
  • T20/T10 front crop: a window set before stream-on is applied and survives substream restarts. The release of the window at tuning-session close is not verified.
  • T20/T10 ROI: absolute ROI is valid, no inversion (the S3 fix).
  • T20 gain cap: isp-m0 reports a maximum analog gain of 128 (device-tested). T10 (jxh42) still reports 144 at boot (128 when set explicitly): open finding. T20 day/night with the driver fix is not yet confirmed.
  • Feature matrix: the function-gap tables were re-audited against agg-34 (only IMP_Log_Set_Option became real since agg-27, host-tested; ISP_Tuning_Get/SetFrontCrop on T31 is now dev); the per-SoC counts were recomputed (T41 column untouched).

Encoder ROI (OpenIMP, device-tested)

Area Was Now Commit
T10/T20/T21 T20: ROI and chroma QP offset only in the release candidate; T21 stored ROI like the vendor and applied nothing SetChnROI and the H.264 chroma QP offset act on the Helix/NVPU (T21 by default, beyond vendor, OPENIMP_T21_ROI=0 switches off); device-tested on all three 8ba6fdd, 0a9389d
T31 No ROI in the vendor library IMP_Encoder_Set/GetChnRoiAttr through the AVPU macroblock QP table (beyond vendor, H.264 only, OPENIMP_T31_ROI=0 refuses the call); end to end with the application: relative -10 gave 2.7x the bit rate d03ca24
T41 None Experimental table path, off unless OPENIMP_T41_ROI=1, code only f2fd9a5
All ROI paths A relative QP of -26 (and an absolute QP far from the macroblock QP) gave mb_qp_delta outside -26..+25: invalid H.264 that software decoders hide and hardware decoders (Intel VA-API, VLC, Firefox, Edge) show broken from the ROI row on Window deltas -25..+25, spread of all deltas at most 25, picture QP plus delta in 0..51 and in the rate control's min/max QP, requests clamped with a one-time warning; under FixQP the T31 table is not clamped to the rate control's min/max QP (8545fb9). T31 measured: relative -20 became -19, absolute 51 +21.7, 0 decoder errors in 20 VA-API checks fec3e69, 8545fb9
T23 n/a Regions go to the vendor encoder; no visible effect was measured (no-op) none

DeepSeek patches (reviewed, in agg-34)

An automated reviewer produced patches from a comparison against the vendor libraries; each one was reviewed against the disassembly. 17 are in agg-34 unchanged, one was corrected (11abe42: the encoder group bound is 6 on T20/T21/T30/T31/T41 but stays 8 on T23 and T40, where the vendor libraries use larger bounds) and one T30 build fix was added. Contents: vendor ABI layouts (T40/T41 IMPEncoderStream 28 bytes, T40 IMPEncoderChnAttr 4 bytes, T40/T41 IMPFSChnAttr and IMPFrameInfo, T40/T41 IMPSensorInfo, T41 IMPOSDRgnAttr caller size, pixel-format enum), encoder group and channel counts, IMP_OSD_SetPoolSize(0) rejected, T31 IVS channel 64 accepted, idempotent T31 IVS group create/destroy, PollingStream created/registered guards, SetDefaultParam profile/rate-control guards, GOP control mode values, GetDefaultBinPath. Host-tested and cross-built only. Device checks still to do: OSD groups, IVS, PollingStream returning -1 without a channel (watch the application CPU at restart), T31 SnapFrame offsets, T41 OSD size.

T20 gain cap (open-tx-isp da9baf1e)

The compact AE clamps analog gain to max_again and to the stabilizer ceiling (128), but isp-m0 printed only the sensor maximum (158 on the tested sensors). isp-m0 now reports the smaller value, shared with T10. Host-tested (tests/t20_ae_max_host_test.c); device-tested on T20 on 2026-10-10 (128). T10 (jxh42) still reports 144 at boot (open).

Camera state after the crop work (2026-10-09 evening)

T23 and T31 were reflashed with the agg-32 recipe plus the crop fix of their SoC; one T20 and the T10 run agg-32 plus an overlay tx-isp-*.ko module with the crop fix (rollback: delete the overlay module and reboot); the others run unchanged agg-32. The soak state of these cameras is therefore changed from 2026-10-09 afternoon.

Open items for the release

  1. T20 day/night: driver fix da9baf1e, operational Day to Night test pending.
  2. Retest the merged crop fixes (T31, T23, T20, T10) on the release image.
  3. T41 channel 1 colour/exposure and the T10 black frame in the dark (not release blockers for T20/T21/T23/T31).
  4. T10 isp-m0 maximum analog gain 144 at boot (128 when set explicitly); release of the T20/T10 crop window at tuning-session close not verified.
  5. The long soak of the release (the combined agg-34 passed the mandatory device tests of 2026-10-10).

Vendor-API gaps T23/T31 (2026-10-10, branch claude/gaps-t23-t31)

Gap work 2026-10-10 (branch claude/gaps-t1x, T10/T20/T21, vendor export check only, host-only, no device session): the 4 vendor libimp builds per SoC (T10 3.9.0/3.12.0, T20 3.9.0/3.12.0, T21 1.0.33) and their libsysutils were checked with nm. Exported by none, so now n.a.: ISP_Tuning_SaveAllParam (T10/T20/T21), ADEC_ReleaseDecoder/AENC_ReleaseEncoder (T10/T20), SU_Battery_* (T10/T20/T21). Gaps in functions: T10 28 to 21, T20 27 to 20, T21 14 to 9. Everything else stays open; the vendor libimp does export ChangeRef, FrmUsedMode, GOPSize, HSkipBlackEnhance, OSD_AttachToGroup, Decoder_* (T21), and the T10/T20 H264 variants, WDRAttr, ISPHVflip, MeshShadingScale, AntiFogAttr, DPStrength (T10/T20), so these are classes b/c and not yet worked (low priority: no application uses them).

  • Gap functions checked against every vendor libimp/libsysutils build (nm plus disassembly): OSD_GetRegionLuma (T23), SU_Battery_*, DPStrength, Decoder_*, EmuFrameSource_*, ADEC_ReleaseDecoder, AENC_ReleaseEncoder are declared in headers but not exported by any build, so they are n.a.
  • T23 Encoder_Get/SetH265TransCfg now behaves like the vendor (value dropped, Get zero-fills); T31 Encoder_SetFrameRelease is a vendor no-op in effect.
  • T31 ISP_SetFixedContraster now takes the attr pointer and sends control 0x8000102 like the vendor (host test tests/t31/fixed_contrast_test.c; apitest PASS on T31 and T23).
  • Gap counts (functions): T23 22 to 15, T31 29 to 8. The rest needs driver handlers (T23 ISP controls) or closed-encoder features.

Vendor-API gaps T10/T20/T21 (2026-10-10, branch claude/gaps-t1x-impl)

Return codes and stores read from the vendor disassembly (T21 1.0.33, T10/T20 3.12.0; the 3.12.0 libimp of T10 and T20 is the same binary), implemented with host tests (tests/t30/p2_gap_test.c, isp_gap_test.c, osd_attach_test.c) and run with the apitest on a T10, a T20 and a T21 camera (agg-34 plus these changes, libimp from /tmp, application stopped and restarted, config md5 unchanged, 0 oopses): T20 148 PASS / 0 FAIL / 2 N/A / 2 SKIP, T21 155 / 0 / 2 / 2, T10 147 / 1 / 2 / 2 (the one FAIL is the known SetSuperFrameCfg read-back on T10).

  • Done: Encoder_Get/SetChnFrmUsedMode, Encoder_GetGOPSize (T10/T20/T21), ISP_Tuning_SetDPStrength (T10/T20, T21 device-tested), ISP_Tuning_Get/SetISPHVflip and Get/SetWDRAttr (T10/T20), OSD_AttachToGroup (T10/T20/T21, host).
  • Stored with the vendor return codes, effect only in the closed vendor encoder: Encoder_Get/SetChangeRef, SetChnHSkipBlackEnhance, Get/SetFisheyeEnableStatus (a creation-time flag: -1 once the channel exists), T10/T20 Get/SetChnDemask and Get/SetChnHSkip.
  • Not done: Decoder_* and the 3.9.0-only ChnH264*/ChnRcAttr (class d), T10/T20 SetAntiFogAttr (the open driver's antifog preset path hung cameras) and SetMeshShadingScale (no driver control) are wishlist items for the driver.
  • Gap counts (rows): T10 21 to 15, T20 20 to 14, T21 8 to 5. Branch also carries 4443657 and ce9ec77 from agg-34 (T21 DPStrength/AntiFogAttr export, T20 CHNAttr with attrDemask), which next does not have yet.

2026-10-06 afternoon/evening: release candidate agg-27/agg-28

The first release was gated on the apitest/imgfx FAILs of the day ("first release only when these problems are fixed"). Every FAIL was either fixed in libimp or the driver, proven to be a tool error (and the tool fixed), or marked as a vendor no-op. This section is the summary of that work and of its device results. Details per change are in the CHANGELOG of each repository.

State of the candidate: OpenIMP claude/agg-27 (affb8ff) and open-tx-isp claude/agg-28 (79b754b4), both on top of next. Release plan: next goes to aperto (fast-forward only) after the long soak and is tagged vYYYY.MM.DD. The first release covers T20, T21, T23 and T31. T10 is part of the first release but was not re-tested on the open stack today (its userspace is the T20 build and its cells mirror T20). T41 is not part of it (see below).

Device results (apitest, one call per vendor function)

Method: the application is stopped, the release libimp is loaded through LD_LIBRARY_PATH and the release-candidate kernel module from RAM (the flashed files stay untouched); afterwards the application is started again and the kernel log is checked for oopses (0 on every camera). N/A = the node or the API does not exist on the board or in the vendor library; SKIP = deliberately not exercised (register writes, reboot, cipher).

SoC (cameras) Run PASS FAIL N/A SKIP Remaining FAILs
T20 (two cameras) first RC run 233 3 16 30 FrameSource GetFrame (luma 0), SetChnROI read-back, GetAeZone
T20 (two cameras) after the fixes 212 0 17 30 none (GetAeZone is N/A: the stock T10/T20 module does not serve the control)
T21 (two cameras) after the fixes 228 0 17 30 none
T23 (one camera) RC run 304 4 12 34 the four AF getters (AF statistics were off by default in that run); with source_af=1 (new default in agg-28) they pass on a second T23 camera
T31 (one camera) after the fixes 274 1 8 34 "H.264 stream after JPEG channel teardown" (see known issues)

Before the fixes the same test gave 37 FAIL on T20 and 33 FAIL on T21 (almost all of them the frame source, see below) and 54 FAIL on a T23 camera that still ran an older driver. T41 is tracked separately (255 PASS / 12 FAIL on the experimental branch).

imgfx (one picture per image function, compared with the base picture of its own batch): the release-candidate run was taken in the dark (night mode), so its colour verdicts are not used and the colour functions of all SoCs are to be repeated in daylight. What was checked with light: T21 brightness (below), T21 sepia/B-W/negative/vivid, and a T31 defog A/B. A green/magenta stripe in the top rows of the saved ch1 pictures was a tool error (the chroma plane was read at width*height instead of after ALIGN16(height) lines); JPEG snapshots and streams were never affected.

OpenIMP (agg-27)

Area Was Now Branch
FrameSource T20 Apps that set a frame depth (imgfx, apitest) got nrVBs frames and then nothing: the driver cycles through as many DMA banks as REQBUFS asks for, OpenIMP asked for nrVBs + depth but queued only nrVBs REQBUFS = pool size (+ max delay), SET_BANKS as the vendor library when a delay FIFO exists; SetFrameDepth(chn, 0) succeeds claude/t20-fs-frames
FrameSource T20/T21/T23/T31 GetFrame/SnapFrame returned at once when the ready queue was empty Wait up to 2 s like the vendor library (T31 1.1.6 header: default timeout 2 s); the encoder keeps its own deadline claude/t20-fs-frames, claude/release-fs-enc-ivs, claude/release-quickwins
FrameSource T20 After a reader stopped with every buffer parked, the capture thread slept in DQBUF for good (an IVS group bound to FS ch1 got no result) Without a buffer in the driver the thread recycles idle frames first claude/release-fs-enc-ivs
Encoder GetFd ENOSYS stub Pollable pipe plus pump thread (a difference, not an addition, see OPENIMP_BEYOND_VENDOR.md) claude/release-fs-enc-ivs
JPEG channel Received frames only while the application also polled the video channel of its group Feeds itself from the frame source when the video channel is not polled for 300 ms (beyond vendor, see OPENIMP_BEYOND_VENDOR.md) claude/release-fs-enc-ivs
IVS One group Two groups as every vendor libimp (CreateGroup checks group < 2); group 1 device-tested on T20 and T21 claude/release-fs-enc-ivs
Encoder T20/T21/T23 InsertUserData not implemented Emits a user_data_unregistered SEI (OEM UUID) in front of the next picture (found in the next 30 frames, apitest) claude/release-su-adec-enc
Encoder PollingModuleStream reported any ready channel Honours the input channel bitmap and polls all selected channels in slices claude/release-su-adec-enc
Encoder T31 SetMaxStreamCnt accepted on a created JPEG channel Refused on a created channel like the stock library claude/release-t23-getters
ISP T31 GetAwbZone wrote 675 bytes through a pointer to a stack struct of three pointers (bus error in apitest); GetAWBCt always returned -1 The caller's buffer is passed like stock; the colour temperature is stored through the pointer claude/release-t23-getters
ISP T23 GetSensorRegister read the bus type at the wrong offset ("There isn't sensor!"); FrameSource_GetPool stub; audio frame stamps could step back by ~10 ms Stock offset; GetPool returns the SetPool id; stamps never go backwards claude/release-t23-getters
Frame source T23 Pool rmem freed at DisableChn although the open driver keeps a stopped MSCA output enabled while the input runs Pool parked for the channel's next pool as on T21 (OPENIMP_VBM_PARK=0 frees at once); 40 application restarts, every snapshot OK, 0 oopses claude/release-t23-vbm
ISP T21 SetDPStrength/SetAntiFogAttr not exported (an application built against the T21 SDK did not load) Exported like the vendor: DP strength (cap 200 %) reaches the DPC ratio, antifog goes to control 0x8000163 (accepted by the OEM kernel without effect) claude/release-t21-image
ISP T31 EnableDefog always wrote 1 Takes the enable flag like stock (patch verified against the vendor disassembly) claude/release-deepseek-defog
Core / ISP IMP_Log_Set_Option not exported; DisableSensor passed the sensor index to DESTROY_LINKS Option = OEM field mask (default output unchanged); DisableSensor passes -1 like stock (patches from an automated review, each verified against the vendor disassembly) claude/release-deepseek
Encoder T10/T20/T21 ROI and H.264 chroma QP offset refused Vendor ROI table and chroma offset on the Helix/NVPU (EFE ROI registers, PPS rewrite); T20 device-tested; documented in docs/T1X_ROI_CHROMA.md; debug hooks OPENIMP_DEBUG_ROI / OPENIMP_DEBUG_CHROMA_QP claude/t1x-roi
Encoder T21 SetChnDenoise/QpgMode/H265TransCfg refused Stored and read back like the vendor library where the vendor does nothing (QpgMode kept without range check, H265TransCfg checked and dropped); ROI, QPG and SuperFrame discard are not applied yet (after the release) claude/release-su-adec-enc, claude/application-gaps-t1x-t23-t31
Audio / T31 IMP_AI_SetHpfCoFrequency cache-only; T31 Enable/DisableMovestate stubs; SetbufshareChn HPF designed like the vendor and handed to libaudioProcess-neo as a float biquad (T23/T31, T41 untested); Movestate runs the vendor logic (AE block of control 0x800002c, move.txt limits, IDR on disable); SetbufshareChn documented as store-only like the vendor. Host-tested only claude/application-gaps-t1x-t23-t31
Quick wins T21 SetModuleControl failed when the open driver rejected control 0x80000e2; IMP_AI_SetHpfCoFrequency(0) refused on T40/T41; a P3 capture start could free a buffer its previous thread still used; T21 OSD INFO lines were always logged Cache fallback; 0 = default accepted; start refused while the previous capture thread has not exited; OSD INFO lines trace-only claude/release-quickwins

open-tx-isp (agg-28)

Area Was Now Branch
T23 defaults Fix set against the channel-restart hang that itself hung the SoC on the first fresh application start The stock-like set that ran 7 h overnight is the default: chan_stop_keep_input=1, msca_keep_enabled=2, msca_fifo_rearm=0, msca_flip_skip_noop=1, msca_restart_skip=1, msca_session_release=1, crumbs=0 (the hang needed chan_stop_keep_input=0 together with msca_fifo_rearm=1). Cold-start snapshot 503 is now prevented as stock does it: STREAMOFF waits up to 21 x 10 ms until the channel's buffers have left the hardware, QBUF invalidates the buffer's cache lines claude/release-t23-driver
T23 MSCA scratch buffer A stopped channel with a kept output wrote every further frame into the stream's last (freed) buffer STREAMOFF parks the output on a scratch area at the tail of the ISP buffer; QBUFs of a parked channel are held back until STREAMON; the input waits until the scratch address was consumed (a first build without the wait hung 3 of ~35 cold starts) (beyond stock) claude/release-t23-af-scratch
T23 AF Off by default (source_af=0) On by default as in the stock module; no measurable cost; four AF getters PASS claude/release-t23-af-scratch
T23 clocks isp_clk/isp_clka were read from the wrong clock-table slot and never reached the hardware Fixed (set like stock) claude/fable-chan-restart (in agg-28)
T23 ISP getters The stock handlers of 19 ISP getters were not routed in the older driver (apitest FAIL with agg-24) Stock handlers routed (AE tuning controls, AWB zone/colour temperature/zone weight/RGB coefficients, gamma, WaitFrame, FixedContraster, autozoom, AWB cluster/trend, mask block); emulator-identical where noted claude/application-gaps-t1x-t23-t31, earlier branches
T21 SetColorfxMode(SEPIA) returned -1 Sepia works (B/W plus a tinted CSC matrix), beyond vendor claude/release-t21-image
T21 SetBrightness stored only (vendor kernel) Scales the AE luma target by value/128, 128 = vendor path (beyond vendor) claude/release-t21-brightness
T31 SetFrameDrop registers swapped, DQBUF dropped a second time in software Stock lsize/fmark semantics: the ISP drops the frames (29.6 fps to 14.8 / 7.4, disabled restores, lsize 32 refused) claude/release-t31-framedrop

The T23 start/stop hang work of the previous days is summarised in the earlier sections; the stock start/stop sequence audit (driver/t23/docs) stays in the branch.

Not in the release: T41 (experimental)

  • OpenIMP claude/release-t41 (8be09a4): software AI/AO mute as the vendor (the audio driver has no working mute ioctl), FrameSource_SetChnAttr on an existing channel, I2D attribute, delay getters (0, no delay FIFO). apitest FAILs on T41: 44 to 24 in the first run, 255 PASS / 12 FAIL in the last.
  • open-tx-isp claude/t41-ch1-fix: the MSCA output geometry, scaler ratios, global input size and the flip/algorithm word are staged registers (a write applies at the next input frame after the latch word is set, a read returns the active value). Without the latch every output ran with its reset geometry (ch1 at 640x360 wrote 1280x720 into 640x360 buffers: garbage chroma, a band at the top of the next buffer). With the latch (t41_msca_cfg_update=1) channel 1 at 640x360..1440x810 is correct and 20 application restarts are OK, but with correct geometry the output-restart hang returns after 4 to 13 cycles (30/30 without it), so the latch stays off by default until the restart hang is solved.
  • Still missing on T41: 38 tuning IDs (gamma, CCM, CSC, module control, autozoom, manual exposure, DRC, DPC, defog ratio, mask, scaler level), flip not reset on restore, no frame-source delay FIFO, GetSensorRegister/AfWeight/FrameDrop/WdrOutputMode in the driver.

Known issues (release candidate)

  • T23 crop hang: the pipeline stops after a FrameSource crop change (hard hang); under investigation, release blocker.
  • T31 H.264 stalls after the JPEG channel is torn down: fixed: two threads polled the same encoder channel at once (AL_Codec_Encode_Process concurrently); IMP_Encoder_PollingStream now serialises per channel (openimp claude/release-fix27 5c2ccef), apitest on T31 FAIL 0 with the fix; goes into the next candidate (agg-29). The same encoder file is used on T41, whose flaky result probably has the same cause (not re-tested).
  • T41 is not part of the first release (channel 1 scaling registers staged, output-restart hang, 38 tuning IDs missing, see above).
  • T21: the IPU needs about 2 s after a wake before the OSD blend takes effect (first snapshot withheld until the overlay is confirmed, beyond vendor); the cause is not found. Whether the OSD shows in the live stream after a wake is checked after the candidate tests.
  • T23: no real WDR; the sporadic Helix encode error (errno 5) is provisionally closed since 2026-10-10 (see there).
  • Colour image functions (imgfx) have to be repeated in daylight; T10 has not been tested on the open stack today.
  • ivs_framework_test is flaky under make -j4 (test harness).

Next steps

  1. Fix the T23 crop hang (blocks the release); the T31 H.264 stall is fixed (agg-29).
  2. Long soak of the candidate (6 h overnight, longer before the tag); on any hang set msca_scratch=0 for the first release and re-test.
  3. Merge the candidate into next, fast-forward aperto, tag vYYYY.MM.DD; documentation and the matrix follow the final state.
  4. After the release: T21 ROI (0.5 to 1 day), SuperFrame DISCARD in software (< 1 day), T21 REENCODE (2 to 4 days), T21 QPG (1 to 3 days), brightness through the AE target on T20/T10.

Evening (2026-10-05, 22:50)

Device-tested this evening (results on the cameras, pictures kept private):

Area Result Branch
T21 OSD on the first snapshot The first snapshot after a (re)start or idle wake had no OSD: the IPU blend has no effect for about 2 s after a wake. OpenIMP now verifies the blend on a glyph pixel and withholds JPEG frames without a confirmed overlay; the first snapshot now carries the OSD (about 2 s later). The vendor stack (Ingenic driver + libimp, tested side by side) shows the same missing first-snapshot OSD, so this is beyond vendor. Root cause of the 2 s IPU delay still open. claude/t21-osd-first-jpeg (in claude/agg-26)
T31 stack overwrites GetAfHist wrote 88 bytes into the 24-byte vendor struct (vendor kernel bug, now 24 bytes at the boundary); Get/SetAeAttr overran the caller by 80 bytes. Verified with guard arenas on cam-A: every AF/AE get writes exactly the vendor size, get/set round trips return 0. claude/t31-af, claude/connect-round3 (in agg-25)
T31 autofocus statistics AF chain rebuilt (focus value, 15x15 zones, weights, histogram); metric reacts to the scene, invalid weights rejected, settings survive day/night. claude/t31-af
T23 gamma SetGamma takes effect at once (steep/linear curves visible, falling curve rejected, restore ok) on cam-B. claude/t23-t31-connect
T20 ROI + chroma QP offset Vendor EFE ROI registers rebuilt: in the H.264 stream a QP-51 region is visibly coarse, a QP-15 region fine; chroma QP offset 12 without colour shift. Note: an absolute ROI QP bypasses CBR (bitrate rose 1.4 → 9.9 Mbit/s), vendor semantics to be checked. claude/t1x-roi
Front crop / CSC on T10/T20/T21 Front crop (mid, top-left), invalid-value rejection and 10 on/off cycles pass on all three; CSC modes neutral in night mode. CSC mode 4 was green on T10/T20 (sign handling) – fixed, daylight check pending. claude/t1x-crop-csc (in agg-25)
T21 rotation with OSD Rotation 0/90/270 with correct colours and OSD, also across day → night → day. claude/t1x-rotation (in agg-25)
T21 colours vs vendor Two T21 cameras side by side under lamp light: open driver and Ingenic driver give nearly the same picture (AWB gains R 0x534/0x530, B 0x9d8/0x984); Bayer phase confirmed (RGGB). Open: magenta with the ISP tuning flip call and with re-setting AWB auto (image-function test), daylight comparison pending. –
T41 channel-restart hang Restarting one channel while the other streams hung the SoC. Proven: hangs follow a live MSCA reprogram / no-op flip update request. Fix (flip update only on a real change, output kept like vendor on stream-off, address-only QBUF): targeted repro 35/35, start matrix 38/38, 40 min soak with diagnostics, client-mix load test running. claude/t41-chan-restart-hang (in agg-26)
T23 cam-B silent reboots Cause found: right after an application start the day/night logic switches and re-asserts the mode several times; each set restarts channel 0, and the T23 driver hard-hangs on such a restart with live input (DMA into freed buffers after a process restart was also seen). Driver fix in progress (not yet proven on the device); an option to keep the frame source enabled is planned. claude/t23-chan-restart-hang (in progress)
Image-function test tool imgfx: one picture per image-changing IMP function per SoC with an automatic "set returned 0 but nothing changed" check; first run on T21. claude/imgfx-tool
Boot guard follow-up One ls per client check instead of a readlink per fd, comment fixes (upstream review). thingino PR #1776
Feature matrix New section "Missing / incomplete functions" per SoC and area. next

Afternoon (2026-10-05, 14:55)

  • T41 audio non-blocking read fixed (branch claude/t41-ai-noblock, device test pending): IMP_AI_GetFrame with NOBLOCK now returns at once when no frame is ready: a capture thread fills a 16-frame FIFO (as already done on T31/T23), BLOCK callers keep the direct path, the frame timestamp is the capture time. Expected effect: the first frame of an RTSP session on T41 after well under a second instead of ~19 s.

Afternoon (2026-10-05, 14:50)

  • T41 hard hang reproduced: the camera freezes completely (both CPUs stop, the hardware watchdog resets it after ~60 s; no kernel panic) when one channel was stopped by the application's idle stop while the other channel kept streaming, and the stopped channel is started again — 3 of 3 times with a targeted sequence, while 38 cold starts without that overlap were clean. Suspected: per-channel MSCA state left behind on a single-channel stop and global scaler registers reprogrammed under a lock with interrupts off at the restart. A fix against the vendor code is in progress; this has the highest priority.
  • T41 slow first frame explained: video (SPS and IDR) arrives 0.07–0.27 s after PLAY, but clients wait ~19 s for audio: the application drains up to 512 audio frames with non-blocking reads while OpenIMP's T41 IMP_AI_GetFrame ignored the non-blocking flag (512 × ~38 ms). A fix is in progress.
  • T10/T20/T21 crop and CSC (code ready, beyond vendor): the vendor libimp has no front-crop or CSC API on these SoCs (headers of T20 3.9.0 and T21 1.0.33); OpenIMP now offers them with the T31 control IDs: CSC presets 0–4 (T21 CSC block; T10/T20 via the RGB-to-YUV calibration table), kept across day/night; front crop full-frame only so far, a crop/zoom (ePTZ) via crop + downscaling on T21 and on the T20/T10 sub channels is being implemented and tested.
  • Unconnected functions audit: every vendor IMP/SU function per SoC is being classified (real, cache-only, stub, missing, error, driver gap) and checked against what the applications call; these gaps come first after the current feature work.
  • Soak policy: no daytime soaks while the driver is being finished; a 6 h soak runs overnight.

Afternoon (2026-10-05, 14:35)

  • Aggregate agg-24 on the cameras: OpenIMP claude/agg-24 and open-tx-isp claude/agg-24 (T20/T10 optimised and vendor-matched firmware incl. the white-balance fix, T21 stability with rollback and AF getters, VBM parking and Helix back-off, quieter T20/T10 logs, new test runner; 58/58 host tests, vendor comparison 0 differences) were flashed on cam-A…cam-E, cam-I and cam-J: 30/30 snapshots, both streams, 0 oops each. The T20/T10 ISP module in RAM is now 325/323 KB instead of 477/475 KB. Short soaks (about 3 h) are used while features are still landing; a long soak comes before the release tag.
  • Boot guard fix submitted (aperto PR #1773): the false trips came from the OTA script stopping the guard only after the root file system was already read-only, from guard state kept in /overlay across images, and from the stable check that only knew one process name. Now a boot is stable after 300 s when any process holds the ISP device nodes (900 s without any ISP client), the guard is stopped before flashing, and the first boot of a different image resets its state; a real crash loop still trips. Host harness 27/27; device test pending.
  • soc_vpu log fix submitted (aperto PR #1774): an encode wait aborted by a dying application is no longer logged as "wait timeout / start vpu failed"; real timeouts still are. Kernel builds for T21, T20 and T31; not yet run on a device.
  • T41: a spontaneous reboot occurred during a long sequence of RTSP client starts (second unexplained reboot of cam-F today); an investigation with a continuous kernel log runs. Code ready for device tests: sensor flip with correct register sequence (the gc5603 SDK driver OR-ed old and new flip bits) and automatic re-apply after a sensor restart (beyond vendor), a frame-source race fix for motion detection, ioctl polish (EFAULT for bad pointers, ioctl trace lines off by default, /dev/aisp hardened). Temper (3D noise reduction) is confirmed to work at high gain (frame-to-frame noise 4–6× lower than with temper off).
  • T10/T20/T21 rotation (code ready): sub-stream rotation 90/270 via the T31 frame-source path (up to 704×576, sizes multiple of 16; estimated 5–7 % CPU at 640×368/15 fps); the main stream is refused with a clear log line.
  • White-balance gain ranges per SoC (for applications): T10/T20/T30 8 bit (128 = 1.0, max 255), T21/T23/T31 Q8 with a saturating 14-bit register (max 4095), T40/T41 Q10 (max 16383).

Afternoon (2026-10-05, 13:20)

  • T41 on the aggregate state: 10 module reloads, double open, rmmod while open fails cleanly, ioctl fuzzing during a live stream (more than 50,000 unknown, oversized, NULL and short-buffer calls return only ENOTTY/EFAULT/EINVAL, one warning per device node, no oops), 1 h soak without findings. The T41 top-5 indirect-call fixes could only be exercised superficially on this camera and one unexplained reboot occurred during the first run with that module (not reproducible in three repeats); they stay out of the next aggregate until a run with a serial console.
  • Next aggregate in preparation: OpenIMP and open-tx-isp claude/agg-24 combine the aggregate with today's device-tested branches (T20/T10 optimised and vendor-matched firmware incl. the white-balance fix, T21 stability with rollback and AF getters, VBM parking and Helix back-off, quieter T20/T10 logs, new test runner). A soak of the current aggregate runs on five cameras as the release candidate.

Early afternoon (2026-10-05, 12:50)

  • Soak ended after 17 h (on request): 6 cameras × 69 samples, 0 encoder/VPU errors, 0 oops, all snapshots 200, no reboots. The next aggregate (OpenIMP claude/agg-23, open-tx-isp claude/agg-23) was then flashed on cam-A…cam-G (cam-F rootfs only): 30/30 snapshots, both streams, 0 oops each. A new soak of this state runs on five cameras; it is the candidate for the first release tag.
  • Boot guard vs. full OTA: after the OTA reboot the boot guard on cam-B treated the previous boot as a crash (pending mark left behind) and skipped the ISP stack. Fixed on the camera with S10isp-guard clear + load; cause (OTA reboot inside the 300 s window) to be fixed in the guard/OTA script. After every flash the guard state is now checked.
  • T20/T10 optimised firmware device-tested: -Os firmware unit behaves like -O0 on cam-I (T20) and cam-E (T10): same AE/AWB, exposure, colour, sharpness; 10 reloads each, 1 h / 30 min soak, 0 oops; module in RAM 482 → 325 KB (T20) and 479 → 323 KB (T10).
  • T20 vendor-matched firmware device-tested: in the default configuration the picture is unchanged (the firmware is parked after the first pass; per frame only CCM/saturation/LSC, Iridix, sharpening, noise reduction, sensor control and the simple AE/AWB run). What changes: controls that did nothing before now work on T20 (max analog gain, DRC/Iridix strength, manual white balance), and the OEM AE converges (it stuck at minimum exposure before). Found and fixed on the device: returning from manual to auto white balance kept the manual gains until a module reload (our simple AWB, not vendor code); now back to auto within 3 s. White-balance gains are 8 bit on T20 like the vendor (128 = 1.0); the application will clamp values above 255.
  • T21 stability device-tested on cam-J: 20 reload cycles with streaming (some with SIGKILL of the application), failed open followed by rmmod, AF getters, and the new rollback after a failed open (fault injection: activated parts are released, the next open streams without reloading the module); VBM rmem parking 50 cycles with a stable largest free block. The "soc_vpu wait timeout" after killing the application is only a misleading log line from the aborted encode of the dying process; a small kernel patch makes it debug-level.
  • Test runner fixed: since 2026-10-02 the open-tx-isp host tests had not run at all (the stale T31 WDR test failed to build, so make -k check built everything and ran nothing). New runner runs every test with a timeout and a summary and fails on unregistered tests; the WDR test was updated to the new buffer layout. Result: 57/57 on next and all open branches green. The T20 vendor-comparison harness now also fails on lockstep divergences and covers CCM/hysteresis boundary cases (4 deliberate mutations are caught).
  • Docs: new page docs/PERFORMANCE.md (open vs vendor per SoC, every number with its source) and a consistency pass (T21 module 452 KB, T23 vendor AE default, build docs).

Late morning (2026-10-05, 11:30)

  • T20/T10 firmware compared with the vendor module (branch, device test pending): a differential harness (tests/t20_fw/vdiff) runs the vendor tx-isp-t20.ko and our recovered firmware side by side in a MIPS emulator: lockstep scenario (day, dusk, night bank, manual exposure, AE modes, full API get/set sweep), per-function replay from recorded vendor machine state, and fuzzing of math helpers and API accessors. Before: 530 divergent scenario steps, 79 of 357 functions and 52 of 68 fuzz candidates differed; after 27 fixes: 0 (at -O0 and -Os). Found and fixed, among others: the OEM AE divided by zero every frame (exposure target always 0, the reason the OEM AE stalled) and lacked histogram weights; the colour matrix used wrong source matrices; the Iridix gain dropped to 0 whenever exposure fell (exp2 of negative inputs); exposure partitioning used one walking accumulator instead of two; analog-gain hysteresis, long-exposure callback pointer, sharpening and flash init; 51 API setters stored nothing (e.g. manual white balance, gain, Iridix) and register API IDs were shifted by one. Most fixes also change the default path, so colour, dynamic range and sharpness may change visibly (towards the vendor picture). Independent review and A/B device tests with image comparison on cam-I (T20) and cam-E (T10) follow. 110 vendor functions are not reached yet (DIS, WDR-FS, SPI/sbus, IIR).
  • T41 unresolved indirect calls, top 5 fixed (branch, device test pending): proc write path of the IVDC block now allocates and frees real DMA memory (before: a garbage return value was used as a CPU pointer and DMA address); IVDC interrupt delivers event 0x1000007 to the notify handler; sensor mode changes send event 0x200000d; suspend/resume call the real callbacks; the two analog-gain setters whose target struct was lost by the recovery now return with a one-time warning instead of a fake success. Verified against libt41-firmware-1.2.6-720-4494.
  • T21 stability (branches, device tests running on cam-J): module unload freed the tuning memory before the last function that reads it (NULL access on rmmod after a failed open; the vendor driver has the same order); AF attribute/metric getters read wrong addresses (reachable via ioctl) and now mirror the vendor; VBM pool rmem block kept per channel across disable/enable (OPENIMP_VBM_PARK=0 disables) and a 1 s back-off after a failed Helix create.
  • New test cameras: cam-I (second T20, jxf22) and cam-J (second T21) were backed up, measured on the vendor stack and flashed with the open stack (30/30 snapshots, 0 oops). A full OTA keeps /overlay: an old /etc file from the previous image can override new image defaults (seen on cam-J: sensor flip parameter), check /overlay/etc after flashing.
  • Docs: consistency pass over README, changelog, matrix and wikis (T21 module size 452 KB everywhere, T23 vendor AE default) and a new performance page in progress; part of this preparation was drafted by another model and verified before use.

Early morning (2026-10-05, 02:30)

  • T20/T10 recovered ISP firmware builds optimised (branch, not yet device-tested): the decompiled firmware unit (tx_isp_t20_firmware.c, also used by T10) had to be built with -O0. A new host harness (tests/t20_fw) runs it as a host binary through init, 239 frames, AE/AWB (simple and OEM), day/night and a tuning get/set sweep, and compares register traces, outputs and state between -O0, -Os and -O2: identical (375 of 517 functions executed). Against the old code the harness catches the problems (the -Os build crashes). About ten real reconstruction errors were fixed to match the vendor disassembly: dropped call arguments, a table overrun, state kept on the stack instead of static, a too-small stack buffer, an inline-asm jump without return, a missing return value. Also fixed: selftest_sensor_id jumped into data (oops on call), and the OEM AE target divided by the high word instead of the histogram population, i.e. by zero on every OEM-AE frame (the default simple AE was not affected). Module T20 590 → 409 KB, T10 587 → 406 KB, largest stack frame 624 → 280 bytes; TX_ISP_FW_O0=1 restores -O0 for A/B. An independent review runs; device tests on cam-C and cam-E follow after the soak.
  • Open findings from that work: the OEM AE path stalls at minimum exposure in the harness (cause open); four further misreconstructions in rarely used paths (exp LUT accumulator, flash init, I2C sample data, API buffer size reset). A function-by-function comparison against the vendor module in an emulator (as done for the T23 AWB) is planned.
  • T41 unresolved indirect calls: the recovery turned about 126 unresolved jalr targets into calls of a pure math helper (private_math_exp2); about 45 sit in compiled code (ioctl fallback, sensor allocation, suspend/resume, an interrupt handler) and do nothing today. No memory corruption, but possible functional gaps; a classification is in progress.
  • Code fixes on branches (next aggregate): T21 tisp_af_set_attr wrote 20 bytes past a 4-byte object and one byte to a wild address, its refresh read from an absolute address (latent: no caller today); T41 temper reaches the 3D-noise-reduction registers (host test added; measurable only as frame-to-frame noise at high gain); OpenIMP tests share one fake rmem allocator.
  • T20 measured now (day mode): ISP module 466 KB, MemFree 54.9 MB (vendor measured earlier 52.3 MB), application CPU 9.1 %, system 17.5 %, RSS 4.3 MB, 21 threads, snapshot 0.34 s average. A fresh A/B against the vendor under identical light is still open.

Night (2026-10-05, 00:30)

  • T23 AWB at cold start and at night – real bug, fixed (not yet daylight-tested): the "AWB HLIL ... ret=-61" lines were not harmless. At night/IR no zone falls into the colour-temperature weight mesh (all zones R/G ≈ B/G ≈ 1.2, dark/IR noise). The vendor AWB then applies the static white-balance gains of the tuning file (CT 5000); the open driver kept the last gains instead, e.g. warm 2300 K evening gains across every application restart. Invisible in the greyscale IR image, but a colour cast is possible when starting in day mode in the dark and at the night → day switch. In about one in three starts the first statistics snapshot also came 17 ms after stream-on with 1 of 225 zones filled and was used anyway. Fix: behave like the vendor (unit ratios on the static gains, CT 5000, not entered into the history) and drop a first snapshot with fewer than half of the zones. Checked bit-exact against the vendor AWB in an emulator with real night zones; on cam-G at night: no -61, 0 oops, snapshots 200. Side finding: with an IQ history window > 1 the open driver smooths in the ratio domain, the vendor in the gain domain (not relevant for cam-G's sensor, window 1).
  • Next aggregate built (not flashed): OpenIMP claude/agg-23 (review-3 fixes, small fixes, the upstream contributor's audio patch, Helix T20 test flake) and open-tx-isp claude/agg-23 (T23 cold-start MSCA fix, T23 log switch, ISP small fixes, the upstream contributor's patches, T41 prototypes and ioctl hardening, T23 AWB fix). Images for all eight cameras keep the memory split each camera runs today (rmem/ispmem unchanged). Flash and device tests follow after the 24 h soak.
  • Soak at 6 h: 0 restarts, 0 encoder/VPU errors, 0 oops. Low MemFree on the 64 MB cameras is page cache (9-14 MB reclaimable); unreclaimable slab 4-5 MB and the application's RSS 3.3-4.6 MB.
  • Docs: feature matrix rewritten to the current state; T10/T20 use the pre-Helix NVPU encoder (wiki corrected); T21/T23 have no H.265 encoder in vendor libimp or hardware (docs/T23_H265.md); Helix wording aligned (frame drops fixed, rare single errno-5 error still open).
  • Housekeeping: merged and superseded branches removed from the forks; two leftovers from an early T21 bring-up branch (VBM rmem block parking, Helix create back-off) will be ported and tested on cam-D; a T31 LSC fix (mirror the shading mesh only for V flip) waits for a device test.

Late evening (2026-10-04, 23:10)

  • Soak: 5 h on the aperto images, all six cameras: 0 application restarts, 0 encoder/VPU errors, 0 oops, every snapshot 200. On cam-F the application was restarted a few times between 21:10 and 21:45 for tests (no reboot, no kernel change); this is noted in the soak log.
  • T41 ioctl stack overflow fixed (open-tx-isp, not yet device-tested): commands that the typed handlers did not catch fell through into decompiled code that copied 8-80 bytes from userspace into 4-byte locals on /dev/tx-isp, /dev/isp-fsN and /dev/isp-m0. Unknown or legacy commands now get one pr_warn_once and -ENOTTY; every command libimp/OpenIMP uses is unchanged. Stack per call shrinks slightly (184 → 168 bytes main ioctl). Only T41 was affected. A custom ISP bin path (non-default) now returns an error instead of crashing. Device test plan (wrong sizes, unknown commands, repeat during live capture) is in driver/t41/README; it runs with the next aggregate image.
  • T41 main stream: an early-morning matrix run saw an undecodable 1080p stream; that was before the rmem best-fit fix. The main stream now reports High profile 1920x1080 and decodes cleanly.
  • Release branch named aperto everywhere: the planned release branch is called aperto in the Lu-Fi forks (README, CHANGELOG, wiki) and will be added as aperto in the original opensensor repositories, whose main stays the original author's line. thingino aperto will pin the date tag.

Evening (2026-10-04, 21:00)

  • Upstream thingino aperto (the upstream contributor's open ISP stack branch) now carries the open stack. Merged: #1747 OTA stage-2 copy on a full overlay, #1748 + #1752 kernel VPU/rmem fixes (open/close races, double free, cache-flush BUG(), bounded killable waits, validated ioctls, Helix residual interrupt), #1749 opt-in ISP boot guard, #1750 SC2336/T31 flip result (device-tested on a production camera), #1751 SC2336/T23 flip race, #1756 OpenIMP and open-tx-isp built from the Lu-Fi forks, T23 fully on OpenIMP. In the thingino ciao branch: #1737 JXF23 GPIO ownership, reset pulse on every detect after review.
  • All test cameras run images built from aperto (cam-A…cam-F, cam-H; 17:39-17:47): 30/30 snapshots, 0 oops, 0 VPU errors; a new 24 h soak started at 17:50 (3 h so far: no application restart, 0 encoder errors, 0 oops). The earlier all-22 soak ran 3 h without errors.
  • T23 snapshot 503 on a second channel – root cause: stale buffer addresses stay in a channel's MSCA address FIFOs after a stream stops (the vendor clears them on STREAMOFF, the open driver did not); when a second channel starts on an already running core, the hardware works through the stale addresses first and sometimes never reaches the fresh buffers. Fix: clear the FIFOs and re-arm the queued buffers before the channel's MSCA start (msca_fifo_rearm, default on): 260 cold-start cycles without a failure (before ~1-7 %). The "AWB HLIL ... ret=-61" lines at start are expected (no zone in the colour-temperature mesh while AE settles or at night) and are now info level. Soak pending before it enters next.
  • T23 log switch: the upstream contributor's idea adapted with an explicit allow-list of pure progress messages behind t23_runtime_trace; all errors, unknown warnings and failed results stay visible. Boot/stream-start log 522 → 78 lines, module +3.5 KB.
  • Memory on cam-B: the slowly falling MemFree is reclaimable kernel cache (dentries/inodes); unreclaimable slab and the application's RSS are flat.

Late afternoon (2026-10-04, 15:50 - 16:30)

  • T41 control paths: AE compensation (AeScenceAttr.AeTargetComp), gain and exposure caps (AeExprInfo: AeMaxAGain linear Q10, AeMaxIntegrationTime in sensor lines) and 2D/3D noise reduction (Module_Ratio index 0/1) now reach the ISP on cam-F (measured: comp 2 lowers the target 65 → 1, gain cap 8x holds 6.9x, sinter 255 cuts wall noise from ~7 to ~1). The T41 driver used to acknowledge unknown tuning IDs with 0; DRC, DPC, defog, HLC, BLC, WDR, CCM, gamma now return "not supported" instead of a silent success. Crop/rotation (I2D) still open. AE itself regulates correctly (it was saturated at max gain in a dark room). cam-F anti-flicker set to 50 Hz.

  • Two new T23 test cameras on the open stack: cam-G (T23, SC1A4T) and cam-H (T23, SC2336P), full OTA with the boot guard, rmem 22 MB: both streams High profile, 0 oops, 0 VPU errors; rmem peak 17.3 MB and 19.0 MB. First devices with these two sensors on the open stack.

  • Branch layout in thingino: the open-stack work moves from the user's ciao fork branch to an aperto branch based on upstream aperto (the upstream contributor's open ISP stack branch, U-Boot 2013.07 like ciao). The upstream PRs were closed and will be resubmitted against aperto; the 64 KiB U-Boot env fix stays local because ciao/aperto build U-Boot 2013.07.

  • Pins: thingino will pin the Lu-Fi forks of OpenIMP and open-tx-isp by date tag from the aperto branch (first tag after the 24 h soak).

  • aperto in the user's thingino fork is live: upstream aperto plus the open-stack layer (opt-in boot guard, DPC slider, VPU/rmem kernel patches as 0098-0105 on top of the upstream contributor's 0097, OpenIMP/open-tx-isp packages pinned to the Lu-Fi forks by date tag from their aperto branch, T23 fully on OpenIMP without vendor blobs, sensor fixes for jxf23/T21, sc4336p/T31, sc2336/T31 and the sc2336/T23 flip race, fw_ota stage-2 fix) and a merge of the thingino branch ciao. A test image for cam-B builds (rootfs 20 KB below the 8 MB flash limit — tight). Application changes now land only in ciao; a GitHub Action merges ciao into aperto (or opens a PR on conflicts).

  • the upstream contributor's upstream aperto patches for OpenIMP/open-tx-isp (written against the opensensor repos) are being reviewed; the useful ones will be ported to the forks with the contributor as author.

  • the upstream contributor's upstream patches reviewed: two ported with the contributor as author — the audio capture read size now always covers whole driver fragments (OpenIMP; a real bug: at 48 kHz, 44.1 kHz or stereo the fixed 1280-byte read was not a multiple of the driver fragment and could hang the audio driver unkillably; tested on cam-A and cam-C, 8 k to 48 k) and the T20 scaler cap without crop (open-tx-isp). Not ported because the fork already does it better: sample-clock audio timestamps (fork stamps in the capture thread, ±0.1 ms), a 30 s give-up on missing frames (the fork fixed the busy loop and keeps the channel recoverable), an alternative T20 WDR oops fix (the fork's fix follows the OEM code). The soc_vpu TLB experiments are left out (off by default, no benefit shown). His T23 log switch is being adapted so that only informational messages are behind it; warnings and errors stay visible.

  • Builds switched to aperto: one build tree, one per-camera user directory, one build script with the per-camera memory sizes (rmem/ispmem) decided today; T41 from an aperto worktree with the local U-Boot 2026 env fix. First full build of all eight test cameras from aperto is running.

Afternoon (2026-10-04, 14:40)

  • all-22 on cam-A…cam-E (full OTA, 13:01-13:07): open-tx-isp next + T20/T10 memory pool off + kernel hardening + T20 AE restart fix; OpenIMP next + hardening + rmem peak logging + Helix logging; local kernel patch 0102 (Helix residual interrupt). 30/30 snapshots, 0 oops, 0 VPU errors on every camera; sensor pin refuses rmmod on cam-A and cam-D. These components are now in next (OpenIMP 2dc60dd, open-tx-isp f9939d64).
  • Helix frame drops fixed: cam-B lost 4-6 pictures per hour because the bounded-wait kernel patch treated a residual Helix interrupt (status 0x100 after a finished job) as an error. With the residue ignored: 60 min, 0 errors. Upstream: #1736 was reduced to the safe patches (VPU open/close races, rmem cache-flush BUG()), the bounded waits follow with the fix in #1743.
  • T41 1080p stream fixed: rmem was exhausted, so the main channel fell back to a broken software encoder (Baseline header, grey frames). Now: stream buffers sized like the vendor (1080p 0.95 instead of 2 MB), capture buffers allocated from the bottom and everything else from the top (best fit) so an idle/restart cycle no longer fragments rmem, the software fallback is refused for video with a clear log line, and an allocation failure logs a concrete rmem suggestion. cam-F: both streams [email protected], 5 idle/restart cycles clean. cam-F now runs rev6 (rootfs) with rmem 26M and the 64 KiB U-Boot env + Bad-CRC guard; the env stays valid across reboots.
  • Motion detection v2 is on by default (OPENIMP_MOTION_V2=0 restores the vendor algorithm). The application exposes boxes, strength and suppress reasons via the versioned OpenIMP_IVS_MoveGetResultEx API.
  • Memory with reserve: cam-E (T10) ispmem 8 → 6 MB (temper still fits, +2 MB for Linux); cam-A (T31) rmem 50 → 36 MB (+14 MB for Linux, 3 RTSP clients + MJPEG + snapshots without allocation errors). T23/T21/T20 stay as they are (reserve too small to gain anything). Rule: measured peak or computed worst case + ≥25 % and ≥2 MB.
  • Repos: 82 merged branches deleted; tracked files cleaned (privacy: real camera/room names, IPs and local paths replaced; ~16 MB of old notes, dumps and binaries archived or removed); new README with logo, badges and changelog; main = next at that time (later not kept in sync; next is authoritative); documentation wiki at the OpenIMP repo.
  • 24 h soak of all five cameras started at 14:15.

Noon (2026-10-04, 11:40 - 12:15)

  • +8 MB RAM on T20/T10: the 8 MiB V4L2-MMAP frame pool is now off by default (isp_mmap_pool_kb=0, parameter kept); only the recovered firmware unit stays -O0 (module −140 KB). MemFree with streams running: cam-C 46.7 → 55 MB, cam-E 1.9 → ~9.7 MB. The open stack now leaves more RAM free than the vendor stack on T20. [open-tx-isp claude/t20-mem-pool]
  • Shortfall logging instead of silent degradation: the T20/T10 driver logs once with have/need/missing and a concrete value when reserved memory is too small (e.g. "set isp_mmap_pool_kb=8104", "set ispmem >= N KB" when temper/WDR would be switched off). OpenIMP logs the rmem peak at stream start and on every new peak, and on an allocation failure "raise rmem by at least M KB (suggest rmem=M)". cam-D peak: 18.4 of 23.5 MB. [claude/t20-mem-pool, openimp claude/imp-rmem-highwater]
  • Hardening (no measurable cost):
    • Kernel: T31 proc writes bounded, VIC stop busy-wait bounded (~10 ms), AE handle wait with 2 s timeout; T20/T10 IRQ registered before its data was published (oops on an early interrupt) fixed. 10 min stream + restarts on cam-A, ISR load unchanged. [open-tx-isp claude/isp-hardening-3]
    • OpenIMP: repeated driver errors are rate-limited (they could log every millisecond), silent -1 returns now logged, four NULL crashes, a buffer overflow in the module-chain dump, lost items on EINTR and an OSD size overflow fixed. [openimp claude/imp-hardening-2]
  • T20 AE after an application restart: with a very bright scene the exposure could stay overexposed after restarting the application without reloading the module (sensor exposure cache and AE state survived the sensor reset). The cache is now invalidated on every sensor sync and the AE state is reset like on a fresh load; 5/5 restarts converge on cam-C and cam-E. [open-tx-isp claude/t20-ae-restart]
  • T41 in next: the T41 unload/flip/BCSH/isp-m0 fixes are merged into open-tx-isp next (9e5eb1ea); all six SoC modules build. Three module reloads on cam-F clean, module 80 KB smaller. The decompiler artefacts (addresses used as constants for AWB/LSC colour temperature, ivdc registers) were already fixed there.
  • Image checks: cam-B (T23) colour in direct sun with the vendor AE is neutral (R/G 0.94, B/G 0.93); cam-C (T20) white balance follows smart bulbs from 2200 to 6500 K (lower limit ~2300 K keeps very warm light slightly warm). Both matrix cells are now ✅.
  • thingino integration: the T23 OEM Helix helper option and the hybrid install (/opt/openimp-t23) are removed from the openimp package; T23 runs fully open. Kernel VPU/rmem stability patches and sensor fixes are being prepared as pull requests against thingino ciao.
  • T41 U-Boot environment: boot scripts writing the environment with the old 32 KiB size broke the 64 KiB environment again (U-Boot fell back to rmem=30M). Restored; the 64 KiB fix needs a guard that refuses to write when the environment already has a bad CRC (otherwise a valid but minimal environment with a network boot command could be written).
  • T41 U-Boot environment fixed for good on cam-F: with /etc/fw_env.config at 64 KiB the environment reads without "Bad CRC"; a guarded fw_setenv refuses to write when the CRC is bad and otherwise leaves the environment byte-identical; after a clean reboot U-Boot uses it again (rmem=24M).
  • Upstream pull requests (thingino ciao):
    • #1736 kernel 3.10.14: VPU (Helix/NVPU) and rmem hardening — bounded and killable waits, no double free on close, validated user pointers and register windows, cache-flush direction/range checks.
    • #1737 sensor fixes: T21 jxf23 releases only its own GPIOs, T31 sc4336p vflip reports the real result.
    • #1738 64 KiB U-Boot environment for 20xx U-Boot plus a guard against writing over a bad CRC.
    • #1739 ISP boot guard as an opt-in package.
  • Feature matrix: boot guard shipped (T20/T23/T31), T41 H.265 and T23/T41 microphone verified; speaker/AEC cells stay untested on purpose (test cameras must not play audio). T41 open cells are being tested now.

Midday (2026-10-04, 11:00)

  • all-21 on all five cameras (full OTA, 10:13-10:19): open-tx-isp next 1559bf60 (all-19 + sensor pin + T23 AWB fix), openimp next b83ebbb (all-19 + IP delta read-back). 30/30 snapshots and 0 oops on every camera; sub stream 0 shifts on cam-B and cam-D; rmmod of the sensor is refused while streaming on cam-A and cam-D.
  • next branches now track the tested aggregate (fast-forward only); aperto (release branch) and the first date tag follow after a clean soak.
  • Open issue (stability): cam-B (T23) logs a single "Helix run failed errno=5 / vpu error status=100" every few minutes on main or sub stream; one frame is lost, the stream continues. Present since before the sub-stream fix; root-cause work started [openimp claude/t23-helix-errno5].
  • Memory review (kernel + userspace): the ~5 MB MemFree gap to the vendor stack on T20 is fully explained by an 8 MiB V4L2-MMAP frame pool that the T20/T10 driver allocates in lowmem at load time and OpenIMP never uses (the vendor driver has no such pool); the application itself needs 3 MB less than with the vendor libimp. In work (stability and image quality first):
    • pool off by default on T20/T10 (≈ +8 MB for Linux, ~20 % of the T10's RAM), parameter kept;
    • T20/T10 driver: only the recovered firmware unit stays -O0 (≈ −140 KB);
    • shortfall logging: the driver and OpenIMP will log once with have/need/missing and a concrete suggestion (ispmem=, rmem=, isp_mmap_pool_kb=) when reserved memory is too small instead of silently degrading;
    • rmem high-water logging in OpenIMP as the basis for shrinking rmem per camera later;
    • T41: five 16 KB arrays look like decompiler artefacts (constants read as addresses) — checked as a possible arithmetic bug (−80 KB). Later, only with image checks: smaller ispmem on T20 (11→8 MB) and T10 (8→4 MB), smaller rmem after the high-water data.

Late morning (2026-10-04, 09:50)

  • A/B vendor vs open stack (cam-C, T20, night, same scene, same application build; only libimp + tx-isp differ, both full OTA images):

    Metric Vendor stack Open stack
    application CPU (all threads) 25.2 % 10.5 %
    System CPU busy 33.5 % 15.3 %
    application RSS / threads 6.8 MB / 30 3.7 MB / 21
    Start to first image 3.0 s 2.5 s
    Snapshot latency (avg of 10) 0.45 s 0.20 s
    Bitrate main / sub 1248 / 261 kbit/s 1311 / 200 kbit/s
    MemFree 52.3 MB 46.9 MB

    The open stack needs less than half the CPU and answers snapshots twice as fast; MemFree is ~5 MB lower because the open driver module is larger and keeps more in RAM. cam-C is back on all-20.

  • Sensor module pin fixed on T21/T31/T41: the sensor i2c driver was registered with the ISP module as owner, so the pin held the wrong module; rmmod of a sensor during streaming caused use-after-free oopses on T21. Now rmmod is refused while streaming, 0 oops (cam-A, cam-D); T20/T10 were already correct. [open-tx-isp claude/sensor-pin-all]

  • T23 white balance flip with the vendor AE fixed: the stream start cleared one black-level channel (register shared with stream enable) and the vendor AE did not rewrite it, so AWB saw +50 % blue and jumped to ~10000 K. Black level is now rewritten after stream start: stable R/B, ~5300 K on cam-B. [open-tx-isp claude/t23-ae-awb-flip]

  • T31 IP delta read-back: SetChnQpIPDelta now updates the value GetChnAttrRcMode returns, like the vendor; QA on cam-A: 46 pass, 0 fail. [openimp claude/t31-ipdelta-readback]

  • Release branches: next created in openimp (d894109) and open-tx-isp (4df00ba).

Morning (2026-10-04, 07:30)

  • all-20 on five cameras (full OTA): open-tx-isp claude/open-tx-isp-all-19 (all-18 + second driver review fixes), openimp claude/openimp-all-19 (sub-stream reference fix + T23 OSD stride fix). cam-A/B/C/D/E: 30/30 snapshots, 0 oops, 0 VPU errors.
  • Sub-stream fix confirmed: the T21/T23 640x360 sub stream no longer scrolls: 0 row shifts on cam-B and cam-D over 30 s captures. cam-B logged one isolated Helix error right after a channel restart during the post-flash check; watching.
  • T23 OSD: the date/time text on cam-B is clean on main and sub stream after the IPU row-pitch fix.
  • Motion detection v2 finished (opt-in, default vendor-identical): overnight shadow/override runs on cam-C and cam-B: false alarms cam-C ~7 → ~2, cam-B 2 → 0-1, IR switch at dawn 5 → 0; real events (car, passing shadows) still detected. Bounding boxes, strength, id, age and suppress reasons via the versioned OpenIMP_IVS_MoveGetResultEx API; +0.4-0.6 % CPU. Car headlights sweeping the scene can still trigger. [openimp claude/imp-motion-v2]
  • Release scheme agreed: fixed branches next (integration) and aperto (release branch, fast-forward only; originally planned under the name release) plus date tags vYYYY.MM.DD on aperto in openimp and open-tx-isp, so thingino's aperto branch can pin a tag instead of a SHA on a changing branch.

Night (2026-10-04, 00:00)

  • H.265 on T41: works: the HEVC channel now uses the AVPU path like T31 (it fell into a legacy probe that blocked the core and once rebooted the box). 1080p HEVC on cam-F decodes clean, 0 oops. A stuck AVPU job now times out after 2 s and resets the core instead of hanging the camera [openimp claude/t41-h265].

  • OpenIMP review fixes: complete O_CLOEXEC, eprc gets FRAME_END for dropped pictures, T31 Allegro RC lock, forced IDR after a YUV error, T20 MB-RC table bounds; T41 CBR overshoot fix now in the main line [claude/imp-review-fixes]. Optimisations: T20 MB-RC 590 → 58 KiB, no per-frame malloc/memset; libimp T31 −34 KB, T41 −20 KB, T21 −17.5 KiB text; eprc pow() → table (bit-identical).

  • CPU: profiling on cam-A/cam-D; optimised JPEG Huffman parsing (table), OSD cache invalidation, T31 EBSP copy: application CPU T31 8.7 → 7.9 %, T21 17.5 → 15.5 % [claude/imp-cpu-opt].

  • all-19 building: open-tx-isp all-18 + openimp claude/openimp-all-17 (0f6ca940). T41 image with H.265 in preparation.

  • Motion detection v2 started: opt-in: background model per grid cell, suppression after IR/exposure switches, blob grouping with minimum size/duration, bounding boxes and strength via a new versioned API; vendor output unchanged when off.

  • Differences to the vendor (current): less: T31 CBR without filler NAL, T41 tuning partly unverified, MB-RC opt-in only; deliberately different: H.265 rejected on T10/T20/T21/T23, T21 ring mode without P re-encode, stricter T23 front crop; more: see OPENIMP_BEYOND_VENDOR.md and OPENIMP_SOC_DIFFS.md.

  • all-19 flashed: on cam-A, cam-D, cam-E at 00:00 (open-tx-isp all-18 e8ed540c, openimp all-17 0f6ca940): 30/30 snapshots, 0 oops. cam-F got rev5 (H.265, reclaim fixes). cam-B and cam-C wait for the sub-stream fix.

  • Regression found: sub-stream corruption on Helix SoCs: on T21 and T23 the 640x360 sub stream shows P-frames predicting from a wrong reference (content jumps up 8–24 px, block artefacts), correlated with helix VPU error 0x100. Main stream clean; T31/T10 clean. Present in all-16/all-17; analysis in progress (suspects: reference-ring sharing on the small channel, eprc long-term reference changes). Workaround: use the main stream.

  • T41 env bug (thingino): after an OTA the firmware runs fw_setenv with a 32 KiB env while U-Boot 2026.07 uses 64 KiB → CRC mismatch → U-Boot defaults (rmem back to 30 MB). Env rewritten by hand on cam-F; permanent fix in the thingino ciao branch (fw_env.config 0x10000), not pushed yet.

  • T30 readiness without hardware: kernel module and OpenIMP build for a real T30 kernel; 810/837 functions match the vendor; H.264 command-list register order identical to the vendor (emulator oracle); fixed a missing isp_printf export (every sensor module would have failed) and an IMPEncoderCHNAttr ABI size bug (4-byte overrun). Missing: audio (being added via the T21 path), T30 rate controller, 11 tuning functions, Radix H.265. Report T30-READINESS.md.

  • Intensive driver review: 0 critical, 3 high (T23 4 MB snapraw buffer allocated at insmod, VIC error IRQs not restarting the VIC on T23/T41, T31 stats DMA freed while active), 8 medium, 14 low; previous fixes verified correct. Fixes in work.

Late night (2026-10-03, 22:30)

  • all-17 on four cameras: open-tx-isp claude/open-tx-isp-all-17 e7c86107 / openimp claude/openimp-all-15 afd2d072 flashed 22:15–22:18 on cam-A, cam-C, cam-D, cam-E: 30/30 snapshots, MJPEG, MP4, 0 oops, boot guard not tripped. New: T23 module 622 KB (vendor 857), T31 711 KB (vendor 829), T21 452 KB (vendor 616); T20/T10 vendor-identical rate controller default with working quality_lvl/change_pos; DPC on T10/T20/T21, DRC and defog (Iridix floor) on T20, scene/colour effects on T10 (beyond vendor); MB-RC opt-in. cam-B waits for the review fixes.

  • T41 memory: rmem 30 → 24 MB via a new u-boot env partition image (old env backed up, MAC kept). MemFree 7.8 MB idle; 5-min stress with 3 streams + 2 snapshot loops: no OOM, no reboot, min 2.6 MB free (before: OOM after 17 s).

  • Kernel module review (independent): 0 critical, 1 high (T23: lifted AE/ADR/defog works not cancelled before freeing the stats DMA on unload → use-after-free), 6 medium, 9 low, plus optimisations (T23 .bss placeholder arrays cost up to several MB RAM). Fixes in work on claude/review-fixes-20261003.

  • Hardening: claude/isp-hardening-qbuf-pin: QBUF buffers must lie in the rmem window from the kernel command line (qbuf_guard=0 disables); the sensor module is pinned while the ISP is open (T23 device-tested: rmmod of the sensor while streaming is refused, 6 clean cycles). OpenIMP opens all device nodes with O_CLOEXEC (claude/imp-cloexec), so helper processes no longer hold /dev/isp-m0.

  • Planned: 03:00: A/B measurement vendor vs open stack (CPU, RAM, rmem, start-up, snapshot latency) on cam-B and cam-D.

  • Feature matrix: 9 more cells closed: DPC on T10/T20/T21, DRC and defog on T20, scene/colour effects on T10, T41 video memory and stability. Remaining open: CCM/LSC readback on T10/T20 and Iridix on T10 (in work), T23 CCM in daylight, T20 AWB under artificial light (no artificial light at night; daylight A/B equal), T23 long-term hangs.

  • In work tonight: T23 review fixes (use-after-free on unload, defog allocations, front-crop overflow, ADR/AE locking, RAM placeholders) for the cam-B image; independent review of OpenIMP; CPU profiling and optimisation of OpenIMP on cam-A/cam-D; remaining matrix '?' cells on T31/T21 (audio input only); overnight soak log of all six cameras every 10 min; A/B measurement vendor vs open stack at 03:00.

  • H.265 on SoCs without HEVC hardware: on T10/T20/T21/T23 (Helix is H.264/JPEG only; Radix only on T30) OpenIMP now fails IMP_Encoder_CreateChn(PT_H265) with -1 and one clear log line, so applications fall back to H.264 at once. The vendor returns 0 and creates an empty channel that never encodes (beyond vendor, documented). Host-tested, T21 and T23 libimp build; branch claude/h265-reject. T41: AVPU HEVC port from T31 in work (claude/t41-h265).

  • CCM/LSC readback on T10/T20: CCM/LSC now readable in isp-m0 on T10/T20; T10 CCM is updated every frame like the vendor and follows day/night, T20 mesh mirror follows hflip. T10 Iridix stays bypassed by the jxh42 IQ bank (vendor-identical); enabling it beyond vendor is a pending decision. Daylight per-CT sweep pending [claude/t1x-ccm-lsc-iridix].

  • all-18 content: open-tx-isp claude/open-tx-isp-all-18 e8ed540c / openimp claude/openimp-all-16 bec17c58, flashed 23:22–23:24 on cam-B, cam-C and cam-E: 30/30 snapshots, 0 oops; cam-B no longer carries the vendor libimp hybrid; cam-A and cam-D are still on all-17 and follow later. Contents: T23 review fixes (unload use-after-free, defog allocations, front-crop overflow, ADR/AE locking, 6 undersized objects resized to the stock size); hardening (QBUF rmem-window check, sensor module pinned while the ISP is open, O_CLOEXEC in OpenIMP); CCM/LSC readback for T10/T20; H.265 rejection on T10/T20/T21/T23.

  • T41 H.265 in work: the channel is created, but there are no frames yet, and one test run rebooted the box; a timeout path is being added.

  • OpenIMP review: 0 critical, 3 high, 8 medium and 9 low issues plus 9 optimisations; fixes are in work.

Night (2026-10-03, 20:39)

  • all-15 on all five cameras: cam-A, B, C, D, E flashed 20:20-20:30 with full OTA. Result: 30/30 snapshots, MJPEG and MP4 on both channels, 0 oops. The one exception is cam-D at 26/30, because a concurrent test restarted the application; it was not a crash. Aggregates: open-tx-isp-all-15 f3f40f9e, openimp-all-13 07afe9a.
  • cam-B without the vendor libimp hybrid: /opt/openimp-t23 is gone, which saves ~328 KiB in the rootfs. Only the T23 hardware JPEG IMP_Decoder still needs the OEM worker; the worker is now optional (T23_BUILD_OEM_WORKER=1, openimp claude/t23-no-oem-worker 9eefbae). thingino will pin openimp to the Lu-Fi fork (9eefbae) for all SoCs, after a build check by the thingino maintainer session.
  • Module size (claude/open-tx-isp-size2 a7214c75): emulator-identical, device-tested on cam-A and cam-B: T23 1,047 to 622 KB (vendor 857), T31 859 to 711 KB (vendor 829), T20 775 to 736 KB, T10 770 to 731 KB. T23 and T31 are now smaller than the vendor module.
  • T21 ae_it_max_us now acts (claude/t21-ae-it-max 840a57ff): the GetExpr hook had been lost when the stock dispatchers were lifted, and the RANGE block of SetIntegrationTime was ignored. The vendor T21 also ignores RANGE, so this is beyond vendor; the user decision on it is pending. cam-D: cap 2000 us gives IT 68 lines and dgain 19 to 63; cap 5000 us gives 172 lines; cap 0 returns to 1125 lines. Caveat: a 4th module reload in the same boot led to segfaults and a watchdog reboot; under investigation.
  • eprc macroblock RC ported (claude/eprc-mbrc 9e2bc3a): 0 deviations against the vendor in the emulator on T23 and T21 (20000 calls + 3x30 random scenes x 150 frames). The vendor uses SAS mode 3 (7 activity-class QP offsets, registers 0x40074/78/7c-84/8c/90), with no per-MB QP map. Opt-in: OPENIMP_EPRC_MBRC=1, and IMP_Encoder_SetMbRC works per channel at runtime (on the vendor, SetMbRC has no effect and MB-RC always runs). Vendor bug: a class-table index reads past a 9-byte table into the stack; OpenIMP uses 0 there. Device test pending.
  • T20/T10 OEM rate controllers as default (claude/t1x-oem-rc-default-a13 f05db18): code done, device test pending. The keys quality_lvl/change_pos act as in the vendor firmware.
  • Stale cells refreshed (21:08): T23 AE (lifted vendor AE is the default, night test on cam-B passed), T41 flip (sensor flip registers follow live: hflip 0x022c=0x01, vflip 0x0063=0x02, off 0x00; daylight picture check pending, claude/t41-matrix-fixes) and T41 white balance (black-picture incident not reproducible; application calls no WB function on T41).
  • T20 OEM rate controller default device-tested (claude/t1x-oem-rc-default-a13): cam-C at 1200 kbit/s: CBR 1300 (P2 I-aware budget), VBR 1044, SMART 1019; quality_lvl 0/6 gives 1130/800 kbit/s, change_pos 50/100 gives 850/1210 kbit/s, also live via /control; decode clean, 0 oops.
  • T21 ae_it_max_us kept: beyond vendor, the user decided to keep it. The docs (matrix, beyond-vendor list, SoC differences) are updated accordingly.
  • MB-level RC per picture type (claude/eprc-mbrc a8b483a): registers 0x400c0/0x400c4 are now set per picture type like the vendor (T23 IDR 0x060404c1/0x61615921, P 0x030484c1/0x61615c21; T21 IDR 0x060407c1, P 0x030487c1). Device test is running.
  • T10 boot guard tripped: a flash reboot happened less than 300 s after a test restart, so the guard counted the load as unstable. The mark was cleared and the camera runs again. Idea: firmware updates should clear the guard's pending mark.

Late evening (2026-10-03)

  • T41 module reload fixed and verified: rev2 image on cam-F: 10/10 rmmod/insmod cycles, refcnt 0, 0 oops; kill -9 of the application recovers 3/3. Root cause: a decompiled tuning-node helper overwrote .bss. Branch claude/t41-matrix-fixes.

  • T41 picture controls and rate control: brightness 255 gives Y 211, contrast 0 flat grey, saturation 0/255 chroma 0.1/7.1 (dark scene); isp-m0 in vendor layout (run mode, BCSH, flip mode, anti-flicker, AE); bitrate 400/1200/3000 gives 518/1195/2777 kbit/s over 30 s each (claude/t41-cbr-overshoot). Forced day/night switch test pending.

  • T41 open points: the driver now writes the sensor flip synchronously (ret 0), but the test application does not call SetHVFLIP live on T41 (under investigation). u-boot ignores the stored env (fw_env.config size mismatch), so changing rmem needs an env-partition image; user decision pending.

  • T21 vendor-identical eprc is the default: 0 oracle deviations; cam-D at 1200 kbit/s: CBR 1326, VBR 1096, SMART 1071. Branch claude/eprc-t21-default.

  • eprc complete (T21/T23): FIXQP, scene-cut IDR, runtime RC/fps/GOP/HSkip changes applied at the next IDR like the vendor, SetChnHSkip on T21/T23; 0 oracle deviations. MB-level RC is not ported (separate task). Branch claude/eprc-complete.

  • T20 frame source: the snapshot debounce no longer polls the JPEG encoder: with 1 snapshot/s on both channels chn0 14.4 / chn1 15.0 fps (was 11.2 / 14.3). A sub-stream height of 270 is rounded to 272 with a warning (was: scaler hang). Branch OpenIMP claude/openimp-t20-jpeg-align.

  • T10 noise reduction: Sinter/Temper strength acts (vendor: no-op): temporal noise 7.11 / 2.91 / 1.51 at temper 0 / 128 / 255, survives day/night. Branch claude/t10-t20-nr-wdr.

  • T23 AE default: the lifted vendor AE becomes the default after the night test (pending at the time; done, default since all-20).

  • T31 Allegro CBR and T21 eprc device results (20:13): T31 (vendor Allegro core, default): CBR 1210 kbit/s at 1200 target and 2973 at 3000 (legacy controller 1511 / 3786, +26 % with large peaks); VBR 1163, CappedVBR 1177, CappedQuality 1174 at 1200; decode clean, 0 oops; no filler NAL written (filler=0 also at 3000). Branch claude/t31-allegro-cbr. T21 eprc complete: SMART/CBR/VBR at 1200 kbit/s gave 1090/1305/1042; runtime HSkip N=4 gives an IDR every 4 GOPs; decode clean, 0 oops; a day/night switch does not trigger the scene-cut IDR (vendor condition: scene class 5). Branch claude/eprc-complete. T23 eprc-complete device test is pending.

  • Aggregate all-15: open-tx-isp claude/open-tx-isp-all-15 f3f40f9e, openimp claude/openimp-all-13 07afe9a (all without the withdrawn QueryCaps). New over all-14: smaller libimp and modules (T23/T20 rootfs back to the old layout), T31 CBR on the vendor Allegro core, eprc complete on T21/T23, P5 on the T21 revision, T20 sub-stream height and snapshot frame-rate fixes, application 422 / unsupported keys not persisted. Flashing on cam-A, B, D, E started 20:2x; cam-C follows.

  • cam-B night test with the lifted vendor AE (default since all-14): switches to night (exposure 109303 > 4096), AE regulates (IT 1200 of 1436 lines, analog gain 133 of 160, gain reported). The all-11 problem (gain reported as 1x, never night) is gone. One night→day→night flip in the first 90 s after start, the same day/night start-up issue as on cam-C

  • Per-SoC difference list: new docs/OPENIMP_SOC_DIFFS.md: OpenIMP vs vendor per SoC in both directions, with API signatures and device-test status.

Evening (2026-10-03)

  • T10 rate control: super-frame fix default: the super-frame fix (P1) is now the default inside the T10 OEM controller (OPENIMP_T10_RC=1; OPENIMP_T10_RC_SUPERFRM=0 restores vendor-exact behaviour). cam-E at 1200 kbit/s: 450 to 822 kbit/s, re-encodes 800 to 0, CPU 8.3 to 5.5 %. Branch claude/t10-rc-superfrm.
  • T20 rate control: I-aware P budget: P2 is the default for CBR (OPENIMP_T20_RC_IAWARE=0 = vendor; =1 forces it for VBR/SMART too). cam-C: CBR 1583 to 1300 kbit/s at 1200 (stats 1244). VBR stays vendor (with P2 it fell to 866). Branch claude/t20-rc-iaware.
  • T31 rate control: the Allegro rate-control core is the default (OPENIMP_T31_RC_CORE=legacy restores the old one; CBR stays legacy). Branch claude/t31-capped-quality.
  • T23 fixes: brightness/contrast/saturation/hue now act (they were reset on every stream start); T10/T20 ae_it_max_us now limits the AE; T23 sub-stream rotation 90/270 works via the native encoder; T23 IMP_Encoder_YuvSetCrop implemented (host-tested only, not called by the test application); T23 contrast/gain feedback: the driver takes the low byte like the vendor and OpenIMP remembers the gain before sending (cam-B: user contrast 100 stays). Branches open-tx-isp claude/t23-bcsh-aeit-fix, openimp claude/t23-yuv-native-aeit.
  • T21/T31 contrast: OpenIMP sends the user contrast instead of the default 128 and remembers the gain before sending (commit 6ba6f17). Code done, device test pending.
  • T10 build: duplicate isp_printf export fixed in open-tx-isp (no local patch needed).
  • Boot guard for T20, T23, T31: S10isp-guard + isp_open=auto added (local image overlay, ships with the next image, not on the device yet). A load counts as stable after 300 s uptime with the application running; otherwise the next boot skips the ISP/sensor modules and the application until S10isp-guard clear.
  • T21 smaller and faster: kernel module 760 to 494 KB (RAM unchanged); the lifted AWB now needs 0.95x of the vendor instructions (was 1.41x), output bit-identical, cam-D isp_fw_process -10 %. Branch claude/t21-size-awb-opt.
  • T41 (cam-F): the bitrate setting had no effect because the OpenIMP T41 controller discarded a negative bucket level; fixed (claude/t41-cbr-overshoot), host-simulated, device test pending. In the dark the gc5603 shows strong column noise, so about 10 Mbit/s even at QP 45 (separate ISP issue). The spontaneous reboot is an OOM: rmem=30M leaves 29.6 MB for Linux; 3 parallel streams plus snapshots exhaust it and the watchdog resets. Proposal: rmem about 24 MB (the vendor image uses 19 MB). After an OOM kill the sensor stays registered and AddSensor returns EBUSY until reboot; a driver fix (claude/t41-sensor-rereg) crashed on the first device load and is being analysed. The black picture after a WB POST was not reproducible (application does not call any WB function on T41).
  • T23 matrix gaps (cam-B, claude/t23-matrix-gaps, open-tx-isp, device-tested): front crop now uses the vendor path (960x540 crop OK); the MASK control returns -EINVAL exactly as the vendor does (no stock handler). The lifted vendor AE now honours anti-flicker and reports AE luma, so backlight/highlight/AE comp work with it (backlight 10: luma 68 to 112, highlight 10: 48). Making the lifted AE the default is a pending user decision; as default, AE IT max has no effect, exactly as on the vendor. Anti-flicker device values: vendor AE 50/60/off gives IT 720/900/971, HLIL AE 720/600/711. Not bugs: IR cut/LED auto night (application auto switches IR cut, ir850 and mono, and back) and the JPEG size (q75 tables are the IJG tables, size matches libjpeg, scene-driven).
  • T41 module reload (cam-F): a rebuilt tx-isp-t41.ko with the sensor re-registration fix (claude/t41-sensor-rereg, not in any aggregate) crashed on insmod twice (rc 139) and the box needed a power cycle. Likely cause: rmmod+insmod of tx_isp_t41 is not safe in general; a control test with the installed module is pending. The T41 kernel has no netconsole/pstore, so an oops cannot be captured after the network dies.
  • T10 module reload (cam-E): rmmod/insmod of tx_isp_t10 gives 'Failed to get csi clock -22' and a NULL oops in isp_csi_set_clk at stream start; module reload is unsafe on T10, the boot-time load is fine.
  • Noise reduction strength (T10/T20, claude/t10-t20-nr-wdr + OpenIMP claude/t20-nr-strength): the vendor firmware renormalises the scaled Sinter/Temper table onto the IQ min/max, so only 0 acts. Now strength acts: T20 device-tested, temper 0/64/128/200 gives 0/42/85/132, sinter 0/17/35/69 at high gain, 128 = IQ, kept across day/night. T10 device test pending (reload oops). Default for T10/T20 is a pending user decision. T31: SDNS (H-S regs 0 to 0, 255 to 15), DPC thresholds and impulses vendor-identical on cam-A; T10 isp-m0 WDR flag fixed.
  • Other results: T20 daylight A/B of simple AWB vs vendor chain: gains 492/393 vs 488/395, neutral ROIs within 0.007, both converge in under 4 s, tungsten test open. T31 anti-flicker with a 22 ms IT cap: IT 1000/900/750 lines for off/50/60 Hz, gain compensates, daylight test pending.
  • T23 dynamic ADR and defog lifted (cam-B, claude/t23-adr-defog, 17:50): lifted from the vendor module including tisp_defog_soft_process; 44/44 emulator cases are identical. The core ISR now dispatches the ADR/defog IRQ callbacks (ADR was static before). Device: DRC 255 gives meanY 158 vs 119, DRC 0 gives 114; defog 255 and day/night switching work, 0 oops. Module parameter source_adr_oem=1 is the default, 0 selects the old static path.
  • T23 module size (cam-B, claude/t23-ko-size, 17:50): 1,282,492 to 1,071,956 B stripped (tparams zero tail moved to .bss, -mno-pdr); stream OK on cam-B. The ADR lift adds ~138 KB; with both branches merged the module is ~1.21 MB.
  • T10 module reload (cam-E, claude/t10-reload-safe): 5 rmmod/insmod cycles while streaming, 0 oops. The earlier 'csi clock -22' oops came from a module built against the T20 kernel tree; the T10 build now refuses that with #error.
  • T41 module reload (cam-F, claude/t41-reload-safe): cause found statically. tx_isp_fs_remove freed the channel array while the framechan0..2 misc devices were still registered, so the next insmod oopses in misc_register. Four static work items were also not drained on unload. The fix is not yet device-tested. Testing needs the box booted without the old module (boot guard isp_open=manual), because the old module's unload leaves the bug behind.
  • User decisions (2026-10-03): (a) T23 default AE becomes the lifted vendor AE (vendor default), after a night-switch test in the dark that is still pending. (b) T20/T10 Sinter/Temper strength acts by default: 128 = the IQ table, so the default picture is identical to the vendor; other values act, which goes beyond the vendor.
  • All-14 aggregates flashed (19:20): open-tx-isp claude/open-tx-isp-all-14 (de10fed6), OpenIMP claude/openimp-all-12 (787d534). Flashed 2026-10-03 ~19:07 on cam-A, cam-C, cam-D and cam-E (full OTA). cam-A, cam-D, cam-E: 30/30 snapshots, MJPEG, MP4 on both channels, 0 oops. cam-B waits for a smaller rootfs; cam-F stays on -all-13 (image rev 1).
  • Image size fixes: the rootfs of T23/T20 had grown past 0x4E0000. claude/openimp-size (2040a03, gc-sections) and claude/open-tx-isp-size (15232deb, strip local symbols): T23 libimp 774 to 726 KB, T20 libimp 694 to 594 KB, T23 module 1,211 to 1,047 KB, T20 module 819 to 775 KB; rootfs back to 0x4DE000 (T23) / 0x4DD000 (T20). Further driver shrinking is in work.
  • T31 CBR on the vendor Allegro core: claude/t31-allegro-cbr: CBR now uses the ported vendor core too (20 trace files + 72 x 400 random frames state-identical). Deviation: no filler NAL is written (the HRD model counts filler bits like the vendor, but a static scene's CBR stream stays below target where the vendor pads); the filler value is per picture like the vendor. Device test pending.
  • eprc QP-down limit (P5) in the T21 vendor revision: claude/eprc-t21-qp-limit, opt-in (OPENIMP_EPRC_QP_DOWN1/2). Device test pending.
  • T41 module reload: root cause: a decompiled tuning-node helper used the 4-byte module parameter ivdc_threshold_line as a struct cdev and overwrote about 60 B of .bss including tx_isp_bringup_level, so tx_isp_exit() bailed out early and left platform drivers, misc devices, IRQs and kthreads registered. Fixed in claude/t41-matrix-fixes (b4ef2cf8), device test pending. T41 image rev 1 (flashed): isp-m0 now in vendor layout; reload still failed with rev 1.
  • Feature matrix: ? cells filled: results of the evening matrix tests (audio input only, no sound played): T31 AWB presets and IR cut/IR LED device-tested; T31 CCM/LSC follow day/night and flip; T20/T10 ISP state not observable; defog/DPC on T10/T20/T21 have no control path (keys accepted but ignored); scaler tested on T10/T20/T21; T20 snapshots on both channels cost video frames; audio input device-tested on T10/T20/T21/T31.

Late afternoon (2026-10-03)

  • T31 rate control: vendor core ported: the Allegro VBR/CappedVBR/CappedQuality controller is ported instruction by instruction and matches the vendor code frame by frame in an emulator (2,100 trace frames + 72 random traces, 0 differences). cam-A at 1200 kbit/s: VBR 1163, CappedVBR 1177, CappedQuality 1174 kbit/s (old controller: 732 / – / 2030). Becomes the default; OPENIMP_T31_RC_CORE=legacy restores the old one; CBR stays on the old controller for now.
  • T21 rate control: vendor-identical: the T21 vendor controller (an older eprc revision) is ported; 0 differences in 873 oracle frames and 360 random scenarios. cam-D: CBR 1326, VBR 1096, SMART 1071 kbit/s at 1200. Opt-in via OPENIMP_T21_EPRC=1; a bug found on the way also affected T23 (CBR with very short GOPs).
  • T20/T10 rate control: kernel patch 0101 lets the vendor T20 controller read its statistics registers (the hardened kernel denied it). cam-C re-flashed: CBR 1435 (+19 %, the vendor controller itself overshoots), VBR 1329, SMART 983 kbit/s — SMART was treated as VBR before, fixed. Opt-in via OPENIMP_T20_RC=1 / OPENIMP_T10_RC=1.
  • Better than the vendor: rate-control study: an offline simulation of all ported controllers found six improvements. Device-tested on cam-E: the T10 VBR super-frame fix stops the vendor's double encoding of nearly every frame (re-encodes 800 → 0, CPU 8.3 → 5.5 %) and becomes the default inside the T10 controller. Being built: an I-frame-aware P budget against the T20 overshoot (opt-in). The eprc QP-step limit showed no measurable effect in a day scene and stays opt-in.
  • Fixes from the feature-matrix tests: T23 brightness/contrast/saturation/hue now act (they were reset on every stream start); T10/T20 max integration time now limits the AE (cam-C 300 µs → 10 lines); T23 sub-stream rotation 90°/270° works with the native encoder (the vendor helper process is not needed). 56 of 105 open matrix cells tested.
  • Open: T41 (cam-F): bitrate setting has no effect (~8.2 Mbit/s), one unexplained reboot, white-balance POST once gave a black picture — in work.

Afternoon (2026-10-03)

  • All six cameras on open-tx-isp-all-13 / openimp-all-11: flashed 14:04–14:20: 30/30 snapshots, MJPEG and MP4, 0 oops; reference-buffer sharing active on T21/T23. cam-F (T41) now boots our driver and OpenIMP from flash (kernel and rootfs flashed separately, the full image does not fit RAM for OTA).
  • Reference-buffer sharing on by default for T21/T23: the artefacts came from a missing wrap byte in the ring register; with it the picture is clean. Saves ~1.4 MB video memory; OPENIMP_REF_SHARE=0 turns it off.
  • Rate control: cam-A T31: plain VBR now closed loop (1514 kbit/s at 1500 target, before 280). cam-B T23: vendor eprc controller with the vendor's CreateChn clamps — SMART 1141, CBR 1253, VBR 1255 kbit/s at 1200, decode clean (old mapping: 3203). cam-D T21: eprc approximation behind OPENIMP_T21_EPRC=1 (CBR 1338 vs 570 with the old controller); a vendor-identical T21 port is in work because the T21 vendor controller is an older revision. T20/T10: vendor controllers ported, bit-exact in the emulator (200×150 frames); on cam-C CBR overshoots 25 % because the hardened kernel denies one statistics register read — kernel allowlist fix in work, default off until then.
  • T31 CappedQuality decoded: differs from CappedVBR in two places: it keeps improving quality while at max bitrate and it never falls into the emergency max-QP after a scene change. A full port of the vendor rate-control core is in work, selectable and verified frame by frame in an emulator.
  • Scene mode and colour effects on T23 and T31: driver and OpenIMP support; device-tested on cam-B and cam-A: B/W, vivid, negative visible, invalid values rejected, 0 oops.
  • Docs for application authors: new docs/OPENIMP_BEYOND_VENDOR.md lists everything where OpenIMP behaves beyond or differently from the vendor libimp, with env switches and how to integrate or disable it. Rule: only device-tested features go in.
  • Branch cleanup: forks pruned after a bundle backup: open-tx-isp 56 → 6 branches, openimp 13 → 10; the 50 old non-claude branches were unchanged copies of upstream. Test-report branches moved to docs/test-reports/.

Late morning (2026-10-03)

  • T23 daylight green cast — found and fixed (claude/t23-day-color, device-tested on cam-B, not flashed yet): every on-demand snapshot restarts the stream, and our driver reset the white-balance gains to 1× on every stream start, so the snapshot was taken before AWB had re-converged. The vendor keeps the AWB state across stream restarts; now we do too. A side-by-side run of the original vendor stack in the same sunlit scene gave neutral colours and confirmed the cause was ours; the register comparison also corrected three stream-start values (top 0x1c, GIB 0x1008/0x1010). The HLIL AE now reaches correct exposure ~4 s after a driver reload (was ~2 min).
  • Vendor T23 uses reference-buffer sharing by default: measured on cam-B with the vendor stack (ring bit set, luma ring = picture + 256 lines); the vendor libimp forces it on for ≤1080p. A register capture is being used to align our port (claude/t23-ref-ring); the T21 opt-in stays off meanwhile.
  • Rate control (claude/rc-modes): T31 CappedVBR/CappedQuality now run the closed-loop regulator with the vendor's PSNR cap (42 dB); T20/T21 report the vendor-clamped RC values. In work: T31 plain VBR closed loop by default and vendor defaults, T23 live readback, which RC writes take effect on T10/T20/T21, and vendor-equal SMART on T23 (eprc controller + long-term background reference).
  • AVPU kernel module review (outside review, verified): fixes for a minor-number leak, a use-after-free on sysfs unbind, an uninitialised list mutex and the flush range (claude/avpu-review-fixes); kernel patch 0100 makes the rmem flush ioctl reject invalid directions instead of crashing. cam-A: reload, 3× kill -9, 5× rmmod/insmod, 0 oops.
  • New T41 test camera (cam-F): OpenIMP runs against the vendor T41 driver with video, JPEG, OSD and motion detection (claude/t41-libimp): a kernel oops from the cache flush was fixed (the T41 kernel expects a physical address), motion detection gets frames without a viewer. application CPU ~10–12 % vs ~27 % with the vendor libimp. Our T41 driver needs an image for testing (vendor module oopses on unload); image being prepared.
  • Feature matrix (English) now in docs/FEATURE_MATRIX.md / docs/feature-matrix.html.

Morning (2026-10-03)

Done and device-tested, waiting for the next aggregate (-all-13):

  • T31 privacy mask (claude/t31-privacy-mask): the ISP mask block is now implemented like the vendor driver (4 rectangles per channel, YUV fill, follows mirror/flip). Emulator: 400/400 random sequences register-identical to the vendor module. cam-A: black and red rectangles at the right place and colour, get/clear OK. OpenIMP converts RGB mask colours to YUV like the vendor libimp (claude/t31-mask-rgb2yuv).
  • T21 tuning controls (claude/t21-tuning-controls, beyond vendor — the vendor kernel ignores them): scene is stored, colour effects black-and-white / vivid / negative work, Sinter and Temper denoise strength act on the hardware, getters return what was set; defaults stay vendor-identical. Sinter strength works on T21 (claude/t21-sinter-strength, 128 = vendor picture). cam-D: effects and denoise visible, 0 oops.
  • T21 debug parameters removed (claude/t21-drop-debug): module 13.8 KB smaller.
  • T20/T21 encoder error limit (claude/helix-error-limit): after 3 failed pictures the encoder is re-created, after 2 fruitless re-creates the channel stops instead of waiting 20 s per picture. cam-C and cam-D soak OK.
  • T23 RC defaults (claude/t23-rc-app-defaults): app value 0 for QP step / static time / change position now means the vendor default (3/15/2/80) instead of "off", taken from the vendor libimp 1.3.0.
  • cam-A sensor driver: vertical flip no longer reports a false error (local thingino patch).

Investigated, not adopted:

  • Reference buffer sharing (vendor BUF_SHARE_CFG): only the T21/T23 Helix hardware has the ring mode. On cam-D it saved ~1.4 MB video memory but produced magenta/green reference artefacts in the first seconds; stays off while the cause is analysed.

In work:

  • T23 by day: with the lifted vendor AE exposure is right at once and AE compensation/highlight work, but the picture is green; with the HLIL AE the first ~2 minutes after a driver reload are overexposed. Cause under analysis (CCM bypassed since it follows the IQ bank). The lifted AE becomes default only after this is fixed.
  • New T41 test camera (vendor stack): build fixes for the T41 driver and an OpenIMP T41 build are being prepared.

Early morning (2026-10-03)

  • Aggregates -all-10 / openimp-all-9 and -all-11 / openimp-all-10 flashed on all five cameras (incl. cam-A, which moved up from -all-5). Checks on every camera: 30/30 valid snapshots on both channels, MJPEG and both MP4 streams, 0 oops, 0 encoder errors. -all-11 was flashed staged (cam-D and cam-C first) because it carries a new kernel.
  • Vendor helper libraries gone: libimp now contains the two logging functions it used from libalog; libalog/libsysutils are no longer built into the images.
  • Kernel soc_vpu (patch 0099): requesting a busy VPU sleeps instead of busy-waiting up to 200 ms; on T20/T10 an encoder error interrupt now ends the wait immediately (with reset) instead of running into the timeout; per-instance bitstream counter on Helix.
  • T23 motion detection fixed: after the last sub-stream viewer left, capture buffers stayed parked and motion detection got no frames (empty motion grid in the web UI). Frames are now recycled for callback-backed pools too.
  • T23 memory: JPEG shares the H.264 bitstream area like the vendor pool (1.44 MB less video memory, main window back to 2 MiB).
  • T23 image pipeline: DPC and CCM follow the IQ bank flags like the vendor (less night noise); a block whose parameters fail to load on a day/night switch is bypassed instead of running with the other bank's values; user bypass bits survive day/night switches.
  • T23 vendor AE (lifted, source_ae_oem=1): first picture after a stream restart no longer black, day/night refresh and gain limits wired like the vendor, AE compensation works at night. Default briefly switched to it in -all-11, but the driver then reported a constant 1× gain, so the application never switched cam-B to night — reverted in -all-11b (HLIL AE default; the vendor AE became the default again in all-20). Follow-up branch claude/t23-ae-oem-export exports the lifted AE's live gain/EV exactly like the vendor getters, feeds AWB/CCM/BCSH/ADR/Defog with the real EV, and repairs ADR/Defog state that the reconstruction had mapped onto unrelated memory (an event table, a CLM LUT word, a module parameter). Verified on cam-B at night in both AE modes; default stays HLIL until a daylight test.
  • T21: colour-temperature updates only when CT moves by more than 50 K (emulator: 62 % fewer register writes, same final state); module reload on cam-D OK.
  • T20/T30 memory: JPEG bitstream buffer 1 MiB instead of a frame-sized buffer (cam-E −328 KiB; more on 1080p). Allocating encoder buffers at channel creation was measured to raise the peak and stays opt-in.
  • Encoder diagnostics: one log line with the effective rate control per channel; out-of-range QP/fps values are clamped with a warning instead of silently replaced.
  • JPEG robustness: if the encoder is busy or video memory is short, the last JPEG is delivered again instead of blocking; one startup warning when pools plus fixed buffers exceed video memory.
  • T23 reconstruction audit (-all-12): a call-graph audit of all mis-resolved memory accesses in the decompiled T23 code found none on the default path; every reachable one (ops-table ISR and IVDC ISR counters, sensor release list walk, CCM state, an AE histogram stack overflow, AF parameter copies, MDNS/DPC/mask state) now targets the vendor's variables. cam-B: 3 module reload cycles and 90 snapshots, 0 oops; flashed 05:54.
  • In work: T20/T21 encoder error limit (re-create after 3 failures, stop after 2 re-creates) waits for a device test.

Night (2026-10-03)

  • T10 picture drifting diagonally fixed (claude/t10-drift-fix, OpenIMP): the T10 encoder added the 16-pixel reference border twice, once for motion prediction and once for the deblocker output, which adds the border itself. Every P frame was predicted from a reference shifted by 16×16 pixels, accumulating until the next I frame (16 px after 1 frame, 160 px after 10). Now the border is added only for the prediction read, like the vendor command lists show. The overrun past the reference planes measured the evening before was the same bug. cam-E: shift 0 on both streams, 0 decode errors, flashed 01:50. Day/night switch on T10 not yet tested.
  • T21 white balance at dusk (claude/t21-awb-hyst, kernel): hysteresis band (default 10 %) on the three AWB brightness thresholds, so the parameter set and the low-light register stop toggling at dusk (emulator: 39 switches → 0 in 40 frames). While in night mode AWB is frozen and the day gains are restored after night→day, so the first day picture no longer starts orange from IR light. Both settings at 0 give the vendor behaviour (10/10 scenes identical). cam-D: night checks OK, 0 oops; dusk itself still to test.
  • T10 sub-stream picture wrong — fixed (found via the web preview): channel 1 (640×360) showed the left half of the main picture at 1:1, vertically scaled — in both H.264 and MJPEG. libimp ruled out. Cause in the lifted firmware shared by T20/T10: _update_ds() computed the horizontal downscaler ratio as output width / output width (always 1.0) instead of input / output (claude/t10-ch1-scaler). cam-E: ratio 2.0, full scene on channel 1, H.264 error-free; flashed 02:31. cam-C (T20) tested by module reload: no regression (its sub-stream uses the other scaler).
  • Independent review of the night's seven branches: no blocking bugs. Follow-ups done (helix-emc-size-2, t21-awb-hyst-2, open-sysutils-2, two doc branches): T21 encoder scratch layout no longer applies to T20/T10 builds; T21 AWB day-gain restore now effective (the first AWB frame used to overwrite it) and manual WB works at night (cam-D confirmed); logging fixes with syslog opt-in (OPENIMP_LOG_SYSLOG=1). Originally: T21 encoder scratch layout must not silently apply to T20/T10 builds (only measured on T21); T21 AWB day-gain restore made effective and manual WB allowed at night; logging fixes (empty-buffer read, one prototype, syslog opt-in); stale docs.
  • OSD flush of edge rows only (outside contribution): not adopted. The kernel already bounds a large flush to one whole-L1/L2 index pass (sc-jz.c), while the change raised rmem ioctls per frame from 4 to thousands for a full-frame rectangle. Only a comment explaining the band flush was taken (claude/osd-flush-band-note).
  • In work: T23 JPEG shares the H.264 bitstream buffer, DPC/CCM follow the IQ bank, block bypass on load failure, vendor AE as T23 default, T23 motion grid empty in the web UI; replacing the remaining Ingenic libraries (libalog, libsysutils).

In progress after the -all-7/-all-6 aggregates (2026-10-02 afternoon)

Committed on single branches, tested as stated, not yet in an aggregate (next: -all-8 after the open items below).

Kernel (open-tx-isp):

  • T23 failed stream start and reload (claude/t23-iq-fail): a reload test crashed cam-B in cycle 5: statistics DMA kept writing into freed buffers, corrupted the IQ file (CRC error -77), the ISP core refused to start but the scaler started anyway, then oopses. Now the core stats DMA is stopped on a refused start and at module exit, and STREAMON fails cleanly. cam-B: 10 reloads with kill -9, missing-IQ-file test (start refused, scaler not started), 0 oops.
  • T23 sharpen block (claude/t23-sharpen-modeflags): the sharpen parameters were never loaded (all 49 arrays read from offset 0, a latent NULL read); the block actually ran on reset values. Now loaded from the active IQ bank in vendor layout, refreshed with gain and on day/night switch; bypass bit follows the bank like vendor. cam-B: registers exactly as predicted from the IQ file.
  • T23 overexposure after stream restarts (claude/t23-ae-minit): every stream start reset the exposure to the longest step; AE needed ~4 s to come back, so on-demand snapshots in sun were blown out (64 % white). The vendor keeps the exposure across stream restarts; now the open driver does too (luma at target from the first frame). Open: cam-B hung hard twice ~45 s after loading this build (no oops, watchdog reboot); bisecting sharpen vs AE change.
  • T21 white balance lifted from vendor (claude/t21-awb-lift): AWB, CT detection, CT-driven CCM/LSC now vendor code (emulator: 10/10 scenes register-identical). cam-D: day colours match vendor (R/G 1.04 vs 1.05, B/G 0.93 vs 0.92), night mono fine, 0 oops. Open: first snapshot after start delayed (503 in 7/10 cycles at 25 s) and an "event free empty" burst at start.
  • T31 tuning controls (claude/t31-tuning-stubs): black level read-back, colour matrix presets 0–4 + user matrix, front crop get/set, scaler level now real (were stubs). Review found and fixed: crop read-back returned only the low byte, crop check used swapped axes, a colour-matrix register written with swapped bytes (wrong for limited-range presets). Boot image unchanged. Device test pending (cam-A).

OpenIMP:

  • Hardware JPEG on Helix without vendor library (claude/helix-jpeg, T20/T21/T23): ~95 % less CPU for snapshots. cam-C passed; cam-D 10/10 (37 ms/job); cam-B 10/10 (29 ms/job). Fixed during testing: per-job memory exhaustion (buffer now allocated once per channel), truncated JPEGs could be served on T23 (now detected via the vendor's ACT_BS bit; retried with coarser tables, then quality lowered by 5 like the vendor, slowly recovered). Software fallback optional at build time (size).
  • OSD lines, rectangles, bitmaps (claude/osd-line-rect, T31/T20/T21/T30): drawn like the vendor (were ignored). Review fixed a use-after-free on bitmap data and a cache hazard. cam-C: all shapes correct on both streams, clipping at the frame edge, 0 oops.
  • T23 rate-control parameters (claude/t23-enc-rc-params): quality level, change point, static time, QP steps, I-frame bias and SMART now reach the encoder at channel creation (were hard-coded) — in the vendor worker path and in the native encoder. Device test pending.
  • Robustness audit, parts 2 and 3 (claude/oimp-robust-2, claude/oimp-robust-3): harmless DQBUF/EPIPE races at channel stop now quiet; atomic worker flags; AEC reference queue heap overflow; audio-effect switch during capture (use-after-free); double stream release in the audio codec; HPF overflow; spin lock without yield on a single core. cam-C: 5 restarts, fd count constant, 0 errors.

Evening additions (all single branches now pushed, still not aggregated):

  • T21 rmem on main↔sub switching (claude/rmem-keep, on helix-jpeg): our T21 build needed ~27.4 MB rmem for main+sub+JPEG (23 MB available) → WebRTC main↔sub switch failed and the camera restarted. Now one shared bitstream buffer sized exactly like the vendor's vpuBs (2,073,600 B), encoder buffers per picture size and allocated at CreateChn, long-lived buffers at the top. cam-D: free rmem with main+sub 0.5 → 1.56 MB (vendor ≈1.2 MB), 32+40 switch cycles OK. T21 ignores the JPEG size-limit register → JPEG now encoded in stripes with restart markers so it can never overrun; the core also drops the last partial 128-byte burst of every job (vendor too) — compensated.
  • Dedicated JPEG/MJPEG channel on T31 fixed too (cam-A MJPEG 24 frames/5 s, was 0 bytes).
  • T21 white balance: event callbacks run with IRQs off like the vendor (pool overflow at stream start gone; worst IRQs-off 1.05 ms, like vendor); review fixes incl. a real lifted-code bug (fix_point_mult3_64 returned a·b·b instead of a·b·c in ae_tune2) (claude/t21-review-fixes); module RAM 688 → 638 KB (vendor 616) (claude/t21-mem).
  • T23: gain index for all gain-driven blocks was linear instead of log2 (denoise/sharpen far too strong from 2× gain) (claude/t23-gain-index); vendor AE0 chain lifted and emulator-identical in 6 scenes incl. 50 Hz flicker, behind source_ae_oem (default off at the time; default on since all-20) (claude/t23-ae-lift); AE resume by EV (claude/t23-ae-resume-ev); frame-path fixes (claude/t23-hang-debug 903b9e18).
  • T23 hard hang (3× in afternoon sun, silent, watchdog reboot): not reproduced in ~3 h of evening stress; kernel soc_vpu/helix defects found and patched for a future image (not yet built); an encoder that stops producing frames at very large frames (QP 10) was found and is being examined.
  • T20 white balance: presets/manual never applied (T20 uses OpenIMP's simple AWB; recovered firmware had several decompilation errors) — fixed, presets in the correct direction on cam-C (claude/t20-wb-presets); work on the vendor AWB chain continues (claude/t20-oem-awb).
  • OpenIMP robustness 2+3, ISP gaps (scene mode, colour effects, T21 DRC/DNS), ISP probe tool, T20 log flood silenced: pushed by a second session.
  • T10L (report from a Thingino maintainer): day/night panic, EFE job never completes, 8 MiB probe pool — under analysis.

Late evening (aggregates built, more fixes on single branches):

  • All five test cameras now run the open stack. cam-B (T23) is fully open: native H.264 encoder is the default (claude/t23-native-default), the image no longer contains the OEM helixd worker or the vendor libimp (rootfs 324 KB smaller). cam-E (T10) booted the open stack for the first time (driver/t10, OpenIMP T20 build with runtime T10 detection, current application/WebUI, boot guard). Both: MJPEG 25 frames/5 s, snapshots OK, no oops.
  • T20 fixes (claude/t20-flip-sharpness, not yet in an image): vertical flip computed the UV start from the 16-aligned height — the DMA wrote 12 chroma lines past the end of the frame buffer and the top rows got no colour (pink/green band); sharpness never applied in the default path because the firmware worker is parked — now updated in the compact AE loop (edge energy 13/230/700 for 0/128/255, was flat).
  • T23 image controls (claude/t23-image-controls): contrast only acts in the day bank (the sc2336 night bank disables the contrast curve, same on the vendor stack); AE compensation works; backlight/highlights and AE compensation fixed for the lifted vendor AE; WDR needs the dynamic ADR port (open).
  • T10 integrated into the aggregates (open-tx-isp-all-9 fa7ac42b, openimp-all-8 9a2e33d2): merging uncovered a real bug — the T10 NVPU writes 21 KB (luma) / 10 KB (chroma) past each padded reference plane on every picture, which in the aggregate's top-down layout hit the bitstream window and made the stream undecodable; reference planes are now sized for it. isp_printf is exported only in the T10 module build. cam-E: 60 s / 1501 frames error-free, MJPEG, 3 day/night switches without oops. An open-stack image for cam-E is being built.
  • cam-B to become fully open: native H.264 encoder as T23 default and an image without the OEM helixd worker / vendor libimp are being prepared (until now the T23 default still used the OEM worker).
  • New user reports being worked on: T23 contrast, AE compensation, WDR and backlight without visible effect; T20 vertical flip gives pink stripes; T20 sharpness without effect.
  • cam-D memory: T21 H.264 EMC scratch sized exactly like the vendor (1080p 996 KiB instead of 2 MiB; vendor offsets reproduced; only one sub-buffer is written by the hardware, measured on the device). Free rmem with main+sub+MJPEG 1.56 → 2.76 MB (vendor ≈1.2 MB). FIXQP IDR pictures now at QP−3 like the vendor (claude/helix-emc-size, not yet in an aggregate).
  • -all-9 / openimp-all-8 flashed on cam-B, cam-C, cam-D (00:35): open-tx-isp-all-9 (T23 IRQ_NONE, T20 vendor-AWB chain behind a switch, T10 fixes, T23 vendor AE behind a switch) and openimp-all-8 (MJPEG fix, T23 overflow v2 + optional hard limit, review nits), plus kernel soc_vpu patches 0095–0098. All up, no oops, MJPEG 25 frames/5 s, snapshots OK; flashed without the usual pre-reboot thanks to a fixed OTA script. T10 encoder support (t10-cpuid) is being merged into the aggregate and re-tested on cam-E.
  • After midnight: MJPEG regression fixed (claude/oimp-jpeg-src-fix: the fan-out decision is per poll again but only waits for a video channel that is actually receiving; cam-C 25 frames/5 s with and without a video consumer). T23 IRQ handlers return IRQ_NONE when nothing is pending, unused IVDC IRQ stays off (claude/t23-irq-none; cam-B clean). Kernel soc_vpu hardening patch 0098 (bounded waits, user-pointer validation, register ioctl restricted to the VPU window, per-file channel release) plus an optional hard bitstream limit for the T23 native encoder (claude/t23-bsf-limit, only active with the patched kernel). Small OpenIMP review fixes (claude/oimp-nits, written by another model, reviewed). Night device tests on cam-B/cam-D: restarts and channel cycling clean; T23 native rate-control parameters take effect; T21 tuning getters return defaults (being checked). 98 merged local worktrees removed. Next aggregates open-tx-isp-all-9 / openimp-all-8 and images for all four cameras are being built (not flashed).
  • Status of the beyond-vendor improvement ideas (maintainer decides each one): 16 implemented or approved, 2 rejected, 42 open. Approved tonight and in work: hardening of the kernel soc_vpu driver (bounded waits, user-pointer validation, register-ioctl restricted), a hard T23 bitstream limit via the BSF interrupt (needs the patched kernel), and T23 IRQ handlers returning IRQ_NONE when nothing is pending.
  • -all-8 images flashed on cam-B, cam-C, cam-D (23:42; cam-A pending): all up, no oops. Known regression found right after: the dedicated MJPEG/JPEG channel delivers no frames again (merge interaction in openimp-all-7), fix in progress. T23 overflow fix v2 (2 MiB window, scratch between bitstream and references) tested on cam-B: 0 decode errors, forced overflows handled without reference damage. T23 vendor AE (default off) tested at night: picture at target brightness where the substitute stayed black.
  • New aggregates pushed: claude/open-tx-isp-all-8 (bfdb0e3e) and claude/openimp-all-7 (cb85922d) — everything from today except the T23 debug commit, the default-off T23 vendor-AE lift and work in progress. All modules/libimps build without new warnings; all host tests green. 24 merged single branches deleted.
  • cam-D WebRTC main↔sub switching confirmed working by the user with the rmem fix.
  • T23 native H.264 bitstream overflow (claude/t23-enc-overflow, local): a frame larger than the 1 MiB window was retried at the same QP until the channel stopped (the application then restarted the camera). Now dropped + QP raised (+4, decaying), IDR if the reference was damaged. Device finding: the core ignores the window and keeps writing up to 1.79 MB, overwriting the reference buffer behind it — a serious candidate for the afternoon hangs (sun → ~1 MB IDRs). The vendor only truncates the length.
  • T10L (report by a Thingino maintainer, now with a T10 test camera): day/night panic root cause found — our reconstruction of wdr_mode() zeroed the general FSM manager pointer (only hit when ispmem leaves room for WDR, i.e. on T10); the T10 encoder needs its own command list (captured from the vendor encoder, word-for-word host test) selected at run time; 8 MiB MMAP pool made optional. cam-E (T10): 720p H.264 25 fps error-free, 10 day/night switches without oops. Branches claude/t10-fixes, claude/t10-efe pushed.
  • T20 vendor AWB chain (claude/t20-oem-awb, behind t20_simple_awb=0, default unchanged): several decompilation errors fixed (mesh never called, wrong offsets, NR event FSM broken, firmware worker parked after the first pass); runs stable on cam-C, white-paper check in daylight pending.

Independent review and fixes (2026-10-02)

An independent code review (no critical findings) led to these fixes, now in the -all-6 aggregates:

  • Kernel: deadlock between sensor unload and reading /proc/jz/sensor/* (shared sinfo code); orphan sensor slots no longer point at unloaded modules; T21 open/release counted every open as the first (same bug in the vendor driver) — now counted and serialised; T23/T31 last-close races with foreign frame-channel users; dead global tuning buffer removed (T31); T20 refuses to release the active sensor; T21 error paths; T23 LSC flip locked, small leak fixed; unreachable decompiled T23 setters disabled. Tested on cam-A (T31), cam-D (T21) and cam-C (T20): foreign open/close while streaming, proc reads during sensor unload, repeated reloads. The T20 test exposed one more case: the T20 sensor module unloads without unregistering, leaving a dangling driver pointer that /proc/jz/sensor/*/name read after unload (oops). Fixed by a module notifier that clears slots of any module being unloaded (claude/open-tx-isp-all-7); retest on cam-C passed (10 sensor reloads during proc reads, 0 oops).
  • OpenIMP: T23 native reconfigure uses a parameter snapshot (no divide-by-zero race); T31 lambda tables are generated from a formula instead of being copied from the vendor binary (output bit-identical, 12 documented ±1 entries); top-level NOTICE incl. WebRTC AECM (BSD-3) and x264-derived H.264 code (GPL-2.0+); committed test binary removed; width alignment check; level recomputed on bitrate change; rotation state published atomically; T23 AEC uses the driver's reference offset.

Branch consolidation

Current aggregates: claude/open-tx-isp-all-7 (all-6 + sinfo module-notifier fix) and claude/openimp-all-6. All single branches and older aggregates contained in them were deleted (2026-10-02: 58 + 3 + 4 branches). Kept: docs and test-result branches, plus three old unmerged branches pending a decision (t31-isp-lifecycle, t31-isp-perf, OpenIMP t31-series).

  • thingino: the packages openimp and open-tx-isp are in the upstream branch aperto (#1756), selected with BR2_PACKAGE_THINGINO_ISP_OPEN and pinned by commit SHA to the Lu-Fi forks (next); T23 runs fully on OpenIMP, the vendor library under /opt/openimp-t23 and the helixd hybrid are gone. A tag will be pinned once the first date tag exists on aperto.
  • Merged upstream (aperto): kernel VPU/rmem stability patches (#1748, #1752), optional boot guard S10isp-guard with u-boot isp_open=manual|auto|off (#1749, default off), SC2336 flip fixes (#1750, #1751), OTA fix (#1747). Closed without merge (superseded by the aperto versions): #1736, #1738 (64 KiB fw_env.config and fw_setenv guard for T41; not upstream), #1739, #1743.
  • T21 image: sensor shvflip=1, TLS and WebRTC enabled.

Evidence

Check SoC Result
Full-stack soak, 25 fps T31 2 h 53 min, 260,648 frames, 1030/1030 snapshots, 0 errors
HEVC decode T31 2 × 900 frames, 0 decode errors
Native Helix soak, 25 fps T23 2 h 34 min, 231,668 frames, 0 decode errors, ~6 % CPU
Tuning checks with t23tune T23 Gain/IT limits with AE retime, DRC/defog bits, idempotent sinter, flip, max dgain: all pass
Night mono T23, T21 Chroma exactly 0
Stop/start cycles T20 20 cycles, 0 oops, no hung process
Motion detection T20 6/6 events, 0 false alarms in 2 min
Long soak, 25 fps T20 1 h 44 min, 156,517 frames per stream, 0 errors
Night stability T21 ISP gain constant (was cycling 6↔25)
Colour blotches T21 Chroma spatial σ 30 → 6
Day exposure T21 Mean Y 235 (blown out) → 120, natural colour
AEC speech loopback T31 Echo vs pauses 29 → 9 dB (−18 dB); AECM ERLE 44 dB
Rotation 1280x704 → 704x1280 T31 Correct picture; 9 ms/frame at 15 fps
Native encoder soak (in progress) T23 25 fps both streams, 0 encoder errors, ~6–7 % CPU
Stock-lift equivalence (emulator) T21 AE 8/8, ADR 40/40, defog 40/40, dispatchers identical

Compared with the vendor stack

Item Vendor Open Comment
libimp code + data, T21 ~1.0 MB ~0.5 MB Open saves about half
libimp code + data, T23 ~1.26 MB ~0.6 MB Native encoder also drops the helixd vendor library
libimp code + data, T31 ~1.05 MB ~0.57 MB
Kernel module, T21 616 KB 452 KB After the size work of 2026-10-03/04 (was 805 KB)
Kernel module, T23 857 KB 622 KB After t23-bss-shrink and the size work (was 1,607 KB)
Kernel module, T31 829 KB 711 KB

Still open (2026-10-04)

  • T23: real WDR missing; the rare Helix encode error (errno 5) is provisionally closed: 0 errors in 6 days on cam-B since the 0102 fix (syslog: 342, 32, 37 and 419 errors on 10-01..10-04, then 0 from 10-05 to 10-10); provisionally closed, still observed.
  • T41: flip, night column noise (gc5603), short IVS gaps, OOM with three parallel streams, AddSensor EBUSY after an OOM kill; day/night and AE/AWB quality untested; ioctl hardening awaits its device test; temper effect; crop/rotation (I2D).
  • T21: a 4th module reload in one boot crashed once (under investigation); VBM rmem block parking and Helix create back-off to be ported.
  • T23: AWB fix (static gains when no zone matches) awaits a daylight test.
  • AEC device tests on T23/T21/T20 (no speaker tests on the shared test cameras).
  • First release tag after the 24 h soak; aperto branch not created yet.
  • Improvements beyond vendor behaviour are collected separately and decided by the maintainer.

Branch map

Both repositories: next is the tested integration branch (fast-forward only); main is the fork default branch and is not kept in sync (it lags behind next; next is authoritative). All aggregate and topic branches (claude/*-all-N and the single branches) that were merged into next have been deleted; branch names in the tables above are historic. Planned: aperto (release branch, fast-forward only) and date tags vYYYY.MM.DD after the first clean soak.

Numbers come from on-device measurements and host checks during the campaign.

⚠️ **GitHub.com Fallback** ⚠️