Reading /proc/jz/isp/isp-m0: your camera's health dashboard

You SSH into your Thingino camera, run a command someone posted on Discord, and get a wall of text.

cat /proc/jz/isp/isp-m0

Thirty-odd lines of sensor statistics, gain values, and debug counters scroll past. It looks like a driver developer’s debug dump — because that’s exactly what it is. But it is also the most detailed live diagnostic your camera can give you. Once you know which numbers matter, this one file tells you more about your camera’s real-time state than any web UI page.


What is isp-m0?

The Ingenic SoC inside your camera has a hardware block called the ISP — Image Signal Processor. It drives the sensor, controls exposure and white balance, applies noise reduction and sharpening, and feeds frames to the encoder. /proc/jz/isp/isp-m0 is a live window into ISP channel 0 (the main stream). Every value is read directly from hardware registers or the driver’s running state. There is no polling, no averaging window, no abstraction. What you see is what the ISP believes is happening right now.

If you are on a T31, T40, or T41 camera, the path is /proc/jz/isp/isp-m0. If you are on an older T10 or T20, it is /proc/jz/isp/isp_info — same location, different filename, and the field names differ in places. This article covers both; differences are called out as they come up. There is also a sibling file, isp-fs, for frame source buffer stats — covered at the end of this article.


The headline

The first block of output gives you the big three: what sensor, what resolution, and how fast.

SENSOR NAME : sc2336
SENSOR OUTPUT WIDTH : 1920
SENSOR OUTPUT HEIGHT : 1080
ISP OUTPUT FPS : 15 / 1

SENSOR NAME tells you which driver the ISP loaded. If this says gc2053 but you ordered an SC2336, your defconfig is wrong. (If it says gc2053 and you ordered a doorbell, you are in the wrong SSH session.)

SENSOR OUTPUT WIDTH/HEIGHT is the native resolution the sensor is streaming. This is not the encoded output resolution (which the streamer can scale down); this is the raw pixel array. If this reads 640x480 and you configured 1080p, the encoder is stretching a VGA sensor to fill a 1080p frame — no amount of bitrate fixes missing pixels.

ISP OUTPUT FPS is the actual frame rate. 15 / 1 means 15 frames per second, with a divisor of 1 (some sensors report 25 / 2 meaning 12.5 fps — the second number divides the first). If this number is lower than your configured FPS, skip ahead to the exposure section — integration time is usually the culprit.


Modes: day, night, custom, WDR

On T31 and later:

ISP Runing Mode : Night
ISP Custom Mode : Disable
ISP WDR Mode : Disable

On T10/T20 the mode line is present but Custom Mode and WDR Mode are absent — those features arrived with the T31 ISP block.

Runing Mode (the driver misspells it — don’t fix it in scripts) toggles between Day and Night. In night mode the ISP switches to a different set of tuning parameters: higher gain ceiling, different noise reduction, and an IR-cut filter control (if your camera has one). The streamer or daynightd flips this automatically based on ambient light.

Custom Mode (T31+) is the lesser-known sibling. The Ingenic ISP can load alternative tuning binaries — custom noise reduction curves, sharpening profiles, gamma tables — that override the built-in day/night defaults. When Disable, you are running the stock Ingenic tuning. When Enable, the ISP loads a user-provided parameter file through IMP_ISP_Tuning_SetISPCustomMode. Thingino uses this for per-camera tuning that a local.fragment or sensor-specific overlay injects. If you are chasing an image quality problem and custom mode is off, your tuning changes may not be reaching the hardware.

WDR Mode (T31+) is Wide Dynamic Range. When enabled, the sensor captures two exposures per frame (short and long) and merges them. Bright windows stop blowing out; dark corners gain detail. It comes at a cost — effective frame rate halves because each output frame needs two captures. Most budget sensors do not support it, so Disable is the common reading.


The exposure triangle: integration time and gain

This is where the FPS mystery usually unravels.

SENSOR Integration Time : 2350 lines
SENSOR Max Integration Time : 2350 lines
SENSOR analog gain : 15
MAX SENSOR analog gain : 158
ISP digital gain : 0
MAX ISP digital gain : 64

Integration time

Integration time is how long each frame exposes — measured in lines, which are sensor rows. A sensor running 1080p has roughly 1100 active lines plus some blanking lines, so 2350 lines is a very long exposure covering multiple frame periods. The sensor cannot start capturing the next frame until the current one finishes exposing. When integration time hits Max Integration Time, the sensor is at its FPS floor — it simply cannot run faster without cutting exposure.

That is what you are seeing in the opening example. Integration Time : 2350 equals Max Integration Time : 2350 — the sensor is fully saturated, running as slow as it can, and FPS drops to 15. This is normal at night. When daylight returns, integration drops to something like 104 lines and FPS jumps back to 25.

