[ros-diffs] [cwittich] 45752: [QEDIT] sync qedit to wine 1.1.39

cwittich at svn.reactos.org cwittich at svn.reactos.org
Tue Mar 2 12:28:12 CET 2010


Author: cwittich
Date: Tue Mar  2 12:28:12 2010
New Revision: 45752

URL: http://svn.reactos.org/svn/reactos?rev=45752&view=rev
Log:
[QEDIT]
sync qedit to wine 1.1.39

Modified:
    trunk/reactos/dll/directx/qedit/samplegrabber.c

Modified: trunk/reactos/dll/directx/qedit/samplegrabber.c
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/directx/qedit/samplegrabber.c?rev=45752&r1=45751&r2=45752&view=diff
==============================================================================
--- trunk/reactos/dll/directx/qedit/samplegrabber.c [iso-8859-1] (original)
+++ trunk/reactos/dll/directx/qedit/samplegrabber.c [iso-8859-1] Tue Mar  2 12:28:12 2010
@@ -33,18 +33,352 @@
 WINE_DEFAULT_DEBUG_CHANNEL(qedit);
 
 static WCHAR const vendor_name[] = { 'W', 'i', 'n', 'e', 0 };
+static WCHAR const pin_in_name[] = { 'I', 'n', 0 };
+static WCHAR const pin_out_name[] = { 'O', 'u', 't', 0 };
+
+IEnumPins *pinsenum_create(IBaseFilter *filter, IPin **pins, ULONG pinCount);
+IEnumMediaTypes *mediaenum_create(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,
+};
+
+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;
+    LONG refCount;
+    BOOL past;
+    AM_MEDIA_TYPE mtype;
+} ME_Impl;
+
+
+/* IEnumMediaTypes interface implementation */
+
+/* IUnknown */
+static ULONG WINAPI
+Single_IEnumMediaTypes_AddRef(IEnumMediaTypes *iface)
+{
+    ME_Impl *This = (ME_Impl *)iface;
+    ULONG refCount = InterlockedIncrement(&This->refCount);
+    TRACE("(%p) new ref = %u\n", This, refCount);
+    return refCount;
+}
+
+/* IUnknown */
+static ULONG WINAPI
+Single_IEnumMediaTypes_Release(IEnumMediaTypes *iface)
+{
+    ME_Impl *This = (ME_Impl *)iface;
+    ULONG refCount = InterlockedDecrement(&This->refCount);
+    TRACE("(%p) new ref = %u\n", This, refCount);
+    if (refCount == 0)
+    {
+        if (This->mtype.pbFormat)
+            CoTaskMemFree(This->mtype.pbFormat);
+        CoTaskMemFree(This);
+        return 0;
+    }
+    return refCount;
+}
+
+/* IUnknown */
+static HRESULT WINAPI
+Single_IEnumMediaTypes_QueryInterface(IEnumMediaTypes *iface, REFIID riid, void **ppvObject)
+{
+    ME_Impl *This = (ME_Impl *)iface;
+    TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppvObject);
+
+    if (IsEqualIID(riid, &IID_IUnknown) ||
+        IsEqualIID(riid, &IID_IEnumMediaTypes)) {
+        Single_IEnumMediaTypes_AddRef(iface);
+        *ppvObject = &(This->me);
+        return S_OK;
+    }
+    *ppvObject = NULL;
+    WARN("(%p, %s,%p): not found\n", This, debugstr_guid(riid), ppvObject);
+    return E_NOINTERFACE;
+}
+
+/* IEnumMediaTypes */
+static HRESULT WINAPI
+Single_IEnumMediaTypes_Next(IEnumMediaTypes *iface, ULONG nTypes, AM_MEDIA_TYPE **types, ULONG *fetched)
+{
+    ME_Impl *This = (ME_Impl *)iface;
+    ULONG count = 0;
+    TRACE("(%p)->(%u, %p, %p)\n", This, nTypes, types, fetched);
+    if (!nTypes)
+        return E_INVALIDARG;
+    if (!types || ((nTypes != 1) && !fetched))
+        return E_POINTER;
+    if (!This->past) {
+        AM_MEDIA_TYPE *mtype = CoTaskMemAlloc(sizeof(AM_MEDIA_TYPE));
+        *mtype = This->mtype;
+        if (mtype->cbFormat) {
+            mtype->pbFormat = CoTaskMemAlloc(mtype->cbFormat);
+            CopyMemory(mtype->pbFormat, This->mtype.pbFormat, mtype->cbFormat);
+        }
+        *types = mtype;
+        This->past = TRUE;
+        count = 1;
+    }
+    if (fetched)
+        *fetched = count;
+    return (count == nTypes) ? S_OK : S_FALSE;
+}
+
+/* IEnumMediaTypes */
+static HRESULT WINAPI
+Single_IEnumMediaTypes_Skip(IEnumMediaTypes *iface, ULONG nTypes)
+{
+    ME_Impl *This = (ME_Impl *)iface;
+    TRACE("(%p)->(%u)\n", This, nTypes);
+    if (nTypes)
+        This->past = TRUE;
+    return This->past ? S_FALSE : S_OK;
+}
+
+/* IEnumMediaTypes */
+static HRESULT WINAPI
+Single_IEnumMediaTypes_Reset(IEnumMediaTypes *iface)
+{
+    ME_Impl *This = (ME_Impl *)iface;
+    TRACE("(%p)->()\n", This);
+    This->past = FALSE;
+    return S_OK;
+}
+
+/* IEnumMediaTypes */
+static HRESULT WINAPI
+Single_IEnumMediaTypes_Clone(IEnumMediaTypes *iface, IEnumMediaTypes **me)
+{
+    ME_Impl *This = (ME_Impl *)iface;
+    TRACE("(%p)->(%p)\n", This, me);
+    if (!me)
+        return E_POINTER;
+    *me = mediaenum_create(&This->mtype);
+    if (!*me)
+        return E_OUTOFMEMORY;
+    ((ME_Impl *)*me)->past = This->past;
+    return S_OK;
+}
+
+
+/* Virtual tables and constructor */
+
+static const IEnumMediaTypesVtbl IEnumMediaTypes_VTable =
+{
+    Single_IEnumMediaTypes_QueryInterface,
+    Single_IEnumMediaTypes_AddRef,
+    Single_IEnumMediaTypes_Release,
+    Single_IEnumMediaTypes_Next,
+    Single_IEnumMediaTypes_Skip,
+    Single_IEnumMediaTypes_Reset,
+    Single_IEnumMediaTypes_Clone,
+};
+
+IEnumMediaTypes *mediaenum_create(AM_MEDIA_TYPE *mtype)
+{
+    ME_Impl *obj = CoTaskMemAlloc(sizeof(ME_Impl));
+    if (obj) {
+        ZeroMemory(obj, sizeof(ME_Impl));
+        obj->me.lpVtbl = &IEnumMediaTypes_VTable;
+        obj->refCount = 1;
+        obj->past = FALSE;
+        obj->mtype = *mtype;
+        obj->mtype.pUnk = NULL;
+        if (mtype->cbFormat) {
+            obj->mtype.pbFormat = CoTaskMemAlloc(mtype->cbFormat);
+            CopyMemory(obj->mtype.pbFormat, mtype->pbFormat, mtype->cbFormat);
+        }
+        else
+            obj->mtype.pbFormat = NULL;
+    }
+    return &obj->me;
+}
+
+
+/* Sample Grabber pin implementation */
+typedef struct _SG_Pin {
+    const IPinVtbl* lpVtbl;
+    PIN_DIRECTION dir;
+    WCHAR const *name;
+    struct _SG_Impl *sg;
+    IPin *pair;
+} SG_Pin;
 
 /* Sample Grabber filter implementation */
 typedef struct _SG_Impl {
     const IBaseFilterVtbl* IBaseFilter_Vtbl;
     const ISampleGrabberVtbl* ISampleGrabber_Vtbl;
+    const IMemInputPinVtbl* IMemInputPin_Vtbl;
     /* TODO: IMediaPosition, IMediaSeeking, IQualityControl */
     LONG refCount;
     FILTER_INFO info;
     FILTER_STATE state;
+    AM_MEDIA_TYPE mtype;
+    SG_Pin pin_in;
+    SG_Pin pin_out;
     IMemAllocator *allocator;
     IReferenceClock *refClock;
+    IMemInputPin *memOutput;
+    ISampleGrabberCB *grabberIface;
+    LONG grabberMethod;
+    LONG oneShot;
 } SG_Impl;
