Mercurial > vloopback
comparison example/feed.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 /* feed.c | |
2 * | |
3 * Example program for videoloopback device. | |
4 * Copyright 2006 by Angel Carpintero (ack@telefonica.net) | |
5 * This software is distributed under the GNU public license version 2 | |
6 * See also the file 'COPYING'. | |
7 * | |
8 */ | |
9 | |
10 #include <unistd.h> | |
11 #include <stdlib.h> | |
12 #include <stdio.h> | |
13 #include <fcntl.h> | |
14 #include <string.h> | |
15 #include <errno.h> | |
16 #include <sys/ioctl.h> | |
17 #include <sys/mman.h> | |
18 #include <signal.h> | |
19 #include <sys/wait.h> | |
20 #include <linux/videodev.h> | |
21 | |
22 | |
23 int fmt=0; | |
24 int noexit = 1; | |
25 int read_img=0; | |
26 | |
27 char *start_capture (int dev, int width, int height) | |
28 { | |
29 struct video_capability vid_caps; | |
30 struct video_window vid_win; | |
31 struct video_mbuf vid_buf; | |
32 char *map; | |
33 | |
34 if (ioctl (dev, VIDIOCGCAP, &vid_caps) == -1) { | |
35 printf ("ioctl (VIDIOCGCAP)\nError[%s]\n",strerror(errno)); | |
36 return (NULL); | |
37 } | |
38 if (vid_caps.type & VID_TYPE_MONOCHROME) fmt=VIDEO_PALETTE_GREY; | |
39 if (ioctl (dev, VIDIOCGMBUF, &vid_buf) == -1) { | |
40 fprintf(stderr, "no mmap falling back on read\n"); | |
41 if (ioctl (dev, VIDIOCGWIN, &vid_win)== -1) { | |
42 printf ("ioctl VIDIOCGWIN\nError[%s]\n",strerror(errno)); | |
43 return (NULL); | |
44 } | |
45 vid_win.width=width; | |
46 vid_win.height=height; | |
47 if (ioctl (dev, VIDIOCSWIN, &vid_win)== -1) { | |
48 printf ("ioctl VIDIOCSWIN\nError[%s]\n",strerror(errno)); | |
49 return (NULL); | |
50 } | |
51 read_img=1; | |
52 map=malloc(width*height*3); | |
53 return (map); | |
54 } | |
55 /* If we are going to capture greyscale we need room to blow the image up */ | |
56 if (fmt==VIDEO_PALETTE_GREY) | |
57 map=mmap(0, vid_buf.size*3, PROT_READ|PROT_WRITE, MAP_SHARED, dev, 0); | |
58 else | |
59 map=mmap(0, vid_buf.size, PROT_READ|PROT_WRITE, MAP_SHARED, dev, 0); | |
60 | |
61 if ((unsigned char *)-1 == (unsigned char *)map) | |
62 return (NULL); | |
63 return map; | |
64 } | |
65 | |
66 int start_pipe (int dev, int width, int height) | |
67 { | |
68 struct video_capability vid_caps; | |
69 struct video_window vid_win; | |
70 struct video_picture vid_pic; | |
71 | |
72 if (ioctl (dev, VIDIOCGCAP, &vid_caps) == -1) { | |
73 printf ("ioctl (VIDIOCGCAP)\nError[%s]\n",strerror(errno)); | |
74 return (1); | |
75 } | |
76 if (ioctl (dev, VIDIOCGPICT, &vid_pic)== -1) { | |
77 printf ("ioctl VIDIOCGPICT\nError[%s]\n",strerror(errno)); | |
78 return (1); | |
79 } | |
80 vid_pic.palette=fmt; | |
81 if (ioctl (dev, VIDIOCSPICT, &vid_pic)== -1) { | |
82 printf ("ioctl VIDIOCSPICT\nError[%s]\n",strerror(errno)); | |
83 return (1); | |
84 } | |
85 if (ioctl (dev, VIDIOCGWIN, &vid_win)== -1) { | |
86 printf ("ioctl VIDIOCGWIN"); | |
87 return (1); | |
88 } | |
89 vid_win.width=width; | |
90 vid_win.height=height; | |
91 if (ioctl (dev, VIDIOCSWIN, &vid_win)== -1) { | |
92 printf ("ioctl VIDIOCSWIN"); | |
93 return (1); | |
94 } | |
95 return 0; | |
96 } | |
97 | |
98 char *next_capture (int dev, char *map, int width, int height) | |
99 { | |
100 int i; | |
101 char *grey, *rgb; | |
102 struct video_mmap vid_mmap; | |
103 | |
104 sigset_t set, old; | |
105 | |
106 if (read_img) { | |
107 if (fmt==VIDEO_PALETTE_GREY) { | |
108 if (read(dev, map, width*height) != width*height) | |
109 return NULL; | |
110 } else { | |
111 if (read(dev, map, width*height*3) != width*height*3) | |
112 return NULL; | |
113 } | |
114 } else { | |
115 vid_mmap.format=fmt; | |
116 vid_mmap.frame=0; | |
117 vid_mmap.width=width; | |
118 vid_mmap.height=height; | |
119 | |
120 sigemptyset (&set); //BTTV hates signals during IOCTL | |
121 sigaddset (&set, SIGCHLD); //block SIGCHLD & SIGALRM | |
122 sigaddset (&set, SIGALRM); //for the time of ioctls | |
123 sigprocmask (SIG_BLOCK, &set, &old); | |
124 | |
125 if (ioctl(dev, VIDIOCMCAPTURE, &vid_mmap) == -1) { | |
126 sigprocmask (SIG_UNBLOCK, &old, NULL); | |
127 return (NULL); | |
128 } | |
129 if (ioctl(dev, VIDIOCSYNC, &vid_mmap) == -1) { | |
130 sigprocmask (SIG_UNBLOCK, &old, NULL); | |
131 return (NULL); | |
132 } | |
133 | |
134 sigprocmask (SIG_UNBLOCK, &old, NULL); //undo the signal blocking | |
135 } | |
136 /* Blow up a grey */ | |
137 if (fmt==VIDEO_PALETTE_GREY) { | |
138 i=width*height; | |
139 grey=map+i-1; | |
140 rgb=map+i*3; | |
141 for (; i>=0; i--, grey--) { | |
142 *(rgb--)=*grey; | |
143 *(rgb--)=*grey; | |
144 *(rgb--)=*grey; | |
145 } | |
146 } | |
147 return map; | |
148 } | |
149 | |
150 int put_image(int dev, char *image, int width, int height) | |
151 { | |
152 if (write(dev, image, width*height*3)!=width*height*3) { | |
153 printf("Error writing image to pipe!\nError[%s]\n",strerror(errno)); | |
154 return 0; | |
155 } | |
156 return 1; | |
157 } | |
158 | |
159 void sig_handler(int signo) | |
160 { | |
161 noexit = 0; | |
162 } | |
163 | |
164 | |
165 int main (int argc, char **argv) | |
166 { | |
167 int devin, devout; | |
168 int width; | |
169 int height; | |
170 char *image_new; | |
171 char palette[10]={'\0'}; | |
172 | |
173 if (argc != 5) { | |
174 printf("Usage:\n\n"); | |
175 printf("feed input output widthxheight(in) rgb24|yuv420p\n\n"); | |
176 printf("example: feed /dev/video0 /dev/video1 352x288 yuv420p\n\n"); | |
177 exit(1); | |
178 } | |
179 sscanf(argv[3], "%dx%d", &width, &height); | |
180 sscanf(argv[4], "%s", palette); | |
181 | |
182 if (!strcmp(palette,"rgb24")) fmt = VIDEO_PALETTE_RGB24; | |
183 else if (!strcmp(palette,"yuv420p")) fmt = VIDEO_PALETTE_YUV420P; | |
184 else fmt = VIDEO_PALETTE_RGB24; | |
185 | |
186 devin=open (argv[1], O_RDWR); | |
187 if (devin < 0) { | |
188 printf ("Failed to open video device %s\nError[%s]\n",argv[1],strerror(errno)); | |
189 exit(1); | |
190 } | |
191 | |
192 devout=open (argv[2], O_RDWR); | |
193 if (devout < 0) { | |
194 printf ("Failed to open video device%s \nError[%s]\n",argv[2],strerror(errno)); | |
195 exit(1); | |
196 } | |
197 | |
198 image_new=start_capture (devin, width, height); | |
199 if (!image_new) { | |
200 printf("Capture error\nError[%s]\n",strerror(errno)); | |
201 exit(1); | |
202 } | |
203 | |
204 start_pipe(devout, width, height); | |
205 | |
206 signal(SIGTERM, sig_handler); | |
207 | |
208 printf("Starting video stream.\n"); | |
209 while ( (next_capture(devin, image_new, width, height)) && (noexit)) { | |
210 if (put_image(devout, image_new, width, height)==0) | |
211 exit(1); | |
212 } | |
213 printf("You bought vaporware!\nError[%s]\n",strerror(errno)); | |
214 close (devin); | |
215 close (devout); | |
216 exit(0); | |
217 } |