All pastes #802877 Raw Edit

cb22

public c v1 · immutable
#802877 ·published 2007-11-30 18:40 UTC
rendered paste body
/* *  vo_v4lw.c * *	Copyright (C) Tilmann Bitterberg - Nov 2001 * *  This is free software; you can redistribute it and/or modify *  it under the terms of the GNU General Public License as published by *  the Free Software Foundation; either version 2, or (at your option) *  any later version. * *  This is distributed in the hope that it will be useful, *  but WITHOUT ANY WARRANTY; without even the implied warranty of *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the *  GNU General Public License for more details. * *  You should have received a copy of the GNU General Public License *  along with GNU Make; see the file COPYING.  If not, write to *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. * *  Updated 4/27/2006 - sfranzyshen <sfranzyshen at hotmail.com> *  compiled against MPlayer-1.0pre7try2 *//*   Quick v4lw loopback howto:   - get the vloopback kernel module from     <http://motion.technolust.cx/vloopback/index.html>   or (alternative) my hacked version from     <http://tibit.org/video/vloopback-0.90-tibit.tar.gz>   - if using my version, you don't need to specify dev_offset.   - untar and compile it   tar xzf vloopback-VERSION.tar.gz && cd vloopback-VERSION   make   - load the vloopback module   insmod vloopback.o dev_offset=2 pipes=1   - Make the devices accessible   chmod og+rw /dev/v4l/video2   chmod og+rw /dev/v4l/video3   - eventually you have to recompile mplayer to let     it see that it can talk v4l.   ./configure --enable-v4lw     to be sure   - start mplayer   mplayer -vo v4lw movie.avi   - start xawtv   xawtv -c /dev/v4l/video3 -geometry 800x600   - done     easy, isn't it.   NOTES:   - avicap doesn't work yet.     I got mp1e to work with a my hacked vloopback.o,     you need to specify the exact size.   - no scaling of video output is possible right now.   - be sure to insmod vloopback with a dev_offset appropriate     for your system. If you have a real grabber card (eg. a bttv     which is at /dev/v4l/video0) you _HAVE_ to use at least a     dev_offset=1 or you'll crash your kernel.   - I am on devfs, if you're not you have to use /dev/video2     instead of /dev/v4l/video2 and may have to create the     devices manually.          Eg. for video2: mknod c 81 2 /dev/video2   - mplayer will tell you the v4lw output device from which you     have to read.   Performance:     System:  2 * 1GHz Intel PIII (Coppermine) #SMP     MPEG1 at 768x576       mplayer CPU Usage ca. 35%, xawtv 11%     Divx  at 512x384       mplayer CPU Usage ca. 20%, xawtv 10% */#include <unistd.h>#include <stdlib.h>#include <stdio.h>#include <fcntl.h>#include <string.h>#include <sys/ioctl.h>#include <sys/mman.h>#include <signal.h>#include <sys/wait.h>#include <linux/videodev.h>#include <errno.h>#include <sys/poll.h>#include <dirent.h>#include <sys/utsname.h>#include "config.h"#include "video_out.h"#include "video_out_internal.h"#include "fastmemcpy.h"#include "sub.h"#include "aspect.h"#include "mp_msg.h"static uint32_t image_width, image_height;static int devout;static uint8_t *image;static unsigned int image_format=0;static int bpp = 24;static int fmt;#define MAXIOCTL 1024#define MAXWIDTH 1280#define MAXHEIGHT 1024int width;int height;char ioctlbuf[MAXIOCTL];int v4ldev;char *image_out;int get_frame(void){        int i;        char colour = 0;        memset(image_out, 0x128, width*height*3);        for (i=10; i<width-10; i++) {                image_out[10*width*3+i*3]=colour++;                image_out[10*width*3+i*3+1]=0;                image_out[10*width*3+i*3+2]=-colour;        }        for (i=10; i<width-10; i++) {                image_out[(height-10)*width*3+i*3]=colour;                image_out[(height-10)*width*3+i*3+1]=0;                image_out[(height-10)*width*3+i*3+2]=-colour++;        }        /*        */        usleep(500); /* BIG XXX */        return 0;}	int v4l_ioctl(unsigned long int cmd, void *arg){        int i;        switch (cmd) {                case VIDIOCGCAP:                {                        struct video_capability *vidcap=arg;                        sprintf(vidcap->name, "Jeroen's dummy v4l driver");                        vidcap->type= VID_TYPE_CAPTURE;                        vidcap->channels=1;                        vidcap->audios=0;                        vidcap->maxwidth=MAXWIDTH;                        vidcap->maxheight=MAXHEIGHT;                        vidcap->minwidth=20;                        vidcap->minheight=20;                        return 0;                }                case VIDIOCGCHAN:                {                        struct video_channel *vidchan= (struct video_channel *)arg;                        printf("VIDIOCGCHAN called\n");                        if (vidchan->channel!=0)                                ;//return 1;                        vidchan->channel=0;                        vidchan->flags=0;                        vidchan->tuners=0;                        vidchan->norm=0;                        vidchan->type=VIDEO_TYPE_CAMERA;                        strcpy(vidchan->name, "Loopback");                        return 0;                }                case VIDIOCSCHAN:                {                        int *v=arg;                        if (v[0]!=0)                                return 1;                        return 0;                }                case VIDIOCGTUNER:                {                        struct video_tuner *v = arg;                        if(v->tuner) {                                printf("VIDIOCGTUNER: Invalid Tuner, was %d\n", v->tuner);                                //return -EINVAL;                        }                        v->tuner=0;                        strcpy(v->name, "Format");                        v->rangelow=0;                        v->rangehigh=0;                        v->flags=0;                        v->mode=VIDEO_MODE_AUTO;                        return 1;                }                case VIDIOCGPICT:                {                        struct video_picture *vidpic=arg;                        vidpic->colour=0x8000;                        vidpic->hue=0x8000;                        vidpic->brightness=0x8000;                        vidpic->contrast=0x8000;                        vidpic->whiteness=0x8000;                        vidpic->depth=0x8000;                        vidpic->palette=fmt;                        return 0;                }                case VIDIOCSPICT:                {                        struct video_picture *vidpic=arg;                        if (vidpic->palette!=fmt)                                return 1;                        return 0;                }                case VIDIOCGWIN:                {                        struct video_window *vidwin=arg;                        vidwin->x=0;                        vidwin->y=0;                        vidwin->width=width;                        vidwin->height=height;                        vidwin->chromakey=0;                        vidwin->flags=0;                        vidwin->clipcount=0;                        return 0;                }                case VIDIOCSWIN:                {                        struct video_window *vidwin=arg;                        if (vidwin->width > MAXWIDTH ||                            vidwin->height > MAXHEIGHT )                                return 1;                        if (vidwin->flags)                                return 1;                        width=vidwin->width;                        height=vidwin->height;                        printf("new size: %dx%d\n", width, height);                        return 0;                }                case VIDIOCGMBUF:                {                        struct video_mbuf *vidmbuf=arg;                        vidmbuf->size=width*height*3;                        vidmbuf->frames=1;                        for (i=0; i<vidmbuf->frames; i++)                                vidmbuf->offsets[i]=i*vidmbuf->size;                        return 0;                }                case VIDIOCMCAPTURE:                {                        struct video_mmap *vidmmap=arg;                        //return 0;                        if (vidmmap->height>MAXHEIGHT ||                            vidmmap->width>MAXWIDTH ||                            vidmmap->format!=fmt )                                return 1;                        if (vidmmap->height!=height ||                            vidmmap->width!=width) {                                height=vidmmap->height;                                width=vidmmap->width;                                printf("new size: %dx%d\n", width, height);                        }                        // check if 'vidmmap->frame' is valid                        // initiate capture for 'vidmmap->frame' frames                        return 0;                }                case VIDIOCSYNC:                {                        //struct video_mmap *vidmmap=arg;                        // check if frames are ready.                        // wait until ready.                        get_frame();                        return 0;                }                default:                {                        printf("unknown ioctl: %ld\n", cmd & 0xff);                        return 1;                }        }        return 0;}static vo_info_t info ={	"video4linux write output",	"v4lw",	"Tilmann Bitterberg <god at tibit.org>",	"update 4/27/06 sfanzyshen <sfranzyshen at hotmail.com>"};LIBVO_EXTERN(v4lw)/* stolen from: * vloopback/example/dummy.c * returns 0 on successfull opening, !0 otherwise */int check_vidpipe(void){        int pipe_fd = -1;        FILE *vloopbacks;        char pipepath[255];        char buffer[255];        char *loop;        char *input;        char *istatus;        char *output;        char *ostatus;        char *major;        char *minor;        struct utsname uts;        if (uname(&uts) < 0) {                printf("Unable to execute uname\nError[%s]\n",strerror(errno));                return -1;        }        major = strtok(uts.release, ".");        minor = strtok(NULL, ".");        if ((major == NULL) || (minor == NULL) || (strcmp(major, "2"))) {                printf("Unable to decipher OS version\n");                return -1;        }                DIR *dir;                struct dirent *dirp;                const char prefix[]="/sys/class/video4linux/";                char *ptr, *io;                int fd;                int low=9999;                int tfd;                int tnum;                if ((dir=opendir(prefix))== NULL) {                        printf( "Failed to open '%s'", prefix);                        return -1;                }                while ((dirp=readdir(dir)) != NULL) {                        if (!strncmp(dirp->d_name, "video", 5)) {                                strcpy(buffer, prefix);                                strcat(buffer, dirp->d_name);                                strcat(buffer, "/name");                                if ((fd=open(buffer, O_RDONLY)) >= 0) {                                        if ((read(fd, buffer, sizeof(buffer)-1))<0) {                                                close(fd);                                                continue;                                        }                                        ptr = strtok(buffer, " ");                                        if (strcmp(ptr,"Video")) {                                                close(fd);                                                continue;                                        }                                        major = strtok(NULL, " ");                                        minor = strtok(NULL, " ");                                        io  = strtok(NULL, " \n");                                        if (strcmp(major, "loopback") || strcmp(io, "input")) {                                                close(fd);                                                continue;                                        }                                        if ((ptr=strtok(buffer, " "))==NULL) {                                                close(fd);                                                continue;                                        }                                        tnum = atoi(minor);                                        if (tnum < low) {                                                strcpy(buffer, "/dev/");                                                strcat(buffer, dirp->d_name);                                                if ((tfd=open(buffer, O_RDWR))>=0) {                                                        strcpy(pipepath, buffer);                                                        if (pipe_fd>=0) {                                                                close(pipe_fd);                                                        }                                                        pipe_fd = tfd;                                                        low = tnum;                                                }                                        }                                        close(fd);                                }                        } }                closedir(dir);                if (pipe_fd >= 0)                        printf("Opened input of %i", pipe_fd);        return 0;}/* copied from * vloopback-0.90/example/invert.c */int start_pipe (int dev, int width, int height){        struct video_capability vid_caps;	struct video_window vid_win;	struct video_picture vid_pic;	printf("Started startpipe");        if (v4l_ioctl (VIDIOCGCAP, &vid_caps) == -1) {                printf ("ioctl (VIDIOCGCAP)\nError[%s]\n",strerror(errno));                return (1);        }        if (v4l_ioctl (VIDIOCGPICT, &vid_pic)== -1) {                printf ("ioctl VIDIOCGPICT\nError[%s]\n",strerror(errno));                return (1);        }	/* this is probably brain dead */	/* vid_pic.palette=VIDEO_PALETTE_RGB24; */	/* vid_pic.palette=VIDEO_PALETTE_YUV420P; */	vid_pic.palette = fmt;        if (v4l_ioctl (VIDIOCSPICT, &vid_pic)== -1) {                printf ("ioctl VIDIOCSPICT\nError[%s]\n",strerror(errno));                return (1);        }        if (v4l_ioctl (VIDIOCGWIN, &vid_win)== -1) {                printf ("ioctl VIDIOCGWIN\nError[%s]\n",strerror(errno));                return (1);        }	vid_win.width = width;	vid_win.height = height;        if (v4l_ioctl (VIDIOCSWIN, &vid_win)== -1) {                printf ("ioctl VIDIOCSWIN\nError[%s]\n",strerror(errno));                return (1);        }	return 0;}/* stolen from   vo_odivx.c   *//* orig size -- working  */static int draw_slice(uint8_t *src[], int stride[], int w,int h,int x,int y){	uint8_t *s;	uint8_t *d;	int i;	int dstride=image_width;	int size = image_width*image_height;	// copy Y	d=image+dstride*y+x;	s=src[0];	for(i=0;i<h;i++){		memcpy(d,s,w);		s+=stride[0];		d+=dstride;	}	w/=2;h/=2;x/=2;y/=2; dstride/=2;	// copy U	d=image + size + dstride*y+x;	s=src[1];	for(i=0;i<h;i++){		memcpy(d,s,w);		s+=stride[1];		d+=dstride;	}	// copy V	d=image + size + size/4 + dstride*y+x;	s=src[2];	for(i=0;i<h;i++){		memcpy(d,s,w);		s+=stride[2];		d+=dstride;	}	return 0;}static void draw_osd(void){}static void put_image(void){	int size = image_width*image_height*3;	if (write(devout, image, size) != size) {		perror("V4lW: Error writing image to pipe!");	}}static void flip_page(void){	put_image();}static int draw_frame(uint8_t *src[]){	/* untested */	printf("Started drawframe");	memcpy (image, src, image_width * image_height * 3);	return 0;}static int query_format(uint32_t format){	switch(format){		case IMGFMT_YV12:		case IMGFMT_I420:		case IMGFMT_YUY2:		case IMGFMT_RGB24:		case IMGFMT_BGR24:			return 1;	}	return 0;}static int config (uint32_t width, uint32_t height, uint32_t d_width,		uint32_t d_height, uint32_t fullscreen, char *title,		uint32_t format){	image_width  = width;	image_height = height;	image_format = format;	switch (image_format) {		case IMGFMT_YV12:		case IMGFMT_I420:			fmt = VIDEO_PALETTE_YUV420P;			break;		case IMGFMT_RGB24:		case IMGFMT_BGR24:			fmt = VIDEO_PALETTE_RGB24;			break;	}	if (check_vidpipe() != 0) {		return 1;	}	if (start_pipe(devout, width, height) != 0) {		printf("You got sqa nooooed!");		return 1;	}	printf("V4lW: width: %d; height: %d; format: %d\n", width, height, format); 	image = (uint8_t *) malloc(width*height*3);	if (!image) {		close (devout);		return 1;	}	/* clear the buffer, grey */	memset(image,0x80,width*height*3);	return 0;}static const vo_info_t*get_info(void){	return &info;}static voiduninit(void){	if (image)		free(image);	close (devout);}static void check_events(void){}static int preinit(const char *arg){  return 0;}static int control(uint32_t request, void *data, ...){  switch (request) {  case VOCTRL_QUERY_FORMAT:    return query_format(*((uint32_t*)data));  }  return VO_NOTIMPL;}