Cameras & sensorsTroubleshooting

Identical lines between consecutive frames: stale buffer or readout

Identical lines between consecutive frames at 200 fps mean a 311 MB/s stream. Tell a stale grab buffer from a sensor fault with timestamp and bandwidth tests.

LumaSpec Vision10 min read Share on LinkedIn

On this page 10 sections
  1. 01The numbers behind a 5 ms frame
  2. 02Three signatures, three causes
  3. 03Test 1: the timestamp decides it
  4. 04Test 2: the copy test, which fixes most cases
  5. 05Test 3: audit the link when timestamps differ
  6. 06Test 4: exposure and frame-rate readback
  7. 07When it really is the sensor
  8. 08When the answer is a faster interface
  9. 09Checklist before you change anything else
  10. 10Questions

You page through a recording from a 200 fps line and find blocks of lines that repeat, pixel for pixel, from one frame into the next. The first suspicion is the sensor; the second is exposure or a bad cable. Both are usually wrong. At high frame rates, identical lines between consecutive frames come almost always from buffer handling in the grab loop, and next from a saturated link — and one timestamp read settles which. The worked example here is a 1440 × 1080 Mono8 stream at 200 fps over USB3: a 5 ms frame period, 1.56 MB per frame, 311 MB/s on the cable. The same tests apply to any GenICam-based SDK on GigE, USB3 or 10GigE; only the payload arithmetic changes.

The numbers behind a 5 ms frame

Two rates govern everything you will test.

payload per frame = width × height × bytes per pixel data rate = payload per frame × frame rate occupancy = data rate / sustained link rate

For the example stream:

  • Payload: 1440 px × 1080 px × 1 B = 1,555,200 B ≈ 1.56 MB per frame.
  • Frame period: 1 / 200 s = 5 ms, which leaves 5 ms / 1080 ≈ 4.6 µs per line.
  • Data rate: 1,555,200 B × 200 = 311 MB/s ≈ 2.5 Gbit/s of payload.
  • Link budget: USB 3.0 signals at 5 Gbit/s; after 8b/10b coding, 4 Gbit/s (500 MB/s) of raw data remains, and a healthy controller sustains roughly 340-380 MB/s of image payload once protocol overhead is paid. 311 MB/s is 62% of the raw ceiling but 82-91% of what ports deliver in practice.
  • Pixel format moves the total quickly: 10-bit packed gives 1,555,200 px × 1.25 B = 1,944,000 B per frame, 389 MB/s at 200 fps; unpacked 16-bit doubles the Mono8 rate to 622 MB/s. Neither fits a USB3 link, and the symptom there is incomplete frames rather than clean duplicates.
  • Exposure shares the 5 ms period with readout, so hold ExposureTime at or below 4 ms as the starting point and let the camera's reported achievable frame rate be the authority. When exposure or bandwidth clips the rate instead, frames arrive late or drop out — a different defect, and the camera FPS drops suddenly: exposure, USB link, bandwidth guide covers it.

Recompute those lines for your own width, format and frame rate before touching hardware.

Three signatures, three causes

"Identical lines between consecutive frames" describes three distinct defects. Sort what you see into one of these before running any test:

  1. Full-frame duplicates. Frame N and frame N+1 are pixel-identical across all 1080 lines: one exposure was delivered twice.
  2. Torn boundaries. A block of lines at the seam belongs to an older exposure — the top of frame N+1 finishes frame N. A buffer was recycled while you were still reading it. That defect has its own walkthrough at torn frames in a camera callback: copy the buffer before you queue it.
  3. Stale content behind fresh counters. Pixels repeat while the target moves and the frame index advances: data inside the delivery path was reused after a partial or failed transfer.

One camera produces one sequential stream, so "concurrent" in a defect report just means adjacent frames in that stream.

Test 1: the timestamp decides it

Chunk data settles the question fastest, and every GenICam camera exposes it under the same feature names:

  1. Turn chunk mode on: ChunkModeActive = true.
  2. Select the timestamp chunk: ChunkSelector = Timestamp, then ChunkEnable = true.
  3. Read the per-frame value — the SFNC names it ChunkTimestamp — and log it with your own frame index before changing any other setting.
  4. Compare the timestamps of the flagged pairs.

Then read the outcome directly:

  • Same timestamp on both frames. The sensor exposed once and your pipeline handed the same buffer back twice. Sensor, cable and bandwidth are innocent; go to the copy test.
  • Different timestamps. Two distinct exposures happened. A genuinely static scene returns identical pixels correctly, so wave a hand in front of the lens and repeat the run; with a moving target and still-identical pixels, audit the link.

The camera latches that value at a defined point of its own cycle — exposure end on most models — which matters when you compare it against encoder or PLC time. Chunk data timestamp: camera time at exposure end and how to latch it covers the latch point, and camera buffer timestamp latency: interpret frame timing covers host arrival time, which is a different clock and must not be mixed with the chunk value.

Test 2: the copy test, which fixes most cases

The dominant cause of full-frame duplicates is buffer ownership: your code keeps the pointer the SDK handed over, the SDK recycles that memory for the next frame, and the image you read later contains old lines. A retrieve that is never followed by a release, or a result held alive across loop iterations, produces the same signature.

Copying costs almost nothing at this data rate:

  • 1,555,200 B × 2 (read plus write) over a single DDR4-3200 channel's 25.6 GB/s theoretical ≈ 121 µs; call it 150-400 µs in practice, under 8% of the 5 ms frame budget.
  • Sustained, 200 copies per second is 311 MB/s of memory traffic, far below what a modern host moves.
  • Make the copy inside the callback, before it returns.
  • Retrieve and release every queued result on each iteration; never let a result survive the iteration that read it.

If the duplicates disappear, you are done. If identical lines persist with different timestamps and a moving target, buffer ownership was one of two problems and the link is the other — continue to the link audit. The same ownership rule applies when you wrap SDK data in your own image classes: stereo frames saved wrong: copy Mat data from the SDK buffer shows the failure for wrapped Mat objects, and reuse image buffers instead of per-frame allocation covers the recycling discipline around them.

Different timestamps with repeating pixels point at the delivery path, and at 311 MB/s you have only 8-18% headroom over a typical host's sustained payload, so ordinary stalls are enough:

  1. Give the camera a dedicated port on its own controller: no hub, no front-panel header (those route through board-level wiring and often share one controller), and a short certified cable.
  2. Disable USB selective suspend for that controller in the OS power plan; a suspended controller misses a frame's worth of empty-buffer requests in one event.
  3. Read the SDK's transfer statistics if it exposes resend or error counters — before and after a test run. A rising resend count convicts the link.
  4. Buy headroom as a controlled test: cut AcquisitionFrameRate to 180 fps, and the payload drops to 1,555,200 B × 180 ≈ 280 MB/s. Defects that vanish at 180 fps and return at 200 fps convict the link without touching the code.

Incomplete or torn transfers have a diagnostic path of their own in USB3 Vision transfer errors: diagnose bandwidth and buffers, and frames that arrive late rather than damaged are covered in camera image latency: diagnose and reduce stale frames.

Test 4: exposure and frame-rate readback

Two configuration faults produce confusion that looks like repeats, though not pixel-identical duplicates by themselves:

  • Exposure above roughly 4 ms at a 200 fps target leaves too little readout time, and the camera delivers fewer frames than you asked for. A recorder that pairs frames to process positions by index then shows stale-looking matches.
  • A saved configuration that never took effect shows up as a frame rate differing from the set value. Verify the readback after startup; camera startup frame rate: verify saved settings and readback walks that check.

Readout order itself caps the rate on some sensors before exposure does; 4x4 binning vs 2x2: sensor readout decides your frame rate shows how the readout mode sets that ceiling.

When it really is the sensor

A failing readout looks different from a duplicate: black or displaced groups of lines, smear trailing out of bright areas, a fixed pattern sitting at the same rows in every frame regardless of scene — and it reproduces at 10 fps as readily as at 200, on a second host, with the copy fix in place.

So commit by elimination. Identical lines sharing one timestamp: not the sensor. Identical lines with different timestamps that survive the copy test, a 180 fps link audit and a run on a second computer: escalate through the vendor's documented support channel with your timestamp log attached, and leave the housing closed — opening or reflashing a camera as a diagnostic destroys the evidence and is not a documented procedure.

