Cosmetics
[rawv.git] / rawv.cpp
blobd2be6493f506022463c6e50c631a35206df2d755
1 /*
2 * RAWV demo
3 * Copyright (C) 2010 Kirill Smelkov <kirr@navytux.spb.ru>
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19 * See COPYING.LIB file for full License terms.
22 #include "rawv.h"
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <stdarg.h>
27 #include <string.h>
29 #include <getopt.h> /* getopt_long() */
31 #include <errno.h>
32 #include <malloc.h>
33 #include <sys/time.h>
35 #include <string>
38 using namespace rawv;
39 using std::string;
40 using std::max;
45 * Globals
48 View *view = NULL;
49 VideoCapture *vcap = NULL;
50 NetTx *nettx = NULL;
51 NetRx *netrx = NULL;
55 /****************************************/
58 void mainloop(void)
60 for (;;) {
61 fd_set fds;
62 struct timeval tv;
63 int r, fdmax=-1;
65 FD_ZERO (&fds);
67 if (vcap) {
68 FD_SET (vcap->fd, &fds);
69 fdmax = max(fdmax, vcap->fd);
72 if (netrx) {
73 FD_SET (netrx->sk, &fds);
74 fdmax = max(fdmax, netrx->sk);
78 /* Timeout. */
79 tv.tv_sec = 2;
80 tv.tv_usec = 0;
82 /* WARNING: select() with timeout under load is very expensive - for
83 * almost every packet the timer will be set up which costs significant
84 * overhead.
86 * Avoid that, but TODO later we'd better figure out how to get rid of
87 * calling lots of select() at all.
89 (void)tv;
90 r = select (fdmax + 1, &fds, NULL, NULL, /*&tv*/NULL);
92 if (-1 == r) {
93 if (EINTR == errno)
94 continue;
96 die_errno ("select");
99 if (0 == r) {
100 fprintf(stderr, "I: select timeout...\n");
101 continue;
104 if (vcap && FD_ISSET(vcap->fd, &fds))
105 if (vcap->read_frame ()) {
106 /* frame processed */
107 ; /* XXX what to do here? */
110 if (netrx && FD_ISSET(netrx->sk, &fds))
111 netrx->handle_recv();
113 /* EAGAIN - continue select loop. */
117 void usage (FILE *fp, int argc, char *argv[])
119 fprintf (fp,
121 RAWV demo (free software; comes with no warranty, but with best wishes)\n\
123 Usage: %s [options]\n\
125 Options:\n\
126 -d | --device name[,WxH][,btt?] Video device name [/dev/video]\n\
127 -v | --view[=WxH[,s]] View video stream in SDL window\n\
128 -t | --nettx dest:port Transmit video stream to dest\n\
129 -r | --netrx [group]:port Receive video stream on port\n\
130 -h | --help Print this message\n\
132 Examples:\n\
133 $ rawv -d /dev/video -v # capture + view\n\
134 $ rawv -d /dev/video -t 127.0.0.255:port # capture + send video over loopback\n\
135 $ rawv -r :port -v # receive video from network + view\n\
136 $ rawv -d /dev/video -v -t 127.0.0.255:port # capture + view + send video to network\n\
138 argv[0]);
141 const char short_options [] = "d:t:r:v::h";
143 const struct option
144 long_options [] = {
145 { "device", required_argument, NULL, 'd' },
146 { "view", optional_argument, NULL, 'v' },
147 { "nettx", required_argument, NULL, 't' },
148 { "netrx", required_argument, NULL, 'r' },
149 { "help", no_argument, NULL, 'h' },
150 { 0, 0, 0, 0 }
155 int main2 (int argc, char *argv[])
157 const char *dev_name = NULL;
158 int video_width, video_height;
159 int video_interlace_tb_swapped = 0;
160 const char *nettx_dst = NULL, *netrx_group = NULL;
161 int nettx_port = 0, netrx_port = 0;
162 int view_width, view_height;
163 bool view_upscale = 0;
164 int do_view = 0;
165 string title;
167 int i;
168 char *p, *q;
171 /* default geometry */
172 video_width = view_width = 640;
173 video_height = view_height = 480;
175 /* title */
176 title = argv[0];
177 for (i=1; i<argc; ++i) {
178 title += " ";
179 title += argv[i];
184 for (;;) {
185 int index;
186 int c;
188 c = getopt_long (argc, argv,
189 short_options, long_options,
190 &index);
192 if (-1 == c)
193 break;
195 switch (c) {
196 case 0: /* getopt_long() flag */
197 break;
199 case 'd':
200 dev_name = optarg;
201 p = strchr(optarg, ',');
202 if (p) {
203 *p = 0;
205 p += 1;
206 q = strrchr(p, 'x');
207 if (!q)
208 die("no 'x' in geometry spec (%s)", p);
210 *q = 0;
212 video_width = atoi(p);
213 video_height = atoi(q+1);
214 if (!video_width || !video_height)
215 die("can't parse video geometry (%s, %s)", p, q+1);
217 q = strchr(q+1, ',');
218 if (q && q[1]=='b' && q[2]=='t')
219 video_interlace_tb_swapped = (q[3]=='t' ? -1 : +1);
222 break;
224 case 'v':
225 do_view = 1;
227 if (optarg) {
228 p = strrchr(optarg, 'x');
229 if (!p)
230 die("no 'x' in geometry spec (%s)", optarg);
232 *p = 0;
233 view_width = atoi(optarg);
234 view_height = atoi(p+1);
235 if (!view_width || !view_height)
236 die("can't parse view geometry (%s, %s)", optarg, p+1);
238 p = strrchr(p+1, ',');
239 if (p && p[1]=='s')
240 view_upscale = 1;
243 break;
245 case 't':
246 p = strrchr(optarg, ':');
247 if (!p)
248 die("no colon in tx spec (%s)", optarg);
250 *p = 0;
252 nettx_dst = optarg;
253 nettx_port = atoi(p+1);
254 if (!nettx_port)
255 die("can't parse port in tx spec (%s)", p+1);
257 break;
259 case 'r':
260 p = strrchr(optarg, ':');
261 if (!p)
262 die("no colon in rx spec (%s)", optarg);
264 *p = 0;
266 if (strlen(optarg) != 0)
267 netrx_group = optarg;
268 netrx_port = atoi(p+1);
269 if (!netrx_port)
270 die("invalid port '%s'", optarg);
272 break;
274 case 'h':
275 usage (stdout, argc, argv);
276 exit (0);
279 default:
280 usage (stderr, argc, argv);
281 exit (1);
285 if (dev_name)
286 vcap = new VideoCapture(dev_name, video_width, video_height, video_interlace_tb_swapped);
288 if (netrx_port)
289 netrx = new NetRx(netrx_group, netrx_port, /* FIXME mtu = */ 7200);
291 if (do_view) {
292 view = new View(view_width, view_height, view_upscale, title.c_str());
294 if (vcap)
295 vcap ->v_subscribe(view);
296 if (netrx)
297 netrx ->v_subscribe(view);
300 if (nettx_dst) {
301 nettx = new NetTx(nettx_dst, nettx_port, /* FIXME mtu = */ 7200);
303 if (vcap)
304 vcap ->v_subscribe(nettx);
305 if (netrx)
306 netrx ->v_subscribe(nettx);
309 if (vcap)
310 vcap->v_start_capture();
311 // --//-- for netrx
313 if (!vcap && !netrx && !view && !nettx)
314 die("E: what should I do?");
316 mainloop ();
318 // --//-- for netrx
319 if (vcap)
320 vcap->v_stop_capture();
323 if (netrx)
324 delete netrx;
325 if (nettx)
326 delete nettx;
327 if (view)
328 delete view;
329 if (vcap)
330 delete vcap;
332 return 0;
336 int main(int argc, char *argv[])
338 try {
339 return main2(argc, argv);
341 catch (const RawvError &e) {
342 fprintf(stderr, "%s\n", e.what());
343 return 1;