简体   繁体   English

如何在WPF中从原始帧渲染视频?

[英]How to render video from raw frames in WPF?

I have a special video camera (using GigEVision protocol) that I control using a provided library. 我有一台特殊的摄像机(使用GigEVision协议),可以使用提供的库进行控制。 I can subscribe to a frame received event and then access the frame data via a IntPtr. 我可以订阅接收到帧的事件,然后通过IntPtr访问帧数据。

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. 在我的旧WinForms应用程序中,我可以通过从数据创建Bitmap对象并将其设置为PictureBox Image或通过将PictureBox手柄传递给提供的库中直接在该区域上绘制的函数来渲染框架。

What is the best and fastest way to do a similar thing in WPF? 在WPF中执行相似操作的最佳和最快方法是什么? The video camera runs anywhere from 30 to 100 fps. 摄像机的运行速度为30到100 fps。

edit(1): 编辑(1):

Since the frame received event is not on the UI thread it has to work across threads. 由于框架接收事件不在UI线程上,因此它必须跨线程工作。

edit(2): 编辑(2):

I found a solution using WriteableBitmap: 我找到了使用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());
        }
    });
}

In the above, VideoImageControlToUpdate is a WPF Image control. 在上面, VideoImageControlToUpdate是WPF图像控件。

For more speed I believe the VideoRendererElement found on codeplex is faster. 为了获得更高的速度,我相信在Codeplex上找到的VideoRendererElement会更快。

Best way: WriteableBitmap.WritePixels(..., IntPtr source, ...) 最好的方法:WriteableBitmap.WritePixels(...,IntPtr源,...)

Fastest way: Use WIC and all operations in IntPtr unmanaged memory. 最快的方法:在IntPtr非托管内存中使用WIC和所有操作。 But why use WPF at all in this case? 但是,为什么在这种情况下完全使用WPF? Consider using DirectX overlay if that kind of performance is required. 如果需要这种性能,请考虑使用DirectX覆盖。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM