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.
29 #include <getopt.h> /* getopt_long() */
49 VideoCapture
*vcap
= NULL
;
55 /****************************************/
68 FD_SET (vcap
->fd
, &fds
);
69 fdmax
= max(fdmax
, vcap
->fd
);
73 FD_SET (netrx
->sk
, &fds
);
74 fdmax
= max(fdmax
, netrx
->sk
);
82 /* WARNING: select() with timeout under load is very expensive - for
83 * almost every packet the timer will be set up which costs significant
86 * Avoid that, but TODO later we'd better figure out how to get rid of
87 * calling lots of select() at all.
90 r
= select (fdmax
+ 1, &fds
, NULL
, NULL
, /*&tv*/NULL
);
100 fprintf(stderr
, "I: select timeout...\n");
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
[])
121 RAWV demo (free software; comes with no warranty, but with best wishes)\n\
123 Usage: %s [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\
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\
141 const char short_options
[] = "d:t:r:v::h";
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' },
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;
171 /* default geometry */
172 video_width
= view_width
= 640;
173 video_height
= view_height
= 480;
177 for (i
=1; i
<argc
; ++i
) {
188 c
= getopt_long (argc
, argv
,
189 short_options
, long_options
,
196 case 0: /* getopt_long() flag */
201 p
= strchr(optarg
, ',');
208 die("no 'x' in geometry spec (%s)", p
);
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);
228 p
= strrchr(optarg
, 'x');
230 die("no 'x' in geometry spec (%s)", optarg
);
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, ',');
246 p
= strrchr(optarg
, ':');
248 die("no colon in tx spec (%s)", optarg
);
253 nettx_port
= atoi(p
+1);
255 die("can't parse port in tx spec (%s)", p
+1);
260 p
= strrchr(optarg
, ':');
262 die("no colon in rx spec (%s)", optarg
);
266 if (strlen(optarg
) != 0)
267 netrx_group
= optarg
;
268 netrx_port
= atoi(p
+1);
270 die("invalid port '%s'", optarg
);
275 usage (stdout
, argc
, argv
);
280 usage (stderr
, argc
, argv
);
286 vcap
= new VideoCapture(dev_name
, video_width
, video_height
, video_interlace_tb_swapped
);
289 netrx
= new NetRx(netrx_group
, netrx_port
, /* FIXME mtu = */ 7200);
292 view
= new View(view_width
, view_height
, view_upscale
, title
.c_str());
295 vcap
->v_subscribe(view
);
297 netrx
->v_subscribe(view
);
301 nettx
= new NetTx(nettx_dst
, nettx_port
, /* FIXME mtu = */ 7200);
304 vcap
->v_subscribe(nettx
);
306 netrx
->v_subscribe(nettx
);
310 vcap
->v_start_capture();
313 if (!vcap
&& !netrx
&& !view
&& !nettx
)
314 die("E: what should I do?");
320 vcap
->v_stop_capture();
336 int main(int argc
, char *argv
[])
339 return main2(argc
, argv
);
341 catch (const RawvError
&e
) {
342 fprintf(stderr
, "%s\n", e
.what());