Signed-off-by: Zebediah Figura z.figura12@gmail.com --- dlls/qcap/filewriter.c | 34 +++++++ dlls/qcap/tests/filewriter.c | 179 ++++++++++++++++++++++++++++++++++- 2 files changed, 212 insertions(+), 1 deletion(-)
diff --git a/dlls/qcap/filewriter.c b/dlls/qcap/filewriter.c index 0b7c1109e5..2b1d219a08 100644 --- a/dlls/qcap/filewriter.c +++ b/dlls/qcap/filewriter.c @@ -18,6 +18,7 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */
+#define COBJMACROS #include "dshow.h" #include "qcap_main.h" #include "wine/debug.h" @@ -27,6 +28,31 @@ WINE_DEFAULT_DEBUG_CHANNEL(qcap); struct file_writer { struct strmbase_filter filter; + + struct strmbase_sink sink; +}; + +static inline struct file_writer *impl_from_strmbase_pin(struct strmbase_pin *iface) +{ + return CONTAINING_RECORD(iface, struct file_writer, sink.pin); +} + +static HRESULT file_writer_sink_query_interface(struct strmbase_pin *iface, REFIID iid, void **out) +{ + struct file_writer *filter = impl_from_strmbase_pin(iface); + + if (IsEqualGUID(iid, &IID_IMemInputPin)) + *out = &filter->sink.IMemInputPin_iface; + else + return E_NOINTERFACE; + + IUnknown_AddRef((IUnknown *)*out); + return S_OK; +} + +static const struct strmbase_sink_ops sink_ops = +{ + .base.pin_query_interface = file_writer_sink_query_interface, };
static inline struct file_writer *impl_from_strmbase_filter(struct strmbase_filter *iface) @@ -36,6 +62,10 @@ static inline struct file_writer *impl_from_strmbase_filter(struct strmbase_filt
static struct strmbase_pin *file_writer_get_pin(struct strmbase_filter *iface, unsigned int index) { + struct file_writer *filter = impl_from_strmbase_filter(iface); + + if (!index) + return &filter->sink.pin; return NULL; }
@@ -43,6 +73,7 @@ static void file_writer_destroy(struct strmbase_filter *iface) { struct file_writer *filter = impl_from_strmbase_filter(iface);
+ strmbase_sink_cleanup(&filter->sink); strmbase_filter_cleanup(&filter->filter); heap_free(filter); } @@ -55,6 +86,7 @@ static struct strmbase_filter_ops filter_ops =
HRESULT file_writer_create(IUnknown *outer, IUnknown **out) { + static const WCHAR sink_name[] = {'i','n',0}; struct file_writer *object;
if (!(object = heap_alloc_zero(sizeof(*object)))) @@ -62,6 +94,8 @@ HRESULT file_writer_create(IUnknown *outer, IUnknown **out)
strmbase_filter_init(&object->filter, outer, &CLSID_FileWriter, &filter_ops);
+ strmbase_sink_init(&object->sink, &object->filter, sink_name, &sink_ops, NULL); + TRACE("Created file writer %p.\n", object); *out = &object->filter.IUnknown_inner; return S_OK; diff --git a/dlls/qcap/tests/filewriter.c b/dlls/qcap/tests/filewriter.c index 9302b07468..8201a4d0c7 100644 --- a/dlls/qcap/tests/filewriter.c +++ b/dlls/qcap/tests/filewriter.c @@ -56,6 +56,8 @@ static void check_interface_(unsigned int line, void *iface_ptr, REFIID iid, BOO static void test_interfaces(void) { IBaseFilter *filter = create_file_writer(); + ULONG ref; + IPin *pin;
todo_wine check_interface(filter, &IID_IAMFilterMiscFlags, TRUE); check_interface(filter, &IID_IBaseFilter, TRUE); @@ -78,7 +80,20 @@ static void test_interfaces(void) check_interface(filter, &IID_IReferenceClock, FALSE); check_interface(filter, &IID_IVideoWindow, FALSE);
- IBaseFilter_Release(filter); + IBaseFilter_FindPin(filter, L"in", &pin); + + check_interface(pin, &IID_IMemInputPin, TRUE); + check_interface(pin, &IID_IPin, TRUE); + todo_wine check_interface(pin, &IID_IQualityControl, TRUE); + check_interface(pin, &IID_IUnknown, TRUE); + + check_interface(pin, &IID_IKsPropertySet, FALSE); + check_interface(pin, &IID_IMediaPosition, FALSE); + check_interface(pin, &IID_IMediaSeeking, FALSE); + + IPin_Release(pin); + ref = IBaseFilter_Release(filter); + ok(!ref, "Got unexpected refcount %d.\n", ref); }
static const GUID test_iid = {0x33333333}; @@ -175,12 +190,174 @@ static void test_aggregation(void) ok(outer_ref == 1, "Got unexpected refcount %d.\n", outer_ref); }
+static void test_enum_pins(void) +{ + IBaseFilter *filter = create_file_writer(); + IEnumPins *enum1, *enum2; + ULONG count, ref; + IPin *pins[2]; + HRESULT hr; + + ref = get_refcount(filter); + ok(ref == 1, "Got unexpected refcount %d.\n", ref); + + hr = IBaseFilter_EnumPins(filter, NULL); + ok(hr == E_POINTER, "Got hr %#x.\n", hr); + + hr = IBaseFilter_EnumPins(filter, &enum1); + ok(hr == S_OK, "Got hr %#x.\n", hr); + ref = get_refcount(filter); + ok(ref == 2, "Got unexpected refcount %d.\n", ref); + ref = get_refcount(enum1); + ok(ref == 1, "Got unexpected refcount %d.\n", ref); + + hr = IEnumPins_Next(enum1, 1, NULL, NULL); + ok(hr == E_POINTER, "Got hr %#x.\n", hr); + + hr = IEnumPins_Next(enum1, 1, pins, NULL); + ok(hr == S_OK, "Got hr %#x.\n", hr); + ref = get_refcount(filter); + ok(ref == 3, "Got unexpected refcount %d.\n", ref); + ref = get_refcount(pins[0]); + ok(ref == 3, "Got unexpected refcount %d.\n", ref); + ref = get_refcount(enum1); + ok(ref == 1, "Got unexpected refcount %d.\n", ref); + IPin_Release(pins[0]); + ref = get_refcount(filter); + ok(ref == 2, "Got unexpected refcount %d.\n", ref); + + hr = IEnumPins_Next(enum1, 1, pins, NULL); + ok(hr == S_FALSE, "Got hr %#x.\n", hr); + + hr = IEnumPins_Reset(enum1); + ok(hr == S_OK, "Got hr %#x.\n", hr); + + hr = IEnumPins_Next(enum1, 1, pins, &count); + ok(hr == S_OK, "Got hr %#x.\n", hr); + ok(count == 1, "Got count %u.\n", count); + IPin_Release(pins[0]); + + hr = IEnumPins_Next(enum1, 1, pins, &count); + ok(hr == S_FALSE, "Got hr %#x.\n", hr); + ok(!count, "Got count %u.\n", count); + + hr = IEnumPins_Reset(enum1); + ok(hr == S_OK, "Got hr %#x.\n", hr); + + hr = IEnumPins_Next(enum1, 2, pins, NULL); + ok(hr == E_INVALIDARG, "Got hr %#x.\n", hr); + + hr = IEnumPins_Next(enum1, 2, pins, &count); + ok(hr == S_FALSE, "Got hr %#x.\n", hr); + ok(count == 1, "Got count %u.\n", count); + IPin_Release(pins[0]); + + hr = IEnumPins_Reset(enum1); + ok(hr == S_OK, "Got hr %#x.\n", hr); + + hr = IEnumPins_Clone(enum1, &enum2); + ok(hr == S_OK, "Got hr %#x.\n", hr); + + hr = IEnumPins_Skip(enum1, 2); + ok(hr == S_FALSE, "Got hr %#x.\n", hr); + + hr = IEnumPins_Skip(enum1, 1); + ok(hr == S_OK, "Got hr %#x.\n", hr); + + hr = IEnumPins_Skip(enum1, 1); + ok(hr == S_FALSE, "Got hr %#x.\n", hr); + + hr = IEnumPins_Next(enum1, 1, pins, NULL); + ok(hr == S_FALSE, "Got hr %#x.\n", hr); + + hr = IEnumPins_Next(enum2, 1, pins, NULL); + ok(hr == S_OK, "Got hr %#x.\n", hr); + IPin_Release(pins[0]); + + IEnumPins_Release(enum2); + IEnumPins_Release(enum1); + ref = IBaseFilter_Release(filter); + ok(!ref, "Got outstanding refcount %d.\n", ref); +} + +static void test_find_pin(void) +{ + IBaseFilter *filter = create_file_writer(); + IEnumPins *enum_pins; + IPin *pin, *pin2; + HRESULT hr; + ULONG ref; + + hr = IBaseFilter_EnumPins(filter, &enum_pins); + ok(hr == S_OK, "Got hr %#x.\n", hr); + + hr = IBaseFilter_FindPin(filter, L"in", &pin); + ok(hr == S_OK, "Got hr %#x.\n", hr); + hr = IEnumPins_Next(enum_pins, 1, &pin2, NULL); + ok(hr == S_OK, "Got hr %#x.\n", hr); + ok(pin2 == pin, "Expected pin %p, got %p.\n", pin, pin2); + IPin_Release(pin2); + IPin_Release(pin); + + IEnumPins_Release(enum_pins); + ref = IBaseFilter_Release(filter); + ok(!ref, "Got outstanding refcount %d.\n", ref); +} + +static void test_pin_info(void) +{ + IBaseFilter *filter = create_file_writer(); + PIN_DIRECTION dir; + PIN_INFO info; + HRESULT hr; + WCHAR *id; + ULONG ref; + IPin *pin; + + hr = IBaseFilter_FindPin(filter, L"in", &pin); + ok(hr == S_OK, "Got hr %#x.\n", hr); + ref = get_refcount(filter); + ok(ref == 2, "Got unexpected refcount %d.\n", ref); + ref = get_refcount(pin); + ok(ref == 2, "Got unexpected refcount %d.\n", ref); + + hr = IPin_QueryPinInfo(pin, &info); + ok(hr == S_OK, "Got hr %#x.\n", hr); + ok(info.pFilter == filter, "Expected filter %p, got %p.\n", filter, info.pFilter); + ok(info.dir == PINDIR_INPUT, "Got direction %d.\n", info.dir); + ok(!wcscmp(info.achName, L"in"), "Got name %s.\n", wine_dbgstr_w(info.achName)); + ref = get_refcount(filter); + ok(ref == 3, "Got unexpected refcount %d.\n", ref); + ref = get_refcount(pin); + ok(ref == 3, "Got unexpected refcount %d.\n", ref); + IBaseFilter_Release(info.pFilter); + + hr = IPin_QueryDirection(pin, &dir); + ok(hr == S_OK, "Got hr %#x.\n", hr); + ok(dir == PINDIR_INPUT, "Got direction %d.\n", dir); + + hr = IPin_QueryId(pin, &id); + ok(hr == S_OK, "Got hr %#x.\n", hr); + ok(!wcscmp(id, L"in"), "Got id %s.\n", wine_dbgstr_w(id)); + CoTaskMemFree(id); + + hr = IPin_QueryInternalConnections(pin, NULL, NULL); + ok(hr == E_NOTIMPL, "Got hr %#x.\n", hr); + + IPin_Release(pin); + ref = IBaseFilter_Release(filter); + ok(!ref, "Got outstanding refcount %d.\n", ref); +} + START_TEST(filewriter) { CoInitializeEx(NULL, COINIT_MULTITHREADED);
test_interfaces(); test_aggregation(); + test_enum_pins(); + test_find_pin(); + test_pin_info();
CoUninitialize(); }