doorbell
diff doorbell-client/src/main.c @ 7:dc4018af3a40
video broadcast with UDP. retarded amount of data, unusable.
author | John Tsiombikas <nuclear@member.fsf.org> |
---|---|
date | Wed, 16 Mar 2016 02:50:30 +0200 |
parents | f21ae31ef0e7 |
children |
line diff
1.1 --- a/doorbell-client/src/main.c Wed Mar 16 00:00:06 2016 +0200 1.2 +++ b/doorbell-client/src/main.c Wed Mar 16 02:50:30 2016 +0200 1.3 @@ -1,6 +1,7 @@ 1.4 #include <stdio.h> 1.5 #include <stdlib.h> 1.6 #include <string.h> 1.7 +#include <stdint.h> 1.8 #include <errno.h> 1.9 #include <unistd.h> 1.10 #include <fcntl.h> 1.11 @@ -12,12 +13,12 @@ 1.12 #include <GL/freeglut_ext.h> 1.13 #include <GL/glx.h> 1.14 1.15 -struct video_block_header { 1.16 - unsigned int magic; 1.17 +struct video_block { 1.18 int frame; 1.19 - int x, y; 1.20 - int width, height; 1.21 - int frame_width, frame_height; 1.22 + uint16_t x, y; 1.23 + uint16_t width, height; 1.24 + uint16_t frame_width, frame_height; 1.25 + uint16_t pixels[1]; 1.26 }; 1.27 1.28 int conn(const char *host, int port); 1.29 @@ -25,15 +26,18 @@ 1.30 void reshape(int x, int y); 1.31 void keyb(unsigned char key, int x, int y); 1.32 int handle_conn(int s); 1.33 +int handle_video(int s); 1.34 void post_redisplay(void); 1.35 1.36 int quit; 1.37 -int srvsock; 1.38 +int ctlsock, vidsock; 1.39 const char *address = "localhost"; 1.40 int port = 2828; 1.41 unsigned int tex, tex_width, tex_height; 1.42 int redraw_pending; 1.43 1.44 +#define MAX(a, b) ((a) > (b) ? (a) : (b)) 1.45 + 1.46 int main(int argc, char **argv) 1.47 { 1.48 Display *dpy; 1.49 @@ -51,10 +55,10 @@ 1.50 dpy = glXGetCurrentDisplay(); 1.51 xsock = ConnectionNumber(dpy); 1.52 1.53 - if((srvsock = conn(address, port)) == -1) { 1.54 + if(conn(address, port) == -1) { 1.55 return 1; 1.56 } 1.57 - write(srvsock, "hello", 5); 1.58 + write(ctlsock, "hello", 5); 1.59 1.60 glGenTextures(1, &tex); 1.61 glBindTexture(GL_TEXTURE_2D, tex); 1.62 @@ -62,15 +66,16 @@ 1.63 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 1.64 1.65 for(;;) { 1.66 - int res; 1.67 - int maxfd = srvsock > xsock ? srvsock : xsock; 1.68 + int res, maxfd; 1.69 struct timeval tv0 = {0, 0}; 1.70 fd_set rdset; 1.71 1.72 FD_ZERO(&rdset); 1.73 FD_SET(xsock, &rdset); 1.74 - FD_SET(srvsock, &rdset); 1.75 + FD_SET(ctlsock, &rdset); 1.76 + FD_SET(vidsock, &rdset); 1.77 1.78 + maxfd = MAX(MAX(xsock, ctlsock), vidsock); 1.79 while((res = select(maxfd + 1, &rdset, 0, 0, redraw_pending ? &tv0 : 0) == -1) && errno == EINTR); 1.80 if(res == -1) break; 1.81 1.82 @@ -80,25 +85,29 @@ 1.83 break; 1.84 } 1.85 } 1.86 - if(FD_ISSET(srvsock, &rdset)) { 1.87 - if(handle_conn(srvsock) == -1) { 1.88 + if(FD_ISSET(ctlsock, &rdset)) { 1.89 + if(handle_conn(ctlsock) == -1) { 1.90 + break; 1.91 + } 1.92 + } 1.93 + if(FD_ISSET(vidsock, &rdset)) { 1.94 + if(handle_video(vidsock) == -1) { 1.95 break; 1.96 } 1.97 } 1.98 } 1.99 1.100 - close(srvsock); 1.101 + close(ctlsock); 1.102 return 0; 1.103 } 1.104 1.105 1.106 int conn(const char *hostname, int port) 1.107 { 1.108 - int s; 1.109 struct sockaddr_in addr; 1.110 struct hostent *host; 1.111 1.112 - if((s = socket(PF_INET, SOCK_STREAM, 0)) == -1) { 1.113 + if((ctlsock = socket(PF_INET, SOCK_STREAM, 0)) == -1) { 1.114 fprintf(stderr, "failed to create socket\n"); 1.115 return -1; 1.116 } 1.117 @@ -114,13 +123,28 @@ 1.118 addr.sin_addr = *(struct in_addr*)host->h_addr; 1.119 1.120 printf("connecting to %s (%s), port %d\n", hostname, inet_ntoa(addr.sin_addr), port); 1.121 - if(connect(s, (struct sockaddr*)&addr, sizeof addr) == -1) { 1.122 + if(connect(ctlsock, (struct sockaddr*)&addr, sizeof addr) == -1) { 1.123 fprintf(stderr, "failed to connect\n"); 1.124 return -1; 1.125 } 1.126 + fcntl(ctlsock, F_SETFL, fcntl(ctlsock, F_GETFL) | O_NONBLOCK); 1.127 1.128 - fcntl(s, F_SETFL, fcntl(s, F_GETFL) | O_NONBLOCK); 1.129 - return s; 1.130 + /* prepare the video socket */ 1.131 + if((vidsock = socket(PF_INET, SOCK_DGRAM, 0)) == -1) { 1.132 + fprintf(stderr, "failed to create video socket\n"); 1.133 + return 1; 1.134 + } 1.135 + 1.136 + memset(&addr, 0, sizeof addr); 1.137 + addr.sin_family = AF_INET; 1.138 + addr.sin_port = htons(port + 1); 1.139 + addr.sin_addr.s_addr = htonl(INADDR_ANY); 1.140 + if(bind(vidsock, (struct sockaddr*)&addr, sizeof addr) == -1) { 1.141 + fprintf(stderr, "failed to bind video socket to port %d\n", port + 1); 1.142 + return 1; 1.143 + } 1.144 + 1.145 + return 0; 1.146 } 1.147 1.148 void display(void) 1.149 @@ -139,10 +163,10 @@ 1.150 glEnable(GL_TEXTURE_2D); 1.151 1.152 glBegin(GL_QUADS); 1.153 - glTexCoord2f(0, 0); glVertex2f(-1, -1); 1.154 - glTexCoord2f(1, 0); glVertex2f(1, -1); 1.155 - glTexCoord2f(1, 1); glVertex2f(1, 1); 1.156 - glTexCoord2f(0, 1); glVertex2f(-1, 1); 1.157 + glTexCoord2f(0, 1); glVertex2f(-1, -1); 1.158 + glTexCoord2f(1, 1); glVertex2f(1, -1); 1.159 + glTexCoord2f(1, 0); glVertex2f(1, 1); 1.160 + glTexCoord2f(0, 0); glVertex2f(-1, 1); 1.161 glEnd(); 1.162 1.163 glDisable(GL_TEXTURE_2D); 1.164 @@ -169,41 +193,44 @@ 1.165 1.166 int handle_conn(int s) 1.167 { 1.168 + fprintf(stderr, "whaaaa!\n"); 1.169 + return -1; 1.170 +} 1.171 + 1.172 +int handle_video(int s) 1.173 +{ 1.174 static int cur_frame; 1.175 - struct video_block_header hdr; 1.176 - int size; 1.177 - unsigned char *pixels; 1.178 + static char buffer[2048]; 1.179 + struct video_block *vblock; 1.180 + struct sockaddr_in addr; 1.181 + socklen_t addr_size; 1.182 1.183 - if(read(s, &hdr, sizeof hdr) != sizeof hdr) { 1.184 - fprintf(stderr, "failed to read video block header\n"); 1.185 - return -1; 1.186 - } 1.187 - if(hdr.frame < cur_frame) { 1.188 - printf("skipping old frame %d\n", hdr.frame); 1.189 - } 1.190 - cur_frame = hdr.frame; 1.191 - printf("updating block %dx%d%+d%+d in frame %d\n", hdr.width, hdr.height, hdr.x, hdr.y, hdr.frame); 1.192 - 1.193 - size = hdr.width * hdr.height * 2; 1.194 - if(!(pixels = malloc(size))) { 1.195 - fprintf(stderr, "failed to allocate pixel block %dx%d\n", hdr.width, hdr.height); 1.196 - return -1; 1.197 - } 1.198 - if(read(s, pixels, size) != size) { 1.199 - fprintf(stderr, "failed to read pixel block\n"); 1.200 + addr_size = sizeof addr; 1.201 + if(recvfrom(vidsock, buffer, sizeof buffer, 0, (struct sockaddr*)&addr, &addr_size) == -1) { 1.202 + perror("failed to receive video block"); 1.203 return -1; 1.204 } 1.205 1.206 + vblock = (struct video_block*)buffer; 1.207 + 1.208 + if(vblock->frame < cur_frame) { 1.209 + printf("skipping old frame %d\n", vblock->frame); 1.210 + return 0; 1.211 + } 1.212 + cur_frame = vblock->frame; 1.213 + printf("updating block %dx%d%+d%+d in frame %d\n", vblock->width, vblock->height, 1.214 + vblock->x, vblock->y, vblock->frame); 1.215 + 1.216 glBindTexture(GL_TEXTURE_2D, tex); 1.217 1.218 - if(tex_width < hdr.frame_width || tex_height < hdr.frame_height) { 1.219 - tex_width = hdr.frame_width; 1.220 - tex_height = hdr.frame_height; 1.221 + if(tex_width < vblock->frame_width || tex_height < vblock->frame_height) { 1.222 + tex_width = vblock->frame_width; 1.223 + tex_height = vblock->frame_height; 1.224 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, tex_width, tex_height, 0, 1.225 GL_RGB, GL_UNSIGNED_SHORT_5_6_5, 0); 1.226 } 1.227 - glTexSubImage2D(GL_TEXTURE_2D, 0, hdr.x, hdr.y, hdr.width, hdr.height, 1.228 - GL_RGB, GL_UNSIGNED_SHORT_5_6_5, pixels); 1.229 + glTexSubImage2D(GL_TEXTURE_2D, 0, vblock->x, vblock->y, vblock->width, vblock->height, 1.230 + GL_RGB, GL_UNSIGNED_SHORT_5_6_5, vblock->pixels); 1.231 1.232 post_redisplay(); 1.233 return 0;