#include "qedit_private.h"
+#include <wine/strmbase.h>
+
static const WCHAR vendor_name[] = { 'W', 'i', 'n', 'e', 0 };
static const WCHAR pin_in_name[] = { 'I', 'n', 0 };
static const WCHAR pin_out_name[] = { 'O', 'u', 't', 0 };
-static IEnumPins *pinsenum_create(IBaseFilter *filter, IPin **pins, ULONG pinCount);
static IEnumMediaTypes *mediaenum_create(const AM_MEDIA_TYPE *mtype);
-/* Fixed pins enumerator, holds filter referenced */
-typedef struct _PE_Impl {
- IEnumPins pe;
- IBaseFilter *filter;
- LONG refCount;
- ULONG numPins;
- ULONG index;
- IPin *pins[0];
-} PE_Impl;
-
-
-/* IEnumPins interface implementation */
-
-/* IUnknown */
-static ULONG WINAPI
-Fixed_IEnumPins_AddRef(IEnumPins *iface)
-{
- PE_Impl *This = (PE_Impl *)iface;
- ULONG refCount = InterlockedIncrement(&This->refCount);
- TRACE("(%p) new ref = %u\n", This, refCount);
- return refCount;
-}
-
-/* IUnknown */
-static ULONG WINAPI
-Fixed_IEnumPins_Release(IEnumPins *iface)
-{
- PE_Impl *This = (PE_Impl *)iface;
- ULONG refCount = InterlockedDecrement(&This->refCount);
- TRACE("(%p) new ref = %u\n", This, refCount);
- if (refCount == 0)
- {
- IBaseFilter_Release(This->filter);
- CoTaskMemFree(This);
- return 0;
- }
- return refCount;
-}
-
-/* IUnknown */
-static HRESULT WINAPI
-Fixed_IEnumPins_QueryInterface(IEnumPins *iface, REFIID riid, void **ppvObject)
-{
- PE_Impl *This = (PE_Impl *)iface;
- TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppvObject);
-
- if (IsEqualIID(riid, &IID_IUnknown) ||
- IsEqualIID(riid, &IID_IEnumPins)) {
- Fixed_IEnumPins_AddRef(iface);
- *ppvObject = This->pins;
- return S_OK;
- }
- *ppvObject = NULL;
- WARN("(%p, %s,%p): not found\n", This, debugstr_guid(riid), ppvObject);
- return E_NOINTERFACE;
-}
-
-/* IEnumPins */
-static HRESULT WINAPI
-Fixed_IEnumPins_Next(IEnumPins *iface, ULONG nPins, IPin **pins, ULONG *fetched)
-{
- PE_Impl *This = (PE_Impl *)iface;
- ULONG count = 0;
- TRACE("(%p)->(%u, %p, %p) index = %u\n", This, nPins, pins, fetched, This->index);
- if (!nPins)
- return E_INVALIDARG;
- if (!pins || ((nPins != 1) && !fetched))
- return E_POINTER;
- while ((count < nPins) && (This->index < This->numPins)) {
- IPin *pin = This->pins[This->index++];
- IPin_AddRef(pin);
- pins[count++] = pin;
- }
- if (fetched)
- *fetched = count;
- return (count == nPins) ? S_OK : S_FALSE;
-}
-
-/* IEnumPins */
-static HRESULT WINAPI
-Fixed_IEnumPins_Skip(IEnumPins *iface, ULONG nPins)
-{
- PE_Impl *This = (PE_Impl *)iface;
- TRACE("(%p)->(%u) index = %u\n", This, nPins, This->index);
- nPins += This->index;
- if (nPins >= This->numPins) {
- This->index = This->numPins;
- return S_FALSE;
- }
- This->index = nPins;
- return S_OK;
-}
-
-/* IEnumPins */
-static HRESULT WINAPI
-Fixed_IEnumPins_Reset(IEnumPins *iface)
-{
- PE_Impl *This = (PE_Impl *)iface;
- TRACE("(%p)->() index = %u\n", This, This->index);
- This->index = 0;
- return S_OK;
-}
-
-/* IEnumPins */
-static HRESULT WINAPI
-Fixed_IEnumPins_Clone(IEnumPins *iface, IEnumPins **pins)
-{
- PE_Impl *This = (PE_Impl *)iface;
- TRACE("(%p)->(%p) index = %u\n", This, pins, This->index);
- if (!pins)
- return E_POINTER;
- *pins = pinsenum_create(This->filter, This->pins, This->numPins);
- if (!*pins)
- return E_OUTOFMEMORY;
- ((PE_Impl *)*pins)->index = This->index;
- return S_OK;
-}
-
-
-/* Virtual tables and constructor */
-
-static const IEnumPinsVtbl IEnumPins_VTable =
-{
- Fixed_IEnumPins_QueryInterface,
- Fixed_IEnumPins_AddRef,
- Fixed_IEnumPins_Release,
- Fixed_IEnumPins_Next,
- Fixed_IEnumPins_Skip,
- Fixed_IEnumPins_Reset,
- Fixed_IEnumPins_Clone,
-};
-
-static IEnumPins *pinsenum_create(IBaseFilter *filter, IPin **pins, ULONG pinCount)
-{
- ULONG len = sizeof(PE_Impl) + (pinCount * sizeof(IPin *));
- PE_Impl *obj = CoTaskMemAlloc(len);
- if (obj) {
- ULONG i;
- ZeroMemory(obj, len);
- obj->pe.lpVtbl = &IEnumPins_VTable;
- obj->refCount = 1;
- obj->filter = filter;
- obj->numPins = pinCount;
- obj->index = 0;
- for (i=0; i<pinCount; i++)
- obj->pins[i] = pins[i];
- IBaseFilter_AddRef(filter);
- }
- return &obj->pe;
-}
-
-
/* Single media type enumerator */
typedef struct _ME_Impl {
IEnumMediaTypes me;
/* Sample Grabber filter implementation */
typedef struct _SG_Impl {
IUnknown IUnknown_inner;
- IBaseFilter IBaseFilter_iface;
+ BaseFilter filter;
ISampleGrabber ISampleGrabber_iface;
- IMemInputPin IMemInputPin_iface;
/* IMediaSeeking and IMediaPosition are implemented by ISeekingPassThru */
IUnknown* seekthru_unk;
- /* TODO: IQualityControl */
IUnknown *outer_unk;
- LONG ref;
- CRITICAL_SECTION critSect;
- FILTER_INFO info;
- FILTER_STATE state;
AM_MEDIA_TYPE mtype;
SG_Pin pin_in;
SG_Pin pin_out;
+ IMemInputPin IMemInputPin_iface;
IMemAllocator *allocator;
- IReferenceClock *refClock;
IMemInputPin *memOutput;
ISampleGrabberCB *grabberIface;
LONG grabberMethod;
return CONTAINING_RECORD(iface, SG_Impl, IUnknown_inner);
}
+static inline SG_Impl *impl_from_BaseFilter(BaseFilter *iface)
+{
+ return CONTAINING_RECORD(iface, SG_Impl, filter);
+}
+
static inline SG_Impl *impl_from_IBaseFilter(IBaseFilter *iface)
{
- return CONTAINING_RECORD(iface, SG_Impl, IBaseFilter_iface);
+ return CONTAINING_RECORD(iface, SG_Impl, filter.IBaseFilter_iface);
}
static inline SG_Impl *impl_from_ISampleGrabber(ISampleGrabber *iface)
static void SampleGrabber_cleanup(SG_Impl *This)
{
TRACE("(%p)\n", This);
- if (This->info.pGraph)
- WARN("(%p) still joined to filter graph %p\n", This, This->info.pGraph);
+ if (This->filter.filterInfo.pGraph)
+ WARN("(%p) still joined to filter graph %p\n", This, This->filter.filterInfo.pGraph);
if (This->allocator)
IMemAllocator_Release(This->allocator);
- if (This->refClock)
- IReferenceClock_Release(This->refClock);
if (This->memOutput)
IMemInputPin_Release(This->memOutput);
if (This->grabberIface)
CoTaskMemFree(This->bufferData);
if(This->seekthru_unk)
IUnknown_Release(This->seekthru_unk);
- This->critSect.DebugInfo->Spare[0] = 0;
- DeleteCriticalSection(&This->critSect);
}
/* SampleGrabber inner IUnknown */
*ppv = &This->IUnknown_inner;
else if (IsEqualIID(riid, &IID_IPersist) || IsEqualIID(riid, &IID_IMediaFilter) ||
IsEqualIID(riid, &IID_IBaseFilter))
- *ppv = &This->IBaseFilter_iface;
+ *ppv = &This->filter.IBaseFilter_iface;
else if (IsEqualIID(riid, &IID_ISampleGrabber))
*ppv = &This->ISampleGrabber_iface;
- else if (IsEqualIID(riid, &IID_IMemInputPin))
- *ppv = &This->IMemInputPin_iface;
else if (IsEqualIID(riid, &IID_IMediaPosition))
return IUnknown_QueryInterface(This->seekthru_unk, riid, ppv);
else if (IsEqualIID(riid, &IID_IMediaSeeking))
return IUnknown_QueryInterface(This->seekthru_unk, riid, ppv);
- else if (IsEqualIID(riid, &IID_IQualityControl))
- FIXME("IQualityControl not implemented\n");
else
WARN("(%p, %s,%p): not found\n", This, debugstr_guid(riid), ppv);
static ULONG WINAPI SampleGrabber_AddRef(IUnknown *iface)
{
SG_Impl *This = impl_from_IUnknown(iface);
- ULONG ref = InterlockedIncrement(&This->ref);
+ ULONG ref = BaseFilterImpl_AddRef(&This->filter.IBaseFilter_iface);
- TRACE("(%p) new ref = %u\n", This, ref);
+ TRACE("(%p) ref=%d\n", This, ref);
return ref;
}
static ULONG WINAPI SampleGrabber_Release(IUnknown *iface)
{
SG_Impl *This = impl_from_IUnknown(iface);
- ULONG ref = InterlockedDecrement(&This->ref);
+ ULONG ref = BaseFilterImpl_Release(&This->filter.IBaseFilter_iface);
- TRACE("(%p) new ref = %u\n", This, ref);
+ TRACE("(%p) ref=%d\n", This, ref);
if (ref == 0)
{
SampleGrabber_Release,
};
+static IPin *WINAPI SampleGrabber_GetPin(BaseFilter *iface, int pos)
+{
+ SG_Impl *This = impl_from_BaseFilter(iface);
+ IPin *pin;
+
+ if (pos == 0)
+ pin = &This->pin_in.IPin_iface;
+ else if (pos == 1)
+ pin = &This->pin_out.IPin_iface;
+ else
+ return NULL;
+
+ IPin_AddRef(pin);
+ return pin;
+}
+
+static LONG WINAPI SampleGrabber_GetPinCount(BaseFilter *iface)
+{
+ return 2;
+}
+
+static const BaseFilterFuncTable basefunc_vtbl = {
+ SampleGrabber_GetPin,
+ SampleGrabber_GetPinCount
+};
+
/* Helper that buffers data and/or calls installed sample callbacks */
static void SampleGrabber_callback(SG_Impl *This, IMediaSample *sample)
{
if (size >= 0 && SUCCEEDED(IMediaSample_GetPointer(sample, &data))) {
if (!data)
size = 0;
- EnterCriticalSection(&This->critSect);
+ EnterCriticalSection(&This->filter.csFilter);
if (This->bufferLen != size) {
if (This->bufferData)
CoTaskMemFree(This->bufferData);
}
if (size)
CopyMemory(This->bufferData, data, size);
- LeaveCriticalSection(&This->critSect);
+ LeaveCriticalSection(&This->filter.csFilter);
}
}
if (!This->grabberIface)
return IUnknown_Release(This->outer_unk);
}
-/* IPersist */
-static HRESULT WINAPI
-SampleGrabber_IBaseFilter_GetClassID(IBaseFilter *iface, CLSID *pClassID)
-{
- TRACE("(%p)\n", pClassID);
- if (!pClassID)
- return E_POINTER;
- *pClassID = CLSID_SampleGrabber;
- return S_OK;
-}
-
/* IMediaFilter */
static HRESULT WINAPI
SampleGrabber_IBaseFilter_Stop(IBaseFilter *iface)
{
SG_Impl *This = impl_from_IBaseFilter(iface);
TRACE("(%p)\n", This);
- This->state = State_Stopped;
+ This->filter.state = State_Stopped;
return S_OK;
}
{
SG_Impl *This = impl_from_IBaseFilter(iface);
TRACE("(%p)\n", This);
- This->state = State_Paused;
+ This->filter.state = State_Paused;
return S_OK;
}
{
SG_Impl *This = impl_from_IBaseFilter(iface);
TRACE("(%p)\n", This);
- This->state = State_Running;
- return S_OK;
-}
-
-/* IMediaFilter */
-static HRESULT WINAPI
-SampleGrabber_IBaseFilter_GetState(IBaseFilter *iface, DWORD msTout, FILTER_STATE *state)
-{
- SG_Impl *This = impl_from_IBaseFilter(iface);
- TRACE("(%p)->(%u, %p)\n", This, msTout, state);
- if (!state)
- return E_POINTER;
- *state = This->state;
- return S_OK;
-}
-
-/* IMediaFilter */
-static HRESULT WINAPI
-SampleGrabber_IBaseFilter_SetSyncSource(IBaseFilter *iface, IReferenceClock *clock)
-{
- SG_Impl *This = impl_from_IBaseFilter(iface);
- TRACE("(%p)->(%p)\n", This, clock);
- if (clock != This->refClock)
- {
- if (clock)
- IReferenceClock_AddRef(clock);
- if (This->refClock)
- IReferenceClock_Release(This->refClock);
- This->refClock = clock;
- }
- return S_OK;
-}
-
-/* IMediaFilter */
-static HRESULT WINAPI
-SampleGrabber_IBaseFilter_GetSyncSource(IBaseFilter *iface, IReferenceClock **clock)
-{
- SG_Impl *This = impl_from_IBaseFilter(iface);
- TRACE("(%p)->(%p)\n", This, clock);
- if (!clock)
- return E_POINTER;
- if (This->refClock)
- IReferenceClock_AddRef(This->refClock);
- *clock = This->refClock;
+ This->filter.state = State_Running;
return S_OK;
}
-/* IBaseFilter */
-static HRESULT WINAPI
-SampleGrabber_IBaseFilter_EnumPins(IBaseFilter *iface, IEnumPins **pins)
-{
- SG_Impl *This = impl_from_IBaseFilter(iface);
- IPin *pin[2];
- TRACE("(%p)->(%p)\n", This, pins);
- if (!pins)
- return E_POINTER;
- pin[0] = &This->pin_in.IPin_iface;
- pin[1] = &This->pin_out.IPin_iface;
- *pins = pinsenum_create(iface, pin, 2);
- return *pins ? S_OK : E_OUTOFMEMORY;
-}
-
/* IBaseFilter */
static HRESULT WINAPI
SampleGrabber_IBaseFilter_FindPin(IBaseFilter *iface, LPCWSTR id, IPin **pin)
return VFW_E_NOT_FOUND;
}
-/* IBaseFilter */
-static HRESULT WINAPI
-SampleGrabber_IBaseFilter_QueryFilterInfo(IBaseFilter *iface, FILTER_INFO *info)
-{
- SG_Impl *This = impl_from_IBaseFilter(iface);
- TRACE("(%p)->(%p)\n", This, info);
- if (!info)
- return E_POINTER;
- if (This->info.pGraph)
- IFilterGraph_AddRef(This->info.pGraph);
- *info = This->info;
- return S_OK;
-}
-
/* IBaseFilter */
static HRESULT WINAPI
SampleGrabber_IBaseFilter_JoinFilterGraph(IBaseFilter *iface, IFilterGraph *graph, LPCWSTR name)
{
SG_Impl *This = impl_from_IBaseFilter(iface);
+
TRACE("(%p)->(%p, %s)\n", This, graph, debugstr_w(name));
- This->info.pGraph = graph;
- if (name)
- lstrcpynW(This->info.achName,name,MAX_FILTER_NAME);
+
+ BaseFilterImpl_JoinFilterGraph(iface, graph, name);
This->oneShot = OneShot_None;
+
return S_OK;
}
{
SG_Impl *This = impl_from_ISampleGrabber(iface);
TRACE("(%p)->(%u)\n", This, bufferEm);
- EnterCriticalSection(&This->critSect);
+ EnterCriticalSection(&This->filter.csFilter);
if (bufferEm) {
if (This->bufferLen < 0)
This->bufferLen = 0;
}
else
This->bufferLen = -1;
- LeaveCriticalSection(&This->critSect);
+ LeaveCriticalSection(&This->filter.csFilter);
return S_OK;
}
TRACE("(%p)->(%p, %p)\n", This, bufSize, buffer);
if (!bufSize)
return E_POINTER;
- EnterCriticalSection(&This->critSect);
+ EnterCriticalSection(&This->filter.csFilter);
if (!This->pin_in.pair)
ret = VFW_E_NOT_CONNECTED;
else if (This->bufferLen < 0)
}
*bufSize = This->bufferLen;
}
- LeaveCriticalSection(&This->critSect);
+ LeaveCriticalSection(&This->filter.csFilter);
return ret;
}
TRACE("(%p)->(%p) output = %p, grabber = %p\n", This, sample, This->memOutput, This->grabberIface);
if (!sample)
return E_POINTER;
- if ((This->state != State_Running) || (This->oneShot == OneShot_Past))
+ if ((This->filter.state != State_Running) || (This->oneShot == OneShot_Past))
return S_FALSE;
SampleGrabber_callback(This, sample);
hr = This->memOutput ? IMemInputPin_Receive(This->memOutput, sample) : S_OK;
TRACE("(%p)->(%p, %u, %p) output = %p, grabber = %p\n", This, samples, nSamples, nProcessed, This->memOutput, This->grabberIface);
if (!samples || !nProcessed)
return E_POINTER;
- if ((This->state != State_Running) || (This->oneShot == OneShot_Past))
+ if ((This->filter.state != State_Running) || (This->oneShot == OneShot_Past))
return S_FALSE;
for (idx = 0; idx < nSamples; idx++)
SampleGrabber_callback(This, samples[idx]);
return E_POINTER;
if (This->pair)
return VFW_E_ALREADY_CONNECTED;
- if (This->sg->state != State_Stopped)
+ if (This->sg->filter.state != State_Stopped)
return VFW_E_NOT_STOPPED;
if (type) {
TRACE("Media type: %s/%s ssize: %u format: %s (%u bytes)\n",
return E_POINTER;
if (This->pair)
return VFW_E_ALREADY_CONNECTED;
- if (This->sg->state != State_Stopped)
+ if (This->sg->filter.state != State_Stopped)
return VFW_E_NOT_STOPPED;
if (type) {
TRACE("Media type: %s/%s ssize: %u format: %s (%u bytes)\n",
SG_Pin *This = impl_from_IPin(iface);
TRACE("(%p)->() pair = %p\n", This, This->pair);
- if (This->sg->state != State_Stopped)
+ if (This->sg->filter.state != State_Stopped)
return VFW_E_NOT_STOPPED;
if (This->pair) {
This->pair = NULL;
SG_Pin *This = impl_from_IPin(iface);
TRACE("(%p)->() pair = %p\n", This, This->pair);
- if (This->sg->state != State_Stopped)
+ if (This->sg->filter.state != State_Stopped)
return VFW_E_NOT_STOPPED;
if (This->pair) {
This->pair = NULL;
TRACE("(%p)->(%p)\n", This, info);
if (!info)
return E_POINTER;
- IBaseFilter_AddRef(&This->sg->IBaseFilter_iface);
- info->pFilter = &This->sg->IBaseFilter_iface;
+ info->pFilter = &This->sg->filter.IBaseFilter_iface;
+ IBaseFilter_AddRef(info->pFilter);
info->dir = This->dir;
lstrcpynW(info->achName,This->name,MAX_PIN_NAME);
return S_OK;
SampleGrabber_IBaseFilter_QueryInterface,
SampleGrabber_IBaseFilter_AddRef,
SampleGrabber_IBaseFilter_Release,
- SampleGrabber_IBaseFilter_GetClassID,
+ BaseFilterImpl_GetClassID,
SampleGrabber_IBaseFilter_Stop,
SampleGrabber_IBaseFilter_Pause,
SampleGrabber_IBaseFilter_Run,
- SampleGrabber_IBaseFilter_GetState,
- SampleGrabber_IBaseFilter_SetSyncSource,
- SampleGrabber_IBaseFilter_GetSyncSource,
- SampleGrabber_IBaseFilter_EnumPins,
+ BaseFilterImpl_GetState,
+ BaseFilterImpl_SetSyncSource,
+ BaseFilterImpl_GetSyncSource,
+ BaseFilterImpl_EnumPins,
SampleGrabber_IBaseFilter_FindPin,
- SampleGrabber_IBaseFilter_QueryFilterInfo,
+ BaseFilterImpl_QueryFilterInfo,
SampleGrabber_IBaseFilter_JoinFilterGraph,
SampleGrabber_IBaseFilter_QueryVendorInfo,
};
}
ZeroMemory(obj, sizeof(SG_Impl));
- obj->ref = 1;
+ BaseFilter_Init(&obj->filter, &IBaseFilter_VTable, &CLSID_SampleGrabber,
+ (DWORD_PTR)(__FILE__ ": SG_Impl.csFilter"), &basefunc_vtbl);
obj->IUnknown_inner.lpVtbl = &samplegrabber_vtbl;
- obj->IBaseFilter_iface.lpVtbl = &IBaseFilter_VTable;
obj->ISampleGrabber_iface.lpVtbl = &ISampleGrabber_VTable;
obj->IMemInputPin_iface.lpVtbl = &IMemInputPin_VTable;
obj->pin_in.IPin_iface.lpVtbl = &IPin_In_VTable;
obj->pin_out.name = pin_out_name;
obj->pin_out.sg = obj;
obj->pin_out.pair = NULL;
- InitializeCriticalSection(&obj->critSect);
- obj->critSect.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": SG_Impl.critSect");
- obj->info.achName[0] = 0;
- obj->info.pGraph = NULL;
- obj->state = State_Stopped;
obj->mtype.majortype = GUID_NULL;
obj->mtype.subtype = MEDIASUBTYPE_None;
obj->mtype.formattype = FORMAT_None;
obj->allocator = NULL;
- obj->refClock = NULL;
obj->memOutput = NULL;
obj->grabberIface = NULL;
obj->grabberMethod = -1;