Witam, ostatnio zacząłem bawić się trochę biblioteką OpenCV, która w bardzo prosty sposób umożliwia przejęcie, wyświetlenie, zapisanie itd. np. obrazu z kamerki. Obraz ten jest w podstawie obiektem struktury typu IplImage, która posiada pole ImageData które to jest niczym innym jak tablicą char. Jej wielkość to (przeważnie, z doświadczenia) Wymiary * ilość kanałów (xyn). Skoro tak to pomyślałem, że może by spróbować w prosty sposób realizacji przesyłu video przez sieć. Problem sprowadził się do przesyłania dużych tablic, np. dla obrazu o rozdzielczości 320x240 (3 kanały RGB) rozmiar tablicy to 230400 bajtów! Decydując się na protokół UDP przeczytałem, że efektywny przesył "czystych danych" to 508 bajtów co dawałoby maksymalną tablicę o wielkości lekko ponad 4000 komórek. Postanowiłem więc podzielić tą tablicę na części tak aby pojedynczy datagram nie był większy niż te 508 bajtów.. Gdy testuję program na jednym komputerze działa bardzo dobrze, w momencie gdy łącze się z kompem w mojej sieci lokalnej, po paru sekundach mam zwieche.. Poniżej przedstawiam kod.. Proszę o sugestie, jak efektywnie przesyłać duże porcje danych, czy o wytknięcie jakiś błędów..
Część wysyłająca w wątku klienta:
#define bits 3840 // liczba bitów jednorazowo przesyłana
char bufor[bits];
char buf[2];
int ret = 0;
int iSize = sizeof(server_adr);
static int p = 0;
while(ret != -1)
{
img = cvRetrieveFrame(cam); // przechwycenie obrazu i zapisanie do (IplImage*) img
cvResize(img, rs_img); // zmiana rozdzielczosc na 320x240
for(int i = 0; i < 60; i++) // funkcja dzielaco-wysylajaca
{
for(int j = 0; j < bits; j++, p++)
bufor[j] = rs_img->imageData[p];
ret = sendto(Socket, bufor, bits, 0, (sockaddr*)&server_adr, sizeof(server_adr));
if(!(p < 230400))
p = 0;
ret = recvfrom(Socket, buf, 2, 0, (sockaddr*)&server_adr, &iSize); //synchronizacja
}
}
Część odbierająca w wątku serwera:
#define bits 3840 // liczba bitow jednorazowo odbierana
char bufer[bits];
static int p = 0;
do
{
ret = recvfrom(Server, bufer, bits, 0, (sockaddr*)&local_adr, &iSize); // odbierz dane
for(int i = 0; i < bits; i++, p++) // (cząstkowe) kopiowanie do pola imageData
img->imageData[p] = bufer[i];
if(!(p < 230400))
{
cvShowImage("obraz", img); // wyswietlenie obrazu
cvWaitKey(20);
p = 0;
}
sendto(Server, ".", 2, 0, (sockaddr*)&local_adr, sizeof(local_adr)); // synchronizacja
}while(ret != -1);
Myślę, że problem sprowadza się do przesyłania dużych tablic szybko po sobie.. Zanim ktoś poleci mi od razu odrzucenie tego pomysłu i wskaże na RTP, proszę o jakieś pomysły ;)