doorbell

view doorbelld/src/main.c @ 4:08ea0abdbb8a

argument parsing
author John Tsiombikas <nuclear@member.fsf.org>
date Mon, 14 Mar 2016 04:20:59 +0200
parents d3f2a2b19504
children f21ae31ef0e7
line source
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <string.h>
4 #include <errno.h>
5 #include <signal.h>
6 #include <pthread.h>
7 #include <wcam.h>
8 #include "srv.h"
10 void *frame_proc(void *arg);
11 int save_image(const char *fname, unsigned char *pixels, int xsz, int ysz);
12 void sighandler(int s);
13 int parse_args(int argc, char **argv);
15 const char *devfile = "/dev/video0";
16 int fd = -1;
17 int port = 2828;
18 int width = 640;
19 int height = 480;
20 int framerate = 30;
21 unsigned char *frame;
22 int done;
23 int frame_available;
24 pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
25 pthread_cond_t condvar = PTHREAD_COND_INITIALIZER;
27 int main(int argc, char **argv)
28 {
29 pthread_t thread;
31 if(parse_args(argc, argv) == -1) {
32 return 1;
33 }
35 signal(SIGINT, sighandler);
36 signal(SIGQUIT, sighandler);
37 signal(SIGSEGV, sighandler);
39 if(srv_init(port) == -1) {
40 return 1;
41 }
43 if(!(frame = malloc(width * height * 4))) {
44 perror("failed to allocate frame");
45 return 1;
46 }
47 if(devfile) {
48 if((fd = wcam_open(devfile, width, height, framerate)) == -1) {
49 fprintf(stderr, "failed to open video device: %s\n", devfile);
50 return 1;
51 }
52 wcam_start(fd);
53 } else {
54 int i, j;
55 unsigned char *pptr = frame;
56 for(i=0; i<height; i++) {
57 for(j=0; j<width; j++) {
58 int p = (i ^ j) & 0xff;
59 pptr[0] = p;
60 pptr[1] = p << 1;
61 pptr[2] = p << 2;
62 pptr[3] = 255;
63 pptr += 4;
64 }
65 }
66 printf("serving test pattern\n");
67 save_image("output.ppm", frame, width, height);
68 }
70 if(pthread_create(&thread, 0, frame_proc, 0) == -1) {
71 fprintf(stderr, "failed to create frame processing thread\n");
72 return 1;
73 }
75 while(!done) {
76 int i, res;
77 int *sock = srv_sockets();
78 int num_sockets = srv_num_sockets();
79 int maxfd = srv_max_socket();
80 fd_set rdset;
82 FD_ZERO(&rdset);
84 if(fd != -1) {
85 if(fd > maxfd) maxfd = fd;
86 FD_SET(fd, &rdset);
87 printf("select on socket: %d (video)\n", fd);
88 }
90 for(i=0; i<num_sockets; i++) {
91 FD_SET(sock[i], &rdset);
92 printf("select on socket: %d\n", sock[i]);
93 }
95 while((res = select(maxfd + 1, &rdset, 0, 0, 0)) == -1 &&
96 errno == EINTR && !done);
97 if(done) break;
98 if(res == -1) {
99 fprintf(stderr, "unexpected failure while waiting for I/O\n");
100 break;
101 }
102 printf("res: %d\n", res);
104 if(fd != -1 && FD_ISSET(fd, &rdset)) {
105 wcam_wait(fd);
106 pthread_mutex_lock(&mutex);
107 frame_available = 1;
108 pthread_mutex_unlock(&mutex);
109 pthread_cond_signal(&condvar);
110 }
112 for(i=0; i<num_sockets; i++) {
113 if(FD_ISSET(sock[i], &rdset)) {
114 srv_handle(sock[i]);
115 }
116 }
117 }
119 frame_available = 1;
120 pthread_cond_signal(&condvar);
121 pthread_join(thread, 0);
122 free(frame);
123 if(fd != -1) {
124 wcam_stop(fd);
125 wcam_close(fd);
126 }
127 return 0;
128 }
130 void *frame_proc(void *arg)
131 {
132 for(;;) {
133 pthread_mutex_lock(&mutex);
134 while(!frame_available) {
135 pthread_cond_wait(&condvar, &mutex);
136 }
137 frame_available = 0;
138 pthread_mutex_unlock(&mutex);
140 if(done) break;
142 if(fd != -1) {
143 wcam_read_frame_rgb(fd, frame);
144 save_image("output.ppm", frame, width, height);
145 }
146 }
147 return 0;
148 }
150 int save_image(const char *fname, unsigned char *pixels, int xsz, int ysz)
151 {
152 int i, num_pixels = xsz * ysz;
153 FILE *fp = fopen(fname, "wb");
154 if(!fp) return -1;
156 fprintf(fp, "P6\n%d %d\n255\n", xsz, ysz);
157 for(i=0; i<num_pixels; i++) {
158 fputc(*pixels++, fp);
159 fputc(*pixels++, fp);
160 fputc(*pixels++, fp);
161 ++pixels;
162 }
163 fclose(fp);
164 return 0;
165 }
167 void sighandler(int s)
168 {
169 done = 1;
170 }
172 void print_usage(const char *argv0)
173 {
174 printf("Usage: %s [options]\n", argv0);
175 printf("options:\n");
176 printf(" -s,-size <WxH>\n");
177 printf(" -f,-fps <framerate>\n");
178 printf(" -d,-device <devfile>\n");
179 printf(" -p,-port <port>\n");
180 printf(" -novideo\n");
181 printf(" -h,-help\n");
182 }
184 int parse_args(int argc, char **argv)
185 {
186 int i;
188 for(i=1; i<argc; i++) {
189 if(argv[i][0] == '-') {
190 if(strcmp(argv[i], "-s") == 0 || strcmp(argv[i], "-size") == 0) {
191 if(sscanf(argv[++i], "%dx%d", &width, &height) != 2) {
192 fprintf(stderr, "invalid size specified: %s\n", argv[i - 1]);
193 return -1;
194 }
195 } else if(strcmp(argv[i], "-f") == 0 || strcmp(argv[i], "-fps") == 0) {
196 framerate = atoi(argv[++i]);
197 if(framerate <= 0) {
198 fprintf(stderr, "invalid framerate specified: %s\n", argv[i - 1]);
199 return -1;
200 }
201 } else if(strcmp(argv[i], "-novideo") == 0) {
202 devfile = 0;
203 } else if(strcmp(argv[i], "-d") == 0 || strcmp(argv[i], "-device") == 0) {
204 devfile = argv[++i];
205 } else if(strcmp(argv[i], "-p") == 0 || strcmp(argv[i], "-port") == 0) {
206 port = atoi(argv[++i]);
207 if(port <= 0 || port >= 65535) {
208 fprintf(stderr, "invalid port specified: %s\n", argv[i - 1]);
209 return -1;
210 }
211 } else {
212 int help = strcmp(argv[i], "-h") == 0 || strcmp(argv[i], "-help") == 0;
213 if(!help) fprintf(stderr, "unrecognized option: %s\n", argv[i]);
214 print_usage(argv[0]);
215 exit(help ? 0 : 1);
216 }
217 } else {
218 fprintf(stderr, "unexpected argument: %s\n", argv[i]);
219 print_usage(argv[0]);
220 return -1;
221 }
222 }
223 return 0;
224 }