[PATCH 2/6] qcap/videocapture: Use formats from capabilities instead of hard coding.

Jactry Zeng jzeng at codeweavers.com
Thu Apr 23 00:28:37 CDT 2020


Signed-off-by: Jactry Zeng <jzeng at codeweavers.com>
---
 dlls/qcap/capture.h            |   2 +-
 dlls/qcap/tests/videocapture.c |  42 ++++++++
 dlls/qcap/v4l.c                | 175 +++++++++++++--------------------
 dlls/qcap/vfwcapture.c         |   2 +-
 4 files changed, 113 insertions(+), 108 deletions(-)

diff --git a/dlls/qcap/capture.h b/dlls/qcap/capture.h
index fa48324dd6..d3cf193e7f 100644
--- a/dlls/qcap/capture.h
+++ b/dlls/qcap/capture.h
@@ -25,7 +25,7 @@ typedef struct _Capture Capture;
 
 Capture *qcap_driver_init(struct strmbase_source *,USHORT) DECLSPEC_HIDDEN;
 HRESULT qcap_driver_destroy(Capture*) DECLSPEC_HIDDEN;
-HRESULT qcap_driver_check_format(Capture*,const AM_MEDIA_TYPE*) DECLSPEC_HIDDEN;
+HRESULT qcap_driver_check_format(Capture* device,const AM_MEDIA_TYPE *mt,LONG *index) DECLSPEC_HIDDEN;
 HRESULT qcap_driver_set_format(Capture*,AM_MEDIA_TYPE*) DECLSPEC_HIDDEN;
 HRESULT qcap_driver_get_format(const Capture*,AM_MEDIA_TYPE**) DECLSPEC_HIDDEN;
 HRESULT qcap_driver_get_prop_range(Capture*,VideoProcAmpProperty,LONG*,LONG*,LONG*,LONG*,LONG*) DECLSPEC_HIDDEN;
diff --git a/dlls/qcap/tests/videocapture.c b/dlls/qcap/tests/videocapture.c
index 5532654650..a43875101c 100644
--- a/dlls/qcap/tests/videocapture.c
+++ b/dlls/qcap/tests/videocapture.c
@@ -21,6 +21,7 @@
 #define COBJMACROS
 #include "dshow.h"
 #include "wine/test.h"
+#include "wine/strmbase.h"
 
 static void test_media_types(IPin *pin)
 {
@@ -59,6 +60,44 @@ static void test_media_types(IPin *pin)
     ok(hr != S_OK, "Got hr %#x.\n", hr);
 }
 
+static void test_stream_config(IPin *pin)
+{
+    IAMStreamConfig *stream_config;
+    VIDEOINFOHEADER *video_info;
+    AM_MEDIA_TYPE *format;
+    HRESULT hr;
+
+    hr = IPin_QueryInterface(pin, &IID_IAMStreamConfig, (void **)&stream_config);
+    ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+    hr = IAMStreamConfig_GetFormat(stream_config, &format);
+    ok(hr == S_OK, "Got hr %#x.\n", hr);
+    ok(IsEqualGUID(&format->majortype, &MEDIATYPE_Video), "Got wrong majortype: %s.\n",
+            debugstr_guid(&format->majortype));
+
+    hr = IAMStreamConfig_SetFormat(stream_config, format);
+    ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+    format->majortype = MEDIATYPE_Audio;
+    hr = IAMStreamConfig_SetFormat(stream_config, format);
+    ok(hr == E_FAIL, "Got hr %#x.\n", hr);
+
+    format->majortype = MEDIATYPE_Video;
+    video_info = (VIDEOINFOHEADER *)format->pbFormat;
+    video_info->bmiHeader.biWidth--;
+    video_info->bmiHeader.biHeight--;
+    hr = IAMStreamConfig_SetFormat(stream_config, format);
+    ok(hr == E_FAIL, "Got hr %#x.\n", hr);
+
+    video_info->bmiHeader.biWidth = 10000000;
+    video_info->bmiHeader.biHeight = 10000000;
+    hr = IAMStreamConfig_SetFormat(stream_config, format);
+    ok(hr == E_FAIL, "Got hr %#x.\n", hr);
+    FreeMediaType(format);
+
+    IAMStreamConfig_Release(stream_config);
+}
+
 static void test_capture(IBaseFilter *filter)
 {
     IEnumPins *enum_pins;
@@ -73,7 +112,10 @@ static void test_capture(IBaseFilter *filter)
         PIN_DIRECTION pin_direction;
         IPin_QueryDirection(pin, &pin_direction);
         if (pin_direction == PINDIR_OUTPUT)
+        {
             test_media_types(pin);
+            test_stream_config(pin);
+        }
         IPin_Release(pin);
     }
 
