【问题标题】:How to render video from raw frames in WPF?如何从 WPF 中的原始帧渲染视频?
【发布时间】:2023-05-08 19:43:01
【问题描述】:

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

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

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

编辑(1):

由于帧接收事件不在 UI 线程上,它必须跨线程工作。

编辑(2):

我找到了使用 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 控件。

为了更快的速度,我相信在 codeplex 上找到的 VideoRendererElement 更快。

【问题讨论】:

    标签: c# wpf video


    【解决方案1】:

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

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

    【讨论】:

    • 您有使用 DirectX 的示例的链接吗?
    • DirectX 是要走的路——它不是超级复杂。您将需要一个 DIrectX 库(对于 C#,有一些开源库),然后 - 一些基本知识。性能摇滚 ;)
    最近更新 更多