When the answer is a faster interface

If the pixel format genuinely needs more than a USB3 port sustains — 16-bit color at high frame rates, for instance — change the link, not the code. GigE carries about 118 MB/s of payload with jumbo frames, 10GigE about 1,000 MB/s (roughly three times a healthy USB3 port), and CoaXPress more still. The area scan cameras catalog spans all of these interfaces, and the camera finder filters by interface, resolution and shutter.

CamerasArea scan cameras

GigE, USB3, 10GigE and CoaXPress

1,287 models · from $149.00

The MV-CH250-25TC-F-NF is an example of the step: a 25 MP APS-H camera with a global shutter on 10GigE and an F-mount, and the GenICam feature names you have been debugging carry over unchanged.

Area scan camerasHikrobot MV-CH250-25TC-F-NF 25 MP 10GigE area scan camera, PYTHON25K, Color, F-mount, With fanMV-CH250-25TC-F-NF
Sensor format
APS-H
Lens mount
F-mount
Interface
10GigE
Resolution
Over 25 MP
$7,349.00 · quotedView and quoteBuild a system with it

Checklist before you change anything else

Work in this order; the first two items cost nothing and settle most cases.

  1. Log ChunkTimestamp with every frame before touching any setting.
  2. Copy each grab result before releasing it, and retrieve-and-release every result in the queue on each iteration.
  3. Set MaxNumBuffer to around 16: 16 × 1,555,200 B ≈ 25 MB, about 80 ms of cover at a 5 ms frame period. A pool of thousands only hides latency and delays diagnosis.
  4. Hold ExposureTime at or below 4 ms and confirm the achievable-rate readback equals the set 200 fps.
  5. Dedicate the port: own controller, no hub, short certified cable, selective suspend off.
  6. Keep occupancy at or below about 80% of your measured sustained rate, and recompute for the pixel format actually enabled — 10-bit packed already adds 25% over Mono8.

Keep the timestamp column in production logging. If the audit ends at "the link cannot carry this payload", the camera configurator steps through interface, resolution and lens in one pass, the machine-vision cameras topic gathers the surrounding guides, and the team answers specific payload arithmetic through the contact page.

Questions

Can identical consecutive frames be normal?

Yes, when the scene does not change between the two exposures. Two valid, different exposures of an unmoving part return identical pixels, which is correct behaviour, not a fault. Wave a hand or fan the target while recording: if the lines then differ, the imaging chain is healthy. The timestamp test still settles it — identical pixels with different timestamps and a moving target is the only combination worth chasing.

How many buffers should MaxNumBuffer be set to?

For the 1.56 MB Mono8 stream in the example, 16 buffers is a good default: 16 × 1,555,200 B ≈ 25 MB of RAM, about 80 ms of cover at a 5 ms frame period. Fewer risks losing frames during processing spikes; hundreds hide latency instead of fixing it, and a pool of 2000 holds roughly 3.1 GB. Size the pool from your worst-case processing jitter in milliseconds, not from a large round number.

Why does the duplicate problem appear only at high frame rates?

The failure window scales with the frame period. At 200 fps each 1.56 MB frame must be consumed within 5 ms; at 30 fps the same code has 33 ms. A copy or conversion that occasionally spikes past the deadline lets the SDK recycle a buffer early, so the next retrieve hands back stale content. As a test, drop the rate below 100 fps: if duplicates vanish, your processing time overruns the frame period.

Does USB3 packet loss damage the camera or only the image?

Only the image. USB3 Vision covers short losses with packet resends; when the host repeatedly fails to supply empty buffers, frames arrive incomplete or late and the SDK reports or drops them. Nothing is written to the sensor, so no hardware damage accumulates. The remedy is bandwidth headroom — a dedicated controller, no hub, a short certified cable — not retry tuning.

How is this different from torn frames in a callback?

A torn frame mixes two exposures inside one image: the upper rows show the scene as it was and the lower rows as it became, because the SDK recycled the single buffer you were still reading. A duplicate delivers one exposure as two whole frames, which the timestamp test exposes immediately. Tearing calls for a copy inside the callback; duplicates call for releasing every grab result.