Video For Windowsを使うと、AVIファイル内の画像フレームを簡単に取り出すことができます。コーデックで圧縮されていても、(対応コーデックなら)任意のフレームを指定した形式のDIBとして取得できるので、AVIの形式をほとんど意識することなく取得したフレームの処理に重点を置いて開発できるので、なかなか便利です。 ビデオストリームとフレームの取得実際のAVIファイル内のフレーム取得は、
という流れで行います。 AVIファイルを開く処理は、AVIFileOpen()にAVIファイルのファイルインターフェース(ハンドル)を格納するPAVIFILE型ポインタ、ファイルパスと開くときのオプション(読み取り専用、他のプロセスとの共有設定)を渡して行います。関数が成功するとポインタにファイルインターフェースが入ってくるので、続いてファイルインターフェースを使ってファイル内のビデオストリームを開きます。この関数の戻り値は、「0なら成功」という意味なので注意してください。 ストリームを開く処理もファイルと同様に、ストリームインターフェースのポインタを渡すとそのポインタに取得したストリームを操作するためのストリームインターフェースが入ってきます。 /* AVIファイルを開く */ AVIFileOpen(&pfAvi, lpszAviFilePath, OF_READ, NULL); /* AVIのビデオストリーム取得 */ AVIFileGetStream(pfAvi, &psAvi, streamtypeVIDEO, 0); ストリームを開いたら(別にその前にやっておいてもかまいませんが)、フレームデータとして取得するDIBの形式を指定します。この形式の設定はライブラリ任せにもできますが、実際にフレームのデータを使って処理をすることを考えると自分の都合の良い形式を設定しておいたほうが後で楽でしょう。具体的には、取得するフレームデータのBITMAPINFOHEADERを設定します。これで、フレームの内容を指定した形式のピクセル列として取得できるようになるわけです。 なお、BITMAPINFOHEADERに指定するDIBのサイズは、予めAVIのフレームサイズをAVIFileInfo()などで取得しておき、それをそのまま使えばよいでしょう。 フレームの形式を設定したら、そのBITMAPINFOのポインタとストリームインターフェースをAVIStreamGetFrameOpen()に渡せば、フレーム取得の準備は完了です。関数が成功すると、フレームの取得時に使うPGETFRAMEが返ってきます。 ZeroMemory(&bmiFrame, sizeof(BITMAPINFOHEADER)); /* 取得するDIBの形式設定 */ bmiFrame.biSize = sizeof(BITMAPINFOHEADER); bmiFrame.biPlanes = 1; bmiFrame.biBitCount = 32; bmiFrame.biWidth = iAviWidth; bmiFrame.biHeight = iAviHeight; pgfFrame = AVIStreamGetFrameOpen(psAvi, &bmiFrame); あとは、取得したいフレームを指定してAVIStreamGetFrame()を呼び出せば、そのフレームの内容が指定した形式のDIBメモリイメージのポインタとして返されます。ただし、このポインタの有効期間は次にAVIStreamGetFrame()を呼ぶかAVIStreamGetFrameClose()を呼び出すまでなので、一時的な処理以外の目的で使うのなら自分で確保したバッファにコピーしておきましょう。 /* フレームデータ用バッファ確保 */ lpData = GlobalAlloc(GPTR, sizeof(BITMAPINFOHEADER) + iAviWidth * iAviHeight * 3); /* フレームデータをバッファにコピー */ CopyMemory(lpData, lpTmp, sizeof(BITMAPINFOHEADER) + iAviWidth * iAviHeight * 3); フレームを取得し終えたら、AVIStreamGetFrameClose()を呼び出してフレーム取得を終了し、ストリームとAVIファイルを閉じます。 AVIStreamGetFrameClose(pgfFrame); /* ストリーム解放 */ AVIStreamRelease(psAvi); /* AVIファイル解放 */ AVIFileRelease(pfAvi); 以上で、フレームを取得する処理は終了です。 プログラム今回は、ソース内で指定したAVIの各フレームをウインドウ上に表示し、マウスの右/左クリックでフレームを移動するプログラムを作ってみました。まず、ソース冒頭の LPCTSTR lpszAviFilePath = "C:\\test.avi"; という部分を、適当なAVIファイルのパスに変えてください。その後実行すると、指定したAVIファイルのフレームが表示されるはずです。ウインドウ上でマウスを右/左クリックして、他のフレームも表示してみてください。 なお、今回のプログラムではDIBの4バイト境界への対応を省略しているので、AVIファイルのフレームの横幅は4の倍数ピクセルになっている必要があります。 |