SSブログ

OS X用GigE Visionカメラドライバ - その32 [OS X用GigE Vision]

前々回前回でGEN<i>CAMのなかのGenApi規格の僕が気に入らない部分を列挙した。プログラマから見ればそれほど無茶は言っていないとわかってくれるだろう思っている。少なくとも僕の後輩がこういう設計をしていたら注意するだろう、という項目をあげたつもりである。

しかし、気にいる気に入らないに関わらずすでに規格として成立していてそれに準拠した製品がどんどん出ているので、ガタガタ言っても仕方がない。独自実装するためにはこのGenApiと、もうひとつGenTLを実装しないといけない。ということでGenTLのほうもざっくりみることにする。

6.3  GenTLの概要

独自実装のためにはGenTLの部分も必要だけど、GenApiと整合を取らないといけない。実装の参考にするためGenTLがどうなっているのかをGenTL1.4(pdf)に基づいて簡単にまとめておく。実際に動かしたわけではないし、かといって単なる翻訳でもないので「...らしい」「...と書いてある」「...だろう」などといちいち書いていたけど、ウザいのでぜんぶやめた。間違ってたらごめんなさい。って、いつもと何も変わらんじゃん。

GenTLはCのAPIを持っているが、オブジェクト指向風に作られていて、オブジェクト指向言語と矛盾しないようになっている(たとえば静的変数を使わないとか)。オブジェクトはハンドルの形(おそらく実態はポインタ型)で与えられる。

GenTLは5つのモジュールからなっているという。
  1. System
  2. Interface
  3. Device
  4. Stream
  5. Buffer
SystemモジュールはGenTL全体を管理する。Interfaceモジュールはカメラデバイスとの具体的な接続方法を抽象化している。GigE VisionだったりIIDC/1394だったりする。Systemモジュールは複数のInterfaceモジュールを持つことができる。ソフトウェアのデザインパターンで言えばSystemモジュールはファクトリメソッド専用オブジェクトのようなものである。

Deviceモジュールは具体的なカメラデバイスを抽象化する。あるInterfaceモジュールは複数のDeviceモジュールを持つことができる。Streamモジュールは画像などのデータストリームを抽象化する。あるDeviceモジュールは複数のStreamモジュールを持つことができる。

Bufferモジュールは画像1フィールド分などのメモリバッファを抽象化する。

規格書にはこの図のように描かれている。カメラをモデル化して実装するならごく普通の考え方だろうと思う。このモデルで言えばGenApiはDeviceモジュールと同じレベルということになる。
0323gentl.png
まずGenTLを使うためにはSetupを行う必要がある。
GC_ERROR GCInitLib ( void );
GC_ERROR GCCloseLib ( void );
これでライブラリ全体の初期化とリソースの解放が行われる。GCInitLib()が成功すると
GC_ERROR GCGetInfo ( TL_INFO_CMD iInfoCmd,
INFO_DATATYPE * piType, void * pBuffer, size_t * piSize );
を使ってGenTLの実装に関する情報が得られる。

Systemモジュールを使うためには
GC_ERROR TLOpen ( TL_HANDLE * phSystem );
GC_ERROR TLClose ( TL_HANDLE hSystem );
を呼ぶ。TLOpenが成功するとphSystemにTL_HANDLE型のSystemモジュールが設定される。
GC_ERROR TLGetNumInterfaces (TL_HANDLE hSystem, uint32_t * piNumIfaces );
GC_ERROR TLUpdateInterfaceList (TL_HANDLE hSystem,
                                bool8_t *pbChanged,
                                uint64_t iTimeout );
GC_ERROR TLGetInterfaceID (TL_HANDLE hSystem,
                           uint32_t iIndex,
                           char *sIfaceID,
                           size_t *piSize );
などで利用可能なInterfaceの情報が得られる。

特定のInterfaceは
GC_ERROR TLOpenInterface (TL_HANDLE hSystem,
                          const char *sIfaceID,
                          IF_HANDLE *phIface );
GC_ERROR IFClose (IF_HANDLE hIface );
で確保解放できる。IF_HANDLEというのがInterfaceへのハンドルである。

同じパターンでInteerfaceにはDeveiceのための
GC_ERROR IFGetNumDevices (IF_HANDLE hIface, uint32_t * piNumDevices);
GC_ERROR IFUpdateDeviceList (IF_HANDLE *hIface,
                             bool8_t pbChanged,
                             uint64_tiTimeout);
GC_ERROR IFGetDeviceInfo (IF_HANDLE hIface,
                          const char * sDeviceID,
                          DEVICE_INFO_CMD iInfoCmd,
                          INFO_DATATYPE * piType,
                          void * pBuffer, 
                          size_t * piSize);
があって、利用可能なデバイスの情報が得られる。

同じようにDeviceは
GC_ERROR IFOpenDevice (IF_HANDLE hIface,
                       const char * sDeviceID,
                       DEVICE_ACCESS_FLAGS iOpenFlags,
                       DEV_HANDLE * phDevice);
でハンドルが得られる。Deviceには
GC_ERROR DevGetPort (DEV_HANDLE hDevice, PORT_HANDLE * phRemoteDev);
GC_ERROR DevOpenDataStream (DEV_HANDLE hDevice,
                            const char *sDataStreamID,
                            DS_HANDLE *phDataStream);
があってPortハンドルとDataStreamハンドルを得ることができる。

Portハンドルには
GC_ERROR GCGetPortInfo (PORT_HANDLE hPort,
                        PORT_INFO_CMD iInfoCmd,
                        INFO_DATATYPE * piType,
                        void * pBuffer, size_t * piSize);
GC_ERROR GCGetPortURL (PORT_HANDLE hPort,
                       char * sURL,
                       size_t * piSize);
GC_ERROR GCGetNumPortURLs (PORT_HANDLE hPort,
                           uint32_t * piNumURLs);
GC_ERROR GCGetPortURLInfo(PORT_HANDLE hPort,
                          uint32_t iURLIndex,
                          URL_INFO_CMD iInfoCmd,
                          INFO_DATATYPE *piType,
                          void *pBuffer,
                          size_t *piSize);
GC_ERROR GCReadPort (PORT_HANDLE hPort,
                     uint64_t iAddress,
                     void *pBuffer,
                     size_t *piSize);
GC_ERROR GCWritePort (PORT_HANDLE hPort,
                      uint64_t iAddress,
                      const void * pBuffer,
                      size_t * piSize);
GC_ERROR GCWritePortStacked (PORT_HANDLE hPort,
                             PORT_REGISTER_STACK_ENTRY *pEntries,
                             size_t *piNumEntries);

GC_ERROR GCReadPortStacked (PORT_HANDLE hPort,
                            PORT_REGISTER_STACK_ENTRY *pEntries,
                            size_t *piNumEntries);
などの関数がある。デバイスの情報を得たり、メモリ空間を読み書きする関数がある。GCGetPortURL()はGEN<i>CAM規格のXMLファイルのURLを得るものらしい(やっぱりGenApiとGenTLはそれぞれ別に対応しないといけないということなのね。わかってたけど)。URLがデバイス内を示していたらGCReadPort()で読み込んでGenApiのノードツリーを作ることになる。

これ以外にカメラデバイス側からのイベントに応答するためのものなどがある。 GenTLはおおまかには以上のような素直なAPIになっている。
nice!(0)  コメント(0)  トラックバック(0) 

nice! 0

コメント 0

コメントを書く

お名前:
URL:
コメント:
画像認証:
下の画像に表示されている文字を入力してください。

トラックバック 0

この広告は前回の更新から一定期間経過したブログに表示されています。更新すると自動で解除されます。