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 }