+
+enum {
+    OneShot_None,
+    OneShot_Wait,
+    OneShot_Past,
+};
 
 /* Get the SampleGrabber implementation This pointer from various interface pointers */
 static inline SG_Impl *impl_from_IBaseFilter(IBaseFilter *iface)
@@ -55,6 +389,11 @@
 static inline SG_Impl *impl_from_ISampleGrabber(ISampleGrabber *iface)
 {
     return (SG_Impl *)((char*)iface - FIELD_OFFSET(SG_Impl, ISampleGrabber_Vtbl));
+}
+
+static inline SG_Impl *impl_from_IMemInputPin(IMemInputPin *iface)
+{
+    return (SG_Impl *)((char*)iface - FIELD_OFFSET(SG_Impl, IMemInputPin_Vtbl));
 }
 
 
@@ -68,6 +407,12 @@
         IMemAllocator_Release(This->allocator);
     if (This->refClock)
 	IReferenceClock_Release(This->refClock);
+    if (This->memOutput)
+        IMemInputPin_Release(This->memOutput);
+    if (This->grabberIface)
+        ISampleGrabberCB_Release(This->grabberIface);
+    if (This->mtype.pbFormat)
+        CoTaskMemFree(This->mtype.pbFormat);
 }
 
 /* Common helper AddRef called from all interfaces */
@@ -110,8 +455,11 @@
         *ppvObject = &(This->ISampleGrabber_Vtbl);
         return S_OK;
     }
