From dec3d502901d56839ee5240c1ee68158efdcfac1 Mon Sep 17 00:00:00 2001 From: Christian Costa Date: Tue, 1 May 2012 10:21:28 +0200 Subject: [PATCH] amstream: Add the corresponding pin to every media stream added to the media stream filter + add tests. --- dlls/amstream/mediastreamfilter.c | 96 +++++++++++++++++++++++++++++-- dlls/amstream/tests/amstream.c | 48 ++++++++++++++++ 2 files changed, 140 insertions(+), 4 deletions(-) diff --git a/dlls/amstream/mediastreamfilter.c b/dlls/amstream/mediastreamfilter.c index cd084902516..ee9d970d7ef 100644 --- a/dlls/amstream/mediastreamfilter.c +++ b/dlls/amstream/mediastreamfilter.c @@ -1,7 +1,7 @@ /* * Implementation of MediaStream Filter * - * Copyright 2008 Christian Costa + * Copyright 2008, 2012 Christian Costa * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -35,10 +35,38 @@ WINE_DEFAULT_DEBUG_CHANNEL(amstream); +typedef struct MediaStreamFilter_InputPin +{ + BaseInputPin pin; +} MediaStreamFilter_InputPin; + +static const IPinVtbl MediaStreamFilter_InputPin_Vtbl = +{ + BaseInputPinImpl_QueryInterface, + BasePinImpl_AddRef, + BaseInputPinImpl_Release, + BaseInputPinImpl_Connect, + BaseInputPinImpl_ReceiveConnection, + BasePinImpl_Disconnect, + BasePinImpl_ConnectedTo, + BasePinImpl_ConnectionMediaType, + BasePinImpl_QueryPinInfo, + BasePinImpl_QueryDirection, + BasePinImpl_QueryId, + BasePinImpl_QueryAccept, + BasePinImpl_EnumMediaTypes, + BasePinImpl_QueryInternalConnections, + BaseInputPinImpl_EndOfStream, + BaseInputPinImpl_BeginFlush, + BaseInputPinImpl_EndFlush, + BasePinImpl_NewSegment +}; + typedef struct { BaseFilter filter; ULONG nb_streams; IMediaStream** streams; + IPin** pins; } IMediaStreamFilterImpl; static inline IMediaStreamFilterImpl *impl_from_IMediaStreamFilter(IMediaStreamFilter *iface) @@ -46,6 +74,32 @@ static inline IMediaStreamFilterImpl *impl_from_IMediaStreamFilter(IMediaStreamF return CONTAINING_RECORD(iface, IMediaStreamFilterImpl, filter); } +static HRESULT WINAPI BasePinImpl_CheckMediaType(BasePin *This, const AM_MEDIA_TYPE *pmt) +{ + return S_FALSE; +} + +static LONG WINAPI BasePinImp_GetMediaTypeVersion(BasePin *This) +{ + return 0; +} + +static HRESULT WINAPI BasePinImp_GetMediaType(BasePin *This, int iPosition, AM_MEDIA_TYPE *amt) +{ + return S_FALSE; +} + +static const BasePinFuncTable input_BaseFuncTable = { + BasePinImpl_CheckMediaType, + NULL, + BasePinImp_GetMediaTypeVersion, + BasePinImp_GetMediaType +}; + +static const BaseInputPinFuncTable input_BaseInputFuncTable = { + NULL +}; + /*** IUnknown methods ***/ static HRESULT WINAPI MediaStreamFilterImpl_QueryInterface(IMediaStreamFilter *iface, REFIID riid, @@ -93,7 +147,10 @@ static ULONG WINAPI MediaStreamFilterImpl_Release(IMediaStreamFilter *iface) { int i; for (i = 0; i < This->nb_streams; i++) + { IMediaStream_Release(This->streams[i]); + IPin_Release(This->pins[i]); + } HeapFree(GetProcessHeap(), 0, This); } @@ -178,6 +235,11 @@ static HRESULT WINAPI MediaStreamFilterImpl_AddMediaStream(IMediaStreamFilter* i { IMediaStreamFilterImpl *This = impl_from_IMediaStreamFilter(iface); IMediaStream** streams; + IPin** pins; + MediaStreamFilter_InputPin* pin; + HRESULT hr; + PIN_INFO info; + MSPID purpose_id; TRACE("(%p)->(%p)\n", iface, pAMMediaStream); @@ -185,6 +247,24 @@ static HRESULT WINAPI MediaStreamFilterImpl_AddMediaStream(IMediaStreamFilter* i if (!streams) return E_OUTOFMEMORY; This->streams = streams; + pins = CoTaskMemRealloc(This->pins, (This->nb_streams + 1) * sizeof(IPin*)); + if (!pins) + return E_OUTOFMEMORY; + This->pins = pins; + info.pFilter = (IBaseFilter*)&This->filter; + info.dir = PINDIR_INPUT; + hr = IAMMediaStream_GetInformation(pAMMediaStream, &purpose_id, NULL); + if (FAILED(hr)) + return hr; + /* Pin name is "I{guid MSPID_PrimaryVideo or MSPID_PrimaryAudio}" */ + info.achName[0] = 'I'; + StringFromGUID2(&purpose_id, info.achName + 1, 40); + hr = BaseInputPin_Construct(&MediaStreamFilter_InputPin_Vtbl, &info, &input_BaseFuncTable, &input_BaseInputFuncTable, &This->filter.csFilter, NULL, &This->pins[This->nb_streams]); + if (FAILED(hr)) + return hr; + + pin = (MediaStreamFilter_InputPin*)This->pins[This->nb_streams]; + pin->pin.pin.pinInfo.pFilter = (LPVOID)This; This->streams[This->nb_streams] = (IMediaStream*)pAMMediaStream; This->nb_streams++; @@ -294,14 +374,22 @@ static const IMediaStreamFilterVtbl MediaStreamFilter_Vtbl = static IPin* WINAPI MediaStreamFilterImpl_GetPin(BaseFilter *iface, int pos) { - /* No pins */ + IMediaStreamFilterImpl* This = (IMediaStreamFilterImpl*)iface; + + if (pos < This->nb_streams) + { + IPin_AddRef(This->pins[pos]); + return This->pins[pos]; + } + return NULL; } static LONG WINAPI MediaStreamFilterImpl_GetPinCount(BaseFilter *iface) { - /* No pins */ - return 0; + IMediaStreamFilterImpl* This = (IMediaStreamFilterImpl*)iface; + + return This->nb_streams; } static const BaseFilterFuncTable BaseFuncTable = { diff --git a/dlls/amstream/tests/amstream.c b/dlls/amstream/tests/amstream.c index c62e83d7ecf..36c97b9f8c5 100644 --- a/dlls/amstream/tests/amstream.c +++ b/dlls/amstream/tests/amstream.c @@ -364,6 +364,54 @@ static void test_media_streams(void) } } + if (media_stream_filter) + { + IEnumPins *enum_pins; + + hr = IMediaStreamFilter_EnumPins(media_stream_filter, &enum_pins); + ok(hr == S_OK, "IBaseFilter_EnumPins returned: %x\n", hr); + if (hr == S_OK) + { + IPin* pins[3] = { NULL, NULL, NULL }; + ULONG nb_pins; + ULONG expected_nb_pins = audio_stream ? 2 : 1; + int i; + + hr = IEnumPins_Next(enum_pins, 3, pins, &nb_pins); + ok(SUCCEEDED(hr), "IEnumPins_Next returned: %x\n", hr); + ok(nb_pins == expected_nb_pins, "Number of pins is %u instead of %u\n", nb_pins, expected_nb_pins); + for (i = 0; i < min(nb_pins, expected_nb_pins); i++) + { + IEnumMediaTypes* enum_media_types; + AM_MEDIA_TYPE* media_types[10]; + ULONG nb_media_types; + IPin* pin; + PIN_INFO info; + WCHAR id[40]; + + /* Pin name is "I{guid MSPID_PrimaryVideo or MSPID_PrimaryAudio}" */ + id[0] = 'I'; + StringFromGUID2(i ? &MSPID_PrimaryAudio : &MSPID_PrimaryVideo, id + 1, 40); + + hr = IPin_ConnectedTo(pins[i], &pin); + ok(hr == VFW_E_NOT_CONNECTED, "IPin_ConnectedTo returned: %x\n", hr); + hr = IPin_QueryPinInfo(pins[i], &info); + ok(hr == S_OK, "IPin_QueryPinInfo returned: %x\n", hr); + IBaseFilter_Release(info.pFilter); + ok(info.dir == PINDIR_INPUT, "Pin direction is %u instead of %u\n", info.dir, PINDIR_INPUT); + ok(!lstrcmpW(info.achName, id), "Pin name is %s instead of %s\n", wine_dbgstr_w(info.achName), wine_dbgstr_w(id)); + hr = IPin_EnumMediaTypes(pins[i], &enum_media_types); + ok(hr == S_OK, "IPin_EnumMediaTypes returned: %x\n", hr); + hr = IEnumMediaTypes_Next(enum_media_types, sizeof(media_types) / sizeof(AM_MEDIA_TYPE), media_types, &nb_media_types); + ok(SUCCEEDED(hr), "IEnumMediaTypes_Next returned: %x\n", hr); + ok(nb_media_types == 0, "nb_media_types should be 0 instead of %u\n", nb_media_types); + IEnumMediaTypes_Release(enum_media_types); + IPin_Release(pins[i]); + } + IEnumPins_Release(enum_pins); + } + } + if (video_stream) IMediaStream_Release(video_stream); if (audio_stream)