DirectShowで開発する時のイロハ

# はじめに

「DirectShowで開発する時のイロハ」と書いたけど、DirectShow.NET中心のネタだけど、DirectShow.NETってほとんど、DirectShowのラッパーなので、参考にできるでしょう。と

メインは、音声と映像の録画をするプログラムが作りたくてのメモなので、映像の編集とか動画ファイルの再生とかの情報は希薄です。

# DirectX

DirectXは広い。... DirectXを.NET Frameworkからアクセスできるようなものって、SlimDXとかManagedDirectX(MDX)とかいろいろあるけど、それらが全てのDirectXをラップしているとは限らないので注意だ。

# DirectShowのアーキテクチャ1

録画中は、アプリケーション側では特に何もしなくてよいほど、DirectShow側がバックグラウンドスレッドのように、よきに計らってくれる。

フィルタ作って、グラフに登録して、そこから先は、特に何もしなくていい**(RunしてStopだけは必要だけど)**、という感じ。
逆に、初期設定というか、録画までの最初の一歩というか、フィルタ作って、グラフに登録して、ピン繋げて、というところが大変というか、DirectShowプログラミングの肝になるところだと思う。

# DirectShowのアーキテクチャ2

COMらしい。

なので、COM⇔.NET相互運用の機能を使って、直接 .NET Framework からアクセスできるかもしれない。

# DirectShowの後継

MediaFoundationというらしい。

まぁ、だからなのか、32bit(x86)のフィルタは充実しているけど、64bit(x64)のフィルタが寂しい状況なのは、こういう事だからなのでしょう。

# DirectShow専門の用語

これは、他のWebサイトを参照してくれ。

以下、簡単に