-    else if (IsEqualIID(riid, &IID_IMemInputPin))
-        FIXME("IMemInputPin not implemented\n");
+    else if (IsEqualIID(riid, &IID_IMemInputPin)) {
+        SampleGrabber_addref(This);
+        *ppvObject = &(This->IMemInputPin_Vtbl);
+        return S_OK;
+    }
     else if (IsEqualIID(riid, &IID_IMediaPosition))
         FIXME("IMediaPosition not implemented\n");
     else if (IsEqualIID(riid, &IID_IMediaSeeking))
@@ -123,6 +471,45 @@
     return E_NOINTERFACE;
 }
 
+/* Helper that calls installed sample callbacks */
+static void SampleGrabber_callback(SG_Impl *This, IMediaSample *sample)
+{
+    double time = 0.0;
+    REFERENCE_TIME tStart, tEnd;
+    if (SUCCEEDED(IMediaSample_GetTime(sample, &tStart, &tEnd)))
+        time = 1e-7 * tStart;
+    switch (This->grabberMethod) {
+        case 0:
+	    {
+		ULONG ref = IMediaSample_AddRef(sample);
+		ISampleGrabberCB_SampleCB(This->grabberIface, time, sample);
+		ref = IMediaSample_Release(sample) + 1 - ref;
+		if (ref)
+		{
+		    ERR("(%p) Callback referenced sample %p by %u\n", This, sample, ref);
+		    /* ugly as hell but some apps are sooo buggy */
+		    while (ref--)
+			IMediaSample_Release(sample);
+		}
+	    }
+            break;
+        case 1:
+            {
+                BYTE *data = 0;
+                long size = IMediaSample_GetActualDataLength(sample);
+                if (size && SUCCEEDED(IMediaSample_GetPointer(sample, &data)) && data)
+                    ISampleGrabberCB_BufferCB(This->grabberIface, time, data, size);
+            }
+            break;
+        case -1:
+            break;
+        default:
+            FIXME("unsupported method %ld\n", (long int)This->grabberMethod);
+            /* do not bother us again */
+            This->grabberMethod = -1;
+    }
+}
+
 
 /* SampleGrabber implementation of IBaseFilter interface */
 
@@ -236,10 +623,14 @@
 SampleGrabber_IBaseFilter_EnumPins(IBaseFilter *iface, IEnumPins **pins)
 {
     SG_Impl *This = impl_from_IBaseFilter(iface);
-    FIXME("(%p)->(%p): stub\n", This, pins);
+    IPin *pin[2];
+    TRACE("(%p)->(%p)\n", This, pins);
     if (!pins)
         return E_POINTER;
-    return E_OUTOFMEMORY;
+    pin[0] = (IPin*)&This->pin_in.lpVtbl;
+    pin[1] = (IPin*)&This->pin_out.lpVtbl;
+    *pins = pinsenum_create(iface, pin, 2);
+    return *pins ? S_OK : E_OUTOFMEMORY;
 }
 
 /* IBaseFilter */
@@ -247,9 +638,21 @@
 SampleGrabber_IBaseFilter_FindPin(IBaseFilter *iface, LPCWSTR id, IPin **pin)
 {
     SG_Impl *This = impl_from_IBaseFilter(iface);
-    FIXME("(%p)->(%s, %p): stub\n", This, debugstr_w(id), pin);
+    TRACE("(%p)->(%s, %p)\n", This, debugstr_w(id), pin);
     if (!id || !pin)
         return E_POINTER;
+    if (!lstrcmpiW(id,pin_in_name))
+    {
+        SampleGrabber_addref(This);
+        *pin = (IPin*)&(This->pin_in.lpVtbl);
+        return S_OK;
+    }
+    else if (!lstrcmpiW(id,pin_out_name))
+    {
+        SampleGrabber_addref(This);
+        *pin = (IPin*)&(This->pin_out.lpVtbl);
+        return S_OK;
+    }
     *pin = NULL;
     return VFW_E_NOT_FOUND;
 }
@@ -277,6 +680,7 @@
     This->info.pGraph = graph;
     if (name)
 	lstrcpynW(This->info.achName,name,MAX_FILTER_NAME);
+    This->oneShot = OneShot_None;
     return S_OK;
 }
 
@@ -321,8 +725,9 @@
 SampleGrabber_ISampleGrabber_SetOneShot(ISampleGrabber *iface, BOOL oneShot)
 {
     SG_Impl *This = impl_from_ISampleGrabber(iface);
-    FIXME("(%p)->(%u): stub\n", This, oneShot);
-    return E_NOTIMPL;
+    TRACE("(%p)->(%u)\n", This, oneShot);
+    This->oneShot = oneShot ? OneShot_Wait : OneShot_None;
+    return S_OK;
 }
 
 /* ISampleGrabber */
@@ -330,10 +735,24 @@
 SampleGrabber_ISampleGrabber_SetMediaType(ISampleGrabber *iface, const AM_MEDIA_TYPE *type)
 {
     SG_Impl *This = impl_from_ISampleGrabber(iface);
-    FIXME("(%p)->(%p): stub\n", This, type);
+    TRACE("(%p)->(%p)\n", This, type);
     if (!type)
         return E_POINTER;
-    return E_NOTIMPL;
+    TRACE("Media type: %s/%s ssize: %u format: %s (%u bytes)\n",
+	debugstr_guid(&type->majortype), debugstr_guid(&type->subtype),
+	type->lSampleSize,
+	debugstr_guid(&type->formattype), type->cbFormat);
+    if (This->mtype.pbFormat)
+        CoTaskMemFree(This->mtype.pbFormat);
+    This->mtype = *type;
+    This->mtype.pUnk = NULL;
+    if (type->cbFormat) {
+        This->mtype.pbFormat = CoTaskMemAlloc(type->cbFormat);
+        CopyMemory(This->mtype.pbFormat, type->pbFormat, type->cbFormat);
+    }
+    else
+        This->mtype.pbFormat = NULL;
+    return S_OK;
 }
 
 /* ISampleGrabber */
@@ -341,10 +760,17 @@
 SampleGrabber_ISampleGrabber_GetConnectedMediaType(ISampleGrabber *iface, AM_MEDIA_TYPE *type)
 {
     SG_Impl *This = impl_from_ISampleGrabber(iface);
-    FIXME("(%p)->(%p): stub\n", This, type);
+    TRACE("(%p)->(%p)\n", This, type);
     if (!type)
         return E_POINTER;
-    return E_NOTIMPL;
+    if (!This->pin_in.pair)
+        return VFW_E_NOT_CONNECTED;
+    *type = This->mtype;
+    if (type->cbFormat) {
+        type->pbFormat = CoTaskMemAlloc(type->cbFormat);
+        CopyMemory(type->pbFormat, This->mtype.pbFormat, type->cbFormat);
+    }
+    return S_OK;
 }
 
 /* ISampleGrabber */
