System designTroubleshooting

GigE Vision camera stream fails on Linux: update and isolate first

A GigE camera on Linux that lists but fails to stream, or streams only after another utility ran first: the causes, the tests, and the fix.

LumaSpec Vision11 min read Share on LinkedIn

On this page 9 sections
  1. 01The symptom: it lists, it reads, it will not stream
  2. 02Cause 1: another client owns the control session
  3. 03Cause 2: the client library predates the camera
  4. 04Cause 3: settings that revert to the camera's defaults
  5. 05Cause 4: the network path drops stream packets
  6. 06Worked example: does 75 fps of 1.3 MP fit on one GigE link?
  7. 07The fix sequence, in order
  8. 08Prevention: pin the version, own the camera, own the subnet
  9. 09Questions

You enumerate the camera, read its features, maybe even set a pixel format — and stream creation still fails. Or the image appears, but only after the maker's own utility has connected and disconnected first. This page is for engineers driving GigE Vision cameras from a Linux PC through a GenICam client such as Aravis or an SDK. It gives the four causes behind that pattern in the order they usually turn out to be the one, a test for each, and the fix — starting with the two that cost nothing: one client at a time, and a client library matched to the camera's generation.

The symptom: it lists, it reads, it will not stream

Three signatures travel together in this failure. Enumeration works: the camera answers discovery, so the link, the IP set-up and the firmware are alive. Control mostly works: feature reads come back, and writes seem to take. The stream does not: the client dies at stream creation, or it succeeds only once another tool has connected and disconnected. The subtle signature is a value that falls back on its own — exposure returns to 5,000 µs, the ROI snaps back to 64 × 32 pixels at offset (0, 0). Those are the camera's startup values, which tells you the write never stuck.

What you see Most likely cause First test
Stream creation fails every time Client library older than the camera Upgrade the library, re-test
Streams only after another utility ran first Contested or stale control session One client, power-cycle, re-test
Writes revert to startup values No live control session, or XML parse failure Write while connected, read back after reconnecting
Stream starts, then tears under load Packet loss: MTU mismatch or small buffers Match packet size end-to-end, raise buffers

A camera missing from the list altogether is a different failure — see ping works, zero cameras: GigE transport layer not loaded. A camera that opens but shows no picture for a plugin reason is covered in camera connected but viewer shows no video: GStreamer missing plugins. This page is the in-between case: control lives, the stream does not.

Cause 1: another client owns the control session

The GigE Vision standard allows one controlling connection per camera — a primary controller, with at most a secondary standing by — never two programs writing at once. The session lives only while its owner answers the camera's heartbeat, a keep-alive the camera checks every few seconds. A viewer left open, an SDK service in the background, a crashed process or a robot controller's client all hold the camera long after you think they have stopped.

Test: stop every acquisition program and background service, power-cycle the camera, and start exactly one client. If the stream then works, you had a session contest, not a broken camera. The same mechanism with a clearer error message is GigE camera open fails in a second tool: exclusive control.

The ritual is the tell. When the maker's utility connects, it runs a complete handshake — it pulls the camera's XML, negotiates the packet size, opens and closes its stream cleanly — and the clean disconnect leaves the camera in a fresh state your client can enter. Read the ritual as a diagnosis: another client is doing something your library cannot do on its own.

Cause 2: the client library predates the camera

A GenICam client does more than open a socket. It downloads the camera's XML description, negotiates the stream packet size and drives the stream protocol — and each of those steps has moved between library and firmware generations. A release older than the camera enumerates and reads features, then fails exactly at stream creation. The same split, properties read fine while video never starts, is worked through in ROS Aravis camera reads properties but no video stream.

In a recorded case on Ubuntu, a camera refused to stream from a 0.5-series Aravis build unless the maker's utility had touched it first; moving the same client to the 0.6.0 release fixed stream creation with no change to the camera, the cable or the network. Version mismatch was the whole problem.

