C# 有没有办法像视频一样从媒体元素中抓取帧而不感到任何延迟WPF
我必须在像视频一样的图像控件中显示媒体元素的帧。我尝试使用计时器从媒体元素中获取连续帧,并将该位图绑定到图像源。但是当将比例设置为1时,看起来帧抓取速度非常慢。当比例降低到0.3或以下时,抓取工作非常快。但是帧的质量正在下降。 有什么办法解决这个问题吗? 简而言之,我希望以原始质量毫不延迟地显示从媒体元素到图像源的帧C# 有没有办法像视频一样从媒体元素中抓取帧而不感到任何延迟WPF,c#,asp.net,wpf,mediaelement,C#,Asp.net,Wpf,Mediaelement,我必须在像视频一样的图像控件中显示媒体元素的帧。我尝试使用计时器从媒体元素中获取连续帧,并将该位图绑定到图像源。但是当将比例设置为1时,看起来帧抓取速度非常慢。当比例降低到0.3或以下时,抓取工作非常快。但是帧的质量正在下降。 有什么办法解决这个问题吗? 简而言之,我希望以原始质量毫不延迟地显示从媒体元素到图像源的帧 <MediaElement x:Name="MediaEL" Volume="0" ScrubbingEnabled=&quo
<MediaElement x:Name="MediaEL" Volume="0" ScrubbingEnabled="True" SnapsToDevicePixels="True" MediaOpened="MediaEL_MediaOpened" LoadedBehavior="Manual" MediaEnded="MediaEL_MediaEnded" MediaFailed="MediaEL_MediaFailed">
</MediaElement>
<Image Name="ImageViewerMediaEL" />
ScreenShotimer = new DispatcherTimer();
ScreenShotimer.Interval = TimeSpan.FromMilliseconds(35);//35//
ScreenShotimer.Tick += ScreenShotimer_Tick;
public Bitmap TakeScreenshot(MediaElement medElement, double scale)
{
Bitmap screenBitmap = null;
double actualHeight = medElement.NaturalVideoHeight;
double actualWidth = medElement.NaturalVideoWidth;
double renderHeight = actualHeight * scale;
double renderWidth = actualWidth * scale;
if ((int)renderWidth > 0 && (int)renderHeight > 0)
{
RenderTargetBitmap renderTarget = new RenderTargetBitmap((int)renderWidth,
(int)renderHeight, 96, 96, PixelFormats.Default);
VisualBrush sourceBrush = new VisualBrush(medElement);
DrawingVisual drawingVisual = new DrawingVisual();
DrawingContext drawingContext = drawingVisual.RenderOpen();
using (drawingContext)
{
drawingContext.PushTransform(new ScaleTransform(scale, scale));
drawingContext.DrawRectangle(sourceBrush, null, new Rect(new System.Windows.Point(0, 0),
new System.Windows.Point(actualWidth, actualHeight)));
}
renderTarget.Render(drawingVisual);
MemoryStream stream = new MemoryStream();
BitmapEncoder encoder = new BmpBitmapEncoder();
encoder.Frames.Add(BitmapFrame.Create(renderTarget));
encoder.Save(stream);
screenBitmap = new Bitmap(stream);
}
return screenBitmap;
}
ScreenShotimer=新的调度程序();
ScreenShotimer.Interval=时间跨度从毫秒(35)//35//
ScreenShotimer.Tick+=屏幕快照计时器\u Tick;
公共位图截图(MediaElement medElement,双比例)
{
位图屏幕位图=空;
双实际高度=medElement.NaturalVideoHeight;
双实际宽度=medElement.NaturalVideoWidth;
双渲染高度=实际高度*比例;
双渲染宽度=实际宽度*比例;
如果((int)渲染宽度>0&(int)渲染宽度>0)
{
RenderTargetBitmap renderTarget=新的RenderTargetBitmap((int)renderWidth,
(int)renderHeight,96,96,PixelFormats.Default);
VisualBrush sourceBrush=新的VisualBrush(medElement);
DrawingVisual DrawingVisual=新建DrawingVisual();
DrawingContext DrawingContext=drawingVisual.RenderOpen();
使用(drawingContext)
{
PushTransform(新的ScaleTransform(scale,scale));
drawingContext.DrawRectangle(sourceBrush,null,new Rect(new System.Windows.Point,0),
新系统.Windows.Point(实际宽度、实际高度));
}
renderTarget.Render(drawingVisual);
MemoryStream stream=新的MemoryStream();
BitmapEncoder编码器=新的BmpBitmapEncoder();
Add(BitmapFrame.Create(renderTarget));
编码器。保存(流);
屏幕位图=新位图(流);
}
返回屏幕位图;
}
在WPF应用程序中使用WinForms位图似乎没有必要
重用仅在必要时创建并指定给图像元素的源属性的RenderTargetBitmap的单个实例
同样,重复使用DrawingVisual并仅在大小更改时使用VisualBrush绘制矩形
private readonly DrawingVisual visual = new DrawingVisual();
private RenderTargetBitmap bitmap;
...
private void OnTimerTick(object sender, EventArgs e)
{
var width = MediaEL.NaturalVideoWidth;
var height = MediaEL.NaturalVideoHeight;
if (width > 0 && height > 0)
{
if (bitmap == null ||
bitmap.PixelWidth != width ||
bitmap.PixelHeight != height)
{
using (var dc = visual.RenderOpen())
{
dc.DrawRectangle(
new VisualBrush(MediaEL), null,
new Rect(0, 0, width, height));
}
bitmap = new RenderTargetBitmap(
width, height, 96, 96, PixelFormats.Default);
ImageViewerMediaEL.Source = bitmap;
}
bitmap.Render(visual);
}
}
上面的代码在使用微软的wildives.wmv和35毫秒的定时器间隔时运行良好