[PATCH 1/4] qcap/tests: Refactor interface testing.
Signed-off-by: Jeff Smith <whydoubt(a)gmail.com> --- Supersede 191486 Based on Zebediah Figura's recommendations, I looked into how setting a pin's stream format would affect the media type enumeration. It turned out that it forces the enumeration down to the single format that was set. It remains this way until the filter is released. So it is necessary to track whether the stream format has been explicitly set, and respond to enumeration requests accordingly. dlls/qcap/tests/videocapture.c | 50 ++++++++++++++++++++-------------- 1 file changed, 30 insertions(+), 20 deletions(-) diff --git a/dlls/qcap/tests/videocapture.c b/dlls/qcap/tests/videocapture.c index 80d4899410..326601a398 100644 --- a/dlls/qcap/tests/videocapture.c +++ b/dlls/qcap/tests/videocapture.c @@ -174,7 +174,30 @@ static void test_stream_config(IPin *pin) IAMStreamConfig_Release(stream_config); } -static void test_capture(IBaseFilter *filter) +static void test_pin_interfaces(IPin *pin) +{ + todo_wine check_interface(pin, &IID_IAMBufferNegotiation, TRUE); + check_interface(pin, &IID_IAMStreamConfig, TRUE); + todo_wine check_interface(pin, &IID_IAMStreamControl, TRUE); + todo_wine check_interface(pin, &IID_IKsPin, TRUE); + check_interface(pin, &IID_IKsPropertySet, TRUE); + todo_wine check_interface(pin, &IID_IMediaSeeking, TRUE); + check_interface(pin, &IID_IPin, TRUE); + todo_wine check_interface(pin, &IID_IQualityControl, TRUE); + todo_wine check_interface(pin, &IID_ISpecifyPropertyPages, TRUE); + + check_interface(pin, &IID_IAMCrossbar, FALSE); + check_interface(pin, &IID_IAMDroppedFrames, FALSE); + check_interface(pin, &IID_IAMFilterMiscFlags, FALSE); + check_interface(pin, &IID_IAMPushSource, FALSE); + check_interface(pin, &IID_IAMTVTuner, FALSE); + check_interface(pin, &IID_IAMVideoCompression, FALSE); + check_interface(pin, &IID_IAMVideoProcAmp, FALSE); + check_interface(pin, &IID_IPersistPropertyBag, FALSE); + check_interface(pin, &IID_IStreamBuilder, FALSE); +} + +static void test_pins(IBaseFilter *filter) { IEnumPins *enum_pins; IPin *pin; @@ -189,32 +212,18 @@ static void test_capture(IBaseFilter *filter) IPin_QueryDirection(pin, &pin_direction); if (pin_direction == PINDIR_OUTPUT) { + test_pin_interfaces(pin); test_media_types(pin); test_stream_config(pin); - - todo_wine check_interface(pin, &IID_IAMBufferNegotiation, TRUE); - check_interface(pin, &IID_IAMStreamConfig, TRUE); - todo_wine check_interface(pin, &IID_IAMStreamControl, TRUE); - check_interface(pin, &IID_IKsPropertySet, TRUE); - todo_wine check_interface(pin, &IID_IMediaSeeking, TRUE); - check_interface(pin, &IID_IPin, TRUE); - todo_wine check_interface(pin, &IID_IQualityControl, TRUE); - todo_wine check_interface(pin, &IID_ISpecifyPropertyPages, TRUE); - - check_interface(pin, &IID_IAMCrossbar, FALSE); - check_interface(pin, &IID_IAMDroppedFrames, FALSE); - check_interface(pin, &IID_IAMFilterMiscFlags, FALSE); - check_interface(pin, &IID_IAMPushSource, FALSE); - check_interface(pin, &IID_IAMTVTuner, FALSE); - check_interface(pin, &IID_IAMVideoCompression, FALSE); - check_interface(pin, &IID_IAMVideoProcAmp, FALSE); - check_interface(pin, &IID_IPersistPropertyBag, FALSE); } IPin_Release(pin); } IEnumPins_Release(enum_pins); +} +static void test_filter_interfaces(IBaseFilter *filter) +{ check_interface(filter, &IID_IAMFilterMiscFlags, TRUE); check_interface(filter, &IID_IAMVideoControl, TRUE); check_interface(filter, &IID_IAMVideoProcAmp, TRUE); @@ -287,7 +296,8 @@ START_TEST(videocapture) hr = IMoniker_BindToObject(moniker, NULL, NULL, &IID_IBaseFilter, (void**)&filter); if (hr == S_OK) { - test_capture(filter); + test_filter_interfaces(filter); + test_pins(filter); test_misc_flags(filter); ref = IBaseFilter_Release(filter); ok(!ref, "Got outstanding refcount %d.\n", ref); -- 2.23.0
Signed-off-by: Jeff Smith <whydoubt(a)gmail.com> --- dlls/qcap/tests/videocapture.c | 137 ++++++++++++++++++++++++++++++--- 1 file changed, 127 insertions(+), 10 deletions(-) diff --git a/dlls/qcap/tests/videocapture.c b/dlls/qcap/tests/videocapture.c index 326601a398..c0fd30aee3 100644 --- a/dlls/qcap/tests/videocapture.c +++ b/dlls/qcap/tests/videocapture.c @@ -23,6 +23,12 @@ #include "wine/test.h" #include "wine/strmbase.h" +static BOOL compare_media_types(const AM_MEDIA_TYPE *a, const AM_MEDIA_TYPE *b) +{ + return !memcmp(a, b, offsetof(AM_MEDIA_TYPE, pbFormat)) + && !memcmp(a->pbFormat, b->pbFormat, a->cbFormat); +} + #define check_interface(a, b, c) check_interface_(__LINE__, a, b, c) static void check_interface_(unsigned int line, void *iface_ptr, REFIID iid, BOOL supported) { @@ -78,11 +84,13 @@ static void test_media_types(IPin *pin) static void test_stream_config(IPin *pin) { VIDEOINFOHEADER *video_info, *video_info2; - AM_MEDIA_TYPE *format, *format2; + AM_MEDIA_TYPE *format, *format2, *formats[2]; VIDEO_STREAM_CONFIG_CAPS vscc; IAMStreamConfig *stream_config; + IEnumMediaTypes *enum_media_types; LONG depth, compression; - LONG count, size; + LONG count, size, i; + ULONG fetched; HRESULT hr; hr = IPin_QueryInterface(pin, &IID_IAMStreamConfig, (void **)&stream_config); @@ -93,9 +101,27 @@ static void test_stream_config(IPin *pin) ok(IsEqualGUID(&format->majortype, &MEDIATYPE_Video), "Got wrong majortype: %s.\n", debugstr_guid(&format->majortype)); + /* Before setting format, multiple media types are enumerated. */ + IPin_EnumMediaTypes(pin, &enum_media_types); + hr = IEnumMediaTypes_Next(enum_media_types, 2, formats, &fetched); + ok(hr == S_OK, "Got hr %#x.\n", hr); + ok(fetched == 2, "Fetched %u.\n", fetched); + DeleteMediaType(formats[0]); + DeleteMediaType(formats[1]); + IEnumMediaTypes_Release(enum_media_types); + hr = IAMStreamConfig_SetFormat(stream_config, format); ok(hr == S_OK, "Got hr %#x.\n", hr); + /* After setting format, a single media type is enumerated. + * This persists until the filter is released. */ + IPin_EnumMediaTypes(pin, &enum_media_types); + hr = IEnumMediaTypes_Next(enum_media_types, 2, formats, &fetched); + todo_wine ok(hr == S_FALSE, "Got hr %#x.\n", hr); + todo_wine ok(fetched == 1, "Fetched %u.\n", fetched); + DeleteMediaType(formats[0]); + IEnumMediaTypes_Release(enum_media_types); + format->majortype = MEDIATYPE_Audio; hr = IAMStreamConfig_SetFormat(stream_config, format); ok(hr == E_FAIL, "Got hr %#x.\n", hr); @@ -162,14 +188,38 @@ static void test_stream_config(IPin *pin) hr = IAMStreamConfig_GetStreamCaps(stream_config, 100000, &format, (BYTE *)&vscc); ok(hr == S_FALSE, "Got hr %#x.\n", hr); - hr = IAMStreamConfig_GetStreamCaps(stream_config, 0, &format, (BYTE *)&vscc); - ok(hr == S_OK, "Got hr %#x.\n", hr); - ok(IsEqualGUID(&format->majortype, &MEDIATYPE_Video), "Got wrong majortype: %s.\n", - debugstr_guid(&MEDIATYPE_Video)); - ok(IsEqualGUID(&vscc.guid, &FORMAT_VideoInfo) - || IsEqualGUID(&vscc.guid, &FORMAT_VideoInfo2), "Got wrong guid: %s.\n", - debugstr_guid(&vscc.guid)); - FreeMediaType(format); + for (i = 0; i < count; i++) + { + hr = IAMStreamConfig_GetStreamCaps(stream_config, i, &format, (BYTE *)&vscc); + ok(hr == S_OK, "Got hr %#x.\n", hr); + ok(IsEqualGUID(&format->majortype, &MEDIATYPE_Video), "Got wrong majortype: %s.\n", + debugstr_guid(&MEDIATYPE_Video)); + ok(IsEqualGUID(&vscc.guid, &FORMAT_VideoInfo) + || IsEqualGUID(&vscc.guid, &FORMAT_VideoInfo2), "Got wrong guid: %s.\n", + debugstr_guid(&vscc.guid)); + + hr = IAMStreamConfig_SetFormat(stream_config, format); + ok(hr == S_OK, "Got hr %#x.\n", hr); + + hr = IAMStreamConfig_GetFormat(stream_config, &format2); + ok(hr == S_OK, "Got hr %#x.\n", hr); + ok(compare_media_types(format, format2), "Media types didn't match.\n"); + DeleteMediaType(format2); + + hr = IPin_EnumMediaTypes(pin, &enum_media_types); + ok(hr == S_OK, "Got hr %#x.\n", hr); + hr = IEnumMediaTypes_Next(enum_media_types, 1, &format2, NULL); + ok(hr == S_OK, "Got hr %#x.\n", hr); + + /* Which media types will match varies in wine depending on the attached webcam */ + todo_wine_if(compare_media_types(format, format2) == FALSE) + ok(compare_media_types(format, format2), "Media types didn't match.\n"); + + DeleteMediaType(format2); + IEnumMediaTypes_Release(enum_media_types); + + FreeMediaType(format); + } IAMStreamConfig_Release(stream_config); } @@ -260,6 +310,50 @@ static void test_misc_flags(IBaseFilter *filter) IAMFilterMiscFlags_Release(misc_flags); } +static int count_media_types(IPin *pin) +{ + IEnumMediaTypes *enum_media_types; + AM_MEDIA_TYPE *pmt; + int count = 0; + + IPin_EnumMediaTypes(pin, &enum_media_types); + while (IEnumMediaTypes_Next(enum_media_types, 1, &pmt, NULL) == S_OK) + { + CoTaskMemFree(pmt); + count++; + } + IEnumMediaTypes_Release(enum_media_types); + + return count; +} + +static void count_pins_media_types(IBaseFilter *filter, int *pin_count, int *media_type_count) +{ + IEnumPins *enum_pins; + IPin *pin; + HRESULT hr; + + *pin_count = 0; + *media_type_count = 0; + + 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) + { + (*pin_count)++; + (*media_type_count) += count_media_types(pin); + } + IPin_Release(pin); + } + + IEnumPins_Release(enum_pins); +} + START_TEST(videocapture) { ICreateDevEnum *dev_enum; @@ -269,6 +363,7 @@ START_TEST(videocapture) WCHAR *name; HRESULT hr; ULONG ref; + int pin_count, media_type_count; CoInitialize(NULL); @@ -297,7 +392,19 @@ START_TEST(videocapture) if (hr == S_OK) { test_filter_interfaces(filter); + + count_pins_media_types(filter, &pin_count, &media_type_count); + ok(media_type_count > pin_count, + "Expected media type count (%d) to be greater than pin count (%d)\n", + media_type_count, pin_count); + test_pins(filter); + + count_pins_media_types(filter, &pin_count, &media_type_count); + todo_wine ok(media_type_count == pin_count, + "Expected media type count (%d) to be equal to pin count (%d)\n", + media_type_count, pin_count); + test_misc_flags(filter); ref = IBaseFilter_Release(filter); ok(!ref, "Got outstanding refcount %d.\n", ref); @@ -305,6 +412,16 @@ START_TEST(videocapture) else skip("Failed to open capture device, hr=%#x.\n", hr); + hr = IMoniker_BindToObject(moniker, NULL, NULL, &IID_IBaseFilter, (void**)&filter); + if (hr == S_OK) + { + count_pins_media_types(filter, &pin_count, &media_type_count); + ok(media_type_count > pin_count, + "Expected media type count (%d) to be greater than pin count (%d)\n", + media_type_count, pin_count); + ref = IBaseFilter_Release(filter); + } + IMoniker_Release(moniker); } -- 2.23.0
On 8/28/20 10:52 AM, Jeff Smith wrote:
Signed-off-by: Jeff Smith <whydoubt(a)gmail.com> --- dlls/qcap/tests/videocapture.c | 137 ++++++++++++++++++++++++++++++--- 1 file changed, 127 insertions(+), 10 deletions(-)
diff --git a/dlls/qcap/tests/videocapture.c b/dlls/qcap/tests/videocapture.c index 326601a398..c0fd30aee3 100644 --- a/dlls/qcap/tests/videocapture.c +++ b/dlls/qcap/tests/videocapture.c @@ -23,6 +23,12 @@ #include "wine/test.h" #include "wine/strmbase.h"
+static BOOL compare_media_types(const AM_MEDIA_TYPE *a, const AM_MEDIA_TYPE *b) +{ + return !memcmp(a, b, offsetof(AM_MEDIA_TYPE, pbFormat)) + && !memcmp(a->pbFormat, b->pbFormat, a->cbFormat); +} + #define check_interface(a, b, c) check_interface_(__LINE__, a, b, c) static void check_interface_(unsigned int line, void *iface_ptr, REFIID iid, BOOL supported) { @@ -78,11 +84,13 @@ static void test_media_types(IPin *pin) static void test_stream_config(IPin *pin) { VIDEOINFOHEADER *video_info, *video_info2; - AM_MEDIA_TYPE *format, *format2; + AM_MEDIA_TYPE *format, *format2, *formats[2]; VIDEO_STREAM_CONFIG_CAPS vscc; IAMStreamConfig *stream_config; + IEnumMediaTypes *enum_media_types; LONG depth, compression; - LONG count, size; + LONG count, size, i; + ULONG fetched; HRESULT hr;
hr = IPin_QueryInterface(pin, &IID_IAMStreamConfig, (void **)&stream_config); @@ -93,9 +101,27 @@ static void test_stream_config(IPin *pin) ok(IsEqualGUID(&format->majortype, &MEDIATYPE_Video), "Got wrong majortype: %s.\n", debugstr_guid(&format->majortype));
+ /* Before setting format, multiple media types are enumerated. */ + IPin_EnumMediaTypes(pin, &enum_media_types); + hr = IEnumMediaTypes_Next(enum_media_types, 2, formats, &fetched); + ok(hr == S_OK, "Got hr %#x.\n", hr); + ok(fetched == 2, "Fetched %u.\n", fetched); + DeleteMediaType(formats[0]); + DeleteMediaType(formats[1]); + IEnumMediaTypes_Release(enum_media_types); +
I'm not exactly sure we need to test this, and I'm a little nervous to given how hardware-dependent behaviour can be.
hr = IAMStreamConfig_SetFormat(stream_config, format); ok(hr == S_OK, "Got hr %#x.\n", hr);
+ /* After setting format, a single media type is enumerated. + * This persists until the filter is released. */ + IPin_EnumMediaTypes(pin, &enum_media_types); + hr = IEnumMediaTypes_Next(enum_media_types, 2, formats, &fetched); + todo_wine ok(hr == S_FALSE, "Got hr %#x.\n", hr); + todo_wine ok(fetched == 1, "Fetched %u.\n", fetched); + DeleteMediaType(formats[0]); + IEnumMediaTypes_Release(enum_media_types); + format->majortype = MEDIATYPE_Audio; hr = IAMStreamConfig_SetFormat(stream_config, format); ok(hr == E_FAIL, "Got hr %#x.\n", hr); @@ -162,14 +188,38 @@ static void test_stream_config(IPin *pin) hr = IAMStreamConfig_GetStreamCaps(stream_config, 100000, &format, (BYTE *)&vscc); ok(hr == S_FALSE, "Got hr %#x.\n", hr);
- hr = IAMStreamConfig_GetStreamCaps(stream_config, 0, &format, (BYTE *)&vscc); - ok(hr == S_OK, "Got hr %#x.\n", hr); - ok(IsEqualGUID(&format->majortype, &MEDIATYPE_Video), "Got wrong majortype: %s.\n", - debugstr_guid(&MEDIATYPE_Video)); - ok(IsEqualGUID(&vscc.guid, &FORMAT_VideoInfo) - || IsEqualGUID(&vscc.guid, &FORMAT_VideoInfo2), "Got wrong guid: %s.\n", - debugstr_guid(&vscc.guid)); - FreeMediaType(format); + for (i = 0; i < count; i++) + { + hr = IAMStreamConfig_GetStreamCaps(stream_config, i, &format, (BYTE *)&vscc); + ok(hr == S_OK, "Got hr %#x.\n", hr); + ok(IsEqualGUID(&format->majortype, &MEDIATYPE_Video), "Got wrong majortype: %s.\n", + debugstr_guid(&MEDIATYPE_Video)); + ok(IsEqualGUID(&vscc.guid, &FORMAT_VideoInfo) + || IsEqualGUID(&vscc.guid, &FORMAT_VideoInfo2), "Got wrong guid: %s.\n", + debugstr_guid(&vscc.guid)); + + hr = IAMStreamConfig_SetFormat(stream_config, format); + ok(hr == S_OK, "Got hr %#x.\n", hr); + + hr = IAMStreamConfig_GetFormat(stream_config, &format2); + ok(hr == S_OK, "Got hr %#x.\n", hr); + ok(compare_media_types(format, format2), "Media types didn't match.\n"); + DeleteMediaType(format2); + + hr = IPin_EnumMediaTypes(pin, &enum_media_types); + ok(hr == S_OK, "Got hr %#x.\n", hr); + hr = IEnumMediaTypes_Next(enum_media_types, 1, &format2, NULL); + ok(hr == S_OK, "Got hr %#x.\n", hr); + + /* Which media types will match varies in wine depending on the attached webcam */ + todo_wine_if(compare_media_types(format, format2) == FALSE) + ok(compare_media_types(format, format2), "Media types didn't match.\n"); + + DeleteMediaType(format2); + IEnumMediaTypes_Release(enum_media_types); + + FreeMediaType(format); + }
IAMStreamConfig_Release(stream_config); } @@ -260,6 +310,50 @@ static void test_misc_flags(IBaseFilter *filter) IAMFilterMiscFlags_Release(misc_flags); }
+static int count_media_types(IPin *pin) +{ + IEnumMediaTypes *enum_media_types; + AM_MEDIA_TYPE *pmt; + int count = 0; + + IPin_EnumMediaTypes(pin, &enum_media_types); + while (IEnumMediaTypes_Next(enum_media_types, 1, &pmt, NULL) == S_OK) + { + CoTaskMemFree(pmt); + count++; + } + IEnumMediaTypes_Release(enum_media_types); + + return count; +} + +static void count_pins_media_types(IBaseFilter *filter, int *pin_count, int *media_type_count) +{ + IEnumPins *enum_pins; + IPin *pin; + HRESULT hr; + + *pin_count = 0; + *media_type_count = 0; + + 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) + { + (*pin_count)++; + (*media_type_count) += count_media_types(pin); + } + IPin_Release(pin); + } + + IEnumPins_Release(enum_pins); +} + START_TEST(videocapture) { ICreateDevEnum *dev_enum; @@ -269,6 +363,7 @@ START_TEST(videocapture) WCHAR *name; HRESULT hr; ULONG ref; + int pin_count, media_type_count;
CoInitialize(NULL);
@@ -297,7 +392,19 @@ START_TEST(videocapture) if (hr == S_OK) { test_filter_interfaces(filter); + + count_pins_media_types(filter, &pin_count, &media_type_count); + ok(media_type_count > pin_count, + "Expected media type count (%d) to be greater than pin count (%d)\n", + media_type_count, pin_count); + test_pins(filter); + + count_pins_media_types(filter, &pin_count, &media_type_count); + todo_wine ok(media_type_count == pin_count, + "Expected media type count (%d) to be equal to pin count (%d)\n", + media_type_count, pin_count); +
This is a bit awkward (and, for that matter, doesn't exactly prove either of the propositions desired). Moreover, it seems that the tests added to test_stream_config() already prove this.
test_misc_flags(filter); ref = IBaseFilter_Release(filter); ok(!ref, "Got outstanding refcount %d.\n", ref); @@ -305,6 +412,16 @@ START_TEST(videocapture) else skip("Failed to open capture device, hr=%#x.\n", hr);
+ hr = IMoniker_BindToObject(moniker, NULL, NULL, &IID_IBaseFilter, (void**)&filter); + if (hr == S_OK) + { + count_pins_media_types(filter, &pin_count, &media_type_count); + ok(media_type_count > pin_count, + "Expected media type count (%d) to be greater than pin count (%d)\n", + media_type_count, pin_count); + ref = IBaseFilter_Release(filter); + } +
I guess, but I also don't really see a reason why the previous instantiation of a filter would affect this one.
IMoniker_Release(moniker); }
On Fri, Aug 28, 2020 at 11:34 AM Zebediah Figura <z.figura12(a)gmail.com> wrote:
On 8/28/20 10:52 AM, Jeff Smith wrote:
Signed-off-by: Jeff Smith <whydoubt(a)gmail.com> --- dlls/qcap/tests/videocapture.c | 137 ++++++++++++++++++++++++++++++--- 1 file changed, 127 insertions(+), 10 deletions(-)
diff --git a/dlls/qcap/tests/videocapture.c b/dlls/qcap/tests/videocapture.c index 326601a398..c0fd30aee3 100644 --- a/dlls/qcap/tests/videocapture.c +++ b/dlls/qcap/tests/videocapture.c @@ -23,6 +23,12 @@ #include "wine/test.h" #include "wine/strmbase.h"
+static BOOL compare_media_types(const AM_MEDIA_TYPE *a, const AM_MEDIA_TYPE *b) +{ + return !memcmp(a, b, offsetof(AM_MEDIA_TYPE, pbFormat)) + && !memcmp(a->pbFormat, b->pbFormat, a->cbFormat); +} + #define check_interface(a, b, c) check_interface_(__LINE__, a, b, c) static void check_interface_(unsigned int line, void *iface_ptr, REFIID iid, BOOL supported) { @@ -78,11 +84,13 @@ static void test_media_types(IPin *pin) static void test_stream_config(IPin *pin) { VIDEOINFOHEADER *video_info, *video_info2; - AM_MEDIA_TYPE *format, *format2; + AM_MEDIA_TYPE *format, *format2, *formats[2]; VIDEO_STREAM_CONFIG_CAPS vscc; IAMStreamConfig *stream_config; + IEnumMediaTypes *enum_media_types; LONG depth, compression; - LONG count, size; + LONG count, size, i; + ULONG fetched; HRESULT hr;
hr = IPin_QueryInterface(pin, &IID_IAMStreamConfig, (void **)&stream_config); @@ -93,9 +101,27 @@ static void test_stream_config(IPin *pin) ok(IsEqualGUID(&format->majortype, &MEDIATYPE_Video), "Got wrong majortype: %s.\n", debugstr_guid(&format->majortype));
+ /* Before setting format, multiple media types are enumerated. */ + IPin_EnumMediaTypes(pin, &enum_media_types); + hr = IEnumMediaTypes_Next(enum_media_types, 2, formats, &fetched); + ok(hr == S_OK, "Got hr %#x.\n", hr); + ok(fetched == 2, "Fetched %u.\n", fetched); + DeleteMediaType(formats[0]); + DeleteMediaType(formats[1]); + IEnumMediaTypes_Release(enum_media_types); +
I'm not exactly sure we need to test this, and I'm a little nervous to
Which 'this' do you mean? That >1 media types are enumerated before SetFormat? Or that exactly 1 media type is enumerated after SetFormat? Or that SetFormat is the point at which this change occurs?
given how hardware-dependent behaviour can be.
A video capture pin that only supported one media type would break this, but unless we find an exception to the rule, isn't it good to attempt testing the rule?
hr = IAMStreamConfig_SetFormat(stream_config, format); ok(hr == S_OK, "Got hr %#x.\n", hr);
+ /* After setting format, a single media type is enumerated. + * This persists until the filter is released. */ + IPin_EnumMediaTypes(pin, &enum_media_types); + hr = IEnumMediaTypes_Next(enum_media_types, 2, formats, &fetched); + todo_wine ok(hr == S_FALSE, "Got hr %#x.\n", hr); + todo_wine ok(fetched == 1, "Fetched %u.\n", fetched); + DeleteMediaType(formats[0]); + IEnumMediaTypes_Release(enum_media_types); + format->majortype = MEDIATYPE_Audio; hr = IAMStreamConfig_SetFormat(stream_config, format); ok(hr == E_FAIL, "Got hr %#x.\n", hr); @@ -162,14 +188,38 @@ static void test_stream_config(IPin *pin) hr = IAMStreamConfig_GetStreamCaps(stream_config, 100000, &format, (BYTE *)&vscc); ok(hr == S_FALSE, "Got hr %#x.\n", hr);
- hr = IAMStreamConfig_GetStreamCaps(stream_config, 0, &format, (BYTE *)&vscc); - ok(hr == S_OK, "Got hr %#x.\n", hr); - ok(IsEqualGUID(&format->majortype, &MEDIATYPE_Video), "Got wrong majortype: %s.\n", - debugstr_guid(&MEDIATYPE_Video)); - ok(IsEqualGUID(&vscc.guid, &FORMAT_VideoInfo) - || IsEqualGUID(&vscc.guid, &FORMAT_VideoInfo2), "Got wrong guid: %s.\n", - debugstr_guid(&vscc.guid)); - FreeMediaType(format); + for (i = 0; i < count; i++) + { + hr = IAMStreamConfig_GetStreamCaps(stream_config, i, &format, (BYTE *)&vscc); + ok(hr == S_OK, "Got hr %#x.\n", hr); + ok(IsEqualGUID(&format->majortype, &MEDIATYPE_Video), "Got wrong majortype: %s.\n", + debugstr_guid(&MEDIATYPE_Video)); + ok(IsEqualGUID(&vscc.guid, &FORMAT_VideoInfo) + || IsEqualGUID(&vscc.guid, &FORMAT_VideoInfo2), "Got wrong guid: %s.\n", + debugstr_guid(&vscc.guid)); + + hr = IAMStreamConfig_SetFormat(stream_config, format); + ok(hr == S_OK, "Got hr %#x.\n", hr); + + hr = IAMStreamConfig_GetFormat(stream_config, &format2); + ok(hr == S_OK, "Got hr %#x.\n", hr); + ok(compare_media_types(format, format2), "Media types didn't match.\n"); + DeleteMediaType(format2); + + hr = IPin_EnumMediaTypes(pin, &enum_media_types); + ok(hr == S_OK, "Got hr %#x.\n", hr); + hr = IEnumMediaTypes_Next(enum_media_types, 1, &format2, NULL); + ok(hr == S_OK, "Got hr %#x.\n", hr); + + /* Which media types will match varies in wine depending on the attached webcam */ + todo_wine_if(compare_media_types(format, format2) == FALSE) + ok(compare_media_types(format, format2), "Media types didn't match.\n"); + + DeleteMediaType(format2); + IEnumMediaTypes_Release(enum_media_types); + + FreeMediaType(format); + }
IAMStreamConfig_Release(stream_config); } @@ -260,6 +310,50 @@ static void test_misc_flags(IBaseFilter *filter) IAMFilterMiscFlags_Release(misc_flags); }
+static int count_media_types(IPin *pin) +{ + IEnumMediaTypes *enum_media_types; + AM_MEDIA_TYPE *pmt; + int count = 0; + + IPin_EnumMediaTypes(pin, &enum_media_types); + while (IEnumMediaTypes_Next(enum_media_types, 1, &pmt, NULL) == S_OK) + { + CoTaskMemFree(pmt); + count++; + } + IEnumMediaTypes_Release(enum_media_types); + + return count; +} + +static void count_pins_media_types(IBaseFilter *filter, int *pin_count, int *media_type_count) +{ + IEnumPins *enum_pins; + IPin *pin; + HRESULT hr; + + *pin_count = 0; + *media_type_count = 0; + + 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) + { + (*pin_count)++; + (*media_type_count) += count_media_types(pin); + } + IPin_Release(pin); + } + + IEnumPins_Release(enum_pins); +} + START_TEST(videocapture) { ICreateDevEnum *dev_enum; @@ -269,6 +363,7 @@ START_TEST(videocapture) WCHAR *name; HRESULT hr; ULONG ref; + int pin_count, media_type_count;
CoInitialize(NULL);
@@ -297,7 +392,19 @@ START_TEST(videocapture) if (hr == S_OK) { test_filter_interfaces(filter); + + count_pins_media_types(filter, &pin_count, &media_type_count); + ok(media_type_count > pin_count, + "Expected media type count (%d) to be greater than pin count (%d)\n", + media_type_count, pin_count); + test_pins(filter); + + count_pins_media_types(filter, &pin_count, &media_type_count); + todo_wine ok(media_type_count == pin_count, + "Expected media type count (%d) to be equal to pin count (%d)\n", + media_type_count, pin_count); +
This is a bit awkward (and, for that matter, doesn't exactly prove
Yes, it is awkward. However, I'm not really sure what would be better for what I am trying to test here.
either of the propositions desired). Moreover, it seems that the tests added to test_stream_config() already prove this.
test_misc_flags(filter); ref = IBaseFilter_Release(filter); ok(!ref, "Got outstanding refcount %d.\n", ref); @@ -305,6 +412,16 @@ START_TEST(videocapture) else skip("Failed to open capture device, hr=%#x.\n", hr);
+ hr = IMoniker_BindToObject(moniker, NULL, NULL, &IID_IBaseFilter, (void**)&filter); + if (hr == S_OK) + { + count_pins_media_types(filter, &pin_count, &media_type_count); + ok(media_type_count > pin_count, + "Expected media type count (%d) to be greater than pin count (%d)\n", + media_type_count, pin_count); + ref = IBaseFilter_Release(filter); + } +
I guess, but I also don't really see a reason why the previous instantiation of a filter would affect this one.
The three tests with count_pins_media_types are to check that releasing pins DOES NOT clear the EnumMediaTypes state, but releasing the filter DOES. TBH, my first assumption had been that that state would be cleared when the pin was released. Perhaps that just proves my naïveté, but it was the test that enlightened me. Also, I have seen states in other areas that persist beyond a particular instantiation, so I didn't want to assume that either.
IMoniker_Release(moniker); }
On 8/28/20 1:33 PM, Jeff Smith wrote:
On Fri, Aug 28, 2020 at 11:34 AM Zebediah Figura <z.figura12(a)gmail.com> wrote:
On 8/28/20 10:52 AM, Jeff Smith wrote:
Signed-off-by: Jeff Smith <whydoubt(a)gmail.com> --- dlls/qcap/tests/videocapture.c | 137 ++++++++++++++++++++++++++++++--- 1 file changed, 127 insertions(+), 10 deletions(-)
diff --git a/dlls/qcap/tests/videocapture.c b/dlls/qcap/tests/videocapture.c index 326601a398..c0fd30aee3 100644 --- a/dlls/qcap/tests/videocapture.c +++ b/dlls/qcap/tests/videocapture.c @@ -23,6 +23,12 @@ #include "wine/test.h" #include "wine/strmbase.h"
+static BOOL compare_media_types(const AM_MEDIA_TYPE *a, const AM_MEDIA_TYPE *b) +{ + return !memcmp(a, b, offsetof(AM_MEDIA_TYPE, pbFormat)) + && !memcmp(a->pbFormat, b->pbFormat, a->cbFormat); +} + #define check_interface(a, b, c) check_interface_(__LINE__, a, b, c) static void check_interface_(unsigned int line, void *iface_ptr, REFIID iid, BOOL supported) { @@ -78,11 +84,13 @@ static void test_media_types(IPin *pin) static void test_stream_config(IPin *pin) { VIDEOINFOHEADER *video_info, *video_info2; - AM_MEDIA_TYPE *format, *format2; + AM_MEDIA_TYPE *format, *format2, *formats[2]; VIDEO_STREAM_CONFIG_CAPS vscc; IAMStreamConfig *stream_config; + IEnumMediaTypes *enum_media_types; LONG depth, compression; - LONG count, size; + LONG count, size, i; + ULONG fetched; HRESULT hr;
hr = IPin_QueryInterface(pin, &IID_IAMStreamConfig, (void **)&stream_config); @@ -93,9 +101,27 @@ static void test_stream_config(IPin *pin) ok(IsEqualGUID(&format->majortype, &MEDIATYPE_Video), "Got wrong majortype: %s.\n", debugstr_guid(&format->majortype));
+ /* Before setting format, multiple media types are enumerated. */ + IPin_EnumMediaTypes(pin, &enum_media_types); + hr = IEnumMediaTypes_Next(enum_media_types, 2, formats, &fetched); + ok(hr == S_OK, "Got hr %#x.\n", hr); + ok(fetched == 2, "Fetched %u.\n", fetched); + DeleteMediaType(formats[0]); + DeleteMediaType(formats[1]); + IEnumMediaTypes_Release(enum_media_types); +
I'm not exactly sure we need to test this, and I'm a little nervous to
Which 'this' do you mean? That >1 media types are enumerated before SetFormat? Or that exactly 1 media type is enumerated after SetFormat? Or that SetFormat is the point at which this change occurs?
That more than one media type is returned.
given how hardware-dependent behaviour can be.
A video capture pin that only supported one media type would break this, but unless we find an exception to the rule, isn't it good to attempt testing the rule?
As far as I see, it doesn't prove anything, and doesn't follow any documented guarantees, so there's no reason to test the rule.
hr = IAMStreamConfig_SetFormat(stream_config, format); ok(hr == S_OK, "Got hr %#x.\n", hr);
+ /* After setting format, a single media type is enumerated. + * This persists until the filter is released. */ + IPin_EnumMediaTypes(pin, &enum_media_types); + hr = IEnumMediaTypes_Next(enum_media_types, 2, formats, &fetched); + todo_wine ok(hr == S_FALSE, "Got hr %#x.\n", hr); + todo_wine ok(fetched == 1, "Fetched %u.\n", fetched); + DeleteMediaType(formats[0]); + IEnumMediaTypes_Release(enum_media_types); + format->majortype = MEDIATYPE_Audio; hr = IAMStreamConfig_SetFormat(stream_config, format); ok(hr == E_FAIL, "Got hr %#x.\n", hr); @@ -162,14 +188,38 @@ static void test_stream_config(IPin *pin) hr = IAMStreamConfig_GetStreamCaps(stream_config, 100000, &format, (BYTE *)&vscc); ok(hr == S_FALSE, "Got hr %#x.\n", hr);
- hr = IAMStreamConfig_GetStreamCaps(stream_config, 0, &format, (BYTE *)&vscc); - ok(hr == S_OK, "Got hr %#x.\n", hr); - ok(IsEqualGUID(&format->majortype, &MEDIATYPE_Video), "Got wrong majortype: %s.\n", - debugstr_guid(&MEDIATYPE_Video)); - ok(IsEqualGUID(&vscc.guid, &FORMAT_VideoInfo) - || IsEqualGUID(&vscc.guid, &FORMAT_VideoInfo2), "Got wrong guid: %s.\n", - debugstr_guid(&vscc.guid)); - FreeMediaType(format); + for (i = 0; i < count; i++) + { + hr = IAMStreamConfig_GetStreamCaps(stream_config, i, &format, (BYTE *)&vscc); + ok(hr == S_OK, "Got hr %#x.\n", hr); + ok(IsEqualGUID(&format->majortype, &MEDIATYPE_Video), "Got wrong majortype: %s.\n", + debugstr_guid(&MEDIATYPE_Video)); + ok(IsEqualGUID(&vscc.guid, &FORMAT_VideoInfo) + || IsEqualGUID(&vscc.guid, &FORMAT_VideoInfo2), "Got wrong guid: %s.\n", + debugstr_guid(&vscc.guid)); + + hr = IAMStreamConfig_SetFormat(stream_config, format); + ok(hr == S_OK, "Got hr %#x.\n", hr); + + hr = IAMStreamConfig_GetFormat(stream_config, &format2); + ok(hr == S_OK, "Got hr %#x.\n", hr); + ok(compare_media_types(format, format2), "Media types didn't match.\n"); + DeleteMediaType(format2); + + hr = IPin_EnumMediaTypes(pin, &enum_media_types); + ok(hr == S_OK, "Got hr %#x.\n", hr); + hr = IEnumMediaTypes_Next(enum_media_types, 1, &format2, NULL); + ok(hr == S_OK, "Got hr %#x.\n", hr); + + /* Which media types will match varies in wine depending on the attached webcam */ + todo_wine_if(compare_media_types(format, format2) == FALSE) + ok(compare_media_types(format, format2), "Media types didn't match.\n"); + + DeleteMediaType(format2); + IEnumMediaTypes_Release(enum_media_types); + + FreeMediaType(format); + }
IAMStreamConfig_Release(stream_config); } @@ -260,6 +310,50 @@ static void test_misc_flags(IBaseFilter *filter) IAMFilterMiscFlags_Release(misc_flags); }
+static int count_media_types(IPin *pin) +{ + IEnumMediaTypes *enum_media_types; + AM_MEDIA_TYPE *pmt; + int count = 0; + + IPin_EnumMediaTypes(pin, &enum_media_types); + while (IEnumMediaTypes_Next(enum_media_types, 1, &pmt, NULL) == S_OK) + { + CoTaskMemFree(pmt); + count++; + } + IEnumMediaTypes_Release(enum_media_types); + + return count; +} + +static void count_pins_media_types(IBaseFilter *filter, int *pin_count, int *media_type_count) +{ + IEnumPins *enum_pins; + IPin *pin; + HRESULT hr; + + *pin_count = 0; + *media_type_count = 0; + + 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) + { + (*pin_count)++; + (*media_type_count) += count_media_types(pin); + } + IPin_Release(pin); + } + + IEnumPins_Release(enum_pins); +} + START_TEST(videocapture) { ICreateDevEnum *dev_enum; @@ -269,6 +363,7 @@ START_TEST(videocapture) WCHAR *name; HRESULT hr; ULONG ref; + int pin_count, media_type_count;
CoInitialize(NULL);
@@ -297,7 +392,19 @@ START_TEST(videocapture) if (hr == S_OK) { test_filter_interfaces(filter); + + count_pins_media_types(filter, &pin_count, &media_type_count); + ok(media_type_count > pin_count, + "Expected media type count (%d) to be greater than pin count (%d)\n", + media_type_count, pin_count); + test_pins(filter); + + count_pins_media_types(filter, &pin_count, &media_type_count); + todo_wine ok(media_type_count == pin_count, + "Expected media type count (%d) to be equal to pin count (%d)\n", + media_type_count, pin_count); +
This is a bit awkward (and, for that matter, doesn't exactly prove
Yes, it is awkward. However, I'm not really sure what would be better for what I am trying to test here.
Well, as stated, I think the tests you've add above already do a good enough job of proving it.
either of the propositions desired). Moreover, it seems that the tests added to test_stream_config() already prove this.
test_misc_flags(filter); ref = IBaseFilter_Release(filter); ok(!ref, "Got outstanding refcount %d.\n", ref); @@ -305,6 +412,16 @@ START_TEST(videocapture) else skip("Failed to open capture device, hr=%#x.\n", hr);
+ hr = IMoniker_BindToObject(moniker, NULL, NULL, &IID_IBaseFilter, (void**)&filter); + if (hr == S_OK) + { + count_pins_media_types(filter, &pin_count, &media_type_count); + ok(media_type_count > pin_count, + "Expected media type count (%d) to be greater than pin count (%d)\n", + media_type_count, pin_count); + ref = IBaseFilter_Release(filter); + } +
I guess, but I also don't really see a reason why the previous instantiation of a filter would affect this one.
The three tests with count_pins_media_types are to check that releasing pins DOES NOT clear the EnumMediaTypes state, but releasing the filter DOES. TBH, my first assumption had been that that state would be cleared when the pin was released. Perhaps that just proves my naïveté, but it was the test that enlightened me. Also, I have seen states in other areas that persist beyond a particular instantiation, so I didn't want to assume that either.
The lifetime of a filter and its pins are pretty well tied together. I'm not necessarily opposed to such a test, but it doesn't seem necessary.
IMoniker_Release(moniker); }
Signed-off-by: Jeff Smith <whydoubt(a)gmail.com> --- dlls/qcap/v4l.c | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/dlls/qcap/v4l.c b/dlls/qcap/v4l.c index 6d67dd19be..c6a5e45831 100644 --- a/dlls/qcap/v4l.c +++ b/dlls/qcap/v4l.c @@ -222,6 +222,9 @@ static HRESULT v4l_device_get_format(struct video_capture_device *iface, AM_MEDI { struct v4l_device *device = v4l_device(iface); + if (!device->current_caps) + return CopyMediaType(mt, &device->caps[0].media_type); + return CopyMediaType(mt, &device->current_caps->media_type); } @@ -406,6 +409,9 @@ static void v4l_device_init_stream(struct video_capture_device *iface) ALLOCATOR_PROPERTIES req_props, ret_props; HRESULT hr; + if (!device->current_caps) + set_caps(device, &device->caps[0]); + req_props.cBuffers = 3; req_props.cbBuffer = device->current_caps->video_info.bmiHeader.biWidth * device->current_caps->video_info.bmiHeader.biHeight; req_props.cbBuffer = (req_props.cbBuffer * device->current_caps->video_info.bmiHeader.biBitCount) / 8; @@ -667,14 +673,6 @@ 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])) - { - 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; - } - device->d.ops = &v4l_device_ops; device->pin = pin; device->state = State_Stopped; @@ -682,9 +680,9 @@ 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); + TRACE("Format: %d bpp - %dx%d.\n", device->caps[0].video_info.bmiHeader.biBitCount, + device->caps[0].video_info.bmiHeader.biWidth, + device->caps[0].video_info.bmiHeader.biHeight); return &device->d; -- 2.23.0
On 8/28/20 10:52 AM, Jeff Smith wrote:
Signed-off-by: Jeff Smith <whydoubt(a)gmail.com> --- dlls/qcap/v4l.c | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-)
diff --git a/dlls/qcap/v4l.c b/dlls/qcap/v4l.c index 6d67dd19be..c6a5e45831 100644 --- a/dlls/qcap/v4l.c +++ b/dlls/qcap/v4l.c @@ -222,6 +222,9 @@ static HRESULT v4l_device_get_format(struct video_capture_device *iface, AM_MEDI { struct v4l_device *device = v4l_device(iface);
+ if (!device->current_caps) + return CopyMediaType(mt, &device->caps[0].media_type); + return CopyMediaType(mt, &device->current_caps->media_type); }
@@ -406,6 +409,9 @@ static void v4l_device_init_stream(struct video_capture_device *iface) ALLOCATOR_PROPERTIES req_props, ret_props; HRESULT hr;
+ if (!device->current_caps) + set_caps(device, &device->caps[0]); +
Explanation for why to do this, either as a comment in the code or as part of a commit message, would be helpful. Patch 4/4 justifies setting current caps to NULL until it's used, but it doesn't justify this hunk. I'm not exactly sure we want to remove error checking here.
req_props.cBuffers = 3; req_props.cbBuffer = device->current_caps->video_info.bmiHeader.biWidth * device->current_caps->video_info.bmiHeader.biHeight; req_props.cbBuffer = (req_props.cbBuffer * device->current_caps->video_info.bmiHeader.biBitCount) / 8; @@ -667,14 +673,6 @@ 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])) - { - 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;
The first error message is redundant, but I think the second should be retained [and probably moved into set_caps()].
- } - device->d.ops = &v4l_device_ops; device->pin = pin; device->state = State_Stopped; @@ -682,9 +680,9 @@ 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); + TRACE("Format: %d bpp - %dx%d.\n", device->caps[0].video_info.bmiHeader.biBitCount, + device->caps[0].video_info.bmiHeader.biWidth, + device->caps[0].video_info.bmiHeader.biHeight);
This trace isn't doing much anymore, especially since we always dump the output of v4l_device_get_format(), so it can probably just be removed, or replaced with a call to strmbase_dump_media_type() in v4l_device_init_stream().
return &device->d;
Signed-off-by: Jeff Smith <whydoubt(a)gmail.com> --- dlls/qcap/qcap_private.h | 1 + dlls/qcap/tests/videocapture.c | 10 +++------- dlls/qcap/v4l.c | 8 ++++++++ dlls/qcap/vfwcapture.c | 11 +++++++++-- 4 files changed, 21 insertions(+), 9 deletions(-) diff --git a/dlls/qcap/qcap_private.h b/dlls/qcap/qcap_private.h index 70a8c85ad4..006e193f3c 100644 --- a/dlls/qcap/qcap_private.h +++ b/dlls/qcap/qcap_private.h @@ -51,6 +51,7 @@ struct video_capture_device_ops HRESULT (*check_format)(struct video_capture_device *device, const AM_MEDIA_TYPE *mt); HRESULT (*set_format)(struct video_capture_device *device, const AM_MEDIA_TYPE *mt); HRESULT (*get_format)(struct video_capture_device *device, AM_MEDIA_TYPE *mt); + BOOL (*is_format_set)(struct video_capture_device *device); HRESULT (*get_caps)(struct video_capture_device *device, LONG index, AM_MEDIA_TYPE **mt, VIDEO_STREAM_CONFIG_CAPS *caps); LONG (*get_caps_count)(struct video_capture_device *device); HRESULT (*get_prop_range)(struct video_capture_device *device, VideoProcAmpProperty property, diff --git a/dlls/qcap/tests/videocapture.c b/dlls/qcap/tests/videocapture.c index c0fd30aee3..ceadf12417 100644 --- a/dlls/qcap/tests/videocapture.c +++ b/dlls/qcap/tests/videocapture.c @@ -117,8 +117,8 @@ static void test_stream_config(IPin *pin) * This persists until the filter is released. */ IPin_EnumMediaTypes(pin, &enum_media_types); hr = IEnumMediaTypes_Next(enum_media_types, 2, formats, &fetched); - todo_wine ok(hr == S_FALSE, "Got hr %#x.\n", hr); - todo_wine ok(fetched == 1, "Fetched %u.\n", fetched); + ok(hr == S_FALSE, "Got hr %#x.\n", hr); + ok(fetched == 1, "Fetched %u.\n", fetched); DeleteMediaType(formats[0]); IEnumMediaTypes_Release(enum_media_types); @@ -210,11 +210,7 @@ static void test_stream_config(IPin *pin) ok(hr == S_OK, "Got hr %#x.\n", hr); hr = IEnumMediaTypes_Next(enum_media_types, 1, &format2, NULL); ok(hr == S_OK, "Got hr %#x.\n", hr); - - /* Which media types will match varies in wine depending on the attached webcam */ - todo_wine_if(compare_media_types(format, format2) == FALSE) ok(compare_media_types(format, format2), "Media types didn't match.\n"); - DeleteMediaType(format2); IEnumMediaTypes_Release(enum_media_types); @@ -401,7 +397,7 @@ START_TEST(videocapture) test_pins(filter); count_pins_media_types(filter, &pin_count, &media_type_count); - todo_wine ok(media_type_count == pin_count, + ok(media_type_count == pin_count, "Expected media type count (%d) to be equal to pin count (%d)\n", media_type_count, pin_count); diff --git a/dlls/qcap/v4l.c b/dlls/qcap/v4l.c index c6a5e45831..10ab26276b 100644 --- a/dlls/qcap/v4l.c +++ b/dlls/qcap/v4l.c @@ -228,6 +228,13 @@ static HRESULT v4l_device_get_format(struct video_capture_device *iface, AM_MEDI return CopyMediaType(mt, &device->current_caps->media_type); } +static BOOL v4l_device_is_format_set(struct video_capture_device *iface) +{ + struct v4l_device *device = v4l_device(iface); + + return !!device->current_caps; +} + static __u32 v4l2_cid_from_qcap_property(VideoProcAmpProperty property) { switch (property) @@ -533,6 +540,7 @@ static const struct video_capture_device_ops v4l_device_ops = .check_format = v4l_device_check_format, .set_format = v4l_device_set_format, .get_format = v4l_device_get_format, + .is_format_set = v4l_device_is_format_set, .get_caps = v4l_device_get_caps, .get_caps_count = v4l_device_get_caps_count, .get_prop_range = v4l_device_get_prop_range, diff --git a/dlls/qcap/vfwcapture.c b/dlls/qcap/vfwcapture.c index 17e56a7ee9..dcaa9aad4f 100644 --- a/dlls/qcap/vfwcapture.c +++ b/dlls/qcap/vfwcapture.c @@ -526,13 +526,20 @@ static HRESULT source_get_media_type(struct strmbase_pin *pin, unsigned int index, AM_MEDIA_TYPE *pmt) { VfwCapture *filter = impl_from_strmbase_pin(pin); + BOOL is_format_set; + unsigned int caps_count; AM_MEDIA_TYPE *vfw_pmt; HRESULT hr; - if (index >= filter->device->ops->get_caps_count(filter->device)) + is_format_set = filter->device->ops->is_format_set(filter->device); + + caps_count = is_format_set ? 1 : filter->device->ops->get_caps_count(filter->device); + if (index >= caps_count) return VFW_S_NO_MORE_ITEMS; - if (SUCCEEDED(hr = filter->device->ops->get_caps(filter->device, index, &vfw_pmt, NULL))) + if (is_format_set) + hr = filter->device->ops->get_format(filter->device, pmt); + else if (SUCCEEDED(hr = filter->device->ops->get_caps(filter->device, index, &vfw_pmt, NULL))) { CopyMediaType(pmt, vfw_pmt); DeleteMediaType(vfw_pmt); -- 2.23.0
On 8/28/20 10:52 AM, Jeff Smith wrote:
Signed-off-by: Jeff Smith <whydoubt(a)gmail.com> --- dlls/qcap/qcap_private.h | 1 + dlls/qcap/tests/videocapture.c | 10 +++------- dlls/qcap/v4l.c | 8 ++++++++ dlls/qcap/vfwcapture.c | 11 +++++++++-- 4 files changed, 21 insertions(+), 9 deletions(-)
diff --git a/dlls/qcap/qcap_private.h b/dlls/qcap/qcap_private.h index 70a8c85ad4..006e193f3c 100644 --- a/dlls/qcap/qcap_private.h +++ b/dlls/qcap/qcap_private.h @@ -51,6 +51,7 @@ struct video_capture_device_ops HRESULT (*check_format)(struct video_capture_device *device, const AM_MEDIA_TYPE *mt); HRESULT (*set_format)(struct video_capture_device *device, const AM_MEDIA_TYPE *mt); HRESULT (*get_format)(struct video_capture_device *device, AM_MEDIA_TYPE *mt); + BOOL (*is_format_set)(struct video_capture_device *device); HRESULT (*get_caps)(struct video_capture_device *device, LONG index, AM_MEDIA_TYPE **mt, VIDEO_STREAM_CONFIG_CAPS *caps); LONG (*get_caps_count)(struct video_capture_device *device); HRESULT (*get_prop_range)(struct video_capture_device *device, VideoProcAmpProperty property, diff --git a/dlls/qcap/tests/videocapture.c b/dlls/qcap/tests/videocapture.c index c0fd30aee3..ceadf12417 100644 --- a/dlls/qcap/tests/videocapture.c +++ b/dlls/qcap/tests/videocapture.c @@ -117,8 +117,8 @@ static void test_stream_config(IPin *pin) * This persists until the filter is released. */ IPin_EnumMediaTypes(pin, &enum_media_types); hr = IEnumMediaTypes_Next(enum_media_types, 2, formats, &fetched); - todo_wine ok(hr == S_FALSE, "Got hr %#x.\n", hr); - todo_wine ok(fetched == 1, "Fetched %u.\n", fetched); + ok(hr == S_FALSE, "Got hr %#x.\n", hr); + ok(fetched == 1, "Fetched %u.\n", fetched); DeleteMediaType(formats[0]); IEnumMediaTypes_Release(enum_media_types);
@@ -210,11 +210,7 @@ static void test_stream_config(IPin *pin) ok(hr == S_OK, "Got hr %#x.\n", hr); hr = IEnumMediaTypes_Next(enum_media_types, 1, &format2, NULL); ok(hr == S_OK, "Got hr %#x.\n", hr); - - /* Which media types will match varies in wine depending on the attached webcam */ - todo_wine_if(compare_media_types(format, format2) == FALSE) ok(compare_media_types(format, format2), "Media types didn't match.\n"); - DeleteMediaType(format2); IEnumMediaTypes_Release(enum_media_types);
@@ -401,7 +397,7 @@ START_TEST(videocapture) test_pins(filter);
count_pins_media_types(filter, &pin_count, &media_type_count); - todo_wine ok(media_type_count == pin_count, + ok(media_type_count == pin_count, "Expected media type count (%d) to be equal to pin count (%d)\n", media_type_count, pin_count);
diff --git a/dlls/qcap/v4l.c b/dlls/qcap/v4l.c index c6a5e45831..10ab26276b 100644 --- a/dlls/qcap/v4l.c +++ b/dlls/qcap/v4l.c @@ -228,6 +228,13 @@ static HRESULT v4l_device_get_format(struct video_capture_device *iface, AM_MEDI return CopyMediaType(mt, &device->current_caps->media_type); }
+static BOOL v4l_device_is_format_set(struct video_capture_device *iface) +{ + struct v4l_device *device = v4l_device(iface); + + return !!device->current_caps; +} + static __u32 v4l2_cid_from_qcap_property(VideoProcAmpProperty property) { switch (property) @@ -533,6 +540,7 @@ static const struct video_capture_device_ops v4l_device_ops = .check_format = v4l_device_check_format, .set_format = v4l_device_set_format, .get_format = v4l_device_get_format, + .is_format_set = v4l_device_is_format_set, .get_caps = v4l_device_get_caps, .get_caps_count = v4l_device_get_caps_count, .get_prop_range = v4l_device_get_prop_range, diff --git a/dlls/qcap/vfwcapture.c b/dlls/qcap/vfwcapture.c index 17e56a7ee9..dcaa9aad4f 100644 --- a/dlls/qcap/vfwcapture.c +++ b/dlls/qcap/vfwcapture.c @@ -526,13 +526,20 @@ static HRESULT source_get_media_type(struct strmbase_pin *pin, unsigned int index, AM_MEDIA_TYPE *pmt) { VfwCapture *filter = impl_from_strmbase_pin(pin); + BOOL is_format_set; + unsigned int caps_count; AM_MEDIA_TYPE *vfw_pmt; HRESULT hr;
- if (index >= filter->device->ops->get_caps_count(filter->device)) + is_format_set = filter->device->ops->is_format_set(filter->device); + + caps_count = is_format_set ? 1 : filter->device->ops->get_caps_count(filter->device); + if (index >= caps_count) return VFW_S_NO_MORE_ITEMS;
- if (SUCCEEDED(hr = filter->device->ops->get_caps(filter->device, index, &vfw_pmt, NULL))) + if (is_format_set) + hr = filter->device->ops->get_format(filter->device, pmt); + else if (SUCCEEDED(hr = filter->device->ops->get_caps(filter->device, index, &vfw_pmt, NULL))) { CopyMediaType(pmt, vfw_pmt); DeleteMediaType(vfw_pmt);
I think I'd prefer to either introduce a get_media_type callback, or move all of the logic into the vfwcapture.c side.
participants (2)
-
Jeff Smith -
Zebediah Figura