- フィルタ
 - 私の[StreamRelay](https://qiita.com/tomoki0sanaki/items/85f20cbe18378e33cd6f)のように、フィルタという単機能なオブジェクトを被せていって(つなげていって)データ処理を行うってアーキテクチャ
 - だけど、映像と音声をまとめたり、まとまっている映像と音声を別々に分離したりと、入力と出力が可変になるので、オブジェクトの継承で済む話ではなくなるので、**ピン**という概念が出てくる
 - キャプチャフィルタでデータを取得して、普通のフィルタで処理(圧縮とか伸張など)して、レンダラフィルタで出力。・・・という流れ
- グラフ
 - フィルタのまとまり
-  ピン
 - フィルタの入力と出力をつかさどる門というか関所みたいなもの
 
# なにはともあれGraphEditer

GUIでグラフ(フィルタの繋がり)を編集できるツールなんだけど、当初、私はこれを毛嫌いしていて、VisualStudioの自分のプログラムで、一覧(Listing)とって、そこからフィルタを選択して...とやろうとしたけど、DirectShowはクセが強いので、私のような入門者には無理だった。

いろんなWebページだと、WindowsSDkに添付されているとか、いろいろと書かれているけど、とりあえず自マシンで、

> dir c:\ /s /b | find "graphedt"

してみると、既にインストール済かもしれない。

また、Microsoft謹製のGraphEditerだけではなく、GraphEditerの代替となるツールを3rdパーティが作っていたりするので、そういうのでもいいと思うので、とりあえずDirectShowの入門者はまずGraphEditerを触ってみる事が肝要だ。

てか、GraphEditerでフィルタの繋がり方をまず定義してからでないと、DirectShowプログラミングは始まらないと言い切ってもいいかもしれない。

特にマルチロディアデータの再生だけなら、GraphEditerにファイルを与えるだけで、フィルタの繋がり方を示してくれるので、GraphEditerを使いこなす事がDirectShowプログラミングの肝のようだ。

# 32bitと64bitのGraphEditer

Microsoft謹製だと、32bit版と64bit版がある。

これが、32bit版のGraphEdt.exeだと繋がらないフィルタの接続でも、64bitだと繋がったりするので、うまくいかない場合は、とりあえず両方で試してみるといい。

# なにはともあれGraphEditer パート2 ～proppage.dll～

DirectShow.NET でコードを書いていると、GraphEdit では繋がるのに、自分のプログラムでは繋がらないピンがあったりする。そうなると GraphEdit側の繋がっているピンの状態が知りたくなるのだけど、そういう時は、proppage.dllだ。
私はこの情報に巡り合うまでは、レジストリ(HKCU)の深い森の中をさまよっていましたよ。

graphedt.exeがインストールされていれば、proppage.dllもイントールされている公算が高い。

とりあえず、

> dir c:\ /s /b | find "proppage.dll"

してみるべきだ。

見つけたら、管理者権限のcmd.exe から win32はwin32のregsvr32.exeで、win64はwin64のregsvr32.exeでレジストリに登録(COMを登録)のだ。

ちなみに、64bit Windowsの場合、win32のregsvr32.exeは

> c:\Windows\SysWOW64\regsvr32.exe

なので、そこは留意点だ。

COM登録が完了すると、右クリックがこんな感じになる。

![propage.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/182822/d851e46a-ef92-51a4-8a7a-7b257b830f82.png)

参考 : [GraphEdit の使い方 (2) – Media Sub Type の確認方法および GraphEdit を使ったファイル コンバータの作成](https://blogs.msdn.microsoft.com/windows_multimedia_jp/2009/03/26/graphedit-2-media-sub-type-graphedit-125/)

# DirectShowのフィルタ

32bit版と64bit版のGraphEdt.exeを起動してみると分かるけど、32bit版のフィルタが圧倒的に多い。...64bit時代の2019年ではDirectShowってオワコンなのか?

# SplitterとMux

まぁ、フィルタ名に**Splitter**って書かれているとなんとなく分かる(配列に分割する際とかSplitってメソッドだしさ)と思うけど、映像と音声と字幕とか、そういうのを個別に分離するフィルタっていうのは分かる。

私は録画(映像と音声)がしたくてDirectShowに手を出したので、それを**まとめるものが何か**って言うのが分からなかった。
**mux**っていうのがそれらしい。

avi 形式の映像にまとめるのが、**AVI Mux**だし、WebM形式にまとめるなら **WebM Muxer** とか言う感じなのがのそれ。
どちらにしろ、録画形式ごとにMuxが必要って事だし、その形式のMuxがないと、映像と音声をまとめられないって事だと思う。

# SplitterとMux ～コンバータ～

つまるところ、コンバータは、動画ファイルを読んで、Splitterで、映像と音声を分離して、映像と音声をそれぞれのデコーダに渡して、それぞれを別のエンコーダで圧縮して、muxでまとめて出力。

という手順をとればコンバータは作れる。という事になると思う。

![ds.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/182822/91f250e9-8ce0-c71b-d49d-496cd85fcdd1.png)

録画は、Splitterから先の、それぞれのキャプチャデバイスからデータを受け取って、映像と音声をそれぞれエンコーダで圧縮して、muxでまとめて出力。という感じ。

映像だけはプレビューが欲しいとかいう事であれば、圧縮前に SmartTeeでキャプチャとプレビューに分離して、プレビュー側はGUIのレンダラフィルタに渡してあげる。という追加処理も必要という感じ。

# SmartTee

これは、キャプチャ(録画)とプレビュー(画面出力)に分離する事ができるフィルタ。

覚えておきたい。

# 録音だけならDirectSoundでも可能

DirectShowには、カメラとマイクがキャプチャデバイスとしてあるので、さらに映像と音声をまとめてくれるmuxフィルタがあるので、録画と録音を同時にできるけど、録音だけも可能...なはず。
しかしながら、録音だけならDirectSoundという選択肢もある。
こちらはリングバッファなどの知識というかそういうものに対してのプログラミング的な慣れも必要だけど、まぁ録音だけならDirectSoundという選択肢もある。

# これ以降は、DirectShow.NET を例えに使っていく

## DirectShow.NET

配布元は[ここかな](https://ja.osdn.net/projects/sfnet_directshownet/)

COM な DirectShow を .NET Framework でアクセスできるようにしたやつ。

というか、DirectShow は COM なのだから、.NET-COM相互運用で、直接アクセスできるかもしれない(試した事はない)。


## キャプチャデバイス一覧

こんな感じ。

```csharp
DirectShowLib.DsDevice[] DsDeviceHako = DirectShowLib.DsDevice.GetDevicesOfCat(DirectShowLib.FilterCategory.VideoInputDevice);
String str = "";
for (int i = 0; i < DsDeviceHako.Length; i++) {
 str += "Name=" + DsDeviceHako[i].Name + ",DevicePath=" + DsDeviceHako[i].DevicePath + "\r\n";
}
```

「VideoInputDevice」を「AudioInputDevice」にすれば、音源の一覧も取れる

## フィルタを探す(フィルタ一覧)

こんな感じで、カテゴリとフィルタ名で抽出して、IBaseFilter インターフェイス型を返せる

キャプチャデバイスの一覧と一緒のような感じで書ける。(キャプチャデバイスも、キャプチャフィルタで、フィルタの一種だからねぇ～)

```csharp
private DirectShowLib.IBaseFilter GetFilter(String filtername, Guid filterCategory){
 DirectShowLib.IBaseFilter ansBaseFilter = null;
 String str = "";
 try{
  DirectShowLib.DsDevice[] DsDeviceHako = DirectShowLib.DsDevice.GetDevicesOfCat(filterCategory);
  for (int i = 0; i < DsDeviceHako.Length; i++){
   str += DsDeviceHako[i].Name + "\r\n";
   if (filtername == DsDeviceHako[i].Name){
    Guid guidBF = typeof(DirectShowLib.IBaseFilter).GUID;
    Object ansObject = null;
    DsDeviceHako[i].Mon.BindToObject(null, null, ref guidBF, out ansObject);
    ansBaseFilter = (DirectShowLib.IBaseFilter)ansObject;
    break;
   }
  }
 }catch { }
 return ansBaseFilter;
}
```

第二引数のfilterCategoryには、DirectShowLib.FilterCategory.LegacyAmFilterCategoryを充てたりする。

LegacyAmFilterCategory は、GraphEdt.exe でフィルタを探す際の「DirectShow Filter」というカテゴリに該当するはず。

## エラーメッセージを調べる

大抵の関数は、int型での返値が「0(場合によっては「1」も)」以外でエラーで、それを言語化してくれるのが、

> DirectShowLib.DsError.ThrowExceptionForHR(int hr);

なので、int型を返す関数を呼び出す際には、返値を取得して、このThrowExceptionForHR()を呼び出すようにしよう

## フィルタからピンを取り出す

DirectShowプログラミングのポイントは、ピンを繋げていく作業なので、フィルタからピンを取り出さないといけない。

ピンを取り出すには、二つの関数がある

```csharp
DirectShowLib.IPin pin = null;
int hr = IBaseFilter.FindPin(ピンの名前, out pin);
DirectShowLib.DsError.ThrowExceptionForHR(int hr);
```

と

```csharp
DirectShowLib.IPin pin = null;
int hr = captureGraphBuilder.FindPin(videoCompressionFilter, DirectShowLib.PinDirection.Output, null, null, true, 0, out pin);
DirectShowLib.DsError.ThrowExceptionForHR(int hr);
```

の二つ。

後者の第三引数、第四引数とかよく分からない。

だけど、基本的に後者でよいと思う。

> 前者は、Outputが複数あって、そのうちの「Preview」と書いてある方

というような複数の可能性がある場面の時に使う。

「Smart Tee」フィルタから「Preview」と「Capture」に分岐させたり、「Mux」系のフィルタで、「Audio」と「Video」を統合したり・・・という場面。

下記のピン一覧から取りだすって方法もあるとは思う。

## 繋がったピン間の MediaType

出力ピンと入力ピンが繋がったとして、その間はどういう形式(画面サイズとか色数とか)のデータが流れる(予定)なのか。というのを返すのが、ConnectionMediaType() メソッド

こんな感じ

```csharp
DirectShowLib.IPin pin // 別のフィルタのピンと繋がっているピンがあるとする
DirectShowLib.AMMediaType mType = new DirectShowLib.AMMediaType();
int hr = pin.ConnectionMediaType(mType);
DirectShowLib.DsError.ThrowExceptionForHR(hr);
...
DirectShowLib.DsUtils.FreeAMMediaType(mType); // 解放を忘れずに
```

なぜか、out が必要ないので、new する必要があるという、例外的なメソッドなので注意。

```csharp
DirectShowLib.AMMediaType mType = null;
int hr = pin.ConnectionMediaType(out mType);　// これはコンパイルエラーだよ。
```

でもいいんじゃないのと思うけど、こうではないので注意だ。

## フィルタからピンの一覧

一覧の取り方が特殊。

こんな感じ

```csharp
DirectShowLib.IEnumPins enumPin;
DirectShowLib.IPin[] pinHako = new DirectShowLib.IPin[1];
int hr = avimuxFilter.EnumPins(out enumPin);
do{
 hr = penumPin.Next(1,pinHako,System.IntPtr.Zero);
 if(pinHako[0] != null){
 }
}while(hr == 0);
DirectShowLib.DsError.ThrowExceptionForHR(int hr);
```

上記は、フィルタからピンの一覧だけど、ピンからメディアタイプの一覧とかも、基本的に同じ手順

1. EnumXXX(out YYY) というメソッドで、一覧のオブジェクトを取得
2. YYYの1つ要素の配列(yyyHako)を宣言する
3. Next(1,yyyHako,System.InPtr.Zero) で、配列の最初に一覧から一個抽出できる
4. 繰り返し

という手順。
Next() 関数の第一引数は、「1」← これにすごく悩んだ。
Next() 関数の第二引数は、要素が一個の配列 ← これにすごく悩んだ。

## ピンとピンを繋げる

Input系統のピンをOutput系統のピンに繋げる事で、データがフィルタ間を流れていくわけだ。

Input系統のピン⇒をOutput系統だよ。

> int hr = DirectShowLib.IGraphBuilder.Connect(DirectShowLib.IPin source, DirectShowLib.IPin dist);

と

> int hr = DirectShowLib.IPin.Connect(DirectShowLib.IPin dist, DirectShowLib.AMMediaType mediaType);
> int hr = DirectShowLib.IPin.ReceiveConnection(DirectShowLib.IPin dist, DirectShowLib.AMMediaType mediaType);

がある。

## (録画の)開始

> int hr = ((DirectShowLib.IMediaControl)DirectShowLib.IGraphBuilder).Run();

Stop(), Pause()とかもあるよ

StopWhenReady() これは何?

## キャプチャサイズ

```csharp
int videoX;
int videoY;
DirectShowLib.IGraphBuilder gb; // ←これはこの部分に到達するまでに、どこかにあるでしょう
DirectShowLib.IBasicVideo2 basicVideo = (DirectShowLib.IBasicVideo2)gb;
basicVideo.GetVideoSize(out videoX, out videoY);
```

こんな感じ。

IGraphBuilderインターフェイス内のIBasicVideo2インターフェイスにGetVideoSize()という関数があるよ。

## キャプチャとして選択できるサイズ(映像)

VideoCaptureDeviceのCaptureピンを選択すると、複数のMediaTypeが取得できるが、それはキャプチャするフォーマット(色数とか画面サイズとか)の違い。

それは、ForamtTypeにあるので、MediaType=videoの時、こんな感じで呼び出せば、一覧がとれる。

```csharp
DirectShowLib.AMMediaType mediaType; // これは PinのEnumMediaTypes とかから取得してくる
if(mediaType == DirectShowLib.MediaType.Video){
    Object o0 = Marshal.PtrToStructure(mediaType.formatPtr, typeof(DirectShowLib.VideoInfoHeader)); // アンマネージドなポインタをマネージコードに移籍
    DirectShowLib.VideoInfoHeader vh = (DirectShowLib.VideoInfoHeader)o0;
    String str = 
      "BitRate=" + vh.BitRate.ToString() + 
      ",BitCount=" + vh.BmiHeader.BitCount.ToString() + // キャプチャ動画の色数(24Bitとか16Bitとか8bit(おそらく白黒)とか)
      ",W=" + vh.BmiHeader.Width.ToString() +  // キャプチャ動画の幅
      ".H=" + vh.BmiHeader.Height.ToString();　// キャプチャ動画の高さ
}
```

ビートレート / (高さ*幅*色ビット) = 1秒当たりのフレーム数 (30とか20とか)
になると思う。

一覧取ると分かるけど USBカメラ/Webカメラから出力する時点で MotionJPEG で圧縮されていたりするんですねぇ～....(知らなかった orz)
→ なので、キャプチャデバイスからいきなり FileWriterに繋げてもMotionJPEGで圧縮されているかも知れない。

## キャプチャとして選択できるサイズ(音声)

映像が出てきたら、次は音声。・・・映像の連想から AudioInfoHeader ・・・ではなかった ...orz

こんな感じ

```csharp
DirectShowLib.AMMediaType mediaType; // これは PinのEnumMediaTypes とかから取得してくる
if (mediaType.majorType == DirectShowLib.MediaType.Audio) {
    Object o1 = Marshal.PtrToStructure(mediaType.formatPtr, typeof(DirectShowLib.WaveFormatEx));
    DirectShowLib.WaveFormatEx wh = (DirectShowLib.WaveFormatEx)o1;
    String str = 
      "Channel=" + wh.nChannels.ToString() +   // チャンネル数。モノラル(1)とステレオ(2)ぐらい!?
      ", bitrate=" + wh.wBitsPerSample.ToString(); // 量子化ビット数(16Bitとか24Bitとか)
      ", SampleHz=" + wh.nSamplesPerSec.ToString(); // サンプリング周波数(44.1kHzとか48kHzとか)
}
```

## キャプチャ品質の変更

上記を使えって、MediaType指定で、ピンを繋げていけば、キャプチャする際の出力品質を制御する事ができる。

## オブジェクトの解放

自分で new した時だけ、解放が必要になる

解放用のメソッドは、

> DirectShowLib.DsUtils.FreeAMMediaType(DirectShowLib.AMMediaType type);

と

> DirectShowLib.DsUtils.FreePinInfo(DirectShowLib.PinInfo pInfo);

の二つがあるので、この二つを new した際には、解放を忘れずに。

## Microsoft MPEG4 version3.0

[[INFO] Microsoft MPEG4 Version 3.0 codec は Windows Media Technologies でのみ使用できる](
https://support.microsoft.com/ja-jp/help/278310/microsoft-mpeg4-version-3-0-codec-can-only-be-used-with-windows-media)

ということだそうだ。

---
## MediaType/MediaSubType の文字列化

普通に ToString() しても、GUID が出力されてチンプンカンブンなので、こんな関数はどうでしょうか。

```csharp
private String MediaTypeStr(Guid mediaType) {
String str = "Unknown";
if (mediaType == DirectShowLib.MediaType.AnalogAudio){
    str = "AnalogAudio";
}else if(mediaType == DirectShowLib.MediaType.AnalogVideo){
    str = "AnalogVideo";
}else if (mediaType == DirectShowLib.MediaType.Audio){
    str = "Audio";
}else if (mediaType == DirectShowLib.MediaType.AuxLine21Data){
    str = "AuxLine21Data";
}else if (mediaType == DirectShowLib.MediaType.AUXTeletextPage){
    str = "AUXTeletextPage";
}else if (mediaType == DirectShowLib.MediaType.CC_Container){
    str = "CC_Container";
}else if (mediaType == DirectShowLib.MediaType.DTVCCData){
    str = "DTVCCData";
}else if (mediaType == DirectShowLib.MediaType.File){
    str = "File";
}else if (mediaType == DirectShowLib.MediaType.Interleaved){
    str = "Interleaved";
}else if (mediaType == DirectShowLib.MediaType.LMRT){
    str = "LMRT";
}else if (mediaType == DirectShowLib.MediaType.Midi){
    str = "Midi";
}else if (mediaType == DirectShowLib.MediaType.Mpeg2Sections){
    str = "Mpeg2Sections";
}else if (mediaType == DirectShowLib.MediaType.MSTVCaption){
    str = "MSTVCaption";
}else if (mediaType == DirectShowLib.MediaType.Null){
    str = "Null";
}else if (mediaType == DirectShowLib.MediaType.ScriptCommand){
    str = "ScriptCommand";
}else if (mediaType == DirectShowLib.MediaType.Stream){
    str = "Stream";
}else if (mediaType == DirectShowLib.MediaType.Texts){
    str = "Texts";
}else if (mediaType == DirectShowLib.MediaType.Timecode){
    str = "Timecode";
}else if (mediaType == DirectShowLib.MediaType.URLStream){
    str = "URLStream";
}else if (mediaType == DirectShowLib.MediaType.VBI){
    str = "VBI";
}else if (mediaType == DirectShowLib.MediaType.Video){
    str = "Video";
}else if (mediaType == DirectShowLib.MediaSubType.A2B10G10R10){
    str = "A2B10G10R10";
}else if (mediaType == DirectShowLib.MediaSubType.A2R10G10B10){
    str = "A2R10G10B10";
}else if (mediaType == DirectShowLib.MediaSubType.AI44){
    str = "AI44";
}else if (mediaType == DirectShowLib.MediaSubType.AIFF){
    str = "AIFF";
}else if (mediaType == DirectShowLib.MediaSubType.AnalogVideo_NTSC_M){
    str = "AnalogVideo_NTSC_M";
}else if (mediaType == DirectShowLib.MediaSubType.AnalogVideo_PAL_B){
    str = "AnalogVideo_PAL_B";
}else if (mediaType == DirectShowLib.MediaSubType.AnalogVideo_PAL_D){
    str = "AnalogVideo_PAL_D";
}else if (mediaType == DirectShowLib.MediaSubType.AnalogVideo_PAL_G){
    str = "AnalogVideo_PAL_G";
}else if (mediaType == DirectShowLib.MediaSubType.AnalogVideo_PAL_H){
    str = "AnalogVideo_PAL_H";
}else if (mediaType == DirectShowLib.MediaSubType.AnalogVideo_PAL_I){
    str = "AnalogVideo_PAL_I";
}else if (mediaType == DirectShowLib.MediaSubType.AnalogVideo_PAL_M){
    str = "AnalogVideo_PAL_M";
}else if (mediaType == DirectShowLib.MediaSubType.AnalogVideo_PAL_N){
    str = "AnalogVideo_PAL_N";
}else if (mediaType == DirectShowLib.MediaSubType.AnalogVideo_PAL_N_COMBO){
    str = "AnalogVideo_PAL_N_COMBO";
}else if (mediaType == DirectShowLib.MediaSubType.AnalogVideo_SECAM_B){
    str = "AnalogVideo_SECAM_B";
}else if (mediaType == DirectShowLib.MediaSubType.AnalogVideo_SECAM_D){
    str = "AnalogVideo_SECAM_D";
}else if (mediaType == DirectShowLib.MediaSubType.AnalogVideo_SECAM_G){
    str = "AnalogVideo_SECAM_G";
}else if (mediaType == DirectShowLib.MediaSubType.AnalogVideo_SECAM_H){
    str = "AnalogVideo_SECAM_H";
}else if (mediaType == DirectShowLib.MediaSubType.AnalogVideo_SECAM_K){
    str = "AnalogVideo_SECAM_K";
}else if (mediaType == DirectShowLib.MediaSubType.AnalogVideo_SECAM_K1){
    str = "AnalogVideo_SECAM_K1";
}else if (mediaType == DirectShowLib.MediaSubType.AnalogVideo_SECAM_L){
    str = "AnalogVideo_SECAM_L";
}else if (mediaType == DirectShowLib.MediaSubType.ARGB1555){
    str = "ARGB1555";
}else if (mediaType == DirectShowLib.MediaSubType.ARGB1555_D3D_DX7_RT){
    str = "ARGB1555_D3D_DX7_RT";
}else if (mediaType == DirectShowLib.MediaSubType.ARGB1555_D3D_DX9_RT){
    str = "ARGB1555_D3D_DX9_RT";
}else if (mediaType == DirectShowLib.MediaSubType.ARGB32){
    str = "ARGB32";
}else if (mediaType == DirectShowLib.MediaSubType.ARGB32_D3D_DX7_RT){
    str = "ARGB32_D3D_DX7_RT";
}else if (mediaType == DirectShowLib.MediaSubType.ARGB32_D3D_DX9_RT){
    str = "ARGB32_D3D_DX9_RT";
}else if (mediaType == DirectShowLib.MediaSubType.ARGB4444){
    str = "ARGB4444";
}else if (mediaType == DirectShowLib.MediaSubType.ARGB4444_D3D_DX7_RT){
    str = "ARGB4444_D3D_DX7_RT";
}else if (mediaType == DirectShowLib.MediaSubType.ARGB4444_D3D_DX9_RT){
    str = "ARGB4444_D3D_DX9_RT";
}else if (mediaType == DirectShowLib.MediaSubType.Asf){
    str = "Asf";
}else if (mediaType == DirectShowLib.MediaSubType.AtscSI){
    str = "AtscSI";
}else if (mediaType == DirectShowLib.MediaSubType.AU){
    str = "AU";
}else if (mediaType == DirectShowLib.MediaSubType.Avi){
    str = "Avi";
}else if (mediaType == DirectShowLib.MediaSubType.AYUV){
    str = "AYUV";
}else if (mediaType == DirectShowLib.MediaSubType.CC_Container){
    str = "CC_Container";
}else if (mediaType == DirectShowLib.MediaSubType.CFCC){
    str = "CFCC";
}else if (mediaType == DirectShowLib.MediaSubType.CLJR){
    str = "CLJR";
}else if (mediaType == DirectShowLib.MediaSubType.CLPL){
    str = "CLPL";
}else if (mediaType == DirectShowLib.MediaSubType.CPFilters_Processed){
    str = "CPFilters_Processed";
}else if (mediaType == DirectShowLib.MediaSubType.CPLA){
    str = "CPLA";
}else if (mediaType == DirectShowLib.MediaSubType.Data708_608){
    str = "Data708_608";
}else if (mediaType == DirectShowLib.MediaSubType.DOLBY_AC3_SPDIF){
    str = "DOLBY_AC3_SPDIF";
}else if (mediaType == DirectShowLib.MediaSubType.DolbyAC3){
    str = "DolbyAC3";
}else if (mediaType == DirectShowLib.MediaSubType.DRM_Audio){
    str = "DRM_Audio";
}else if (mediaType == DirectShowLib.MediaSubType.DssAudio){
    str = "DssAudio";
}else if (mediaType == DirectShowLib.MediaSubType.DssVideo){
    str = "DssVideo";
}else if (mediaType == DirectShowLib.MediaSubType.DtvCcData){
    str = "DtvCcData";
}else if (mediaType == DirectShowLib.MediaSubType.dv25){
    str = "dv25";
}else if (mediaType == DirectShowLib.MediaSubType.dv50){
    str = "dv50";
}else if (mediaType == DirectShowLib.MediaSubType.DVB_Subtitles){
    str = "DVB_Subtitles";
}else if (mediaType == DirectShowLib.MediaSubType.DvbSI){
    str = "DvbSI";
}else if (mediaType == DirectShowLib.MediaSubType.DVCS){
    str = "DVCS";
}else if (mediaType == DirectShowLib.MediaSubType.dvh1){
    str = "dvh1";
}else if (mediaType == DirectShowLib.MediaSubType.dvhd){
    str = "dvhd";
}else if (mediaType == DirectShowLib.MediaSubType.DVSD){
    str = "DVSD";
}else if (mediaType == DirectShowLib.MediaSubType.dvsl){
    str = "dvsl";
}else if (mediaType == DirectShowLib.MediaSubType.ETDTFilter_Tagged){
    str = "ETDTFilter_Tagged";
}else if (mediaType == DirectShowLib.MediaSubType.H264){
    str = "H264";
}else if (mediaType == DirectShowLib.MediaSubType.I420){
    str = "I420";
}else if (mediaType == DirectShowLib.MediaSubType.IA44){
    str = "IA44";
}else if (mediaType == DirectShowLib.MediaSubType.IEEE_FLOAT){
    str = "IEEE_FLOAT";
}else if (mediaType == DirectShowLib.MediaSubType.IF09){
    str = "IF09";
}else if (mediaType == DirectShowLib.MediaSubType.IJPG){
    str = "IJPG";
}else if (mediaType == DirectShowLib.MediaSubType.IMC1){
    str = "IMC1";
}else if (mediaType == DirectShowLib.MediaSubType.IMC2){
    str = "IMC2";
}else if (mediaType == DirectShowLib.MediaSubType.IMC3){
    str = "IMC3";
}else if (mediaType == DirectShowLib.MediaSubType.IMC4){
    str = "IMC4";
}else if (mediaType == DirectShowLib.MediaSubType.ISDB_Captions){
    str = "ISDB_Captions";
}else if (mediaType == DirectShowLib.MediaSubType.ISDB_Superimpose){
    str = "ISDB_Superimpose";
}else if (mediaType == DirectShowLib.MediaSubType.IYUV){
    str = "IYUV";
}else if (mediaType == DirectShowLib.MediaSubType.Line21_BytePair){
    str = "Line21_BytePair";
}else if (mediaType == DirectShowLib.MediaSubType.Line21_GOPPacket){
    str = "Line21_GOPPacket";
}else if (mediaType == DirectShowLib.MediaSubType.Line21_VBIRawData){
    str = "Line21_VBIRawData";
}else if (mediaType == DirectShowLib.MediaSubType.MDVF){
    str = "MDVF";
}else if (mediaType == DirectShowLib.MediaSubType.MJPG){
    str = "MJPG";
}else if (mediaType == DirectShowLib.MediaSubType.MPEG1Audio){
    str = "MPEG1Audio";
}else if (mediaType == DirectShowLib.MediaSubType.MPEG1AudioPayload){
    str = "MPEG1AudioPayload";
}else if (mediaType == DirectShowLib.MediaSubType.MPEG1Packet){
    str = "MPEG1Packet";
}else if (mediaType == DirectShowLib.MediaSubType.MPEG1Payload){
    str = "MPEG1Payload";
}else if (mediaType == DirectShowLib.MediaSubType.MPEG1System){
    str = "MPEG1System";
}else if (mediaType == DirectShowLib.MediaSubType.MPEG1SystemStream){
    str = "MPEG1SystemStream";
}else if (mediaType == DirectShowLib.MediaSubType.MPEG1Video){
    str = "MPEG1Video";
}else if (mediaType == DirectShowLib.MediaSubType.MPEG1VideoCD){
    str = "MPEG1VideoCD";
}else if (mediaType == DirectShowLib.MediaSubType.Mpeg2Audio){
    str = "Mpeg2Audio";
}else if (mediaType == DirectShowLib.MediaSubType.Mpeg2Data){
    str = "Mpeg2Data";
}else if (mediaType == DirectShowLib.MediaSubType.Mpeg2Program){
    str = "Mpeg2Program";
}else if (mediaType == DirectShowLib.MediaSubType.Mpeg2Transport){
    str = "Mpeg2Transport";
}else if (mediaType == DirectShowLib.MediaSubType.Mpeg2TransportStride){
    str = "Mpeg2TransportStride";
}else if (mediaType == DirectShowLib.MediaSubType.Mpeg2Video){
    str = "Mpeg2Video";
}else if (mediaType == DirectShowLib.MediaSubType.None){
    str = "None";
}else if (mediaType == DirectShowLib.MediaSubType.Null){
    str = "Null";
}else if (mediaType == DirectShowLib.MediaSubType.NV11){
    str = "NV11";
}else if (mediaType == DirectShowLib.MediaSubType.NV12){
    str = "NV12";
}else if (mediaType == DirectShowLib.MediaSubType.NV24){
    str = "NV24";
}else if (mediaType == DirectShowLib.MediaSubType.Overlay){
    str = "Overlay";
}else if (mediaType == DirectShowLib.MediaSubType.P010){
    str = "P010";
}else if (mediaType == DirectShowLib.MediaSubType.P016){
    str = "P016";
}else if (mediaType == DirectShowLib.MediaSubType.P208){
    str = "P208";
}else if (mediaType == DirectShowLib.MediaSubType.P210){
    str = "P210";
}else if (mediaType == DirectShowLib.MediaSubType.P216){
    str = "P216";
}else if (mediaType == DirectShowLib.MediaSubType.P408){
    str = "P408";
}else if (mediaType == DirectShowLib.MediaSubType.PCM){
    str = "PCM";
}else if (mediaType == DirectShowLib.MediaSubType.PCMAudio_Obsolete){
    str = "PCMAudio_Obsolete";
}else if (mediaType == DirectShowLib.MediaSubType.PLUM){
    str = "PLUM";
}else if (mediaType == DirectShowLib.MediaSubType.QTJpeg){
    str = "QTJpeg";
}else if (mediaType == DirectShowLib.MediaSubType.QTMovie){
    str = "QTMovie";
}else if (mediaType == DirectShowLib.MediaSubType.QTRle){
    str = "QTRle";
}else if (mediaType == DirectShowLib.MediaSubType.QTRpza){
    str = "QTRpza";
}else if (mediaType == DirectShowLib.MediaSubType.QTSmc){
    str = "QTSmc";
}else if (mediaType == DirectShowLib.MediaSubType.RAW_SPORT){
    str = "RAW_SPORT";
}else if (mediaType == DirectShowLib.MediaSubType.RGB1){
    str = "RGB1";
}else if (mediaType == DirectShowLib.MediaSubType.RGB16_D3D_DX7_RT){
    str = "RGB16_D3D_DX7_RT";
}else if (mediaType == DirectShowLib.MediaSubType.RGB16_D3D_DX9_RT){
    str = "RGB16_D3D_DX9_RT";
}else if (mediaType == DirectShowLib.MediaSubType.RGB24){
    str = "RGB24";
}else if (mediaType == DirectShowLib.MediaSubType.RGB32){
    str = "RGB32";
}else if (mediaType == DirectShowLib.MediaSubType.RGB32_D3D_DX7_RT){
    str = "RGB32_D3D_DX7_RT";
}else if (mediaType == DirectShowLib.MediaSubType.RGB32_D3D_DX9_RT){
    str = "RGB32_D3D_DX9_RT";
}else if (mediaType == DirectShowLib.MediaSubType.RGB4){
    str = "RGB4";
}else if (mediaType == DirectShowLib.MediaSubType.RGB555){
    str = "RGB555";
}else if (mediaType == DirectShowLib.MediaSubType.RGB565){
    str = "RGB565";
}else if (mediaType == DirectShowLib.MediaSubType.RGB8){
    str = "RGB8";
}else if (mediaType == DirectShowLib.MediaSubType.S340){
    str = "S340";
}else if (mediaType == DirectShowLib.MediaSubType.S342){
    str = "S342";
}else if (mediaType == DirectShowLib.MediaSubType.SPDIF_TAG_241h){
    str = "SPDIF_TAG_241h";
}else if (mediaType == DirectShowLib.MediaSubType.TELETEXT){
    str = "TELETEXT";
}else if (mediaType == DirectShowLib.MediaSubType.TVMJ){
    str = "TVMJ";
}else if (mediaType == DirectShowLib.MediaSubType.UYVY){
    str = "UYVY";
}else if (mediaType == DirectShowLib.MediaSubType.VBI){
    str = "VBI";
}else if (mediaType == DirectShowLib.MediaSubType.VideoImage){
    str = "VideoImage";
}else if (mediaType == DirectShowLib.MediaSubType.VPS){
    str = "VPS";
}else if (mediaType == DirectShowLib.MediaSubType.VPVBI){
    str = "VPVBI";
}else if (mediaType == DirectShowLib.MediaSubType.VPVideo){
    str = "VPVideo";
}else if (mediaType == DirectShowLib.MediaSubType.WAKE){
    str = "WAKE";
}else if (mediaType == DirectShowLib.MediaSubType.WAVE){
    str = "WAVE";
}else if (mediaType == DirectShowLib.MediaSubType.WebStream){
    str = "WebStream";
}else if (mediaType == DirectShowLib.MediaSubType.WSS){
    str = "WSS";
}else if (mediaType == DirectShowLib.MediaSubType.XDS){
    str = "XDS";
}else if (mediaType == DirectShowLib.MediaSubType.Y210){
    str = "Y210";
}else if (mediaType == DirectShowLib.MediaSubType.Y211){
    str = "Y211";
}else if (mediaType == DirectShowLib.MediaSubType.Y216){
    str = "Y216";
}else if (mediaType == DirectShowLib.MediaSubType.Y411){
    str = "Y411";
}else if (mediaType == DirectShowLib.MediaSubType.Y41P){
    str = "Y41P";
}else if (mediaType == DirectShowLib.MediaSubType.YUY2){
    str = "YUY2";
}else if (mediaType == DirectShowLib.MediaSubType.YUYV){
    str = "YUYV";
}else if (mediaType == DirectShowLib.MediaSubType.YV12){
    str = "YV12";
}else if (mediaType == DirectShowLib.MediaSubType.YVU9){
    str = "YVU9";
}else if (mediaType == DirectShowLib.MediaSubType.YVYU){
    str = "YVYU";
}else{
    Guid guid = new Guid("000000ff-0000-0010-8000-00aa00389b71");
    if (mediaType.Equals(guid) == true) {
        str = "Microsoft AAC Audio Decoder MFT";
    }
    guid = new Guid("3447504D-0000-0010-8000-00AA00389B71");
    if (mediaType.Equals(guid) == true){
        str = "Microsoft MPEG4 ver1";
    }
    guid = new Guid("3467706D-0000-0010-8000-00AA00389B71");
    if (mediaType.Equals(guid) == true){
        str = "Microsoft MPEG4 ver1";
    }
    guid = new Guid("3334504D-0000-0010-8000-00AA00389B71");
    if (mediaType.Equals(guid) == true){
        str = "Microsoft MPEG4 ver3";
    }
}
return str;
}
```



## 以上