快速video显示WPF

我正在开发一个WPF应用程序,需要以快速帧速率显示多个video流(我们希望30 fps)。 video流是1920×1080原始(RGB24)帧(它们存储在System.Drawing.Bitmap中)。 有没有人对如何实现这一点有任何想法?

更多细节:

  • 我们之前的尝试使用了标准的WPF图像控件,改变了每帧的源。 这适用于单个流,但现在我们必须渲染多个流,它正在放慢速度。
  • 我们还尝试使用Direct2D来处理绘图,使用D3D9共享曲面作为Image控件的源。 虽然这个速度更快,但我们仍然无法从中获得稳定的30fps(当事情恢复时它会在24-32 fps之间跳跃)。
  • video流在后台线程中进入,然后被封送(使用窗口的Dispatcher)到适当的UI线程进行绘制。 然后在UI线程上完成所有绘图。 我们还尝试为每个窗口提供自己的线程。

如果有人想看,我可以提供我们尝试过的代码示例。

谢谢!

任何人都在寻找解决方案,我们使用DirectX 11编写了一个自定义winforms控件,并将高度优化的副本写入图形内存,然后在WinformsHost托管控件,我可以向感兴趣的任何人提供一些代码。

优化复制到gpu内存

  // Using native memcpy for the fastest possible copy [DllImport("msvcrt.dll", EntryPoint = "memcpy", CallingConvention = CallingConvention.Cdecl, SetLastError = false)] private static extern IntPtr memcpy(IntPtr dest, IntPtr src, UIntPtr count); ///  /// Copies a bitmap to gpu memory ///  /// The image to copy to the gpu /// A texture in gpu memory for the bitmap public Texture2D CopyFrameToGpuMemory(Bitmap frame) { SampleDescription sampleDesc = new SampleDescription(); sampleDesc.Count = 1; sampleDesc.Quality = 0; Texture2DDescription texDesc = new Texture2DDescription() { ArraySize = 1, MipLevels = 1, SampleDescription = sampleDesc, Format = Format.B8G8R8A8_UNorm, CpuAccessFlags = CpuAccessFlags.Write, BindFlags = BindFlags.ShaderResource, Usage = ResourceUsage.Dynamic, Height = frame.Height, Width = frame.Width }; Texture2D tex = new Texture2D(Device, texDesc); Surface surface = tex.AsSurface(); DataRectangle mappedRect = surface.Map(SlimDX.DXGI.MapFlags.Write | SlimDX.DXGI.MapFlags.Discard); BitmapData pixelData = frame.LockBits(new Rectangle(0, 0, frame.Width, frame.Height), ImageLockMode.ReadOnly, PixelFormat.Format32bppRgb); unsafe //!!! { byte* pixelDataStart = (byte*)pixelData.Scan0.ToPointer(); byte* mappedRectDataStart = (byte*)mappedRect.Data.DataPointer.ToPointer(); for (int y = 0; y < texDesc.Height; y++) { byte* lineLocationDest = mappedRectDataStart + (y * mappedRect.Pitch); byte* lineLocationSrc = pixelDataStart + (y * pixelData.Stride); // Copy line by line for best performance memcpy((IntPtr)lineLocationDest, (IntPtr)lineLocationSrc, (UIntPtr)(texDesc.Width * 4)); } } //!!! frame.UnlockBits(pixelData); mappedRect.Data.Dispose(); surface.Unmap(); surface.Dispose(); return tex; }