From: Hans de Goede Date: Fri, 7 Oct 2011 07:54:24 +0000 (+0200) Subject: libv4l: handle some ioctls changing the format as a side effect X-Git-Tag: v4l-utils-0.9.0-test1~212 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=9df290ceeb7a15581f89c82eda46f0cb8089516e;p=platform%2Fupstream%2Fv4l-utils.git libv4l: handle some ioctls changing the format as a side effect Some ioctls may change the devices fmt as a side effect, handle this properly. Signed-off-by: Hans de Goede --- diff --git a/lib/libv4l2/libv4l2-priv.h b/lib/libv4l2/libv4l2-priv.h index 2e99200..730f193 100644 --- a/lib/libv4l2/libv4l2-priv.h +++ b/lib/libv4l2/libv4l2-priv.h @@ -100,6 +100,7 @@ void v4l2_plugin_cleanup(void *plugin_lib, void *plugin_priv, const struct libv4l2_dev_ops *dev_ops); /* From log.c */ +extern const char *v4l2_ioctls[]; void v4l2_log_ioctl(unsigned long int request, void *arg, int result); #endif diff --git a/lib/libv4l2/libv4l2.c b/lib/libv4l2/libv4l2.c index f7ec85d..0db7230 100644 --- a/lib/libv4l2/libv4l2.c +++ b/lib/libv4l2/libv4l2.c @@ -1059,6 +1059,13 @@ int v4l2_ioctl(int fd, unsigned long int request, ...) stream_needs_locking = 1; } break; + case VIDIOC_S_STD: + case VIDIOC_S_INPUT: + case VIDIOC_S_DV_PRESET: + case VIDIOC_S_DV_TIMINGS: + is_capture_request = 1; + stream_needs_locking = 1; + break; } if (!is_capture_request) { @@ -1150,6 +1157,53 @@ no_capture_request: break; } + case VIDIOC_S_STD: + case VIDIOC_S_INPUT: + case VIDIOC_S_DV_PRESET: + case VIDIOC_S_DV_TIMINGS: { + struct v4l2_format src_fmt; + + result = devices[index].dev_ops->ioctl( + devices[index].dev_ops_priv, + fd, request, arg); + if (result) + break; + + /* These ioctls may have changed the device's fmt */ + src_fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + result = devices[index].dev_ops->ioctl( + devices[index].dev_ops_priv, + fd, VIDIOC_G_FMT, &src_fmt); + if (result) { + V4L2_LOG_ERR("getting pixformat after %s: %s\n", + v4l2_ioctls[_IOC_NR(request)], + strerror(errno)); + result = 0; /* The original command did succeed */ + break; + } + + if (v4l2_pix_fmt_compat(&devices[index].src_fmt, &src_fmt)) { + v4l2_set_src_and_dest_format(index, &src_fmt, + &devices[index].dest_fmt); + break; + } + + /* The fmt has been changed, remember the new format ... */ + devices[index].src_fmt = src_fmt; + devices[index].dest_fmt = src_fmt; + /* and try to restore the last set destination pixelformat. */ + src_fmt.fmt.pix.pixelformat = + devices[index].dest_fmt.fmt.pix.pixelformat; + result = v4l2_s_fmt(index, &src_fmt); + if (result) { + V4L2_LOG_WARN("restoring destination pixelformat after %s failed\n", + v4l2_ioctls[_IOC_NR(request)]); + result = 0; /* The original command did succeed */ + } + + break; + } + case VIDIOC_REQBUFS: { struct v4l2_requestbuffers *req = arg; diff --git a/lib/libv4l2/log.c b/lib/libv4l2/log.c index 37d2e1f..f7ce06f 100644 --- a/lib/libv4l2/log.c +++ b/lib/libv4l2/log.c @@ -31,7 +31,7 @@ FILE *v4l2_log_file = NULL; -static const char *v4l2_ioctls[] = { +const char *v4l2_ioctls[] = { /* start v4l2 ioctls */ [_IOC_NR(VIDIOC_QUERYCAP)] = "VIDIOC_QUERYCAP", [_IOC_NR(VIDIOC_RESERVED)] = "VIDIOC_RESERVED",