@@ -383,8 +809,465 @@
 SampleGrabber_ISampleGrabber_SetCallback(ISampleGrabber *iface, ISampleGrabberCB *cb, LONG whichMethod)
 {
     SG_Impl *This = impl_from_ISampleGrabber(iface);
-    FIXME("(%p)->(%p, %u): stub\n", This, cb, whichMethod);
+    TRACE("(%p)->(%p, %u)\n", This, cb, whichMethod);
+    if (This->grabberIface)
+        ISampleGrabberCB_Release(This->grabberIface);
+    This->grabberIface = cb;
+    This->grabberMethod = whichMethod;
+    if (cb)
+        ISampleGrabberCB_AddRef(cb);
+    return S_OK;
+}
+
+
+/* SampleGrabber implementation of IMemInputPin interface */
+
+/* IUnknown */
+static HRESULT WINAPI
+SampleGrabber_IMemInputPin_QueryInterface(IMemInputPin *iface, REFIID riid, void **ppvObject)
+{
+    return SampleGrabber_query(impl_from_IMemInputPin(iface), riid, ppvObject);
+}
+
+/* IUnknown */
+static ULONG WINAPI
+SampleGrabber_IMemInputPin_AddRef(IMemInputPin *iface)
+{
+    return SampleGrabber_addref(impl_from_IMemInputPin(iface));
+}
+
+/* IUnknown */
+static ULONG WINAPI
+SampleGrabber_IMemInputPin_Release(IMemInputPin *iface)
+{
+    return SampleGrabber_release(impl_from_IMemInputPin(iface));
+}
+
+/* IMemInputPin */
+static HRESULT WINAPI
+SampleGrabber_IMemInputPin_GetAllocator(IMemInputPin *iface, IMemAllocator **allocator)
+{
+    SG_Impl *This = impl_from_IMemInputPin(iface);
+    TRACE("(%p)->(%p) allocator = %p\n", This, allocator, This->allocator);
+    if (!allocator)
+        return E_POINTER;
+    *allocator = This->allocator;
+    if (!*allocator)
+        return VFW_E_NO_ALLOCATOR;
+    IMemAllocator_AddRef(*allocator);
+    return S_OK;
+}
+
+/* IMemInputPin */
+static HRESULT WINAPI
+SampleGrabber_IMemInputPin_NotifyAllocator(IMemInputPin *iface, IMemAllocator *allocator, BOOL readOnly)
+{
+    SG_Impl *This = impl_from_IMemInputPin(iface);
+    TRACE("(%p)->(%p, %u) allocator = %p\n", This, allocator, readOnly, This->allocator);
+    if (This->allocator == allocator)
+        return S_OK;
+    if (This->allocator)
+        IMemAllocator_Release(This->allocator);
+    This->allocator = allocator;
+    if (allocator)
+        IMemAllocator_AddRef(allocator);
+    return S_OK;
+}
+
+/* IMemInputPin */
+static HRESULT WINAPI
+SampleGrabber_IMemInputPin_GetAllocatorRequirements(IMemInputPin *iface, ALLOCATOR_PROPERTIES *props)
+{
+    SG_Impl *This = impl_from_IMemInputPin(iface);
+    FIXME("(%p)->(%p): semi-stub\n", This, props);
+    if (!props)
+        return E_POINTER;
+    return This->memOutput ? IMemInputPin_GetAllocatorRequirements(This->memOutput, props) : E_NOTIMPL;
+}
+
+/* IMemInputPin */
+static HRESULT WINAPI
+SampleGrabber_IMemInputPin_Receive(IMemInputPin *iface, IMediaSample *sample)
+{
+    SG_Impl *This = impl_from_IMemInputPin(iface);
+    HRESULT hr;
+    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))
+        return S_FALSE;
+    if (This->grabberIface)
+        SampleGrabber_callback(This, sample);
+    hr = This->memOutput ? IMemInputPin_Receive(This->memOutput, sample) : S_OK;
+    if (This->oneShot == OneShot_Wait) {
+        This->oneShot = OneShot_Past;
+        hr = S_FALSE;
+        if (This->pin_out.pair)
+            IPin_EndOfStream(This->pin_out.pair);
+    }
+    return hr;
+}
+
+/* IMemInputPin */
+static HRESULT WINAPI
+SampleGrabber_IMemInputPin_ReceiveMultiple(IMemInputPin *iface, IMediaSample **samples, LONG nSamples, LONG *nProcessed)
+{
+    SG_Impl *This = impl_from_IMemInputPin(iface);
+    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))
+        return S_FALSE;
+    if (This->grabberIface) {
+        LONG idx;
+        for (idx = 0; idx < nSamples; idx++)
+            SampleGrabber_callback(This, samples[idx]);
+    }
+    return This->memOutput ? IMemInputPin_ReceiveMultiple(This->memOutput, samples, nSamples, nProcessed) : S_OK;
+}
+
+/* IMemInputPin */
+static HRESULT WINAPI
+SampleGrabber_IMemInputPin_ReceiveCanBlock(IMemInputPin *iface)
+{
+    SG_Impl *This = impl_from_IMemInputPin(iface);
+    TRACE("(%p)\n", This);
+    return This->memOutput ? IMemInputPin_ReceiveCanBlock(This->memOutput) : S_OK;
+}
+
+
+/* SampleGrabber member pin implementation */
+
+/* IUnknown */
+static ULONG WINAPI
+SampleGrabber_IPin_AddRef(IPin *iface)
+{
+    return SampleGrabber_addref(((SG_Pin *)iface)->sg);
+}
+
+/* IUnknown */
+static ULONG WINAPI
+SampleGrabber_IPin_Release(IPin *iface)
+{
+    return SampleGrabber_release(((SG_Pin *)iface)->sg);
+}
+
+/* IUnknown */
+static HRESULT WINAPI
+SampleGrabber_IPin_QueryInterface(IPin *iface, REFIID riid, void **ppvObject)
+{
+    SG_Pin *This = (SG_Pin *)iface;
+    TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppvObject);
+
+    if (IsEqualIID(riid, &IID_IUnknown) ||
+        IsEqualIID(riid, &IID_IPin)) {
+        SampleGrabber_addref(This->sg);
+        *ppvObject = This;
+        return S_OK;
+    }
+    else if (IsEqualIID(riid, &IID_IMemInputPin)) {
+        SampleGrabber_addref(This->sg);
+        *ppvObject = &(This->sg->IMemInputPin_Vtbl);
+        return S_OK;
+    }
+    *ppvObject = NULL;
+    WARN("(%p, %s,%p): not found\n", This, debugstr_guid(riid), ppvObject);
+    return E_NOINTERFACE;
+}
+
+/* IPin - input pin */
+static HRESULT WINAPI
+SampleGrabber_In_IPin_Connect(IPin *iface, IPin *receiver, const AM_MEDIA_TYPE *mtype)
+{
+    WARN("(%p, %p): unexpected\n", receiver, mtype);
+    return E_UNEXPECTED;
+}
+
+/* IPin - output pin */
+static HRESULT WINAPI
+SampleGrabber_Out_IPin_Connect(IPin *iface, IPin *receiver, const AM_MEDIA_TYPE *type)
+{
+    SG_Pin *This = (SG_Pin *)iface;
+    HRESULT hr;
+    TRACE("(%p)->(%p, %p)\n", This, receiver, type);
+    if (!receiver)
+        return E_POINTER;
+    if (This->pair)
+        return VFW_E_ALREADY_CONNECTED;
+    if (This->sg->state != State_Stopped)
+        return VFW_E_NOT_STOPPED;
+    if (type) {
+	TRACE("Media type: %s/%s ssize: %u format: %s (%u bytes)\n",
+	    debugstr_guid(&type->majortype), debugstr_guid(&type->subtype),
+	    type->lSampleSize,
+	    debugstr_guid(&type->formattype), type->cbFormat);
+	if (!IsEqualGUID(&This->sg->mtype.majortype,&GUID_NULL) &&
+	    !IsEqualGUID(&This->sg->mtype.majortype,&type->majortype))
+	    return VFW_E_TYPE_NOT_ACCEPTED;
+	if (!IsEqualGUID(&This->sg->mtype.subtype,&MEDIASUBTYPE_None) &&
+	    !IsEqualGUID(&This->sg->mtype.subtype,&type->subtype))
+	    return VFW_E_TYPE_NOT_ACCEPTED;
+	if (!IsEqualGUID(&This->sg->mtype.formattype,&GUID_NULL) &&
+	    !IsEqualGUID(&This->sg->mtype.formattype,&FORMAT_None) &&
+	    !IsEqualGUID(&This->sg->mtype.formattype,&type->formattype))
+	    return VFW_E_TYPE_NOT_ACCEPTED;
+    }
+    else
+	type = &This->sg->mtype;
+    hr = IPin_ReceiveConnection(receiver,(IPin*)&This->lpVtbl,type);
+    if (FAILED(hr))
+	return hr;
+    This->pair = receiver;
+    if (This->sg->memOutput) {
+        IMemInputPin_Release(This->sg->memOutput);
+        This->sg->memOutput = NULL;
+    }
+    IPin_QueryInterface(receiver,&IID_IMemInputPin,(void **)&(This->sg->memOutput));
+    TRACE("(%p) Accepted IPin %p, IMemInputPin %p\n", This, receiver, This->sg->memOutput);
+    return S_OK;
+}
+
+/* IPin - input pin */
+static HRESULT WINAPI
+SampleGrabber_In_IPin_ReceiveConnection(IPin *iface, IPin *connector, const AM_MEDIA_TYPE *type)
+{
+    SG_Pin *This = (SG_Pin *)iface;
+    TRACE("(%p)->(%p, %p)\n", This, connector, type);
+    if (!connector)
+        return E_POINTER;
+    if (This->pair)
+        return VFW_E_ALREADY_CONNECTED;
+    if (This->sg->state != State_Stopped)
+        return VFW_E_NOT_STOPPED;
+    if (type) {
+	TRACE("Media type: %s/%s ssize: %u format: %s (%u bytes)\n",
+	    debugstr_guid(&type->majortype), debugstr_guid(&type->subtype),
+	    type->lSampleSize,
+	    debugstr_guid(&type->formattype), type->cbFormat);
+	if (!IsEqualGUID(&This->sg->mtype.majortype,&GUID_NULL) &&
+	    !IsEqualGUID(&This->sg->mtype.majortype,&type->majortype))
+	    return VFW_E_TYPE_NOT_ACCEPTED;
+	if (!IsEqualGUID(&This->sg->mtype.subtype,&MEDIASUBTYPE_None) &&
+	    !IsEqualGUID(&This->sg->mtype.subtype,&type->subtype))
+	    return VFW_E_TYPE_NOT_ACCEPTED;
+	if (!IsEqualGUID(&This->sg->mtype.formattype,&GUID_NULL) &&
+	    !IsEqualGUID(&This->sg->mtype.formattype,&FORMAT_None) &&
+	    !IsEqualGUID(&This->sg->mtype.formattype,&type->formattype))
+	    return VFW_E_TYPE_NOT_ACCEPTED;
+        if (This->sg->mtype.pbFormat)
+            CoTaskMemFree(This->sg->mtype.pbFormat);
+        This->sg->mtype = *type;
+        This->sg->mtype.pUnk = NULL;
+        if (type->cbFormat) {
+            This->sg->mtype.pbFormat = CoTaskMemAlloc(type->cbFormat);
+            CopyMemory(This->sg->mtype.pbFormat, type->pbFormat, type->cbFormat);
+        }
+        else
+            This->sg->mtype.pbFormat = NULL;
+    }
+    This->pair = connector;
+    TRACE("(%p) Accepted IPin %p\n", This, connector);
+    return S_OK;
+}
+
+/* IPin - output pin */
+static HRESULT WINAPI
+SampleGrabber_Out_IPin_ReceiveConnection(IPin *iface, IPin *connector, const AM_MEDIA_TYPE *mtype)
+{
+    WARN("(%p, %p): unexpected\n", connector, mtype);
+    return E_UNEXPECTED;
+}
+
+/* IPin - input pin */
+static HRESULT WINAPI
+SampleGrabber_In_IPin_Disconnect(IPin *iface)
+{
+    SG_Pin *This = (SG_Pin *)iface;
+    TRACE("(%p)->() pair = %p\n", This, This->pair);
+    if (This->sg->state != State_Stopped)
+        return VFW_E_NOT_STOPPED;
+    if (This->pair) {
+        This->pair = NULL;
+        return S_OK;
+    }
+    return S_FALSE;
+}
+
+/* IPin - output pin */
+static HRESULT WINAPI
+SampleGrabber_Out_IPin_Disconnect(IPin *iface)
+{
+    SG_Pin *This = (SG_Pin *)iface;
+    TRACE("(%p)->() pair = %p\n", This, This->pair);
+    if (This->sg->state != State_Stopped)
+        return VFW_E_NOT_STOPPED;
+    if (This->pair) {
+        This->pair = NULL;
+        if (This->sg->memOutput) {
+            IMemInputPin_Release(This->sg->memOutput);
+            This->sg->memOutput = NULL;
+        }
+        return S_OK;
+    }
+    return S_FALSE;
+}
+
+/* IPin */
+static HRESULT WINAPI
+SampleGrabber_IPin_ConnectedTo(IPin *iface, IPin **pin)
+{
+    SG_Pin *This = (SG_Pin *)iface;
+    TRACE("(%p)->(%p) pair = %p\n", This, pin, This->pair);
+    if (!pin)
+        return E_POINTER;
+    *pin = This->pair;
+    if (*pin) {
+        IPin_AddRef(*pin);
+        return S_OK;
+    }
+    return VFW_E_NOT_CONNECTED;
+}
+
+/* IPin */
+static HRESULT WINAPI
+SampleGrabber_IPin_ConnectionMediaType(IPin *iface, AM_MEDIA_TYPE *mtype)
+{
+    SG_Pin *This = (SG_Pin *)iface;
+    TRACE("(%p)->(%p)\n", This, mtype);
+    if (!mtype)
+        return E_POINTER;
+    if (!This->pair)
+        return VFW_E_NOT_CONNECTED;
+    *mtype = This->sg->mtype;
+    if (mtype->cbFormat) {
+        mtype->pbFormat = CoTaskMemAlloc(mtype->cbFormat);
+        CopyMemory(mtype->pbFormat, This->sg->mtype.pbFormat, mtype->cbFormat);
+    }
+    return S_OK;
+}
+
+/* IPin */
+static HRESULT WINAPI
+SampleGrabber_IPin_QueryPinInfo(IPin *iface, PIN_INFO *info)
+{
+    SG_Pin *This = (SG_Pin *)iface;
+    TRACE("(%p)->(%p)\n", This, info);
+    if (!info)
+        return E_POINTER;
+    SampleGrabber_addref(This->sg);
+    info->pFilter = (IBaseFilter *)This->sg;
+    info->dir = This->dir;
+    lstrcpynW(info->achName,This->name,MAX_PIN_NAME);
+    return S_OK;
+}
+
+/* IPin */
+static HRESULT WINAPI
+SampleGrabber_IPin_QueryDirection(IPin *iface, PIN_DIRECTION *dir)
+{
+    SG_Pin *This = (SG_Pin *)iface;
+    TRACE("(%p)->(%p)\n", This, dir);
+    if (!dir)
+        return E_POINTER;
+    *dir = This->dir;
+    return S_OK;
+}
+
+/* IPin */
+static HRESULT WINAPI
+SampleGrabber_IPin_QueryId(IPin *iface, LPWSTR *id)
+{
+    SG_Pin *This = (SG_Pin *)iface;
+    int len;
+    TRACE("(%p)->(%p)\n", This, id);
+    if (!id)
+        return E_POINTER;
+    len = sizeof(WCHAR)*(1+lstrlenW(This->name));
+    *id = CoTaskMemAlloc(len);
+    CopyMemory(*id, This->name, len);
+    return S_OK;
+}
+
+/* IPin */
+static HRESULT WINAPI
+SampleGrabber_IPin_QueryAccept(IPin *iface, const AM_MEDIA_TYPE *mtype)
+{
+    TRACE("(%p)\n", mtype);
+    return S_OK;
+}
+
+/* IPin */
+static HRESULT WINAPI
+SampleGrabber_IPin_EnumMediaTypes(IPin *iface, IEnumMediaTypes **mtypes)
+{
+    SG_Pin *This = (SG_Pin *)iface;
+    TRACE("(%p)->(%p)\n", This, mtypes);
+    if (!mtypes)
+        return E_POINTER;
+    *mtypes = mediaenum_create(&This->sg->mtype);
+    return *mtypes ? S_OK : E_OUTOFMEMORY;
+}
+
+/* IPin - input pin */
+static HRESULT WINAPI
+SampleGrabber_In_IPin_QueryInternalConnections(IPin *iface, IPin **pins, ULONG *nPins)
+{
+    SG_Pin *This = (SG_Pin *)iface;
+    TRACE("(%p)->(%p, %p) size = %u\n", This, pins, nPins, (nPins ? *nPins : 0));
+    if (!nPins)
+        return E_POINTER;
+    if (*nPins) {
+	if (!pins)
+	    return E_POINTER;
+	IPin_AddRef((IPin*)&This->sg->pin_out.lpVtbl);
+	*pins = (IPin*)&This->sg->pin_out.lpVtbl;
+	*nPins = 1;
+	return S_OK;
+    }
+    *nPins = 1;
+    return S_FALSE;
+}
+
+/* IPin - output pin */
+static HRESULT WINAPI
+SampleGrabber_Out_IPin_QueryInternalConnections(IPin *iface, IPin **pins, ULONG *nPins)
+{
+    WARN("(%p, %p): unexpected\n", pins, nPins);
+    if (nPins)
+        *nPins = 0;
     return E_NOTIMPL;
+}
+
+/* IPin */
+static HRESULT WINAPI
+SampleGrabber_IPin_EndOfStream(IPin *iface)
+{
+    FIXME(": stub\n");
+    return S_OK;
+}
+
+/* IPin */
+static HRESULT WINAPI
+SampleGrabber_IPin_BeginFlush(IPin *iface)
+{
+    FIXME(": stub\n");
+    return S_OK;
+}
+
+/* IPin */
+static HRESULT WINAPI
+SampleGrabber_IPin_EndFlush(IPin *iface)
+{
+    FIXME(": stub\n");
+    return S_OK;
+}
+
+/* IPin */
+static HRESULT WINAPI
+SampleGrabber_IPin_NewSegment(IPin *iface, REFERENCE_TIME tStart, REFERENCE_TIME tStop, double rate)
+{
+    FIXME(": stub\n");
+    return S_OK;
 }
 
 
