Fast Video Display WPF

前端 未结 1 1135
悲哀的现实
悲哀的现实 2021-02-06 19:49

I am working on a WPF application that needs to display several video streams at a fast frame rate (we would like 30 fps). The video streams are 1920x1080 raw (RGB24) frames (th

1条回答
  •  无人共我
    2021-02-06 20:05

    Anyone looking for a solution, we wrote a custom winforms control using DirectX 11 with a highly optimized copy into graphics memory, then hosted the control in a WinformsHost, I can provide some code to anyone who is interested.

    Optimized copy into gpu memory

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

    0 讨论(0)
提交回复
热议问题