ビデオ入力デバイスからの映像をAVIに保存する

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

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

まず、何も考えずに以下のコードを書いてみましょう。 このコードは、最初に発見したビデオ入力デバイスをAVIに保存します。 例えば、一番最初に発見したビデオキャプチャデバイスがアナログのテレビチューナーデバイスであった場合、テレビ映像が保存されます。 ビデオカメラを一番最初に発見した場合にはビデオカメラからの映像が保存されます。

AVIへの保存は、出力先のRendererを画面表示ではなくAVIファイルにすることにより実現します。 保存先の指定はICaptureGraphBuilder2のSetOutputFileNameメソッドを利用して行います。 指定したAVIファイルへ出力するGraphを作成するためには、RenderStreamにSetOutputFileNameから取得したAVIファイル出力用フィルタを渡します。


#include <stdio.h>

#include <dshow.h>

// 保存するファイル名
#define	OUTPUTFILENAME	L"save.avi"

int
main()
{
 IGraphBuilder *pGraphBuilder;
 ICaptureGraphBuilder2 *pCaptureGraphBuilder2;
 IMediaControl *pMediaControl;

 IFileSinkFilter *pSink;
 IBaseFilter *pFileOut;


 ICreateDevEnum *pCreateDevEnum = NULL;
 IEnumMoniker *pEnumMoniker = NULL;
 IMoniker *pMoniker = NULL;

 ULONG nFetched = 0;
 IBaseFilter *pDeviceFilter;

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

 // FilterGraphを生成
 CoCreateInstance(CLSID_FilterGraph,
	NULL,
	CLSCTX_INPROC,
	IID_IGraphBuilder,
	(LPVOID *)&pGraphBuilder);

 // CaptureGraphBuilder2というキャプチャ用GraphBuilderを生成する
 CoCreateInstance(CLSID_CaptureGraphBuilder2, NULL, CLSCTX_INPROC, 
   IID_ICaptureGraphBuilder2, 
   (LPVOID *)&pCaptureGraphBuilder2);

 // FilterGraphをセットする
 pCaptureGraphBuilder2->SetFiltergraph(pGraphBuilder);

 // MediaControlインターフェース取得
 pGraphBuilder->QueryInterface(IID_IMediaControl,
	(LPVOID *)&pMediaControl);

 // デバイスを列挙するための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を取得
 pEnumMoniker->Next(1, &pMoniker, &nFetched);

 // MonkierをFilterにBindする
 pMoniker->BindToObject(0, 0, IID_IBaseFilter, (void**)&pDeviceFilter );

 // FilterGraphにデバイスフィルタを追加する
 pGraphBuilder->AddFilter(pDeviceFilter, L"Device Filter");

 // この時点でMonkier系、Enumerator系は用済み
 pMoniker->Release();
 pEnumMoniker->Release();
 pCreateDevEnum->Release();

 // 出力ファイル名を設定する
 pCaptureGraphBuilder2->SetOutputFileName(&MEDIASUBTYPE_Avi,
   OUTPUTFILENAME, &pFileOut, &pSink);

 // Graphを生成する
 pCaptureGraphBuilder2->RenderStream(&PIN_CATEGORY_CAPTURE,
   NULL, pDeviceFilter, NULL, pFileOut);

 // 再生開始
 pMediaControl->Run();

 // 再生中にプログラムが終わってしまわないように。
 // OKが押されるまで保存を行います
 MessageBox(NULL,
	"Block Execution",
	"Block",
	MB_OK);

 // 資源を解放
 pMediaControl->Release();
 pCaptureGraphBuilder2->Release();
 pGraphBuilder->Release();

 pFileOut->Release();
 pSink->Release();

 // COM終了
 CoUninitialize();

 return 0;
}


例の中で利用しているMessageBoxは、アプリケーションが終了してしまわないようにブロックするためにあります。 MessageBoxの「OK」ボタンをクリックするとAVIへの保存は終了します。

このサンプルは最も基本的な機能だけに絞り込んでいるため、これだけでは使えません。 入力デバイスを選んだり、発見したデバイスの情報を表示したりする方法は別ページの説明をご覧下さい。

IPv6基礎検定

YouTubeチャンネルやってます!