System designTroubleshooting

Changing pixel format halves your frame rate: check linked attributes

A pixel-format write can reset a linked attribute like packet size and halve your frame rate. Re-set the attribute in code and the full rate returns.

LumaSpec Vision12 min read Share on LinkedIn

On this page 9 sections
  1. 01Why does a pixel-format change halve your frame rate?
  2. 02Which transport attributes reset when PixelFormat changes?
  3. 03How do you tell a genuine format cost from a stuck attribute?
  4. 04What does the GigE bandwidth arithmetic look like?
  5. 05How much frame rate does a small PacketSize cost?
  6. 06How do you restore the full rate without resetting the driver?
  7. 07When is a halved frame rate the correct answer?
  8. 08What do you check before the camera goes into production?
  9. 09Questions

You change the pixel format, change it back, and a camera that ran at 30 fps now delivers 15. Even the vendor's example program shows the low rate, and nothing short of a full configuration reset brings the speed back — which no production cell can afford. The sensor did not slow down and the link did not shrink: writing PixelFormat silently reset a linked transport attribute, usually PacketSize. Here is how to find the coupled attribute, re-set it in your acquisition code, and keep the full rate stable in production.

Why does a pixel-format change halve your frame rate?

In almost every case the format write itself is innocent: writing PixelFormat silently resets a linked transport attribute, usually PacketSize, and the camera keeps streaming with the smaller value even after you set the format back, which is why the observed rate drops by about half and stays there.

Every GenICam camera carries a machine-readable map of its features, and the firmware is free to recompute some of them when another one changes. Packet size is the classic case. A write to PixelFormat makes the camera re-evaluate its transport settings, and many models restore PacketSize to the Ethernet default of 1500 bytes. Your 9000-byte jumbo setting is gone. Setting the format back runs the same recompute again — from the default, not from your earlier value — so the small packet survives the round trip and the rate stays low through every program restart, while all your other settings read back exactly as you left them.

If the camera never reached its rated rate even before any format change, the cause is upstream of this. Work through Camera not reaching max frame rate: find the bottleneck first, because a stuck attribute is only one of several possible ceilings.

Which transport attributes reset when PixelFormat changes?

Look first at PacketSize, then at any inter-packet delay, then at the camera's bandwidth-reservation or throughput feature: on GigE Vision cameras these three sit in the transport layer, are writable at runtime, and are the ones firmware most often recomputes when PixelFormat changes.

Check them in that order:

  • PacketSize — the classic coupling. A 9000-byte jumbo value falls back to 1500, and the rate falls with the sixfold packet count quantified below.
  • Inter-packet delay — firmware that re-derives pacing from a bandwidth calculation can leave a delay sized for the old payload, throttling the new one even at the correct packet size.
  • Bandwidth or throughput reservation — cameras that advertise a per-stream bandwidth figure can carry the old, larger reservation into the new format.
  • PixelSize-dependent internal timing — a higher PixelSize can move the camera's internal timing, so the achievable rate range shifts beyond the byte-per-pixel ratio. That one is expected behaviour, not a fault.

On some models the format write also resets ROI or binning selectors, so read those back too. The order of writes matters, which is why the packet size belongs before acquisition start — the pattern in Set GigE camera packet size before starting acquisition.

Bring-up on an emulated camera can mislead the search: emulated devices fail on some format writes for reasons that never appear on real hardware, so see Camera emulator crashes after pixel format changes before blaming the camera.

How do you tell a genuine format cost from a stuck attribute?

Compute the frame size before you touch anything: width × height × bytes per pixel gives the payload, and a rate that falls with the byte-per-pixel ratio is genuine physics while one that stays low after you revert the format is a stuck attribute.

What you observe Verdict Test that confirms it
Rate falls by the byte-per-pixel ratio Genuine payload cost Frame-bytes arithmetic below
Rate stays low after you revert the format Stuck linked attribute Read PacketSize right after the write
Rate low since first power-up, format untouched General bottleneck The frame-rate bottleneck checklist
Incomplete frames, horizontal streaks Packet loss on the host The packet-loss checklist
frame bytes = width × height × bytes per pixel payload ceiling ≈ 118 MB/s on one gigabit port (1 Gbit/s ÷ 8, less ~6 % overhead) ceiling fps = payload ceiling ÷ frame bytes packets per frame = frame bytes ÷ PacketSize

Mono8 to Mono16 doubles frame bytes, so a fall from 9.8 fps to 4.9 fps on the same sensor is exactly the byte ratio — leave it alone. A camera back on Mono8 that still runs 4.5 fps is delivering 54 MB/s against a 118 MB/s ceiling: the link is loafing, and something is stuck. The arithmetic is the whole test, and it takes two minutes at the bench.

What does the GigE bandwidth arithmetic look like?

A gigabit link delivers about 118 MB/s after GigE Vision overhead, so a 4000 × 3000 Mono8 frame of 12 MB tops out near 9.8 fps and Mono16 halves that to about 4.9 fps — the arithmetic that separates a link ceiling from a stuck attribute.

