Mercurial > vloopback
comparison example/resize.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 /* resize.c | |
2 * | |
3 * Example program for videoloopback device. | |
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 <linux/videodev.h> | |
22 | |
23 | |
24 int fmt=0; | |
25 int noexit = 1; | |
26 int read_img=0; | |
27 | |
28 char *start_capture (int dev, int width, int height) | |
29 { | |
30 struct video_capability vid_caps; | |
31 struct video_window vid_win; | |
32 struct video_mbuf vid_buf; | |
33 char *map; | |
34 | |
35 if (ioctl (dev, VIDIOCGCAP, &vid_caps) == -1) { | |
36 printf ("ioctl (VIDIOCGCAP)\nError[%s]\n",strerror(errno)); | |
37 return (NULL); | |
38 } | |
39 if (vid_caps.type & VID_TYPE_MONOCHROME) fmt=VIDEO_PALETTE_GREY; | |
40 if (ioctl (dev, VIDIOCGMBUF, &vid_buf) == -1) { | |
41 fprintf(stderr, "no mmap falling back on read\n"); | |
42 if (ioctl (dev, VIDIOCGWIN, &vid_win)== -1) { | |
43 printf ("ioctl VIDIOCGWIN\nError[%s]\n",strerror(errno)); | |
44 return (NULL); | |
45 } | |
46 vid_win.width=width; | |
47 vid_win.height=height; | |
48 if (ioctl (dev, VIDIOCSWIN, &vid_win)== -1) { | |
49 printf ("ioctl VIDIOCSWIN\nError[%s]\n",strerror(errno)); | |
50 return (NULL); | |
51 } | |
52 read_img=1; | |
53 map=malloc(width*height*3); | |
54 return (map); | |
55 } | |
56 /* If we are going to capture greyscale we need room to blow the image up */ | |
57 if (fmt==VIDEO_PALETTE_GREY) | |
58 map=mmap(0, vid_buf.size*3, PROT_READ|PROT_WRITE, MAP_SHARED, dev, 0); | |
59 else | |
60 map=mmap(0, vid_buf.size, PROT_READ|PROT_WRITE, MAP_SHARED, dev, 0); | |
61 | |
62 if ((unsigned char *)-1 == (unsigned char *)map) | |
63 return (NULL); | |
64 return map; | |
65 } | |
66 | |
67 int start_pipe (int dev, int width, int height) | |
68 { | |
69 struct video_capability vid_caps; | |
70 struct video_window vid_win; | |
71 struct video_picture vid_pic; | |
72 | |
73 if (ioctl (dev, VIDIOCGCAP, &vid_caps) == -1) { | |
74 printf ("ioctl (VIDIOCGCAP)\nError[%s]\n",strerror(errno)); | |
75 return (1); | |
76 } | |
77 if (ioctl (dev, VIDIOCGPICT, &vid_pic)== -1) { | |
78 printf ("ioctl VIDIOCGPICT\nError[%s]\n",strerror(errno)); | |
79 return (1); | |
80 } | |
81 vid_pic.palette=fmt; | |
82 if (ioctl (dev, VIDIOCSPICT, &vid_pic)== -1) { | |
83 printf ("ioctl VIDIOCSPICT\nError[%s]\n",strerror(errno)); | |
84 return (1); | |
85 } | |
86 if (ioctl (dev, VIDIOCGWIN, &vid_win)== -1) { | |
87 printf ("ioctl VIDIOCGWIN"); | |
88 return (1); | |
89 } | |
90 vid_win.width=width; | |
91 vid_win.height=height; | |
92 if (ioctl (dev, VIDIOCSWIN, &vid_win)== -1) { | |
93 printf ("ioctl VIDIOCSWIN"); | |
94 return (1); | |
95 } | |
96 return 0; | |
97 } | |
98 | |
99 char *next_capture (int dev, char *map, int width, int height) | |
100 { | |
101 int i; | |
102 char *grey, *rgb; | |
103 struct video_mmap vid_mmap; | |
104 | |
105 sigset_t set, old; | |
106 | |
107 if (read_img) { | |
108 if (fmt==VIDEO_PALETTE_GREY) { | |
109 if (read(dev, map, width*height) != width*height) | |
110 return NULL; | |
111 } else { | |
112 if (read(dev, map, width*height*3) != width*height*3) | |
113 return NULL; | |
114 } | |
115 } else { | |
116 vid_mmap.format=fmt; | |
117 vid_mmap.frame=0; | |
118 vid_mmap.width=width; | |
119 vid_mmap.height=height; | |
120 | |
121 sigemptyset (&set); //BTTV hates signals during IOCTL | |
122 sigaddset (&set, SIGCHLD); //block SIGCHLD & SIGALRM | |
123 sigaddset (&set, SIGALRM); //for the time of ioctls | |
124 sigprocmask (SIG_BLOCK, &set, &old); | |
125 | |
126 if (ioctl(dev, VIDIOCMCAPTURE, &vid_mmap) == -1) { | |
127 sigprocmask (SIG_UNBLOCK, &old, NULL); | |
128 return (NULL); | |
129 } | |
130 if (ioctl(dev, VIDIOCSYNC, &vid_mmap) == -1) { | |
131 sigprocmask (SIG_UNBLOCK, &old, NULL); | |
132 return (NULL); | |
133 } | |
134 | |
135 sigprocmask (SIG_UNBLOCK, &old, NULL); //undo the signal blocking | |
136 } | |
137 /* Blow up a grey */ | |
138 if (fmt==VIDEO_PALETTE_GREY) { | |
139 i=width*height; | |
140 grey=map+i-1; | |
141 rgb=map+i*3; | |
142 for (; i>=0; i--, grey--) { | |
143 *(rgb--)=*grey; | |
144 *(rgb--)=*grey; | |
145 *(rgb--)=*grey; | |
146 } | |
147 } | |
148 return map; | |
149 } | |
150 | |
151 int put_image(int dev, char *image, int width, int height) | |
152 { | |
153 if (write(dev, image, width*height*3)!=width*height*3) { | |
154 printf("Error writing image to pipe!\nError[%s]\n",strerror(errno)); | |
155 return 0; | |
156 } | |
157 return 1; | |
158 } | |
159 | |
160 void sig_handler(int signo) | |
161 { | |
162 noexit = 0; | |
163 } | |
164 | |
165 int main (int argc, char **argv) | |
166 { | |
167 int x, y, devin, devout; | |
168 int width, realwidth; | |
169 int height; | |
170 int widthout, realwidthout; | |
171 int heightout; | |
172 int **newy, **newx, **line; | |
173 char *image_out, *image_new; | |
174 char palette[10]={'\0'}; | |
175 | |
176 if (argc != 6) { | |
177 printf("Usage:\n\n"); | |
178 printf("resize input output widthxheight(in) widthxheight(out) rgb24|yuv420p\n\n"); | |
179 printf("example: resize /dev/video0 /dev/video1 352x288 176x144 yuv420p\n\n"); | |
180 exit(1); | |
181 } | |
182 sscanf(argv[3], "%dx%d", &width, &height); | |
183 sscanf(argv[4], "%dx%d", &widthout, &heightout); | |
184 sscanf(argv[5], "%s", palette); | |
185 | |
186 if (!strcmp(palette,"rgb24")) fmt = VIDEO_PALETTE_RGB24; | |
187 else if (!strcmp(palette,"yuv420p")) fmt = VIDEO_PALETTE_YUV420P; | |
188 else fmt = VIDEO_PALETTE_RGB24; | |
189 | |
190 realwidth=width*3; | |
191 realwidthout=widthout*3; | |
192 | |
193 image_out=malloc(widthout*heightout*3); | |
194 line=malloc(sizeof(int*)*heightout); | |
195 newy=malloc(sizeof(int*)*heightout); | |
196 newx=malloc(sizeof(int*)*realwidthout); | |
197 for (y=0; y<heightout; y++) { | |
198 line[y]=malloc(sizeof(int)); | |
199 line[y][0]=y*realwidthout; | |
200 newy[y]=malloc(sizeof(int)); | |
201 newy[y][0]=y*height/heightout*realwidth; | |
202 } | |
203 for (x=0; x<widthout; x++) { | |
204 newx[x*3]=malloc(sizeof(int)); | |
205 newx[x*3+1]=malloc(sizeof(int)); | |
206 newx[x*3+2]=malloc(sizeof(int)); | |
207 newx[x*3][0]=x*width/widthout*3; | |
208 newx[x*3+1][0]=x*width/widthout*3+1; | |
209 newx[x*3+2][0]=x*width/widthout*3+2; | |
210 } | |
211 | |
212 devin=open (argv[1], O_RDWR); | |
213 if (devin < 0) { | |
214 printf ("Failed to open video device %s\nError[%s]\n",argv[1],strerror(errno)); | |
215 exit(1); | |
216 } | |
217 | |
218 devout=open (argv[2], O_RDWR); | |
219 if (devout < 0) { | |
220 printf ("Failed to open video device%s \nError[%s]\n",argv[2],strerror(errno)); | |
221 exit(1); | |
222 } | |
223 | |
224 image_new=start_capture (devin, width, height); | |
225 if (!image_new) { | |
226 printf("Capture error\nError[%s]\n",strerror(errno)); | |
227 exit(1); | |
228 } | |
229 | |
230 start_pipe(devout, widthout, heightout); | |
231 | |
232 signal(SIGTERM, sig_handler); | |
233 | |
234 printf("Starting video stream.\n"); | |
235 while ( (next_capture(devin, image_new, width, height)) && (noexit)) { | |
236 for (y=0; y<heightout; y++) { | |
237 for (x=0; x<realwidthout; x++) { | |
238 image_out[line[y][0]+x]= | |
239 image_new[newy[y][0]+newx[x][0]]; | |
240 } | |
241 } | |
242 if (put_image(devout, image_out, widthout, heightout)==0) | |
243 exit(1); | |
244 } | |
245 printf("You bought vaporware!\nError[%s]\n",strerror(errno)); | |
246 close (devin); | |
247 close (devout); | |
248 | |
249 for (y=0; y<heightout; y++) { | |
250 free(line[y]); | |
251 free(newy[y]); | |
252 } | |
253 for (x=0; x<widthout; x++) { | |
254 free(newx[x*3]); | |
255 free(newx[x*3+1]); | |
256 free(newx[x*3+2]); | |
257 } | |
258 | |
259 free(line); | |
260 free(newx); | |
261 free(newy); | |
262 | |
263 free(image_out); | |
264 exit(0); | |
265 } |