ビデオ ファイルのサムネイルを生成する目的で、directshownet DirectShow ラッパーを利用することに成功しました。多くのテスト インスタンスでは、コードは問題なく動作します。
ただし、RenderStream 関数呼び出しで「不明な例外」をスローするものもあります。
例外の原因を追跡できませんでした。エラー コードは「-2147467259」、InnerException:null です。COM インターフェイスの障害を調査した経験はあまりありませんが、エラー コードは論理値を形成していないようです。
私の最初の考えは、適切なコーデックなどの欠如でしたが、問題は、人気のあるコーデック パックのほとんどがインストールされているいくつかのテスト マシン (ffdshow、k-lite コーデック パックなど) で解決しません。動画もアプリの外で問題なく再生されます。
マシンは x64 バージョンの Windows (Windows 7 および win server 2008 r2) を実行しており、x64 バージョンの ffdshow コーデック パックをインストールしてから、32 ビット バージョンの ffdshow をインストールするなどの他の設定で再生し、x64 でテスト アプリをコンパイルすることもできます。 x86 ビルド モードと同様です。サンプル クリップで常に失敗します。また、特に h264 を見て、FFDSHOW 設定パネルで特定のコーデックを有効/無効にしようとしました。何もない。問題のあるサンプル ビデオは、次の仕様を使用してエンコードされています: v-codec:H264 - MPEG-4 AVC (パート 10) avc1 解像度:1280x768 FPS:23..
グラフを構築するためのコードは、多くのテスト ケースで機能するので問題ないと思いますが、次のとおりです。
private void SetupGraph( string FileName)
{
int hr;
// Get the graphbuilder object
m_FilterGraph = new FilterGraph() as IFilterGraph2;
// Get a ICaptureGraphBuilder2 to help build the graph
ICaptureGraphBuilder2 icgb2 = new CaptureGraphBuilder2() as ICaptureGraphBuilder2;
try
{
// Link the ICaptureGraphBuilder2 to the IFilterGraph2
hr = icgb2.SetFiltergraph(m_FilterGraph);
DsError.ThrowExceptionForHR(hr);
// Add the filters necessary to render the file. This function will
// work with a number of different file types.
IBaseFilter sourceFilter = null;
hr = m_FilterGraph.AddSourceFilter(FileName, null, out sourceFilter);
DsError.ThrowExceptionForHR(hr);
// Get the SampleGrabber interface
m_sampGrabber = (ISampleGrabber)new SampleGrabber();
IBaseFilter baseGrabFlt = (IBaseFilter)m_sampGrabber;
// Configure the Sample Grabber
ConfigureSampleGrabber(m_sampGrabber);
// Add it to the filter
hr = m_FilterGraph.AddFilter(baseGrabFlt, "Ds.NET Grabber");
DsError.ThrowExceptionForHR(hr);
// Connect the pieces together, use the default renderer
hr = icgb2.RenderStream(null, null, sourceFilter, baseGrabFlt, null);
DsError.ThrowExceptionForHR(hr); // **HERE** is where the 'unknown exception' is thrown.
// Now that the graph is built, read the dimensions of the bitmaps we'll be getting
SaveSizeInfo(m_sampGrabber);
// Configure the Video Window
IVideoWindow videoWindow = m_FilterGraph as IVideoWindow;
videoWindow.put_AutoShow(OABool.False);
// ConfigureVideoWindow(videoWindow, hWin);
//
// Grab some other interfaces
m_mediaEvent = m_FilterGraph as IMediaEvent;
m_mediaCtrl = m_FilterGraph as IMediaControl;
m_mediaSeeking = m_FilterGraph as IMediaSeeking;
m_mediaSample = m_FilterGraph as IMediaSample;
m_mediaPosition = m_FilterGraph as IMediaPosition;
}
catch
{ }
finally
{
if (icgb2 != null)
{
Marshal.ReleaseComObject(icgb2);
icgb2 = null;
}
}
}
まだ問題を絞り込もうとしています。私は単にアイデアを使い果たしたので、コメントをいただければ幸いです。 更新: 問題をより具体的にすることができるようです: DirecShow utlize h264 コーデックをシステムで利用できるようにするために、上記のグラフを変更する方法は? 見た目からして、それ自体は起こりません。もう 1 つの更新に値するものがあると思います: grapsh の構築などのテーマについて深く掘り下げました。さまざまなフィルター設定で遊ぶために、GrapStudio ソフトウェアもダウンロードしました。ただし、Render Media File サブメニューを選択して問題のあるビデオを指定するとすぐに、「ファイルをレンダリングできません」と表示されます。ビデオ ファイルは、Windows メディア プレーヤーまたは VLC で問題なく再生されます。FFDSHOW が提供する h264video コーデックでエンコードされています。
別の更新: K-Lite コーデック パック x64 を使用して、GraphStudio のレンダリング ムービー ([ファイル] -> [MEdia ファイルのレンダリング]) を作成することができました。グラフが作成されます (LAV Video Decoder を使用します)。私のアプリはまだグラフの自動生成に失敗していますが、x64 プラットフォームもターゲットにしており、GraphStudio が同じ API 関数を呼び出すだけで読んだことからもわかります。それはとても奇妙です。そこで、半自動グラフを作成することにしました。
Guid gui = new Guid("EE30215D-164F-4A92-A4EB-9D4C13390F9F");
Object o;
ty = Type.GetTypeFromCLSID(gui);
o = Activator.CreateInstance(ty, false);
IBaseFilter ibfVideoDec = (IBaseFilter)o;
hr=m_FilterGraph.AddFilter(ibfVideoDec, "LAV Video decoder");
DsError.ThrowExceptionForHR(hr);
必要な他のフィルターを追加しながら、RenderFile を呼び出します。なし。すべてのフィルターは、対応する CLSID によって初期化されました。エラーはありません。レンダリングされません。最新のコーデックなどの使用に関しては、DirectShowNetまたはおそらくDirectShow全体がひどく文書化されていると私に尋ねたら.