diff --git a/dlls/qcap/v4l.c b/dlls/qcap/v4l.c
index 26eccf6ee3..db9117d593 100644
--- a/dlls/qcap/v4l.c
+++ b/dlls/qcap/v4l.c
@@ -103,7 +103,7 @@ struct capabilitie
 
 struct _Capture
 {
-    UINT width, height, bitDepth, fps, outputwidth, outputheight;
+    UINT outputwidth, outputheight;
     struct capabilitie *current_cap;
     struct capabilitie **caps;
     LONG caps_count;
@@ -146,126 +146,78 @@ HRESULT qcap_driver_destroy(Capture *capBox)
     return S_OK;
 }
 
-HRESULT qcap_driver_check_format(Capture *device, const AM_MEDIA_TYPE *mt)
+HRESULT qcap_driver_check_format(Capture *device, const AM_MEDIA_TYPE *mt, LONG *index)
 {
-    HRESULT hr;
+    LONG i;
+
     TRACE("device %p, mt %p.\n", device, mt);
 
     if (!mt)
         return E_POINTER;
 
     if (!IsEqualGUID(&mt->majortype, &MEDIATYPE_Video))
-        return S_FALSE;
+        return E_FAIL;
 
-    if (IsEqualGUID(&mt->formattype, &FORMAT_VideoInfo) && mt->pbFormat
-            && mt->cbFormat >= sizeof(VIDEOINFOHEADER))
+    for (i = device->caps_count - 1; i >= 0; i--)
     {
-        VIDEOINFOHEADER *vih = (VIDEOINFOHEADER *)mt->pbFormat;
-        if (vih->bmiHeader.biBitCount == 24 && vih->bmiHeader.biCompression == BI_RGB)
-            hr = S_OK;
-        else
+        VIDEOINFOHEADER *video_info = (VIDEOINFOHEADER *)mt->pbFormat;
+        struct capabilitie *cap = device->caps[i];
+
+        if (IsEqualIID(&mt->formattype, &cap->media_type.formattype)
+                && mt->cbFormat >= sizeof(VIDEOINFOHEADER)
+                && video_info
+                && video_info->bmiHeader.biWidth == cap->width
+                && video_info->bmiHeader.biHeight == cap->height)
         {
-            FIXME("Unsupported compression %#x, bpp %u.\n", vih->bmiHeader.biCompression,
-                    vih->bmiHeader.biBitCount);
-            hr = S_FALSE;
+            if (index)
+                *index = i;
+            TRACE("matched with: %d.\n", i);
+            return S_OK;
         }
     }
-    else
-        hr = VFW_E_INVALIDMEDIATYPE;
 
-    return hr;
+    return E_FAIL;
 }
 
 HRESULT qcap_driver_set_format(Capture *device, AM_MEDIA_TYPE *mt)
 {
     struct v4l2_format format = {0};
-    int newheight, newwidth;
-    VIDEOINFOHEADER *vih;
-    int fd = device->fd;
+    UINT newheight, newwidth;
+    LONG index;
     HRESULT hr;
 
-    if (FAILED(hr = qcap_driver_check_format(device, mt)))
+    if (FAILED(hr = qcap_driver_check_format(device, mt, &index)))
         return hr;
-    vih = (VIDEOINFOHEADER *)mt->pbFormat;
 
-    newwidth = vih->bmiHeader.biWidth;
-    newheight = vih->bmiHeader.biHeight;
-
-    if (device->height == newheight && device->width == newwidth)
+    if (device->current_cap == device->caps[index])
         return S_OK;
+    device->current_cap = device->caps[index];
 
-    format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
-    if (xioctl(fd, VIDIOC_G_FMT, &format) == -1)
-    {
-        ERR("Failed to get current format: %s\n", strerror(errno));
-        return VFW_E_TYPE_NOT_ACCEPTED;
-    }
+    newwidth = device->current_cap->width;
+    newheight = device->current_cap->height;
 
+    format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+    format.fmt.pix.pixelformat = device->current_cap->pixelformat;
     format.fmt.pix.width = newwidth;
     format.fmt.pix.height = newheight;
 
-    if (!xioctl(fd, VIDIOC_S_FMT, &format)
-            && format.fmt.pix.width == newwidth
-            && format.fmt.pix.height == newheight)
-    {
-        device->width = newwidth;
-        device->height = newheight;
-        device->swresize = FALSE;
-    }
-    else
-    {
-        TRACE("Using software resize: %dx%d -> %dx%d.\n",
-               format.fmt.pix.width, format.fmt.pix.height, device->width, device->height);
-        device->swresize = TRUE;
-    }
+    if (xioctl(device->fd, VIDIOC_S_FMT, &format) == -1
+            || format.fmt.pix.width != newwidth
+            || format.fmt.pix.height != newheight)
+        ERR("Failed to set pixel format: %s.\n", strerror(errno));
+
     device->outputwidth = format.fmt.pix.width;
     device->outputheight = format.fmt.pix.height;
     return S_OK;
 }
 
