This is an automatic generated email to let you know that the following patch 
were queued at the 
http://git.linuxtv.org/xawtv3.git tree:

Subject: drv0-v4l2: Fix snapshot function breaking streaming
Author:  Hans de Goede <hdego...@redhat.com>
Date:    Tue Apr 2 14:03:09 2013 +0200

Drivers using videobuf2 don't allow mixing and matching mmap and read calls,
so after the first read calls any s_fmt or reqbufs calls will return EBUSY,
thus taking a snapshot breaks the streaming (it does not resume after taking
the snapshot).

This patch fixes this by "detecting" these type of drivers by their reporting
of EBUSY on a s_fmt after a read call, and then re-opening the device (to
clear the EBUSY condition), and marking the device as not read() capable.

Signed-off-by: Hans de Goede <hdego...@redhat.com>

 libng/plugins/drv0-v4l2.tmpl.c |   49 +++++++++++++++++++++++++++++++++++++--
 1 files changed, 46 insertions(+), 3 deletions(-)

---

http://git.linuxtv.org/xawtv3.git?a=commitdiff;h=889b467350f198956178ca2d5f5a21d09c0800c5

diff --git a/libng/plugins/drv0-v4l2.tmpl.c b/libng/plugins/drv0-v4l2.tmpl.c
index 88abb04..ded868d 100644
--- a/libng/plugins/drv0-v4l2.tmpl.c
+++ b/libng/plugins/drv0-v4l2.tmpl.c
@@ -87,7 +87,8 @@ struct v4l2_handle {
     int                         fd;
 
     /* device descriptions */
-    int                         ninputs,nstds,nfmts;
+    char                        *device;
+    int                         ninputs, nstds, nfmts, read_done;
     unsigned int                min_width, min_height;
     struct v4l2_capability     cap;
     struct v4l2_streamparm     streamparm;
@@ -545,6 +546,11 @@ v4l2_open_handle(char *device, int req_flags)
     if (NULL == h)
        return NULL;
     memset(h,0,sizeof(*h));
+    h->device = strdup(device);
+    if (!h->device) {
+        free(h);
+       return NULL;
+    }
 
     if (-1 == (h->fd = open(device, O_RDWR))) {
 #ifdef HAVE_EXPLAIN
@@ -653,6 +659,7 @@ v4l2_close_handle(void *handle)
        h->attr = NULL;
     }
 
+    free(h->device);
     free(h);
     h = NULL;
 
@@ -1065,7 +1072,9 @@ static int
 v4l2_setformat(void *handle, struct ng_video_fmt *fmt)
 {
     struct v4l2_handle *h = handle;
+    int rc, fd;
 
+retry:
     h->fmt_v4l2.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
     h->fmt_v4l2.fmt.pix.pixelformat  = xawtv_pixelformat[fmt->fmtid];
     h->fmt_v4l2.fmt.pix.width        = fmt->width;
@@ -1077,8 +1086,40 @@ v4l2_setformat(void *handle, struct ng_video_fmt *fmt)
     else
        h->fmt_v4l2.fmt.pix.bytesperline = 0;
 
-    if (-1 == xioctl(h->fd, VIDIOC_S_FMT, &h->fmt_v4l2, 1))
-       return -1;
+#ifdef USE_LIBV4L
+    rc = v4l2_ioctl(h->fd, VIDIOC_S_FMT, &h->fmt_v4l2);
+#else
+    rc = ioctl(h->fd, VIDIOC_S_FMT, &h->fmt_v4l2);
+#endif
+    /* Some devices do not like mixing read and mmap, they give EBUSY
+       here after the first read */
+    if (rc < 0 && errno == EBUSY && h->read_done) {
+        fprintf(stderr, "v4l2: %s does not support switching between "
+                        "read and mmap, reopening\n", h->device);
+        /* HACK only way to recover is to close and re-open the fd */
+        fd = open(h->device, O_RDWR);
+        if (fd == -1) {
+            fprintf(stderr, "v4l2: open %s: %s\n", h->device, strerror(errno));
+            return -1;
+        }
+#ifdef USE_LIBV4L
+        rc = v4l2_fd_open(fd, 0);
+        if (rc != -1)
+           fd = rc;
+        v4l2_close(h->fd);
+#else
+        close(h->fd);
+#endif
+        h->fd = fd;
+        h->cap.capabilities &= ~V4L2_CAP_READWRITE;
+        h->read_done = 0;
+        goto retry;
+    }
+    if (rc < 0) {
+        print_ioctl(stderr, ioctls_v4l2, PREFIX, VIDIOC_S_FMT, &h->fmt_v4l2);
+        fprintf(stderr,": %s\n", strerror(errno));
+        return -1;
+    }
     if (h->fmt_v4l2.fmt.pix.pixelformat != xawtv_pixelformat[fmt->fmtid])
        return -1;
     fmt->width        = h->fmt_v4l2.fmt.pix.width;
@@ -1217,6 +1258,8 @@ v4l2_getimage(void *handle)
            h->ov_on = 1;
            xioctl(h->fd, VIDIOC_OVERLAY, &h->ov_on, 0);
        }
+        if (rc >= 0)
+            h->read_done = 1;
        if (rc != size) {
            if (-1 == rc) {
                perror("v4l2: read");

_______________________________________________
linuxtv-commits mailing list
linuxtv-commits@linuxtv.org
http://www.linuxtv.org/cgi-bin/mailman/listinfo/linuxtv-commits

Reply via email to