2010-11-23 4 views
5

私はASICでキャプチャしたフレームを再生するビデオプレーヤーを作成しています。それらはカスタムフォーマットであり、私はASICの状態をデコードする機能を備えています。ビデオは640x480から2560x1200までの任意のサイズ(!!!)です。各状態サイクルの出力は16×16ブロックのピクセルであり、画面上でビデオに入る必要があります。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を使用して検討します。そうすれば、1ピクセルあたり3バイト、4ではなく3バイトのオーバーヘッドがかなり少なくなります。

アップデート2

物事はより大きなフレームサイズのため、まだ遅すぎる場合は、あなたもかかわらず、複雑に次のことを考えることができます。

2つのフレームバッファの維持と反転を検討してください。このようにして、バックグラウンドスレッドでフレームを合成し、完成したフレームをUIスレッドでblitできます。 Whist UIスレッドはフレームをレンダリングしているので、代替バッファで合成を続けることができます。

アップデート3

あなたのキャプチャから、あなたのピクセルの色情報の配列が正しいフォーマットである場合は、フレームバッファ配列に一括コピーに元の画素配列をBuffer.BlockCopyを使用して試みることができます。ビットマップ形式はbgr32にしておく必要があります。この低レベルアレイコピー技術は、いくらかの性能向上をもたらすことができる。

+0

ありがとう! Buffer.BlockCopyを使用してバックグラウンドでバッファを構築し、次にフレームごとにWritePixels()を呼び出すことがトリックでした! – Stevoman

関連する問題