4

各フレームを生の ImageData 形式 (RGBA 順でピクセルあたり 4 バイト) で送信することにより、WebSocket 経由でビデオをストリーミングしています。クライアントで各フレームを ( として) 受け取ったら、 putImageDataArrayBufferを使用して、この画像をできるだけ効率的にキャンバスに直接ペイントしたいと考えています。

これは私の現在の解決策です:

// buffer is an ArrayBuffer representing a properly-formatted image
var array = new Uint8ClampedArray(buffer);
var image = new ImageData(array, width, height);
canvas.putImageData(image, 0, 0);

しかし、それはかなり遅いです。理由についての私の理論:

  • 配列 (サイズは ~1MB) は、フレームごとに 3 回、 に 1 回、 に 1 回、最後にキャンバスに 3 回 (1 秒あたり 30 回)Uint8ClampedArrayコピーされます。ImageData

  • newフレームごとに 2 回使用していますが、これはガベージ コレクターにとって問題になる可能性があります。

これらの理論は正しいですか?もしそうなら、これをできるだけ速くするためにどのようなトリックを採用できますか? ブラウザ固有の回答を喜んで受け入れます。

4

1 に答える 1

5

いいえ、ImageDataimageと TypedArray の両方arrayがまったく同じ buffer を共有していますbuffer

これらは単なるポインターであり、元のバッファーが「コピー」されることはありません。

var ctx = document.createElement('canvas').getContext('2d');

var buffer = ctx.getImageData(0,0,ctx.canvas.width, ctx.canvas.height).data.buffer;

var array = new Uint8ClampedArray(buffer);

var image = new ImageData(array, ctx.canvas.width, ctx.canvas.height);

console.log(array.buffer === buffer && image.data.buffer === buffer);

処理時間の問題については、単純にビデオ ストリームを直接 videoElement に送信して を使用するのが最善の方法drawImageです。

于 2016-09-21T03:36:19.323 に答える