C# 有没有办法像视频一样从媒体元素中抓取帧而不感到任何延迟WPF

C# 有没有办法像视频一样从媒体元素中抓取帧而不感到任何延迟WPF,c#,asp.net,wpf,mediaelement,C#,Asp.net,Wpf,Mediaelement,我必须在像视频一样的图像控件中显示媒体元素的帧。我尝试使用计时器从媒体元素中获取连续帧,并将该位图绑定到图像源。但是当将比例设置为1时,看起来帧抓取速度非常慢。当比例降低到0.3或以下时,抓取工作非常快。但是帧的质量正在下降。 有什么办法解决这个问题吗? 简而言之,我希望以原始质量毫不延迟地显示从媒体元素到图像源的帧 <MediaElement x:Name="MediaEL" Volume="0" ScrubbingEnabled=&quo

我必须在像视频一样的图像控件中显示媒体元素的帧。我尝试使用计时器从媒体元素中获取连续帧,并将该位图绑定到图像源。但是当将比例设置为1时,看起来帧抓取速度非常慢。当比例降低到0.3或以下时,抓取工作非常快。但是帧的质量正在下降。 有什么办法解决这个问题吗? 简而言之,我希望以原始质量毫不延迟地显示从媒体元素到图像源的帧

    <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毫秒的定时器间隔时运行良好