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  }