[MPlayer-dev-eng] RE: compiling vo_v4lw module, please help !!!!

Scott Franzyshen sfranzyshen at hotmail.com
Thu Apr 27 18:50:02 CEST 2006


>>Author: Raul Lucientes
>>Date: 2004-09-21 02:41 -600
>>To: mplayer-dev-eng
>>Subject: [MPlayer-dev-eng] compiling vo_v4lw module, please help !!!!
>>Hi,
>>
>>Im triyng to compile the mplayer (MPlayer-1.0pre5) with support for
>>"vloopback" (patch vo_v4l-patch-04-09-2002.p1), I have followed the
>>Tilmann´s procedure:
>>
>>http://www1.mplayerhq.hu/pipermail/mplayer-dev-eng/2001-November/002591.html
>>
>>But, when the compiling process arrive to the "vo_v4lw.c" module this 
>>error
>>happens :-(
>>


OK! I know this hasn't been in the news lately, but I was think how useful 
this would be to have
around. So I hacked it up to work for now, but I would like to work this 
back into main stream development. Any help would be greatly appreciated. I 
do not know most of the mplayer internal
stuff. Anyway, here is the patch (below) against MPlayer-1.0pre7try2 (for 
now ... I am working on
bringing it up to cvs)

Just a reminder to you all about this back in 2001 Tilmann Bitterberg 
created this patch;

>>Author: Tilmann Bitterberg
>>Date: 2001-11-27 09:49 -700
>>To: mplayer-dev-eng
>>Subject: [MPlayer-dev-eng] New vo_v4lw video output module
>>Hi,
>>
>>I hacked together a new libvo module called vo_v4lw.c. It
>>provides write support for the video4linux api. This means that
>>mplayer can act as a video4linux device providing (uncompressed)
>>YUV/RGB data to other v4l applications like xawtv, mp1e etc.

So why do I think this would be handy? Well I was thinking about directfb 
and how nice it
would be to use the output of mplayer as a videoprovider within a directfb 
application. However,
the "-vo directfb" is limited to only outputting fullscreen to the directfb 
screen. This doesn't
allow any directfb api interaction. (No overlay, alpha channel, etc.) So, If 
I was able to use directfb's
videodev(v4l) videoprovider, I could use an mplayer's ( or mplayers' ) 
output(s) within a direcfb application rendered to any directfb surface.(not 
just the whole screen)

I got this to work using the following setup;

MPlayer-1.0pre7try2 - Might work against CVS (haven't tried yet)
This Patch
vloopback-0.91
linux-2.4.27 - debian sarge source

- I patched MPlayer with this patch
- I built vloopback kernel module and insmod it
  (if you don't have a real v4l device don't forget to modprobe videodev 
first)
- I then built MPlayer with --enable-v4lw
- Then I start player outputting to v4l;

  mplayer -vo v4lw -vf scale=640:480 The.Simpsons.avi

- The I start another instance of MPlayer playing the v4l stream;

  mplayer -tv device=/dev/video1:driver=v4l:width=640:height=480 -vo 
directfb tv://

- This works for me, however this patch needs to be cleaned up and brought 
up to 2006
  development standards.

also there seems to be a problem with the current directfb cvs version of 
the v4l videoprovider.
It isn't working. I should be able to do something like dfbsee /dev/video1 
to watch the v4l stream
... but it don't work :(

Besides directfb. There are tons of applications out there that use the v4l 
standard ...
This would also add a level of virtualization to real hardware devices.

Thanks
sfranzyshen


==================== PATCH ====================================
diff -uraN MPlayer-1.0pre7try2/configure MPlayer-1.0pre7try2-v4lw/configure
--- MPlayer-1.0pre7try2/configure	2005-04-13 05:46:35.000000000 -0600
+++ MPlayer-1.0pre7try2-v4lw/configure	2006-04-26 13:54:47.000000000 -0600
@@ -249,6 +249,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-xvmc          build with XvMC acceleration for X 4.x [disable]
   --enable-vm            build with XF86VidMode support for X11 
[autodetect]
@@ -1343,6 +1344,7 @@
_real=auto
_live=auto
_xinerama=auto
+_v4lw=auto
_mga=auto
_xmga=auto
_vm=auto
@@ -1550,6 +1552,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	;;
@@ -3704,6 +3708,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
@@ -7466,6 +7483,7 @@
$_def_directx
$_def_ggi
$_def_3dfx
+$_def_v4lw
$_def_tdfxfb
$_def_tdfxvid
$_def_directfb
diff -uraN MPlayer-1.0pre7try2/libvo/video_out.c 
MPlayer-1.0pre7try2-v4lw/libvo/video_out.c
--- MPlayer-1.0pre7try2/libvo/video_out.c	2004-12-21 13:33:51.000000000 
-0700
+++ MPlayer-1.0pre7try2-v4lw/libvo/video_out.c	2006-04-26 13:58:19.000000000 
-0600
@@ -80,6 +80,7 @@
extern vo_functions_t video_out_syncfb;
extern vo_functions_t video_out_fbdev;
extern vo_functions_t video_out_fbdev2;
+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;
@@ -192,6 +193,9 @@
#ifdef HAVE_AA
	&video_out_aa,
#endif
+#ifdef HAVE_V4LW
+	&video_out_v4lw,
+#endif
#ifdef HAVE_CACA
	&video_out_caca,
#endif
diff -uraN MPlayer-1.0pre7try2/libvo/vo_v4lw.c 
MPlayer-1.0pre7try2-v4lw/libvo/vo_v4lw.c
--- MPlayer-1.0pre7try2/libvo/vo_v4lw.c	1969-12-31 17:00:00.000000000 -0700
+++ MPlayer-1.0pre7try2-v4lw/libvo/vo_v4lw.c	2006-04-26 16:02:56.000000000 
-0600
@@ -0,0 +1,423 @@
+/*
+ *  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 "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;
+
+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)
+{
+	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<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;
+}
+/*
+   printf("%d, %d, %d, %d, %d, %d, %d\n", stride[0], stride[1], stride[2], 
w, h, x, y);
+   720, 360, 360, 720, 16, 0, 0
+   720, 360, 360, 720, 16, 0, 16
+   ...
+   720, 360, 360, 720, 16, 0, 544
+   720, 360, 360, 720, 16, 0, 560
+*/
+#if 0
+/* Half size */
+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 j;
+	int dstride = image_width;
+	int size = image_width*image_height;
+
+	stride[0]<<=1;
+	stride[1]<<=1;
+	stride[2]<<=1;
+
+	// copy Y
+	d=image+dstride/2*y+x;
+	s=src[0];
+	for(i=0;i<h;i+=2){
+		for (j=0; j<w; j+=2)
+			d[j>>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<h;i+=2){
+		for (j=0; j<w; j+=2)
+			d[j>>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<h;i+=2){
+		for (j=0; j<w; j+=2)
+			d[j>>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)
+{
+
+	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 &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;
+}
+
==================== PATCH ====================================





More information about the MPlayer-dev-eng mailing list