Ultimamente ho lavorato su un semplice programma di condivisione dello schermo.C# Programma di streaming dello schermo
In realtà il programma funziona su un TCP protocol
e utilizza il Desktop duplicazione API - un servizio cool che supporta la cattura schermo molto veloce e anche fornire informazioni su MovedRegions
(aree che hanno cambiato solo la loro posizione sullo schermo, ma esistono ancora) e UpdatedRegions
(aree modificate).
La duplicazione desktop ha 2 Properties- 2 matrici di byte improtant una matrice per la previouspixels
e una matrice NewPixels
. Ogni 4 byte rappresentano un pixel nel RGBA forma così per esempio se lo schermo è 1920 x 1080 la dimensione del buffer è di 1920 x 1080 * 4.
riportano i principali dati importanti della mia strategia
- Nello stato iniziale (la prima volta) invio l'intero buffer di pixel (nel mio caso è 1920 x 1080 * 3) - il componente alpha è sempre 255 sugli schermi :)
Da ora in poi, iterato su AggiornatoRegioni (è una matrice di rettangoli) e invio i limiti delle regioni e Xo'r i pixel al loro interno qualcosa del genere:
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]); } } }
- I Comprimere il buffer utilizzando il wrapper lz4 scritto in C# (fare riferimento a [email protected]). Quindi, scrivo i dati su un NetworkStream.
- ho fondere le aree del lato ricevitore per ottenere l'immagine aggiornata - questo non è il nostro problema oggi :)
'scrittore' è un'istanza della classe 'QuickBinaryWriter' ho scritto (semplicemente quello di riutilizzare la stessa buffer di nuovo).
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]);
}
}
Da molte misure, ho visto che i dati inviati è davvero enorme, e, a volte per un singolo aggiornamento fotogramma i dati potrebbero arrivare fino a 200KB (dopo la compressione!). Siamo sinceri: 200kb non è proprio nulla, ma se voglio scorrere lo schermo in modo fluido e poter guardare in alta frequenza Fps dovrei lavorare un po 'su questo - a minimizzare il traffico di rete e l'utilizzo della larghezza di banda .
Sto cercando suggerimenti e idee creative per migliorare l'efficienza del programma, principalmente i dati inviati sulla parte di rete (imballandola in altri modi o qualsiasi altra idea), apprezzerò qualsiasi aiuto e idee. Grazie.
tuo la domanda è un po 'vaga. È necessario specificare quale parte si desidera ottimizzare. In questo momento la domanda ha troppe risposte potenziali, che possono portare a un calo dei voti e essere messe in attesa per essere troppo ampie. Darò un esempio di quanto ampio. Vuoi ottimizzare il codice, come invia i dati, la compressione o come aggiorna lo schermo? – dakre18
@ dakre18 grazie per l'attenzione, pricipalmente cerco per la compressione dei dati - ho bisogno di concentrarsi sulla minimizzazione del networktrafic - magari imballando i dati grafici in altro modo ...non so che è quello che ho scritto la mia domanda :) – Slashy
Hai già fatto questa domanda prima. – harold