Is there any way to grab the frames from media element like a video without feeling any delay? – WPF

I have to show the frames from a media element in an Image control like a video. I have tried to grab continues frames from media element using a timer and bind that bitmap to Image source. But when setting the scale as 1, it seems like frames are grabbing very slowly. And when reduce the scale to 0.3 or below, the grabbing is working very fast. but the quality of frame is reducing.
Is there any way to solve this?
In short, I want to display the frames from media element to an Image source without any delay and with original quality.

    <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;
    }

Answers:

Thank you for visiting the Q&A section on Magenaut. Please note that all the answers may not help you solve the issue immediately. So please treat them as advisements. If you found the post helpful (or not), leave a comment & I’ll get back to you as soon as possible.

Method 1

Using a WinForms Bitmap in a WPF application doesn’t seem to be necessary.

Reuse a single instance of a RenderTargetBitmap that is only created when necessary and assigned to the Source property of the Image element.

As well, reuse the DrawingVisual and draw a rectangle with a VisualBrush only when size changes.

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);
    }
}

The code above works fine for me with Microsoft’s Wildlife.wmv and 35 ms timer interval.


All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0

0 0 votes
Article Rating
Subscribe
Notify of
guest

0 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
0
Would love your thoughts, please comment.x
()
x