-HRESULT qcap_driver_get_format(const Capture *capBox, AM_MEDIA_TYPE ** mT)
+HRESULT qcap_driver_get_format(const Capture *device, AM_MEDIA_TYPE **mt)
 {
-    VIDEOINFOHEADER *vi;
-
-    mT[0] = CoTaskMemAlloc(sizeof(AM_MEDIA_TYPE));
-    if (!mT[0])
-        return E_OUTOFMEMORY;
-    vi = CoTaskMemAlloc(sizeof(VIDEOINFOHEADER));
-    mT[0]->cbFormat = sizeof(VIDEOINFOHEADER);
-    if (!vi)
-    {
-        CoTaskMemFree(mT[0]);
-        mT[0] = NULL;
+    *mt = CoTaskMemAlloc(sizeof(AM_MEDIA_TYPE));
+    if (!*mt)
         return E_OUTOFMEMORY;
-    }
-    mT[0]->majortype = MEDIATYPE_Video;
-    mT[0]->subtype = MEDIASUBTYPE_RGB24;
-    mT[0]->formattype = FORMAT_VideoInfo;
-    mT[0]->bFixedSizeSamples = TRUE;
-    mT[0]->bTemporalCompression = FALSE;
-    mT[0]->pUnk = NULL;
-    mT[0]->lSampleSize = capBox->outputwidth * capBox->outputheight * capBox->bitDepth / 8;
-    TRACE("Output format: %dx%d - %d bits = %u KB\n", capBox->outputwidth,
-          capBox->outputheight, capBox->bitDepth, mT[0]->lSampleSize/1024);
-    vi->rcSource.left = 0; vi->rcSource.top = 0;
-    vi->rcTarget.left = 0; vi->rcTarget.top = 0;
-    vi->rcSource.right = capBox->width; vi->rcSource.bottom = capBox->height;
-    vi->rcTarget.right = capBox->outputwidth; vi->rcTarget.bottom = capBox->outputheight;
-    vi->dwBitRate = capBox->fps * mT[0]->lSampleSize;
-    vi->dwBitErrorRate = 0;
-    vi->AvgTimePerFrame = (LONGLONG)10000000.0 / (LONGLONG)capBox->fps;
-    vi->bmiHeader.biSize = 40;
-    vi->bmiHeader.biWidth = capBox->outputwidth;
-    vi->bmiHeader.biHeight = capBox->outputheight;
-    vi->bmiHeader.biPlanes = 1;
-    vi->bmiHeader.biBitCount = 24;
-    vi->bmiHeader.biCompression = BI_RGB;
-    vi->bmiHeader.biSizeImage = mT[0]->lSampleSize;
-    vi->bmiHeader.biClrUsed = vi->bmiHeader.biClrImportant = 0;
-    vi->bmiHeader.biXPelsPerMeter = 100;
-    vi->bmiHeader.biYPelsPerMeter = 100;
-    mT[0]->pbFormat = (void *)vi;
-    return S_OK;
+
+    return CopyMediaType(*mt, &device->current_cap->media_type);
 }
 
 static __u32 v4l2_cid_from_qcap_property(VideoProcAmpProperty property)
