[MPlayer-dev-eng] [PATCH] updated old v4lw vo patch

kirin_e at users.sourceforge.net kirin_e at users.sourceforge.net
Mon Apr 7 16:50:58 CEST 2008


Hi,

I've recently been playing around a bit with v4l vloopback and have
updated an old mplayer patch i found that added a video4linux write vo.
Figured i'd send the updated version to the list in case it's of use to
someone else. Patch is against snapshot 2008-04-05.

Updated patch is attached, the old original patch is found here:
http://www.tibit.org/video/

Just install the vloopback kernel module 1.1-rc1 and then patch mplayer &
enable the vo with:
'configure --enable-v4lw'

To use:
'mplayer -vo v4lw:/dev/videoX'

Now you can read from the other end of the vloopback pipe with whatever
program you use, mplayer or something else. Just make sure you specify
correct resolution or you will get garbled video output as vloopback
doesn't resize or crop.

/kirin
-------------- next part --------------
diff -Naur ../uu/mplayer-export-2008-04-05/configure ./configure
--- ../uu/mplayer-export-2008-04-05/configure   Fri Apr  4 21:38:06 2008
+++ ./configure Sun Apr  6 20:43:38 2008
@@ -354,6 +354,7 @@
   --enable-dxr3            enable DXR3/H+ video output [autodetect]
   --enable-ivtv            enable IVTV TV-Out video output [autodetect]
   --enable-v4l2            enable V4L2 Decoder audio/video output [autodetect]
+  --enable-v4lw            enable video4linux write video output [disable]
   --enable-dvb             enable DVB video output [autodetect]
   --enable-dvbhead         enable DVB video output (HEAD version) [autodetect]
   --enable-mga             enable mga_vid video output [autodetect]
@@ -545,6 +546,7 @@
 _dxr3=auto
 _ivtv=auto
 _v4l2=auto
+_v4lw=no
 _iconv=auto
 _langinfo=auto
 _rtc=auto
@@ -871,6 +873,8 @@
   --disable-ivtv)       _ivtv=no        ;;
   --enable-v4l2)        _v4l2=yes       ;;
   --disable-v4l2)       _v4l2=no        ;;
+  --enable-v4lw)        _v4lw=yes       ;;
+  --disable-v4lw)       _v4lw=no        ;;
   --enable-iconv)	_iconv=yes	;;
   --disable-iconv)	_iconv=no	;;
   --enable-langinfo)	_langinfo=yes	;;
@@ -4789,6 +4795,19 @@
 fi
 echores "$_vesa"
 
+
+echocheck "v4lw vloopback support"
+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'
+  _novomodules="v4lw $_novomodules"
+fi
+echores "$_v4lw"
+
+
 #################
 # VIDEO + AUDIO #
 #################
@@ -8620,6 +8639,7 @@
 $_def_dxr3
 $_def_ivtv
 $_def_v4l2
+$_def_v4lw
 $_def_dvb
 $_def_dvb_in
 $_def_svga
diff -Naur ../uu/mplayer-export-2008-04-05/libvo/video_out.c ./libvo/video_out.c
--- ../uu/mplayer-export-2008-04-05/libvo/video_out.c	Sat Mar 15 10:49:14 2008
+++ ./libvo/video_out.c	Sun Apr  6 20:15:48 2008
@@ -97,6 +97,7 @@
 extern vo_functions_t video_out_dxr3;
 extern vo_functions_t video_out_ivtv;
 extern vo_functions_t video_out_v4l2;
+extern vo_functions_t video_out_v4lw;
 extern vo_functions_t video_out_jpeg;
 extern vo_functions_t video_out_gif89a;
 extern vo_functions_t video_out_vesa;
@@ -190,6 +191,9 @@
 #ifdef HAVE_V4L2_DECODER
         &video_out_v4l2,
 #endif
+#ifdef HAVE_V4LW
+	&video_out_v4lw,
+#endif
 #ifdef HAVE_ZR
 	&video_out_zr,
 	&video_out_zr2,
