1 /* DirectShow Sample Grabber object (QEDIT.DLL)
3 * Copyright 2009 Paul Chitescu
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
30 #include "qedit_private.h"
31 #include "wine/debug.h"
33 WINE_DEFAULT_DEBUG_CHANNEL(qedit);
35 static WCHAR const vendor_name[] = { 'W', 'i', 'n', 'e', 0 };
36 static WCHAR const pin_in_name[] = { 'I', 'n', 0 };
37 static WCHAR const pin_out_name[] = { 'O', 'u', 't', 0 };
39 /* Sample Grabber pin implementation */
40 typedef struct _SG_Pin {
41 const IPinVtbl* lpVtbl;
48 /* Sample Grabber filter implementation */
49 typedef struct _SG_Impl {
50 const IBaseFilterVtbl* IBaseFilter_Vtbl;
51 const ISampleGrabberVtbl* ISampleGrabber_Vtbl;
52 const IMemInputPinVtbl* IMemInputPin_Vtbl;
53 /* TODO: IMediaPosition, IMediaSeeking, IQualityControl */
60 IMemAllocator *allocator;
61 IReferenceClock *refClock;
62 IMemInputPin *memOutput;
63 ISampleGrabberCB *grabberIface;
74 /* Get the SampleGrabber implementation This pointer from various interface pointers */
75 static inline SG_Impl *impl_from_IBaseFilter(IBaseFilter *iface)
77 return (SG_Impl *)((char*)iface - FIELD_OFFSET(SG_Impl, IBaseFilter_Vtbl));
80 static inline SG_Impl *impl_from_ISampleGrabber(ISampleGrabber *iface)
82 return (SG_Impl *)((char*)iface - FIELD_OFFSET(SG_Impl, ISampleGrabber_Vtbl));
85 static inline SG_Impl *impl_from_IMemInputPin(IMemInputPin *iface)
87 return (SG_Impl *)((char*)iface - FIELD_OFFSET(SG_Impl, IMemInputPin_Vtbl));
91 /* Cleanup at end of life */
92 static void SampleGrabber_cleanup(SG_Impl *This)
94 TRACE("(%p)\n", This);
95 if (This->info.pGraph)
96 WARN("(%p) still joined to filter graph %p\n", This, This->info.pGraph);
98 IMemAllocator_Release(This->allocator);
100 IReferenceClock_Release(This->refClock);
102 IMemInputPin_Release(This->memOutput);
103 if (This->grabberIface)
104 ISampleGrabberCB_Release(This->grabberIface);
105 if (This->mtype.pbFormat)
106 CoTaskMemFree(This->mtype.pbFormat);
109 /* Common helper AddRef called from all interfaces */
110 static ULONG SampleGrabber_addref(SG_Impl *This)
112 ULONG refCount = InterlockedIncrement(&This->refCount);
113 TRACE("(%p) new ref = %u\n", This, refCount);
117 /* Common helper Release called from all interfaces */
118 static ULONG SampleGrabber_release(SG_Impl *This)
120 ULONG refCount = InterlockedDecrement(&This->refCount);
121 TRACE("(%p) new ref = %u\n", This, refCount);
124 SampleGrabber_cleanup(This);
131 /* Common helper QueryInterface called from all interfaces */
132 static HRESULT SampleGrabber_query(SG_Impl *This, REFIID riid, void **ppvObject)
134 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppvObject);
136 if (IsEqualIID(riid, &IID_IUnknown) ||
137 IsEqualIID(riid, &IID_IPersist) ||
138 IsEqualIID(riid, &IID_IMediaFilter) ||
139 IsEqualIID(riid, &IID_IBaseFilter)) {
140 SampleGrabber_addref(This);
141 *ppvObject = &(This->IBaseFilter_Vtbl);
144 else if (IsEqualIID(riid, &IID_ISampleGrabber)) {
145 SampleGrabber_addref(This);
146 *ppvObject = &(This->ISampleGrabber_Vtbl);
149 else if (IsEqualIID(riid, &IID_IMemInputPin)) {
150 SampleGrabber_addref(This);
151 *ppvObject = &(This->IMemInputPin_Vtbl);
154 else if (IsEqualIID(riid, &IID_IMediaPosition))
155 FIXME("IMediaPosition not implemented\n");
156 else if (IsEqualIID(riid, &IID_IMediaSeeking))
157 FIXME("IMediaSeeking not implemented\n");
158 else if (IsEqualIID(riid, &IID_IQualityControl))
159 FIXME("IQualityControl not implemented\n");
161 WARN("(%p, %s,%p): not found\n", This, debugstr_guid(riid), ppvObject);
162 return E_NOINTERFACE;
165 /* Helper that calls installed sample callbacks */
166 static void SampleGrabber_callback(SG_Impl *This, IMediaSample *sample)
169 REFERENCE_TIME tStart, tEnd;
170 if (SUCCEEDED(IMediaSample_GetTime(sample, &tStart, &tEnd)))
171 time = 1e-7 * tStart;
172 switch (This->grabberMethod) {
175 ULONG ref = IMediaSample_AddRef(sample);
176 ISampleGrabberCB_SampleCB(This->grabberIface, time, sample);
177 ref = IMediaSample_Release(sample) + 1 - ref;
180 ERR("(%p) Callback referenced sample %p by %u\n", This, sample, ref);
181 /* ugly as hell but some apps are sooo buggy */
183 IMediaSample_Release(sample);
190 long size = IMediaSample_GetActualDataLength(sample);
191 if (size && SUCCEEDED(IMediaSample_GetPointer(sample, &data)) && data)
192 ISampleGrabberCB_BufferCB(This->grabberIface, time, data, size);
198 FIXME("unsupported method %ld\n", (long int)This->grabberMethod);
199 /* do not bother us again */
200 This->grabberMethod = -1;
205 /* SampleGrabber implementation of IBaseFilter interface */
208 static HRESULT WINAPI
209 SampleGrabber_IBaseFilter_QueryInterface(IBaseFilter *iface, REFIID riid, void **ppvObject)
211 return SampleGrabber_query(impl_from_IBaseFilter(iface), riid, ppvObject);
216 SampleGrabber_IBaseFilter_AddRef(IBaseFilter *iface)
218 return SampleGrabber_addref(impl_from_IBaseFilter(iface));
223 SampleGrabber_IBaseFilter_Release(IBaseFilter *iface)
225 return SampleGrabber_release(impl_from_IBaseFilter(iface));
229 static HRESULT WINAPI
230 SampleGrabber_IBaseFilter_GetClassID(IBaseFilter *iface, CLSID *pClassID)
232 TRACE("(%p)\n", pClassID);
235 *pClassID = CLSID_SampleGrabber;
240 static HRESULT WINAPI
241 SampleGrabber_IBaseFilter_Stop(IBaseFilter *iface)
243 SG_Impl *This = impl_from_IBaseFilter(iface);
244 TRACE("(%p)\n", This);
245 This->state = State_Stopped;
250 static HRESULT WINAPI
251 SampleGrabber_IBaseFilter_Pause(IBaseFilter *iface)
253 SG_Impl *This = impl_from_IBaseFilter(iface);
254 TRACE("(%p)\n", This);
255 This->state = State_Paused;
260 static HRESULT WINAPI
261 SampleGrabber_IBaseFilter_Run(IBaseFilter *iface, REFERENCE_TIME tStart)
263 SG_Impl *This = impl_from_IBaseFilter(iface);
264 TRACE("(%p)\n", This);
265 This->state = State_Running;
270 static HRESULT WINAPI
271 SampleGrabber_IBaseFilter_GetState(IBaseFilter *iface, DWORD msTout, FILTER_STATE *state)
273 SG_Impl *This = impl_from_IBaseFilter(iface);
274 TRACE("(%p)->(%u, %p)\n", This, msTout, state);
277 *state = This->state;
282 static HRESULT WINAPI
283 SampleGrabber_IBaseFilter_SetSyncSource(IBaseFilter *iface, IReferenceClock *clock)
285 SG_Impl *This = impl_from_IBaseFilter(iface);
286 TRACE("(%p)->(%p)\n", This, clock);
287 if (clock != This->refClock)
290 IReferenceClock_AddRef(clock);
292 IReferenceClock_Release(This->refClock);
293 This->refClock = clock;
299 static HRESULT WINAPI
300 SampleGrabber_IBaseFilter_GetSyncSource(IBaseFilter *iface, IReferenceClock **clock)
302 SG_Impl *This = impl_from_IBaseFilter(iface);
303 TRACE("(%p)->(%p)\n", This, clock);
307 IReferenceClock_AddRef(This->refClock);
308 *clock = This->refClock;
313 static HRESULT WINAPI
314 SampleGrabber_IBaseFilter_EnumPins(IBaseFilter *iface, IEnumPins **pins)
316 SG_Impl *This = impl_from_IBaseFilter(iface);
317 FIXME("(%p)->(%p): stub\n", This, pins);
320 return E_OUTOFMEMORY;
324 static HRESULT WINAPI
325 SampleGrabber_IBaseFilter_FindPin(IBaseFilter *iface, LPCWSTR id, IPin **pin)
327 SG_Impl *This = impl_from_IBaseFilter(iface);
328 TRACE("(%p)->(%s, %p)\n", This, debugstr_w(id), pin);
331 if (!lstrcmpiW(id,pin_in_name))
333 SampleGrabber_addref(This);
334 *pin = (IPin*)&(This->pin_in.lpVtbl);
337 else if (!lstrcmpiW(id,pin_out_name))
339 SampleGrabber_addref(This);
340 *pin = (IPin*)&(This->pin_out.lpVtbl);
344 return VFW_E_NOT_FOUND;
348 static HRESULT WINAPI
349 SampleGrabber_IBaseFilter_QueryFilterInfo(IBaseFilter *iface, FILTER_INFO *info)
351 SG_Impl *This = impl_from_IBaseFilter(iface);
352 TRACE("(%p)->(%p)\n", This, info);
355 if (This->info.pGraph)
356 IFilterGraph_AddRef(This->info.pGraph);
362 static HRESULT WINAPI
363 SampleGrabber_IBaseFilter_JoinFilterGraph(IBaseFilter *iface, IFilterGraph *graph, LPCWSTR name)
365 SG_Impl *This = impl_from_IBaseFilter(iface);
366 TRACE("(%p)->(%p, %s)\n", This, graph, debugstr_w(name));
367 This->info.pGraph = graph;
369 lstrcpynW(This->info.achName,name,MAX_FILTER_NAME);
370 This->oneShot = OneShot_None;
375 static HRESULT WINAPI
376 SampleGrabber_IBaseFilter_QueryVendorInfo(IBaseFilter *iface, LPWSTR *vendor)
378 TRACE("(%p)\n", vendor);
381 *vendor = CoTaskMemAlloc(sizeof(vendor_name));
382 CopyMemory(*vendor, vendor_name, sizeof(vendor_name));
387 /* SampleGrabber implementation of ISampleGrabber interface */
390 static HRESULT WINAPI
391 SampleGrabber_ISampleGrabber_QueryInterface(ISampleGrabber *iface, REFIID riid, void **ppvObject)
393 return SampleGrabber_query(impl_from_ISampleGrabber(iface), riid, ppvObject);
398 SampleGrabber_ISampleGrabber_AddRef(ISampleGrabber *iface)
400 return SampleGrabber_addref(impl_from_ISampleGrabber(iface));
405 SampleGrabber_ISampleGrabber_Release(ISampleGrabber *iface)
407 return SampleGrabber_release(impl_from_ISampleGrabber(iface));
411 static HRESULT WINAPI
412 SampleGrabber_ISampleGrabber_SetOneShot(ISampleGrabber *iface, BOOL oneShot)
414 SG_Impl *This = impl_from_ISampleGrabber(iface);
415 TRACE("(%p)->(%u)\n", This, oneShot);
416 This->oneShot = oneShot ? OneShot_Wait : OneShot_None;
421 static HRESULT WINAPI
422 SampleGrabber_ISampleGrabber_SetMediaType(ISampleGrabber *iface, const AM_MEDIA_TYPE *type)
424 SG_Impl *This = impl_from_ISampleGrabber(iface);
425 TRACE("(%p)->(%p)\n", This, type);
428 TRACE("Media type: %s/%s ssize: %u format: %s (%u bytes)\n",
429 debugstr_guid(&type->majortype), debugstr_guid(&type->subtype),
431 debugstr_guid(&type->formattype), type->cbFormat);
432 if (This->mtype.pbFormat)
433 CoTaskMemFree(This->mtype.pbFormat);
435 This->mtype.pUnk = NULL;
436 if (type->cbFormat) {
437 This->mtype.pbFormat = CoTaskMemAlloc(type->cbFormat);
438 CopyMemory(This->mtype.pbFormat, type->pbFormat, type->cbFormat);
441 This->mtype.pbFormat = NULL;
446 static HRESULT WINAPI
447 SampleGrabber_ISampleGrabber_GetConnectedMediaType(ISampleGrabber *iface, AM_MEDIA_TYPE *type)
449 SG_Impl *This = impl_from_ISampleGrabber(iface);
450 TRACE("(%p)->(%p)\n", This, type);
453 if (!This->pin_in.pair)
454 return VFW_E_NOT_CONNECTED;
456 if (type->cbFormat) {
457 type->pbFormat = CoTaskMemAlloc(type->cbFormat);
458 CopyMemory(type->pbFormat, This->mtype.pbFormat, type->cbFormat);
464 static HRESULT WINAPI
465 SampleGrabber_ISampleGrabber_SetBufferSamples(ISampleGrabber *iface, BOOL bufferEm)
467 TRACE("(%u)\n", bufferEm);
469 FIXME("buffering not implemented\n");
476 static HRESULT WINAPI
477 SampleGrabber_ISampleGrabber_GetCurrentBuffer(ISampleGrabber *iface, LONG *bufSize, LONG *buffer)
479 FIXME("(%p, %p): stub\n", bufSize, buffer);
486 static HRESULT WINAPI
487 SampleGrabber_ISampleGrabber_GetCurrentSample(ISampleGrabber *iface, IMediaSample **sample)
489 /* MS doesn't implement it either, noone should call it */
490 WARN("(%p): not implemented\n", sample);
495 static HRESULT WINAPI
496 SampleGrabber_ISampleGrabber_SetCallback(ISampleGrabber *iface, ISampleGrabberCB *cb, LONG whichMethod)
498 SG_Impl *This = impl_from_ISampleGrabber(iface);
499 TRACE("(%p)->(%p, %u)\n", This, cb, whichMethod);
500 if (This->grabberIface)
501 ISampleGrabberCB_Release(This->grabberIface);
502 This->grabberIface = cb;
503 This->grabberMethod = whichMethod;
505 ISampleGrabberCB_AddRef(cb);
510 /* SampleGrabber implementation of IMemInputPin interface */
513 static HRESULT WINAPI
514 SampleGrabber_IMemInputPin_QueryInterface(IMemInputPin *iface, REFIID riid, void **ppvObject)
516 return SampleGrabber_query(impl_from_IMemInputPin(iface), riid, ppvObject);
521 SampleGrabber_IMemInputPin_AddRef(IMemInputPin *iface)
523 return SampleGrabber_addref(impl_from_IMemInputPin(iface));
528 SampleGrabber_IMemInputPin_Release(IMemInputPin *iface)
530 return SampleGrabber_release(impl_from_IMemInputPin(iface));
534 static HRESULT WINAPI
535 SampleGrabber_IMemInputPin_GetAllocator(IMemInputPin *iface, IMemAllocator **allocator)
537 SG_Impl *This = impl_from_IMemInputPin(iface);
538 TRACE("(%p)->(%p) allocator = %p\n", This, allocator, This->allocator);
541 *allocator = This->allocator;
543 return VFW_E_NO_ALLOCATOR;
544 IMemAllocator_AddRef(*allocator);
549 static HRESULT WINAPI
550 SampleGrabber_IMemInputPin_NotifyAllocator(IMemInputPin *iface, IMemAllocator *allocator, BOOL readOnly)
552 SG_Impl *This = impl_from_IMemInputPin(iface);
553 TRACE("(%p)->(%p, %u) allocator = %p\n", This, allocator, readOnly, This->allocator);
554 if (This->allocator == allocator)
557 IMemAllocator_Release(This->allocator);
558 This->allocator = allocator;
560 IMemAllocator_AddRef(allocator);
565 static HRESULT WINAPI
566 SampleGrabber_IMemInputPin_GetAllocatorRequirements(IMemInputPin *iface, ALLOCATOR_PROPERTIES *props)
568 SG_Impl *This = impl_from_IMemInputPin(iface);
569 FIXME("(%p)->(%p): semi-stub\n", This, props);
572 return This->memOutput ? IMemInputPin_GetAllocatorRequirements(This->memOutput, props) : E_NOTIMPL;
576 static HRESULT WINAPI
577 SampleGrabber_IMemInputPin_Receive(IMemInputPin *iface, IMediaSample *sample)
579 SG_Impl *This = impl_from_IMemInputPin(iface);
581 TRACE("(%p)->(%p) output = %p, grabber = %p\n", This, sample, This->memOutput, This->grabberIface);
584 if ((This->state != State_Running) || (This->oneShot == OneShot_Past))
586 if (This->grabberIface)
587 SampleGrabber_callback(This, sample);
588 hr = This->memOutput ? IMemInputPin_Receive(This->memOutput, sample) : S_OK;
589 if (This->oneShot == OneShot_Wait) {
590 This->oneShot = OneShot_Past;
592 if (This->pin_out.pair)
593 IPin_EndOfStream(This->pin_out.pair);
599 static HRESULT WINAPI
600 SampleGrabber_IMemInputPin_ReceiveMultiple(IMemInputPin *iface, IMediaSample **samples, LONG nSamples, LONG *nProcessed)
602 SG_Impl *This = impl_from_IMemInputPin(iface);
603 TRACE("(%p)->(%p, %u, %p) output = %p, grabber = %p\n", This, samples, nSamples, nProcessed, This->memOutput, This->grabberIface);
604 if (!samples || !nProcessed)
606 if ((This->state != State_Running) || (This->oneShot == OneShot_Past))
608 if (This->grabberIface) {
610 for (idx = 0; idx < nSamples; idx++)
611 SampleGrabber_callback(This, samples[idx]);
613 return This->memOutput ? IMemInputPin_ReceiveMultiple(This->memOutput, samples, nSamples, nProcessed) : S_OK;
617 static HRESULT WINAPI
618 SampleGrabber_IMemInputPin_ReceiveCanBlock(IMemInputPin *iface)
620 SG_Impl *This = impl_from_IMemInputPin(iface);
621 TRACE("(%p)\n", This);
622 return This->memOutput ? IMemInputPin_ReceiveCanBlock(This->memOutput) : S_OK;
626 /* SampleGrabber member pin implementation */
630 SampleGrabber_IPin_AddRef(IPin *iface)
632 return SampleGrabber_addref(((SG_Pin *)iface)->sg);
637 SampleGrabber_IPin_Release(IPin *iface)
639 return SampleGrabber_release(((SG_Pin *)iface)->sg);
643 static HRESULT WINAPI
644 SampleGrabber_IPin_QueryInterface(IPin *iface, REFIID riid, void **ppvObject)
646 SG_Pin *This = (SG_Pin *)iface;
647 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppvObject);
649 if (IsEqualIID(riid, &IID_IUnknown) ||
650 IsEqualIID(riid, &IID_IPin)) {
651 SampleGrabber_addref(This->sg);
655 else if (IsEqualIID(riid, &IID_IMemInputPin)) {
656 SampleGrabber_addref(This->sg);
657 *ppvObject = &(This->sg->IMemInputPin_Vtbl);
661 WARN("(%p, %s,%p): not found\n", This, debugstr_guid(riid), ppvObject);
662 return E_NOINTERFACE;
665 /* IPin - input pin */
666 static HRESULT WINAPI
667 SampleGrabber_In_IPin_Connect(IPin *iface, IPin *receiver, const AM_MEDIA_TYPE *mtype)
669 WARN("(%p, %p): unexpected\n", receiver, mtype);
673 /* IPin - output pin */
674 static HRESULT WINAPI
675 SampleGrabber_Out_IPin_Connect(IPin *iface, IPin *receiver, const AM_MEDIA_TYPE *type)
677 SG_Pin *This = (SG_Pin *)iface;
678 TRACE("(%p)->(%p, %p)\n", This, receiver, type);
682 return VFW_E_ALREADY_CONNECTED;
683 if (This->sg->state != State_Stopped)
684 return VFW_E_NOT_STOPPED;
686 TRACE("Media type: %s/%s ssize: %u format: %s (%u bytes)\n",
687 debugstr_guid(&type->majortype), debugstr_guid(&type->subtype),
689 debugstr_guid(&type->formattype), type->cbFormat);
690 if (!IsEqualGUID(&This->sg->mtype.majortype,&GUID_NULL) &&
691 !IsEqualGUID(&This->sg->mtype.majortype,&type->majortype))
692 return VFW_E_TYPE_NOT_ACCEPTED;
693 if (!IsEqualGUID(&This->sg->mtype.subtype,&MEDIASUBTYPE_None) &&
694 !IsEqualGUID(&This->sg->mtype.subtype,&type->subtype))
695 return VFW_E_TYPE_NOT_ACCEPTED;
696 if (!IsEqualGUID(&This->sg->mtype.formattype,&GUID_NULL) &&
697 !IsEqualGUID(&This->sg->mtype.formattype,&FORMAT_None) &&
698 !IsEqualGUID(&This->sg->mtype.formattype,&type->formattype))
699 return VFW_E_TYPE_NOT_ACCEPTED;
701 This->pair = receiver;
702 if (This->sg->memOutput) {
703 IMemInputPin_Release(This->sg->memOutput);
704 This->sg->memOutput = NULL;
706 if (SUCCEEDED(IPin_QueryInterface(receiver,&IID_IMemInputPin,(void **)&(This->sg->memOutput))))
707 TRACE("pair IMemInputPin %p\n", This->sg->memOutput);
711 /* IPin - input pin */
712 static HRESULT WINAPI
713 SampleGrabber_In_IPin_ReceiveConnection(IPin *iface, IPin *connector, const AM_MEDIA_TYPE *type)
715 SG_Pin *This = (SG_Pin *)iface;
716 TRACE("(%p)->(%p, %p)\n", This, connector, type);
720 return VFW_E_ALREADY_CONNECTED;
721 if (This->sg->state != State_Stopped)
722 return VFW_E_NOT_STOPPED;
724 TRACE("Media type: %s/%s ssize: %u format: %s (%u bytes)\n",
725 debugstr_guid(&type->majortype), debugstr_guid(&type->subtype),
727 debugstr_guid(&type->formattype), type->cbFormat);
728 if (!IsEqualGUID(&This->sg->mtype.majortype,&GUID_NULL) &&
729 !IsEqualGUID(&This->sg->mtype.majortype,&type->majortype))
730 return VFW_E_TYPE_NOT_ACCEPTED;
731 if (!IsEqualGUID(&This->sg->mtype.subtype,&MEDIASUBTYPE_None) &&
732 !IsEqualGUID(&This->sg->mtype.subtype,&type->subtype))
733 return VFW_E_TYPE_NOT_ACCEPTED;
734 if (!IsEqualGUID(&This->sg->mtype.formattype,&GUID_NULL) &&
735 !IsEqualGUID(&This->sg->mtype.formattype,&FORMAT_None) &&
736 !IsEqualGUID(&This->sg->mtype.formattype,&type->formattype))
737 return VFW_E_TYPE_NOT_ACCEPTED;
738 if (This->sg->mtype.pbFormat)
739 CoTaskMemFree(This->sg->mtype.pbFormat);
740 This->sg->mtype = *type;
741 This->sg->mtype.pUnk = NULL;
742 if (type->cbFormat) {
743 This->sg->mtype.pbFormat = CoTaskMemAlloc(type->cbFormat);
744 CopyMemory(This->sg->mtype.pbFormat, type->pbFormat, type->cbFormat);
747 This->sg->mtype.pbFormat = NULL;
749 This->pair = connector;
753 /* IPin - output pin */
754 static HRESULT WINAPI
755 SampleGrabber_Out_IPin_ReceiveConnection(IPin *iface, IPin *connector, const AM_MEDIA_TYPE *mtype)
757 WARN("(%p, %p): unexpected\n", connector, mtype);
761 /* IPin - input pin */
762 static HRESULT WINAPI
763 SampleGrabber_In_IPin_Disconnect(IPin *iface)
765 SG_Pin *This = (SG_Pin *)iface;
766 TRACE("(%p)->() pair = %p\n", This, This->pair);
767 if (This->sg->state != State_Stopped)
768 return VFW_E_NOT_STOPPED;
776 /* IPin - output pin */
777 static HRESULT WINAPI
778 SampleGrabber_Out_IPin_Disconnect(IPin *iface)
780 SG_Pin *This = (SG_Pin *)iface;
781 TRACE("(%p)->() pair = %p\n", This, This->pair);
782 if (This->sg->state != State_Stopped)
783 return VFW_E_NOT_STOPPED;
786 if (This->sg->memOutput) {
787 IMemInputPin_Release(This->sg->memOutput);
788 This->sg->memOutput = NULL;
796 static HRESULT WINAPI
797 SampleGrabber_IPin_ConnectedTo(IPin *iface, IPin **pin)
799 SG_Pin *This = (SG_Pin *)iface;
800 TRACE("(%p)->(%p) pair = %p\n", This, pin, This->pair);
808 return VFW_E_NOT_CONNECTED;
812 static HRESULT WINAPI
813 SampleGrabber_IPin_ConnectionMediaType(IPin *iface, AM_MEDIA_TYPE *mtype)
815 SG_Pin *This = (SG_Pin *)iface;
816 TRACE("(%p)->(%p)\n", This, mtype);
820 return VFW_E_NOT_CONNECTED;
821 *mtype = This->sg->mtype;
822 if (mtype->cbFormat) {
823 mtype->pbFormat = CoTaskMemAlloc(mtype->cbFormat);
824 CopyMemory(mtype->pbFormat, This->sg->mtype.pbFormat, mtype->cbFormat);
830 static HRESULT WINAPI
831 SampleGrabber_IPin_QueryPinInfo(IPin *iface, PIN_INFO *info)
833 SG_Pin *This = (SG_Pin *)iface;
834 TRACE("(%p)->(%p)\n", This, info);
837 SampleGrabber_addref(This->sg);
838 info->pFilter = (IBaseFilter *)This->sg;
839 info->dir = This->dir;
840 lstrcpynW(info->achName,This->name,MAX_PIN_NAME);
845 static HRESULT WINAPI
846 SampleGrabber_IPin_QueryDirection(IPin *iface, PIN_DIRECTION *dir)
848 SG_Pin *This = (SG_Pin *)iface;
849 TRACE("(%p)->(%p)\n", This, dir);
857 static HRESULT WINAPI
858 SampleGrabber_IPin_QueryId(IPin *iface, LPWSTR *id)
860 SG_Pin *This = (SG_Pin *)iface;
862 TRACE("(%p)->(%p)\n", This, id);
865 len = sizeof(WCHAR)*(1+lstrlenW(This->name));
866 *id = CoTaskMemAlloc(len);
867 CopyMemory(*id, This->name, len);
872 static HRESULT WINAPI
873 SampleGrabber_IPin_QueryAccept(IPin *iface, const AM_MEDIA_TYPE *mtype)
875 TRACE("(%p)\n", mtype);
880 static HRESULT WINAPI
881 SampleGrabber_IPin_EnumMediaTypes(IPin *iface, IEnumMediaTypes **mtypes)
883 SG_Pin *This = (SG_Pin *)iface;
884 FIXME("(%p)->(%p): stub\n", This, mtypes);
887 return E_OUTOFMEMORY;
890 /* IPin - input pin */
891 static HRESULT WINAPI
892 SampleGrabber_In_IPin_QueryInternalConnections(IPin *iface, IPin **pins, ULONG *nPins)
894 SG_Pin *This = (SG_Pin *)iface;
895 TRACE("(%p)->(%p, %p) size = %u\n", This, pins, nPins, (nPins ? *nPins : 0));
901 IPin_AddRef((IPin*)&This->sg->pin_out.lpVtbl);
902 *pins = (IPin*)&This->sg->pin_out.lpVtbl;
910 /* IPin - output pin */
911 static HRESULT WINAPI
912 SampleGrabber_Out_IPin_QueryInternalConnections(IPin *iface, IPin **pins, ULONG *nPins)
914 WARN("(%p, %p): unexpected\n", pins, nPins);
921 static HRESULT WINAPI
922 SampleGrabber_IPin_EndOfStream(IPin *iface)
929 static HRESULT WINAPI
930 SampleGrabber_IPin_BeginFlush(IPin *iface)
937 static HRESULT WINAPI
938 SampleGrabber_IPin_EndFlush(IPin *iface)
945 static HRESULT WINAPI
946 SampleGrabber_IPin_NewSegment(IPin *iface, REFERENCE_TIME tStart, REFERENCE_TIME tStop, double rate)
953 /* SampleGrabber vtables and constructor */
955 static const IBaseFilterVtbl IBaseFilter_VTable =
957 SampleGrabber_IBaseFilter_QueryInterface,
958 SampleGrabber_IBaseFilter_AddRef,
959 SampleGrabber_IBaseFilter_Release,
960 SampleGrabber_IBaseFilter_GetClassID,
961 SampleGrabber_IBaseFilter_Stop,
962 SampleGrabber_IBaseFilter_Pause,
963 SampleGrabber_IBaseFilter_Run,
964 SampleGrabber_IBaseFilter_GetState,
965 SampleGrabber_IBaseFilter_SetSyncSource,
966 SampleGrabber_IBaseFilter_GetSyncSource,
967 SampleGrabber_IBaseFilter_EnumPins,
968 SampleGrabber_IBaseFilter_FindPin,
969 SampleGrabber_IBaseFilter_QueryFilterInfo,
970 SampleGrabber_IBaseFilter_JoinFilterGraph,
971 SampleGrabber_IBaseFilter_QueryVendorInfo,
974 static const ISampleGrabberVtbl ISampleGrabber_VTable =
976 SampleGrabber_ISampleGrabber_QueryInterface,
977 SampleGrabber_ISampleGrabber_AddRef,
978 SampleGrabber_ISampleGrabber_Release,
979 SampleGrabber_ISampleGrabber_SetOneShot,
980 SampleGrabber_ISampleGrabber_SetMediaType,
981 SampleGrabber_ISampleGrabber_GetConnectedMediaType,
982 SampleGrabber_ISampleGrabber_SetBufferSamples,
983 SampleGrabber_ISampleGrabber_GetCurrentBuffer,
984 SampleGrabber_ISampleGrabber_GetCurrentSample,
985 SampleGrabber_ISampleGrabber_SetCallback,
988 static const IMemInputPinVtbl IMemInputPin_VTable =
990 SampleGrabber_IMemInputPin_QueryInterface,
991 SampleGrabber_IMemInputPin_AddRef,
992 SampleGrabber_IMemInputPin_Release,
993 SampleGrabber_IMemInputPin_GetAllocator,
994 SampleGrabber_IMemInputPin_NotifyAllocator,
995 SampleGrabber_IMemInputPin_GetAllocatorRequirements,
996 SampleGrabber_IMemInputPin_Receive,
997 SampleGrabber_IMemInputPin_ReceiveMultiple,
998 SampleGrabber_IMemInputPin_ReceiveCanBlock,
1001 static const IPinVtbl IPin_In_VTable =
1003 SampleGrabber_IPin_QueryInterface,
1004 SampleGrabber_IPin_AddRef,
1005 SampleGrabber_IPin_Release,
1006 SampleGrabber_In_IPin_Connect,
1007 SampleGrabber_In_IPin_ReceiveConnection,
1008 SampleGrabber_In_IPin_Disconnect,
1009 SampleGrabber_IPin_ConnectedTo,
1010 SampleGrabber_IPin_ConnectionMediaType,
1011 SampleGrabber_IPin_QueryPinInfo,
1012 SampleGrabber_IPin_QueryDirection,
1013 SampleGrabber_IPin_QueryId,
1014 SampleGrabber_IPin_QueryAccept,
1015 SampleGrabber_IPin_EnumMediaTypes,
1016 SampleGrabber_In_IPin_QueryInternalConnections,
1017 SampleGrabber_IPin_EndOfStream,
1018 SampleGrabber_IPin_BeginFlush,
1019 SampleGrabber_IPin_EndFlush,
1020 SampleGrabber_IPin_NewSegment,
1023 static const IPinVtbl IPin_Out_VTable =
1025 SampleGrabber_IPin_QueryInterface,
1026 SampleGrabber_IPin_AddRef,
1027 SampleGrabber_IPin_Release,
1028 SampleGrabber_Out_IPin_Connect,
1029 SampleGrabber_Out_IPin_ReceiveConnection,
1030 SampleGrabber_Out_IPin_Disconnect,
1031 SampleGrabber_IPin_ConnectedTo,
1032 SampleGrabber_IPin_ConnectionMediaType,
1033 SampleGrabber_IPin_QueryPinInfo,
1034 SampleGrabber_IPin_QueryDirection,
1035 SampleGrabber_IPin_QueryId,
1036 SampleGrabber_IPin_QueryAccept,
1037 SampleGrabber_IPin_EnumMediaTypes,
1038 SampleGrabber_Out_IPin_QueryInternalConnections,
1039 SampleGrabber_IPin_EndOfStream,
1040 SampleGrabber_IPin_BeginFlush,
1041 SampleGrabber_IPin_EndFlush,
1042 SampleGrabber_IPin_NewSegment,
1045 HRESULT SampleGrabber_create(IUnknown *pUnkOuter, LPVOID *ppv)
1047 SG_Impl* obj = NULL;
1049 TRACE("(%p,%p)\n", ppv, pUnkOuter);
1052 return CLASS_E_NOAGGREGATION;
1054 obj = CoTaskMemAlloc(sizeof(SG_Impl));
1057 return E_OUTOFMEMORY;
1059 ZeroMemory(obj, sizeof(SG_Impl));
1062 obj->IBaseFilter_Vtbl = &IBaseFilter_VTable;
1063 obj->ISampleGrabber_Vtbl = &ISampleGrabber_VTable;
1064 obj->IMemInputPin_Vtbl = &IMemInputPin_VTable;
1065 obj->pin_in.lpVtbl = &IPin_In_VTable;
1066 obj->pin_in.dir = PINDIR_INPUT;
1067 obj->pin_in.name = pin_in_name;
1068 obj->pin_in.sg = obj;
1069 obj->pin_in.pair = NULL;
1070 obj->pin_out.lpVtbl = &IPin_Out_VTable;
1071 obj->pin_out.dir = PINDIR_OUTPUT;
1072 obj->pin_out.name = pin_out_name;
1073 obj->pin_out.sg = obj;
1074 obj->pin_out.pair = NULL;
1075 obj->info.achName[0] = 0;
1076 obj->info.pGraph = NULL;
1077 obj->state = State_Stopped;
1078 obj->mtype.majortype = GUID_NULL;
1079 obj->mtype.subtype = MEDIASUBTYPE_None;
1080 obj->mtype.formattype = FORMAT_None;
1081 obj->allocator = NULL;
1082 obj->refClock = NULL;
1083 obj->memOutput = NULL;
1084 obj->grabberIface = NULL;
1085 obj->grabberMethod = -1;
1086 obj->oneShot = OneShot_None;