# HG changeset patch # User John Tsiombikas <nuclear@member.fsf.org> # Date 1457922059 -7200 # Node ID 08ea0abdbb8aadaf4626cfb4f08ed9b2ee515caa # Parent 73b16c2ae6bf9e7b071a5a1d23f880174e90f8d8 argument parsing diff -r 73b16c2ae6bf -r 08ea0abdbb8a doorbelld/src/main.c --- a/doorbelld/src/main.c Sun Mar 13 07:56:26 2016 +0200 +++ b/doorbelld/src/main.c Mon Mar 14 04:20:59 2016 +0200 @@ -10,8 +10,11 @@ void *frame_proc(void *arg); int save_image(const char *fname, unsigned char *pixels, int xsz, int ysz); void sighandler(int s); +int parse_args(int argc, char **argv); -int fd; +const char *devfile = "/dev/video0"; +int fd = -1; +int port = 2828; int width = 640; int height = 480; int framerate = 30; @@ -23,18 +26,17 @@ int main(int argc, char **argv) { - char *devfile = "/dev/video0"; pthread_t thread; - if(argv[1]) { - devfile = argv[1]; + if(parse_args(argc, argv) == -1) { + return 1; } signal(SIGINT, sighandler); signal(SIGQUIT, sighandler); signal(SIGSEGV, sighandler); - if(srv_init(2828) == -1) { + if(srv_init(port) == -1) { return 1; } @@ -42,12 +44,28 @@ perror("failed to allocate frame"); return 1; } - - if((fd = wcam_open(devfile, width, height, framerate)) == -1) { - fprintf(stderr, "failed to open video device: %s\n", devfile); - return 1; + if(devfile) { + if((fd = wcam_open(devfile, width, height, framerate)) == -1) { + fprintf(stderr, "failed to open video device: %s\n", devfile); + return 1; + } + wcam_start(fd); + } else { + int i, j; + unsigned char *pptr = frame; + for(i=0; i<height; i++) { + for(j=0; j<width; j++) { + int p = (i ^ j) & 0xff; + pptr[0] = p; + pptr[1] = p << 1; + pptr[2] = p << 2; + pptr[3] = 255; + pptr += 4; + } + } + printf("serving test pattern\n"); + save_image("output.ppm", frame, width, height); } - wcam_start(fd); if(pthread_create(&thread, 0, frame_proc, 0) == -1) { fprintf(stderr, "failed to create frame processing thread\n"); @@ -61,22 +79,29 @@ int maxfd = srv_max_socket(); fd_set rdset; - if(fd > maxfd) maxfd = fd; + FD_ZERO(&rdset); - FD_ZERO(&rdset); - FD_SET(fd, &rdset); + if(fd != -1) { + if(fd > maxfd) maxfd = fd; + FD_SET(fd, &rdset); + printf("select on socket: %d (video)\n", fd); + } for(i=0; i<num_sockets; i++) { FD_SET(sock[i], &rdset); + printf("select on socket: %d\n", sock[i]); } - while((res = select(maxfd + 1, &rdset, 0, 0, 0)) == -1 && errno == EINTR); + while((res = select(maxfd + 1, &rdset, 0, 0, 0)) == -1 && + errno == EINTR && !done); + if(done) break; if(res == -1) { fprintf(stderr, "unexpected failure while waiting for I/O\n"); break; } + printf("res: %d\n", res); - if(FD_ISSET(fd, &rdset)) { + if(fd != -1 && FD_ISSET(fd, &rdset)) { wcam_wait(fd); pthread_mutex_lock(&mutex); frame_available = 1; @@ -95,8 +120,10 @@ pthread_cond_signal(&condvar); pthread_join(thread, 0); free(frame); - wcam_stop(fd); - wcam_close(fd); + if(fd != -1) { + wcam_stop(fd); + wcam_close(fd); + } return 0; } @@ -112,8 +139,10 @@ if(done) break; - wcam_read_frame_rgb(fd, frame); - save_image("output.ppm", frame, width, height); + if(fd != -1) { + wcam_read_frame_rgb(fd, frame); + save_image("output.ppm", frame, width, height); + } } return 0; } @@ -139,3 +168,57 @@ { done = 1; } + +void print_usage(const char *argv0) +{ + printf("Usage: %s [options]\n", argv0); + printf("options:\n"); + printf(" -s,-size <WxH>\n"); + printf(" -f,-fps <framerate>\n"); + printf(" -d,-device <devfile>\n"); + printf(" -p,-port <port>\n"); + printf(" -novideo\n"); + printf(" -h,-help\n"); +} + +int parse_args(int argc, char **argv) +{ + int i; + + for(i=1; i<argc; i++) { + if(argv[i][0] == '-') { + if(strcmp(argv[i], "-s") == 0 || strcmp(argv[i], "-size") == 0) { + if(sscanf(argv[++i], "%dx%d", &width, &height) != 2) { + fprintf(stderr, "invalid size specified: %s\n", argv[i - 1]); + return -1; + } + } else if(strcmp(argv[i], "-f") == 0 || strcmp(argv[i], "-fps") == 0) { + framerate = atoi(argv[++i]); + if(framerate <= 0) { + fprintf(stderr, "invalid framerate specified: %s\n", argv[i - 1]); + return -1; + } + } else if(strcmp(argv[i], "-novideo") == 0) { + devfile = 0; + } else if(strcmp(argv[i], "-d") == 0 || strcmp(argv[i], "-device") == 0) { + devfile = argv[++i]; + } else if(strcmp(argv[i], "-p") == 0 || strcmp(argv[i], "-port") == 0) { + port = atoi(argv[++i]); + if(port <= 0 || port >= 65535) { + fprintf(stderr, "invalid port specified: %s\n", argv[i - 1]); + return -1; + } + } else { + int help = strcmp(argv[i], "-h") == 0 || strcmp(argv[i], "-help") == 0; + if(!help) fprintf(stderr, "unrecognized option: %s\n", argv[i]); + print_usage(argv[0]); + exit(help ? 0 : 1); + } + } else { + fprintf(stderr, "unexpected argument: %s\n", argv[i]); + print_usage(argv[0]); + return -1; + } + } + return 0; +} diff -r 73b16c2ae6bf -r 08ea0abdbb8a doorbelld/src/srv.c --- a/doorbelld/src/srv.c Sun Mar 13 07:56:26 2016 +0200 +++ b/doorbelld/src/srv.c Mon Mar 14 04:20:59 2016 +0200 @@ -10,6 +10,8 @@ #include "srv.h" #include "dynarr.h" +/* TODO convert this whole thing to multicast */ + static int lis_sock = -1, max_socket = -1; static int *csock; @@ -45,6 +47,7 @@ lis_sock = -1; return -1; } + listen(lis_sock, 8); return 0; } @@ -84,16 +87,19 @@ if(s == lis_sock) { /* incoming connection */ struct sockaddr_in addr; - int addr_size; - - if((s = accept(lis_sock, (struct sockaddr*)&addr, (int*)&addr_size)) == -1) { - fprintf(stderr, "%s: failed to accept incoming connection\n", __func__); + socklen_t addr_size = sizeof addr; + if((s = accept(lis_sock, (struct sockaddr*)&addr, &addr_size)) == -1) { + fprintf(stderr, "%s: failed to accept incoming connection: %s\n", __func__, strerror(errno)); return -1; } printf("%s: incoming connection from %s:%d\n", __func__, inet_ntoa(addr.sin_addr), ntohs(addr.sin_port)); csock = dynarr_push(csock, &s); assert(csock); + if(s > max_socket) { + max_socket = s; + } + fcntl(s, F_SETFD, fcntl(s, F_GETFD) | O_NONBLOCK); return 0; } @@ -101,23 +107,44 @@ while((sz = read(s, buf, sizeof buf - 1)) > 0) { printf("%s: got data: %s\n", __func__, buf); } - if(sz < 0 && errno != EAGAIN) { + if(sz <= 0 && errno != EAGAIN) { /* client closed connection probably */ int i, num_clients = dynarr_size(csock); printf("%s: removing client\n", __func__); close(s); + max_socket = lis_sock; for(i=0; i<num_clients; i++) { if(csock[i] == s) { csock[i] = csock[num_clients - 1]; - csock = dynarr_pop(csock); - break; + } + if(csock[i] > max_socket) { + max_socket = csock[i]; } } - assert(i < num_clients); + + csock = dynarr_pop(csock); + --num_clients; } return 0; } +struct video_block { + int frame; + int x, y; + int width, height; + char pixels[1]; +}; +#define VBLOCK_HEADER_SIZE (offsetof(struct video_block, pixels)) + void srv_send_frame(unsigned char *frame, int xsz, int ysz) { + static unsigned char *buffer; + struct video_block *vblock; + + /* for now just send a big block */ + if(!buffer && !(buffer = malloc(xsz * ysz * 2) + VBLOCK_HEADER_SIZE)) { + fprintf(stderr, "failed to allocate frame send buffer\n"); + return; + } + vblock = buffer; }