Sample Grabberのサンプルプログラムの実行について

解決


m.okada  2006-11-08 01:20:30  No: 63519

以下に、Sample Grabberを使用した、サンプルプログラムです。
内容は、動画を再生しOKボタンを押した時のフレームをビットマップとして保存するものです。

このプログラム自体はサンプルを提供してくださる方のサイトで拾ったものなのですが、このサンプルを実行するにはどのような設定をしたらいいのでしょうか。C言語でのプログラムは経験ありますが、VC++は初めてなのでアドバイスいただけたら嬉しいです。

わからないことは、上で述べた設定のことと、以下のサンプルプログラムをどのソースファイルのどこに埋め込むのか、という点です。お願いします。

環境は、Microsoft Visual Studio .NET 2003です。

#include <stdio.h>

#include <dshow.h>
#include <qedit.h> // SampleGrabber用

#define  FILENAME L"C:\\DXSDK\\Samples\\Media\\butterfly.mpg"

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

 IBaseFilter *pSampleGrabberFilter;
 ISampleGrabber *pSampleGrabber;
 AM_MEDIA_TYPE am_media_type;

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

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

 // SampleGrabber(Filter)を生成
 CoCreateInstance(CLSID_SampleGrabber,
   NULL,
   CLSCTX_INPROC,
   IID_IBaseFilter,
   (LPVOID *)&pSampleGrabberFilter);

 // FilterからISampleGrabberインターフェースを取得します
 pSampleGrabberFilter->QueryInterface(IID_ISampleGrabber,
   (LPVOID *)&pSampleGrabber);

 // SampleGrabberを接続するフォーマットを指定。
 // ここがポイントです。
 // ここの指定の仕方によりSampleGrabberの挿入箇所を
 // 決定できます。このサンプルのような指定をすると
 // 画面出力の寸前でサンプルを取得できます。
 ZeroMemory(&am_media_type, sizeof(am_media_type));
 am_media_type.majortype = MEDIATYPE_Video;
 am_media_type.subtype = MEDIASUBTYPE_RGB24;
 am_media_type.formattype = FORMAT_VideoInfo;
 pSampleGrabber->SetMediaType(&am_media_type);

 // GraphにSampleGrabber Filterを追加
 pGraphBuilder->AddFilter(pSampleGrabberFilter,
   L"Sample Grabber");

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

 // Graphを生成。
 // ここでSampleGrabberを含んだGraphが自動的に作成されます。
 pMediaControl->RenderFile(FILENAME);

 // 接続情報取得。
 // この処理はRenderFileによりGraphが構成された後に
 // 行う必要があります。
 pSampleGrabber->GetConnectedMediaType(&am_media_type);
 VIDEOINFOHEADER *pVideoInfoHeader =
     (VIDEOINFOHEADER *)am_media_type.pbFormat;

 // 画像(映像)の幅と高さを表示
 // サンプルをわかりやすくするために表示しているだけなので、
 // 必ず必要というわけではありません。
 printf("size = %dx%d\n",
   pVideoInfoHeader->bmiHeader.biWidth,
   pVideoInfoHeader->bmiHeader.biHeight);

 // データサイズを表示
 // これも説明のために表示しています。
 printf("sample size = %d\n",
   am_media_type.lSampleSize);

 // Grabを行う事を設定
 // SetBufferSamplesを行わないとバッファから
 // データを取得できません。
 // 不必要に負荷をかけたくない場合にはFALSEにしておいて、
 // データを取得したくなったら、TRUEに変える
 // という方法もできます。
 pSampleGrabber->SetBufferSamples(TRUE);

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

 // 再生中にプログラムが終わってしまわないように
 MessageBox(NULL,
  "Block Execution",
  "Block",
  MB_OK);

 // OKが押されるとBITMAPを保存する

 // バッファを用意
 long nBufferSize = am_media_type.lSampleSize;
 long *pBuffer = (long *)malloc(nBufferSize);

 // 現在表示されている映像を静止画として取得
 pSampleGrabber->GetCurrentBuffer(&nBufferSize,
     pBuffer);

 //
 // Bitmapに保存。
 // このサンプルではキャプチャ結果を見るために
 // Bitmapに保存しています。
 //
 HANDLE fh;
 BITMAPFILEHEADER bmphdr;
 DWORD nWritten;

 memset(&bmphdr, 0, sizeof(bmphdr));

 bmphdr.bfType = ('M' << 8) | 'B';
 bmphdr.bfSize = sizeof(bmphdr) + sizeof(BITMAPINFOHEADER) + nBufferSize;
 bmphdr.bfOffBits = sizeof(bmphdr) + sizeof(BITMAPINFOHEADER);

 fh = CreateFile("result.bmp",
   GENERIC_WRITE, 0, NULL,
   CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
 WriteFile(fh, &bmphdr, sizeof(bmphdr), &nWritten, NULL);
 WriteFile(fh,
     &pVideoInfoHeader->bmiHeader,
     sizeof(BITMAPINFOHEADER), &nWritten, NULL);
 WriteFile(fh, pBuffer, nBufferSize, &nWritten, NULL);
 CloseHandle(fh);

 free(pBuffer);

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

 // COM終了
 CoUninitialize();

 return 0;
}


モーヲタ  2006-11-10 08:43:13  No: 63520

>このサンプルを実行するにはどのような設定をしたらいいのでしょうか
>どのソースファイルのどこに埋め込むのか
んー、このような質問が出るということはもっと別の事を
勉強すべきと思いますね。別の事とは基本をもっと勉強すべきと
思いますね。

それだけだとかわいそうなのでちょっとヒントを。

>このサンプルを実行するにはどのような設定をしたらいいのでしょうか
これはまずDirectShowというMicrosoftが提供しているAPIを
開発環境PCにインストールしないといけません。DirectShowは
Plattoform SDKといういろんなコンポーネントがつまった中の
一つです。まずはこのPlattoform SDKをMicrosoftのHPからDL
してインストールしてください。

次に開発環境の設定は必要ヘッダなどのパスやらライブラリやらを
設定してください。→DirectShowのインストール先にIncludeや
libができているはずなので。

>どのソースファイルのどこに埋め込むのか
サンプルそのままでOKです。但し、コンソールプロジェクト
又はWin32プロジェクトでないと動かないでしょうね・・・そのままでは。
一つ言っておきますと、このサンプルをそのままコピペしても
まともな動作はしないでしょう。ホントに単純に動画ファイル
をOPENして静止画出力してすぐに終了しているから。
通常は動画を再生しながら好きな位置で静止画を出力しますよね?
つまりそのような作りに変える必要があります。

よって、DirectShowについて勉強してください。また、
再生する動画ファイルによっては別途コーデックが必要です。
コーデックについてはネットで調べてください。
でないと後先困るのはあなた自身です。

#私は市販されているDirectX 9.0cの本とネットでDirectShowを学びました。


m.okada  2006-11-15 20:33:07  No: 63521

モーヲタさんありがとうございます。

サンプルを試しに動かしてみることで、VC++をどんなものなのか理解できるのではないかという甘い気持ちでした・・・

モーヲタさんのヒントを参考に、勉強してみます。ありがとうございました☆


※返信する前に利用規約をご確認ください。

※Google reCAPTCHA認証からCloudflare Turnstile認証へ変更しました。






  このエントリーをはてなブックマークに追加