eGrabber for MultiCam users

Concepts

MultiCam eGrabber
Board Interface
Channel Device + Data stream
Surface Buffer
Surface cluster (MC_Cluster) Buffers announced to the data stream
- Remote device (camera)
MultiCam parameters GenApi set/get features
- GenApi commands
CAM file Euresys GenApi script
- CallbackOnDemand
Callback functions CallbackSingleThread
- CallbackMultiThread

Initialization

MultiCam:
MCSTATUS status = McOpenDriver(NULL);
if (status != MC_OK) {
    ...
}
eGrabber:
Euresys::EGenTL gentl;

Channel creation

MultiCam:
MCSTATUS status;
MCHANDLE channel;
status = McCreate(MC_CHANNEL, &handle);
if (status != MC_OK) {
    ...
}
status = McSetParamInt(channel, MC_DriverIndex, CARD_INDEX);
if (status != MC_OK) {
    ...
}
status = McSetParamInt(channel, MC_Connector, CONNECTOR);
if (status != MC_OK) {
    ...
}
eGrabber:
Euresys::EGrabber<> grabber(gentl, CARD_INDEX, DEVICE_INDEX);

Surface creation (automatic)

MultiCam:
status = McSetParamInt(channel, MC_SurfaceCount, BUFFER_COUNT);
if (status != MC_OK) {
    ...
}
eGrabber:
grabber.reallocBuffers(BUFFER_COUNT);

Surface creation (manual)

MultiCam:
for (size_t i = 0; i < BUFFER_COUNT; ++i) {
    MCHANDLE surface;
    MCSTATUS status;
    void *mem = malloc(BUFFER_SIZE);
    if (!mem) {
        ...
    }
    status = McCreate(MC_DEFAULT_SURFACE_HANDLE, &surface);
    if (status != MC_OK) {
        ...
    }
    status = McSetParamInt(surface, MC_SurfaceSize, BUFFER_SIZE);
    if (status != MC_OK) {
        ...
    }
    status = McSetParamPtr(surface, MC_SurfaceAddr, mem);
    if (status != MC_OK) {
        ...
    }
    status = McSetParamPtr(surface, MC_SurfaceContext, USER_PTR[i]);
    if (status != MC_OK) {
        ...
    }
    status = McSetParamInst(channel, MC_Cluster + i, surface);
    if (status != MC_OK) {
        ...
    }
}
eGrabber:
for (size_t i = 0; i < BUFFER_COUNT; ++i) {
    void *mem = malloc(BUFFER_SIZE);
    if (!mem) {
        ...
    }
    grabber.announceAndQueue(Euresys::UserMemory(mem, BUFFER_SIZE, USER_PTR[i]));
}

Surface cluster reset

MultiCam:
MCSTATUS status;
for (size_t i = 0; i < BUFFER_COUNT; ++i) {
    MCHANDLE surface;
    status = McGetParamInst(channel, MC_Cluster + i, &surface);
    if (status != MC_OK) {
        ...
    }
    status = McSetParamInt(surface, MC_SurfaceState, MC_SurfaceState_FREE);
    if (status != MC_OK) {
        ...
    }
}
status = McSetParamInt(channel, MC_SurfaceIndex, 0);
if (status != MC_OK) {
    ...
}
eGrabber:
grabber.resetBufferQueue();

Frame grabber configuration

MultiCam eGrabber

McSetParamStr(H, MC_CamFile, filepath)

grabber.runScript(filepath)
- grabber.runScript(script)
McSetParamInt(H, id, value) or McSetParamNmInt(H, name, value) grabber.setInteger<M>(name, value)
McSetParamFloat(H, id, value) or McSetParamNmFloat(H, name, value) grabber.setFloat<M>(name, value)
McSetParamStr(H, id, value) or McSetParamNmStr(H, name, value) grabber.setString<M>(name, value)

where H is a MC_HANDLE (the global MC_CONFIGURATION handle, a board handle, or a channel handle), and M specifies the target module (either SystemModule, InterfaceModule, DeviceModule, or StreamModule).

Camera configuration

MultiCam eGrabber
- grabber.runScript(filepath)
- grabber.runScript(script)
- grabber.setInteger<RemoteModule>(name, value), grabber.setFloat<RemoteModule>(name, value), or grabber.setString<RemoteModule>(name, value)

Script files

MultiCam:
; CAM file
ChannelParam1 = Value1;
ChannelParam2 = Value2;
eGrabber:
// Euresys GenApi Script  
var grabber = grabbers[0];  
grabber.DevicePort.set('DeviceFeature1', Value1);  
grabber.DevicePort.set('DeviceFeature2', Value2);  
grabber.RemotePort.set('CameraFeatureA', ValueA);
            

Acquisition start/stop

