From: Damjan Jovanovic damjan.jov@gmail.com
Signed-off-by: Zebediah Figura z.figura12@gmail.com --- I've made some stylistic tweaks, and also removed test_property_bag which was only duplicating tests already extant in devenum.
dlls/qcap/capture.h | 1 + dlls/qcap/tests/Makefile.in | 3 +- dlls/qcap/tests/videocapture.c | 133 +++++++++++++++++++++++++++++++++ dlls/qcap/v4l.c | 40 ++++++++-- dlls/qcap/vfwcapture.c | 6 +- 5 files changed, 173 insertions(+), 10 deletions(-) create mode 100644 dlls/qcap/tests/videocapture.c
diff --git a/dlls/qcap/capture.h b/dlls/qcap/capture.h index 65ed2dfc27..aed88893e5 100644 --- a/dlls/qcap/capture.h +++ b/dlls/qcap/capture.h @@ -25,6 +25,7 @@ typedef struct _Capture Capture;
Capture *qcap_driver_init(IPin*,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_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/Makefile.in b/dlls/qcap/tests/Makefile.in index 2b988476ad..a5b9d0e474 100644 --- a/dlls/qcap/tests/Makefile.in +++ b/dlls/qcap/tests/Makefile.in @@ -5,4 +5,5 @@ C_SRCS = \ audiorecord.c \ avico.c \ qcap.c \ - smartteefilter.c + smartteefilter.c \ + videocapture.c diff --git a/dlls/qcap/tests/videocapture.c b/dlls/qcap/tests/videocapture.c new file mode 100644 index 0000000000..b80b0f2624 --- /dev/null +++ b/dlls/qcap/tests/videocapture.c @@ -0,0 +1,133 @@ +/* + * WDM video capture filter unit tests + * + * Copyright 2019 Damjan Jovanovic + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#define COBJMACROS +#include "dshow.h" +#include "wine/test.h" + +static void test_media_types(IPin *pin) +{ + IEnumMediaTypes *enum_media_types; + AM_MEDIA_TYPE mt, *pmt; + HRESULT hr; + + hr = IPin_EnumMediaTypes(pin, &enum_media_types); + ok(hr == S_OK, "Got hr %#x.\n", hr); + + while (IEnumMediaTypes_Next(enum_media_types, 1, &pmt, NULL) == S_OK) + { + hr = IPin_QueryAccept(pin, pmt); + ok(hr == S_OK, "Got hr %#x.\n", hr); + CoTaskMemFree(pmt); + } + IEnumMediaTypes_Release(enum_media_types); + + hr = IPin_QueryAccept(pin, NULL); + todo_wine ok(hr == E_POINTER, "Got hr %#x.\n", hr); + + memset(&mt, 0, sizeof(mt)); + hr = IPin_QueryAccept(pin, &mt); + ok(hr != S_OK, "Got hr %#x.\n", hr); + + mt.majortype = MEDIATYPE_Video; + hr = IPin_QueryAccept(pin, &mt); + ok(hr != S_OK, "Got hr %#x.\n", hr); + + mt.formattype = FORMAT_VideoInfo; + hr = IPin_QueryAccept(pin, &mt); + ok(hr != S_OK, "Got hr %#x.\n", hr); + + mt.formattype = FORMAT_None; + hr = IPin_QueryAccept(pin, &mt); + ok(hr != S_OK, "Got hr %#x.\n", hr); +} + +static void test_capture(IBaseFilter *filter) +{ + IEnumPins *enum_pins; + IPin *pin; + HRESULT hr; + + hr = IBaseFilter_EnumPins(filter, &enum_pins); + ok(hr == S_OK, "Got hr %#x.\n", hr); + + while ((hr = IEnumPins_Next(enum_pins, 1, &pin, NULL)) == S_OK) + { + PIN_DIRECTION pin_direction; + IPin_QueryDirection(pin, &pin_direction); + if (pin_direction == PINDIR_OUTPUT) + test_media_types(pin); + IPin_Release(pin); + } + + IEnumPins_Release(enum_pins); +} + +START_TEST(videocapture) +{ + ICreateDevEnum *dev_enum; + IEnumMoniker *class_enum; + IBaseFilter *filter; + IMoniker *moniker; + WCHAR *name; + HRESULT hr; + ULONG ref; + + CoInitialize(NULL); + + hr = CoCreateInstance(&CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC, + &IID_ICreateDevEnum, (void **)&dev_enum); + ok(hr == S_OK, "Got hr %#x.\n", hr); + + hr = ICreateDevEnum_CreateClassEnumerator(dev_enum, &CLSID_VideoInputDeviceCategory, &class_enum, 0); + if (hr == S_FALSE) + { + skip("No video capture devices present.\n"); + ICreateDevEnum_Release(dev_enum); + CoUninitialize(); + return; + } + ok(hr == S_OK, "Got hr=%#x.\n", hr); + + while (IEnumMoniker_Next(class_enum, 1, &moniker, NULL) == S_OK) + { + hr = IMoniker_GetDisplayName(moniker, NULL, NULL, &name); + ok(hr == S_OK, "Got hr %#x.\n", hr); + trace("Testing device %s.\n", wine_dbgstr_w(name)); + CoTaskMemFree(name); + + hr = IMoniker_BindToObject(moniker, NULL, NULL, &IID_IBaseFilter, (void**)&filter); + if (hr == S_OK) + { + test_capture(filter); + IBaseFilter_Release(filter); + } + else + skip("Failed to open capture device, hr=%#x.\n", hr); + + ref = IBaseFilter_Release(filter); + ok(!ref, "Got outstanding refcount %d.\n", ref); + IMoniker_Release(moniker); + } + + ICreateDevEnum_Release(dev_enum); + IEnumMoniker_Release(class_enum); + CoUninitialize(); +} diff --git a/dlls/qcap/v4l.c b/dlls/qcap/v4l.c index f0875f7636..6fe394af0a 100644 --- a/dlls/qcap/v4l.c +++ b/dlls/qcap/v4l.c @@ -131,20 +131,48 @@ HRESULT qcap_driver_destroy(Capture *capBox) return S_OK; }
+HRESULT qcap_driver_check_format(Capture *device, const AM_MEDIA_TYPE *mt) +{ + HRESULT hr; + TRACE("device %p, mt %p.\n", device, mt); + dump_AM_MEDIA_TYPE(mt); + + if (!mt) + return E_POINTER; + + if (!IsEqualGUID(&mt->majortype, &MEDIATYPE_Video)) + return S_FALSE; + + if (IsEqualGUID(&mt->formattype, &FORMAT_VideoInfo) && mt->pbFormat + && mt->cbFormat >= sizeof(VIDEOINFOHEADER)) + { + VIDEOINFOHEADER *vih = (VIDEOINFOHEADER *)mt->pbFormat; + if (vih->bmiHeader.biBitCount == 24 && vih->bmiHeader.biCompression == BI_RGB) + hr = S_OK; + else + { + FIXME("Unsupported compression %#x, bpp %u.\n", vih->bmiHeader.biCompression, + vih->bmiHeader.biBitCount); + hr = S_FALSE; + } + } + else + hr = VFW_E_INVALIDMEDIATYPE; + + return hr; +} + 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; + HRESULT hr;
+ if (FAILED(hr = qcap_driver_check_format(device, mt))) + return hr; vih = (VIDEOINFOHEADER *)mt->pbFormat; - if (vih->bmiHeader.biBitCount != 24 || vih->bmiHeader.biCompression != BI_RGB) - { - FIXME("Unsupported compression %#x, bpp %u.\n", vih->bmiHeader.biCompression, - vih->bmiHeader.biBitCount); - return VFW_E_INVALIDMEDIATYPE; - }
newwidth = vih->bmiHeader.biWidth; newheight = vih->bmiHeader.biHeight; diff --git a/dlls/qcap/vfwcapture.c b/dlls/qcap/vfwcapture.c index 6297a80e61..8cf25c19b2 100644 --- a/dlls/qcap/vfwcapture.c +++ b/dlls/qcap/vfwcapture.c @@ -658,10 +658,10 @@ static inline VfwPinImpl *impl_from_BasePin(BasePin *pin) return CONTAINING_RECORD(pin, VfwPinImpl, pin.pin); }
-static HRESULT WINAPI VfwPin_CheckMediaType(BasePin *pin, const AM_MEDIA_TYPE *amt) +static HRESULT WINAPI VfwPin_CheckMediaType(BasePin *pin, const AM_MEDIA_TYPE *mt) { - FIXME("(%p) stub\n", pin); - return E_NOTIMPL; + VfwPinImpl *filter = impl_from_BasePin(pin); + return qcap_driver_check_format(filter->parent->driver_info, mt); }
static HRESULT WINAPI VfwPin_GetMediaType(BasePin *pin, int iPosition, AM_MEDIA_TYPE *pmt)