Worked example, line by line:

  • Frame size: 4000 × 3000 = 12,000,000 pixels; at Mono8 (1 byte per pixel) that is 12 MB per frame.
  • Wire ceiling: 1 Gbit/s ÷ 8 = 125 MB/s; GigE Vision, UDP/IP and Ethernet headers consume roughly 6 %, leaving about 118 MB/s of payload.
  • Mono8 ceiling: 118 MB/s ÷ 12 MB ≈ 9.8 fps.
  • Mono16 ceiling: 118 MB/s ÷ 24 MB ≈ 4.9 fps.
  • The fault case: back on Mono8 but reading 4.5 fps. That is 12 MB × 4.5 = 54 MB/s, under half the ceiling — bandwidth is not the constraint, a stuck attribute is.

Production 12 MP GigE cameras sit exactly on this ceiling:

Area scan cameras12 MP GigE area scan camera, IMX226, 1/1.7" rolling shutter, 9 fps (LS-CMR-0053)LS-CMR-0053
Sensor format
1/1.7"
Lens mount
C-mount
Interface
GigE
Resolution
12 MP
$560.00View partBuild a system with it

Twelve-megabyte frames at 9 fps need 108 MB/s, about 92 % of the payload ceiling — the margin a designer leaves instead of running the link at its wire limit. Treat the same arithmetic as your acceptance test: a measured rate within about 10 % of ceiling ÷ frame bytes means the link is healthy, and a wider gap means look for a stuck attribute.

Larger sensors pull the ceiling down in proportion:

Area scan camerasHikrobot MV-CS200-10GC 20 MP Area Scan Camera, GigE, IMX183, Color, BasicMV-CS200-10GC
Sensor format
1"
Lens mount
C-mount
Interface
GigE
Resolution
16-25 MP
$739.00View partBuild a system with it

A 20 MB Mono8 frame tops out near 6 fps on one gigabit port. At that resolution class, GigE is a deliberate, budgeted choice — and 10GigE or CoaXPress exist precisely because the byte arithmetic says so.

How much frame rate does a small PacketSize cost?

At 9000-byte packets a 12 MB frame needs about 1333 packets; at 1500 bytes it needs 8000, a sixfold jump in per-packet interrupt and reassembly work, and a host that was already near its CPU limit starts dropping frames, which shows up as roughly half the frame rate.

At 9 fps those 12 MB frames produce about 12,000 packets per second at PacketSize 9000 and 72,000 at 1500. Every packet costs the receive path an interrupt or poll, a kernel buffer, header parsing and a copy into the SDK's frame buffer. One modern core absorbs 72,000 small packets per second in isolation; the same core that is also debayering, thresholding and talking to a PLC does not. When the receive path saturates, packets drop, the partial frame is discarded, and the observed rate falls until the load balances. On a host already carrying 60-80 % CPU on the receiving core, that balancing point lands near half rate — which is why the symptom presents so consistently.

The fix is not a faster CPU. Match the packet size to the path first: jumbo frames end to end — camera, adapter and every switch port at 9000 — collapse the packet count by six. Partial frames and horizontal streaks are the fingerprint of this loss, and the diagnosis lives in GigE Vision packet loss horizontal lines in live images. A camera that refuses a packet size the path cannot carry fails earlier and louder; the recovery is in GigE Vision test packet not received: fix packet size negotiation. A link that has fallen below gigabit has its own failure mode, covered in GigE camera packet size error when your link drops below gigabit.

How do you restore the full rate without resetting the driver?

Write the attributes back in your own code, in a fixed order, on every acquisition start: PixelFormat first, then PacketSize, then any packet delay, then read everything back and start acquisition — no driver reset, and the full rate returns every time.

  1. Write PixelFormat to the working value before anything else. It is the write that triggers the recompute, so let it run first and absorb the reset.
  2. Write PacketSize back to your target: 9000 when the whole path carries jumbo frames, otherwise 1500.
  3. Re-assert the inter-packet delay if the camera exposes one; leave it at the minimum unless a switch requires pacing.
  4. Read every value back and log it with a timestamp. A mismatch here is the fault, caught before it costs a shift.
  5. Start acquisition only after the read-back passes, then measure the achieved rate over at least 100 frames and compare it with the ceiling arithmetic.
  6. Run the whole block on every acquisition start, not only the first: power cycles and reconnects repeat the coupling.
# Illustrative pseudocode - call your SDK's real equivalents
write("PixelFormat", "Mono8")     # the write that triggers the reset
write("PacketSize", 9000)         # re-assert the transport target
if read("PixelFormat") != "Mono8" or read("PacketSize") != 9000:
    stop_and_log()                # fail loudly before acquisition
start_acquisition()

Then give the receive path room on the host: adapter MTU matched to PacketSize, receive buffers raised, and multi-camera streams on dedicated PCIe network cards rather than motherboard ports:

Frame grabbersHikrobot MV-GE2002P Dual-port PoE NIC, full height V2.0MV-GE2002P
Interface
GigE
Ports
2 ports
$249.00View part
Frame grabbersHikrobot MV-GT2104 Quad-port copper 10GbE NICMV-GT2104
Interface
10GigE
Ports
4 ports
$1,429.00View part

Two cameras stream and power over one dual-port PoE card; four GigE cameras, or a single 10GigE stream, fit a quad-port 10GbE card with headroom for the packet storm a 1500-byte path creates.

When is a halved frame rate the correct answer?

Half rate is the correct answer when the bytes per pixel genuinely double: Mono8 to Mono16 doubles the payload, a 24-bit colour format triples it against Mono8, and if exposure time approaches or exceeds the frame period the camera cannot hold the rate regardless of format or packet size.

  • Bytes per pixel doubled. Mono8 to Mono16 doubles the payload and the ceiling moves with the bytes, exactly as the formula predicts. Budget for it; do not debug it.
  • Exposure governs. At 9 fps the frame period is 111 ms. A 120 ms exposure caps the camera at 1000 ÷ 120 ≈ 8.3 fps no matter what the link could carry.
  • A shared link divided. Two cameras splitting one gigabit port share about 118 MB/s between them; each running near half its solo rate is arithmetic, not a fault.

A fourth case is subtler and still genuine: some sensors move their maximum rate when PixelSize changes, beyond what the byte ratio predicts, because readout timing changes with the format. Expect it and budget for it.

USB-side rate falls have their own causes, worked through in Camera FPS drops suddenly: exposure, USB link, bandwidth; the colour-format side of the trade is laid out in RGB camera frame rate limits: pixel format and exposure.

What do you check before the camera goes into production?

Before the camera ships, log PixelFormat, PacketSize and the achieved frame rate for a fixed test scene, compare the rate against the bandwidth ceiling, and make the start-up code assert on both attributes so a silent reset fails loudly instead of halving your throughput.

  • Assert the pair on every start. Write PixelFormat, re-assert PacketSize, read both back and fail loudly on a mismatch — the reset is silent and only a read-back catches it.
  • Measure 100 frames, not 10. Compare the mean against ceiling ÷ frame bytes; a gap wider than about 10 % means a stuck attribute or a lossy path.
  • Match MTUs end to end. Camera PacketSize, adapter MTU and every switch port at 9000, or everything at 1500; a mixed path throttles or fails negotiation.
  • Budget shared ports on paper. Sum the frame bytes per second of every camera on a port and keep it under about 118 MB/s before you wire anything.
  • Re-run the start-up log after firmware updates. The coupling map is firmware content and can change between versions.
  • Watch the receiving core. Packet loss climbs when reception and processing share one CPU core at full rate.

If you are sizing a camera or a host for a rate-critical line, start from the area scan cameras category or the camera finder, and carry the link budget into the camera configurator. Multi-camera receive paths belong on dedicated cards from the frame grabbers category and the accessories finder. More rate diagnostics sit on the systems topic page, and free expert support comes with every order — bring your frame-size arithmetic to the contact page and we will check it with you.

Questions

Do USB3 or CoaXPress cameras show the same linked-attribute behaviour?

Packet size is a writable transport feature on GigE Vision cameras, which is why the silent coupling shows up there. USB3 Vision streams over bulk transfers with no user-set packet size, and CoaXPress fixes the per-link rate, so there is no transport value for the firmware to reset. The payload arithmetic still applies on every interface: write the format first, read back what you set, then start acquisition.

What PacketSize should I set on a GigE camera?

Set 9000 when the camera, the adapter and every switch port on the path have jumbo frames enabled, and set the adapter's MTU to match. Fall back to 1500 if any hop keeps the standard MTU, and accept the higher CPU load or a lower frame rate to fit. The camera cannot exceed the smallest MTU on the path; an oversized value fails at the test-packet stage rather than silently.

Can a firmware update change which attributes are linked?

Yes. The coupling lives in the camera's feature description and its firmware, so an update can add, remove or change which features are recomputed together. After any update, re-run your start-up routine on a bench camera, compare the logged PacketSize and frame rate against the bandwidth arithmetic, and only then roll the firmware out to the line.

Does packet size change latency as well as frame rate?

Hardly. On a gigabit link, 9000 bytes of payload take about 72 µs of wire time and 1500 bytes take about 12 µs, but the total wire time for a frame is the same either way — the payload does not shrink. What changes is the per-packet software work: fewer, larger packets mean fewer interrupts and less reassembly, which is where the frame rate comes from.

How many frames should I measure before trusting the rate?

Judge the rate on at least 100 consecutive frames, taken after the camera has streamed continuously for a few seconds. Short samples catch the start-up transient rather than the steady state, and a single dropped frame early in a run skews a ten-frame average badly. Compare the measured mean against your bandwidth arithmetic — ceiling ÷ frame bytes — not against the data sheet alone.