私はDirectShow.NETを使用してウェブカメラコントロールを持っています。私はビデオを表示し、ウェブカメラから画像をキャプチャするカスタムコントロールを作成しました。私は別のWPFウィンドウでそのカスタムコントロールを使用しています。私はちょうど少しDirectShowのプログラミングを抽象化し、単にBitmap
を返すカスタムコントロールのpublic Bitmap CaptureImage()
関数があります。イメージは比較的大きいので(1920x1080)、IVMRWindowlessControl9
のGetCurrentImage()
機能は処理にかなりの時間がかかります(2〜3秒)。私は自分のコードを踏んで、この呼び出しが処理に時間がかかる唯一の呼び出しであることを確認できます。バックグラウンドでIVMRWindowlessControl9.GetCurrentImage()を実行します。
メインWPFウィンドウのGUIスレッドがハングし、数秒間応答しなくなるため、イメージがキャプチャされている間に進行スピナーを表示したい場合は、そのまま固定されます。ここで
CaptureImage()
ためのコードです:
public Bitmap CaptureImage()
{
if (!IsCapturing)
return null;
this.mediaControl.Stop();
IntPtr currentImage = IntPtr.Zero;
Bitmap bmp = null;
try
{
int hr = this.windowlessControl.GetCurrentImage(out currentImage);
DsError.ThrowExceptionForHR(hr);
if (currentImage != IntPtr.Zero)
{
BitmapInfoHeader bih = new BitmapInfoHeader();
Marshal.PtrToStructure(currentImage, bih);
...
// Irrelevant code removed
...
bmp = new Bitmap(bih.Width, bih.Height, stride, pixelFormat, new IntPtr(currentImage.ToInt64() + Marshal.SizeOf(bih)));
bmp.RotateFlip(RotateFlipType.RotateNoneFlipY);
}
}
catch (Exception ex)
{
MessageBox.Show("Failed to capture image:" + ex.Message);
}
finally
{
Marshal.FreeCoTaskMem(currentImage);
}
return bmp;
}
は、この問題を解決するために、私は次のようにバックグラウンドタスクとしてこれを実行しようとしました:
public async void CaptureImageAsync()
{
try
{
await Task.Run(() =>
{
CaptureImage();
});
}
catch(Exception ex)
{
MessageBox.Show(ex.Message);
}
}
私は複数を試してみましたこれを行う方法はBackgroundWorker
を使用していますが、この呼び出しを非同期的に行うたびにこのエラーが発生します。
ときに、このライン上のUnable to cast COM object of type 'DirectShowLib.VideoMixingRenderer9' to interface type 'DirectShowLib.IVMRWindowlessControl9'. This operation failed because the QueryInterface call on the COM component for the interface with IID '{8F537D09-F85E-4414-B23B-502E54C79927}' failed due to the following error: No such interface supported (Exception from HRESULT: 0x80004002 (E_NOINTERFACE)).
エラーが常に起こる:
CaptureImage()
を呼び出す
int hr = this.windowlessControl.GetCurrentImage(out currentImage);
は同期の正常な結果が得られます。イメージがキャプチャされ、すべてが意図どおりに機能します。しかし、あらゆる種類の非同期機能を使用するように切り替えると、そのエラーが発生します。
大きな説明 - 「最も人気がありますが不器用なのはサンプルグラバーを使用しています」という記述を少し拡張できますか?サンプルグラバーの仕組みがぎこちなく、何が良い方法でしょうか? –
@Roman R. DirectShow関連のコード用にMTAスレッドのプールを実装する方法についてもう少し詳細を教えてください。スレッドをSTAにする必要があるため、MTAスレッドでWPFウィンドウを開くことができません。私はあなたが言及したメソッドを実装しようとしてきましたが、実際の解決策を考え出すことはできません。 –
@MikeDinescu:これはこの質問の範囲を超えていると思いますが、後ほどこれを書き留めるノートを作成しました。 –