GraphEditの使い方

# はじめに
DirectShowを用いた開発を行う機会があったため、用語やツールの使い方の覚え書きとして本記事を作成しました。

# DirectShowとは
メディアファイルまたはストリームに対する様々な操作を行うマルチメディアフレームワークとAPIのこと。

* マルチメディアタスク（映像・音声再生など）を「**フィルタ**」として扱い、各フィルタを入出力の操作を行う「**ピン**」で接続することで様々な機能を実現する。
* 「フィルタ」、「ピン」の設定を「**フィルタグラフ**」として作成する必要がある。

#### フィルタ
映像を流す機能（ソースフィルタ）や映像を画面に移す機能（レンダリングフィルタ）などの1つの機能のこと。

#### ピン
フィルタ同士をつなぎ、映像信号など入出力のやり取りする端子。

#### フィルタグラフ
フィルタの作成とピンとの接続などの構築内容を示すもの。

# フィルタグラフの作成
フィルタグラフの作成は、WindowsSDKに含まれるGraphEditを使用して行いました。

WindowsSDKのインストールはこちらから
https://developer.microsoft.com/ja-jp/windows/downloads/windows-sdk/

## GraphEditとは
DirectShowを使用するプログラムで必要となる「フィルタグラフ」を視覚的に作成できるツール。

フィルタグラフの作成・テストに使用することができる。

以下から取得
`C:\Program Files (x86)\Windows Kits\10\bin\10.0.22000.0\x64またはx86`
※bin以下のパスはPC環境によって異なる場合がある。
各環境の最新バージョンのフォルダを選択し、フィルタ(dllファイル)のアーキテクチャに合わせてx86かx64を選択する

# 使ってみる
## デスクトップカメラをキャプチャする
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2840516/79464157-b87b-de11-82ee-d63293712dff.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2840516/369d4fc5-57f9-0569-6a9c-cd2ace58a363.png)

1.　GraphEditを起動
2.　タブの`Graph`から`Insert Filters…`を選択し、以下の２つのフィルタをそれぞれ`Insert Filter`する。
・`Video Capture Sources`の中にあるデスクトップカメラのフィルタ
(↑の画像ではUSB Video Device)
・`DirectShow Filters`の中にある`Video Renderer`
デスクトップカメラのフィルタと`Video Renderer`をピンでつなぐ。

※`DirectShow Filters`内には２つの`Video Renderer`があるが、
Insert Filter実行後に`VMR Input0`として表示されるものが新しいらしいので、本記事では`VMR Input0`を使用する。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2840516/124bfa99-3b55-2d2c-069e-3b16049edb3e.png)

## DirectShowのフィルタソースを使用して作成する
https://github.com/HexagramNM/NMVCamFilter
今回は、このURLのフィルタを使用させて頂きます。
ビルド方法などは上記のURLからご確認ください。

1.　ビルド後、生成されたDLLファイルをフィルタとしてGraphEditに登録する。

コマンドプロンプトを監理者権限で起動し、以下のコマンドを実行
`regsvr32.exe "dllファイルのパス"`

2.　フィルタの登録ができたら、GraphEditを起動する。
3.　タブの`Graph`から`Insert Filters…`を選択し、以下の２つのフィルタをそれぞれ`Insert Filter`する。
・`Video Capture Sources`の中にある`NMVCamFilter`
・`DirectShow Filters`の中にある`Video Renderer`
4.　 フィルタを下の画像のようにピンでつなぐ。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2840516/136a079c-9cd0-3a02-353f-0bd6d3f07922.png)
つなぐと`Color Space Converter`が自動生成され
以下のようなフィルタグラフができる。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2840516/f627c4d7-0fa7-88c7-b7c9-79f99f00cb93.png)
5.　再生ボタンを実行しデバッグする
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2840516/bfaeb582-6a73-bf39-9173-4581bfc18e2c.png)
NMVCamFilterは指定したウィンドウのキャプチャを行うが、今回はウィンドウの指定を行わなかったため「NO SIGNAL」と出力されている。

## キャプチャ対象を変更する
フィルタとして使用しているプロジェクトの`stdafx.h`で定義されている`TARGET_WINDOW_NAME`を変更することで、キャプチャするウィンドウの指定を行うことができた。

今回はペイントのウィンドウ名を指定し、前項と同じ方法でフィルタグラフを作成した。
```
#define TARGET_WINDOW_NAME (L“_NM_MicDisplay_”)
```
上記のコードを以下のように変更した。
```
#define TARGET_WINDOW_NAME (L“タイトルなし - ペイント”)
```
ウィンドウ名はウィンドウ左上に記載されているものを指定する。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2840516/e8575ddd-52db-a64e-69f3-a8db5add4dd7.png)

TARGET_WINDOW_NAME変更後、DirectShowのフィルタソースを使用して作成する」の手順で再度デバッグを行うと、ペイントのウィンドウのキャプチャができる。

以下のスクリーンショットは、キャプチャ対象のウィンドウに弊社のロゴを張り付けたときのキャプチャ画像。

※キャプチャ対象とフィルタのウィンドウサイズを合わせていないため黒い余白ができている。
フィルタ側でウィンドウサイズの調整を行うことも可能。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2840516/52dc6f70-2c06-067f-0ce8-e6ec44b233cf.png)

# おわりに
本記事の作成を通じて、DirectShowについての基礎知識や、GraphEditの使い方を学ぶ良い機会になりました。
フィルタに対応する自作のアプリケーション作り、DirectShowと組み合わせて使っていけたらいいなと思います。

# 参考記事
* https://ja.wikipedia.org/wiki/DirectShow
* https://qiita.com/HexagramNM/items/2311f025f3af758c83a0
* https://github.com/HexagramNM/NMVCamFilter
* https://learn.microsoft.com/ja-jp/visualstudio/debugger/introducing-spy-increment?view=vs-2022
* http://konbiki.starfree.jp/Old/dshow/dshow2.html

最後までお読みいただきありがとうございます。