amstream: Add the corresponding pin to every media stream added to the media stream filter + add tests.
This commit is contained in:
parent
49762b1679
commit
dec3d50290
|
@ -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 = {
|
||||||
|
|
|
@ -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)
|
||||||
|
|
Loading…
Reference in New Issue