MultiCam:
// start "live"
McSetParamInt(channel, MC_GrabCount, MC_INFINITE);
McSetParamInt(channel, MC_ChannelState, MC_ChannelState_ACTIVE);
// stop
McSetParamInt(channel, MC_ChannelState, MC_ChannelState_IDLE);
// grab 10 images
McSetParamInt(channel, MC_GrabCount, 10);
McSetParamInt(channel, MC_ChannelState, MC_ChannelState_ACTIVE);
eGrabber:
// start "live"
grabber.start();
// stop
grabber.stop();
// grab 10 images
grabber.start(10);

Synchronous (blocking) buffer reception

MultiCam:
MCSTATUS status;
MCSIGNALINFO info;
// wait for a surface
status = McWaitSignal(channel, MC_SIG_SURFACE_PROCESSING, timeout, &info);
if (status != MC_OK) {
    ...
}
MCHANDLE surface = info.SignalInfo;
// process surface
...
// make surface available for new images
status = McSetParamInt(surface, MC_SurfaceState, MC_SurfaceState_FREE);
if (status != MC_OK) {
    ...
}
eGrabber:
// wait for a buffer
Buffer buffer = grabber.pop(timeout);
// process buffer
...
// make buffer available for new images
buffer.push(grabber);
eGrabber:
{
    // wait for a buffer
    ScopedBuffer buffer(grabber, timeout);
    // process buffer
    ...
    // ScopedBuffer destructor takes care of making buffer available for new images
}

Callbacks

MultiCam:
class MyChannel {
    public:
        MyChannel() {
            // create and configure channel
            ...
            // enable "SURFACE_PROCESSING" events
            status = McSetParamInt(channel, MC_SignalEnable + MC_SIG_SURFACE_PROCESSING,
                                            MC_SignalEnable_ON);
            if (status != MC_OK) {
                ...
            }
            // enable "END_EXPOSURE" events
            status = McSetParamInt(channel, MC_SignalEnable + MC_SIG_END_EXPOSURE,
                                            MC_SignalEnable_ON);
            if (status != MC_OK) {
                ...
            }
            // register "extern C" callback function
            MCSTATUS status = McRegisterCallback(channel, GlobalCallbackFunction, this);
            if (status != MC_OK) {
                ...
            }
        }

        void onEvent(MCSIGNALINFO *info) {
            switch (info->Signal) {
                case MC_SIG_SURFACE_PROCESSING:
                    MCHANDLE surface = info.SignalInfo;
                    // process surface
                    ...
                    break;
                case MC_SIG_END_EXPOSURE:
                    // handle "END_EXPOSURE" event
                    ...
                    break;
            }
        }

    private:
        MCHANDLE channel;
};

void MCAPI GlobalCallbackFunction(MCSIGNALINFO *info) {
    if (info && info->Context) {
        MyGrabber *grabber = (MyGrabber *)info->Context;
        grabber->onEvent(info);
    }
};
eGrabber:
class MyGrabber : public EGrabber<CallbackSingleThread> {
    public:
        MyGrabber(EGenTL &gentl) : EGrabber<CallbackSingleThread>(gentl) {
            // configure grabber
            ...
            // enable "NewBuffer" events
            enableEvent<NewBufferData>();
            // enable "Cic" events
            enableEvent<CicData>();
        }

    private:
        virtual  void onNewBufferEvent(const NewBufferData& data) {
            ScopedBuffer buffer(*this, data);
            // process buffer
            ...
        }
        virtual  void onCicEvent(const CicData &data) {
            // handle "Cic" event
            ...
        }
};

Synchronous (blocking) event handling

MultiCam:
class MyChannel {
    public:
        MyChannel() {
            // create and configure channel
            ...
            // enable "END_EXPOSURE" events
            status = McSetParamInt(channel, MC_SignalEnable + MC_SIG_END_EXPOSURE,
                                            MC_SignalEnable_ON);
            if (status != MC_OK) {
                ...
            }
        }

        void waitForEvent(uint32_t timeout) {
            // wait for an event
            MCSTATUS status = McWaitSignal(channel, MC_SIG_END_EXPOSURE, timeout, &info);
            if (status != MC_OK) {
                ...
            }
            // handle "END_EXPOSURE" event
            ...
        }

    private:
        ...
};
eGrabber:
class MyGrabber : public EGrabber<CallbackOnDemand> {
    public:
        MyGrabber(EGenTL &gentl) : EGrabber<CallbackOnDemand>(gentl) {
            // configure grabber
            ...
            // enable "Cic" events
            enableEvent<CicData>();
        }

        void waitForEvent(uint64_t timeout) {
            // wait for an event
            processEvent<CicData>(timeout);
        }

    private:
        // onCicEvent is called by processEvent when a "Cic" event occurs  
        virtual  void onCicEvent(const CicData &data) {
            // handle "Cic" event
            ...
        }
};