最後に、それを達成する方法を見つけました。MediaPlayer が必要で、それを各 Canvas.OnRender ループの drawingContext.DrawVideo にフィードするだけです。以下のサンプル画像とコード。また、ビデオからフレーム (BitmapSource) をキャプチャするメソッドと、それを古い System.Drawing.Bitmap に変換する方法も含めました)。
public partial class RenderCanvas : UserControl
{
readonly MediaPlayer player;
public RenderCanvas()
{
InitializeComponent();
player = new MediaPlayer();
player.Open(new Uri(@"test.avi", UriKind.Relative));
player.Play();
}
protected override void OnRender(DrawingContext drawingContext)
{
base.OnRender(drawingContext);
if (player != null && player.Source != null)
drawingContext.DrawVideo(player, new Rect(0, 0, 200, 150));
// draw any shape in front of the video
drawingContext.DrawEllipse(Brushes.Blue, new Pen(Brushes.Red, 5), new Point(150, 150), 60, 60);
}
BitmapSource GetBitmapSourceFromVideo()
{
var drawingVisual = new DrawingVisual();
var renderTargetBitmap = new RenderTargetBitmap(player.NaturalVideoWidth, player.NaturalVideoHeight, 96, 96, PixelFormats.Default);
using (var drawingContext = drawingVisual.RenderOpen())
{
drawingContext.DrawVideo(player, new Rect(0, 0, player.NaturalVideoWidth, player.NaturalVideoHeight));
}
renderTargetBitmap.Render(drawingVisual);
return renderTargetBitmap;
}
System.Drawing.Bitmap GetBitmapFromVideo()
{
BitmapSource bitmapSource = GetBitmapSourceFromVideo();
var encoder = new PngBitmapEncoder();
encoder.Frames.Add(BitmapFrame.Create(bitmapSource));
using (var stream = new MemoryStream())
{
encoder.Save(stream);
stream.Seek(0, SeekOrigin.Begin);
return (System.Drawing.Bitmap)System.Drawing.Image.FromStream(stream);
}
}
}
サンプル アプリケーションの XAML コードを次に示します。RenderCanvas の XAML に変更はありません。
<Window x:Class="CanvasTest_OnRender.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:CanvasTest_OnRender="clr-namespace:CanvasTest_OnRender" Title="MainWindow" Height="350" Width="525">
<Grid>
<CanvasTest_OnRender:RenderCanvas />
</Grid>
</Window>