@@ -345,13 +297,18 @@ HRESULT qcap_driver_set_prop(Capture *device, VideoProcAmpProperty property,
 
 static void Resize(const Capture * capBox, LPBYTE output, const BYTE *input)
 {
+    UINT width, height, bitdepth, depth;
+
+    width = capBox->current_cap->width;
+    height = capBox->current_cap->height;
+    bitdepth = capBox->current_cap->depth;
+    depth = bitdepth / 8;
     /* the whole image needs to be reversed,
        because the dibs are messed up in windows */
     if (!capBox->swresize)
     {
-        int depth = capBox->bitDepth / 8;
-        int inoffset = 0, outoffset = capBox->height * capBox->width * depth;
-        int ow = capBox->width * depth;
+        int inoffset = 0, outoffset = height * width * depth;
+        int ow = width * depth;
         while (outoffset > 0)
         {
             int x;
@@ -365,7 +322,6 @@ static void Resize(const Capture * capBox, LPBYTE output, const BYTE *input)
     {
         HDC dc_s, dc_d;
         HBITMAP bmp_s, bmp_d;
-        int depth = capBox->bitDepth / 8;
         int inoffset = 0, outoffset = (capBox->outputheight) * capBox->outputwidth * depth;
         int ow = capBox->outputwidth * depth;
         LPBYTE myarray;
@@ -375,12 +331,12 @@ static void Resize(const Capture * capBox, LPBYTE output, const BYTE *input)
         myarray = CoTaskMemAlloc(capBox->outputwidth * capBox->outputheight * depth);
         dc_s = CreateCompatibleDC(NULL);
         dc_d = CreateCompatibleDC(NULL);
-        bmp_s = CreateBitmap(capBox->width, capBox->height, 1, capBox->bitDepth, input);
-        bmp_d = CreateBitmap(capBox->outputwidth, capBox->outputheight, 1, capBox->bitDepth, NULL);
+        bmp_s = CreateBitmap(width, height, 1, bitdepth, input);
+        bmp_d = CreateBitmap(capBox->outputwidth, capBox->outputheight, 1, bitdepth, NULL);
         SelectObject(dc_s, bmp_s);
         SelectObject(dc_d, bmp_d);
         StretchBlt(dc_d, 0, 0, capBox->outputwidth, capBox->outputheight,
-                   dc_s, 0, 0, capBox->width, capBox->height, SRCCOPY);
+                   dc_s, 0, 0, width, height, SRCCOPY);
         GetBitmapBits(bmp_d, capBox->outputwidth * capBox->outputheight * depth, myarray);
         while (outoffset > 0)
         {
@@ -407,8 +363,12 @@ static DWORD WINAPI ReadThread(LPVOID lParam)
     ULONG framecount = 0;
     unsigned char *pTarget, *image_data;
     unsigned int image_size;
+    UINT width, height, depth;
 
-    image_size = capBox->height * capBox->width * 3;
+    width = capBox->current_cap->width;
+    height = capBox->current_cap->height;
+    depth = capBox->current_cap->depth / 8;
+    image_size = height * width * 3;
     if (!(image_data = heap_alloc(image_size)))
     {
         ERR("Failed to allocate memory.\n");
@@ -426,9 +386,9 @@ static DWORD WINAPI ReadThread(LPVOID lParam)
             int len;
             
             if (!capBox->swresize)
-                len = capBox->height * capBox->width * capBox->bitDepth / 8;
+                len = height * width * depth;
             else
-                len = capBox->outputheight * capBox->outputwidth * capBox->bitDepth / 8;
+                len = capBox->outputheight * capBox->outputwidth * depth;
             IMediaSample_SetActualDataLength(pSample, len);
 
             len = IMediaSample_GetActualDataLength(pSample);
@@ -468,10 +428,10 @@ void qcap_driver_init_stream(Capture *device)
 
     req_props.cBuffers = 3;
     if (!device->swresize)
-        req_props.cbBuffer = device->width * device->height;
+        req_props.cbBuffer = device->current_cap->width * device->current_cap->height;
     else
         req_props.cbBuffer = device->outputwidth * device->outputheight;
-    req_props.cbBuffer = (req_props.cbBuffer * device->bitDepth) / 8;
+    req_props.cbBuffer = (req_props.cbBuffer * device->current_cap->depth) / 8;
     req_props.cbAlign = 1;
     req_props.cbPrefix = 0;
 
@@ -711,9 +671,13 @@ Capture *qcap_driver_init(struct strmbase_source *pin, USHORT card)
 
     device->current_cap = device->caps[0];
 
-    format.fmt.pix.pixelformat = V4L2_PIX_FMT_BGR24;
+    memset(&format, 0, sizeof(format));
+    format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+    format.fmt.pix.pixelformat = device->current_cap->pixelformat;
+    format.fmt.pix.width = device->current_cap->width;
+    format.fmt.pix.height = device->current_cap->height;
     if (xioctl(fd, VIDIOC_S_FMT, &format) == -1
-            || format.fmt.pix.pixelformat != V4L2_PIX_FMT_BGR24)
+            || format.fmt.pix.pixelformat != device->current_cap->pixelformat)
     {
         ERR("Failed to set pixel format: %s\n", strerror(errno));
         if (!have_libv4l2)
@@ -721,16 +685,15 @@ Capture *qcap_driver_init(struct strmbase_source *pin, USHORT card)
         goto error;
     }
 
-    device->outputwidth = device->width = format.fmt.pix.width;
-    device->outputheight = device->height = format.fmt.pix.height;
+    device->outputwidth = format.fmt.pix.width;
+    device->outputheight = format.fmt.pix.height;
     device->swresize = FALSE;
-    device->bitDepth = 24;
     device->pin = pin;
-    device->fps = 3;
     device->state = State_Stopped;
     device->run_event = CreateEventW(NULL, TRUE, FALSE, NULL);
 
-    TRACE("Format: %d bpp - %dx%d.\n", device->bitDepth, device->width, device->height);
+    TRACE("Format: %d bpp - %dx%d.\n", device->current_cap->depth,
+            device->current_cap->width, device->current_cap->height);
 
     return device;
 
@@ -759,7 +722,7 @@ HRESULT qcap_driver_destroy(Capture *capBox)
     FAIL_WITH_ERR;
 }
 
-HRESULT qcap_driver_check_format(Capture *device, const AM_MEDIA_TYPE *mt)
+HRESULT qcap_driver_check_format(Capture *device, const AM_MEDIA_TYPE *mt, LONG *index)
 {
     FAIL_WITH_ERR;
 }
diff --git a/dlls/qcap/vfwcapture.c b/dlls/qcap/vfwcapture.c
index 4b1d14082a..ab323845bf 100644
--- a/dlls/qcap/vfwcapture.c
+++ b/dlls/qcap/vfwcapture.c
@@ -500,7 +500,7 @@ static inline VfwCapture *impl_from_strmbase_pin(struct strmbase_pin *pin)
 static HRESULT source_query_accept(struct strmbase_pin *pin, const AM_MEDIA_TYPE *mt)
 {
     VfwCapture *filter = impl_from_strmbase_pin(pin);
-    return qcap_driver_check_format(filter->driver_info, mt);
+    return qcap_driver_check_format(filter->driver_info, mt, NULL);
 }
 
 static HRESULT source_get_media_type(struct strmbase_pin *pin,
-- 
2.26.1




More information about the wine-devel mailing list