Java. Zdalny pulpit. Jak przyspieszyć zrzut ekranu, przetwarzanie obrazu i przesył danych?

0

Witam.

Piszę program w stylu TeamViewer. Przesyłam dane pomiędzy klientem i serwerem na własnym komputerze "localhost".
Niestety uzyskuję tylko 10 fps. Zrzut ekranu ok 50 ms robotem javy. Kompresja BufferedImage na format jpg i przesył danych to ok 70-150 ms.
Chciałbym uzyskać chociaż 20 fps.
Pracuję na Windows 10, procesor i5 4x2.5-3.4, 8GB RAM rozdzielczość 1920 x 1080.
Do przesyłania danych używam protokołu TCP.
Wąskim gardłem przede wszystkim jest tu Robot Javy, konwersacja obrazu na jpg.

Może ktoś z Was walczył już z tymi problemami.
Zapoznam się chętnie ze wszystkimi propozycjami.

Pozdrawiam.

0

Nigdy nie robiłem czegoś takiego, ale co ty na to, żeby spróbować zmienić protokół TCP na UDP? Zazwyczaj streamy video jadą na UDP.. może czasem brakować jakiejś informacji, ale będzie trochę szybciej

1

Ło panie. Nawet jak będziesz płynnie i szybko kompresował to pewnie zje cię transfer - 200 megabitów może nie starczyć (przy lepszej jakości) :-)
Rozwiązanie gorsze:
Przesyłaj tylko zmienione fragmenty - zwykle na ekranie niewiele się dzieje i to głównie w jednym miejscu (kursor myszy i klawiatury).
Możesz po screenshocie najpierw szukać (skanowac) gdzie sie względem poprzedniej klatki zmieniło i tylko te fragmenty wysyłać.
Tylko po dużych zmiannach typu show desktop, maksymalizacja okienka - będzie przycinka - co zresztą zwykle sie dzieje we wszystkich remote desktopach.
W zasadzie to jest kwestia podobna jak kompresja wideo, klatki kluczowe i zmiany, są pewnie biblioteki do tego . W każdym razie przewalanie każdej klatki do jpg i przez sieć to raczej słaby pomysł.

Rozwiązanie lepsze:
zobacz jak to robią inni
https://github.com/bachirbenyammi/jrdesktop

0
caprio napisał(a):

Witam.

Piszę program w stylu TeamViewer. Przesyłam dane pomiędzy klientem i serwerem na własnym komputerze "localhost".
Niestety uzyskuję tylko 10 fps. Zrzut ekranu ok 50 ms robotem javy. Kompresja BufferedImage na format jpg i przesył danych to ok 70-150 ms.
Chciałbym uzyskać chociaż 20 fps.
Pracuję na Windows 10, procesor i5 4x2.5-3.4, 8GB RAM rozdzielczość 1920 x 1080.
Do przesyłania danych używam protokołu TCP.
Wąskim gardłem przede wszystkim jest tu Robot Javy, konwersacja obrazu na jpg.

Może ktoś z Was walczył już z tymi problemami.
Zapoznam się chętnie ze wszystkimi propozycjami.

Pozdrawiam.

Kiedyś bawiłem się w tego stylu aplikację z doświadczeń:

  • nie warto przesyłać danych przez TCP sam tak zrobiłem niestety, lepszym rozwiązaniem wydaje się być UDP
  • co do zrzutów ekranu tutaj możesz spróbowac podzielić obraz na fragmenty i za każdy niech odpowiada inny wątek odrobinę zyskasz, lub można się bawić w jakieś bardziej zaawansowane rozwiązania z predykcjami itp
  • można zmniejszyć obraz przed wysłaniem, i po stronie klienta zastosować operację odwrotną w efekcie mniej danych wysyłasz, co prawda strata na jakości ale zystkuje płynność
  • dodatkowo można pomyśleć by to skalowanie wielkości obrazu po jednej i drugiej stronie mogły być dostosowywane przez użytkownika w locie, coś takiego stosowałem i się sprawdzało, oczywiście wtedy trzeba pamiętac by wyliczać współczynniki żeby można było później kompesować współrzędne kliknięć myszy
0

Przede wszystkim nie renderuj JPG z BufferedImage za każdym razem, to jest ciężka operacja. Przekonwertuj BufferedImage do postaci 8bit na pixel, wyciągnij z niego tablicę bajtów i porównaj z ostatnia klatką. W rezultacie otrzymasz bardzo wiele zer przy obrazie nie zmieniającym się często, więc wtedy możesz taką deltę skompresować przez proste RLE i wysłać po sieci. Po drugiej stronie rozpakowywujesz deltę i aplikujesz zmiany w pamięci.

Robiłem podobny projekt, ale trochę bardziej przerypany bo chodziło o streaming okien należących tylko do konkretnego procesu - skończyło się na wywoływaniu WinAPI poprzez bibliotekę JNA i wzorowaniu na WebRTC z kodu Chromium :D

0

Wydaje mi się że skorzystam z komunikacji udp. Jednak jest tu pewien problem. Każda przesłany pakiet różni się wielkością. No ale chyba trzeba będzie dać coś na wyrost i wyrównać. Co do kompresji to fakt, daje popalić. A ten zas...y robot... Da się te shoty zrobić szybciej? ...jakimś jni, jna, opengl...czy coś? Jak nie to 4 wątki i ogień. Tylko też przy wyświetlaniu artefakty wychodzą. Porównywanie obrazów działa szybko jak się bufferedimage rzuci na tablicę bajtów i porówna jej długość. No ale przerzucenie na tablicę też jest czasochłonne. Porównywanie po pikselu odpada bo to już w ogóle jakaś lipa jest. Ciekawe jak to w teamviewerze zrobili ze tak śmiga? Fakt to nie w javie ale coś się tam kryje😆. Dzięki za podpowiedzi. Jakbyście mieli coś jeszcze ciekawego to piszcie, bo nie jeden z tym walczy...

0

Napisałem program do komunikacji UDP celem sprawdzenia jak to się spisze. Na maszynie lokalnej w pętli zwrotnej działa ładnie. Jednak na komputerze w sieci odpowiedź z serwera trwa ok 2 sekund. Przesyłamy pakiet zawiera krótki tekst. TCP działa normalnie. Azybko. Nie wiem o co chodzi. Macie jakieś pomysły?

1 użytkowników online, w tym zalogowanych: 0, gości: 1