2012-08-10 4 views
1

나는 빠른 프레임 속도 (우리는 30fps를 원할 것임)로 여러 비디오 스트림을 표시해야하는 WPF 응용 프로그램을 만들고 있습니다. 비디오 스트림은 1920x1080 raw (RGB24) 프레임 (System.Drawing.Bitmap에 저장 됨)입니다. 누구든지 이것을 달성하는 방법에 대한 아이디어가 있습니까?빠른 비디오 디스플레이 WPF

자세한 내용 : 우리의 이전의 시도가 각 프레임에 대한 소스를 변경, 표준 WPF의 Image 컨트롤을 사용한

  • . 이것은 단일 스트림에 대해서는 효과적 이었지만 이제 다중 스트림을 렌더링해야하므로 속도가 느려집니다.
  • 또한 우리는 D3D9 공유 표면을 Image 컨트롤의 소스로 사용하여 Direct2D를 사용하여 그림을 처리해 보았습니다. 이 속도는 더 빠르지 만 여전히 안정적인 30fps를 얻을 수는 없습니다 (백업시 24-32fps로 점프합니다).
  • 비디오 스트림이 백그라운드 스레드로 들어온 후, (화면의 Dispatcher를 사용하여) 그리기 위해 적절한 UI 스레드로 마샬링됩니다. 그런 다음 모든 드로잉은 UI 스레드에서 수행됩니다. 또한 각 창에 자체 스레드를 제공하려고했습니다.

누구든지보고 싶은 경우 시도한 코드 샘플을 제공 할 수 있습니다.

감사합니다.

답변

4

솔루션을 찾는 사람이라면 그래픽 메모리에 고도로 최적화 된 복사본이 포함 된 DirectX 11을 사용하여 사용자 정의 winforms 컨트롤을 작성한 다음 WinformsHost에 컨트롤을 호스팅하여 관심있는 사람에게 코드를 제공 할 수 있습니다.

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

    /// <summary> 
    /// Copies a bitmap to gpu memory 
    /// </summary> 
    /// <param name="frame">The image to copy to the gpu</param> 
    /// <returns>A texture in gpu memory for the bitmap</returns> 
    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

당신이 그래픽 메모리로 복사를 최적화하는 방법을 더 말할 수 GPU 메모리에 복사 최적화? –

+1

@ 토마스 방금 복사 한 방법 코드의 전체 코드를 업데이트했습니다 –

+0

솔루션에 관심이 있습니다 ... 저에게 그것을 보낼 수 있습니까? linusang {at} yahoo {dot} com – icube

관련 문제