DirectShowでスムーズにフレーム取得するには


ふうこ  2012-07-04 23:38:13  No: 73454  IP: 192.*.*.*

DirectShowについてネットで調べながら勉強しています。
映像を単に再生するのはできたので、映像をランダムに再生して見てみたらどうなるのだろうと思い、試しに映像を読み込んで指定したフレームを1つ取得する関数を作ってみましたが、ループさせるとフレームレートが低くて困っています。

どなたか、ご教授いただけませんでしょうか?
環境はwindowsXPでvisualstudio2008を使用しています。

以下は関数になります。

oid Get_Image(){
  // サンプルグラバーを使って動画からの静止画キャプチャ
  // 変数
  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を接続するフォーマットを指定。
  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(L"test.mpg");

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

  // Grabを行う事を設定
  // SetBufferSamplesを行わないとバッファからデータを取得できない
  pSampleGrabber->SetBufferSamples(TRUE);

  // ワンショット(1/2)
  // SetOneShotをTRUEにすると画像を1枚だけ取得してgraphをstop状態にできる
  pSampleGrabber->SetOneShot(TRUE);

  // 再生開始
  pMediaControl->Run();
 
  //指定したいフレームにセット
  long long set_num = 100;  //適当な値
  
  SetFramePosition(pGraphBuilder, set_num);   //フレームをセットする自作の関数を呼び出し

  // ワンショット(2/2)
  // graphが終了するのを待つ
  IMediaEvent *pEvent;
  pGraphBuilder->QueryInterface(IID_IMediaEvent, (LPVOID *)&pEvent);
  long evCode;
  pEvent->WaitForCompletion(INFINITE, &evCode);

  // バッファを用意
  long nBufferSize = am_media_type.lSampleSize;
  long *pBuffer = new long[nBufferSize];

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

  //画像表示(省略)//

  delete[] pBuffer;

  pMediaControl->Stop();

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

  // COM終了
  CoUninitialize();
}

編集 削除
fdsa  2012-09-01 01:38:05  No: 73455  IP: 192.*.*.*

メディアタイプとかメディアプロパティが正しく設定できてないと起こることの有る現象ですね。

あと本題ではないんだけど、XPと2008を開発環境にしてる理由はなに?w
それはそれでいいんだけどちと古くないかね。

編集 削除