ビデオ入力デバイス情報を取得する

ここでは、ビデオカメラ(デスクトップカメラ、DVカメラなど)やTVチューナーデバイスの情報を取得する方法を説明したいと思います。 (注意)ここの例では、サンプルを簡潔にするためにエラー処理を書いていません。

とりあえず、コードを書いてみる

前述したビデオキャプチャデバイス情報サンプルは、FriendlyNameだけ取得していました。 FriendlyNameだけの取得では、同じ種類のデバイスが複数あったときにどれがどれだかわからなくなってしまいます。 ここでは、IPropertyBagを利用して取得できるビデオキャプチャデバイスに関する情報全てを取得するサンプルを示します。 例えば、一番最初に発見したビデオキャプチャデバイスがDVカメラであった場合、MessageBoxで以下のように表示されます。

FriendlyName : Microsoft DV Camera and VCR
Description  : AVC Compliant DV Device
DevicePath   : \\?\avc#aaa&xx-dv111&camcoder&dv#123456#{abcd-1111-aaa-ccc}\global

#include <stdio.h>

#include <dshow.h>

int
main()
{
 // 補足情報)英単語の日本語訳
 //   Enumerate : 列挙、一覧
 //   Moniker   : あだ名
 ICreateDevEnum *pCreateDevEnum = NULL;
 IEnumMoniker *pEnumMoniker = NULL;
 IMoniker *pMoniker = NULL;
 ULONG nFetched = 0;

 // COMを初期化
 CoInitialize(NULL);

 // デバイスを列挙するためのCreateDevEnumを生成
 CoCreateInstance(CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC_SERVER, 
   IID_ICreateDevEnum, (PVOID *)&pCreateDevEnum);
    
 // VideoInputDeviceを列挙するためのEnumMonikerを生成 
 pCreateDevEnum->CreateClassEnumerator(CLSID_VideoInputDeviceCategory,
   &pEnumMoniker, 0);
 if (pEnumMoniker == NULL) {
   // 接続された映像入力デバイスが一つも無い場合にはこのif文に入ります
   printf("no device\n");
   return 0;
 }

 // EnumMonikerをResetする
 // Resetすると、先頭から数えなおします
 pEnumMoniker->Reset();

 // 最初のMonikerを取得
 while (pEnumMoniker->Next(1, &pMoniker, &nFetched) == S_OK) {
   IPropertyBag *pPropertyBag;
   TCHAR devname[256];
   TCHAR description[256];
   TCHAR devpath[256];

   // IPropertyBagにbindする
   pMoniker->BindToStorage(0, 0, IID_IPropertyBag,
     (void **)&pPropertyBag);

   VARIANT var;


   // FriendlyNameを取得
   // FrienlyName : The name of the device
   var.vt = VT_BSTR;

   pPropertyBag->Read(L"FriendlyName", &var, 0);

   WideCharToMultiByte(CP_ACP, 0,
     var.bstrVal, -1, devname, sizeof(devname), 0, 0);

   VariantClear(&var);


   // Descriptionを取得
   // Description : A description of the device
   var.vt = VT_BSTR;

   pPropertyBag->Read(L"Description", &var, 0);

   WideCharToMultiByte(CP_ACP, 0,
     var.bstrVal, -1, description, sizeof(description), 0, 0);

   VariantClear(&var);


   // DevicePathを取得
   // DevicePath : A unique string
   var.vt = VT_BSTR;

   pPropertyBag->Read(L"DevicePath", &var, 0);

   WideCharToMultiByte(CP_ACP, 0,
     var.bstrVal, -1, devpath, sizeof(devpath), 0, 0);

   VariantClear(&var);


   // 結果を表示
   TCHAR result[1024];

   memset(result, 0, sizeof(result));
   sprintf(result,
	   "FriendlyName : %s\r\n"
	   "Description  : %s\r\n"
	   "DevicePath   : %s\r\n",
	   devname, description, devpath);

   MessageBox(NULL, result, "RESULT", MB_OK);


   // 資源を解放
   pMoniker->Release();
   pPropertyBag->Release();
 }

 // 資源を解放
 pEnumMoniker->Release();
 pCreateDevEnum->Release();

 // COM終了
 CoUninitialize();

 return 0;
}

このサンプルから得られる情報を選択可能リストUIなどと組み合わせたりするとキャプチャに利用するデバイスを動的に選択できるアプリケーションを作成できたりします。 上記サンプルが何かの役に立てば幸いです。