Analog gain

Analog gain amplifies the sensor’s electrical signal before digitization. A value of 15 means 15x amplification. The MAX line (158) is the sensor’s ceiling — if gain is pinned at max, the camera is struggling for light and the image will be noisy. A gain of 0 at MAX 160 means the scene is well-lit and the sensor is coasting.

Digital gain

Digital gain multiplies pixel values after the ADC, in the digital domain. It brightens the image but also brightens noise — analog gain is always preferable. A reading of 0 means no digital gain is applied. If this number climbs above zero while analog gain still has headroom, the driver is making a questionable choice.

Tgain

ISP Tgain DB : 0

Temperature gain, in decibels. Compensates for sensor noise drift as the chip warms up. 0 means no correction is active. On long-running cameras in hot environments, this can creep up.


EV: the combined exposure value

ISP EV value: 3373
ISP EV value log2: 768077
ISP EV value us: 65277

EV is the ISP’s internal arithmetic — integration time multiplied by gain, boiled down to a single number. The raw EV value is in the ISP’s proprietary units; you can’t compare it across sensor models, but you can watch it on one camera over time. If EV climbs, the scene is getting darker and the ISP is compensating.

EV value us is integration time in microseconds — 65277 us is 65 ms of exposure plus ~1.7 ms of frame blanking, exactly the 15 FPS period (1 second / 15 = 66.7 ms). EV value log2 is the binary logarithm, used internally for exposure step calculations.

EV min int and EV min again are the minimum integration and analog gain the AE algorithm will use — the ISP won’t drop below these even in bright light. They are set by sensor tuning and rarely need changing.


White balance

ISP WB weighted rgain: 354
ISP WB weighted bgain: 402
ISP WB color temperature: 8224
ISP AWB Start rgain 220: bgain 156

WB weighted rgain/bgain are the red and blue channel gains the auto-white-balance algorithm is currently applying. Values above 256 mean that channel is being boosted (the ISP uses a fixed-point scale where 256 = 1.0x). Your scene has rgain 354 and bgain 402 — both above baseline, with blue boosted more than red — which tracks with the color temperature estimate of 8224K, a cool/blue-tinged light source like overcast daylight or a 6500K+ LED. A warm incandescent scene would show low bgain and high rgain.

AWB Start is the gain pair the algorithm initializes to on a fresh start — a fallback before it has enough frames to converge. If your colors look wrong immediately after boot but settle after a few seconds, this is the value being refined away.


Image tuning knobs

Saturation : 128
Sharpness : 128
Contrast : 128
Brightness : 128

These are the standard ISP image adjustments, all normalized to a baseline of 128. At 128, the ISP applies its default value for that sensor. Values below 128 reduce the effect; above 128 increase it. They map to the streamer’s image controls:

  • Saturation – color intensity. Below 128 desaturates toward monochrome; above 128 makes colors pop (at the risk of artifacts).
  • Sharpness – edge enhancement. A value too high produces halos around high-contrast edges.
  • Contrast – tonal range stretch. Low contrast looks flat and washed out; high contrast clips shadows and highlights.
  • Brightness – black-level offset. Shifts the entire histogram up or down without affecting contrast.

If you have been adjusting prudyntctl image settings or the web UI sliders, these numbers reflect the live result.


Anti-flicker and orientation

On T31 and later:

Antiflicker : 2
Mirror: Disable, Flip: Disable
Antiflicker nodes: 8: step : 300. 600. 900. 1200. 1500. 1800. 2100. 2400.

On T10/T20 the antiflicker line reads differently:

ISP Antiflicker : 60[0 means disable]

The T20 format is the mains frequency in Hz directly (50 or 60), while the T31 uses an enumerated index (0 = off, 1 = 50 Hz, 2 = 60 Hz). A reading of 0 means disabled on both platforms. If you see horizontal bands rolling through the image under fluorescent or LED lighting, this number is wrong for your region (North America is 60 Hz; most of Europe and Asia is 50 Hz).

The nodes line (T31+) lists the integration time steps (in lines) that avoid flicker at the configured frequency. The ISP’s auto-exposure algorithm snaps to the nearest node rather than using arbitrary integration times — this prevents the banding without forcing a fixed exposure. T10/T20 firmware handles this internally and does not expose the node list.

Mirror / Flip (T31+) control image orientation. Mirror flips horizontally; Flip flips vertically. Both disabled is the sensor’s native orientation. If your ceiling-mounted camera shows an upside-down image, you flip here rather than rotating in software. On T10/T20 these controls are not exposed in the proc file.


T10/T20 extras: noise reduction, LSC, CCM

