Image コントロールを継承する VideoRenderer クラス、VideoRenderer インスタンスを持つ MyVideo クラス、および MainWindow コード ビハインドの RenderFrames メソッドがあります。
これらのクラスの関連セクション、RenderFrames メソッド、および MainWindow 分離コード コンストラクターの一部を以下に添付しました。
VideoRenderer は外部ビデオを受け取り、ビデオ フレームを Bitmap オブジェクトとして生成し、「bitmap」フィールドに格納します。各プロセスが終了したら、ビットマップのクローンをフィールド「bitmapCopy」に保存します。
MyVideo は、VideoRenderer インスタンス「sharedVideoRenderer」が、MainWindow RenderFrames メソッドへのフレームの送受信を開始および停止するタイミングを制御し、ThreadPool.QueueUserWorkItem を使用して VideoRenderer インスタンスをオブジェクト パラメータとして渡します。
RenderFrames は、MyVideo が bool の「レンダリング中」プロパティのいずれかを変更して停止するように指示するまでループし、Bitmap -> BitmapImage -> Image.Source から変換を行い、MainWindow Dispatcher を使用して VideoContentControl.Content を画像として設定します。 .
すべてが機能し、ビデオはレンダリングされますが、操作全体を MainWindow スレッドにディスパッチし、絶えずループするとスレッドが拘束されるため、GUI コントロールは基本的にフリーズし、他のボタンやその他の機能は機能しません。
私の質問は次のとおりです。ビットマップ フレームを「sharedVideoRenderer」から VideoContentControl に転送し、GUI をフリーズせずに新しい画像で更新し続けるには、他にどのような方法がありますか?
どんな助けでも大歓迎です。
関連コード:
VideoRenderer.cs:
internal void DrawBitmap()
{
lock (bitmapLock)
{
bitmapCopy = (Bitmap)bitmap.Clone();
}
}
MyVideo.cs:
public static void RenderVideoPreview()
{
sharedVideoRenderer.VideoObject = videoPreview;
sharedVideoRenderer.Start();
videoPreviewIsRendering = true;
ThreadPool.QueueUserWorkItem((Application.Current.MainWindow as MainWindow).RenderFrames, sharedVideoRenderer);
}
MainWindow.xaml.cs:
Dispatcher mainWindowDispatcher;
public MainWindow()
{
InitializeComponent();
mainWindowDispatcher = this.Dispatcher;
...
public void RenderFrames(object videoRenderer)
{
while (MyVideo.VideoPreviewIsRendering || MyVideo.LiveSessionParticipantVideoIsRendering)
{
mainWindowDispatcher.Invoke(new Action(() =>
{
try
{
System.Drawing.Bitmap bitmap;
bitmap = (videoRenderer as VideoRenderer).BitmapCopy;
using (MemoryStream memory = new MemoryStream())
{
BitmapImage bitmapImage = new BitmapImage();
ImageSource imageSource;
Image image;
image = new Image();
bitmap.Save(memory, System.Drawing.Imaging.ImageFormat.Bmp);
memory.Position = 0;
bitmapImage.BeginInit();
bitmapImage.StreamSource = memory;
bitmapImage.CacheOption = BitmapCacheOption.OnLoad;
bitmapImage.EndInit();
imageSource = bitmapImage;
image.Source = imageSource;
VideoContentControl.Content = image;
memory.Close();
}
}
catch (Exception)
{
}
}));
}
mainWindowDispatcher.Invoke(new Action(() =>
{
VideoContentControl.ClearValue(ContentProperty);
VideoContentControl.InvalidateVisual();
}));
}