2013年6月10日月曜日

VMR-9 フィルタを使う

VMR-9 フィルタ グラフの作成

#include <dshow.h>

void main(void)
{
 IGraphBuilder *pGraph;
 IMediaControl *pMediaControl;
 ICaptureGraphBuilder2 *pBuild;

 // COM ライブラリを初期化する。
 HRESULT hr = CoInitialize(NULL);
 if (FAILED(hr))
 {
  printf("ERROR - Could not initialize COM library");
  return;
 }

 // フィルタ グラフ マネージャを作成し、インターフェイスを問い合わせる。
 hr = CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER, 
  IID_IGraphBuilder, (void **)&pGraph);
 if (FAILED(hr))
 {
  printf("ERROR - Could not create the Filter Graph Manager.");
  return;
 }

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

 IBaseFilter *pVmr = NULL;
 //CoCreateInstance を呼び出し、VMR-9 を作成する。
 hr = CoCreateInstance(CLSID_VideoMixingRenderer9, 0, 
  CLSCTX_INPROC_SERVER, IID_IBaseFilter, (void**)&pVmr);

 // VMR-9 をフィルタ グラフに追加する。
 hr = pGraph->AddFilter(pVmr, L"VMR9");


 // ビデオ ファイル用のソース フィルタを追加する。
 IBaseFilter *pSource;
 hr = pGraph->AddSourceFilter(L"G:\\sampleMovie\\avi_divx5_mp3.avi", L"Source", &pSource);

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

 // FilterGraphをセットする
 hr = pBuild->SetFiltergraph(pGraph);

 // ビデオ ストリームを VMR にレンダリングする。
 hr = pBuild->RenderStream(0, 0, pSource, 0, pVmr);
 //オーディオ ストリームをレンダリングする。
 hr = pBuild->RenderStream(0, &MEDIATYPE_Audio, pSource, 0, NULL);

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

 MessageBox(0,0,0,0);

 pMediaControl->Release();
 pBuild->Release();
 pGraph->Release();

 // COM終了
 CoUninitialize();
}
フィルタを表示させてみた

こんな感じか?

フィルタを表示させたときのソース
#include <dshow.h>

HRESULT EnumFilters (IFilterGraph *pGraph);

void main(void)
{
 IGraphBuilder *pGraph;
 IMediaControl *pMediaControl;
 ICaptureGraphBuilder2 *pBuild;

 // COM ライブラリを初期化する。
 HRESULT hr = CoInitialize(NULL);
 if (FAILED(hr))
 {
  printf("ERROR - Could not initialize COM library");
  return;
 }

 // フィルタ グラフ マネージャを作成し、インターフェイスを問い合わせる。
 hr = CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER, 
  IID_IGraphBuilder, (void **)&pGraph);
 if (FAILED(hr))
 {
  printf("ERROR - Could not create the Filter Graph Manager.");
  return;
 }

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

 IBaseFilter *pVmr = NULL;
 //CoCreateInstance を呼び出し、VMR-9 を作成する。
 hr = CoCreateInstance(CLSID_VideoMixingRenderer9, 0, 
  CLSCTX_INPROC_SERVER, IID_IBaseFilter, (void**)&pVmr);

 // VMR-9 をフィルタ グラフに追加する。
 hr = pGraph->AddFilter(pVmr, L"VMR9");


 // ビデオ ファイル用のソース フィルタを追加する。
 IBaseFilter *pSource;
 hr = pGraph->AddSourceFilter(L"G:\\sampleMovie\\avi_divx5_mp3.avi", L"Source", &pSource);

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

 // FilterGraphをセットする
 hr = pBuild->SetFiltergraph(pGraph);

 // ビデオ ストリームを VMR にレンダリングする。
 hr = pBuild->RenderStream(0, 0, pSource, 0, pVmr);
 //オーディオ ストリームをレンダリングする。
 hr = pBuild->RenderStream(0, &MEDIATYPE_Audio, pSource, 0, NULL);

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

 EnumFilters(pGraph);

 MessageBox(0,0,0,0);


 pMediaControl->Release();
 pBuild->Release();
 pGraph->Release();

 // COM終了
 CoUninitialize();
}

HRESULT EnumFilters (IFilterGraph *pGraph) 
{
 IEnumFilters *pEnum = NULL;
 IBaseFilter *pFilter;
 ULONG cFetched;

 // COM ライブラリを初期化する。
 HRESULT hr = CoInitialize(NULL);
 if (FAILED(hr))
 {
  printf("ERROR - Could not initialize COM library");
  return 0;
 }

 hr = pGraph->EnumFilters(&pEnum);
 if (FAILED(hr)) return hr;

 while(pEnum->Next(1, &pFilter, &cFetched) == S_OK)
 {
  FILTER_INFO FilterInfo;
  hr = pFilter->QueryFilterInfo(&FilterInfo);
  if (FAILED(hr))
  {
   MessageBox(NULL, TEXT("Could not get the filter info"),
    TEXT("Error"), MB_OK | MB_ICONERROR);
   continue;  // 次は正しく動く可能性がある。
  }

#ifdef UNICODE
  //MessageBox(NULL, FilterInfo.achName, TEXT("Filter Name"), MB_OK);
  //printf(FilterInfo.achName);
  wprintf(L"%s\n", FilterInfo.achName);
#else
  char szName[MAX_FILTER_NAME];
  int cch = WideCharToMultiByte(CP_ACP, 0, FilterInfo.achName,
   MAX_FILTER_NAME, szName, MAX_FILTER_NAME, 0, 0);
  if (chh > 0)
   MessageBox(NULL, szName, TEXT("Filter Name"), MB_OK);
#endif

  // FILTER_INFO 構造体はフィルタ グラフ マネージャへのポインタを保持する。
  // その参照カウントは解放しなければならない。
  if (FilterInfo.pGraph != NULL)
  {
   FilterInfo.pGraph->Release();
  }
  pFilter->Release();
 }

 pEnum->Release();
 return S_OK;
}

