doorbell
diff doorbelld/src/srv.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 | 026156ea8801 |
children |
line diff
1.1 --- a/doorbelld/src/srv.c Wed Mar 16 00:00:06 2016 +0200 1.2 +++ b/doorbelld/src/srv.c Wed Mar 16 02:50:30 2016 +0200 1.3 @@ -59,9 +59,11 @@ 1.4 fprintf(stderr, "%s: failed to create video broadcast socket\n", __func__); 1.5 return -1; 1.6 } 1.7 + /*fcntl(bsock, F_SETFL, fcntl(bsock, F_GETFL) | O_NONBLOCK);*/ 1.8 val = 1; 1.9 setsockopt(bsock, SOL_SOCKET, SO_BROADCAST, &val, sizeof val); 1.10 1.11 + /* prepare the broadcast address struct */ 1.12 memset(&baddr, 0, sizeof baddr); 1.13 baddr.sin_family = AF_INET; 1.14 baddr.sin_port = htons(port + 1); 1.15 @@ -127,7 +129,7 @@ 1.16 while((sz = read(s, buf, sizeof buf - 1)) > 0) { 1.17 printf("%s: got data: %s\n", __func__, buf); 1.18 } 1.19 - if(sz <= 0 && errno != EAGAIN) { 1.20 + if((sz < 0 && errno != EAGAIN) || sz == 0) { 1.21 /* client closed connection probably */ 1.22 int i, num_clients = dynarr_size(csock); 1.23 printf("%s: removing client\n", __func__); 1.24 @@ -158,54 +160,84 @@ 1.25 } 1.26 1.27 struct video_block { 1.28 - unsigned int magic; 1.29 int frame; 1.30 - int x, y; 1.31 - int width, height; 1.32 - int frame_width, frame_height; 1.33 - char pixels[1]; 1.34 + uint16_t x, y; 1.35 + uint16_t width, height; 1.36 + uint16_t frame_width, frame_height; 1.37 + uint16_t pixels[1]; 1.38 }; 1.39 #define VBLOCK_HEADER_SIZE (offsetof(struct video_block, pixels)) 1.40 1.41 -void srv_send_frame(unsigned char *frame, int xsz, int ysz) 1.42 +/* ideally we would want each block to stay under the MTU (1500) */ 1.43 +#define BLKSZ 24 1.44 + 1.45 +int srv_send_frame(unsigned char *frame, int xsz, int ysz) 1.46 { 1.47 static int frame_num; 1.48 - static unsigned char *buffer; 1.49 - int i, j, size, num_clients; 1.50 + int i, j; 1.51 struct video_block *vblock; 1.52 - uint16_t *dest; 1.53 + int blksz; 1.54 1.55 - printf("sending frame\n"); 1.56 + printf("sending frame: %d\n", frame_num); 1.57 1.58 - /* for now just send a big block */ 1.59 - size = xsz * ysz * 2 + VBLOCK_HEADER_SIZE; 1.60 - if(!buffer && !(buffer = malloc(size))) { 1.61 - fprintf(stderr, "failed to allocate frame send buffer\n"); 1.62 - return; 1.63 + blksz = BLKSZ * BLKSZ * 2 + VBLOCK_HEADER_SIZE; 1.64 + if(!(vblock = malloc(blksz))) { 1.65 + fprintf(stderr, "failed to allocate %dx%d block buffer\n", BLKSZ, BLKSZ); 1.66 + return -1; 1.67 } 1.68 - vblock = (struct video_block*)buffer; 1.69 1.70 - vblock->magic = 0x12341234; 1.71 vblock->frame = frame_num++; 1.72 vblock->x = vblock->y = 0; 1.73 - vblock->width = vblock->frame_width = xsz; 1.74 - vblock->height = vblock->frame_height = ysz; 1.75 + vblock->frame_width = xsz; 1.76 + vblock->frame_height = ysz; 1.77 1.78 - dest = (uint16_t*)vblock->pixels; 1.79 + vblock->y = 0; 1.80 + while(vblock->y < ysz) { 1.81 + if(vblock->y + BLKSZ <= ysz) { 1.82 + vblock->height = BLKSZ; 1.83 + } else { 1.84 + vblock->height = ysz - vblock->y; 1.85 + } 1.86 1.87 - for(i=0; i<ysz; i++) { 1.88 - for(j=0; j<xsz; j++) { 1.89 - unsigned int r = frame[0]; 1.90 - unsigned int g = frame[1]; 1.91 - unsigned int b = frame[2]; 1.92 + vblock->x = 0; 1.93 + while(vblock->x < xsz) { 1.94 + if(vblock->x + BLKSZ <= xsz) { 1.95 + vblock->width = BLKSZ; 1.96 + } else { 1.97 + vblock->width = xsz - vblock->x; 1.98 + } 1.99 1.100 - *dest++ = ((r << 8) & 0xf800) | ((g << 3) & 0x7e0) | ((b >> 3) & 0x1f); 1.101 - frame += 4; 1.102 + unsigned char *src = frame + (vblock->y * xsz + vblock->x) * 4; 1.103 + uint16_t *dest = vblock->pixels; 1.104 + 1.105 + /* convert block to 565 */ 1.106 + for(i=0; i<vblock->height; i++) { 1.107 + for(j=0; j<vblock->width; j++) { 1.108 + unsigned int r = src[0]; 1.109 + unsigned int g = src[1]; 1.110 + unsigned int b = src[2]; 1.111 + 1.112 + *dest++ = ((r << 8) & 0xf800) | ((g << 3) & 0x7e0) | ((b >> 3) & 0x1f); 1.113 + src += 4; 1.114 + } 1.115 + src += (xsz - vblock->width) * 4; 1.116 + } 1.117 + 1.118 + /* and broadcast it */ 1.119 + printf("f(%d) b(%d,%d)\n", frame_num - 1, vblock->x, vblock->y); 1.120 + if(sendto(bsock, vblock, blksz, 0, (struct sockaddr*)&baddr, sizeof baddr) == -1) { 1.121 + perror("failed to send block"); 1.122 + if(errno == EMSGSIZE) { 1.123 + abort(); 1.124 + } 1.125 + return -1; 1.126 + } 1.127 + 1.128 + vblock->x += BLKSZ; 1.129 } 1.130 + vblock->y += BLKSZ; 1.131 } 1.132 1.133 - num_clients = dynarr_size(csock); 1.134 - for(i=1; i<num_clients; i++) { /* first socket is the listening socket */ 1.135 - write(csock[i], buffer, size); 1.136 - } 1.137 + free(vblock); 1.138 + return 0; 1.139 }