amstream: Reimplement IBaseFilter methods in the media stream filter.

In the long (or even short) term we probably want to decouple amstream from
strmbase entirely. The fact that pins and filters belong to separate objects
(and either one can even be provided by the application) prevents us from
performing some helpful restructuring.

Signed-off-by: Zebediah Figura <z.figura12@gmail.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Zebediah Figura 2019-05-17 00:31:06 -05:00 committed by Alexandre Julliard
parent f423c6e707
commit 7ef5f3be5a
1 changed files with 144 additions and 81 deletions

View File

@ -18,19 +18,9 @@
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include "wine/debug.h"
#define COBJMACROS
#include "winbase.h"
#include "wingdi.h"
#include "dshow.h"
#include "wine/strmbase.h"
#include "amstream_private.h"
#include "ddstream.h"
#include "wine/debug.h"
WINE_DEFAULT_DEBUG_CHANNEL(amstream);
@ -171,18 +161,22 @@ static const IEnumPinsVtbl enum_pins_vtbl =
};
typedef struct {
BaseFilter filter;
IMediaStreamFilter IMediaStreamFilter_iface;
LONG refcount;
CRITICAL_SECTION cs;
IReferenceClock *clock;
WCHAR name[128];
IFilterGraph *graph;
ULONG nb_streams;
IAMMediaStream** streams;
} IMediaStreamFilterImpl;
static inline IMediaStreamFilterImpl *impl_from_IMediaStreamFilter(IMediaStreamFilter *iface)
{
return CONTAINING_RECORD(iface, IMediaStreamFilterImpl, filter);
return CONTAINING_RECORD(iface, IMediaStreamFilterImpl, IMediaStreamFilter_iface);
}
/*** IUnknown methods ***/
static HRESULT WINAPI MediaStreamFilterImpl_QueryInterface(IMediaStreamFilter *iface, REFIID riid, void **ret_iface)
{
TRACE("(%p)->(%s, %p)\n", iface, debugstr_guid(riid), ret_iface);
@ -207,47 +201,45 @@ static HRESULT WINAPI MediaStreamFilterImpl_QueryInterface(IMediaStreamFilter *i
static ULONG WINAPI MediaStreamFilterImpl_AddRef(IMediaStreamFilter *iface)
{
IMediaStreamFilterImpl *This = impl_from_IMediaStreamFilter(iface);
ULONG ref = BaseFilterImpl_AddRef(&This->filter.IBaseFilter_iface);
IMediaStreamFilterImpl *filter = impl_from_IMediaStreamFilter(iface);
ULONG refcount = InterlockedIncrement(&filter->refcount);
TRACE("(%p)->(): new ref = %u\n", iface, ref);
TRACE("%p increasing refcount to %u.\n", iface, refcount);
return ref;
return refcount;
}
static ULONG WINAPI MediaStreamFilterImpl_Release(IMediaStreamFilter *iface)
{
IMediaStreamFilterImpl *This = impl_from_IMediaStreamFilter(iface);
ULONG ref = InterlockedDecrement(&This->filter.refCount);
IMediaStreamFilterImpl *filter = impl_from_IMediaStreamFilter(iface);
ULONG refcount = InterlockedDecrement(&filter->refcount);
unsigned int i;
TRACE("(%p)->(): new ref = %u\n", iface, ref);
TRACE("%p decreasing refcount to %u.\n", iface, refcount);
if (!ref)
if (!refcount)
{
ULONG i;
for (i = 0; i < This->nb_streams; i++)
for (i = 0; i < filter->nb_streams; ++i)
{
IAMMediaStream_JoinFilter(This->streams[i], NULL);
IAMMediaStream_Release(This->streams[i]);
IAMMediaStream_JoinFilter(filter->streams[i], NULL);
IAMMediaStream_Release(filter->streams[i]);
}
CoTaskMemFree(This->streams);
BaseFilter_Destroy(&This->filter);
HeapFree(GetProcessHeap(), 0, This);
heap_free(filter->streams);
if (filter->clock)
IReferenceClock_Release(filter->clock);
DeleteCriticalSection(&filter->cs);
heap_free(filter);
}
return ref;
return refcount;
}
/*** IPersist methods ***/
static HRESULT WINAPI MediaStreamFilterImpl_GetClassID(IMediaStreamFilter *iface, CLSID *clsid)
{
IMediaStreamFilterImpl *This = impl_from_IMediaStreamFilter(iface);
return BaseFilterImpl_GetClassID(&This->filter.IBaseFilter_iface, clsid);
*clsid = CLSID_MediaStreamFilter;
return S_OK;
}
/*** IBaseFilter methods ***/
static HRESULT WINAPI MediaStreamFilterImpl_Stop(IMediaStreamFilter *iface)
{
FIXME("(%p)->(): Stub!\n", iface);
@ -269,22 +261,48 @@ static HRESULT WINAPI MediaStreamFilterImpl_Run(IMediaStreamFilter *iface, REFER
return E_NOTIMPL;
}
static HRESULT WINAPI MediaStreamFilterImpl_GetState(IMediaStreamFilter *iface, DWORD ms_timeout, FILTER_STATE *state)
static HRESULT WINAPI MediaStreamFilterImpl_GetState(IMediaStreamFilter *iface, DWORD timeout, FILTER_STATE *state)
{
IMediaStreamFilterImpl *This = impl_from_IMediaStreamFilter(iface);
return BaseFilterImpl_GetState(&This->filter.IBaseFilter_iface, ms_timeout, state);
FIXME("iface %p, timeout %u, state %p, stub!\n", iface, timeout, state);
*state = State_Stopped;
return S_OK;
}
static HRESULT WINAPI MediaStreamFilterImpl_SetSyncSource(IMediaStreamFilter *iface, IReferenceClock *clock)
{
IMediaStreamFilterImpl *This = impl_from_IMediaStreamFilter(iface);
return BaseFilterImpl_SetSyncSource(&This->filter.IBaseFilter_iface, clock);
IMediaStreamFilterImpl *filter = impl_from_IMediaStreamFilter(iface);
TRACE("iface %p, clock %p.\n", iface, clock);
EnterCriticalSection(&filter->cs);
if (clock)
IReferenceClock_AddRef(clock);
if (filter->clock)
IReferenceClock_Release(filter->clock);
filter->clock = clock;
LeaveCriticalSection(&filter->cs);
return S_OK;
}
static HRESULT WINAPI MediaStreamFilterImpl_GetSyncSource(IMediaStreamFilter *iface, IReferenceClock **clock)
{
IMediaStreamFilterImpl *This = impl_from_IMediaStreamFilter(iface);
return BaseFilterImpl_GetSyncSource(&This->filter.IBaseFilter_iface, clock);
IMediaStreamFilterImpl *filter = impl_from_IMediaStreamFilter(iface);
TRACE("iface %p, clock %p.\n", iface, clock);
EnterCriticalSection(&filter->cs);
if (filter->clock)
IReferenceClock_AddRef(filter->clock);
*clock = filter->clock;
LeaveCriticalSection(&filter->cs);
return S_OK;
}
static HRESULT WINAPI MediaStreamFilterImpl_EnumPins(IMediaStreamFilter *iface, IEnumPins **enum_pins)
@ -295,6 +313,8 @@ static HRESULT WINAPI MediaStreamFilterImpl_EnumPins(IMediaStreamFilter *iface,
TRACE("iface %p, enum_pins %p.\n", iface, enum_pins);
EnterCriticalSection(&filter->cs);
if (!enum_pins)
return E_POINTER;
@ -316,32 +336,91 @@ static HRESULT WINAPI MediaStreamFilterImpl_EnumPins(IMediaStreamFilter *iface,
WARN("Stream %p does not support IPin.\n", filter->streams[i]);
}
LeaveCriticalSection(&filter->cs);
*enum_pins = &object->IEnumPins_iface;
return S_OK;
}
static HRESULT WINAPI MediaStreamFilterImpl_FindPin(IMediaStreamFilter *iface, LPCWSTR id, IPin **pin)
static HRESULT WINAPI MediaStreamFilterImpl_FindPin(IMediaStreamFilter *iface, const WCHAR *id, IPin **out)
{
IMediaStreamFilterImpl *This = impl_from_IMediaStreamFilter(iface);
return BaseFilterImpl_FindPin(&This->filter.IBaseFilter_iface, id, pin);
IMediaStreamFilterImpl *filter = impl_from_IMediaStreamFilter(iface);
unsigned int i;
WCHAR *ret_id;
IPin *pin;
TRACE("iface %p, id %s, out %p.\n", iface, debugstr_w(id), out);
EnterCriticalSection(&filter->cs);
for (i = 0; i < filter->nb_streams; ++i)
{
if (FAILED(IAMMediaStream_QueryInterface(filter->streams[i], &IID_IPin, (void **)&pin)))
{
WARN("Stream %p does not support IPin.\n", filter->streams[i]);
continue;
}
if (SUCCEEDED(IPin_QueryId(pin, &ret_id)))
{
if (!lstrcmpW(id, ret_id))
{
CoTaskMemFree(ret_id);
*out = pin;
return S_OK;
}
CoTaskMemFree(ret_id);
}
IPin_Release(pin);
}
LeaveCriticalSection(&filter->cs);
return VFW_E_NOT_FOUND;
}
static HRESULT WINAPI MediaStreamFilterImpl_QueryFilterInfo(IMediaStreamFilter *iface, FILTER_INFO *info)
{
IMediaStreamFilterImpl *This = impl_from_IMediaStreamFilter(iface);
return BaseFilterImpl_QueryFilterInfo(&This->filter.IBaseFilter_iface, info);
IMediaStreamFilterImpl *filter = impl_from_IMediaStreamFilter(iface);
TRACE("iface %p, info %p.\n", iface, info);
EnterCriticalSection(&filter->cs);
lstrcpyW(info->achName, filter->name);
if (filter->graph)
IFilterGraph_AddRef(filter->graph);
info->pGraph = filter->graph;
LeaveCriticalSection(&filter->cs);
return S_OK;
}
static HRESULT WINAPI MediaStreamFilterImpl_JoinFilterGraph(IMediaStreamFilter *iface, IFilterGraph *graph, LPCWSTR name)
static HRESULT WINAPI MediaStreamFilterImpl_JoinFilterGraph(IMediaStreamFilter *iface,
IFilterGraph *graph, const WCHAR *name)
{
IMediaStreamFilterImpl *This = impl_from_IMediaStreamFilter(iface);
return BaseFilterImpl_JoinFilterGraph(&This->filter.IBaseFilter_iface, graph, name);
IMediaStreamFilterImpl *filter = impl_from_IMediaStreamFilter(iface);
TRACE("iface %p, graph %p, name.%s.\n", iface, graph, debugstr_w(name));
EnterCriticalSection(&filter->cs);
if (name)
lstrcpynW(filter->name, name, ARRAY_SIZE(filter->name));
else
filter->name[0] = 0;
filter->graph = graph;
LeaveCriticalSection(&filter->cs);
return S_OK;
}
static HRESULT WINAPI MediaStreamFilterImpl_QueryVendorInfo(IMediaStreamFilter *iface, LPWSTR *vendor_info)
{
IMediaStreamFilterImpl *This = impl_from_IMediaStreamFilter(iface);
return BaseFilterImpl_QueryVendorInfo(&This->filter.IBaseFilter_iface, vendor_info);
WARN("iface %p, vendor_info %p, stub!\n", iface, vendor_info);
return E_NOTIMPL;
}
/*** IMediaStreamFilter methods ***/
@ -470,40 +549,24 @@ static const IMediaStreamFilterVtbl MediaStreamFilter_Vtbl =
MediaStreamFilterImpl_EndOfStream
};
static IPin* WINAPI MediaStreamFilterImpl_GetPin(BaseFilter *iface, int pos)
HRESULT MediaStreamFilter_create(IUnknown *outer, void **out)
{
IMediaStreamFilterImpl* This = (IMediaStreamFilterImpl*)iface;
IMediaStreamFilterImpl *object;
if (pos < This->nb_streams)
{
IPin *pin = NULL;
IAMMediaStream_QueryInterface(This->streams[pos], &IID_IPin, (void **)&pin);
return pin;
}
TRACE("outer %p, out %p.\n", outer, out);
return NULL;
}
static const BaseFilterFuncTable BaseFuncTable = {
MediaStreamFilterImpl_GetPin,
};
HRESULT MediaStreamFilter_create(IUnknown *pUnkOuter, void **ppObj)
{
IMediaStreamFilterImpl* object;
TRACE("(%p,%p)\n", pUnkOuter, ppObj);
if( pUnkOuter )
if (outer)
return CLASS_E_NOAGGREGATION;
object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IMediaStreamFilterImpl));
if (!object)
if (!(object = heap_alloc_zero(sizeof(*object))))
return E_OUTOFMEMORY;
BaseFilter_Init(&object->filter, (IBaseFilterVtbl*)&MediaStreamFilter_Vtbl, &CLSID_MediaStreamFilter, (DWORD_PTR)(__FILE__ ": MediaStreamFilterImpl.csFilter"), &BaseFuncTable);
*ppObj = &object->filter.IBaseFilter_iface;
object->IMediaStreamFilter_iface.lpVtbl = &MediaStreamFilter_Vtbl;
object->refcount = 1;
InitializeCriticalSection(&object->cs);
object->cs.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": MediaStreamFilter.cs");
TRACE("Created media stream filter %p.\n", object);
*out = &object->IMediaStreamFilter_iface;
return S_OK;
}