/*++ Module Name: sample1.c Abstract: simultaneously grabbing of 9 cameras by GINGA++ M2 and M4. Environment: user mode Notes: gingapp driver usage sample 1 Revision History: --*/ #include #include #include "GINGAPPEX.H" #define TIMEOUT 10000 /* 10 sec */ #define REPEAT 10 typedef enum { NONE_TYPE = -1, GINGAPP_M4 = 0, GINGAPP_M2 } GINGAPP_BOARD_TYPE; typedef struct tagFunctions { HMODULE hGingaDll; /* Ginga++ API */ long (*GingaPPResetDevice)(void); unsigned long (*GingaPPCountCaptureChannel)(void); void **(*GingaPPAllocFrameBuffer)(unsigned long Width, unsigned long Height, unsigned long NFrame); long (*GingaPPFreeFrameBuffer)(void **BufferId); long (*GingaPPOpenConfiguration)(char * pConfigFilePath, GINGAPP_CAPTURE_CONFIGURATION ** ppConfig); long (*GingaPPCloseConfiguration)(GINGAPP_CAPTURE_CONFIGURATION * pConfig); long (*GingaPPSetConfiguration)(unsigned long ChannelNumber, GINGAPP_CAPTURE_CONFIGURATION * pConfig); long (*GingaPPStartCapture)(unsigned long ChannelNumber, unsigned long StartFrameNumber, unsigned long EndFrameNumber); long (*GingaPPForceShot)(unsigned long ChannelNumber); long (*GingaPPSenseStatus)(unsigned long ChannelNumber, long * pStatus); long (*GingaPPStopCapture)(unsigned long ChannelNumber); long (*GingaPPAbortCapture)(unsigned long ChannelNumber); long (*GingaPPGetLastFrame)(void ** BufferId, unsigned long * pFrameNumber, unsigned long ChannelNumber); long (*GingaPPIsFrameValid)(void ** BufferId, unsigned long FrameNumber, BOOL * pValid, unsigned long ChannelNumber); } Functions; // Structure PortInfo: Use this structure to obtain information of capture port typedef struct tagPortInfo { GINGAPP_BOARD_TYPE BoardTypd; /* board type */ int PortNumber; /* port number */ char *CameraFile; /* camera file */ unsigned long Width; /* image width */ unsigned long Height; /* image height */ int NumBuffer; /* number of buffer */ } PortInfo; // Structure CapturePort: Use this structre to obtain the setting information for capturing. typedef struct tagCapturePort { int num; /* port number */ void **BufferId; /* frame buffer */ unsigned long Width; /* image width */ unsigned long Height; /* image height */ int NumBuffer; /* number of framebuffer */ HANDLE hFrameComplete; /* frame complete event */ HANDLE hCaptureStop; /* capture stop event */ GINGAPP_CAPTURE_CONFIGURATION *pConfig; /* configuration file */ GINGAPP_BOARD_TYPE type; /* board type */ Functions *func; /* GINGA++ functions */ } CapturePort; /* funtion prototype */ void DriverErrorCheck( long Status, char * pErrorMessage ); int DetectDevice( GINGAPP_BOARD_TYPE type ); Functions * LoadFunctions( GINGAPP_BOARD_TYPE type ); void FreeFunctions( Functions *fc ); CapturePort * InitCapturePort( PortInfo *info, Functions *m4_func, Functions *m2_func ); void CloseCapturePort( CapturePort *port ); #define USE_CAPTURE_CHANNEL 9 //#define USE_CAPTURE_CHANNEL 2 int main(void) { long Status; long ChannelStatus; HANDLE WaithFrameComplete[USE_CAPTURE_CHANNEL]; HANDLE WaithCaptureStop[USE_CAPTURE_CHANNEL]; DWORD WaitResult; int i, j; int m4_num_port, m2_num_port; Functions *m4_func = NULL, *m2_func = NULL; CapturePort *Port[USE_CAPTURE_CHANNEL]; // 各取り込みポートの情報を設定します // {ボードの種類、取り込みポート番号、カメラファイル名、フレームバッファ横サイズ、フレームバッファの縦サイズ、フレームバッファの数} /* { board type, port number, name of camera file, image width, image height, number of frame buffer } */ PortInfo PortSetting[] = { { GINGAPP_M4, 0, "cis/VCC870A_NI_TRIG_DEMAND", 640, 480, 2 }, { GINGAPP_M4, 1, "cis/VCC870A_NI_TRIG_DEMAND", 640, 480, 2 }, { GINGAPP_M4, 2, "cis/VCC870A_NI_TRIG_DEMAND", 640, 480, 2 }, { GINGAPP_M4, 3, "cis/VCC870A_NI_TRIG_DEMAND", 640, 480, 2 }, { GINGAPP_M4, 4, "cis/VCC870A_NI_TRIG_DEMAND", 640, 480, 2 }, { GINGAPP_M4, 5, "cis/VCC870A_NI_TRIG_DEMAND", 640, 480, 2 }, { GINGAPP_M4, 6, "cis/VCC870A_NI_TRIG_DEMAND", 640, 480, 2 }, { GINGAPP_M4, 7, "cis/VCC870A_NI_TRIG_DEMAND", 640, 480, 2 }, { GINGAPP_M2, 0, "cis/VCC870A_NI_TRIG_DEMAND", 640, 480, 2 } }; /* PortInfo PortSetting[] = { { GINGAPP_M4, 0, "cis/VCC850A_NI_TRIG_DEMAND", 640, 480, 2 }, { GINGAPP_M2, 1, "cis/VCC850A_NI_TRIG_DEMAND", 640, 480, 3 } }; */ // 利用可能な取り込みポートの数を取得します /* detect board type */ m4_num_port = DetectDevice(GINGAPP_M4); m2_num_port = DetectDevice(GINGAPP_M2); // 銀河++の種類別API関数をロードします /* load GINGA++ API functions */ if (m4_num_port > 0) m4_func = LoadFunctions(GINGAPP_M4); if (m2_num_port > 0) m2_func = LoadFunctions(GINGAPP_M2); if (!m4_func || !m2_func) { printf("LoadFunctions failed.\n"); exit(0); } // PortInfo構造体の設定情報をもとに、各取り込みチャンネルを初期化します /* initialize capture port */ for (i = 0; i < USE_CAPTURE_CHANNEL; i++) { Port[i] = InitCapturePort(&PortSetting[i], m4_func, m2_func); if (!Port[i]) { printf("capture port init failed.\n"); exit(0); } } // 全ての取り込みチャンネルの各イベントハンドルをコピーします for (i = 0; i < USE_CAPTURE_CHANNEL; ++i) { WaithFrameComplete[i] = Port[i]->hFrameComplete; WaithCaptureStop[i] = Port[i]->hCaptureStop; } // 全てのチャンネルで取り込みを開始します /* start capture */ for (i = 0; i < USE_CAPTURE_CHANNEL; ++i) { Status = Port[i]->func->GingaPPStartCapture(Port[i]->num, 0, Port[i]->NumBuffer-1); DriverErrorCheck(Status, "capture start failed.\n"); } for (j = 0; j < REPEAT; j++) { #if 1 /* software trigger */ for (i = 0; i < USE_CAPTURE_CHANNEL; ++i) { Status = Port[i]->func->GingaPPForceShot(Port[i]->num); DriverErrorCheck(Status, "force shot failed.\n"); } #endif // 全ての取り込みチャンネルで取り込みが完了するのを"TIMEOUT(msec)"だけ待ちます // 画像取り込みでタイムアウトした場合はエラー処理を行いプログラムを終了します /* wait for frame complete event */ WaitResult = WaitForMultipleObjects(USE_CAPTURE_CHANNEL, WaithFrameComplete, TRUE, TIMEOUT); if (WaitResult == WAIT_TIMEOUT) { printf("capture timeout.\n"); for(i = 0; i < USE_CAPTURE_CHANNEL; ++i) { Status = Port[i]->func->GingaPPSenseStatus(Port[i]->num, &ChannelStatus); DriverErrorCheck(Status, "sense channel status failed.\n"); if(Status != GINGAPP_STATUS_IDLE) { Status = Port[i]->func->GingaPPAbortCapture(Port[i]->num); DriverErrorCheck(Status, "capture abort failed.\n"); WaitResult = WaitForSingleObject(Port[i]->hCaptureStop, TIMEOUT); if(WaitResult == WAIT_TIMEOUT) { printf("abort timeout.\n"); exit(0); } } } } else if (WaitResult == WAIT_OBJECT_0) { //全てのチャンネルがシグナル状態になった場合 unsigned long FrameNumber; printf("FrameComplete:\n"); for (i = 0; i < USE_CAPTURE_CHANNEL; ++i) { // 全ての取り込みチャンネルで最後に取り込まれたフレームバッファ番号を調べます Port[i]->func->GingaPPGetLastFrame(Port[i]->BufferId, &FrameNumber, Port[i]->num); // ボードの種類別にその結果を画面上に出力します if (Port[i]->type == GINGAPP_M4) printf("\tBoardType=M4, Port=%d, LastBufferId=%d\n", Port[i]->num, FrameNumber); else if (Port[i]->type == GINGAPP_M2) printf("\tBoardType=M2, Port=%d, LastBufferId=%d\n", Port[i]->num, FrameNumber); } } } // 各取り込みチャンネルに対して終了処理を行います for (i = 0; i < USE_CAPTURE_CHANNEL; ++i) CloseCapturePort(Port[i]); FreeFunctions(m4_func); FreeFunctions(m2_func); return 1; } /********************/ /* DriverErrorCheck */ /********************/ static void DriverErrorCheck(long Status, char * pErrorMessage) { if(Status != GINGAPP_NO_ERROR) { printf("%s", pErrorMessage); exit(0); } } /****************************/ /* DetectDevice */ /* ret: total port number */ /* arg: board type */ /****************************/ static int DetectDevice(GINGAPP_BOARD_TYPE type) { int ret = 0; /* number of port */ HMODULE hDll; char DllName[256]; unsigned long (*GingaPPCountCaptureChannel)(void); if (type == GINGAPP_M4) { strcpy(DllName, "GingaPP.dll"); } else if (type == GINGAPP_M2) { strcpy(DllName, "GingaM2.dll"); } else return ret; hDll = LoadLibrary(DllName); if (!hDll) return ret; GingaPPCountCaptureChannel = (unsigned long (*)(void)) GetProcAddress(hDll, "GingaPPCountCaptureChannel"); if (GingaPPCountCaptureChannel) ret = GingaPPCountCaptureChannel(); FreeLibrary(hDll); return ret; } /************************************/ /* LoadFunctions */ /* ret: struct Functions pointer */ /* arg: board type */ /************************************/ static Functions * LoadFunctions(GINGAPP_BOARD_TYPE type) { Functions *fc = NULL; fc = (Functions *) malloc(sizeof(Functions)); if (!fc) { printf("LoadFunctions: could not allocate memory.\n"); return fc; } memset(fc, 0, sizeof(Functions)); // ボードの種類に合わせたライブラリを読み込みます if (type == GINGAPP_M2) { fc->hGingaDll = LoadLibrary("GingaM2.dll"); } else if (type == GINGAPP_M4) { fc->hGingaDll = LoadLibrary("GingaPP.dll"); } else { printf("LoadFunctions: could not find board type.\n"); return NULL; } if (!fc->hGingaDll) { printf("LoadFunctions: LoadLibray failed.\n"); return NULL; } /* GingaPPResetDevice */ fc->GingaPPResetDevice = (long (*)(void)) GetProcAddress(fc->hGingaDll, "GingaPPResetDevice"); if (!fc->GingaPPResetDevice) { printf("load address error. GingaPPResetDevice\n"); FreeFunctions(fc); return NULL; } /* GingaPPCountCaptureChannel */ fc->GingaPPCountCaptureChannel = (unsigned long (*)(void)) GetProcAddress(fc->hGingaDll, "GingaPPCountCaptureChannel"); if (!fc->GingaPPCountCaptureChannel) { printf("load address error. GingaPPCountCaptureChannel\n"); FreeFunctions(fc); return NULL; } /* GingaPPAllocFrameBuffer */ fc->GingaPPAllocFrameBuffer = (void ** (*)(unsigned long, unsigned long, unsigned long)) GetProcAddress(fc->hGingaDll, "GingaPPAllocFrameBuffer"); if (!fc->GingaPPAllocFrameBuffer) { printf("load address error. GingaPPAllocFrameBuffer\n"); FreeFunctions(fc); return NULL; } /* GingaPPFreeFrameBuffer */ fc->GingaPPFreeFrameBuffer = (long (*)(void **)) GetProcAddress(fc->hGingaDll, "GingaPPFreeFrameBuffer"); if (!fc->GingaPPFreeFrameBuffer) { printf("load address error. GingaPPFreeFrameBuffer\n"); FreeFunctions(fc); return NULL; } /* GingaPPOpenConfiguration */ fc->GingaPPOpenConfiguration = (long (*)(char *, GINGAPP_CAPTURE_CONFIGURATION **)) GetProcAddress(fc->hGingaDll, "GingaPPOpenConfiguration"); if (!fc->GingaPPOpenConfiguration) { printf("load address error. GingaPPOpenConfiguration\n"); FreeFunctions(fc); return NULL; } /* GingaPPCloseConfiguration */ fc->GingaPPCloseConfiguration = (long (*)(GINGAPP_CAPTURE_CONFIGURATION *)) GetProcAddress(fc->hGingaDll, "GingaPPCloseConfiguration"); if (!fc->GingaPPCloseConfiguration) { printf("load address error. GingaPPCloseConfiguration\n"); FreeFunctions(fc); return NULL; } /* GingaPPSetConfiguration */ fc->GingaPPSetConfiguration = (long (*)(unsigned long, GINGAPP_CAPTURE_CONFIGURATION *)) GetProcAddress(fc->hGingaDll, "GingaPPSetConfiguration"); if (!fc->GingaPPSetConfiguration) { printf("load address error. GingaPPSetConfiguration\n"); FreeFunctions(fc); return NULL; } /* GingaPPStartCapture */ fc->GingaPPStartCapture = (long (*)(unsigned long, unsigned long, unsigned long)) GetProcAddress(fc->hGingaDll, "GingaPPStartCapture"); if (!fc->GingaPPStartCapture) { printf("load address error. GingaPPStartCapture\n"); FreeFunctions(fc); return NULL; } /* GingaPPForceShot */ fc->GingaPPForceShot = (long (*)(unsigned long)) GetProcAddress(fc->hGingaDll, "GingaPPForceShot"); if (!fc->GingaPPForceShot) { printf("load address error. GingaPPForceShot\n"); FreeFunctions(fc); return NULL; } /* GingaPPSenseStatus */ fc->GingaPPSenseStatus = (long (*)(unsigned long, long *)) GetProcAddress(fc->hGingaDll, "GingaPPSenseStatus"); if (!fc->GingaPPSenseStatus) { printf("load address error. GingaPPSenseStatus\n"); FreeFunctions(fc); return NULL; } /* GingaPPStopCapture */ fc->GingaPPStopCapture = (long (*)(unsigned long)) GetProcAddress(fc->hGingaDll, "GingaPPStopCapture"); if (!fc->GingaPPStopCapture) { printf("load address error. GingaPPStopCapture\n"); FreeFunctions(fc); return NULL; } /* GingaPPAbortCapture */ fc->GingaPPAbortCapture = (long (*)(unsigned long)) GetProcAddress(fc->hGingaDll, "GingaPPAbortCapture"); if (!fc->GingaPPAbortCapture) { printf("load address error. GingaPPAbortCapture\n"); FreeFunctions(fc); return NULL; } /* GingaPPGetLastFrame */ fc->GingaPPGetLastFrame = (long (*)(void **, unsigned long *, unsigned long)) GetProcAddress(fc->hGingaDll, "GingaPPGetLastFrame"); if (!fc->GingaPPGetLastFrame) { printf("load address error. GingaPPGetLastFrame\n"); FreeFunctions(fc); return NULL; } /* GingaPPIsFrameValid */ fc->GingaPPIsFrameValid = (long (*)(void **, unsigned long, BOOL *, unsigned long)) GetProcAddress(fc->hGingaDll, "GingaPPIsFrameValid"); if (!fc->GingaPPIsFrameValid) { printf("load address error. GingaPPIsFrameValid\n"); FreeFunctions(fc); return NULL; } return fc; } static void FreeFunctions(Functions *fc) { FreeLibrary(fc->hGingaDll); free(fc); fc = NULL; } static CapturePort * InitCapturePort(PortInfo *info, Functions *m4_func, Functions *m2_func) { CapturePort *cp = NULL; long Status; cp = (CapturePort *) malloc(sizeof(CapturePort)); if (!cp) { printf("InitCapturePort: could not allcate memory.\n"); return cp; } // 各チャンネルの設定情報を読み込みます cp->Width = info->Width; cp->Height = info->Height; cp->NumBuffer = info->NumBuffer; cp->num = info->PortNumber; if (info->BoardTypd == GINGAPP_M4) { if (!m4_func) { printf("Port information mistake.\n"); CloseCapturePort(cp); return NULL; } cp->func = m4_func; cp->type = GINGAPP_M4; } else if (info->BoardTypd == GINGAPP_M2) { if (!m2_func) { printf("Port information mistake.\n"); CloseCapturePort(cp); return NULL; } cp->func = m2_func; cp->type = GINGAPP_M2; } // カメラファイルを読み込みます Status = cp->func->GingaPPOpenConfiguration(info->CameraFile, &cp->pConfig); DriverErrorCheck(Status, "configuration file open failed."); // 設定されたフレームバッファの条件を基にフレームバッファを割り当てます cp->BufferId = cp->func->GingaPPAllocFrameBuffer(cp->Width, cp->Height, cp->NumBuffer); if (!cp->BufferId) { printf("memory allcation failed.\n"); CloseCapturePort(cp); return NULL; } // 取り込み完了イベントを生成します cp->hFrameComplete = CreateEvent(NULL, FALSE, FALSE, NULL); if (!cp->hFrameComplete) { printf("\"frame complete\"event create failed.\n"); CloseCapturePort(cp); return NULL; } cp->hCaptureStop = CreateEvent(NULL, FALSE, FALSE, NULL); if (!cp->hCaptureStop) { printf("\"capture stop\"evetn create failed.\n"); CloseCapturePort(cp); return NULL; } cp->pConfig->Destination.BufferId = cp->BufferId; cp->pConfig->Events.FrameComplete = cp->hFrameComplete; cp->pConfig->Events.CaptureStop = cp->hCaptureStop; if (strstr(info->CameraFile, "TRIG")) cp->pConfig->NRepeat = 0; /* ring buffer */ else cp->pConfig->NRepeat = 1; // 取り込みポートの設定を行います Status = cp->func->GingaPPSetConfiguration(cp->num, cp->pConfig); DriverErrorCheck(Status, "set configuration failed.\n"); return cp; } static void CloseCapturePort(CapturePort *port) { long ChannelStatus; long Status; DWORD WaitResult; if (!port) return; // 各チャンネルの取り込み状態を確認して、取り込みを終了します Status = port->func->GingaPPSenseStatus(port->num, &ChannelStatus); DriverErrorCheck(Status, "sense channel status failed.\n"); if(Status != GINGAPP_STATUS_IDLE) { Status = port->func->GingaPPAbortCapture(port->num); DriverErrorCheck(Status, "capture abort failed.\n"); WaitResult = WaitForSingleObject(port->hCaptureStop, TIMEOUT); if(WaitResult == WAIT_TIMEOUT) { printf("abort timeout.\n"); exit(0); } } // フレームバッファの解放を行います if (port->BufferId) port->func->GingaPPFreeFrameBuffer(port->BufferId); // 各イベントハンドルを解放します if (port->hFrameComplete) CloseHandle(port->hFrameComplete); if (port->hCaptureStop) CloseHandle(port->hCaptureStop); // 取り込み設定情報を解放します if (port->pConfig) port->func->GingaPPCloseConfiguration(port->pConfig); // 各チャンネルの設定情報構造体を解放します free(port); }