comparison example/dummy.c @ 0:5f21a4dddc0c

Initial checkin
author KennethLavrsen
date Sun, 01 Apr 2007 05:22:43 +0000
parents
children 2fce9e157b8d
comparison
equal deleted inserted replaced
-1:000000000000 0:5f21a4dddc0c
1 /* dummy.c
2 *
3 * Example program for using a videoloopback device in zero-copy mode.
4 * Copyright 2000 by Jeroen Vreeken (pe1rxq@amsat.org)
5 * Copyright 2005 by Angel Carpintero (ack@telefonica.net)
6 * This software is distributed under the GNU public license version 2
7 * See also the file 'COPYING'.
8 *
9 */
10
11 #include <unistd.h>
12 #include <stdlib.h>
13 #include <stdio.h>
14 #include <fcntl.h>
15 #include <string.h>
16 #include <errno.h>
17 #include <sys/ioctl.h>
18 #include <sys/mman.h>
19 #include <signal.h>
20 #include <sys/wait.h>
21 #include <sys/poll.h>
22 #include <dirent.h>
23 #include <sys/utsname.h>
24 #include <linux/videodev.h>
25
26 /* all seem reasonable, or not? */
27 #define MAXIOCTL 1024
28 #define MAXWIDTH 640
29 #define MAXHEIGHT 480
30 int width;
31 int height;
32 int fmt=0;
33 char ioctlbuf[MAXIOCTL];
34 int v4ldev;
35 char *image_out;
36
37
38 int get_frame(void)
39 {
40 int i;
41 char colour = 0;
42
43 memset(image_out, 0x128, width*height*3);
44
45 for (i=10; i<width-10; i++) {
46 image_out[10*width*3+i*3]=colour++;
47 image_out[10*width*3+i*3+1]=0;
48 image_out[10*width*3+i*3+2]=-colour;
49 }
50 for (i=10; i<width-10; i++) {
51 image_out[(height-10)*width*3+i*3]=colour;
52 image_out[(height-10)*width*3+i*3+1]=0;
53 image_out[(height-10)*width*3+i*3+2]=-colour++;
54 }
55 /*
56 */
57 usleep(500); /* BIG XXX */
58 return 0;
59 }
60
61 char *v4l_create (int dev, int memsize)
62 {
63 char *map;
64
65 map=mmap(0, memsize, PROT_READ|PROT_WRITE, MAP_SHARED, dev, 0);
66 if ((unsigned char *)-1 == (unsigned char *)map)
67 return NULL;
68 return map;
69 }
70
71 int v4l_ioctl(unsigned long int cmd, void *arg)
72 {
73 int i;
74 switch (cmd) {
75 case VIDIOCGCAP:
76 {
77 struct video_capability *vidcap=arg;
78
79 sprintf(vidcap->name, "Jeroen's dummy v4l driver");
80 vidcap->type= VID_TYPE_CAPTURE;
81 vidcap->channels=1;
82 vidcap->audios=0;
83 vidcap->maxwidth=MAXWIDTH;
84 vidcap->maxheight=MAXHEIGHT;
85 vidcap->minwidth=20;
86 vidcap->minheight=20;
87 return 0;
88 }
89 case VIDIOCGCHAN:
90 {
91 struct video_channel *vidchan= (struct video_channel *)arg;
92
93 printf("VIDIOCGCHAN called\n");
94 if (vidchan->channel!=0)
95 ;//return 1;
96 vidchan->channel=0;
97 vidchan->flags=0;
98 vidchan->tuners=0;
99 vidchan->norm=0;
100 vidchan->type=VIDEO_TYPE_CAMERA;
101 strcpy(vidchan->name, "Loopback");
102
103 return 0;
104 }
105 case VIDIOCSCHAN:
106 {
107 int *v=arg;
108
109 if (v[0]!=0)
110 return 1;
111 return 0;
112 }
113 case VIDIOCGTUNER:
114 {
115 struct video_tuner *v = arg;
116
117 if(v->tuner) {
118 printf("VIDIOCGTUNER: Invalid Tuner, was %d\n", v->tuner);
119 //return -EINVAL;
120 }
121 v->tuner=0;
122 strcpy(v->name, "Format");
123 v->rangelow=0;
124 v->rangehigh=0;
125 v->flags=0;
126 v->mode=VIDEO_MODE_AUTO;
127 return 1;
128 }
129 case VIDIOCGPICT:
130 {
131 struct video_picture *vidpic=arg;
132
133 vidpic->colour=0x8000;
134 vidpic->hue=0x8000;
135 vidpic->brightness=0x8000;
136 vidpic->contrast=0x8000;
137 vidpic->whiteness=0x8000;
138 vidpic->depth=0x8000;
139 vidpic->palette=fmt;
140 return 0;
141 }
142 case VIDIOCSPICT:
143 {
144 struct video_picture *vidpic=arg;
145
146 if (vidpic->palette!=fmt)
147 return 1;
148 return 0;
149 }
150 case VIDIOCGWIN:
151 {
152 struct video_window *vidwin=arg;
153
154 vidwin->x=0;
155 vidwin->y=0;
156 vidwin->width=width;
157 vidwin->height=height;
158 vidwin->chromakey=0;
159 vidwin->flags=0;
160 vidwin->clipcount=0;
161 return 0;
162 }
163 case VIDIOCSWIN:
164 {
165 struct video_window *vidwin=arg;
166
167 if (vidwin->width > MAXWIDTH ||
168 vidwin->height > MAXHEIGHT )
169 return 1;
170 if (vidwin->flags)
171 return 1;
172 width=vidwin->width;
173 height=vidwin->height;
174 printf("new size: %dx%d\n", width, height);
175 return 0;
176 }
177 case VIDIOCGMBUF:
178 {
179 struct video_mbuf *vidmbuf=arg;
180
181 vidmbuf->size=width*height*3;
182 vidmbuf->frames=1;
183 for (i=0; i<vidmbuf->frames; i++)
184 vidmbuf->offsets[i]=i*vidmbuf->size;
185 return 0;
186 }
187 case VIDIOCMCAPTURE:
188 {
189 struct video_mmap *vidmmap=arg;
190
191 //return 0;
192 if (vidmmap->height>MAXHEIGHT ||
193 vidmmap->width>MAXWIDTH ||
194 vidmmap->format!=fmt )
195 return 1;
196 if (vidmmap->height!=height ||
197 vidmmap->width!=width) {
198 height=vidmmap->height;
199 width=vidmmap->width;
200 printf("new size: %dx%d\n", width, height);
201 }
202 // check if 'vidmmap->frame' is valid
203 // initiate capture for 'vidmmap->frame' frames
204 return 0;
205 }
206 case VIDIOCSYNC:
207 {
208 //struct video_mmap *vidmmap=arg;
209
210 // check if frames are ready.
211 // wait until ready.
212 get_frame();
213 return 0;
214 }
215 default:
216 {
217 printf("unknown ioctl: %ld\n", cmd & 0xff);
218 return 1;
219 }
220 }
221 return 0;
222 }
223
224 #define VIDIOCSINVALID _IO('v',BASE_VIDIOCPRIVATE+1)
225
226 void sighandler(int signo)
227 {
228 int size, ret;
229 unsigned long int cmd;
230 struct pollfd ufds;
231
232 if (signo!=SIGIO)
233 return;
234 ufds.fd=v4ldev;
235 ufds.events=POLLIN;
236 ufds.revents=0;
237 poll(&ufds, 1, 1000);
238 if (!ufds.revents & POLLIN) {
239 printf("Received signal but got negative on poll?!?!?!?\n");
240 return;
241 }
242 size=read(v4ldev, ioctlbuf, MAXIOCTL);
243 if (size >= sizeof(unsigned long int)) {
244 memcpy(&cmd, ioctlbuf, sizeof(unsigned long int));
245 if (cmd==0) {
246 printf("Client closed device\n");
247 return;
248 }
249 ret=v4l_ioctl(cmd, ioctlbuf+sizeof(unsigned long int));
250 if (ret) {
251 memset(ioctlbuf+sizeof(unsigned long int), MAXIOCTL-sizeof(unsigned long int), 0xff);
252 printf("ioctl %lx unsuccesfull, lets issue VIDIOCSINVALID (%x)\n", cmd, VIDIOCSINVALID);
253 ioctl(v4ldev, VIDIOCSINVALID);
254 } else
255 ioctl(v4ldev, cmd, ioctlbuf+sizeof(unsigned long int));
256 }
257 return;
258 }
259
260 int open_vidpipe(void)
261 {
262 int pipe_fd = -1;
263 FILE *vloopbacks;
264 char pipepath[255];
265 char buffer[255];
266 char *loop;
267 char *input;
268 char *istatus;
269 char *output;
270 char *ostatus;
271 char *major;
272 char *minor;
273 struct utsname uts;
274
275 if (uname(&uts) < 0) {
276 printf("Unable to execute uname\nError[%s]\n",strerror(errno));
277 return -1;
278 }
279
280 major = strtok(uts.release, ".");
281 minor = strtok(NULL, ".");
282 if ((major == NULL) || (minor == NULL) || (strcmp(major, "2"))) {
283 printf("Unable to decipher OS version\n");
284 return -1;
285 }
286
287 if (strcmp(minor, "5") < 0) {
288
289 vloopbacks=fopen("/proc/video/vloopback/vloopbacks", "r");
290 if (!vloopbacks) {
291 printf ("Failed to open '/proc/video/vloopback/vloopbacks");
292 return -1;
293 }
294 /* Read vloopback version */
295 fgets(buffer, 255, vloopbacks);
296 printf("%s", buffer);
297 /* Read explaination line */
298 fgets(buffer, 255, vloopbacks);
299 while (fgets(buffer, 255, vloopbacks)) {
300 if (strlen(buffer)>1) {
301 buffer[strlen(buffer)-1]=0;
302 loop=strtok(buffer, "\t");
303 input=strtok(NULL, "\t");
304 istatus=strtok(NULL, "\t");
305 output=strtok(NULL, "\t");
306 ostatus=strtok(NULL, "\t");
307 if (istatus[0]=='-') {
308 sprintf(pipepath, "/dev/%s", input);
309 pipe_fd=open(pipepath, O_RDWR);
310 if (pipe_fd>=0) {
311 printf("Input: /dev/%s\n", input);
312 printf("Output: /dev/%s\n", output);
313 return pipe_fd;
314 }
315 }
316 }
317 }
318
319 }else{
320 DIR *dir;
321 struct dirent *dirp;
322 const char prefix[]="/sys/class/video4linux/";
323 char *ptr, *io;
324 int fd;
325 int low=9999;
326 int tfd;
327 int tnum;
328
329 if ((dir=opendir(prefix))== NULL) {
330 printf( "Failed to open '%s'", prefix);
331 return -1;
332 }
333
334 while ((dirp=readdir(dir)) != NULL) {
335 if (!strncmp(dirp->d_name, "video", 5)) {
336 strcpy(buffer, prefix);
337 strcat(buffer, dirp->d_name);
338 strcat(buffer, "/name");
339 if ((fd=open(buffer, O_RDONLY)) >= 0) {
340 if ((read(fd, buffer, sizeof(buffer)-1))<0) {
341 close(fd);
342 continue;
343 }
344 ptr = strtok(buffer, " ");
345 if (strcmp(ptr,"Video")) {
346 close(fd);
347 continue;
348 }
349 major = strtok(NULL, " ");
350 minor = strtok(NULL, " ");
351 io = strtok(NULL, " \n");
352 if (strcmp(major, "loopback") || strcmp(io, "input")) {
353 close(fd);
354 continue;
355 }
356 if ((ptr=strtok(buffer, " "))==NULL) {
357 close(fd);
358 continue;
359 }
360 tnum = atoi(minor);
361 if (tnum < low) {
362 strcpy(buffer, "/dev/");
363 strcat(buffer, dirp->d_name);
364 if ((tfd=open(buffer, O_RDWR))>=0) {
365 strcpy(pipepath, buffer);
366 if (pipe_fd>=0) {
367 close(pipe_fd);
368 }
369 pipe_fd = tfd;
370 low = tnum;
371 }
372 }
373 close(fd);
374 }
375 }
376 }
377
378
379 closedir(dir);
380 if (pipe_fd >= 0)
381 printf("Opened input of %s", pipepath);
382 }
383
384 return pipe_fd;
385 }
386
387 int main (int argc, char **argv)
388 {
389 char palette[10]={'\0'};
390
391 if (argc != 3) {
392 printf("dummy.c\n");
393 printf("A example for using a video4linux loopback in zero-copy mode\n");
394 printf("Written by Jeroen Vreeken, 2000\n");
395 printf("Updated to vloopback API v0.97\n\n");
396 printf("Usage:\n\n");
397 printf("dummy widthxheight rgb24|yuv420p\n\n");
398 printf("example: dummy 352x288 yuv420p\n\n");
399 exit(1);
400 }
401
402 sscanf(argv[1], "%dx%d", &width, &height);
403 sscanf(argv[2], "%s", palette);
404
405 if (!strcmp(palette,"rgb24")) fmt = VIDEO_PALETTE_RGB24;
406 else if (!strcmp(palette,"yuv420p")) fmt = VIDEO_PALETTE_YUV420P;
407 else fmt = VIDEO_PALETTE_RGB24;
408
409 /* Default startup values, nothing special
410 width=352;
411 height=288;
412 */
413
414 v4ldev=open_vidpipe();
415 if (v4ldev < 0) {
416 printf ("Failed to open video loopback device\nError[%s]\n",strerror(errno));
417 exit(1);
418 }
419 image_out=v4l_create(v4ldev, MAXWIDTH*MAXHEIGHT*3);
420 if (!image_out) {
421 exit(1);
422 printf ("Failed to set device to zero-copy mode\nError[%s]\n",strerror(errno));
423 }
424
425 signal (SIGIO, sighandler);
426
427 printf("\nListening.\n");
428 while (1) {
429 sleep(1000);
430 }
431
432 close (v4ldev);
433 free(image_out);
434 exit(0);
435 }