@@ -423,6 +1306,63 @@
     SampleGrabber_ISampleGrabber_SetCallback,
 };
 
+static const IMemInputPinVtbl IMemInputPin_VTable =
+{
+    SampleGrabber_IMemInputPin_QueryInterface,
+    SampleGrabber_IMemInputPin_AddRef,
+    SampleGrabber_IMemInputPin_Release,
+    SampleGrabber_IMemInputPin_GetAllocator,
+    SampleGrabber_IMemInputPin_NotifyAllocator,
+    SampleGrabber_IMemInputPin_GetAllocatorRequirements,
+    SampleGrabber_IMemInputPin_Receive,
+    SampleGrabber_IMemInputPin_ReceiveMultiple,
+    SampleGrabber_IMemInputPin_ReceiveCanBlock,
+};
+
+static const IPinVtbl IPin_In_VTable =
+{
+    SampleGrabber_IPin_QueryInterface,
+    SampleGrabber_IPin_AddRef,
+    SampleGrabber_IPin_Release,
+    SampleGrabber_In_IPin_Connect,
+    SampleGrabber_In_IPin_ReceiveConnection,
+    SampleGrabber_In_IPin_Disconnect,
+    SampleGrabber_IPin_ConnectedTo,
+    SampleGrabber_IPin_ConnectionMediaType,
+    SampleGrabber_IPin_QueryPinInfo,
+    SampleGrabber_IPin_QueryDirection,
+    SampleGrabber_IPin_QueryId,
+    SampleGrabber_IPin_QueryAccept,
+    SampleGrabber_IPin_EnumMediaTypes,
+    SampleGrabber_In_IPin_QueryInternalConnections,
+    SampleGrabber_IPin_EndOfStream,
+    SampleGrabber_IPin_BeginFlush,
+    SampleGrabber_IPin_EndFlush,
+    SampleGrabber_IPin_NewSegment,
+};
+
+static const IPinVtbl IPin_Out_VTable =
+{
+    SampleGrabber_IPin_QueryInterface,
+    SampleGrabber_IPin_AddRef,
+    SampleGrabber_IPin_Release,
+    SampleGrabber_Out_IPin_Connect,
+    SampleGrabber_Out_IPin_ReceiveConnection,
+    SampleGrabber_Out_IPin_Disconnect,
+    SampleGrabber_IPin_ConnectedTo,
+    SampleGrabber_IPin_ConnectionMediaType,
+    SampleGrabber_IPin_QueryPinInfo,
+    SampleGrabber_IPin_QueryDirection,
+    SampleGrabber_IPin_QueryId,
+    SampleGrabber_IPin_QueryAccept,
+    SampleGrabber_IPin_EnumMediaTypes,
+    SampleGrabber_Out_IPin_QueryInternalConnections,
+    SampleGrabber_IPin_EndOfStream,
+    SampleGrabber_IPin_BeginFlush,
+    SampleGrabber_IPin_EndFlush,
+    SampleGrabber_IPin_NewSegment,
+};
+
 HRESULT SampleGrabber_create(IUnknown *pUnkOuter, LPVOID *ppv)
 {
     SG_Impl* obj = NULL;
@@ -442,11 +1382,29 @@
     obj->refCount = 1;
     obj->IBaseFilter_Vtbl = &IBaseFilter_VTable;
     obj->ISampleGrabber_Vtbl = &ISampleGrabber_VTable;
+    obj->IMemInputPin_Vtbl = &IMemInputPin_VTable;
+    obj->pin_in.lpVtbl = &IPin_In_VTable;
+    obj->pin_in.dir = PINDIR_INPUT;
+    obj->pin_in.name = pin_in_name;
+    obj->pin_in.sg = obj;
+    obj->pin_in.pair = NULL;
+    obj->pin_out.lpVtbl = &IPin_Out_VTable;
+    obj->pin_out.dir = PINDIR_OUTPUT;
+    obj->pin_out.name = pin_out_name;
+    obj->pin_out.sg = obj;
+    obj->pin_out.pair = NULL;
     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;
+    obj->oneShot = OneShot_None;
     *ppv = obj;
 
     return S_OK;




More information about the Ros-diffs mailing list