msdnのページでは、Capture Graph Builder を使いたくない場合の方法も書いてあったので、
とりあえずやってみた。
未整理のソースコード、一応動く程度

#include <dshow.h>

void main(void)
{
 IGraphBuilder *pGraph;
 IMediaControl *pMediaControl;

 // COM ライブラリを初期化する。
 HRESULT hr = CoInitialize(NULL);
 if (FAILED(hr))
 {
  printf("ERROR - Could not initialize COM library");
  return;
 }

 // フィルタ グラフ マネージャを作成し、インターフェイスを問い合わせる。
 hr = CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER, 
  IID_IGraphBuilder, (void **)&pGraph);
 if (FAILED(hr))
 {
  printf("ERROR - Could not create the Filter Graph Manager.");
  return;
 }

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

 IBaseFilter *pVmr = NULL;
 //CoCreateInstance を呼び出し、VMR-9 を作成する。
 hr = CoCreateInstance(CLSID_VideoMixingRenderer9, 0, 
  CLSCTX_INPROC_SERVER, IID_IBaseFilter, (void**)&pVmr);

 // VMR-9 をフィルタ グラフに追加する。
 hr = pGraph->AddFilter(pVmr, L"VMR9");


 // ビデオ ファイル用のソース フィルタを追加する。
 IBaseFilter *pSource;
 hr = pGraph->AddSourceFilter(L"G:\\sampleMovie\\cap.avi", L"Source", &pSource);

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

 // FilterGraphをセットする
 /*hr = pBuild->SetFiltergraph(pGraph);*/

 // ビデオ ストリームを VMR にレンダリングする。
 // hr = pBuild->RenderStream(0, 0, pSource, 0, pVmr);
 //オーディオ ストリームをレンダリングする。
 //hr = pBuild->RenderStream(0, &MEDIATYPE_Audio, pSource, 0, NULL);

 //ピンの列挙
 IFilterGraph* pFGraph;
 hr = pGraph->QueryInterface(IID_IFilterGraph, (void**)&pFGraph);

 IEnumFilters *pEnum = NULL;
 IBaseFilter *pFilter;
 ULONG cFetched;

 hr = pGraph->EnumFilters(&pEnum);
 if (FAILED(hr))
  return;

 //フィルタの列挙
 while(pEnum->Next(1, &pFilter, &cFetched) == S_OK) {
  IPin  *pPin = NULL;
  FILTER_INFO FilterInfo;

  hr = pFilter->QueryFilterInfo(&FilterInfo);

  wprintf(L"%s", FilterInfo.achName);
  printf(" フィルターが見つかった\n");

  //ピンを探しに行く
  IFilterGraph2 *pGraph2 = NULL;
  hr = pGraph->QueryInterface(IID_PPV_ARGS(&pGraph2));

  {
   IEnumPins  *pEnum;
   IPin       *pPin;
   IPin* pConnectedPin = NULL;

   hr = pFilter->EnumPins(&pEnum);
   if (FAILED(hr))
   {
    return ;
   }
    while(pEnum->Next(1, &pPin, 0) == S_OK)
    {
     // ピンが列挙される
     printf("pinの列挙--");
     PIN_DIRECTION PinDirThis;

     hr = pPin->QueryDirection(&PinDirThis);
     if ((hr == S_OK)&&(PinDirThis == PINDIR_INPUT))
     {
      printf("入力ピン--");// 
      hr = pPin->ConnectedTo(&pConnectedPin);//接続済みか調べる
      if (hr == S_OK)
      {
       printf("接続済み\n");// 
      }else{
       printf("未接続\n");// 
      }
     }

     if ((hr == S_OK)&&(PinDirThis == PINDIR_OUTPUT))
     {
      printf("出力ピン--");//
      hr = pPin->ConnectedTo(&pConnectedPin);//接続済みか調べる
      if (hr == S_OK)
      {
       printf("接続済み\n");// 
      }else
       printf("未接続\n");// 
      hr = pGraph2->RenderEx(pPin,AM_RENDEREX_RENDERTOEXISTINGRENDERERS, NULL);
     }

    }
  }

  // 見つかったピンを何かに使用
  if (pPin) {
   pPin->Release();
  }

  pFilter->Release();
 }

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

 MessageBox(0,0,0,0);

 pMediaControl->Release();
// pBuild->Release();
 pGraph->Release();

 // /COM終了
 CoUninitialize();
}


AM_RENDEREX_RENDERTOEXISTINGRENDERERS フラグを使って、IFilterGraph2::RenderEx を呼び出すと、既にグラフにあるレンダリング フィルタ のみを使い、出力ファイルがレンダリングされるそうです。

音は出ない。どうすればいいのだろうか?
サウンドフィルタの追加
 /*サウンド部分*/
 IBaseFilter *pAudioRenderer = NULL;
 hr = CoCreateInstance(CLSID_DSoundRender, NULL,
  CLSCTX_INPROC_SERVER, IID_IBaseFilter, (void **)&pAudioRenderer);

 hr = pGraph->AddFilter(pAudioRenderer, L"Audio Renderer");

0 件のコメント:

コメントを投稿