Test before reconfiguring anything: run the reference viewer with debug output on. With Aravis, set ARV_DEBUG=stream:3,device:3 before starting arv-viewer and read the last line printed before the failure — it names the handshake stage that died. Then move the whole stack to a current release and keep exactly one library in the build; two stacks on one host recreate the contest from cause 1. Check your camera against the SDK's supported-generations list first, as in camera not recognized by your SDK: check version support first.

Cause 3: settings that revert to the camera's defaults

Values shown while no control session is active are startup values, not your settings. In the recorded case the camera reported 5,000 µs of exposure and a 64 × 32 ROI at offset (0, 0) after every refresh — both straight from its startup state. A write made from a device list goes nowhere: with no session, no one receives it.

Test: connect, write, read back in the same session; disconnect, reconnect, read again. A value that survives the second read has stuck. If values revert while you stay connected, the client is failing to download or parse the camera's XML — a truncated file or an unsupported schema — and you are back in cause 2: upgrade before debugging further.

Build one sanity write into your start-up code: set the exposure to a value you can see in the image, grab a frame, and check the brightness moved the way you expect. That one check catches stuck writes, dead sessions and swapped exposure units in seconds.

Cause 4: the network path drops stream packets

The image travels as UDP packets with no delivery guarantee beyond the camera's resend mechanism, so loss shows up as torn or incomplete buffers, grey bands, or a stream that dies under load. A badly mismatched packet size also fails stream creation outright, so rule the path out early.

Commit to two settings. First, packet size: pick the largest packet size in the FAQ answer above — 9,000-byte jumbo frames only when the camera, the network interface and every switch on the path support them, and never enable them on the camera before the MTU at both ends matches. Then give the client room to receive: raise the kernel's receive-buffer limits and the transport layer's buffer count until incomplete-buffer errors stop. Both checks, and the counters that show where packets vanish, are in GigE Vision stream timeout: check packets, buffers and MTU and GigE camera buffer was incompletely grabbed: fix lost packets.

Cabling sits inside this test, not at the end of the project: the camera cables category splits fixed-run from high-flex types. A fixed bench or machine run wants a locking connector that cannot creep out of the jack — the LS-CBL-0117 is a 15 m camera data cable with an RJ45 locking stud. A drag-chain or gantry move wants flex rating instead: the LS-CBL-0199 is a 3 m high-flex GigE cable with screw locks.

Example inputs, typical of a 1.3 MP mono camera: 1,280 × 1,024 pixels, 8-bit output, 75 fps target. A GigE link carries 1,000 Mb/s.

payload (Mb/s) = width × height × bytes per pixel × 8 × fps / 1,000,000 packets per second ≈ payload bytes per second / payload bytes per packet

Payload: 1,280 × 1,024 × 1 × 8 × 75 = 786,432,000 bits/s ≈ 786 Mb/s, which is 79% of the link before a single header. Packets at a 1,500-byte MTU: roughly 1,460 bytes of each packet carries image data, so one frame needs 1,310,720 / 1,460 ≈ 898 packets, and 75 fps makes that ≈ 67,000 packets/s. At 9,000-byte jumbo packets, about 8,960 bytes of each packet carries image data: 1,310,720 / 8,960 ≈ 146 packets per frame, ≈ 11,000 packets/s.

Decision: the camera fits on one GigE link at 1,500-byte packets only with large receive buffers and nothing else on the wire — the margin over 1,000 Mb/s is about 20% before resend traffic. With jumbo frames the packet count falls six-fold, and so does the chance of losing a packet in any frame.

The fix sequence, in order

  1. Stop every acquisition program and background service, power-cycle the camera, and run one client at a time. This clears a contested or stale session in minutes.
  2. Move the GenICam client library to a current release and keep one library in the build. Version mismatch is the most common single cause of stream creation failing while reads succeed.
  3. Re-test with the reference viewer and debug output enabled, and read the failing step by name before changing anything else.
  4. Match packet size end-to-end — 9,000 bytes when every device supports jumbo frames, otherwise 1,500 everywhere — and raise receive buffers until incomplete-buffer errors stop.
  5. Prove writes stick: connect, set a visible exposure, disconnect, reconnect, read back.
  6. Run a swap test on the same port and cable. A different current-production GigE camera that streams cleanly separates a camera-side problem from a host-side one in a single step.
  7. If the symptom survives all of that, capture the traffic in Wireshark and compare a failed stream start with one made right after the maker's utility has connected and disconnected. The first differing packet names the handshake stage to fix.

