2010-11-23 4 views
5

우리 ASIC에서 캡처 한 프레임을 재생하기 위해 비디오 플레이어를 쓰고 있습니다. 그것들은 사용자 정의 형식이며, ASIC 상태를 디코딩하는 기능이 제공되었습니다. 동영상의 크기는 640x480에서 2560x1200 (!!!)까지 가능합니다. 각 상태 사이클의 출력은 16x16 픽셀 블록으로, 화면에서 비디오로 들어가야합니다.WPF에서 비디오를 생성하고 그릴 수있는 가장 빠른 방법은 무엇입니까?

화면을 업데이트해야 할 때마다, 나는 다음과 같은 정보가 있습니다

  • 블록 폭
  • 블록 높이
  • X 시작 블록의 좌표
  • Y 블록의 좌표를 시작
  • RGB32 픽셀 색상 정보의 1 차원 배열

개 주요 제한 :

  • .NET 3.5

나는 다음과 같이 뭔가를 WriteableBitmap을 시도하고, 이미지의 소스로 사용하여이 아침 보냈다 안전하지 않은 코드 :

private WriteableBitmap ImageSource; 

    public MainWindow() 
    { 
     InitializeComponent(); 

     ImageSource = new WriteableBitmap(FrameWidth, FrameHeight, 96, 96, PixelFormats.Bgr32, null); 
     ImagePanel.Source = ImageSource; 
    } 

    private void DrawBox(byte Red, byte Green, byte Blue, int X, int Y) 
    { 
     int BoxWidth = 16; 
     int BoxHeight = 16; 
     int BytesPerPixel = ImageSource.Format.BitsPerPixel/8; 

     byte[] Pixels = new byte[BoxWidth * BoxHeight * BytesPerPixel]; 

     for (int i = 0; i < Pixels.Length; i += 4) 
     { 
      Pixels[i + 0] = Blue; 
      Pixels[i + 1] = Green; 
      Pixels[i + 2] = Red; 
      Pixels[i + 3] = 0; 
     } 

     int Stride = BoxWidth * BytesPerPixel; 
     Int32Rect DrawBox = new Int32Rect(X, Y, BoxWidth, BoxHeight); 

     ImageSource.Lock(); 
     ImageSource.WritePixels(DrawBox, Pixels, Stride, 0); 
     ImageSource.Unlock(); 
    } 

내 비디오가 작동하지만 작동하지만 sloooooooow입니다. 실시간 재생 속도가 거의 없습니다. 거기에 일련의 비트 맵을 절차 적으로 생성하는 것 외에 더 좋은 방법이 있습니까? D3Dimage에 대해 읽은 적이 있지만 3D 장면을 비트 맵으로 내보내는 것이 더 많은 것 같습니다. 여기에 제안이 있습니까?

+0

DrawBox는 단색의 16 * 16 픽셀 블록을 만드는 것처럼 보입니다. 이 올바른지? –

+0

WriteableBitmap.WritePixels 메서드 (Int32Rect, Array, Int32, Int32, Int32)를 사용하면 소스 잠금 및 잠금 해제를 사용할 필요가 없습니다. http://msdn.microsoft.com/en-us/library/cc490065.aspx – Gorgen

+0

예 , DrawBox는 솔리드 컬러 블록을 그리기 위해 함께 사용했던 것입니다. 또한 Locking에 감사드립니다. 더 가까이 읽었어야했습니다. – Stevoman

답변

6

올바르게 이해하면 16 * 16 픽셀 블록이 캡처로 제공되며 위의 예에서 이러한 각 업데이트에 대해 쓰기 가능한 비트 맵을 업데이트합니다.

이것은 각 블록에서 렌더링이 시작될 때 많은 혼란처럼 보입니다.

  • 는 전체 프레임을 나타내는 단일 바이트 버퍼를 유지 :

    더 좋을 없다.
  • 버퍼를받은대로 16 * 16 블록으로 업데이트하십시오.
  • 프레임의 모든 블록을 받았으면 버퍼를 비트 맵에 씁니다.
  • 다음 프레임의 프레임 버퍼를 다시 덮어서 다시 사용하십시오.

이렇게하면 수신하는 각 블록에 대해 렌더링을 트리거하지 않으므로 각 프레임에 대해서만 렌더링을 수행하므로 훨씬 적은 양의 렌더링이 가능합니다.

업데이트 1

나는 또한 당신이 알파 채널을 사용하지 않는 경우 픽셀 형식으로 Bgr24 사용을 고려한다. 그렇게하면 픽셀 당 3 바이트가되므로 4보다 훨씬 적은 오버 헤드가 발생합니다.상황이 여전히 큰 프레임 크기가 너무 느린 경우

업데이트 2

은 또한 비록 복잡해 다음을 고려할 수 있습니다.

두 개의 프레임 버퍼 유지 및 반전을 고려하십시오. 이 방법으로 배경 스레드에서 프레임을 합성 한 다음 완성 된 프레임을 UI 스레드에서 블릿 할 수 있습니다. UI 스레드가 프레임을 렌더링하고 있기 때문에 대체 버퍼에서 계속 합성 할 수 있습니다.

업데이트 3

캡처에서 픽셀의 색상 정보 배열이 올바른 형식 인 경우, 당신은 대량으로 Buffer.BlockCopy는 프레임 버퍼 배열에 소스 픽셀 배열을 복사하여 시도 할 수 있습니다. 비트 맵 형식을 bgr32로 유지해야합니다. 이 저수준 배열 복사 기술은 성능을 약간 향상시킬 수 있습니다.

+0

감사합니다! Buffer.BlockCopy를 사용하여 백그라운드에서 버퍼를 만든 다음 프레임 당 한 번 WritePixels()를 호출하면 트릭을 만들었습니다! – Stevoman

관련 문제