qedit: Add pins, IMemInputPin implementation and grabbing to SampleGrabber.
This commit is contained in:
parent
983cff23fa
commit
4457717d79
|
@ -33,19 +33,43 @@
|
|||
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 };
|
||||
|
||||
/* 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;
|
||||
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)
|
||||
{
|
||||
|
@ -57,6 +81,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));
|
||||
}
|
||||
|
||||
|
||||
/* Cleanup at end of life */
|
||||
static void SampleGrabber_cleanup(SG_Impl *This)
|
||||
|
@ -68,6 +97,10 @@ static void SampleGrabber_cleanup(SG_Impl *This)
|
|||
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);
|
||||
}
|
||||
|
||||
/* Common helper AddRef called from all interfaces */
|
||||
|
@ -110,8 +143,11 @@ static HRESULT SampleGrabber_query(SG_Impl *This, REFIID riid, void **ppvObject)
|
|||
*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 +159,45 @@ static HRESULT SampleGrabber_query(SG_Impl *This, REFIID riid, void **ppvObject)
|
|||
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 */
|
||||
|
||||
|
@ -247,9 +322,21 @@ static HRESULT WINAPI
|
|||
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 +364,7 @@ SampleGrabber_IBaseFilter_JoinFilterGraph(IBaseFilter *iface, IFilterGraph *grap
|
|||
This->info.pGraph = graph;
|
||||
if (name)
|
||||
lstrcpynW(This->info.achName,name,MAX_FILTER_NAME);
|
||||
This->oneShot = OneShot_None;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
@ -321,8 +409,9 @@ static HRESULT WINAPI
|
|||
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 */
|
||||
|
@ -383,10 +472,402 @@ static HRESULT WINAPI
|
|||
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;
|
||||
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;
|
||||
return VFW_E_TYPE_NOT_ACCEPTED;
|
||||
}
|
||||
|
||||
/* 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;
|
||||
return VFW_E_TYPE_NOT_ACCEPTED;
|
||||
}
|
||||
|
||||
/* 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;
|
||||
return VFW_E_NOT_CONNECTED;
|
||||
}
|
||||
|
||||
/* 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;
|
||||
FIXME("(%p)->(%p): stub\n", This, mtypes);
|
||||
if (!mtypes)
|
||||
return E_POINTER;
|
||||
return 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;
|
||||
}
|
||||
|
||||
|
||||
/* SampleGrabber vtables and constructor */
|
||||
|
||||
|
@ -423,6 +904,63 @@ static const ISampleGrabberVtbl ISampleGrabber_VTable =
|
|||
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 +980,26 @@ HRESULT SampleGrabber_create(IUnknown *pUnkOuter, LPVOID *ppv)
|
|||
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->allocator = NULL;
|
||||
obj->refClock = NULL;
|
||||
obj->memOutput = NULL;
|
||||
obj->grabberIface = NULL;
|
||||
obj->grabberMethod = -1;
|
||||
obj->oneShot = OneShot_None;
|
||||
*ppv = obj;
|
||||
|
||||
return S_OK;
|
||||
|
|
Loading…
Reference in New Issue