System designHow-to

Switch GigE camera resolution without reconnecting

Switch a GigE camera's resolution without reconnecting: write the mode, re-read PayloadSize, drain the stream queue and requeue new-size buffers in place.

LumaSpec Vision9 min read Share on LinkedIn

On this page 9 sections
  1. 01Why a reconnect costs seconds and the switch itself does not
  2. 02What you need
  3. 03Switch resolution in place: the sequence
  4. 04Size the modes before you switch: the bandwidth math
  5. 05Standard Width and Height: stop acquisition, not the connection
  6. 06Prove the switch took
  7. 07Common mistakes
  8. 08When a reconnect is the right answer
  9. 09Questions

Switching a GigE camera's resolution mid-run looks like it demands a full reconnect: stop acquisition, destroy the device and stream objects, rebuild everything, wait for the camera to answer. That loop costs seconds every time, and it is not necessary. The control session and the stream can stay open; the only things that must change are the mode value, the payload size your buffers are allocated at, and what is sitting in the stream queue. This guide gives the in-place sequence, the bandwidth math that decides which modes three cameras can stream at once, and the checks that prove the switch took.

Why a reconnect costs seconds and the switch itself does not

A resolution change touches exactly three things: the camera's active readout mode, the byte size of one frame (PayloadSize), and the buffers waiting in the stream queue. Nothing else has to move.

The expensive path rebuilds layers that never needed to move. Destroying the device object drops the GVCP control session; destroying the stream object drops the GVSP association; re-creating them re-runs discovery, re-downloads the camera's GenICam XML description, renegotiates the stream and re-primes an empty buffer queue. That handshake chain is where the 2-3 seconds goes. The mode write itself is one register transaction on the control link.

A rebuilt device also forgets your configuration. Code that reconnects must re-apply pixel format, exposure time and gain after every switch; the in-place path never touches them.

What you need

  • A GigE Vision camera whose GenICam features you can write: a preset-mode selector register, or the standard Width and Height features.
  • PayloadSize, readable as an integer feature — the byte count every buffer must match.
  • A GenICam library that keeps the device and the stream as separate objects. The function names below are Aravis; other GenICam stacks expose the same operations under other names.
  • The Enumeration entries of your camera's resolution selector, read once from its GenICam XML. Six preset modes plus a custom entry is the typical shape of a register-based camera, each entry pairing a name with an integer value.

Any GigE area scan camera exposes PayloadSize over GenICam, so the sequence below transfers across the family unchanged:

Area scan camerasHikrobot MV-CU020-90GC 2.5 MP Area Scan Camera, GigE, GMAX4002, ColorMV-CU020-90GC
Sensor format
1/1.7"
Lens mount
C-mount
$309.00View part
Area scan camerasHikrobot MV-CS200-10GC 20 MP Area Scan Camera, GigE, IMX183, Color, BasicMV-CS200-10GC
Sensor format
1"
Lens mount
C-mount
$739.00View part
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
$560.00View part
Area scan camerasHikrobot MV-CT0MG0060/R/NN/NN 6 MP Area Scan Camera, 3rd Gen., GigE, Mono, BASEMV-CT0MG0060/R/NN/NN
Sensor format
1/1.8"
Lens mount
C-mount
$909.00View part

Switch resolution in place: the sequence