The T10/T20 isp_info file exposes far more tuning detail than the T31 counterpart. If you are on an older camera, you will also see:

  • ISP Sinter (spatial interleaved noise reduction) — thresholds and strengths for horizontal and vertical noise filtering. Higher strength values trade sharpness for a cleaner image.
  • ISP Temper (temporal noise reduction) — thresholds for frame-to-frame averaging. Reduces sensor noise in static scenes without softening edges.
  • ISP Iridix — adaptive tone mapping strength. Controls how the ISP compresses high dynamic range into the output bit depth. Higher values preserve shadow and highlight detail but can look unnatural.
  • ISP LSC mesh (Lens Shading Correction) — compensates for vignetting and color shift toward the edges of the lens. Each mesh table (R, G, B) applies a per-channel gain map.
  • ISP Black level — per-channel black-point offsets (4 values for the Bayer pattern). Set during sensor calibration; incorrect values cause a color cast in dark areas.
  • ISP CCM (Color Correction Matrix) — a 3x3 matrix that transforms sensor RGB into display RGB. These nine values define the camera’s color rendering; the numbers look cryptic but the first row (R_R, R_G, R_B) determines red-channel mixing.
  • ISP Defect pixel — threshold and slope for dead-pixel concealment. The ISP detects and interpolates over stuck pixels before the encoder ever sees the frame.
  • ISP sharpening directional/undirectional — separates edge enhancement by orientation. Directional sharpening targets edges; undirectional is a gentler full-frame sharpen.

None of these have equivalents on T31’s isp-m0 output. The T31 ISP moved most tuning into opaque binary parameter files, so the proc interface is sparser.

Debug counters (T31+)

debug : ch0 done 5157,ip done 5169,0,0,0,0,0,0
debug1 : 24,0,841

These are driver-internal counters and appear only on T31 and later. ch0 done counts frames the ISP channel has processed; ip done counts interrupt completions. The two should track closely — if ch0 done lags behind, frames are being dropped between the sensor and the ISP output. The zero-filled fields are error counters (frame drops, buffer overruns) that stay zero on a healthy system.

Unless you are porting a new sensor driver, these debug lines are noise.


The frame source: isp-fs

If isp-m0 tells you what the sensor is doing, /proc/jz/isp/isp-fs tells you whether those frames are reaching the encoder. This is the DMA buffer pipeline between sensor output and encoder input.

Three numbers matter. Here is a healthy channel 0:

queue count: 3
ch0_pre_dequeue_drop is: 0
ch0_pre_dequeue_intc_ahead_cnt is: 0

And here is one in trouble:

queue count: 1
ch0_pre_dequeue_drop is: 12
ch0_pre_dequeue_intc_ahead_cnt is: 36

queue count is the number of DMA buffers. A 1080p main stream needs at least 2 — one being filled by the sensor, one being read by the encoder. queue count: 1 means the pipeline has no slack; any hiccup costs a frame.

ch0_pre_dequeue_drop is counts frames dropped because a buffer was not ready when the sensor interrupt fired. Zero is the only healthy reading.

ch0_pre_dequeue_intc_ahead_cnt is counts near-misses — interrupts that fired while a buffer was still in flight. A non-zero value means you are close to dropping frames.

The per-buffer block at the bottom shows each DMA buffer’s queue/dequeue counts. The numbers should differ by 0 or 1 across all buffers. A buffer with counts lagging its peers is stuck and the driver cannot release it.

Channel 1 (the sub stream, usually 640x360) gets its own section. If it is clean while channel 0 is dropping, the problem is specific to the main stream. If both are dirty, you have a system-wide stall.

Check isp-fs when FPS looks correct in isp-m0 but the RTSP stream stutters, or after changing resolution or enabling a second stream. Buffer pools are allocated at stream start and cannot grow at runtime — the only fix is reducing the load: lower resolution, drop the sub stream, or reduce FPS.


What you learned

  • isp-m0 (or isp_info on T10/T20) is a live dashboard, not a log. Every value reflects the hardware’s current state. Run it once, change a setting, run it again — the difference is the effect.
  • Integration time controls FPS. When Integration Time equals Max Integration Time, the sensor is at its speed floor. This is normal at night and the reason your 25 FPS config only delivers 15.
  • Day/Night and Custom Mode are two different layers (T31+). Day/Night switches the base tuning; Custom Mode loads an optional user-provided overlay on top. Both must be right for your tuning changes to land.
  • White balance gains tell you the light color. High bgain + low rgain = cool light; the reverse = warm light. The color temperature estimate puts a Kelvin number on it.
  • isp-fs catches what isp-m0 can’t see. FPS reads 25 but your stream stutters? Check isp-fs. Dropped frames and buffer starvation happen between the sensor and the encoder — and the buffer pool cannot grow at runtime, so the only fix is reducing the load.