[PATCH v2 1/6] qcap/videocapture: Storage capabilities information.
Jactry Zeng
jzeng at codeweavers.com
Tue Apr 28 09:11:54 CDT 2020
Signed-off-by: Jactry Zeng <jzeng at codeweavers.com>
---
dlls/qcap/v4l.c | 118 ++++++++++++++++++++++++++++++++++++++++++++++--
1 file changed, 115 insertions(+), 3 deletions(-)
diff --git a/dlls/qcap/v4l.c b/dlls/qcap/v4l.c
index 6fe92d2d0a..a370c7583a 100644
--- a/dlls/qcap/v4l.c
+++ b/dlls/qcap/v4l.c
@@ -93,9 +93,19 @@ static BOOL video_init(void)
#endif
}
+struct caps
+{
+ __u32 pixelformat;
+ AM_MEDIA_TYPE media_type;
+ VIDEOINFOHEADER video_info;
+ VIDEO_STREAM_CONFIG_CAPS config;
+};
+
struct _Capture
{
UINT width, height, bitDepth, fps, outputwidth, outputheight;
+ struct caps *caps;
+ LONG caps_count;
BOOL swresize;
struct strmbase_source *pin;
@@ -120,9 +130,12 @@ HRESULT qcap_driver_destroy(Capture *capBox)
{
TRACE("%p\n", capBox);
- if( capBox->fd != -1 )
+ if (capBox->fd != -1)
video_close(capBox->fd);
- CoTaskMemFree(capBox);
+ if (capBox->caps_count)
+ heap_free(capBox->caps);
+ heap_free(capBox);
+
return S_OK;
}
@@ -495,6 +508,41 @@ void qcap_driver_cleanup_stream(Capture *device)
ERR("Failed to decommit allocator, hr %#x.\n", hr);
}
+
+static void fill_caps(__u32 pixelformat, __u32 width, __u32 height,
+ __u32 max_fps, __u32 min_fps, struct caps *caps)
+{
+ LONG depth = 24;
+
+ caps->video_info.dwBitRate = width * height * depth * max_fps;
+ caps->video_info.bmiHeader.biSize = sizeof(caps->video_info.bmiHeader);
+ caps->video_info.bmiHeader.biWidth = width;
+ caps->video_info.bmiHeader.biHeight = height;
+ caps->video_info.bmiHeader.biPlanes = 1;
+ caps->video_info.bmiHeader.biBitCount = depth;
+ caps->video_info.bmiHeader.biCompression = BI_RGB;
+ caps->video_info.bmiHeader.biSizeImage = width * height * depth / 8;
+ caps->media_type.majortype = MEDIATYPE_Video;
+ caps->media_type.subtype = MEDIASUBTYPE_RGB24;
+ caps->media_type.bFixedSizeSamples = TRUE;
+ caps->media_type.bTemporalCompression = FALSE;
+ caps->media_type.lSampleSize = width * height * depth / 8;
+ caps->media_type.formattype = FORMAT_VideoInfo;
+ caps->media_type.pUnk = NULL;
+ caps->media_type.cbFormat = sizeof(VIDEOINFOHEADER);
+ caps->media_type.pbFormat = (void *)&caps->video_info;
+ caps->config.MaxFrameInterval = 10000000 * max_fps;
+ caps->config.MinFrameInterval = 10000000 * min_fps;;
+ caps->config.MaxOutputSize.cx = width;
+ caps->config.MaxOutputSize.cy = height;
+ caps->config.MinOutputSize.cx = width;
+ caps->config.MinOutputSize.cy = height;
+ caps->config.guid = FORMAT_VideoInfo;
+ caps->config.MinBitsPerSecond = width * height * depth * min_fps;
+ caps->config.MaxBitsPerSecond = width * height * depth * max_fps;
+ caps->pixelformat = pixelformat;
+}
+
Capture *qcap_driver_init(struct strmbase_source *pin, USHORT card)
{
struct v4l2_capability caps = {{0}};
@@ -506,7 +554,7 @@ Capture *qcap_driver_init(struct strmbase_source *pin, USHORT card)
have_libv4l2 = video_init();
- if (!(device = CoTaskMemAlloc(sizeof(*device))))
+ if (!(device = heap_alloc_zero(sizeof(*device))))
return NULL;
sprintf(path, "/dev/video%i", card);
@@ -559,6 +607,70 @@ Capture *qcap_driver_init(struct strmbase_source *pin, USHORT card)
goto error;
}
+ format.fmt.pix.pixelformat = V4L2_PIX_FMT_BGR24;
+ if (xioctl(fd, VIDIOC_TRY_FMT, &format) != -1
+ && format.fmt.pix.pixelformat == V4L2_PIX_FMT_BGR24)
+ {
+ struct v4l2_frmsizeenum frmsize = {0};
+
+ frmsize.pixel_format = format.fmt.pix.pixelformat;
+ while(xioctl(fd, VIDIOC_ENUM_FRAMESIZES, &frmsize) != -1)
+ {
+ struct v4l2_frmivalenum frmival = {0};
+ __u32 max_fps = 30, min_fps = 30;
+ struct caps *new_caps;
+
+ frmival.pixel_format = format.fmt.pix.pixelformat;
+ if (frmsize.type == V4L2_FRMSIZE_TYPE_DISCRETE)
+ {
+ frmival.width = frmsize.discrete.width;
+ frmival.height = frmsize.discrete.height;
+ }
+ else if (frmsize.type == V4L2_FRMSIZE_TYPE_STEPWISE)
+ {
+ frmival.width = frmsize.stepwise.max_width;
+ frmival.height = frmsize.stepwise.min_height;
+ }
+ else
+ {
+ FIXME("Unhandled frame size type: %d.\n", frmsize.type);
+ continue;
+ }
+
+ if (xioctl(fd, VIDIOC_ENUM_FRAMEINTERVALS, &frmival) != -1)
+ {
+ if (frmival.type == V4L2_FRMIVAL_TYPE_DISCRETE)
+ {
+ max_fps = frmival.discrete.denominator / frmival.discrete.numerator;
+ min_fps = max_fps;
+ }
+ else if (frmival.type == V4L2_FRMIVAL_TYPE_STEPWISE
+ || frmival.type == V4L2_FRMIVAL_TYPE_CONTINUOUS)
+ {
+ max_fps = frmival.stepwise.max.denominator / frmival.stepwise.max.numerator;
+ min_fps = frmival.stepwise.min.denominator / frmival.stepwise.min.numerator;
+ }
+ }
+ else
+ ERR("Failed to get fps: %s.\n", strerror(errno));
+
+ new_caps = heap_realloc(device->caps, (device->caps_count + 1) * sizeof(*device->caps));
+ if (!new_caps)
+ goto error;
+ device->caps = new_caps;
+ fill_caps(format.fmt.pix.pixelformat, frmsize.discrete.width, frmsize.discrete.height,
+ max_fps, min_fps, &device->caps[device->caps_count]);
+ device->caps_count++;
+
+ frmsize.index++;
+ }
+ }
+ else
+ {
+ ERR("This device doesn't support V4L2_PIX_FMT_BGR24 format.\n");
+ goto error;
+ }
+
format.fmt.pix.pixelformat = V4L2_PIX_FMT_BGR24;
if (xioctl(fd, VIDIOC_S_FMT, &format) == -1
|| format.fmt.pix.pixelformat != V4L2_PIX_FMT_BGR24)
--
2.26.2
More information about the wine-devel
mailing list