Protocol overview#
pyGigEVision implements two complementary UDP protocols from the
GigE Vision specification:
GVCP (Gigabit Vision Control Protocol): request-response control on UDP port 3956. Used for camera discovery, register read/write, bulk memory access, and heartbeat keepalive.
GVSP (Gigabit Vision Streaming Protocol): one-way push streaming on a UDP port the host chooses. The camera sends each frame as a Leader packet, a sequence of Data packets, and a Trailer packet.
GVCP#
The control protocol exposes a small set of commands. Every packet is an 8-byte header plus a payload:
[0x42] [flags] [command: 2B] [payload_len: 2B] [req_id: 2B]
The GVCPClient class wraps the commands in
Pythonic methods (read_reg(),
write_reg(),
read_mem(), etc.) and handles
acknowledgement validation, retries, PENDING_ACK responses, and
heartbeat keepalive in a background thread.
Bootstrap (boot-time) registers defined by the GigE Vision spec live
in pyGigEVision.standard.
Discovery#
pyGigEVision.discover() called with no argument (discover(""))
enumerates the host network interfaces (via psutil) and scans from
each one. On every interface it sends a global broadcast and a
per-subnet directed broadcast, then dedupes the replies by camera IP.
Sweeping all interfaces by default means cameras on secondary NICs and
on USB-to-GigE adapters are found without naming an interface. Pass an
explicit interface_ip to restrict the scan to a single host
interface.
Each result dict includes the camera ip and mac as well as
interface_ip, the host interface address the camera replied on.
A vendor driver can use interface_ip to bind the matching local
interface when it connects, which keeps the connection on the same NIC
that saw the discovery reply.
If a camera comes up on a subnet that none of the host interfaces can
reach, force_ip() re-homes it by MAC. It
broadcasts a FORCEIP command that assigns a new ip and mask (and
optional gateway) to the camera identified by mac, so it lands
on a reachable subnet. The assignment is not persistent across a power
cycle.
GVSP#
The streaming receiver runs on its own background thread:
Listens on a host-chosen UDP port.
Reads incoming packets and dispatches by packet type (Leader / Data / Trailer).
Reassembles frames into pre-allocated NumPy buffers (direct offset writes, no dictionary-and-sort overhead).
Detects gaps in packet sequence numbers in real time and requests resends directly from the receive socket.
Pushes completed frames onto a thread-safe queue for the consumer to pop via
get_frame().
Byte order#
Some cameras send pixel data in little-endian and others in big-endian
order. pyGigEVision does not assume; set the byteswap
parameter of GVSPReceiver according to your
camera’s convention.
Troubleshooting#
Discovery finds nothing.
Check that the camera is on the same subnet as one of your network
interfaces. On Windows, also verify that the Ethernet adapter profile
is set to Private (Public profile blocks inbound UDP by default).
If a VPN is active and owns a virtual link-local interface, that
interface may shadow the camera’s Ethernet adapter. In that case, pass
an explicit interface_ip to pyGigEVision.discover() to scan
from the host interface the camera is attached to.
Packets unrecoverable warnings during streaming. Host-side UDP buffer overflows. Try one of:
Increase the OS UDP receive buffer.
Reduce the camera frame rate.
Increase the packet inter-spacing via the
REG_SC_PACKET_DELAYregister (seepyGigEVision.standard).
Stream channel writes get ``ACCESS_DENIED``. Another process holds control privilege. Either close the other client or wait for its heartbeat to expire (default ~3 seconds).