[PATCH v3 3/4] qcap: Delay setting V4L format until creating stream.

Jeff Smith whydoubt at gmail.com
Mon Sep 7 15:17:58 CDT 2020


Signed-off-by: Jeff Smith <whydoubt at gmail.com>
---
Set the V4L format during stream initialization only, and only use the
VIDIOC_TRY_FMT ioctl elsewhere.  This, along with the previous patch,
allows for using current_caps exclusively to indicate the latest format
passed to SetFormat (or NULL if it has not been called).

 dlls/qcap/v4l.c | 45 ++++++++++++++++++++++++++++++++++++---------
 1 file changed, 36 insertions(+), 9 deletions(-)

diff --git a/dlls/qcap/v4l.c b/dlls/qcap/v4l.c
index dade5a51e0..f151cc66a3 100644
--- a/dlls/qcap/v4l.c
+++ b/dlls/qcap/v4l.c
@@ -196,13 +196,36 @@ static BOOL set_caps(struct v4l_device *device, const struct caps *caps)
         return FALSE;
     }
 
-    device->current_caps = caps;
     device->image_size = width * height * caps->video_info.bmiHeader.biBitCount / 8;
     device->image_pitch = width * caps->video_info.bmiHeader.biBitCount / 8;
 
     return TRUE;
 }
 
+static BOOL try_caps(struct v4l_device *device, const struct caps *caps)
+{
+    struct v4l2_format format = {0};
+    LONG width = caps->video_info.bmiHeader.biWidth;
+    LONG height = caps->video_info.bmiHeader.biHeight;
+
+    TRACE("device %p, width %d, height %d, pixelformat %#x.\n", device, width, height, caps->pixelformat);
+
+    format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+    format.fmt.pix.pixelformat = caps->pixelformat;
+    format.fmt.pix.width = width;
+    format.fmt.pix.height = height;
+    if (xioctl(device->fd, VIDIOC_TRY_FMT, &format) == -1
+            || format.fmt.pix.pixelformat != caps->pixelformat
+            || format.fmt.pix.width != width
+            || format.fmt.pix.height != height)
+    {
+        ERR("Failed trying pixel format: %s.\n", strerror(errno));
+        return FALSE;
+    }
+
+    return TRUE;
+}
+
 static HRESULT v4l_device_set_format(struct video_capture_device *iface, const AM_MEDIA_TYPE *mt)
 {
     struct v4l_device *device = v4l_device(iface);
@@ -215,9 +238,11 @@ static HRESULT v4l_device_set_format(struct video_capture_device *iface, const A
     if (device->current_caps == caps)
         return S_OK;
 
-    if (!set_caps(device, caps))
+    if (!try_caps(device, caps))
         return VFW_E_TYPE_NOT_ACCEPTED;
 
+    device->current_caps = caps;
+
     return S_OK;
 }
 
@@ -225,7 +250,10 @@ static HRESULT v4l_device_get_format(struct video_capture_device *iface, AM_MEDI
 {
     struct v4l_device *device = v4l_device(iface);
 
-    return CopyMediaType(mt, &device->current_caps->media_type);
+    if (device->current_caps)
+        return CopyMediaType(mt, &device->current_caps->media_type);
+
+    return CopyMediaType(mt, &device->caps[0].media_type);
 }
 
 static __u32 v4l2_cid_from_qcap_property(VideoProcAmpProperty property)
@@ -396,6 +424,10 @@ static void v4l_device_init_stream(struct video_capture_device *iface)
     ALLOCATOR_PROPERTIES req_props, ret_props;
     HRESULT hr;
 
+    /* We must commit to a particular format before reading from device. */
+    if (!set_caps(device, (device->current_caps) ? device->current_caps : &device->caps[0]))
+        ERR("Failed to set format.\n");
+
     req_props.cBuffers = 3;
     req_props.cbBuffer = device->image_size;
     req_props.cbAlign = 1;
@@ -656,9 +688,8 @@ struct video_capture_device *v4l_device_create(struct strmbase_source *pin, USHO
     for (i = 0; i < device->caps_count; ++i)
         device->caps[i].media_type.pbFormat = (BYTE *)&device->caps[i].video_info;
 
-    if (!set_caps(device, &device->caps[0]))
+    if (!try_caps(device, &device->caps[0]))
     {
-        ERR("Failed to set pixel format: %s\n", strerror(errno));
         if (!have_libv4l2)
             ERR_(winediag)("You may need libv4l2 to use this device.\n");
         goto error;
@@ -671,10 +702,6 @@ struct video_capture_device *v4l_device_create(struct strmbase_source *pin, USHO
     InitializeCriticalSection(&device->state_cs);
     device->state_cs.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": v4l_device.state_cs");
 
-    TRACE("Format: %d bpp - %dx%d.\n", device->current_caps->video_info.bmiHeader.biBitCount,
-            device->current_caps->video_info.bmiHeader.biWidth,
-            device->current_caps->video_info.bmiHeader.biHeight);
-
     return &device->d;
 
 error:
-- 
2.23.0




More information about the wine-devel mailing list