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 }