• ベストアンサー
※ 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

  • DirectShowでフィルタの削除

    現在、キャプチャソフトを作っています。 プレビューとキャプチャの切替で行き詰まってしまいました。 プレビューからキャプチャき切り替える時は、グラフにファイルライタフィルタを追加することで簡単に切り替える事が出来るのですが、 キャプチャからプレビューに切り替える時はファイルライタフィルタをグラフから削除する方法がわからないのです。 IFileSinkFilter->Release()で消すことはできそうですが、グラフエディタで見ると残ってしまいます。 なのでキャプチャとプレビューを切替続けると不具合が起きそうです。 ICaptureGraphBuilder2::SetOutputFileName(...)でグラフに追加したファイルシンクフィルタをRemoveする方法はないのでしょうか?

  • Directshowフィルターのインストールについてです。

    Directshowフィルターのインストールについてです。 ネットで落とした動画をDivX Plus Playerで再生しようとすると 「このビデオは対応していないフォーマットです。 Directshowフィルターを追加インストールしないと再生できません。」 と出て再生できません。 WMPで再生すると 「そのファイルの圧縮に使用したコーデックをサポート していない可能性があります。」と出ます。 Directshowフィルターをインストールすればよいのでしょうか? ネットで探してみましたがダウンロード出来る場所が 見当たりません。 場所をご存知の方よろしくお願いいたします。

  • DirectShowで作成した動画がうまく見れない

    現在、Visual Studio2010のC++で、webカメラで撮影した動画をDirectshowを使ってaviファイルとして保存するようなプログラムを書いているのですが、ここで出力されたaviファイルをQuicktimePlayerで再生しようとすると、音声のみが流れて画面は真っ黒という状態が起きてしまいます。 再生のため、一通りのコーデック(ffdshow,DivX等)をインストールして再生を試みたのですが、全く変化がありません。 また、DirectShowで動画作成時に圧縮を行う際には"x264vfw - H.264/MPEG-4 AVC codec"を使用しました。 一応のため、作成した動画を真空波動研で調べてみた結果 +++++++++++++++++ [h264.avi] 640x480 24Bit H.264 30.00fps 233f 1809.00kb/s PCM 44.10kHz 16Bit 2ch 1411.20kb/s [RIFF(AVI2.0)] 00:00:07.766 (7.766sec) / 3,195,904Bytes h264.avi / DLL 110813 Unicode +++++++++++++++++ という内容となりました。 どうにかして出力されたaviファイルをQuickTimePlayerで見れるようにしたいと考えています。 再生部分の問題なのか、保存部分の問題なのか全くわからない状態です・・・ かなり限られた状況なので、難しい質問かもしれませんが、何か解る方がいらっしゃいましたらご教授お願いします! また、動画圧縮時に他にもいろいろなコーデックを試してみたのですが、その中にもQuicktimePlayerで見れるものと見れないものが存在しました。 手掛かりになる情報かどうかはわかりませんが、それも記述しておきます。 (×:見れないもの) Microsoft Windows Media Video 9 Microsoft MPEG-4 Video Codec V3 DivX 6.9.2 Codec (4 Logical CPUs) (○:見れるもの) Intel IYUV コーデック MJPEG Compressor Microsoft Video 1

  • DirectShowでの動画の保存

    現在DirectShowで再生している動画をaviで保存しようとしています。 しかし動画の再生はできたのですが、aviに保存する方法がよくわかりません。 http://www.geekpage.jp/programming/directshow/video-capture-save-avi.php このページを参考にして、ビデオデバイスの部分を再生している動画ファイルに変更したいのですがどのようにすればよいのでしょうか?

  • aviutlで編集したaviファイルが巨大化

    aviutlで、あるaviファイルが読めこめなかったので、DirectShow File Reader プラグイン for AviUtlを導入して、読み込めるようになったのですが、 編集していざavi出力しようとすると、ファイルが巨大化してしまうのです。 以前にも似たような質問があったので参考にさせてもらいました。 しかし、ビデオ圧縮、オーディオ圧縮の再圧縮無しにチェックをいれたのにも関らず、巨大化してしまうのです。 aviファイルをキャプチャーする時、すべてがキーフレームになっているのが気になります。関係ないかもしれませんが。 他のaviファイルは巨大化せずに出力できるのですが・・・。 DirectShow File Reader プラグイン for AviUtlを導入してキャプチャーできるようになったaviファイルにこの現象が共通してると思うのです。 解決策等わかる方、回答よろしくお願いします。

  • DirectXのDirectShowについて

    こんにちは マイクロソフトのサイトからDirectX9.0のSDKをダウンロードしました。 で、DirectShowでVideoファイルを再生しながら、BITMAPとTextを表示させたいのですがどちらか一方しか出来ません。Video再生の上にBITMAP表示かまたは、Video再生時にText表示 サンプルソフトは通常インストールするとここのディレクトリーになります C:\Program Files\Microsoft DirectX 9.0 SDK (Summer 2004)\Samples\C++\DirectShow\VMR\Ticker Videoを再生しながら、BITMAP表示とText表示が出来るサンプルソフトなんてありますか?

  • GraphEditではつながるのに、DirectShowだとConnectできない

    少し特殊なフォーマットをサードパーティ製のフィルターを通して DirectShowを使用して再生します。 該当素材はGraphEditにDnDすると普通にFilterが接続され再生も可能です。 あまり詳しくかけませんので概略のみ 該当素材をAddSourceFilter()して、Splitter/Renderなど必要な FilterをAddFilter()で全て加えます。 SourceのOutpinとSplitterのInpinを HRESULT hr = IGraphBuilder->Connect(Outpin, Inpin); この際 hr = 0x80040207 (VFW_E_NO_ACCEPTABLE_TYPES) となりPinの接続ができません。 Render()でも 0x80040218(VFW_E_CANNOT_RENDER) です。  Source を Mpeg1、Splitter を Mpeg-1 Stream Splitter  に変更しますと普通に接続できますので、Programの  構造としてはあっていると思います。 文字通りMediaTypeが異なるから? と QueryAccept()で確認しましたが問題はないようです。 さらにMSDNのサンプルを参考にして上記のProgramで作ったフィルタグラフを .grfファイルに書き出しました。 GraphEditで開きますと必要なFilterはすべて追加されているが、 つながってはいない状態です。これは上記の現象から理解できます。 しかし解せないことに、このGraphEditでSourceFileのPinから Render Pinを行うと完璧にフィルターが接続されます。 もちろんPin同士だけをつなげることも可能です。 基本的にGraphEditでできることはProgramでも出来ると思うのですが、 今回のケースは理解できません。 GraphEditでつながるにも関わらず、直接Pinの接続が出来ないというのは なぜなのでしょうか。 以下に環境を記載します。 Windows XP SP2 DirectX 9.0C Microsoft DirectX SDK (March 2008) Microsoft Platform SDK for Windows Server 2003 SP1

  • カメラからの映像をキャプチャしwmvに変換して保存したい

    USBカメラからの映像をキャプチャし、 wmv形式で保存するプログラムをVC.net2003で書いているのですがうまくいきません。 Directshowサンプルや資料を見ながら、 キャプチャした映像をaviで保存することははできました。 が、圧縮に関する資料が見当たりません。 どなたかヒントがあればご教授いただきたいです。

  • DirectShowでのピンの接続

    現在C++およびDirectShowでプログラムを作成しています まずGraphEditで以下のようなものを作成しました ttp://sageuploader.if.land.to/cgi-bin/1upload/src/sage1_8271.jpg これをプログラムで書きたいのですが ピンのつなぎ方がよくわかりません この場合はおそらくSetOutputFileNameとRenderStreamを使えばよいのかな?と考えてはいるのですが サンプルがビデオキャプチャからの取得方法ばかりで こういった場合にどのような記述をすればよいのかわかりません できれば具体的な記述方法等で教えてくださるとありがたいです

  • MMMの圧縮フィルタ

    MMM(MikMikuMoving)を使っています。 AVI出力の圧縮フィルタが非常に圧縮効率悪いです。 5分程度の動画が6GBとか、非圧縮と変わらないくらい。 Ut Video Codecというのを入れてみましたがそれで6GBです。 ちなみに最終的にはPowerDirector10という編集ツールで編集するので 数十Mにはなりますが、途中のファイルがあまりに巨大なので、 せいぜい数百MB程度まで圧縮したいです。 どなたかご存知の方教えてください。 よろしくお願いいたします。