diff -Naur ../uu/mplayer-export-2008-04-05/libvo/vo_v4lw.c ./libvo/vo_v4lw.c
--- ../uu/mplayer-export-2008-04-05/libvo/vo_v4lw.c	Thu Jan  1 01:00:00 1970
+++ ./libvo/vo_v4lw.c	Sun Apr  6 19:45:30 2008
@@ -0,0 +1,341 @@
+/* 
+ *  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. 
+ *
+ */
+
+/*
+ *  Apr 2008 - Updated by kirin, got the original patch from here:
+ *  http://www.tibit.org/video/
+ *  
+ *  Usage:
+ *  mplayer -vo v4lw:/dev/videoX
+ *  
+ *  More info about vloopback at http://motion.sourceforge.net/vloopback/
+ *
+ */
+
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <fcntl.h>
+#include <string.h>
+#include <errno.h>
+#include <sys/ioctl.h>
+#include <linux/videodev.h>
+
+#include "config.h"
+#include "video_out.h"
+#include "video_out_internal.h"
+
+#include "sub.h"
+#include "fastmemcpy.h"
+#include "mp_msg.h"
+
+static int dev_fd;
+static const char default_dev[] = "/dev/video1";
+static void (*draw_alpha_func)();
+
+static uint8_t *image = NULL;
+static uint32_t image_width, image_height;
+static unsigned int image_format;
+static unsigned int image_size;
+static unsigned int nr_planes;
+
+static struct {
+	uint8_t *dst;
+	unsigned int size;
+	unsigned int hfact;
+	unsigned int vfact;
+	unsigned int pixel_bytes;
+	unsigned int stride;
+} p[3];
+
+static const vo_info_t info = 
+{
+	"video4linux write output",
+	"v4lw",
+	"Tilmann Bitterberg <god at tibit.org>",
+	"experimental"
+};
+
+LIBVO_EXTERN(v4lw)
+
+
+static int check_pipe(const char *dev_name)
+{
+	dev_fd = open(dev_name, O_RDWR);
+	if (dev_fd >= 0) {
+		mp_msg(MSGT_VO, MSGL_INFO, "v4lw: using '%s'\n", dev_name);
+	} else {
+		mp_msg(MSGT_VO, MSGL_ERR,
+			"v4lw: error opening '%s': %s\n",
+			dev_name, strerror(errno));
+		mp_msg(MSGT_VO, MSGL_ERR,
+			"v4lw: failed to open vloopback pipe for writing\n");
+		return 1;
+	}
+
+	return 0;
+}
+
+static int start_pipe(int dev, int width, int height)
+{
+        struct video_capability vid_cap;
+	struct video_window vid_win;
+	struct video_picture vid_pic;
+
+	if (ioctl(dev, VIDIOCGCAP, &vid_cap) == -1) {
+	 	perror("ioctl VIDIOCGCAP");
+	 	return 1;
+	}
+
+	mp_msg(MSGT_VO, MSGL_INFO, "v4lw: device '%s', min size %dx%d\n",
+		vid_cap.name, vid_cap.minwidth, vid_cap.minheight);
+
+	if (ioctl(dev, VIDIOCGPICT, &vid_pic)== -1) {
+		perror("ioctl VIDIOCGPICT");
+		return 1;
+	}
+
+	vid_pic.palette = image_format;
+
+	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;
+}
+
+static int draw_slice(uint8_t *src[], int stride[], int w, int h, int x, int y)
+{
+	uint8_t *s, *d;
+	unsigned int i, j, w_tmp, h_tmp, x_tmp, y_tmp;
+
+	for (i = 0; i < nr_planes; i++) {
+		w_tmp = (w >> p[i].hfact) * p[i].pixel_bytes;
+		h_tmp = h >> p[i].vfact;
+		x_tmp = x >> p[i].hfact;
+		y_tmp = y >> p[i].vfact;
+
+		s = src[i];
+		d = p[i].dst + y_tmp * p[i].stride + x_tmp * p[i].pixel_bytes;
+	
+		for (j = 0; j < h_tmp; j++) {
+			fast_memcpy(d, s, w_tmp);
+			s += stride[i];
+			d += p[i].stride;
+		}
+	}
+
+	return 0;
+}
+
+static int draw_frame(uint8_t *src[])
+{
+	unsigned int i;
+
+	for (i = 0; i < nr_planes; i++) {
+		fast_memcpy(p[i].dst, src[i], p[i].size);
+	}
+
+	return 0;
+}
+
+static void draw_alpha(int x0, int y0, int w, int h, unsigned char *src,
+                       unsigned char *srca, int stride)
+{
+	unsigned char *d = p[0].dst + y0 * p[0].stride + x0 * p[0].pixel_bytes;
+
+	if (draw_alpha_func)
+		draw_alpha_func(w, h, src, srca, stride, d, p[0].stride);
+}
+
+static void draw_osd(void)
+{
+	vo_draw_text(image_width, image_height, draw_alpha);
+}
+
+static void put_image(void)
+{
+	if (write(dev_fd, image, image_size) != image_size) {
+		mp_msg(MSGT_VO, MSGL_ERR,
+			"v4lw: error writing image to pipe: %s\n",
+			strerror(errno));
+	}
+}
+
+static void flip_page(void)
+{
+	put_image();
+}
+
+static int query_format(uint32_t format)
+{
+	int flags = VFCAP_CSP_SUPPORTED | VFCAP_OSD | VFCAP_ACCEPT_STRIDE;
+
+	switch (format) {
+		// case IMGFMT_RGB32:
+		// case IMGFMT_RGB24:
+		case IMGFMT_BGR32:
+		case IMGFMT_BGR24:
+		case IMGFMT_YUY2:
+		case IMGFMT_UYVY:
+		case IMGFMT_422P:
+		case IMGFMT_I420:
+		case IMGFMT_IYUV:
+		case IMGFMT_YV12:
+			return flags;
+	}
+
+	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)
+{
+	unsigned int i, bpp;
+	unsigned int pixel_bytes = 1;
+	unsigned int vfact = 0,	hfact = 0;
+
+	draw_alpha_func = NULL;
+	nr_planes = 1;
+	
+	switch (format) {
+		case IMGFMT_RGB32:
+		case IMGFMT_BGR32:
+			image_format = VIDEO_PALETTE_RGB32;
+			draw_alpha_func = vo_draw_alpha_rgb32;
+			bpp = 32; pixel_bytes = bpp >> 3;
+			break;
+		case IMGFMT_RGB24:
+		case IMGFMT_BGR24:
+			image_format = VIDEO_PALETTE_RGB24;
+			draw_alpha_func = vo_draw_alpha_rgb24;
+			bpp = 24; pixel_bytes = bpp >> 3;
+			break;
+		case IMGFMT_YUY2:
+			image_format = VIDEO_PALETTE_YUV422;
+			draw_alpha_func = vo_draw_alpha_yuy2;
+			bpp = 16; pixel_bytes = bpp >> 3;
+			break;
+		case IMGFMT_UYVY:
+			image_format = VIDEO_PALETTE_UYVY;
+			draw_alpha_func = vo_draw_alpha_uyvy;
+			bpp = 16; pixel_bytes = bpp >> 3;
+			break;
+		case IMGFMT_422P:
+			image_format = VIDEO_PALETTE_YUV422P;
+			draw_alpha_func = vo_draw_alpha_yv12;
+			bpp = 16; nr_planes = 3; hfact = 1;
+			break;
+		case IMGFMT_I420:
+		case IMGFMT_IYUV:
+		case IMGFMT_YV12:
+			image_format = VIDEO_PALETTE_YUV420P;
+			draw_alpha_func = vo_draw_alpha_yv12;
+			bpp = 12; nr_planes = 3; hfact = 1; vfact = 1;
+			break;
+		default: /* unsupported */
+			return 1;
+	}
+
+	if (start_pipe(dev_fd, width, height) != 0)
+		return 1;
+
+	image_width  = width;
+	image_height = height;
+	image_size = (image_width * image_height * bpp) >> 3;
+
+	mp_msg(MSGT_VO, MSGL_INFO, "v4lw: %dx%d, format 0x%08x\n",
+		image_width, image_height, image_format);
+
+	if (image && (vo_config_count > 0))
+		free(image);
+	image = (uint8_t *) malloc(image_size);
+	if (!image)
+		return 1;
+
+	memset(image, 0x80, image_size); /* grey */
+
+	p[0].pixel_bytes = pixel_bytes;
+	p[0].hfact = 0;
+	p[0].vfact = 0;
+	p[0].stride = (image_width >> p[0].hfact) * p[0].pixel_bytes;
+	p[0].size = p[0].stride * image_height >> p[0].vfact;
+	p[0].dst = image;
+	
+	for (i = 1; i < nr_planes; i++) {
+		p[i].pixel_bytes = pixel_bytes;
+		p[i].hfact = hfact;
+		p[i].vfact = vfact;
+		p[i].stride = (image_width >> p[i].hfact) * p[i].pixel_bytes;
+		p[i].size = p[i].stride * image_height >> p[i].vfact;
+		p[i].dst = p[i - 1].dst + p[i - 1].size;
+	}
+
+	return 0;
+}
+
+static int preinit(const char *arg)
+{
+	if (check_pipe(arg ? arg : default_dev) != 0)
+		return 1;
+	
+	return 0;
+}
+
+static void uninit(void)
+{
+	if (image) {
+		free(image);
+		image = NULL;
+	}
+
+	close(dev_fd);
+}
+
+static void check_events(void)
+{
+}
+
+static int control(uint32_t request, void *data, ...)
+{
+	switch (request) {
+		case VOCTRL_QUERY_FORMAT:
+			return query_format(*((uint32_t *) data));
+	}
+
+	return VO_NOTIMPL;
+}
+



More information about the MPlayer-dev-eng mailing list