Signed-off-by: Gabriel Ivăncescu gabrielopcode@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);