- 締切済み
WinAPI Directshow 動画
WindowsプログラミングでDirectshowを使って動画処理をしています。 最終的には、動画処理した結果をウィンドウに順に表示させていくプログラムを作りたいです。 そのため、まずは、下の手順のようなプログラムを現在作っています。 (1) 動画を1フレームごとに取り込む (2) 情報をビットマップに書き出す (3) ビットマップを読み込む (4) ウィンドウに描画する (5) (1)~(4)を繰り返す プログラムはVisualStudio2005を使い、ウィンドウズアプリケーションで作成しています。 ウィンドウにビットマップが表示されてほしいのですが、何も表示されません。 2週間悩んでいますが、解決しません;; 以下にソースを貼らせていただきますので、アドバイスいただきたいです。 ※ソースの量が多いので、WM_TIMER, WM_PAINTの部分を中心に載せています。 (その他の部分は、最初から書かれているソースからほぼ変更していないです) なお、WM_TIMER部分については、文字数の関係から別アカウントから回答1に書かせていただきます。 ----------------------- <追加グローバル宣言> int douga_flag=0; //メニューで動画処理を選ぶと1になります IGraphBuilder *pigb = NULL; /* フィルタグラフ用 */ IMediaControl *pimc = NULL; IMediaSeeking *pims = NULL; IBaseFilter *pibf = NULL; /* サンプルグラブ用 */ ISampleGrabber *pisg = NULL; IVideoWindow *pivw =NULL; AM_MEDIA_TYPE amt; HRESULT hr; OAFilterState fs; long n; LONGLONG nn1, flame_number; CImage1 gazou; /* ビットマップ画像のクラス */ // gazou.width(横サイズ), gazou.height(縦サイズ), gazou.bmmap_data(画像情報の入った配列) /* 動画→lpBmpDataに情報がはいる */ typedef struct { HINSTANCE hi; int x; // 表示開始位置 int y; HWND hwnd; // 自分のウィンドウハンドル BYTE *lpBmpData; // BMPのデータ部分 BITMAPINFOHEADER bih; } IMG0; IMG0 img00; ----------------------- <WndProc(主に WM_PAINT のソース)> LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { int wmId, wmEvent; int id, ww, hh; PAINTSTRUCT ps; HBITMAP hBmp, hBmpOld; BITMAP bmp_info; HDC hdc, hdc_mem; switch (message) { ...省略... case WM_TIMER: //文字数の関係から別アカウントから回答1に書きます break; case WM_PAINT: hdc = BeginPaint(hWnd, &ps); hdc_mem = CreateCompatibleDC(hdc); hBmp = LoadBitmap(hInst, TEXT("bitmap.bmp")); GetObject(hBmp, (int)sizeof(BITMAP), &bmp_info); ww = bmp_info.bmWidth; hh = bmp_info.bmHeight; hBmpOld = (HBITMAP)SelectObject(hdc_mem, hBmp); BitBlt(hdc, 0, 0, ww, hh, hdc_mem, 0, 0, SRCCOPY); SelectObject(hdc_mem, hBmpOld); DeleteDC(hdc_mem); DeleteObject( hBmp ); // ロードしたビットマップを削除する EndPaint(hWnd, &ps); break; ...省略... }
- みんなの回答 (1)
- 専門家の回答
みんなの回答
- TAE_spring2
- ベストアンサー率0% (0/0)
質問者のTae_Springです。 WM_TIMERのソースを以下に貼らせていただきます。 なお、TIMERについてですが、既存のInitInstance関数でウィンドウの作成をした後、 SetTimer(hWnd, 100, 500, NULL); と設定しています。 (とりあえず500ミリセカンドで1回描画していくようにしています) ---------------------- <WM_TIMER のソース> case WM_TIMER: if(douga_flag==1) { /* (1)1回目だけおこなう処理 */ if(nn1==0) { gazou.open_bmmap("dummy.bmp"); //自作のビットマップ読み込み関数 // bitmap.bmpと同じ規格のdummy.bmpを読み込むことでビットマップ情報を先に取得しておく // これにより、gazou.widthに横、gazou.heightに縦のサイズがはいり、 // gazou.bmmap_dataという動画処理用の配列を取得する // COMの準備 + FilterGraph,GrabberFilter等の設定 <ソース省略> // 再生するファイルを指定 hr = pigb -> RenderFile(TEXT("MOVIE.avi"), NULL ); // ビットマップ情報の取得 pisg -> GetConnectedMediaType( &amt ); // ビデオヘッダーには、ビットマップ情報が含まれる。 n = amt.lSampleSize; img00.bih = ((VIDEOINFOHEADER*)amt.pbFormat) -> bmiHeader; img00.lpBmpData = (BYTE *)malloc( amt.lSampleSize ); // シークをフレーム単位で行うよう設定 hr = pims -> SetTimeFormat( &(TIME_FORMAT_FRAME) ) ; pims -> GetDuration(&flame_number); // グラブ開始 pisg -> SetBufferSamples(TRUE); } /* (2)動画抽出 or 動画の最後に行う処理 */ if( nn1 <= flame_number){ // 動画情報を抽出する部分 pims -> SetPositions( &nn1, AM_SEEKING_AbsolutePositioning, &nn1, AM_SEEKING_AbsolutePositioning );// シーク pimc -> StopWhenReady();// シークしてレンダリング pimc -> GetState( INFINITE, & fs);// レンダリング完了を待つ pisg -> GetCurrentBuffer( &n, (long*)img00.lpBmpData );// グラブ InvalidateRect( hWnd, NULL, FALSE); // 表示 nn1++; // lpBmpDataの値を、ビットマップ表示用配列にコピー for(int j=0; j<gazou.height; j++){ for(int i=0; i<gazou.width; i++){ gazou.bmmap_data[(j*gazou.width+i)*3] = int(img00.lpBmpData[(j*gazou.width+i)*3]); gazou.bmmap_data[(j*gazou.width+i)*3+1] = int(img00.lpBmpData[(j*gazou.width+i)*3+1]); gazou.bmmap_data[(j*gazou.width+i)*3+2] = int(img00.lpBmpData[(j*gazou.width+i)*3+2]); } } // 自作のビットマップ書き込み関数→gazou.bmmap_dataの情報からbitmap.bmpを作成 gazou.out_bmmap("bitmap.bmp"); }else{ // FilterGraph他の開放 pigb -> Release(); pimc -> Release(); pims -> Release(); pibf -> Release(); pisg-> Release(); CoUninitialize(); nn1=0; douga_flag=0; //←これで動画処理をぬける } } break; 以上となります。 よろしくお願いします。