diff -Nur -X dontdiff /tmp/MPlayer-0.90pre6/configure MPlayer-release/configure --- /tmp/MPlayer-0.90pre6/configure Mon Aug 5 17:23:22 2002 +++ MPlayer-release/configure Wed Sep 4 09:55:35 2002 @@ -183,6 +183,7 @@ (check for /dev/mga_vid) [autodetect] --enable-xmga build with mga_vid X Window support (check for X & /dev/mga_vid) [autodetect] + --enable-v4lw build with video4linux write support [autodetect] --enable-xv build with Xv render support for X 4.x [autodetect] --enable-vm build with XF86VidMode support for X11 [autodetect] --enable-xinerama build with Xinerama support for X11 [autodetect] @@ -926,6 +927,7 @@ _real=auto _live=no _xinerama=auto +_v4lw=auto _mga=auto _xmga=auto _vm=auto @@ -1053,6 +1055,8 @@ --disable-live) _live=no ;; --enable-xinerama) _xinerama=yes ;; --disable-xinerama) _xinerama=no ;; + --enable-v4lw) _v4lw=yes ;; + --disable-v4lw) _v4lw=no ;; --enable-mga) _mga=yes ;; --disable-mga) _mga=no ;; --enable-xmga) _xmga=yes ;; @@ -2277,6 +2281,19 @@ fi echores "$_gl" +echocheck "/proc/video/vloopback" +if test "$_v4lw" = auto ; then + _v4lw=no + test -d /proc/video/vloopback && _v4lw=yes +fi +if test "$_v4lw" = yes ; then + _def_v4lw='#define HAVE_V4LW 1' + _vosrc="$_vosrc vo_v4lw.c" + _vomodules="v4lw $_vomodules" +else + _def_v4lw='#undef HAVE_V4LW' +fi +echores "$_v4lw" echocheck "/dev/mga_vid" if test "$_mga" = auto ; then @@ -4570,6 +4587,7 @@ $_def_sdlbuggy $_def_ggi $_def_3dfx +$_def_v4lw $_def_tdfxfb $_def_directfb $_def_directfb_version diff -Nur -X dontdiff /tmp/MPlayer-0.90pre6/libvo/video_out.c MPlayer-release/libvo/video_out.c --- /tmp/MPlayer-0.90pre6/libvo/video_out.c Wed Jul 24 18:16:59 2002 +++ MPlayer-release/libvo/video_out.c Wed Sep 4 09:55:35 2002 @@ -85,6 +85,7 @@ extern vo_functions_t video_out_md5; extern vo_functions_t video_out_syncfb; extern vo_functions_t video_out_fbdev; +extern vo_functions_t video_out_v4lw; extern vo_functions_t video_out_svga; extern vo_functions_t video_out_png; extern vo_functions_t video_out_ggi; @@ -154,6 +155,9 @@ #endif #ifdef HAVE_AA &video_out_aa, +#endif +#ifdef HAVE_V4LW + &video_out_v4lw, #endif #ifdef HAVE_DXR2 &video_out_dxr2, diff -Nur -X dontdiff /tmp/MPlayer-0.90pre6/libvo/vo_v4lw.c MPlayer-release/libvo/vo_v4lw.c --- /tmp/MPlayer-0.90pre6/libvo/vo_v4lw.c Thu Jan 1 00:00:00 1970 +++ MPlayer-release/libvo/vo_v4lw.c Wed Sep 4 13:03:20 2002 @@ -0,0 +1,418 @@ +/* + * 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. + * + */ + +/* + Quick v4lw loopback howto: + + - get the vloopback kernel module from + + or (alternative) my hacked version from + + + - 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "config.h" +#include "video_out.h" +#include "video_out_internal.h" + +LIBVO_EXTERN(v4lw) + +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; + +static vo_info_t vo_info = +{ + "video4linux write output", + "v4lw", + "Tilmann Bitterberg ", + "experimental" +}; + +/* stolen from: + * vloopback/example/dummy.c + * returns 0 on successfull opening, !0 otherwise + */ +int check_vidpipe(void) +{ + FILE *vloopbacks; + char pipepath[255]; + char buffer[255]; + char *loop; /* internal loop nr */ + char *input; /* our output dev */ + char *istatus; + char *output; /* user should read from */ + char *ostatus; + + vloopbacks=fopen("/proc/video/vloopback/vloopbacks", "r"); + if (!vloopbacks) { + perror ("V4lW: Failed to open '/proc/video/vloopback/vloopbacks'"); + printf ("V4lW: You need to load the vlooback kernel module\n"); + return -1; + } + /* Read vloopback version */ + fgets(buffer, 255, vloopbacks); + /* Read explaination line */ + fgets(buffer, 255, vloopbacks); + while (fgets(buffer, 255, vloopbacks)) { + if (strlen(buffer)>1) { + buffer[strlen(buffer)-1]=0; + loop = strtok(buffer, "\t"); + input = strtok(NULL, "\t"); + istatus = strtok(NULL, "\t"); + output = strtok(NULL, "\t"); + ostatus = strtok(NULL, "\t"); + if (istatus[0] == '-') { + sprintf(pipepath, "/dev/%s", input); + devout = open (pipepath, O_RDWR); + if (devout >= 0) { + printf("V4lW: I am writing to: /dev/%s\n", input); + printf("V4lW: You should read from: /dev/%s\n", output); + /* Ok, found one */ + return 0; + } else { + printf ("V4lW: Error opening /dev/%s\n", input); + perror ("V4lW: Failed to open output video device"); + /* scan ahead */ + } + } + } + } + printf("V4lW: Unable to find a available vloopback device\n"); + printf("V4lW: Maybe insmod with a greater pipes= value helps\n"); + return -1; +} +/* 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; + + if (ioctl (dev, VIDIOCGCAP, &vid_caps) == -1) { + perror ("ioctl (VIDIOCGCAP)"); + return (1); + } + if (ioctl (dev, VIDIOCGPICT, &vid_pic)== -1) { + perror ("ioctl VIDIOCGPICT"); + return (1); + } + /* this is probably brain dead */ + /* vid_pic.palette=VIDEO_PALETTE_RGB24; */ + /* vid_pic.palette=VIDEO_PALETTE_YUV420P; */ + vid_pic.palette = fmt; + + if (ioctl (dev, VIDIOCSPICT, &vid_pic)== -1) { + perror ("ioctl VIDIOCSPICT"); + return (1); + } + if (ioctl (dev, VIDIOCGWIN, &vid_win)== -1) { + perror ("ioctl VIDIOCGWIN"); + return (1); + } + vid_win.width = width; + vid_win.height = height; + if (ioctl (dev, VIDIOCSWIN, &vid_win)== -1) { + perror ("ioctl VIDIOCSWIN"); + return (1); + } + return 0; +} + +/* stolen from + vo_odivx.c + */ +/* orig size -- working */ +static uint32_t 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>1]=s[j]; + s+=stride[0]; + d+=dstride; + } + + w/=2;h/=2;x/=2;y/=2; dstride/=2; + + // copy U + d=image + size + dstride/2*y+x; + s=src[1]; + for(i=0;i>1]=s[j]; + s+=stride[1]; + d+=dstride; + } + + // copy V + d=image + size + size/4 + dstride/2*y+x; + s=src[2]; + for(i=0;i>1]=s[j]; + s+=stride[2]; + d+=dstride; + } + + return 0; +} +#endif +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 uint32_t draw_frame(uint8_t *src[]) +{ + /* untested */ + memcpy (image, src, image_width * image_height * 3); + return 0; +} + +static uint32_t 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 uint32_t config (uint32_t width, uint32_t height, uint32_t d_width, + uint32_t d_height, uint32_t fullscreen, char *title, + uint32_t format,const vo_tune_info_t *info) +{ + + 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) { + 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 &vo_info; +} + +static void +uninit(void) +{ + if (image) + free(image); + close (devout); +} + + +static void check_events(void) +{ +} +static uint32_t preinit(const char *arg) +{ + return 0; +} + +static uint32_t control(uint32_t request, void *data, ...) +{ + switch (request) { + case VOCTRL_QUERY_FORMAT: + return query_format(*((uint32_t*)data)); + } + return VO_NOTIMPL; +} +