如何从 WPF 中的原始帧渲染视频? [英] How to render video from raw frames in WPF?

查看:35
本文介绍了如何从 WPF 中的原始帧渲染视频?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个特殊的摄像机(使用 GigEVision 协议),我使用提供的库进行控制.我可以订阅帧接收事件,然后通过 IntPtr 访问帧数据.

I have a special video camera (using GigEVision protocol) that I control using a provided library. I can subscribe to a frame received event and then access the frame data via a IntPtr.

在我的旧 WinForms 应用程序中,我可以通过从数据创建 Bitmap 对象并将其设置为 PictureBox 图像,或将 PictureBox 句柄传递给提供的库中的函数来渲染框架,该函数将直接在该区域上绘制.

In my old WinForms app I could render the frame by either creating a Bitmap object from the data and setting it to a PictureBox Image, or by passing the PictureBox handle to a function in the provided library which would draw directly on the area.

在 WPF 中做类似事情的最好和最快的方法是什么?摄像机以 30 到 100 fps 的速度运行.

What is the best and fastest way to do a similar thing in WPF? The video camera runs anywhere from 30 to 100 fps.

编辑(1):

由于帧接收事件不在 UI 线程上,因此必须跨线程工作.

Since the frame received event is not on the UI thread it has to work across threads.

编辑(2):

我找到了一个使用 WriteableBitmap 的解决方案:

I found a solution using WriteableBitmap:

void camera_FrameReceived(IntPtr info, IntPtr frame) 
{
    if (VideoImageControlToUpdate == null)
    {
        throw new NullReferenceException("VideoImageControlToUpdate must be set before frames can be processed");
    }

    int width, height, size;
    unsafe
    {
        BITMAPINFOHEADER* b = (BITMAPINFOHEADER*)info;

        width = b->biWidth;
        height = b->biHeight;
        size = (int)b->biSizeImage;
    }
    if (height < 0) height = -height;

        //Warp space-time
        VideoImageControlToUpdate.Dispatcher.Invoke((Action)delegate {
        try
        {
            if (VideoImageControlToUpdateSource == null)
            {
                VideoImageControlToUpdateSource =
                    new WriteableBitmap(width, height, 96, 96, PixelFormats.Gray8, BitmapPalettes.Gray256);
            }
            else if (VideoImageControlToUpdateSource.PixelHeight != height ||
                     VideoImageControlToUpdateSource.PixelWidth != width)
            {
                VideoImageControlToUpdateSource =
                    new WriteableBitmap(width, height, 96, 96, PixelFormats.Gray8, BitmapPalettes.Gray256);
            }

            VideoImageControlToUpdateSource.Lock();

            VideoImageControlToUpdateSource.WritePixels(
                new Int32Rect(0, 0, width, height),
                frame,
                size,
                width);

            VideoImageControlToUpdateSource.AddDirtyRect(new System.Windows.Int32Rect(0, 0, width, height));
            VideoImageControlToUpdateSource.Unlock();
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.ToString());
        }
    });
}

上面的VideoImageControlToUpdate是一个WPF Image控件.

In the above, VideoImageControlToUpdate is a WPF Image control.

对于更快的速度,我相信在 codeplex 上找到的 VideoRendererElement 会更快.

For more speed I believe the VideoRendererElement found on codeplex is faster.

推荐答案

最佳方式:WriteableBitmap.WritePixels(..., IntPtr source, ...)

Best way: WriteableBitmap.WritePixels(..., IntPtr source, ...)

最快的方式:在 IntPtr 非托管内存中使用 WIC 和所有操作.但是为什么在这种情况下完全使用 WPF?如果需要这种性能,请考虑使用 DirectX 覆盖.

Fastest way: Use WIC and all operations in IntPtr unmanaged memory. But why use WPF at all in this case? Consider using DirectX overlay if that kind of performance is required.

这篇关于如何从 WPF 中的原始帧渲染视频?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