[PATCH v2 12/13] qedit/tests: Add tests for get_Filter and put_Filter with a custom filter.

Gabriel Ivăncescu gabrielopcode at gmail.com
Thu Apr 16 10:25:04 CDT 2020


Signed-off-by: Gabriel Ivăncescu <gabrielopcode at gmail.com>
---
 dlls/qedit/tests/mediadet.c | 965 ++++++++++++++++++++++++++++++++++++
 1 file changed, 965 insertions(+)

diff --git a/dlls/qedit/tests/mediadet.c b/dlls/qedit/tests/mediadet.c
index 596171b..10127cf 100644
--- a/dlls/qedit/tests/mediadet.c
+++ b/dlls/qedit/tests/mediadet.c
@@ -24,6 +24,7 @@
 #include "ole2.h"
 #include "vfwmsgs.h"
 #include "uuids.h"
+#include "dshow.h"
 #include "wine/test.h"
 #include "qedit.h"
 #include "control.h"
@@ -71,6 +72,867 @@ static const IUnknownVtbl outer_vtbl =
 
 static IUnknown test_outer = {&outer_vtbl};
 
+struct testfilter
+{
+    IBaseFilter IBaseFilter_iface;
+    IMediaSeeking IMediaSeeking_iface;
+    IMediaPosition IMediaPosition_iface;
+    LONG ref;
+    WCHAR *name;
+    IFilterGraph *graph;
+    FILTER_STATE state;
+    double rate;
+
+    IEnumPins IEnumPins_iface;
+    UINT enum_idx;
+
+    IPin IPin_iface;
+    IPin *peer;
+
+    IEnumMediaTypes IEnumMediaTypes_iface;
+    UINT mt_enum_idx;
+};
+
+static inline struct testfilter *impl_from_IEnumMediaTypes(IEnumMediaTypes *iface)
+{
+    return CONTAINING_RECORD(iface, struct testfilter, IEnumMediaTypes_iface);
+}
+
+static HRESULT WINAPI testenummt_QueryInterface(IEnumMediaTypes *iface, REFIID iid, void **out)
+{
+    *out = NULL;
+    return E_NOINTERFACE;
+}
+
+static ULONG WINAPI testenummt_AddRef(IEnumMediaTypes *iface)
+{
+    struct testfilter *filter = impl_from_IEnumMediaTypes(iface);
+    return IBaseFilter_AddRef(&filter->IBaseFilter_iface);
+}
+
+static ULONG WINAPI testenummt_Release(IEnumMediaTypes *iface)
+{
+    struct testfilter *filter = impl_from_IEnumMediaTypes(iface);
+    return IBaseFilter_Release(&filter->IBaseFilter_iface);
+}
+
+static HRESULT WINAPI testenummt_Next(IEnumMediaTypes *iface, ULONG count, AM_MEDIA_TYPE **out, ULONG *fetched)
+{
+    struct testfilter *filter = impl_from_IEnumMediaTypes(iface);
+    ULONG i = 0;
+
+    if (count && !filter->mt_enum_idx)
+    {
+        static const VIDEOINFOHEADER source_format =
+        {
+            .bmiHeader.biSize = sizeof(BITMAPINFOHEADER),
+            .bmiHeader.biWidth = 640,
+            .bmiHeader.biHeight = 480,
+            .bmiHeader.biPlanes = 1,
+            .bmiHeader.biBitCount = 24,
+            .bmiHeader.biCompression = BI_RGB,
+            .bmiHeader.biSizeImage = 640 * 480 * 3
+        };
+        AM_MEDIA_TYPE source_type =
+        {
+            .majortype = MEDIATYPE_Video,
+            .subtype = MEDIASUBTYPE_RGB24,
+            .bFixedSizeSamples = TRUE,
+            .lSampleSize = source_format.bmiHeader.biSizeImage,
+            .formattype = FORMAT_VideoInfo,
+            .cbFormat = sizeof(source_format)
+        };
+
+        source_type.pbFormat = CoTaskMemAlloc(sizeof(source_format));
+        memcpy(source_type.pbFormat, &source_format, sizeof(source_format));
+
+        out[i] = CoTaskMemAlloc(sizeof(*out[i]));
+        *out[i++] = source_type;
+    }
+
+    if (fetched) *fetched = i;
+    filter->mt_enum_idx += i;
+
+    return (i == count) ? S_OK : S_FALSE;
+}
+
+static HRESULT WINAPI testenummt_Skip(IEnumMediaTypes *iface, ULONG count)
+{
+    ok(0, "Unexpected call.\n");
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI testenummt_Reset(IEnumMediaTypes *iface)
+{
+    struct testfilter *filter = impl_from_IEnumMediaTypes(iface);
+
+    filter->mt_enum_idx = 0;
+    return S_OK;
+}
+
+static HRESULT WINAPI testenummt_Clone(IEnumMediaTypes *iface, IEnumMediaTypes **out)
+{
+    ok(0, "Unexpected call.\n");
+    return E_NOTIMPL;
+}
+
+static const IEnumMediaTypesVtbl testenummt_vtbl =
+{
+    testenummt_QueryInterface,
+    testenummt_AddRef,
+    testenummt_Release,
+    testenummt_Next,
+    testenummt_Skip,
+    testenummt_Reset,
+    testenummt_Clone
+};
+
+static inline struct testfilter *impl_from_IPin(IPin *iface)
+{
+    return CONTAINING_RECORD(iface, struct testfilter, IPin_iface);
+}
+
+static HRESULT WINAPI testpin_QueryInterface(IPin *iface, REFIID iid, void **out)
+{
+    struct testfilter *filter = impl_from_IPin(iface);
+
+    if (IsEqualGUID(iid, &IID_IUnknown) || IsEqualGUID(iid, &IID_IPin))
+        *out = &filter->IPin_iface;
+    else if (IsEqualGUID(iid, &IID_IMediaSeeking))
+        *out = &filter->IMediaSeeking_iface;
+    else if (IsEqualGUID(iid, &IID_IMediaPosition))
+        *out = &filter->IMediaPosition_iface;
+    else
+    {
+        *out = NULL;
+        return E_NOINTERFACE;
+    }
+
+    IUnknown_AddRef((IUnknown *)*out);
+    return S_OK;
+}
+
+static ULONG WINAPI testpin_AddRef(IPin *iface)
+{
+    struct testfilter *filter = impl_from_IPin(iface);
+    return IBaseFilter_AddRef(&filter->IBaseFilter_iface);
+}
+
+static ULONG WINAPI testpin_Release(IPin *iface)
+{
+    struct testfilter *filter = impl_from_IPin(iface);
+    return IBaseFilter_Release(&filter->IBaseFilter_iface);
+}
+
+static HRESULT WINAPI testpin_Connect(IPin *iface, IPin *peer, const AM_MEDIA_TYPE *mt)
+{
+    struct testfilter *filter = impl_from_IPin(iface);
+    IEnumMediaTypes *enummt;
+    AM_MEDIA_TYPE *pmt;
+    HRESULT hr;
+
+    ok(!mt, "Got media type %p\n", mt);
+
+    IPin_EnumMediaTypes(iface, &enummt);
+    IEnumMediaTypes_Next(enummt, 1, &pmt, NULL);
+    IEnumMediaTypes_Reset(enummt);
+    IEnumMediaTypes_Release(enummt);
+
+    hr = IPin_ReceiveConnection(peer, &filter->IPin_iface, pmt);
+    CoTaskMemFree(pmt->pbFormat);
+    CoTaskMemFree(pmt);
+    if (FAILED(hr))
+        return hr;
+
+    filter->peer = peer;
+    IPin_AddRef(peer);
+    return S_OK;
+}
+
+static HRESULT WINAPI testpin_ReceiveConnection(IPin *iface, IPin *peer, const AM_MEDIA_TYPE *mt)
+{
+    ok(0, "Unexpected call.\n");
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI testpin_Disconnect(IPin *iface)
+{
+    struct testfilter *filter = impl_from_IPin(iface);
+
+    if (filter->peer)
+    {
+        IPin_Release(filter->peer);
+        filter->peer = NULL;
+    }
+    return S_OK;
+}
+
+static HRESULT WINAPI testpin_ConnectedTo(IPin *iface, IPin **peer)
+{
+    struct testfilter *filter = impl_from_IPin(iface);
+
+    if (!filter->peer)
+        return VFW_E_NOT_CONNECTED;
+
+    *peer = filter->peer;
+    IPin_AddRef(*peer);
+    return S_OK;
+}
+
+static HRESULT WINAPI testpin_ConnectionMediaType(IPin *iface, AM_MEDIA_TYPE *mt)
+{
+    ok(0, "Unexpected call.\n");
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI testpin_QueryPinInfo(IPin *iface, PIN_INFO *info)
+{
+    struct testfilter *filter = impl_from_IPin(iface);
+
+    info->pFilter = &filter->IBaseFilter_iface;
+    IBaseFilter_AddRef(&filter->IBaseFilter_iface);
+    info->dir = PINDIR_OUTPUT;
+    wcscpy(info->achName, L"testpin");
+    return S_OK;
+}
+
+static HRESULT WINAPI testpin_QueryDirection(IPin *iface, PIN_DIRECTION *dir)
+{
+    *dir = PINDIR_OUTPUT;
+    return S_OK;
+}
+
+static HRESULT WINAPI testpin_QueryId(IPin *iface, WCHAR **id)
+{
+    if (!(*id = CoTaskMemAlloc(sizeof(L"deadbeef"))))
+        return E_OUTOFMEMORY;
+
+    wcscpy(*id, L"deadbeef");
+    return S_OK;
+}
+
+static HRESULT WINAPI testpin_QueryAccept(IPin *iface, const AM_MEDIA_TYPE *mt)
+{
+    ok(0, "Unexpected call.\n");
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI testpin_EnumMediaTypes(IPin *iface, IEnumMediaTypes **out)
+{
+    struct testfilter *filter = impl_from_IPin(iface);
+
+    *out = &filter->IEnumMediaTypes_iface;
+    IEnumMediaTypes_AddRef(*out);
+    filter->mt_enum_idx = 0;
+    return S_OK;
+}
+
+static HRESULT WINAPI testpin_QueryInternalConnections(IPin *iface, IPin **out, ULONG *count)
+{
+    *count = 0;
+    return S_OK;
+}
+
+static HRESULT WINAPI testpin_EndOfStream(IPin *iface)
+{
+    ok(0, "Unexpected call.\n");
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI testpin_BeginFlush(IPin *iface)
+{
+    ok(0, "Unexpected call.\n");
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI testpin_EndFlush(IPin *iface)
+{
+    ok(0, "Unexpected call.\n");
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI testpin_NewSegment(IPin *iface, REFERENCE_TIME start, REFERENCE_TIME stop, double rate)
+{
+    ok(0, "Unexpected call.\n");
+    return E_NOTIMPL;
+}
+
+static const IPinVtbl testpin_vtbl =
+{
+    testpin_QueryInterface,
+    testpin_AddRef,
+    testpin_Release,
+    testpin_Connect,
+    testpin_ReceiveConnection,
+    testpin_Disconnect,
+    testpin_ConnectedTo,
+    testpin_ConnectionMediaType,
+    testpin_QueryPinInfo,
+    testpin_QueryDirection,
+    testpin_QueryId,
+    testpin_QueryAccept,
+    testpin_EnumMediaTypes,
+    testpin_QueryInternalConnections,
+    testpin_EndOfStream,
+    testpin_BeginFlush,
+    testpin_EndFlush,
+    testpin_NewSegment
+};
+
+static inline struct testfilter *impl_from_IEnumPins(IEnumPins *iface)
+{
+    return CONTAINING_RECORD(iface, struct testfilter, IEnumPins_iface);
+}
+
+static HRESULT WINAPI testenumpins_QueryInterface(IEnumPins *iface, REFIID iid, void **out)
+{
+    ok(0, "Unexpected call with iid %s.\n", wine_dbgstr_guid(iid));
+    return E_NOINTERFACE;
+}
+
+static ULONG WINAPI testenumpins_AddRef(IEnumPins *iface)
+{
+    struct testfilter *filter = impl_from_IEnumPins(iface);
+    return IBaseFilter_AddRef(&filter->IBaseFilter_iface);
+}
+
+static ULONG WINAPI testenumpins_Release(IEnumPins *iface)
+{
+    struct testfilter *filter = impl_from_IEnumPins(iface);
+    return IBaseFilter_Release(&filter->IBaseFilter_iface);
+}
+
+static HRESULT WINAPI testenumpins_Next(IEnumPins *iface, ULONG count, IPin **out, ULONG *fetched)
+{
+    struct testfilter *filter = impl_from_IEnumPins(iface);
+    ULONG i = 0;
+
+    /* Only report one pin */
+    if (count && !filter->enum_idx)
+    {
+        out[i] = &filter->IPin_iface;
+        IPin_AddRef(out[i++]);
+    }
+
+    if (fetched) *fetched = i;
+    filter->enum_idx += i;
+
+    return (i == count) ? S_OK : S_FALSE;
+}
+
+static HRESULT WINAPI testenumpins_Skip(IEnumPins *iface, ULONG count)
+{
+    ok(0, "Unexpected call.\n");
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI testenumpins_Reset(IEnumPins *iface)
+{
+    struct testfilter *filter = impl_from_IEnumPins(iface);
+
+    filter->enum_idx = 0;
+    return S_OK;
+}
+
+static HRESULT WINAPI testenumpins_Clone(IEnumPins *iface, IEnumPins **out)
+{
+    ok(0, "Unexpected call.\n");
+    return E_NOTIMPL;
+}
+
+static const IEnumPinsVtbl testenumpins_vtbl =
+{
+    testenumpins_QueryInterface,
+    testenumpins_AddRef,
+    testenumpins_Release,
+    testenumpins_Next,
+    testenumpins_Skip,
+    testenumpins_Reset,
+    testenumpins_Clone
+};
+
+static inline struct testfilter *impl_from_IMediaSeeking(IMediaSeeking *iface)
+{
+    return CONTAINING_RECORD(iface, struct testfilter, IMediaSeeking_iface);
+}
+
+static HRESULT WINAPI testseek_QueryInterface(IMediaSeeking *iface, REFIID iid, void **out)
+{
+    struct testfilter *filter = impl_from_IMediaSeeking(iface);
+    return IBaseFilter_QueryInterface(&filter->IBaseFilter_iface, iid, out);
+}
+
+static ULONG WINAPI testseek_AddRef(IMediaSeeking *iface)
+{
+    struct testfilter *filter = impl_from_IMediaSeeking(iface);
+    return IBaseFilter_AddRef(&filter->IBaseFilter_iface);
+}
+
+static ULONG WINAPI testseek_Release(IMediaSeeking *iface)
+{
+    struct testfilter *filter = impl_from_IMediaSeeking(iface);
+    return IBaseFilter_Release(&filter->IBaseFilter_iface);
+}
+
+static HRESULT WINAPI testseek_GetCapabilities(IMediaSeeking *iface, DWORD *caps)
+{
+    *caps = AM_SEEKING_CanGetDuration;
+    return S_OK;
+}
+
+static HRESULT WINAPI testseek_CheckCapabilities(IMediaSeeking *iface, DWORD *caps)
+{
+    ok(0, "Unexpected call.\n");
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI testseek_IsFormatSupported(IMediaSeeking *iface, const GUID *format)
+{
+    return IsEqualGUID(format, &TIME_FORMAT_MEDIA_TIME) ? S_OK : S_FALSE;
+}
+
+static HRESULT WINAPI testseek_QueryPreferredFormat(IMediaSeeking *iface, GUID *format)
+{
+    *format = TIME_FORMAT_MEDIA_TIME;
+    return S_OK;
+}
+
+static HRESULT WINAPI testseek_GetTimeFormat(IMediaSeeking *iface, GUID *format)
+{
+    *format = TIME_FORMAT_MEDIA_TIME;
+    return S_OK;
+}
+
+static HRESULT WINAPI testseek_IsUsingTimeFormat(IMediaSeeking *iface, const GUID *format)
+{
+    return IsEqualGUID(format, &TIME_FORMAT_MEDIA_TIME) ? S_OK : S_FALSE;
+}
+
+static HRESULT WINAPI testseek_SetTimeFormat(IMediaSeeking *iface, const GUID *format)
+{
+    return IsEqualGUID(format, &TIME_FORMAT_MEDIA_TIME) ? S_OK : E_INVALIDARG;
+}
+
+static HRESULT WINAPI testseek_GetDuration(IMediaSeeking *iface, LONGLONG *duration)
+{
+    *duration = 42000000;
+    return S_OK;
+}
+
+static HRESULT WINAPI testseek_GetStopPosition(IMediaSeeking *iface, LONGLONG *stop)
+{
+    *stop = 42000000;
+    return S_OK;
+}
+
+static HRESULT WINAPI testseek_GetCurrentPosition(IMediaSeeking *iface, LONGLONG *current)
+{
+    *current = 0;
+    return S_OK;
+}
+
+static HRESULT WINAPI testseek_ConvertTimeFormat(IMediaSeeking *iface, LONGLONG *target,
+    const GUID *target_format, LONGLONG source, const GUID *source_format)
+{
+    ok(0, "Unexpected call.\n");
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI testseek_SetPositions(IMediaSeeking *iface, LONGLONG *current,
+    DWORD current_flags, LONGLONG *stop, DWORD stop_flags)
+{
+    *current = 0;
+    *stop = 42000000;
+    return S_OK;
+}
+
+static HRESULT WINAPI testseek_GetPositions(IMediaSeeking *iface, LONGLONG *current, LONGLONG *stop)
+{
+    *current = 0;
+    *stop = 42000000;
+    return S_OK;
+}
+
+static HRESULT WINAPI testseek_GetAvailable(IMediaSeeking *iface, LONGLONG *earliest, LONGLONG *latest)
+{
+    *earliest = 0;
+    *latest = 42000000;
+    return S_OK;
+}
+
+static HRESULT WINAPI testseek_SetRate(IMediaSeeking *iface, double rate)
+{
+    struct testfilter *filter = impl_from_IMediaSeeking(iface);
+
+    filter->rate = rate;
+    return S_OK;
+}
+
+static HRESULT WINAPI testseek_GetRate(IMediaSeeking *iface, double *rate)
+{
+    struct testfilter *filter = impl_from_IMediaSeeking(iface);
+
+    *rate = filter->rate;
+    return S_OK;
+}
+
+static HRESULT WINAPI testseek_GetPreroll(IMediaSeeking *iface, LONGLONG *preroll)
+{
+    *preroll = 0;
+    return S_OK;
+}
+
+static const IMediaSeekingVtbl testseek_vtbl =
+{
+    testseek_QueryInterface,
+    testseek_AddRef,
+    testseek_Release,
+    testseek_GetCapabilities,
+    testseek_CheckCapabilities,
+    testseek_IsFormatSupported,
+    testseek_QueryPreferredFormat,
+    testseek_GetTimeFormat,
+    testseek_IsUsingTimeFormat,
+    testseek_SetTimeFormat,
+    testseek_GetDuration,
+    testseek_GetStopPosition,
+    testseek_GetCurrentPosition,
+    testseek_ConvertTimeFormat,
+    testseek_SetPositions,
+    testseek_GetPositions,
+    testseek_GetAvailable,
+    testseek_SetRate,
+    testseek_GetRate,
+    testseek_GetPreroll
+};
+
+static inline struct testfilter *impl_from_IMediaPosition(IMediaPosition *iface)
+{
+    return CONTAINING_RECORD(iface, struct testfilter, IMediaPosition_iface);
+}
+
+static HRESULT WINAPI testpos_QueryInterface(IMediaPosition *iface, REFIID iid, void **out)
+{
+    struct testfilter *filter = impl_from_IMediaPosition(iface);
+    return IBaseFilter_QueryInterface(&filter->IBaseFilter_iface, iid, out);
+}
+
+static ULONG WINAPI testpos_AddRef(IMediaPosition *iface)
+{
+    struct testfilter *filter = impl_from_IMediaPosition(iface);
+    return IBaseFilter_AddRef(&filter->IBaseFilter_iface);
+}
+
+static ULONG WINAPI testpos_Release(IMediaPosition *iface)
+{
+    struct testfilter *filter = impl_from_IMediaPosition(iface);
+    return IBaseFilter_Release(&filter->IBaseFilter_iface);
+}
+
+static HRESULT WINAPI testpos_GetTypeInfoCount(IMediaPosition *iface, UINT *pctinfo)
+{
+    ok(0, "Unexpected call.\n");
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI testpos_GetTypeInfo(IMediaPosition *iface, UINT iTInfo, LCID lcid, ITypeInfo **ppTInfo)
+{
+    ok(0, "Unexpected call.\n");
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI testpos_GetIDsOfNames(IMediaPosition *iface, REFIID riid, LPOLESTR *rgszNames,
+    UINT cNames, LCID lcid, DISPID *rgDispId)
+{
+    ok(0, "Unexpected call.\n");
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI testpos_Invoke(IMediaPosition *iface, DISPID dispIdMember, REFIID riid, LCID lcid,
+    WORD wFlags, DISPPARAMS *pDispParams, VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr)
+{
+    ok(0, "Unexpected call.\n");
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI testpos_get_Duration(IMediaPosition *iface, REFTIME *duration)
+{
+    *duration = 4.2;
+    return S_OK;
+}
+
+static HRESULT WINAPI testpos_put_CurrentPosition(IMediaPosition *iface, REFTIME current)
+{
+    return S_OK;
+}
+
+static HRESULT WINAPI testpos_get_CurrentPosition(IMediaPosition *iface, REFTIME *current)
+{
+    *current = 0.0;
+    return S_OK;
+}
+
+static HRESULT WINAPI testpos_get_StopTime(IMediaPosition *iface, REFTIME *stop)
+{
+    *stop = 4.2;
+    return S_OK;
+}
+
+static HRESULT WINAPI testpos_put_StopTime(IMediaPosition *iface, REFTIME stop)
+{
+    return S_OK;
+}
+
+static HRESULT WINAPI testpos_get_PrerollTime(IMediaPosition *iface, REFTIME *preroll)
+{
+    *preroll = 0.0;
+    return S_OK;
+}
+
+static HRESULT WINAPI testpos_put_PrerollTime(IMediaPosition *iface, REFTIME preroll)
+{
+    return S_OK;
+}
+
+static HRESULT WINAPI testpos_put_Rate(IMediaPosition *iface, double rate)
+{
+    struct testfilter *filter = impl_from_IMediaPosition(iface);
+
+    filter->rate = rate;
+    return S_OK;
+}
+
+static HRESULT WINAPI testpos_get_Rate(IMediaPosition *iface, double *rate)
+{
+    struct testfilter *filter = impl_from_IMediaPosition(iface);
+
+    *rate = filter->rate;
+    return S_OK;
+}
+
+static HRESULT WINAPI testpos_CanSeekForward(IMediaPosition *iface, LONG *can_seek)
+{
+    *can_seek = OAFALSE;
+    return S_OK;
+}
+
+static HRESULT WINAPI testpos_CanSeekBackward(IMediaPosition *iface, LONG *can_seek)
+{
+    *can_seek = OAFALSE;
+    return S_OK;
+}
+
+static const IMediaPositionVtbl testpos_vtbl =
+{
+    testpos_QueryInterface,
+    testpos_AddRef,
+    testpos_Release,
+    testpos_GetTypeInfoCount,
+    testpos_GetTypeInfo,
+    testpos_GetIDsOfNames,
+    testpos_Invoke,
+    testpos_get_Duration,
+    testpos_put_CurrentPosition,
+    testpos_get_CurrentPosition,
+    testpos_get_StopTime,
+    testpos_put_StopTime,
+    testpos_get_PrerollTime,
+    testpos_put_PrerollTime,
+    testpos_put_Rate,
+    testpos_get_Rate,
+    testpos_CanSeekForward,
+    testpos_CanSeekBackward
+};
+
+static inline struct testfilter *impl_from_IBaseFilter(IBaseFilter *iface)
+{
+    return CONTAINING_RECORD(iface, struct testfilter, IBaseFilter_iface);
+}
+
+static HRESULT WINAPI testfilter_QueryInterface(IBaseFilter *iface, REFIID iid, void **out)
+{
+    struct testfilter *filter = impl_from_IBaseFilter(iface);
+
+    if (IsEqualGUID(iid, &IID_IUnknown)
+            || IsEqualGUID(iid, &IID_IPersist)
+            || IsEqualGUID(iid, &IID_IMediaFilter)
+            || IsEqualGUID(iid, &IID_IBaseFilter))
+    {
+        *out = &filter->IBaseFilter_iface;
+    }
+    else if (IsEqualGUID(iid, &IID_IMediaSeeking))
+        *out = &filter->IMediaSeeking_iface;
+    else if (IsEqualGUID(iid, &IID_IMediaPosition))
+        *out = &filter->IMediaPosition_iface;
+    else
+    {
+        if (IsEqualGUID(iid, &IID_IFileSourceFilter)) ok(0, "Filter queried for IFileSourceFilter\n");
+
+        *out = NULL;
+        return E_NOINTERFACE;
+    }
+
+    IUnknown_AddRef((IUnknown *)*out);
+    return S_OK;
+}
+
+static ULONG WINAPI testfilter_AddRef(IBaseFilter *iface)
+{
+    struct testfilter *filter = impl_from_IBaseFilter(iface);
+    return InterlockedIncrement(&filter->ref);
+}
+
+static ULONG WINAPI testfilter_Release(IBaseFilter *iface)
+{
+    struct testfilter *filter = impl_from_IBaseFilter(iface);
+    LONG ref = InterlockedDecrement(&filter->ref);
+
+    if (!ref)
+    {
+        HeapFree(GetProcessHeap(), 0, filter->name);
+        HeapFree(GetProcessHeap(), 0, filter);
+    }
+    return ref;
+}
+
+static HRESULT WINAPI testfilter_GetClassID(IBaseFilter *iface, CLSID *clsid)
+{
+    memset(clsid, 0xde, sizeof(*clsid));
+    return S_OK;
+}
+
+static HRESULT WINAPI testfilter_Stop(IBaseFilter *iface)
+{
+    struct testfilter *filter = impl_from_IBaseFilter(iface);
+
+    filter->state = State_Stopped;
+    return S_OK;
+}
+
+static HRESULT WINAPI testfilter_Pause(IBaseFilter *iface)
+{
+    struct testfilter *filter = impl_from_IBaseFilter(iface);
+
+    filter->state = State_Paused;
+    return S_OK;
+}
+
+static HRESULT WINAPI testfilter_Run(IBaseFilter *iface, REFERENCE_TIME start)
+{
+    struct testfilter *filter = impl_from_IBaseFilter(iface);
+
+    filter->state = State_Running;
+    return S_OK;
+}
+
+static HRESULT WINAPI testfilter_GetState(IBaseFilter *iface, DWORD timeout, FILTER_STATE *state)
+{
+    struct testfilter *filter = impl_from_IBaseFilter(iface);
+
+    *state = filter->state;
+    return S_OK;
+}
+
+static HRESULT WINAPI testfilter_SetSyncSource(IBaseFilter *iface, IReferenceClock *clock)
+{
+    return S_OK;
+}
+
+static HRESULT WINAPI testfilter_GetSyncSource(IBaseFilter *iface, IReferenceClock **clock)
+{
+    ok(0, "Unexpected call.\n");
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI testfilter_EnumPins(IBaseFilter *iface, IEnumPins **out)
+{
+    struct testfilter *filter = impl_from_IBaseFilter(iface);
+
+    *out = &filter->IEnumPins_iface;
+    IEnumPins_AddRef(*out);
+    filter->enum_idx = 0;
+    return S_OK;
+}
+
+static HRESULT WINAPI testfilter_FindPin(IBaseFilter *iface, const WCHAR *id, IPin **pin)
+{
+    ok(0, "Unexpected call.\n");
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI testfilter_QueryFilterInfo(IBaseFilter *iface, FILTER_INFO *info)
+{
+    struct testfilter *filter = impl_from_IBaseFilter(iface);
+
+    info->pGraph = filter->graph;
+    if (filter->graph)
+        IFilterGraph_AddRef(filter->graph);
+    if (filter->name)
+        wcscpy(info->achName, filter->name);
+    else
+        info->achName[0] = 0;
+    return S_OK;
+}
+
+static HRESULT WINAPI testfilter_JoinFilterGraph(IBaseFilter *iface, IFilterGraph *graph, const WCHAR *name)
+{
+    struct testfilter *filter = impl_from_IBaseFilter(iface);
+
+    filter->graph = graph;
+    HeapFree(GetProcessHeap(), 0, filter->name);
+    if (name)
+    {
+        filter->name = HeapAlloc(GetProcessHeap(), 0, (wcslen(name) + 1) * sizeof(WCHAR));
+        wcscpy(filter->name, name);
+    }
+    else
+        filter->name = NULL;
+    return S_OK;
+}
+
+static HRESULT WINAPI testfilter_QueryVendorInfo(IBaseFilter *iface, WCHAR **info)
+{
+    return E_NOTIMPL;
+}
+
+static const IBaseFilterVtbl testfilter_vtbl =
+{
+    testfilter_QueryInterface,
+    testfilter_AddRef,
+    testfilter_Release,
+    testfilter_GetClassID,
+    testfilter_Stop,
+    testfilter_Pause,
+    testfilter_Run,
+    testfilter_GetState,
+    testfilter_SetSyncSource,
+    testfilter_GetSyncSource,
+    testfilter_EnumPins,
+    testfilter_FindPin,
+    testfilter_QueryFilterInfo,
+    testfilter_JoinFilterGraph,
+    testfilter_QueryVendorInfo
+};
+
+static IBaseFilter *create_testfilter(void)
+{
+    struct testfilter *filter = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*filter));
+
+    if (!filter) return NULL;
+
+    filter->IBaseFilter_iface.lpVtbl = &testfilter_vtbl;
+    filter->IMediaSeeking_iface.lpVtbl = &testseek_vtbl;
+    filter->IMediaPosition_iface.lpVtbl = &testpos_vtbl;
+    filter->IEnumPins_iface.lpVtbl = &testenumpins_vtbl;
+    filter->IPin_iface.lpVtbl = &testpin_vtbl;
+    filter->IEnumMediaTypes_iface.lpVtbl = &testenummt_vtbl;
+    filter->ref = 1;
+    filter->state = State_Stopped;
+    filter->rate = 1.0;
+
+    return &filter->IBaseFilter_iface;
+}
+
 static void test_aggregation(void)
 {
     IMediaDet *detector, *detector2;
@@ -188,13 +1050,17 @@ static BOOL init_tests(void)
 static void test_mediadet(void)
 {
     HRESULT hr;
+    IBaseFilter *filter, *filter2;
+    FILTER_INFO filter_info;
     IMediaDet *pM = NULL;
     BSTR filename = NULL;
+    IFilterGraph *graph;
     LONG nstrms = 0;
     LONG strm;
     GUID guid;
     BSTR bstr;
     AM_MEDIA_TYPE mt;
+    IUnknown *unk;
     double fps;
     int flags;
     int i;
@@ -256,6 +1122,61 @@ static void test_mediadet(void)
     hr = IMediaDet_get_StreamTypeB(pM, NULL);
     ok(hr == E_INVALIDARG, "IMediaDet_get_StreamTypeB failed: %08x\n", hr);
 
+    hr = IMediaDet_get_Filter(pM, NULL);
+    ok(hr == E_POINTER, "IMediaDet_get_Filter failed: %08x\n", hr);
+
+    unk = (IUnknown*)0xdeadbeef;
+    hr = IMediaDet_get_Filter(pM, &unk);
+    ok(hr == S_FALSE, "IMediaDet_get_Filter failed: %08x\n", hr);
+    ok(unk == NULL, "Wrong filter %p\n", unk);
+
+    hr = IMediaDet_put_Filter(pM, NULL);
+    ok(hr == E_POINTER, "IMediaDet_put_Filter failed: %08x\n", hr);
+
+    filter = create_testfilter();
+    hr = IMediaDet_put_Filter(pM, (IUnknown*)filter);
+    ok(hr == S_OK, "IMediaDet_put_Filter failed: %08x\n", hr);
+
+    hr = IMediaDet_get_Filter(pM, &unk);
+    ok(hr == S_OK, "IMediaDet_get_Filter failed: %08x\n", hr);
+    ok(unk != NULL, "NULL filter\n");
+    hr = IUnknown_QueryInterface(unk, &IID_IBaseFilter, (void**)&filter2);
+    IUnknown_Release(unk);
+    ok(hr == S_OK, "Could not get IBaseFilter interface: %08x\n", hr);
+    ok(filter == filter2, "Wrong filter\n");
+    IBaseFilter_Release(filter2);
+
+    hr = IBaseFilter_QueryFilterInfo(filter, &filter_info);
+    ok(hr == S_OK, "IBaseFilter_QueryFilterInfo failed: %08x\n", hr);
+    ok(!wcscmp(filter_info.achName, L"Source"), "Wrong filter name: %s\n", wine_dbgstr_w(filter_info.achName));
+    IBaseFilter_Release(filter);
+    graph = filter_info.pGraph;
+
+    filter = create_testfilter();
+    hr = IMediaDet_put_Filter(pM, (IUnknown*)filter);
+    ok(hr == S_OK, "IMediaDet_put_Filter failed: %08x\n", hr);
+    IBaseFilter_Release(filter);
+
+    hr = IMediaDet_get_Filter(pM, &unk);
+    ok(hr == S_OK, "IMediaDet_get_Filter failed: %08x\n", hr);
+    ok(unk != NULL, "NULL filter\n");
+    hr = IUnknown_QueryInterface(unk, &IID_IBaseFilter, (void**)&filter);
+    IUnknown_Release(unk);
+    ok(hr == S_OK, "Could not get IBaseFilter interface: %08x\n", hr);
+
+    hr = IBaseFilter_QueryFilterInfo(filter, &filter_info);
+    ok(hr == S_OK, "IBaseFilter_QueryFilterInfo failed: %08x\n", hr);
+    ok(!wcscmp(filter_info.achName, L"Source"), "Wrong filter name: %s\n", wine_dbgstr_w(filter_info.achName));
+    ok(graph != filter_info.pGraph, "Same filter graph was used\n");
+    IFilterGraph_Release(filter_info.pGraph);
+    IFilterGraph_Release(graph);
+    IBaseFilter_Release(filter);
+
+    strm = -1;
+    hr = IMediaDet_get_CurrentStream(pM, &strm);
+    ok(hr == S_OK, "IMediaDet_get_CurrentStream failed: %08x\n", hr);
+    ok(strm == 0, "IMediaDet_get_CurrentStream: strm is %i\n", strm);
+
     filename = SysAllocString(test_avi_filename);
     hr = IMediaDet_put_Filename(pM, filename);
     ok(hr == S_OK, "IMediaDet_put_Filename failed: %08x\n", hr);
@@ -427,6 +1348,50 @@ static void test_mediadet(void)
     ok(hr == S_OK, "IMediaDet_get_CurrentStream failed: %08x\n", hr);
     ok(strm == 1, "IMediaDet_get_CurrentStream: strm is %i\n", strm);
 
+    hr = IMediaDet_get_Filter(pM, &unk);
+    ok(hr == S_OK, "IMediaDet_get_Filter failed: %08x\n", hr);
+    ok(unk != NULL, "NULL filter\n");
+    hr = IUnknown_QueryInterface(unk, &IID_IBaseFilter, (void**)&filter2);
+    IUnknown_Release(unk);
+    ok(hr == S_OK, "Could not get IBaseFilter interface: %08x\n", hr);
+
+    hr = IBaseFilter_QueryFilterInfo(filter2, &filter_info);
+    ok(hr == S_OK, "IBaseFilter_QueryFilterInfo failed: %08x\n", hr);
+    ok(!wcscmp(filter_info.achName, L"Source"), "Wrong filter name: %s\n", wine_dbgstr_w(filter_info.achName));
+    graph = filter_info.pGraph;
+
+    filter = create_testfilter();
+    hr = IMediaDet_put_Filter(pM, (IUnknown*)filter);
+    ok(hr == S_OK, "IMediaDet_put_Filter failed: %08x\n", hr);
+    IBaseFilter_Release(filter);
+
+    hr = IMediaDet_get_Filter(pM, &unk);
+    ok(hr == S_OK, "IMediaDet_get_Filter failed: %08x\n", hr);
+    ok(unk != NULL, "NULL filter\n");
+    hr = IUnknown_QueryInterface(unk, &IID_IBaseFilter, (void**)&filter);
+    IUnknown_Release(unk);
+    ok(hr == S_OK, "Could not get IBaseFilter interface: %08x\n", hr);
+    ok(filter != filter2, "Same filter\n");
+    IBaseFilter_Release(filter2);
+
+    hr = IBaseFilter_QueryFilterInfo(filter, &filter_info);
+    ok(hr == S_OK, "IBaseFilter_QueryFilterInfo failed: %08x\n", hr);
+    ok(!wcscmp(filter_info.achName, L"Source"), "Wrong filter name: %s\n", wine_dbgstr_w(filter_info.achName));
+    ok(graph != filter_info.pGraph, "Same filter graph was used\n");
+    IFilterGraph_Release(filter_info.pGraph);
+    IFilterGraph_Release(graph);
+    IBaseFilter_Release(filter);
+
+    filename = NULL;
+    hr = IMediaDet_get_Filename(pM, &filename);
+    ok(hr == S_OK, "IMediaDet_get_Filename failed: %08x\n", hr);
+    ok(!filename, "Expected NULL filename, got %s.\n", debugstr_w(filename));
+    SysFreeString(filename);
+
+    hr = IMediaDet_get_OutputStreams(pM, &nstrms);
+    ok(hr == S_OK, "IMediaDet_get_OutputStreams failed: %08x\n", hr);
+    ok(nstrms == 1, "IMediaDet_get_OutputStreams: nstrms is %i\n", nstrms);
+
     hr = IMediaDet_Release(pM);
     ok(hr == 0, "IMediaDet_Release returned: %x\n", hr);
 
-- 
2.21.0




More information about the wine-devel mailing list