最近我一直在做一個簡單的屏幕共享程序。C#屏幕流媒體程序
其實程序工作在TCP protocol
並使用桌面複製API - 一個很酷的服務支持非常快速的屏幕捕捉,並且還提供了有關MovedRegions
(即只改變了屏幕上的位置,但仍然領域存在)和信息UpdatedRegions
(更改區域)。
桌面複製有2個重要屬性 - 2字節數組數組爲previouspixels
和NewPixels
數組。每4個字節代表了RGBA形式的像素因此,例如,如果我的屏幕爲1920×1080的緩衝區大小爲1920×1080×4
下面是我的戰略的重要亮點
- 在初始狀態下(第一次),我發送整個像素緩衝區(在我的情況下它是1920 x 1080 * 3) - alpha分量始終爲255在屏幕上:)
從現在起,我遍歷UpdatedRegions (這是一個矩形陣列),我發送區域邊界和像素這樣的像素:
writer.Position = 0; var n = frame._newPixels; var w = 1920 * 4; //frame boundaries. var p = frame._previousPixels; foreach (var region in frame.UpdatedRegions) { writer.WriteInt(region.Top); writer.WriteInt(region.Height); writer.WriteInt(region.Left); writer.WriteInt(region.Width); for (int y = region.Top, yOffset = y * w; y < region.Bottom; y++, yOffset += w) { for (int x = region.Left, xOffset = x * 4, i = yOffset + xOffset; x < region.Right; x++, i += 4) { writer.WriteByte(n[i]^p[i]); //'n' is the newpixels buffer and 'p' is the previous.xoring for differences. writer.WriteByte(n[i+1]^p[i+1]); writer.WriteByte(n[i + 2]^p[i + 2]); } } }
- 我用c#編寫的lz4包裝器(參考[email protected])壓縮緩衝區。然後,我將數據寫入NetworkStream。
- 我合併在接收側的區域,以獲得更新的圖像 - 今天這個:)
「作家」是我寫的「QuickBinaryWriter」類實例(簡單地重複使用相同的不是我們的問題緩衝區)。
public class QuickBinaryWriter
{
private readonly byte[] _buffer;
private int _position;
public QuickBinaryWriter(byte[] buffer)
{
_buffer = buffer;
}
public int Position
{
get { return _position; }
set { _position = value; }
}
public void WriteByte(byte value)
{
_buffer[_position++] = value;
}
public void WriteInt(int value)
{
byte[] arr = BitConverter.GetBytes(value);
for (int i = 0; i < arr.Length; i++)
WriteByte(arr[i]);
}
}
從很多措施,我已經看到了發送的數據確實是巨大的,有時單個幀更新的數據可以得到高達200KB(壓縮後!)。 讓我們誠實 - 200kb是真的沒什麼,但如果我想流暢地流媒體屏幕,並能夠以高FPS速率觀看,我將不得不在這一點上工作 - 以最大限度地減少網絡流量和帶寬使用 。
我在尋找建議和創意,以提高程序的效率 - 主要是網絡部分發送的數據(通過用其他方式或任何其他想法包裝)我會很感激任何幫助和想法。謝謝。
你問題有點含糊。您應該指定您想要優化的部分。現在這個問題有太多可能的答案,這可能會導致反對票被擱置,因爲過於寬泛而被擱置。我將舉一個廣泛的例子。你想優化代碼,它如何發送數據,壓縮,或者它如何更新屏幕? – dakre18
@ dakre18感謝您的關注,我主要尋找數據壓縮 - 我需要關注最小化網絡流量 - 可能以其他方式打包圖形數據...我不知道這就是我寫我的問題:) – Slashy
您以前問過這個問題。 – harold