• ベストアンサー
※ ChatGPTを利用し、要約された質問です(原文:VC++ DirectShow グラフにフィルターを追加する方法)

VC++でDirectShowのグラフにフィルターを追加する方法

このQ&Aのポイント
  • VC++でDirectShowを使用して、ビデオキャプチャデバイスからファイルに保存する方法について説明します。
  • 保存する際には、圧縮を行いたい場合はMicrosoft Video 1というフィルターを追加する必要があります。
  • 初心者の方には、MSDNなどの情報が理解しにくい場合もあるため、簡単なサンプルがあれば助かるでしょう。

質問者が選んだベストアンサー

  • ベストアンサー
回答No.1

 こんばんは。以下のURLが参考になります。  http://msdn.microsoft.com/ja-jp/library/cc973418.aspx  http://msdn.microsoft.com/ja-jp/library/cc353106.aspx  http://www.codeguru.com/forum/showthread.php?t=392724  圧縮コーデックの一覧から、Microsoft Video 1を探し出して見つかればフィルタを作成して、SplitterとMuxの間に挟み込めばOK見たいです。  大分乱暴なコードですが、以下で圧縮が出来ました。参考程度に。 #include <stdio.h> #include <dshow.h> #include <qedit.h> #pragma comment(lib, "strmiids.lib") //コーデックを探す static IBaseFilter* FindCodec(BSTR bstrDesire) { ICreateDevEnum *pSysDevEnum = NULL; IEnumMoniker *pEnum = NULL; IMoniker *pMoniker = NULL; IBaseFilter *pFilter = NULL; HRESULT hr = ::CoCreateInstance(CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC_SERVER, IID_ICreateDevEnum, (void**)&pSysDevEnum); if(FAILED(hr)) return pFilter; hr = pSysDevEnum->CreateClassEnumerator(CLSID_VideoCompressorCategory, &pEnum, 0); if(hr != S_OK) return pFilter; while (S_OK == pEnum->Next(1, &pMoniker, NULL)) { IPropertyBag *pPropBag = NULL; pMoniker->BindToStorage(0, 0, IID_IPropertyBag, (void**)&pPropBag); VARIANT var; ::VariantInit(&var); hr = pPropBag->Read(L"FriendlyName", &var, 0); if(SUCCEEDED(hr)) { ::wprintf(L"[codec %s]\n", var.bstrVal); //見つかったのでフィルタを作成する if(::lstrcmp(var.bstrVal, bstrDesire) == 0) { pMoniker->BindToObject(NULL, NULL, IID_IBaseFilter, (void**)&pFilter); } } ::VariantClear(&var); pPropBag->Release(); pMoniker->Release(); //見つかっているのでループから抜ける if(pFilter)break; } //最後の後始末 pSysDevEnum->Release(); pEnum->Release(); return pFilter; } int main() { IGraphBuilder *pGraph = NULL; IMediaControl *pControl = NULL; IMediaEvent *pEvent = NULL; ::CoInitialize(NULL); //グラフの作成 ::CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER, IID_IGraphBuilder, (void **)&pGraph); //コントロールとイベントの作成 pGraph->QueryInterface(IID_IMediaControl, (void **)&pControl); pGraph->QueryInterface(IID_IMediaEvent, (void **)&pEvent); //グラフビルダーの作成 ICaptureGraphBuilder2* pBuilder = NULL; ::CoCreateInstance(CLSID_CaptureGraphBuilder2, NULL,CLSCTX_INPROC_SERVER, IID_ICaptureGraphBuilder2, (void **)&pBuilder); //フィルタの作成 IBaseFilter *pFileSource; pGraph->AddSourceFilter( L"test.avi", L"Source", &pFileSource); IBaseFilter *pAviSplit; ::CoCreateInstance(CLSID_AviSplitter, 0, CLSCTX_INPROC_SERVER, IID_IBaseFilter, (void **)&pAviSplit); IBaseFilter *pAviMux; ::CoCreateInstance(CLSID_AviDest, 0, CLSCTX_INPROC_SERVER, IID_IBaseFilter, (void **)&pAviMux); IBaseFilter *pWriter; ::CoCreateInstance(CLSID_FileWriter, 0, CLSCTX_INPROC_SERVER, IID_IBaseFilter, (void **)&pWriter); IBaseFilter *pMSVideo1 = ::FindCodec(L"Microsoft Video 1"); //出力先の設定 IFileSinkFilter *pSink= NULL; pWriter->QueryInterface(IID_IFileSinkFilter, (void**)&pSink); pSink->SetFileName(L"testresult.avi", NULL); pSink->Release(); //フィルタを追加 pGraph->AddFilter(pFileSource, L"AVI Source"); pGraph->AddFilter(pAviSplit, L"AVI Splitter"); pGraph->AddFilter(pAviMux, L"AVI MUX"); pGraph->AddFilter(pWriter, L"AVI Writer"); pGraph->AddFilter(pMSVideo1, L"Microsoft Video 1"); //フィルタ同士の接続 pBuilder->SetFiltergraph(pGraph); pBuilder->RenderStream(0, 0, pFileSource, 0, pAviSplit); pBuilder->RenderStream(0, &MEDIATYPE_Video, pAviSplit, pMSVideo1, pAviMux);//split⇔mux間にMS Video1を挟み込む pBuilder->RenderStream(0, &MEDIATYPE_Audio, pAviSplit, 0, pAviMux); pBuilder->RenderStream(0, 0, pAviMux, 0, pWriter); //書き込みスタート pControl->Run(); //達成まで待つ long evCode; pEvent->WaitForCompletion(INFINITE, &evCode); //停止 此れがないと駄目 pControl->Stop(); //始末 pControl->Release(); pEvent->Release(); pGraph->Release(); pFileSource->Release(); pAviSplit->Release(); pAviMux->Release(); pWriter->Release(); pMSVideo1->Release(); pBuilder->Release(); return 0; }

tkhr1109
質問者

お礼

大変細かな親切なご回答本当にありがとうございます。 とても分かりやすく、すぐにできました。 ありがとうございました。

関連するQ&A