The whole switch is a handful of calls between the mode write and the requeue:

  1. Read the modes once, at connect. Take each Enumeration entry of the resolution selector from the GenICam XML with its integer value. On a standard camera, read the Width and Height minimum, maximum and Increment instead. Do not hardcode either one.
  2. Write the new mode while the stream runs. On a camera whose preset register latches immediately — the ResolutionSelReg type — write the integer mid-stream, with no AcquisitionStop and no AcquisitionStart. If the stack refuses the write while acquisition is active, use the stop-first path further down.
  3. Re-read PayloadSize. The value that was correct at 1600 × 1200 is wrong the moment the mode changes. Every buffer pushed from here on must match the new number.
  4. Drain the queue. Pop buffers until a pop returns nothing, and release each one: a popped buffer belongs to your code, so dropping the pointer without unreferencing it leaks one allocation per switch. Drain with a zero timeout — the timeout argument is in microseconds, and the 100000 you use while waiting for frames means a 100 ms stall per empty pop. The same discipline applies when stopping camera acquisition with busy buffers for any reason.
  5. Push fresh buffers at the new payload. Ten to twenty buffers is the usual working range: at 30 fps that covers 0.3-0.7 s of scheduling jitter. Allocate each at the payload of your largest mode, and a down-switch needs no reallocation at all.
  6. Drop the transition frames. One or two completions can still arrive at the old size. Check each buffer's status and byte count against the new PayloadSize and discard what does not match.
  7. Map the frame with the new dimensions. The image container takes the new width and height at the same moment the camera does, or the picture shears.
ArvDevice *device;    /* existing control session, left open */
ArvStream *stream;    /* existing stream, left open */
int mode_value = 5;   /* from the Enumeration entries, not hardcoded */
guint payload_new = 0;
ArvBuffer *buffer = NULL;

arv_device_set_integer_feature_value (device, "ResolutionSelReg", mode_value);
payload_new = arv_device_get_integer_feature_value (device, "PayloadSize");

while ((buffer = arv_stream_timeout_pop_buffer (stream, 0)) != NULL)
    g_object_unref (buffer);    /* drain: popped buffers belong to you */

for (int i = 0; i < 10; i++)
    arv_stream_push_buffer (stream, arv_buffer_new (payload_new, NULL));

The switch is proven when arv_buffer_get_status on the next popped buffer returns ARV_BUFFER_STATUS_SUCCESS and its size equals payload_new. At 30 fps the first clean frame lands within one or two frame periods, 33 to 67 ms, against the seconds the rebuild path takes.

Size the modes before you switch: the bandwidth math

Running three cameras at mixed sizes is arithmetic, not preference. One frame costs width × height × bytes per pixel, and a camera's link load is that payload times the frame rate:

payload = width × height × bytes per pixel link load (Mbps) = payload × frame rate × 8 ÷ 1,000,000

Mono 8 packs one byte per pixel. At 30 fps:

  • 1600 × 1200: 1600 × 1200 × 1 B = 1,920,000 B per frame; × 30 fps = 57.6 MB/s; × 8 = 460.8 Mbps per camera.
  • 320 × 240: 320 × 240 × 1 B = 76,800 B per frame; × 30 fps = 2.304 MB/s = 18.4 Mbps.
  • Three full-size cameras: 3 × 460.8 Mbps = 1,382.4 Mbps, past the practical ceiling of a 1 GbE link — about 940 Mbps — so frames drop even on dedicated ports feeding one host adapter.
  • One full, two small, the picture-in-picture mix: 460.8 + 18.4 + 18.4 = 497.6 Mbps, roughly half that ceiling, about 1.9× headroom for other traffic.

The decision follows: inspect on the full-resolution stream, run the two overview cameras at the small mode, and use the in-place switch to move a camera between roles without dropping its session. If a smaller mode raises the frame rate your camera allows, redo the arithmetic at the new rate before trusting the headroom.

The same math sets GigE's own ceiling. A 20 MP Mono 8 frame is about 20 MB, so a 940 Mbps link delivers 940 ÷ 8 ÷ 20 ≈ 6 full frames per second; a 10 Gigabit link lifts that toward 60. Cameras built for that class of stream keep the same GenICam feature set over the faster link:

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

Standard Width and Height: stop acquisition, not the connection

Cameras without a preset register expose resolution as Width and Height, and GenICam marks region features as not writable while acquisition runs. The answer is one command, not a reconnect: execute AcquisitionStop, write the new Width and Height honoring the Increment, re-read PayloadSize, drain and re-push as above, then AcquisitionStart. You lose a frame or two — not the control session, not the XML download, not your exposure and gain. A camera in continuous acquisition mode for live image loops resumes exactly where it stopped.

Prove the switch took

