Gostaria de tentar implementar um VNC, para permitir que clientes vejam um videozinho do que eu estou fazendo no meu desktop, por exemplo enquanto eu mexo no Eclipse. Não preciso do controle remoto, apenas do video.
Estou meio perdido:
Existe um protocolo padrão para VNC com baixo consumo de banda?
Pensando um pouco pensei que eu poderia implementar o meu próprio protocolo, enviando apenas os pixels que estão mudando na tela. Daí se o cara fica olhando admirado para o eclipse sem fazer nada ele não manda nada. Se o cara digita um código ele só manda os pixelzinhos do texto que está aparecendo ali. É assim que o VNC funciona ou é algo bem mais sofisticado?
De qualquer maneira, pegar os pixels e ver o que foi alterado é uma operação terrivelmente onerosa.
Provavelmente você deve ter já usado o VNC (tanto faz se é o TightVNC ou o RealVNC) e visto que ele puxa uma CPU violenta da máquina que está sendo controlada (eu estava controlando uma máquina Windows 98, Celeron 333 para poder fazer uns testes. O RealVNC estava puxando 30% da CPU )
O que o RealVNC faz agora é algo um pouco mais esperto. Ele instala um “hook” no Windows que vigia todas as operações de mouse, teclado e janelas. Quando alguma coisa é alterada na máquina que está sendo controlada, ele usa o “hook” para enviar para o client VNC os parâmetros da API que está sendo chamada pelo Windows para mover o mouse, ou tratar o teclado, ou pintar as janelas. Só que isso é tudo código em C mesmo. Ele só não usa o hook quando você está usando uma aplicação console. Nesse caso ele tem de usar o método de pegar os pixels e ver o que foi alterado - aí o bicho pega.
Acho que no meu caso, onde eu quero apenas um videozinho que vai passar dentro de uma janela com scrollbar, o primeiro método é mais indicado né?
Agora vc tem razão quanto a fome disso: 1024 x 768 = 786432 pixels
Se eu tenho um frame rate de 1 por segundo, vou ter que percorrer esse array a cada um segundo pra ver se algo mudou. O CPU não vai ficar idle nunca assim… É assim mesmo que eu vou ter que fazer isso né ??? Depois é legal meter um Zip encima dos pixels que mudaram né… Se o cara abriu uma tela branca encima, eu não vou querer mandar 786432 pixels brancos.
Quanto à “independência de plataforma” acho que você vai ter de se restringir à parte client. Tanto o TightVNC quanto o RealVNC têm clients Java.
E o esquema de compressão de ambos é bastante complicado, porque para fazer uma compressão eficiente, é necessário fazê-la em duas dimensões, não somente em uma, se você fosse usar um esquema ingênuo de .zip (e até 3 se você considerar a cor como sendo uma dimensão; o VNC tem a opção de diminuir a profundidade das cores - de 16M cores para somente 256 cores, por exemplo - para diminuir a quantidade de dados a serem transmitidos) . Além disso, usam alguns truques, por exemplo, é interessante atualizar mais freqüentemente a área em volta do “caret” e do ponteiro do mouse, porque é provavelmente lá onde você está focalizando sua atenção, e é provavelmente lá que a tela está sendo modificada.
Usa mpeg1, ou pelo menos jpeg, pra comprimir os frames. Codificar jpeg com java é brincadeira de criança (já tem API pra isso). Já mpeg exige um pouquinho mais de trabalho. Se usar jpeg, use tabelas fixas de compressão e quantização, isso te salva uns tantos bytes.
A parte ruim de usar técnicas lossy é que texto fica dificil de ler com compressão muito alta.
Mas se você estiver realmente se sentindo aventuroso, use lzw mesmo e use motion vectors, damage zones e toda esses truques para acelerar a transmissão.
E o mais importante, fique o mais longe possivel do TCP se você quer algo que funcione em real-time.
Fico imaginando um VNC com “lossy compression” (não só a redução de profundidade nas cores)…
Ia ser meio complicado digitar texto no site do GUJ, que usa umas letras muito pequenas. Ia aparecer só “sujeira”.
Pois é, já tem tudo pronto, e o client do RealVNC é minúsculo (tanto o applet quanto o executável), e foi portado para N arquiteturas, que custa rodar o client e o server? Eu lembro que existe um modo do VNC que lhe permite conectar N clients a um único server, para que você possa mostrar o tal “videozinho”.
Nao rodei o codigo, mas se eu entendi ele desenha um JFrame de 1024x768 na tela, e poe ele como visivel em cima de tudo, capturando o que estiver ali. Se for pra capturar soh coisas que acontecem dentro de uma janela AWT que vc tem controle, eh mais facil escutar a EventQueue - e tirar o screenshot sempre que um evento passar por ali
Acho que o legal seria vc minimizar esse JFrame e começar a mexer no Eclipse por exemplo. Daí o frame vai pegando tudo.
Mas concordo contigo, esse JFrame ficou sem utilidade. Não faz sentido para a pessoa que está capturando ver o que ela está capturando. Se não acaba virando espelho infinito.
Pô, tentei comprimir com ZIP e ficou ruim. Picos de 10 k por segundo. Fica muito pesado em termos de banda.
Vou dar uma olhada no VNC. Reinventar a roda dessa vez vai ser realmente loucura.
Acabei de ver tb que para cada pixel vc tem que enviar a posição e o valor, ou seja, o dobro de informações.
Que pena que o Swing não tem um esquema de permitir você amarrar um “hook” nas rotinas que você está chamando - ou teria se você mexesse em javax.swing.DebugGraphics?
(O fonte do Swing está disponível, mas você tem coragem de mexer nele?).
Senão dava para fazer uma coisa parecida com o RealVNC (ou o TightVNC usando um driver especial). Ou seja, em vez de ler a tela (uma operação lenta), a cada vez que o server executasse um comando do tipo drawString ou drawOval, por exemplo, enviasse para seus clientes (talvez usando UDP e multicast ) o comando drawString codificado, com os parâmetros…