You are writing C# to grab images, analyse them and act on the outcome, and you want the capture code to outlive the first camera. The decision that decides that is not the class design — it is the transport. GigE Vision and USB3 Vision cameras speak GenICam through a standard GenTL producer, so one small interface in your code drives any of them. A Camera Link camera delivers its pixels into a frame grabber whose maker owns the API, so there your code locks to that grabber's SDK. This guide gives the decision, the bandwidth arithmetic behind it, a C# interface you can copy, and the checks to run before you write the abstraction.
The decision, up front
Choose the transport before you design any interface. Three cases cover nearly every line we see:
- New line, cameras not yet bought. Buy GigE Vision or USB3 Vision area scan cameras and write the capture layer against GenICam over GenTL. One wrapper drives any compliant camera, and no per-vendor SDK ever enters your process. This is the default answer.
- Stream faster than USB3 carries. Move to CoaXPress or a 10GigE camera once the payload passes about 3.5 Gbit/s. The wrapper stays; only the producer library changes.
- Camera Link camera already on the shelf. Accept the grabber SDK, but bury it behind your own interface so that exactly one assembly in the application is transport-specific.
If you must keep several vendor SDKs alive side by side, wrap them all behind one acquisition layer — that pattern has its own guide to unifying multi-brand camera SDKs in C#. The approach here removes the problem one level lower, at the transport. If you would rather buy a finished environment than write capture code, start from choosing a machine vision development environment instead.
What the standards hand your C# code
Three standards do the work. GigE Vision and USB3 Vision define how a camera is discovered on the link and how pixels travel to the host. GenICam defines the camera's controls as a tree of nodes: every value, button and selector you can read or write. GenTL defines the transport-layer calls your code makes — enumerate interfaces, enumerate devices, open a data stream, announce buffers, start acquisition, wait for a filled buffer, requeue it.
The only per-transport piece your process loads is the GenTL producer, one library per transport family; cameras ship theirs, frame grabbers ship theirs. Feature names are standardized, so the string "ExposureTime" — microseconds, the standard unit — sets exposure on every compliant camera, and "PixelFormat" reads and writes the same way. When a setting resists the generic tree, the camera's registers can still be reached from your own control code, as described in accessing GigE camera registers at runtime. Day-to-day changes belong in the tree you can browse and set through a generic feature tree.
The capture interface, in code
Keep the abstraction small: open, set, grab, close. Processing, decisions and storage live above it and never see a transport. The names below are ours, not a vendor API:
public interface IImageSource : IDisposable
{
void Open(string deviceId); // id from enumeration
void Set(string feature, string value); // standard GenICam feature name
byte[] Grab(int timeoutMs); // one frame, copied out
int Width { get; } // filled in by Open()
int Height { get; }
}
The grab loop copies each frame out of the producer's buffer and requeues that buffer at once; holding a buffer while you process is the classic way to stall acquisition. The test that proves the design is deliberately transport-blind — it cannot tell which camera answered:
[Fact]
public void Every_transport_returns_the_same_frame_shape()
{
Config cfg = Config.Load(); // producer paths from file
string[] ids = Enumerator.All(cfg); // your enumeration helper
Assert.True(ids.Length >= 2, "connect two cameras first");
using IImageSource a = Capture.Connect(cfg.ProducerPath, ids[0]);
using IImageSource b = Capture.Connect(cfg.ProducerPath2, ids[1]);
byte[] fa = a.Grab(2000); // 2000 ms timeout
byte[] fb = b.Grab(2000);
Assert.Equal(a.Width * a.Height, fa.Length);
Assert.Equal(b.Width * b.Height, fb.Length);
}
GenTL itself is a C API. From C# you bind it with the wrappers in the producer's package, with a commercial library, or with your own P/Invoke layer — the same trade-off you meet pulling camera-specific attributes through a managed wrapper or P/Invoke. The layer is not C#-only, either: one GenICam capture library can serve one codebase across many languages.
Size the stream before you size the code
The transport sets the ceiling, so run this arithmetic first:
The catalog carries the same 12 MP sensor behind two transports, in the LS-CMR-0053 and the LS-CMR-0166:
- Sensor format
- 1/1.7"
- Lens mount
- C-mount
- Sensor format
- 1/1.7"
- Interface
- USB3
The USB3 model outputs 4000 × 3000 pixels at 30 fps; the GigE model outputs the same pixels at 9 fps. The sensor did not change — the link did. At 8 bits per pixel one frame is 4000 × 3000 × 1 byte = 12 MB. Over USB3 at 30 fps that is 12 MB × 30 = 360 MB/s, or 2.88 Gbit/s of payload, against the roughly 3.2-3.5 Gbit/s a USB3 Vision link sustains after its 5 Gbit/s line rate loses encoding and protocol overhead — about 10% headroom, which is why the camera stops there. Over GigE at 9 fps the same frames need 12 MB × 9 = 108 MB/s ≈ 0.86 Gbit/s, just under the 115 MB/s a well-tuned GigE Vision link sustains with jumbo frames. Frame rate is link rate divided by frame size; the camera maker already did that division and printed the outcome in the specification.
If you have not fixed the pixel count yet, start one step earlier, from the field of view and the smallest defect you must resolve:
Then feed that pixel count into the formula before you commit to a camera the link cannot carry at speed. On GigE, the ceiling holds only with a large packet size and jumbo frames enabled end to end; a camera that drops to a fraction of its rate almost always has small packets or a shared link — the settings are in fixing a 10GigE camera stuck at 1 Gbps: packet size and NIC setup. Give the cameras their own card rather than the PC's onboard port, for example the dual-port PoE GigE NIC MV-GE2002P:
- Interface
- GigE
- Ports
- 2 ports
Camera Link: where vendor-neutral ends
A Camera Link camera has no network stack and no USB controller. Its pixels cross dedicated LVDS pairs straight into a frame grabber, and its configuration travels over a serial channel the grabber exposes. Discovery, buffers, triggering and register access therefore all live in the grabber maker's SDK, and no standard API spans grabber brands. Whatever interface you design, the implementation under it compiles against that one SDK.
That is workable when you treat it as a bounded cost: implement IImageSource over the grabber SDK, keep it in its own assembly, and the rest of the application stays clean. What must match between camera and grabber — tap count, camera files, cable wiring — is listed in Camera Link camera and frame grabber compatibility, and the acquisition side of these cards is walked through in frame grabber image acquisition for Camera Link and CoaXPress. For the card itself, a Camera Link frame grabber such as the MV-GC1102IOL:
- Interface
- Camera Link
Because the code now depends on one maker's SDK, that maker's support quality becomes part of your machine's design life. Evaluating machine vision vendor support is worth doing before you commit, and so is understanding why one frame grabber SDK viewer works while another fails.
Four transports compared
Line rates are the standards' own; payload figures are typical sustained image throughput, the basis used in the worked example above.
| GigE Vision | USB3 Vision | CoaXPress | Camera Link | |
|---|---|---|---|---|
| Generic C# path | GenTL producer, standardized | GenTL producer, standardized | GenTL producer on many grabbers | Grabber maker's SDK only |
| One wrapper, many camera brands | Yes | Yes | Yes, within one grabber | No |
| Payload per link | ~115 MB/s on a 1 Gbit/s line | ~3.2-3.5 Gbit/s on a 5 Gbit/s line | 6.25 Gbit/s per coax at CXP-6, aggregated across links | Set by grabber and tap count |
| Cable reach | 100 m on Cat5e | 3-5 m passive, longer on active cables | ~35 m at CXP-6 on the specified coax | ~7 m typical |
| Camera power | PoE on the data cable | Bus power | Power over the same coax | Separate supply |
For the reliability argument per interface, read the most reliable camera interface: GigE, USB3, Camera Link or CoaXPress. On the CoaXPress column the hardware looks like this, an octo CXP-6 frame grabber such as the MV-GX1008:
- Interface
- CoaXPress
How to choose, case by case
- Multi-camera production line, cameras to be bought: GigE Vision. Four cameras share one card, PoE carries their power, cable reach covers the line, and one wrapper covers every brand you ever add. Filter the camera finder to GigE and shortlist from there.
- Bench or machine with one or two cameras: USB3 Vision. Less setup, short locked cables, and one producer for every compliant camera you plug in.
- Streams past USB3: CoaXPress through a grabber whose software package lists a GenTL producer — without one, the CXP path costs you a second implementation. A 10GigE camera is the other exit; a quad-port copper 10GbE card such as the MV-GT2104 serves several of them.
- Camera Link camera already specified: wrap the grabber SDK behind the same interface and confine it to one assembly, as above.
To assemble a matched chain, run the system configurator from the camera step, or from the extras step to add a frame grabber and its cables; the accessories finder lists both.
Checks before you write the wrapper
- Enumerate before you design. Run the producer's device enumeration on the target PC with one camera attached; discovery is the first thing to prove.
- Read the feature tree of each camera model you might buy, and confirm the features your recipe depends on exist on all of them.
- On GigE, set the packet size to the largest the card accepts and enable jumbo frames on both ends — then measure the frame rate, don't assume it.
- Pin the producer and SDK versions in source control, so a rebuild never mixes library versions; that failure is quiet and looks like a camera bug, and pinning one library version everywhere shows the pattern.
- Copy frames out of buffers and requeue immediately; keep processing off the grab thread.
- Match the cable to the transport and the length, as in the 3 m high-flex drag-chain camera cables LS-CBL-0199 for GigE and LS-CBL-0219 for USB3.0:
When the generic answer is wrong
- The camera is Camera Link and cannot change: the grabber SDK is the honest implementation, and hiding it behind IImageSource keeps the cost local.
- You need grabber-side hardware behaviour — encoder-to-strobe routing, trigger arbitration between cameras. Two cameras on one grabber raise exactly these issues, down to the snap-timeout failure of two cameras on one frame grabber.
- The device is a 3D profiler or a smart camera with onboard processing: its SDK owns the geometry and the depth map, and a generic 2D capture interface is the wrong tool.
- Your processing library already ships acquisition for your transports: write the wrapper only where it buys you real freedom to change hardware.
The five-minute checklist
- Transport chosen before the interface is written — GenTL everywhere a Camera Link camera does not force the grabber SDK.
- Payload in Mbit/s computed for the target frame rate, and the link ceiling confirmed above it.
- Enumeration proven on the target PC, on the production card.
- Feature tree read for every candidate camera model.
- Packet size and jumbo frames set on GigE; producer versions pinned.
- Frames copied out, buffers requeued, safety left on safety circuits.
When you want a second pair of eyes on the chain, talk to us: free expert support comes with every order, and a quote request for a matched camera, card and cable set takes minutes.
Questions
Will one GenTL wrapper really drive cameras from different makers?
Yes, across GigE Vision and USB3 Vision cameras from any maker: enumeration, feature access and buffer handling all go through the same producer calls, and feature names follow the same standard. What still differs between makers is which optional features exist and what the vendor-specific ones are called, so enumerate the feature tree once per model and read out its pixel formats and trigger modes before you rely on them.
What does the GenTL software cost?
The producer library ships in the software package of the camera or frame grabber it belongs to, so buying the hardware covers it. The wrapper is your own code. The only paid software you might add is a commercial processing library, and that is a choice, not a requirement: the capture layer needs none of it to grab frames and hand them to your analysis.
How do I add a Camera Link camera to the same interface?
Implement the same IImageSource surface on top of the grabber's SDK and keep that implementation in its own assembly. The rest of the application sees open, set, grab and close, and never learns which transport is underneath. Expect the grabber's camera file, cable wiring and trigger routing to need attention before the first frame arrives; the compatibility checks are the same for every camera you add on that grabber.
How much bandwidth does my camera need?
Multiply it out: width × height × bytes per pixel × frames per second × 8. A 20 MP mono camera at 8 bits and 30 fps streams 20 000 000 × 1 × 30 × 8 = 4.8 Gbit/s, which is past USB3 Vision and needs 10GigE or CoaXPress. Do this arithmetic before choosing the transport, not after the cameras arrive.
Does CoaXPress work with the same wrapper?
Only through a frame grabber that ships a GenTL producer; many CXP grabbers do, and then your wrapper opens it like any other transport and reaches 6.25 Gbit/s per coax at CXP-6. Without a producer you are on the grabber's own SDK, and the code locks to it exactly as with Camera Link. Check the producer in the grabber's software package before you design around it.
GigE or USB3 for a first multi-camera line?
GigE Vision. One quad-port card drives four cameras, PoE carries their power on the data cable, and 100 m of reach covers a production line. USB3 Vision wins on a bench with one or two cameras and short locked cables: simpler setup, no network configuration, and enough bandwidth for anything up to about 3 Gbit/s of payload.