Three checks, in order:

  • Read the register back. A selector that latches immediately returns the new value right after the write. If the read-back still shows the old value while streaming, the camera applies the mode only at the next start: move the write between AcquisitionStop and AcquisitionStart.
  • Check the first clean frame. Status equal to success, byte count equal to the new PayloadSize, and width and height taken from the new mode rather than a constant.
  • Count mismatches for a minute. One or two during the transition is the drain working. A steady count means your buffer size and the camera's PayloadSize have diverged; re-read it.

Common mistakes

  • Reusing the old payload size. Every buffer pushed at the old value fails against the new frame size. Re-read PayloadSize after every write; never carry it across modes.
  • Skipping the drain. An old-size frame in a new-size buffer gives a sheared picture: rows shifted, garbage along the edge.
  • Leaking the drained buffers. Pop hands ownership to you; unref or reuse every buffer you do not requeue.
  • Hardcoding mode integers and sizes. Preset values live in the camera's GenICam XML, and sensor mode lists differ by family — how sensor resolution modes work explains why the list looks the way it does.
  • Restarting into a triggered mode. After a stop/start, a camera left in hardware-triggered acquisition delivers one frame and waits. Frames stopping after exactly one is the hardware trigger and its acquisition mode, not your resolution change.
  • Sizing downstream code to the old mode. ROIs, lookup tables and picture-in-picture positions must switch with the camera, in the same code path as the buffers.

When a reconnect is the right answer

  • Packet size changes. The GVSP packet size is settled when the stream is created, so changing it mid-run means rebuilding the stream. Set it before you start, not during.
  • The register will not latch mid-stream and the stop/start path is refused too. Rare, but then take the rebuild and budget its multi-second cost.
  • Persistent transport errors. Timeouts and corrupt frames that survive a drain point at packets, buffers or MTU rather than the mode change; the GigE Vision stream timeout checks cover that diagnosis.

The rule: a resolution or pixel-format change stays in place — direct write or stop-first; a transport-level change is the only reason to rebuild. To size a three-camera cell from scratch, the camera finder filters by interface, resolution and shutter, and the camera configurator pairs cameras with lenses and cables; the systems topic page collects the rest of the stream-handling guides, and questions about a specific cell go to our engineers through the contact page.

Questions

Does the frame rate change when I switch to a smaller resolution?

Usually upward. Smaller frames move fewer bytes, so many cameras raise their maximum frame rate until another limit binds — most often exposure time. After a switch, read the advertised frame-rate range again instead of assuming the old value: a 30 fps setting at 1600 × 1200 may sit well below what a 320 × 240 mode can do. Exposure time caps the rate in every mode, so shorten it if you need the higher ceiling.

Can I change PixelFormat with the same in-place sequence?

Yes. The two rules are identical: write the format only when the camera accepts it while acquisition runs, and rebuild buffers around the new PayloadSize. Mono 8 packs one byte per pixel; 10- and 12-bit formats move more bytes per pixel or pack several pixels together, so never carry the old payload across a format change. Re-read PayloadSize, drain the queue, and push buffers at the new size.

Why do buffers fail with a size mismatch right after the switch?

GVSP packets of the old frame size are still in flight when the new mode takes effect, and old-size buffers left in the queue carry the previous payload. The camera fills a buffer that no longer matches, so the completion comes back flagged instead of rendered. That should last one or two frames; if it continues past a dozen, your buffer size and the camera's PayloadSize have diverged.

Do I have to re-apply exposure and gain after an in-place switch?

No. The control session stays open, so every feature you wrote keeps its value. That is one of the main gains over the rebuild path: re-creating the device drops the session, and the camera falls back to power-on defaults until you write the settings again. If your code re-applies exposure, gain and pixel format on every connect, the in-place switch simply skips that work.

Does every GigE camera switch resolution this way?

The sequence is the same; the feature that selects the resolution differs. Many cameras expose standard Width and Height features that are writable only while acquisition is stopped, so they take the stop-first path. Others provide a preset-mode register that latches immediately during streaming. Read the feature list from the camera's GenICam XML once at connect time and you will know which path applies — both avoid the full rebuild.