Whole frames of solid green in a raw MIPI CSI-2 capture almost never mean a broken sensor. They mean the capture engine's programmed timing disagrees with the line timing the sensor actually puts on the lanes. This page is for engineers bringing up a board-level camera module or an FPGA video source on an embedded Linux capture board, where you own the driver, the mode table and the device tree. You will read the two v4l2-ctl outputs correctly, compute the line stride and payload budget, derive the pixel clock the mode really needs, and fix the driver so frames stay clean at full rate. The decision up front: if your mode's line stride had to be padded — 720 active pixels captured as 736 — suspect the width-and-clock pair in the driver before touching anything else.
What green frames tell you
Play the capture frame by frame before changing anything. In the bring-up behind this page, the recording held two green frames between every good frame — a fixed count, repeating for the whole clip. A deterministic pattern is a timing mismatch: the receiver loses sync at a rate set by how far its programmed clock drifts from the wire, so it fails the same way every time. Contrast the neighbours. Random speckle that moves from frame to frame is lane signal integrity. A colour cast on every intact frame is white balance or ISP calibration, a different fault entirely. Torn frames, half old and half new, are buffer handling — why three streaming buffers beat one covers that side. Whole-frame corruption with otherwise clean capture is the timing family, and the rest of this page is about it. For a wider pass through the same symptoms on another capture platform, the V4L2 CSI image artifact checklist is a good companion.
Likely causes, in order
| Rank | Cause | Signature | Test |
|---|---|---|---|
| 1 | Padded width paired with a fixed or mis-derived pixel clock | Fixed-count green frames; capture otherwise completes at full rate | Stride arithmetic (next section); compare the programmed clock with HTOT × VTOT × fps |
| 2 | Pixel-format interpretation (UYVY vs NV16 vs raw) | Frames present, colours or line phase scrambled | Dump raw and inspect; switch between the driver's enumerated formats |
| 3 | Lane signal integrity | Random speckle, errors that move frame to frame | Shorten or reroute the lane wiring; lower the lane rate and retest |
| 4 | Buffer or bandwidth starvation | Clean for minutes, then drops or a receiver timeout | Watch dmesg during a long continuous capture |
If frames time out entirely rather than corrupting, separate the I2C configuration path from the MIPI lanes first — separating I2C from MIPI failures works that in order. Slow-onset failures are their own family too; the CSI camera timeout walkthrough covers streams that run clean, then die.
Why the width pads from 720 to 736
A CSI mode table advertises the sensor's active line: 720 pixels here. The capture you get back is 736 wide. Neither v4l2-ctl output is lying — they answer different questions. --list-formats-ext runs VIDIOC_ENUM_FMT and lists the discrete modes the driver registered: the sensor's true 720×576 at 50 fps. -V runs VIDIOC_G_FMT and reports the buffer geometry after the driver's alignment: 736 pixels wide, Bytes per Line 1472, Size Image 847,872.
Capture engines write image lines to memory in fixed-size bursts, so the driver pads the width until the stride lands on that boundary. With UYVY at 2 bytes per pixel:
The boundary on this engine is 64 bytes: the padded stride clears it and the unpadded one does not, which is the whole story of the extra 16 pixels. They carry no image data — they are stride filler that a crop removes. Padding itself is normal and harmless. What breaks the capture is a driver that pads the buffer while its programmed timing still describes a different line. Where each of these values is produced on the way from sensor to host is mapped in the MIPI CSI-2 capture pipeline walkthrough.
The pixel clock your driver must program
Sensor drivers carry a pixel clock value per mode; the capture engine uses it to derive when each line and each frame should end. Vendor documentation calls this the sensor pixel clock, and the derivation is the same everywhere:
Worked example — the 576p50 raster with the classic ITU-R 601 totals:
- HTOT = 864 pixels (720 active + 144 horizontal blanking)
- VTOT = 625 lines (576 visible + 49 vertical blanking)
- pixel clock = 864 × 625 × 50 = 27,000,000 Hz = 27.0 MHz
- cross-check: a line arrives every 1 / (625 × 50) s = 32 µs, and 864 pixels / 27.0 MHz = 32 µs — consistent
Now the failure arithmetic. The driver in the failing build carried one fixed value, 182.4 MHz. Measured against the same 864-pixel totals, a receiver running that clock expects a line every 864 / 182.4 MHz = 4.7 µs while lines actually arrive every 32 µs — a 6.8× drift. A receiver that far ahead finishes its line and frame counts early, hits a resync, and writes default-pattern frames at a steady rate: the two green frames between good ones. Your sensor's blanking registers need not equal 864 and 625 — read its timing table and apply the formula per mode. What never works is one fixed default across modes.
The lane budget is a separate number. The padded frame is 1472 × 576 = 847,872 bytes, so 50 fps moves 847,872 × 50 = 42,393,600 bytes/s ≈ 42.4 MB/s ≈ 339 Mbit/s of payload. CSI-2 spends 10 wire bits per byte, so four lanes carry 339 / 4 × 10 / 8 ≈ 106 Mbit/s each before packet overhead and blanking; plan roughly 120 to 130 Mbit/s per lane as a working margin. The full lane arithmetic, with the same totals method, is in MIPI CSI-2 frame rate estimation: lanes and data rate.
Why one mode failed and two passed
The same bring-up ran three modes, and only the padded one corrupted:
| Mode | Active width | Stride | Payload | Result |
|---|---|---|---|---|
| 720×576, 50 fps, 4 lanes | 720 px | padded: 1440 → 1472 B | 42.4 MB/s | fixed-count green frames |
| 640×480, 89 fps, 4 lanes | 640 px | 1280 B = 64 × 20 | 54.7 MB/s | clean |
| 736×288, 50 fps, 2 lanes | 736 px | 1472 B = 64 × 23 | 21.2 MB/s | clean |
Payload arithmetic: 1280 × 480 × 89 = 54,681,600 bytes/s ≈ 54.7 MB/s for the 640×480 mode; 1472 × 288 × 50 = 21,196,800 bytes/s ≈ 21.2 MB/s for the reduced mode. The failing mode draws the least of the three — throughput was never the discriminator; the width was. Both clean modes had strides that already matched the burst boundary, so buffer geometry and wire timing described the same line. Only the padded mode forced two line widths to coexist, and with one fixed clock the driver could not serve both. The reduced 736×288 workaround succeeded for the same reason: its width came back aligned, so the symptom vanished while the clock stayed wrong.
Fix the driver, in order
- Read the sensor's true totals from its datasheet timing entry or register configuration: HTOT (active + HSYNC + HFP + HBP) and VTOT (active + vertical blanking). For the raster above, 864 and 625.
- Compute pixel clock = HTOT × VTOT × frame rate for every mode — 864 × 625 × 50 = 27.0 MHz here — and program the per-mode result. Delete any fixed default such as 182.4 MHz.
- Make one width authoritative. Either the sensor sends 736-pixel lines and every field of the mode says 736, or it sends 720 and the capture engine pads internally while timing stays keyed to the sensor's totals. The failing driver advertised 720, padded to 736, and timed for neither.
- Rebuild the driver and the device-tree mode entries that repeat it, reload, and re-check
v4l2-ctl -V: width, Bytes per Line and Size Image must form one consistent set — 736 / 1472 / 847,872 for this capture. - Prove it at rate: dump ten raw frames and step through them, then run several minutes of continuous capture with dmesg open. A timing error shows within seconds; a marginal one shows as occasional drops under load.
When the usual answer is wrong
A green cast on every intact frame is colour, not capture timing: white balance or a missing ISP calibration, fixed in the ISP rather than the driver. The blue-tint board camera case draws that boundary. Short-frame errors — the receiver complains about geometry instead of rendering green — mean the sensor's output mode and the driver's table disagree outright; matching the mode to the sensor output is that fault. A GigE or USB3 camera has no user-programmed pixel clock at all: it generates its own timing and ships finished frames, so whole green frames cannot occur; the wrong number there appears as a frame rate that drops at longer exposures. Finished area scan cameras and USB3 board-level camera modules are the short path when you no longer want to own a driver, and fixed-function CSI sources such as stereo and structured-light 3D sensors program their lane timing in firmware, so their depth corruption follows its own diagnostics. Why a green tint together with dropped frames is yet another fault, on a finished industrial camera, is laid out in green tint and dropped frames walkthrough.
Next step
If the capture is yours to debug, work the causes table top to bottom and fix the clock before touching hardware. If the capture is yours to specify, finished modules remove this class of fault entirely: the camera finder filters by interface, mount and shutter, and the camera configurator builds a matched set around your board. For the selection maths before you order, the board-level camera selection guide is the companion read, and the rest of the capture-path debugging lives on the systems topic page.
Compact cameras to build in
120 models · from $179.00Questions
Why does v4l2-ctl -V report 736×576 when the mode list says 720×576?
The two outputs come from different ioctls. --list-formats-ext (VIDIOC_ENUM_FMT) lists the discrete modes the sensor driver registered — the sensor's true 720×576. -V (VIDIOC_G_FMT) reports the capture buffer after alignment: 736 pixels wide, a 1472-byte stride, 847,872 bytes per frame. Neither value is wrong. The fault appears only when the driver's programmed pixel clock still describes the unpadded 720-pixel line.
How much bandwidth does the 736-pixel padding waste?
16 pixels at 2 bytes each is 32 bytes of filler per line. Over 576 lines at 50 fps that is 32 × 576 × 50 = 921,600 bytes/s ≈ 0.9 MB/s, about 2.2 percent of the 42.4 MB/s the active image needs. On a four-lane CSI-2 link that is negligible; a mis-timed receiver that corrupts frames costs far more than aligned strides ever will.
Can I fix it by setting the width back to 720 with v4l2-ctl?
No. --set-fmt-video is a request to the driver, and the driver's alignment logic pads the request back to 736 before capture starts. The sensor also keeps sending its own line length regardless of what the host asks for. The width and the clock have to agree inside the driver's mode table; no host-side ioctl can repair a mismatch that lives there.
Is there a sample driver for interlaced 720×576 CSI capture?
Most embedded board-support packages register progressive modes only in their sample sensor drivers, because the capture engine writes progressive buffers. The pattern to copy lives in the vendor's HDMI-to-CSI bridge driver: it detects an interlaced timing and doubles the reported height, so the capture engine writes one progressive frame per pair of fields. Expect to adapt that bridge pattern rather than find a ready 576i sensor example.
Does this green-frame failure apply to GigE or USB3 cameras?
No. GigE and USB3 industrial cameras generate their own sensor timing and deliver complete frames over a packet link, so there is no user-programmed pixel clock to get wrong. The analogous failures are bandwidth limits — a GigE link slows at long exposures — and host-side buffer starvation, which shows as dropped or torn frames rather than whole green ones.