Mercurial > vloopback
view example/resize.c @ 8:80590d10a596
Added num of buffers as a module param, indent code using spaces instead of tabs
author | AngelCarpintero |
---|---|
date | Tue, 26 Aug 2008 11:50:37 +0000 |
parents | 2fce9e157b8d |
children |
line wrap: on
line source
/* resize.c * * Example program for videoloopback device. * Copyright 2000 by Jeroen Vreeken (pe1rxq@amsat.org) * Copyright 2005 by Angel Carpintero (ack@telefonica.net) * This software is distributed under the GNU public license version 2 * See also the file 'COPYING'. * */ #include <unistd.h> #include <stdlib.h> #include <stdio.h> #include <fcntl.h> #include <string.h> #include <errno.h> #include <sys/ioctl.h> #include <sys/mman.h> #include <signal.h> #include <sys/wait.h> #include <linux/videodev.h> int fmt = 0; int noexit = 1; int read_img = 0; char *start_capture (int dev, int width, int height) { struct video_capability vid_caps; struct video_window vid_win; struct video_mbuf vid_buf; char *map; if (ioctl(dev, VIDIOCGCAP, &vid_caps) == -1) { printf ("ioctl (VIDIOCGCAP)\nError[%s]\n", strerror(errno)); return (NULL); } if (vid_caps.type & VID_TYPE_MONOCHROME) fmt = VIDEO_PALETTE_GREY; if (ioctl(dev, VIDIOCGMBUF, &vid_buf) == -1) { fprintf(stderr, "no mmap falling back on read\n"); if (ioctl(dev, VIDIOCGWIN, &vid_win)== -1) { printf ("ioctl VIDIOCGWIN\nError[%s]\n", strerror(errno)); return (NULL); } vid_win.width = width; vid_win.height = height; if (ioctl(dev, VIDIOCSWIN, &vid_win)== -1) { printf ("ioctl VIDIOCSWIN\nError[%s]\n", strerror(errno)); return (NULL); } read_img = 1; map = malloc(width * height * 3); return (map); } /* If we are going to capture greyscale we need room to blow the image up */ if (fmt == VIDEO_PALETTE_GREY) map=mmap(0, vid_buf.size * 3, PROT_READ|PROT_WRITE, MAP_SHARED, dev, 0); else map=mmap(0, vid_buf.size, PROT_READ|PROT_WRITE, MAP_SHARED, dev, 0); if ((unsigned char *)-1 == (unsigned char *)map) return (NULL); return map; } int start_pipe (int dev, int width, int height) { struct video_capability vid_caps; struct video_window vid_win; struct video_picture vid_pic; if (ioctl(dev, VIDIOCGCAP, &vid_caps) == -1) { printf ("ioctl (VIDIOCGCAP)\nError[%s]\n", strerror(errno)); return (1); } if (ioctl(dev, VIDIOCGPICT, &vid_pic) == -1) { printf ("ioctl VIDIOCGPICT\nError[%s]\n", strerror(errno)); return (1); } vid_pic.palette = fmt; if (ioctl(dev, VIDIOCSPICT, &vid_pic) == -1) { printf ("ioctl VIDIOCSPICT\nError[%s]\n", strerror(errno)); return (1); } if (ioctl(dev, VIDIOCGWIN, &vid_win) == -1) { printf ("ioctl VIDIOCGWIN"); return (1); } vid_win.width = width; vid_win.height = height; if (ioctl(dev, VIDIOCSWIN, &vid_win)== -1) { printf ("ioctl VIDIOCSWIN"); return (1); } return 0; } char *next_capture (int dev, char *map, int width, int height) { int i; char *grey, *rgb; struct video_mmap vid_mmap; sigset_t set, old; if (read_img) { if (fmt == VIDEO_PALETTE_GREY) { size_t size = width * height; if (read(dev, map, size) != size) return NULL; } else { size_t size = width * height * 3; if (read(dev, map, size) != size) return NULL; } } else { vid_mmap.format = fmt; vid_mmap.frame = 0; vid_mmap.width = width; vid_mmap.height = height; sigemptyset (&set); //BTTV hates signals during IOCTL sigaddset (&set, SIGCHLD); //block SIGCHLD & SIGALRM sigaddset (&set, SIGALRM); //for the time of ioctls sigprocmask (SIG_BLOCK, &set, &old); if (ioctl(dev, VIDIOCMCAPTURE, &vid_mmap) == -1) { sigprocmask (SIG_UNBLOCK, &old, NULL); return (NULL); } if (ioctl(dev, VIDIOCSYNC, &vid_mmap) == -1) { sigprocmask (SIG_UNBLOCK, &old, NULL); return (NULL); } sigprocmask(SIG_UNBLOCK, &old, NULL); //undo the signal blocking } /* Blow up a grey */ if (fmt == VIDEO_PALETTE_GREY) { i = width * height; grey = map + i - 1; rgb = map + i * 3; for (; i >= 0; i--, grey--) { *(rgb--) =*grey; *(rgb--) =*grey; *(rgb--) =*grey; } } return map; } int put_image(int dev, char *image, int width, int height) { if (write(dev, image, width * height * 3) != width * height * 3) { printf("Error writing image to pipe!\nError[%s]\n", strerror(errno)); return 0; } return 1; } void sig_handler(int signo) { noexit = 0; } int main (int argc, char **argv) { int x, y, devin, devout; int width, realwidth; int height; int widthout, realwidthout; int heightout; int **newy, **newx, **line; char *image_out, *image_new; char palette[10] = {'\0'}; if (argc != 6) { printf("Usage:\n\n"); printf("resize input output widthxheight(in) widthxheight(out) rgb24|yuv420p\n\n"); printf("example: resize /dev/video0 /dev/video1 352x288 176x144 yuv420p\n\n"); exit(1); } sscanf(argv[3], "%dx%d", &width, &height); sscanf(argv[4], "%dx%d", &widthout, &heightout); sscanf(argv[5], "%s", palette); if (!strcmp(palette,"rgb24")) fmt = VIDEO_PALETTE_RGB24; else if (!strcmp(palette,"yuv420p")) fmt = VIDEO_PALETTE_YUV420P; else fmt = VIDEO_PALETTE_RGB24; realwidth = width * 3; realwidthout = widthout * 3; image_out = malloc(widthout * heightout * 3); line = malloc(sizeof(int*) * heightout); newy = malloc(sizeof(int*) * heightout); newx = malloc(sizeof(int*) * realwidthout); for (y = 0; y < heightout; y++) { line[y] = malloc(sizeof(int)); line[y][0] = y * realwidthout; newy[y] = malloc(sizeof(int)); newy[y][0] = y * height / heightout * realwidth; } for (x = 0; x < widthout; x++) { newx[x *3] = malloc(sizeof(int)); newx[x *3 + 1] = malloc(sizeof(int)); newx[x *3 + 2] = malloc(sizeof(int)); newx[x *3][0] = x * width / widthout * 3; newx[x *3 + 1][0] = x * width / widthout * 3 + 1; newx[x * 3 + 2][0] = x * width / widthout * 3 + 2; } devin = open(argv[1], O_RDWR); if (devin < 0) { printf ("Failed to open video device %s\nError[%s]\n", argv[1], strerror(errno)); exit(1); } devout = open(argv[2], O_RDWR); if (devout < 0) { printf ("Failed to open video device%s \nError[%s]\n", argv[2], strerror(errno)); exit(1); } image_new=start_capture (devin, width, height); if (!image_new) { printf("Capture error\nError[%s]\n", strerror(errno)); exit(1); } start_pipe(devout, widthout, heightout); signal(SIGTERM, sig_handler); printf("Starting video stream.\n"); while ((next_capture(devin, image_new, width, height)) && (noexit)) { for (y = 0; y < heightout; y++) { for (x = 0; x < realwidthout; x++) image_out[line[y][0] + x] = image_new[newy[y][0] + newx[x][0]]; } if (put_image(devout, image_out, widthout, heightout) == 0) exit(1); } printf("You bought vaporware!\nError[%s]\n", strerror(errno)); close(devin); close(devout); for (y = 0; y < heightout; y++) { free(line[y]); free(newy[y]); } for (x = 0; x < widthout; x++) { free(newx[x * 3]); free(newx[x * 3 + 1]); free(newx[x * 3 + 2]); } free(line); free(newx); free(newy); free(image_out); exit(0); }