amstream: Add the corresponding pin to every media stream added to the media stream filter + add tests.

This commit is contained in:
Christian Costa 2012-05-01 10:21:28 +02:00 committed by Alexandre Julliard
parent 49762b1679
commit dec3d50290
2 changed files with 140 additions and 4 deletions

View File

@ -1,7 +1,7 @@
/* /*
* Implementation of MediaStream Filter * Implementation of MediaStream Filter
* *
* Copyright 2008 Christian Costa * Copyright 2008, 2012 Christian Costa
* *
* This library is free software; you can redistribute it and/or * This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public * modify it under the terms of the GNU Lesser General Public
@ -35,10 +35,38 @@
WINE_DEFAULT_DEBUG_CHANNEL(amstream); 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 { typedef struct {
BaseFilter filter; BaseFilter filter;
ULONG nb_streams; ULONG nb_streams;
IMediaStream** streams; IMediaStream** streams;
IPin** pins;
} IMediaStreamFilterImpl; } IMediaStreamFilterImpl;
static inline IMediaStreamFilterImpl *impl_from_IMediaStreamFilter(IMediaStreamFilter *iface) 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); 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 ***/ /*** IUnknown methods ***/
static HRESULT WINAPI MediaStreamFilterImpl_QueryInterface(IMediaStreamFilter *iface, REFIID riid, static HRESULT WINAPI MediaStreamFilterImpl_QueryInterface(IMediaStreamFilter *iface, REFIID riid,
@ -93,7 +147,10 @@ static ULONG WINAPI MediaStreamFilterImpl_Release(IMediaStreamFilter *iface)
{ {
int i; int i;
for (i = 0; i < This->nb_streams; i++) for (i = 0; i < This->nb_streams; i++)
{
IMediaStream_Release(This->streams[i]); IMediaStream_Release(This->streams[i]);
IPin_Release(This->pins[i]);
}
HeapFree(GetProcessHeap(), 0, This); HeapFree(GetProcessHeap(), 0, This);
} }
@ -178,6 +235,11 @@ static HRESULT WINAPI MediaStreamFilterImpl_AddMediaStream(IMediaStreamFilter* i
{ {
IMediaStreamFilterImpl *This = impl_from_IMediaStreamFilter(iface); IMediaStreamFilterImpl *This = impl_from_IMediaStreamFilter(iface);
IMediaStream** streams; IMediaStream** streams;
IPin** pins;
MediaStreamFilter_InputPin* pin;
HRESULT hr;
PIN_INFO info;
MSPID purpose_id;
TRACE("(%p)->(%p)\n", iface, pAMMediaStream); TRACE("(%p)->(%p)\n", iface, pAMMediaStream);
@ -185,6 +247,24 @@ static HRESULT WINAPI MediaStreamFilterImpl_AddMediaStream(IMediaStreamFilter* i
if (!streams) if (!streams)
return E_OUTOFMEMORY; return E_OUTOFMEMORY;
This->streams = streams; 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->streams[This->nb_streams] = (IMediaStream*)pAMMediaStream;
This->nb_streams++; This->nb_streams++;
@ -294,14 +374,22 @@ static const IMediaStreamFilterVtbl MediaStreamFilter_Vtbl =
static IPin* WINAPI MediaStreamFilterImpl_GetPin(BaseFilter *iface, int pos) 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; return NULL;
} }
static LONG WINAPI MediaStreamFilterImpl_GetPinCount(BaseFilter *iface) static LONG WINAPI MediaStreamFilterImpl_GetPinCount(BaseFilter *iface)
{ {
/* No pins */ IMediaStreamFilterImpl* This = (IMediaStreamFilterImpl*)iface;
return 0;
return This->nb_streams;
} }
static const BaseFilterFuncTable BaseFuncTable = { static const BaseFilterFuncTable BaseFuncTable = {

View File

@ -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) if (video_stream)
IMediaStream_Release(video_stream); IMediaStream_Release(video_stream);
if (audio_stream) if (audio_stream)