[MPlayer-dev-eng] [PATCH] fix for v4l1 driver

Trent Piepho xyzzy at speakeasy.org
Sat Apr 28 12:54:06 CEST 2007


This patch makes the v4l1 driver work properly.  There were some bugs in
the kernel v4l1 compat system, but mplayer had some bugs too.  This patch
applies on top of the cosmetic patch I sent earlier.

The main problem is that it called VIDIOCGMBUF to memory map the capture
buffer _before_ calling VIDIOCSPICT (to set the pixel format) and
VIDIOCSWIN (to set the capture size).  The buffer that would be mapped wouldn't
be correct for the size/format actually used.  The V4L1 docs state that one
must call VIDIOCSPICT & VIDIOCSWIN before calling VIDIOCGMBUF.

So I added a call to VIDIOCSPICT and moved the call to VIDIOCGMBUF to after
the capture parameters have been setup.

mplayer ignores most ioctl failures.  If one tries to use a pixel format
that is not supported, for example the default planar format isn't
supported by the cx88 driver, mplayer would ignore VIDIOCSPICT failing and
then randomly screw up later.

I made mplayer give a better error message when an unsupported pixel format
is used and fail immediately, so the problem is clear to the user.

There was also a set vs get typo that I fixed.
-------------- next part --------------
--- stream/tvi_v4l.c.cosmetic	2007-04-28 01:31:46.000000000 -0700
+++ stream/tvi_v4l.c	2007-04-28 01:31:08.000000000 -0700
@@ -597,35 +597,6 @@
 	goto err;
     }
     
-    if ( !tv_param_mjpeg )
-    {
-	/* map grab buffer */
-	if (ioctl(priv->video_fd, VIDIOCGMBUF, &priv->mbuf) == -1)
-	{
-	    mp_msg(MSGT_TV, MSGL_ERR, "ioctl get mbuf failed: %s\n", strerror(errno));
-	    goto err;
-	}
-
-	mp_msg(MSGT_TV, MSGL_V, "mbuf: size=%d, frames=%d\n",
-	    priv->mbuf.size, priv->mbuf.frames);
-	priv->mmap = mmap(0, priv->mbuf.size, PROT_READ|PROT_WRITE,
-			  MAP_SHARED, priv->video_fd, 0);
-	if (priv->mmap == (unsigned char *)-1)
-	{
-	    mp_msg(MSGT_TV, MSGL_ERR, "Unable to map memory for buffers: %s\n", strerror(errno));
-	    goto err;
-	}
-	mp_msg(MSGT_TV, MSGL_DBG2, "our buffer: %p\n", priv->mmap);
-
-	/* num of buffers */
-	priv->nbuf = priv->mbuf.frames;
-    
-	/* video buffers */
-	priv->buf = calloc(priv->nbuf, sizeof(struct video_mmap));
-	if (!priv->buf)
-	    goto malloc_failed;
-	memset(priv->buf, 0, priv->nbuf * sizeof(struct video_mmap));
-    }
     
     /* init v4l audio even when we don't capture */
     init_v4l_audio(priv);
@@ -772,6 +743,7 @@
 {
     int i;
     int bytes_per_sample;
+    struct video_window win;
     
     if (ioctl(priv->video_fd, VIDIOCGPICT, &priv->picture) == -1)
     {
@@ -798,6 +770,53 @@
     if (ioctl(priv->video_fd, VIDIOCSPICT, &priv->picture) == -1)
     {
 	mp_msg(MSGT_TV, MSGL_ERR, "ioctl set picture failed: %s\n", strerror(errno));
+	mp_msg(MSGT_TV, MSGL_ERR, "The 'outfmt' of '%s' is likely not supported by your card\n",
+	       vo_format_name(priv->format));
+	return 0;
+    }
+
+    /* Set capture size */
+    win.x = 0;
+    win.y = 0;
+    win.width = priv->width;
+    win.height = priv->height;
+    win.chromakey = -1;
+    win.flags = 0;
+    win.clipcount = 0;
+    if (ioctl(priv->video_fd, VIDIOCSWIN, &win) == -1)
+    {
+	mp_msg(MSGT_TV, MSGL_ERR, "ioctl set window failed: %s\n", strerror(errno));
+    }
+
+
+    if ( !tv_param_mjpeg )
+    {
+	/* map grab buffer */
+	if (ioctl(priv->video_fd, VIDIOCGMBUF, &priv->mbuf) == -1)
+	{
+	    mp_msg(MSGT_TV, MSGL_ERR, "ioctl get mbuf failed: %s\n", strerror(errno));
+	    return 0;
+	}
+
+	mp_msg(MSGT_TV, MSGL_V, "mbuf: size=%d, frames=%d\n",
+	    priv->mbuf.size, priv->mbuf.frames);
+	priv->mmap = mmap(0, priv->mbuf.size, PROT_READ|PROT_WRITE,
+			  MAP_SHARED, priv->video_fd, 0);
+	if (priv->mmap == (unsigned char *)-1)
+	{
+	    mp_msg(MSGT_TV, MSGL_ERR, "Unable to map memory for buffers: %s\n", strerror(errno));
+	    return 0;
+	}
+	mp_msg(MSGT_TV, MSGL_DBG2, "our buffer: %p\n", priv->mmap);
+
+	/* num of buffers */
+	priv->nbuf = priv->mbuf.frames;
+    
+	/* video buffers */
+	priv->buf = calloc(priv->nbuf, sizeof(struct video_mmap));
+	if (!priv->buf)
+	    return 0;
+	memset(priv->buf, 0, priv->nbuf * sizeof(struct video_mmap));
     }
 
     if ( !tv_param_mjpeg )
@@ -829,20 +848,6 @@
 #endif
 
 #if 0
-    {
-	struct video_window win;
-
-	win.x = 0;
-	win.y = 0;
-	win.width = priv->width;
-	win.height = priv->height;
-	win.chromakey = -1;
-	win.flags = 0;
-	//win.clipcount = 0;
-	
-	ioctl(priv->video_fd, VIDIOCSWIN, &win);
-    }
-
     // initialize video sub-capture
     if (ioctl(priv->video_fd, VIDIOCCAPTURE, &one) == -1)
     {
@@ -1072,7 +1077,7 @@
 	case TVI_CONTROL_VID_SET_PICTURE:
 	    if (ioctl(priv->video_fd, VIDIOCSPICT, &priv->picture) == -1)
 	    {
-		mp_msg(MSGT_TV, MSGL_ERR, "ioctl get picture failed: %s\n", strerror(errno));
+		mp_msg(MSGT_TV, MSGL_ERR, "ioctl set picture failed: %s\n", strerror(errno));
 		return(TVI_CONTROL_FALSE);
 	    }
 	    return(TVI_CONTROL_TRUE);


More information about the MPlayer-dev-eng mailing list