Mercurial > vloopback
comparison example/invert.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 /* invert.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\nError[%s]\n",strerror(errno)); | |
| 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\nError[%s]\n",strerror(errno)); | |
| 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 | |
| 161 void sig_handler(int signo) | |
| 162 { | |
| 163 noexit = 0; | |
| 164 } | |
| 165 | |
| 166 int main (int argc, char **argv) | |
| 167 { | |
| 168 int i, devin, devout; | |
| 169 int width; | |
| 170 int height; | |
| 171 char *image_out, *image_new; | |
| 172 char palette[10]={'\0'}; | |
| 173 | |
| 174 if (argc != 5) { | |
| 175 printf("Usage:\n\n"); | |
| 176 printf("invert input output widthxheight rgb24|yuv420p\n\n"); | |
| 177 printf("example: invert /dev/video0 /dev/video1 352x288 yuv420p\n\n"); | |
| 178 exit(1); | |
| 179 } | |
| 180 sscanf(argv[3], "%dx%d", &width, &height); | |
| 181 sscanf(argv[4], "%s", palette); | |
| 182 | |
| 183 if (!strcmp(palette,"rgb24")) fmt = VIDEO_PALETTE_RGB24; | |
| 184 else if (!strcmp(palette,"yuv420p")) fmt = VIDEO_PALETTE_YUV420P; | |
| 185 else fmt = VIDEO_PALETTE_RGB24; | |
| 186 | |
| 187 | |
| 188 image_out=malloc(width*height*3); | |
| 189 | |
| 190 devin=open (argv[1], O_RDWR); | |
| 191 if (devin < 0) { | |
| 192 printf("Failed to open input video device [%s]\nError:[%s]\n",argv[1],strerror(errno)); | |
| 193 exit(1); | |
| 194 } | |
| 195 | |
| 196 devout=open (argv[2], O_RDWR); | |
| 197 if (devout < 0) { | |
| 198 printf ("Failed to open output video device [%s]\nError:[%s]\n",argv[2],strerror(errno)); | |
| 199 exit(1); | |
| 200 } | |
| 201 | |
| 202 image_new=start_capture (devin, width, height); | |
| 203 if (!image_new) { | |
| 204 printf("Capture error \n Error[%s]\n",strerror(errno)); | |
| 205 exit(1); | |
| 206 } | |
| 207 | |
| 208 start_pipe(devout, width, height); | |
| 209 | |
| 210 signal(SIGTERM, sig_handler); | |
| 211 | |
| 212 printf("Starting video stream.\n"); | |
| 213 while ( (next_capture(devin, image_new, width, height)) && (noexit) ){ | |
| 214 for (i=width*height*3; i>=0; i--) image_out[i]=-image_new[i]; | |
| 215 if (put_image(devout, image_out, width, height)==0) | |
| 216 exit(1); | |
| 217 } | |
| 218 printf("You bought vaporware!\nError[%s]\n",strerror(errno)); | |
| 219 close (devin); | |
| 220 close (devout); | |
| 221 free(image_out); | |
| 222 exit(0); | |
| 223 } |