Keep three reference cameras for step 6, covering the spread: a 6 MP mono GigE camera with a 1/1.8-inch rolling-shutter sensor and a C-mount; a 2.5 MP global-shutter colour model; and a 12 MP GigE camera that streams at 9 fps, slow enough that bandwidth drops out of the question.

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
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 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

Prevention: pin the version, own the camera, own the subnet

Pin the client library to one release on the bench machine and every production host — a program that works on one machine and not another is usually a version difference — and apply the discipline from Docker build SDK version mismatch: pin one library version everywhere to plain hosts as well. In production, let one process own the camera and have every other program talk to that process.

Keep the camera and the network interface on the same subnet with static addresses on both ends; discovery across subnets and ARP-based addressing fail in ways that look exactly like flaky sessions.

Two cases this is not. A robot controller that polls the camera follows the same single-session rule, and its side of the handshake is covered in GigE Vision camera connection troubleshooting on a robot controller. A device that serves its video as an RTSP stream will never open in a GenICam library at any version — that requirement is handled in resolving RTSP stream requirements on a GigE camera.

If you are specifying rather than rescuing, start in the GigE area scan cameras category or the camera finder; the camera configurator matches camera, lens and cable in one pass. More transport-layer fixes sit on the systems topic page, and a stubborn case is worth sending to the applications team with the debug output from step 3 — the failing step's name usually ends the discussion.

Questions

Why does my camera stream only after the maker's utility has connected and disconnected?

The utility runs a complete, clean handshake: it downloads the camera's XML, negotiates the packet size and closes its session properly. That clean disconnect leaves the camera in a fresh state an older client library can enter. Treat the ritual as evidence of a version or session problem — upgrade the library and run one client at a time, and the ritual stops being necessary.

Can two programs use one GigE Vision camera at the same time?

Not as two independent clients. The standard gives each camera one primary control connection, with at most a secondary standing by, so a second program's writes and stream requests fail while the first holds the session. In production, let one process own the camera and have other programs talk to that process, or stop one client before starting the next.

What packet size should a GigE Vision camera use?

The largest value every device on the path accepts: 9,000-byte jumbo frames when the camera, the network interface and every switch support them, otherwise 1,500 bytes. A mixed path — one old switch at 1,500 — forces 1,500 on the camera too; replace or re-seat that switch instead. Jumbo frames cut a 1.3 MP 75 fps stream from about 67,000 to about 11,000 packets per second.

How much bandwidth does a 1.3 MP GigE camera need at 10-bit?

Double the bytes per pixel against the 8-bit figure: 1,280 × 1,024 at 75 fps needs 786 × 10/8 = 983 Mb/s of payload, which no longer fits reliably in a 1,000 Mb/s link once headers and resends are counted. Halve the frame rate to roughly 40 fps, crop the ROI, or move the camera to a 2.5 or 10 GigE interface.

Why did my ROI write revert to 64 × 32 at offset 0, 0?

That tiny window is the camera's reset value from its GenICam XML, and it reappears whenever no control session is active. A write made from a device list or a disconnected viewer changes nothing on the camera. Connect, write, disconnect, reconnect and read back: a value that survives the round trip has stuck. If it still reverts while connected, upgrade the client library.

Does the camera's IP set-up cause stream failures like this?

It causes failures that look like this one. Keep the camera and the network interface on the same subnet with static addresses on both ends, and leave the firewall open for the client's port range during testing. A camera that answers discovery but sits on another subnet, or behind a firewall that drops its stream packets, enumerates fine and streams never.