Commit 953cf311 authored by Zebediah Figura's avatar Zebediah Figura Committed by Alexandre Julliard

amstream: Reimplement IPin locally for the primary audio stream.

parent 55274438
...@@ -25,6 +25,10 @@ ...@@ -25,6 +25,10 @@
WINE_DEFAULT_DEBUG_CHANNEL(amstream); WINE_DEFAULT_DEBUG_CHANNEL(amstream);
static const WCHAR sink_id[] = {'I','{','A','3','5','F','F','5','6','B',
'-','9','F','D','A','-','1','1','D','0','-','8','F','D','F',
'-','0','0','C','0','4','F','D','9','1','8','9','D','}',0};
typedef struct { typedef struct {
IAudioStreamSample IAudioStreamSample_iface; IAudioStreamSample IAudioStreamSample_iface;
LONG ref; LONG ref;
...@@ -164,27 +168,23 @@ static HRESULT audiostreamsample_create(IAudioMediaStream *parent, IAudioData *a ...@@ -164,27 +168,23 @@ static HRESULT audiostreamsample_create(IAudioMediaStream *parent, IAudioData *a
return S_OK; return S_OK;
} }
struct AudioMediaStreamImpl;
typedef struct {
BaseInputPin pin;
struct audio_stream *parent;
} AudioMediaStreamInputPin;
struct audio_stream struct audio_stream
{ {
IAMMediaStream IAMMediaStream_iface; IAMMediaStream IAMMediaStream_iface;
IAudioMediaStream IAudioMediaStream_iface; IAudioMediaStream IAudioMediaStream_iface;
IMemInputPin IMemInputPin_iface; IMemInputPin IMemInputPin_iface;
IPin IPin_iface;
LONG ref; LONG ref;
IMultiMediaStream* parent; IMultiMediaStream* parent;
MSPID purpose_id; MSPID purpose_id;
STREAM_TYPE stream_type; STREAM_TYPE stream_type;
AudioMediaStreamInputPin *input_pin; CRITICAL_SECTION cs;
CRITICAL_SECTION critical_section; IMediaStreamFilter *filter;
IPin *peer;
IMemAllocator *allocator; IMemAllocator *allocator;
AM_MEDIA_TYPE mt;
}; };
static inline struct audio_stream *impl_from_IAMMediaStream(IAMMediaStream *iface) static inline struct audio_stream *impl_from_IAMMediaStream(IAMMediaStream *iface)
...@@ -217,7 +217,7 @@ static HRESULT WINAPI AudioMediaStreamImpl_IAMMediaStream_QueryInterface(IAMMedi ...@@ -217,7 +217,7 @@ static HRESULT WINAPI AudioMediaStreamImpl_IAMMediaStream_QueryInterface(IAMMedi
else if (IsEqualGUID(riid, &IID_IPin)) else if (IsEqualGUID(riid, &IID_IPin))
{ {
IAMMediaStream_AddRef(iface); IAMMediaStream_AddRef(iface);
*ret_iface = &This->input_pin->pin.pin.IPin_iface; *ret_iface = &This->IPin_iface;
return S_OK; return S_OK;
} }
else if (IsEqualGUID(riid, &IID_IMemInputPin)) else if (IsEqualGUID(riid, &IID_IMemInputPin))
...@@ -250,8 +250,7 @@ static ULONG WINAPI AudioMediaStreamImpl_IAMMediaStream_Release(IAMMediaStream * ...@@ -250,8 +250,7 @@ static ULONG WINAPI AudioMediaStreamImpl_IAMMediaStream_Release(IAMMediaStream *
if (!ref) if (!ref)
{ {
BaseInputPin_Destroy((BaseInputPin *)This->input_pin); DeleteCriticalSection(&This->cs);
DeleteCriticalSection(&This->critical_section);
HeapFree(GetProcessHeap(), 0, This); HeapFree(GetProcessHeap(), 0, This);
} }
...@@ -358,13 +357,13 @@ static HRESULT WINAPI AudioMediaStreamImpl_IAMMediaStream_JoinAMMultiMediaStream ...@@ -358,13 +357,13 @@ static HRESULT WINAPI AudioMediaStreamImpl_IAMMediaStream_JoinAMMultiMediaStream
return S_FALSE; return S_FALSE;
} }
static HRESULT WINAPI AudioMediaStreamImpl_IAMMediaStream_JoinFilter(IAMMediaStream *iface, IMediaStreamFilter *media_stream_filter) static HRESULT WINAPI AudioMediaStreamImpl_IAMMediaStream_JoinFilter(IAMMediaStream *iface, IMediaStreamFilter *filter)
{ {
struct audio_stream *This = impl_from_IAMMediaStream(iface); struct audio_stream *stream = impl_from_IAMMediaStream(iface);
TRACE("(%p/%p)->(%p)\n", This, iface, media_stream_filter); TRACE("stream %p, filter %p.\n", stream, filter);
This->input_pin->pin.pin.pinInfo.pFilter = (IBaseFilter *)media_stream_filter; stream->filter = filter;
return S_OK; return S_OK;
} }
...@@ -675,127 +674,249 @@ static const IEnumMediaTypesVtbl enum_media_types_vtbl = ...@@ -675,127 +674,249 @@ static const IEnumMediaTypesVtbl enum_media_types_vtbl =
enum_media_types_Clone, enum_media_types_Clone,
}; };
static inline AudioMediaStreamInputPin *impl_from_AudioMediaStreamInputPin_IPin(IPin *iface) static inline struct audio_stream *impl_from_IPin(IPin *iface)
{ {
return CONTAINING_RECORD(iface, AudioMediaStreamInputPin, pin.pin.IPin_iface); return CONTAINING_RECORD(iface, struct audio_stream, IPin_iface);
} }
/*** IUnknown methods ***/ static HRESULT WINAPI audio_sink_QueryInterface(IPin *iface, REFIID iid, void **out)
static HRESULT WINAPI AudioMediaStreamInputPin_IPin_QueryInterface(IPin *iface, REFIID riid, void **ret_iface)
{ {
AudioMediaStreamInputPin *This = impl_from_AudioMediaStreamInputPin_IPin(iface); struct audio_stream *stream = impl_from_IPin(iface);
return IAMMediaStream_QueryInterface(&stream->IAMMediaStream_iface, iid, out);
}
return IAMMediaStream_QueryInterface(&This->parent->IAMMediaStream_iface, riid, ret_iface); static ULONG WINAPI audio_sink_AddRef(IPin *iface)
{
struct audio_stream *stream = impl_from_IPin(iface);
return IAMMediaStream_AddRef(&stream->IAMMediaStream_iface);
} }
static ULONG WINAPI AudioMediaStreamInputPin_IPin_AddRef(IPin *iface) static ULONG WINAPI audio_sink_Release(IPin *iface)
{ {
AudioMediaStreamInputPin *This = impl_from_AudioMediaStreamInputPin_IPin(iface); struct audio_stream *stream = impl_from_IPin(iface);
return IAMMediaStream_Release(&stream->IAMMediaStream_iface);
}
return IAMMediaStream_AddRef(&This->parent->IAMMediaStream_iface); static HRESULT WINAPI audio_sink_Connect(IPin *iface, IPin *peer, const AM_MEDIA_TYPE *mt)
{
WARN("iface %p, peer %p, mt %p, unexpected call!\n", iface, peer, mt);
return E_UNEXPECTED;
} }
static ULONG WINAPI AudioMediaStreamInputPin_IPin_Release(IPin *iface) static HRESULT WINAPI audio_sink_ReceiveConnection(IPin *iface, IPin *peer, const AM_MEDIA_TYPE *mt)
{ {
AudioMediaStreamInputPin *This = impl_from_AudioMediaStreamInputPin_IPin(iface); struct audio_stream *stream = impl_from_IPin(iface);
PIN_DIRECTION dir;
TRACE("stream %p, peer %p, mt %p.\n", stream, peer, mt);
EnterCriticalSection(&stream->cs);
return IAMMediaStream_Release(&This->parent->IAMMediaStream_iface); if (stream->peer)
{
LeaveCriticalSection(&stream->cs);
return VFW_E_ALREADY_CONNECTED;
}
IPin_QueryDirection(peer, &dir);
if (dir != PINDIR_OUTPUT)
{
WARN("Rejecting connection from input pin.\n");
LeaveCriticalSection(&stream->cs);
return VFW_E_INVALID_DIRECTION;
}
CopyMediaType(&stream->mt, mt);
IPin_AddRef(stream->peer = peer);
LeaveCriticalSection(&stream->cs);
return S_OK;
} }
static HRESULT WINAPI audio_sink_EnumMediaTypes(IPin *iface, IEnumMediaTypes **enum_media_types) static HRESULT WINAPI audio_sink_Disconnect(IPin *iface)
{ {
struct enum_media_types *object; struct audio_stream *stream = impl_from_IPin(iface);
TRACE("iface %p, enum_media_types %p.\n", iface, enum_media_types); TRACE("stream %p.\n", stream);
if (!enum_media_types) EnterCriticalSection(&stream->cs);
return E_POINTER;
if (!(object = heap_alloc(sizeof(*object)))) if (!stream->peer)
return E_OUTOFMEMORY; {
LeaveCriticalSection(&stream->cs);
return S_FALSE;
}
object->IEnumMediaTypes_iface.lpVtbl = &enum_media_types_vtbl; IPin_Release(stream->peer);
object->refcount = 1; stream->peer = NULL;
object->index = 0; FreeMediaType(&stream->mt);
memset(&stream->mt, 0, sizeof(AM_MEDIA_TYPE));
LeaveCriticalSection(&stream->cs);
*enum_media_types = &object->IEnumMediaTypes_iface;
return S_OK; return S_OK;
} }
static const IPinVtbl AudioMediaStreamInputPin_IPin_Vtbl = static HRESULT WINAPI audio_sink_ConnectedTo(IPin *iface, IPin **peer)
{ {
AudioMediaStreamInputPin_IPin_QueryInterface, struct audio_stream *stream = impl_from_IPin(iface);
AudioMediaStreamInputPin_IPin_AddRef, HRESULT hr;
AudioMediaStreamInputPin_IPin_Release,
BaseInputPinImpl_Connect, TRACE("stream %p, peer %p.\n", stream, peer);
BaseInputPinImpl_ReceiveConnection,
BasePinImpl_Disconnect,
BasePinImpl_ConnectedTo,
BasePinImpl_ConnectionMediaType,
BasePinImpl_QueryPinInfo,
BasePinImpl_QueryDirection,
BasePinImpl_QueryId,
BasePinImpl_QueryAccept,
audio_sink_EnumMediaTypes,
BasePinImpl_QueryInternalConnections,
BaseInputPinImpl_EndOfStream,
BaseInputPinImpl_BeginFlush,
BaseInputPinImpl_EndFlush,
BaseInputPinImpl_NewSegment,
};
static HRESULT WINAPI AudioMediaStreamInputPin_CheckMediaType(BasePin *base, const AM_MEDIA_TYPE *media_type) EnterCriticalSection(&stream->cs);
if (stream->peer)
{
IPin_AddRef(*peer = stream->peer);
hr = S_OK;
}
else
{
*peer = NULL;
hr = VFW_E_NOT_CONNECTED;
}
LeaveCriticalSection(&stream->cs);
return hr;
}
static HRESULT WINAPI audio_sink_ConnectionMediaType(IPin *iface, AM_MEDIA_TYPE *mt)
{ {
AudioMediaStreamInputPin *This = impl_from_AudioMediaStreamInputPin_IPin(&base->IPin_iface); struct audio_stream *stream = impl_from_IPin(iface);
HRESULT hr;
TRACE("(%p)->(%p)\n", This, media_type); TRACE("stream %p, mt %p.\n", stream, mt);
if (IsEqualGUID(&media_type->majortype, &MEDIATYPE_Audio)) EnterCriticalSection(&stream->cs);
if (stream->peer)
{
CopyMediaType(mt, &stream->mt);
hr = S_OK;
}
else
{ {
if (IsEqualGUID(&media_type->subtype, &MEDIASUBTYPE_PCM)) memset(mt, 0, sizeof(AM_MEDIA_TYPE));
{ hr = VFW_E_NOT_CONNECTED;
TRACE("Audio sub-type %s matches\n", debugstr_guid(&media_type->subtype));
return S_OK;
}
} }
LeaveCriticalSection(&stream->cs);
return hr;
}
static HRESULT WINAPI audio_sink_QueryPinInfo(IPin *iface, PIN_INFO *info)
{
struct audio_stream *stream = impl_from_IPin(iface);
TRACE("stream %p, info %p.\n", stream, info);
IBaseFilter_AddRef(info->pFilter = (IBaseFilter *)stream->filter);
info->dir = PINDIR_INPUT;
lstrcpyW(info->achName, sink_id);
return S_OK; return S_OK;
} }
static HRESULT WINAPI AudioMediaStreamInputPin_GetMediaType(BasePin *base, int index, AM_MEDIA_TYPE *media_type) static HRESULT WINAPI audio_sink_QueryDirection(IPin *iface, PIN_DIRECTION *dir)
{ {
AudioMediaStreamInputPin *This = impl_from_AudioMediaStreamInputPin_IPin(&base->IPin_iface); TRACE("iface %p, dir %p.\n", iface, dir);
*dir = PINDIR_INPUT;
return S_OK;
}
TRACE("(%p)->(%d,%p)\n", This, index, media_type); static HRESULT WINAPI audio_sink_QueryId(IPin *iface, WCHAR **id)
{
TRACE("iface %p, id %p.\n", iface, id);
/* FIXME: Reset structure as we only fill majortype and minortype for now */ if (!(*id = CoTaskMemAlloc(sizeof(sink_id))))
ZeroMemory(media_type, sizeof(*media_type)); return E_OUTOFMEMORY;
if (index) lstrcpyW(*id, sink_id);
return S_FALSE;
return S_OK;
}
static HRESULT WINAPI audio_sink_QueryAccept(IPin *iface, const AM_MEDIA_TYPE *mt)
{
TRACE("iface %p, mt %p.\n", iface, mt);
return S_OK;
}
static HRESULT WINAPI audio_sink_EnumMediaTypes(IPin *iface, IEnumMediaTypes **enum_media_types)
{
struct enum_media_types *object;
TRACE("iface %p, enum_media_types %p.\n", iface, enum_media_types);
if (!enum_media_types)
return E_POINTER;
media_type->majortype = MEDIATYPE_Audio; if (!(object = heap_alloc(sizeof(*object))))
media_type->subtype = MEDIASUBTYPE_PCM; return E_OUTOFMEMORY;
object->IEnumMediaTypes_iface.lpVtbl = &enum_media_types_vtbl;
object->refcount = 1;
object->index = 0;
*enum_media_types = &object->IEnumMediaTypes_iface;
return S_OK; return S_OK;
} }
static HRESULT WINAPI AudioMediaStreamInputPin_Receive(BaseInputPin *base, IMediaSample *sample) static HRESULT WINAPI audio_sink_QueryInternalConnections(IPin *iface, IPin **pins, ULONG *count)
{ {
AudioMediaStreamInputPin *This = impl_from_AudioMediaStreamInputPin_IPin(&base->pin.IPin_iface); TRACE("iface %p, pins %p, count %p.\n", iface, pins, count);
return E_NOTIMPL;
}
FIXME("(%p)->(%p) stub!\n", This, sample); static HRESULT WINAPI audio_sink_EndOfStream(IPin *iface)
{
FIXME("iface %p, stub!\n", iface);
return E_NOTIMPL;
}
static HRESULT WINAPI audio_sink_BeginFlush(IPin *iface)
{
FIXME("iface %p, stub!\n", iface);
return E_NOTIMPL; return E_NOTIMPL;
} }
static const BaseInputPinFuncTable AudioMediaStreamInputPin_FuncTable = static HRESULT WINAPI audio_sink_EndFlush(IPin *iface)
{ {
{ FIXME("iface %p, stub!\n", iface);
AudioMediaStreamInputPin_CheckMediaType, return E_NOTIMPL;
AudioMediaStreamInputPin_GetMediaType, }
},
AudioMediaStreamInputPin_Receive, static HRESULT WINAPI audio_sink_NewSegment(IPin *iface, REFERENCE_TIME start, REFERENCE_TIME stop, double rate)
{
FIXME("iface %p, start %s, stop %s, rate %0.16e, stub!\n",
iface, wine_dbgstr_longlong(start), wine_dbgstr_longlong(stop), rate);
return E_NOTIMPL;
}
static const IPinVtbl audio_sink_vtbl =
{
audio_sink_QueryInterface,
audio_sink_AddRef,
audio_sink_Release,
audio_sink_Connect,
audio_sink_ReceiveConnection,
audio_sink_Disconnect,
audio_sink_ConnectedTo,
audio_sink_ConnectionMediaType,
audio_sink_QueryPinInfo,
audio_sink_QueryDirection,
audio_sink_QueryId,
audio_sink_QueryAccept,
audio_sink_EnumMediaTypes,
audio_sink_QueryInternalConnections,
audio_sink_EndOfStream,
audio_sink_BeginFlush,
audio_sink_EndFlush,
audio_sink_NewSegment,
}; };
static inline struct audio_stream *impl_from_IMemInputPin(IMemInputPin *iface) static inline struct audio_stream *impl_from_IMemInputPin(IMemInputPin *iface)
...@@ -897,8 +1018,6 @@ HRESULT audiomediastream_create(IMultiMediaStream *parent, const MSPID *purpose_ ...@@ -897,8 +1018,6 @@ HRESULT audiomediastream_create(IMultiMediaStream *parent, const MSPID *purpose_
IUnknown *stream_object, STREAM_TYPE stream_type, IAMMediaStream **media_stream) IUnknown *stream_object, STREAM_TYPE stream_type, IAMMediaStream **media_stream)
{ {
struct audio_stream *object; struct audio_stream *object;
PIN_INFO pin_info;
HRESULT hr;
TRACE("(%p,%s,%p,%p)\n", parent, debugstr_guid(purpose_id), stream_object, media_stream); TRACE("(%p,%s,%p,%p)\n", parent, debugstr_guid(purpose_id), stream_object, media_stream);
...@@ -912,22 +1031,10 @@ HRESULT audiomediastream_create(IMultiMediaStream *parent, const MSPID *purpose_ ...@@ -912,22 +1031,10 @@ HRESULT audiomediastream_create(IMultiMediaStream *parent, const MSPID *purpose_
object->IAMMediaStream_iface.lpVtbl = &AudioMediaStreamImpl_IAMMediaStream_Vtbl; object->IAMMediaStream_iface.lpVtbl = &AudioMediaStreamImpl_IAMMediaStream_Vtbl;
object->IAudioMediaStream_iface.lpVtbl = &AudioMediaStreamImpl_IAudioMediaStream_Vtbl; object->IAudioMediaStream_iface.lpVtbl = &AudioMediaStreamImpl_IAudioMediaStream_Vtbl;
object->IMemInputPin_iface.lpVtbl = &audio_meminput_vtbl; object->IMemInputPin_iface.lpVtbl = &audio_meminput_vtbl;
object->IPin_iface.lpVtbl = &audio_sink_vtbl;
object->ref = 1; object->ref = 1;
InitializeCriticalSection(&object->critical_section); InitializeCriticalSection(&object->cs);
pin_info.pFilter = NULL;
pin_info.dir = PINDIR_INPUT;
pin_info.achName[0] = 'I';
StringFromGUID2(purpose_id, pin_info.achName + 1, MAX_PIN_NAME - 1);
hr = BaseInputPin_Construct(&AudioMediaStreamInputPin_IPin_Vtbl,
sizeof(AudioMediaStreamInputPin), &pin_info, &AudioMediaStreamInputPin_FuncTable,
&object->critical_section, NULL, (IPin **)&object->input_pin);
if (FAILED(hr))
goto out_object;
object->input_pin->parent = object;
object->parent = parent; object->parent = parent;
object->purpose_id = *purpose_id; object->purpose_id = *purpose_id;
object->stream_type = stream_type; object->stream_type = stream_type;
...@@ -935,9 +1042,4 @@ HRESULT audiomediastream_create(IMultiMediaStream *parent, const MSPID *purpose_ ...@@ -935,9 +1042,4 @@ HRESULT audiomediastream_create(IMultiMediaStream *parent, const MSPID *purpose_
*media_stream = &object->IAMMediaStream_iface; *media_stream = &object->IAMMediaStream_iface;
return S_OK; return S_OK;
out_object:
HeapFree(GetProcessHeap(), 0, object);
return hr;
} }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment