wined3d: Simplify shader interface matching for SM4+ vertex shaders.
[wine.git] / dlls / qedit / samplegrabber.c
blob151827e23a18359bf4d49c02d02b4ae97fcbcf43
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
20 #include <assert.h>
21 #include <stdarg.h>
23 #define COBJMACROS
25 #include "windef.h"
26 #include "winbase.h"
27 #include "winuser.h"
28 #include "ole2.h"
30 #include "qedit_private.h"
31 #include "wine/debug.h"
32 #include "wine/strmbase.h"
34 WINE_DEFAULT_DEBUG_CHANNEL(qedit);
36 static const WCHAR vendor_name[] = { 'W', 'i', 'n', 'e', 0 };
37 static const WCHAR pin_in_name[] = { 'I', 'n', 0 };
38 static const WCHAR pin_out_name[] = { 'O', 'u', 't', 0 };
40 static IEnumMediaTypes *mediaenum_create(const AM_MEDIA_TYPE *mtype, BOOL past);
42 /* Single media type enumerator */
43 typedef struct _ME_Impl {
44 IEnumMediaTypes IEnumMediaTypes_iface;
45 LONG refCount;
46 BOOL past;
47 AM_MEDIA_TYPE mtype;
48 } ME_Impl;
51 /* IEnumMediaTypes interface implementation */
53 static inline ME_Impl *impl_from_IEnumMediaTypes(IEnumMediaTypes *iface)
55 return CONTAINING_RECORD(iface, ME_Impl, IEnumMediaTypes_iface);
58 static HRESULT WINAPI Single_IEnumMediaTypes_QueryInterface(IEnumMediaTypes *iface, REFIID riid,
59 void **ret_iface)
61 ME_Impl *This = impl_from_IEnumMediaTypes(iface);
63 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), ret_iface);
65 if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IEnumMediaTypes)) {
66 *ret_iface = iface;
67 IEnumMediaTypes_AddRef(iface);
68 return S_OK;
70 *ret_iface = NULL;
71 WARN("(%p, %s,%p): not found\n", This, debugstr_guid(riid), ret_iface);
72 return E_NOINTERFACE;
75 static ULONG WINAPI Single_IEnumMediaTypes_AddRef(IEnumMediaTypes *iface)
77 ME_Impl *This = impl_from_IEnumMediaTypes(iface);
78 ULONG refCount = InterlockedIncrement(&This->refCount);
80 TRACE("(%p) new ref = %u\n", This, refCount);
81 return refCount;
84 static ULONG WINAPI Single_IEnumMediaTypes_Release(IEnumMediaTypes *iface)
86 ME_Impl *This = impl_from_IEnumMediaTypes(iface);
87 ULONG refCount = InterlockedDecrement(&This->refCount);
89 TRACE("(%p) new ref = %u\n", This, refCount);
90 if (refCount == 0)
92 if (This->mtype.pbFormat)
93 CoTaskMemFree(This->mtype.pbFormat);
94 CoTaskMemFree(This);
96 return refCount;
99 /* IEnumMediaTypes */
100 static HRESULT WINAPI Single_IEnumMediaTypes_Next(IEnumMediaTypes *iface, ULONG nTypes,
101 AM_MEDIA_TYPE **types, ULONG *fetched)
103 ME_Impl *This = impl_from_IEnumMediaTypes(iface);
104 ULONG count = 0;
106 TRACE("(%p)->(%u, %p, %p)\n", This, nTypes, types, fetched);
107 if (!nTypes)
108 return E_INVALIDARG;
109 if (!types || ((nTypes != 1) && !fetched))
110 return E_POINTER;
111 if (!This->past && !IsEqualGUID(&This->mtype.majortype,&GUID_NULL)) {
112 AM_MEDIA_TYPE *mtype = CoTaskMemAlloc(sizeof(AM_MEDIA_TYPE));
113 *mtype = This->mtype;
114 if (mtype->cbFormat) {
115 mtype->pbFormat = CoTaskMemAlloc(mtype->cbFormat);
116 CopyMemory(mtype->pbFormat, This->mtype.pbFormat, mtype->cbFormat);
118 *types = mtype;
119 This->past = TRUE;
120 count = 1;
122 if (fetched)
123 *fetched = count;
124 return (count == nTypes) ? S_OK : S_FALSE;
127 static HRESULT WINAPI Single_IEnumMediaTypes_Skip(IEnumMediaTypes *iface, ULONG nTypes)
129 ME_Impl *This = impl_from_IEnumMediaTypes(iface);
131 TRACE("(%p)->(%u)\n", This, nTypes);
132 if (nTypes)
133 This->past = TRUE;
134 return This->past ? S_FALSE : S_OK;
137 static HRESULT WINAPI Single_IEnumMediaTypes_Reset(IEnumMediaTypes *iface)
139 ME_Impl *This = impl_from_IEnumMediaTypes(iface);
141 TRACE("(%p)->()\n", This);
142 This->past = FALSE;
143 return S_OK;
146 static HRESULT WINAPI Single_IEnumMediaTypes_Clone(IEnumMediaTypes *iface, IEnumMediaTypes **me)
148 ME_Impl *This = impl_from_IEnumMediaTypes(iface);
150 TRACE("(%p)->(%p)\n", This, me);
151 if (!me)
152 return E_POINTER;
153 *me = mediaenum_create(&This->mtype, This->past);
154 if (!*me)
155 return E_OUTOFMEMORY;
156 return S_OK;
160 /* Virtual tables and constructor */
162 static const IEnumMediaTypesVtbl IEnumMediaTypes_VTable =
164 Single_IEnumMediaTypes_QueryInterface,
165 Single_IEnumMediaTypes_AddRef,
166 Single_IEnumMediaTypes_Release,
167 Single_IEnumMediaTypes_Next,
168 Single_IEnumMediaTypes_Skip,
169 Single_IEnumMediaTypes_Reset,
170 Single_IEnumMediaTypes_Clone,
173 static IEnumMediaTypes *mediaenum_create(const AM_MEDIA_TYPE *mtype, BOOL past)
175 ME_Impl *obj = CoTaskMemAlloc(sizeof(ME_Impl));
177 if (!obj)
178 return NULL;
179 ZeroMemory(obj, sizeof(*obj));
180 obj->IEnumMediaTypes_iface.lpVtbl = &IEnumMediaTypes_VTable;
181 obj->refCount = 1;
182 obj->past = past;
183 if (mtype) {
184 obj->mtype = *mtype;
185 obj->mtype.pUnk = NULL;
186 if (mtype->cbFormat) {
187 obj->mtype.pbFormat = CoTaskMemAlloc(mtype->cbFormat);
188 CopyMemory(obj->mtype.pbFormat, mtype->pbFormat, mtype->cbFormat);
190 else
191 obj->mtype.pbFormat = NULL;
193 else
194 obj->mtype.majortype = GUID_NULL;
196 return &obj->IEnumMediaTypes_iface;
200 /* Sample Grabber pin implementation */
201 typedef struct _SG_Pin {
202 IPin IPin_iface;
203 PIN_DIRECTION dir;
204 WCHAR const *name;
205 struct _SG_Impl *sg;
206 IPin *pair;
207 } SG_Pin;
209 static inline SG_Pin *impl_from_IPin(IPin *iface)
211 return CONTAINING_RECORD(iface, SG_Pin, IPin_iface);
214 /* Sample Grabber filter implementation */
215 typedef struct _SG_Impl {
216 IUnknown IUnknown_inner;
217 BaseFilter filter;
218 ISampleGrabber ISampleGrabber_iface;
219 /* IMediaSeeking and IMediaPosition are implemented by ISeekingPassThru */
220 IUnknown* seekthru_unk;
221 IUnknown *outer_unk;
222 AM_MEDIA_TYPE mtype;
223 SG_Pin pin_in;
224 SG_Pin pin_out;
225 IMemInputPin IMemInputPin_iface;
226 IMemAllocator *allocator;
227 IMemInputPin *memOutput;
228 ISampleGrabberCB *grabberIface;
229 LONG grabberMethod;
230 LONG oneShot;
231 LONG bufferLen;
232 void* bufferData;
233 } SG_Impl;
235 enum {
236 OneShot_None,
237 OneShot_Wait,
238 OneShot_Past,
241 static inline SG_Impl *impl_from_IUnknown(IUnknown *iface)
243 return CONTAINING_RECORD(iface, SG_Impl, IUnknown_inner);
246 static inline SG_Impl *impl_from_BaseFilter(BaseFilter *iface)
248 return CONTAINING_RECORD(iface, SG_Impl, filter);
251 static inline SG_Impl *impl_from_IBaseFilter(IBaseFilter *iface)
253 return CONTAINING_RECORD(iface, SG_Impl, filter.IBaseFilter_iface);
256 static inline SG_Impl *impl_from_ISampleGrabber(ISampleGrabber *iface)
258 return CONTAINING_RECORD(iface, SG_Impl, ISampleGrabber_iface);
261 static inline SG_Impl *impl_from_IMemInputPin(IMemInputPin *iface)
263 return CONTAINING_RECORD(iface, SG_Impl, IMemInputPin_iface);
267 /* Cleanup at end of life */
268 static void SampleGrabber_cleanup(SG_Impl *This)
270 TRACE("(%p)\n", This);
271 if (This->filter.filterInfo.pGraph)
272 WARN("(%p) still joined to filter graph %p\n", This, This->filter.filterInfo.pGraph);
273 if (This->allocator)
274 IMemAllocator_Release(This->allocator);
275 if (This->memOutput)
276 IMemInputPin_Release(This->memOutput);
277 if (This->grabberIface)
278 ISampleGrabberCB_Release(This->grabberIface);
279 if (This->mtype.pbFormat)
280 CoTaskMemFree(This->mtype.pbFormat);
281 if (This->bufferData)
282 CoTaskMemFree(This->bufferData);
283 if(This->seekthru_unk)
284 IUnknown_Release(This->seekthru_unk);
287 /* SampleGrabber inner IUnknown */
288 static HRESULT WINAPI SampleGrabber_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
290 SG_Impl *This = impl_from_IUnknown(iface);
292 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppv);
294 *ppv = NULL;
295 if (IsEqualIID(riid, &IID_IUnknown))
296 *ppv = &This->IUnknown_inner;
297 else if (IsEqualIID(riid, &IID_IPersist) || IsEqualIID(riid, &IID_IMediaFilter) ||
298 IsEqualIID(riid, &IID_IBaseFilter))
299 *ppv = &This->filter.IBaseFilter_iface;
300 else if (IsEqualIID(riid, &IID_ISampleGrabber))
301 *ppv = &This->ISampleGrabber_iface;
302 else if (IsEqualIID(riid, &IID_IMediaPosition))
303 return IUnknown_QueryInterface(This->seekthru_unk, riid, ppv);
304 else if (IsEqualIID(riid, &IID_IMediaSeeking))
305 return IUnknown_QueryInterface(This->seekthru_unk, riid, ppv);
306 else
307 WARN("(%p, %s,%p): not found\n", This, debugstr_guid(riid), ppv);
309 if (!*ppv)
310 return E_NOINTERFACE;
312 IUnknown_AddRef((IUnknown*)*ppv);
313 return S_OK;
316 static ULONG WINAPI SampleGrabber_AddRef(IUnknown *iface)
318 SG_Impl *This = impl_from_IUnknown(iface);
319 ULONG ref = BaseFilterImpl_AddRef(&This->filter.IBaseFilter_iface);
321 TRACE("(%p) ref=%d\n", This, ref);
323 return ref;
326 static ULONG WINAPI SampleGrabber_Release(IUnknown *iface)
328 SG_Impl *This = impl_from_IUnknown(iface);
329 ULONG ref = BaseFilterImpl_Release(&This->filter.IBaseFilter_iface);
331 TRACE("(%p) ref=%d\n", This, ref);
333 if (ref == 0)
335 SampleGrabber_cleanup(This);
336 CoTaskMemFree(This);
338 return ref;
341 static const IUnknownVtbl samplegrabber_vtbl =
343 SampleGrabber_QueryInterface,
344 SampleGrabber_AddRef,
345 SampleGrabber_Release,
348 static IPin *WINAPI SampleGrabber_GetPin(BaseFilter *iface, int pos)
350 SG_Impl *This = impl_from_BaseFilter(iface);
351 IPin *pin;
353 if (pos == 0)
354 pin = &This->pin_in.IPin_iface;
355 else if (pos == 1)
356 pin = &This->pin_out.IPin_iface;
357 else
358 return NULL;
360 IPin_AddRef(pin);
361 return pin;
364 static LONG WINAPI SampleGrabber_GetPinCount(BaseFilter *iface)
366 return 2;
369 static const BaseFilterFuncTable basefunc_vtbl = {
370 SampleGrabber_GetPin,
371 SampleGrabber_GetPinCount
374 /* Helper that buffers data and/or calls installed sample callbacks */
375 static void SampleGrabber_callback(SG_Impl *This, IMediaSample *sample)
377 double time = 0.0;
378 REFERENCE_TIME tStart, tEnd;
379 if (This->bufferLen >= 0) {
380 BYTE *data = 0;
381 LONG size = IMediaSample_GetActualDataLength(sample);
382 if (size >= 0 && SUCCEEDED(IMediaSample_GetPointer(sample, &data))) {
383 if (!data)
384 size = 0;
385 EnterCriticalSection(&This->filter.csFilter);
386 if (This->bufferLen != size) {
387 if (This->bufferData)
388 CoTaskMemFree(This->bufferData);
389 This->bufferData = size ? CoTaskMemAlloc(size) : NULL;
390 This->bufferLen = size;
392 if (size)
393 CopyMemory(This->bufferData, data, size);
394 LeaveCriticalSection(&This->filter.csFilter);
397 if (!This->grabberIface)
398 return;
399 if (SUCCEEDED(IMediaSample_GetTime(sample, &tStart, &tEnd)))
400 time = 1e-7 * tStart;
401 switch (This->grabberMethod) {
402 case 0:
404 ULONG ref = IMediaSample_AddRef(sample);
405 ISampleGrabberCB_SampleCB(This->grabberIface, time, sample);
406 ref = IMediaSample_Release(sample) + 1 - ref;
407 if (ref)
409 ERR("(%p) Callback referenced sample %p by %u\n", This, sample, ref);
410 /* ugly as hell but some apps are sooo buggy */
411 while (ref--)
412 IMediaSample_Release(sample);
415 break;
416 case 1:
418 BYTE *data = 0;
419 LONG size = IMediaSample_GetActualDataLength(sample);
420 if (size && SUCCEEDED(IMediaSample_GetPointer(sample, &data)) && data)
421 ISampleGrabberCB_BufferCB(This->grabberIface, time, data, size);
423 break;
424 case -1:
425 break;
426 default:
427 FIXME("unsupported method %d\n", This->grabberMethod);
428 /* do not bother us again */
429 This->grabberMethod = -1;
434 /* SampleGrabber implementation of IBaseFilter interface */
436 /* IUnknown */
437 static HRESULT WINAPI
438 SampleGrabber_IBaseFilter_QueryInterface(IBaseFilter *iface, REFIID riid, void **ppv)
440 SG_Impl *This = impl_from_IBaseFilter(iface);
441 return IUnknown_QueryInterface(This->outer_unk, riid, ppv);
444 /* IUnknown */
445 static ULONG WINAPI
446 SampleGrabber_IBaseFilter_AddRef(IBaseFilter *iface)
448 SG_Impl *This = impl_from_IBaseFilter(iface);
449 return IUnknown_AddRef(This->outer_unk);
452 /* IUnknown */
453 static ULONG WINAPI
454 SampleGrabber_IBaseFilter_Release(IBaseFilter *iface)
456 SG_Impl *This = impl_from_IBaseFilter(iface);
457 return IUnknown_Release(This->outer_unk);
460 /* IMediaFilter */
461 static HRESULT WINAPI
462 SampleGrabber_IBaseFilter_Stop(IBaseFilter *iface)
464 SG_Impl *This = impl_from_IBaseFilter(iface);
465 TRACE("(%p)\n", This);
466 This->filter.state = State_Stopped;
467 return S_OK;
470 /* IMediaFilter */
471 static HRESULT WINAPI
472 SampleGrabber_IBaseFilter_Pause(IBaseFilter *iface)
474 SG_Impl *This = impl_from_IBaseFilter(iface);
475 TRACE("(%p)\n", This);
476 This->filter.state = State_Paused;
477 return S_OK;
480 /* IMediaFilter */
481 static HRESULT WINAPI
482 SampleGrabber_IBaseFilter_Run(IBaseFilter *iface, REFERENCE_TIME tStart)
484 SG_Impl *This = impl_from_IBaseFilter(iface);
485 TRACE("(%p)\n", This);
486 This->filter.state = State_Running;
487 return S_OK;
490 /* IBaseFilter */
491 static HRESULT WINAPI
492 SampleGrabber_IBaseFilter_FindPin(IBaseFilter *iface, LPCWSTR id, IPin **pin)
494 SG_Impl *This = impl_from_IBaseFilter(iface);
495 TRACE("(%p)->(%s, %p)\n", This, debugstr_w(id), pin);
496 if (!id || !pin)
497 return E_POINTER;
498 if (!lstrcmpiW(id,pin_in_name))
500 *pin = &This->pin_in.IPin_iface;
501 IPin_AddRef(*pin);
502 return S_OK;
504 else if (!lstrcmpiW(id,pin_out_name))
506 *pin = &This->pin_out.IPin_iface;
507 IPin_AddRef(*pin);
508 return S_OK;
510 *pin = NULL;
511 return VFW_E_NOT_FOUND;
514 /* IBaseFilter */
515 static HRESULT WINAPI
516 SampleGrabber_IBaseFilter_JoinFilterGraph(IBaseFilter *iface, IFilterGraph *graph, LPCWSTR name)
518 SG_Impl *This = impl_from_IBaseFilter(iface);
520 TRACE("(%p)->(%p, %s)\n", This, graph, debugstr_w(name));
522 BaseFilterImpl_JoinFilterGraph(iface, graph, name);
523 This->oneShot = OneShot_None;
525 return S_OK;
528 /* IBaseFilter */
529 static HRESULT WINAPI
530 SampleGrabber_IBaseFilter_QueryVendorInfo(IBaseFilter *iface, LPWSTR *vendor)
532 TRACE("(%p)\n", vendor);
533 if (!vendor)
534 return E_POINTER;
535 *vendor = CoTaskMemAlloc(sizeof(vendor_name));
536 CopyMemory(*vendor, vendor_name, sizeof(vendor_name));
537 return S_OK;
541 /* SampleGrabber implementation of ISampleGrabber interface */
543 /* IUnknown */
544 static HRESULT WINAPI
545 SampleGrabber_ISampleGrabber_QueryInterface(ISampleGrabber *iface, REFIID riid, void **ppv)
547 SG_Impl *This = impl_from_ISampleGrabber(iface);
548 return IUnknown_QueryInterface(This->outer_unk, riid, ppv);
551 /* IUnknown */
552 static ULONG WINAPI
553 SampleGrabber_ISampleGrabber_AddRef(ISampleGrabber *iface)
555 SG_Impl *This = impl_from_ISampleGrabber(iface);
556 return IUnknown_AddRef(This->outer_unk);
559 /* IUnknown */
560 static ULONG WINAPI
561 SampleGrabber_ISampleGrabber_Release(ISampleGrabber *iface)
563 SG_Impl *This = impl_from_ISampleGrabber(iface);
564 return IUnknown_Release(This->outer_unk);
567 /* ISampleGrabber */
568 static HRESULT WINAPI
569 SampleGrabber_ISampleGrabber_SetOneShot(ISampleGrabber *iface, BOOL oneShot)
571 SG_Impl *This = impl_from_ISampleGrabber(iface);
572 TRACE("(%p)->(%u)\n", This, oneShot);
573 This->oneShot = oneShot ? OneShot_Wait : OneShot_None;
574 return S_OK;
577 /* ISampleGrabber */
578 static HRESULT WINAPI
579 SampleGrabber_ISampleGrabber_SetMediaType(ISampleGrabber *iface, const AM_MEDIA_TYPE *type)
581 SG_Impl *This = impl_from_ISampleGrabber(iface);
582 TRACE("(%p)->(%p)\n", This, type);
583 if (!type)
584 return E_POINTER;
585 TRACE("Media type: %s/%s ssize: %u format: %s (%u bytes)\n",
586 debugstr_guid(&type->majortype), debugstr_guid(&type->subtype),
587 type->lSampleSize,
588 debugstr_guid(&type->formattype), type->cbFormat);
589 if (This->mtype.pbFormat)
590 CoTaskMemFree(This->mtype.pbFormat);
591 This->mtype = *type;
592 This->mtype.pUnk = NULL;
593 if (type->cbFormat) {
594 This->mtype.pbFormat = CoTaskMemAlloc(type->cbFormat);
595 CopyMemory(This->mtype.pbFormat, type->pbFormat, type->cbFormat);
597 else
598 This->mtype.pbFormat = NULL;
599 return S_OK;
602 /* ISampleGrabber */
603 static HRESULT WINAPI
604 SampleGrabber_ISampleGrabber_GetConnectedMediaType(ISampleGrabber *iface, AM_MEDIA_TYPE *type)
606 SG_Impl *This = impl_from_ISampleGrabber(iface);
607 TRACE("(%p)->(%p)\n", This, type);
608 if (!type)
609 return E_POINTER;
610 if (!This->pin_in.pair)
611 return VFW_E_NOT_CONNECTED;
612 *type = This->mtype;
613 if (type->cbFormat) {
614 type->pbFormat = CoTaskMemAlloc(type->cbFormat);
615 CopyMemory(type->pbFormat, This->mtype.pbFormat, type->cbFormat);
617 return S_OK;
620 /* ISampleGrabber */
621 static HRESULT WINAPI
622 SampleGrabber_ISampleGrabber_SetBufferSamples(ISampleGrabber *iface, BOOL bufferEm)
624 SG_Impl *This = impl_from_ISampleGrabber(iface);
625 TRACE("(%p)->(%u)\n", This, bufferEm);
626 EnterCriticalSection(&This->filter.csFilter);
627 if (bufferEm) {
628 if (This->bufferLen < 0)
629 This->bufferLen = 0;
631 else
632 This->bufferLen = -1;
633 LeaveCriticalSection(&This->filter.csFilter);
634 return S_OK;
637 /* ISampleGrabber */
638 static HRESULT WINAPI
639 SampleGrabber_ISampleGrabber_GetCurrentBuffer(ISampleGrabber *iface, LONG *bufSize, LONG *buffer)
641 SG_Impl *This = impl_from_ISampleGrabber(iface);
642 HRESULT ret = S_OK;
643 TRACE("(%p)->(%p, %p)\n", This, bufSize, buffer);
644 if (!bufSize)
645 return E_POINTER;
646 EnterCriticalSection(&This->filter.csFilter);
647 if (!This->pin_in.pair)
648 ret = VFW_E_NOT_CONNECTED;
649 else if (This->bufferLen < 0)
650 ret = E_INVALIDARG;
651 else if (This->bufferLen == 0)
652 ret = VFW_E_WRONG_STATE;
653 else {
654 if (buffer) {
655 if (*bufSize >= This->bufferLen)
656 CopyMemory(buffer, This->bufferData, This->bufferLen);
657 else
658 ret = E_OUTOFMEMORY;
660 *bufSize = This->bufferLen;
662 LeaveCriticalSection(&This->filter.csFilter);
663 return ret;
666 /* ISampleGrabber */
667 static HRESULT WINAPI
668 SampleGrabber_ISampleGrabber_GetCurrentSample(ISampleGrabber *iface, IMediaSample **sample)
670 /* MS doesn't implement it either, no one should call it */
671 WARN("(%p): not implemented\n", sample);
672 return E_NOTIMPL;
675 /* ISampleGrabber */
676 static HRESULT WINAPI
677 SampleGrabber_ISampleGrabber_SetCallback(ISampleGrabber *iface, ISampleGrabberCB *cb, LONG whichMethod)
679 SG_Impl *This = impl_from_ISampleGrabber(iface);
680 TRACE("(%p)->(%p, %u)\n", This, cb, whichMethod);
681 if (This->grabberIface)
682 ISampleGrabberCB_Release(This->grabberIface);
683 This->grabberIface = cb;
684 This->grabberMethod = whichMethod;
685 if (cb)
686 ISampleGrabberCB_AddRef(cb);
687 return S_OK;
691 /* SampleGrabber implementation of IMemInputPin interface */
693 /* IUnknown */
694 static HRESULT WINAPI
695 SampleGrabber_IMemInputPin_QueryInterface(IMemInputPin *iface, REFIID riid, void **ppv)
697 SG_Impl *This = impl_from_IMemInputPin(iface);
698 return IUnknown_QueryInterface(This->outer_unk, riid, ppv);
701 /* IUnknown */
702 static ULONG WINAPI
703 SampleGrabber_IMemInputPin_AddRef(IMemInputPin *iface)
705 SG_Impl *This = impl_from_IMemInputPin(iface);
706 return IUnknown_AddRef(This->outer_unk);
709 /* IUnknown */
710 static ULONG WINAPI
711 SampleGrabber_IMemInputPin_Release(IMemInputPin *iface)
713 SG_Impl *This = impl_from_IMemInputPin(iface);
714 return IUnknown_Release(This->outer_unk);
717 /* IMemInputPin */
718 static HRESULT WINAPI
719 SampleGrabber_IMemInputPin_GetAllocator(IMemInputPin *iface, IMemAllocator **allocator)
721 SG_Impl *This = impl_from_IMemInputPin(iface);
722 TRACE("(%p)->(%p) allocator = %p\n", This, allocator, This->allocator);
723 if (!allocator)
724 return E_POINTER;
725 *allocator = This->allocator;
726 if (!*allocator)
727 return VFW_E_NO_ALLOCATOR;
728 IMemAllocator_AddRef(*allocator);
729 return S_OK;
732 /* IMemInputPin */
733 static HRESULT WINAPI
734 SampleGrabber_IMemInputPin_NotifyAllocator(IMemInputPin *iface, IMemAllocator *allocator, BOOL readOnly)
736 SG_Impl *This = impl_from_IMemInputPin(iface);
737 TRACE("(%p)->(%p, %u) allocator = %p\n", This, allocator, readOnly, This->allocator);
738 if (This->allocator == allocator)
739 return S_OK;
740 if (This->allocator)
741 IMemAllocator_Release(This->allocator);
742 This->allocator = allocator;
743 if (allocator)
744 IMemAllocator_AddRef(allocator);
745 return S_OK;
748 /* IMemInputPin */
749 static HRESULT WINAPI
750 SampleGrabber_IMemInputPin_GetAllocatorRequirements(IMemInputPin *iface, ALLOCATOR_PROPERTIES *props)
752 SG_Impl *This = impl_from_IMemInputPin(iface);
753 FIXME("(%p)->(%p): semi-stub\n", This, props);
754 if (!props)
755 return E_POINTER;
756 return This->memOutput ? IMemInputPin_GetAllocatorRequirements(This->memOutput, props) : E_NOTIMPL;
759 /* IMemInputPin */
760 static HRESULT WINAPI
761 SampleGrabber_IMemInputPin_Receive(IMemInputPin *iface, IMediaSample *sample)
763 SG_Impl *This = impl_from_IMemInputPin(iface);
764 HRESULT hr;
765 TRACE("(%p)->(%p) output = %p, grabber = %p\n", This, sample, This->memOutput, This->grabberIface);
766 if (!sample)
767 return E_POINTER;
768 if (This->oneShot == OneShot_Past)
769 return S_FALSE;
770 SampleGrabber_callback(This, sample);
771 hr = This->memOutput ? IMemInputPin_Receive(This->memOutput, sample) : S_OK;
772 if (This->oneShot == OneShot_Wait) {
773 This->oneShot = OneShot_Past;
774 hr = S_FALSE;
775 if (This->pin_out.pair)
776 IPin_EndOfStream(This->pin_out.pair);
778 return hr;
781 /* IMemInputPin */
782 static HRESULT WINAPI
783 SampleGrabber_IMemInputPin_ReceiveMultiple(IMemInputPin *iface, IMediaSample **samples, LONG nSamples, LONG *nProcessed)
785 SG_Impl *This = impl_from_IMemInputPin(iface);
786 LONG idx;
787 TRACE("(%p)->(%p, %u, %p) output = %p, grabber = %p\n", This, samples, nSamples, nProcessed, This->memOutput, This->grabberIface);
788 if (!samples || !nProcessed)
789 return E_POINTER;
790 if ((This->filter.state != State_Running) || (This->oneShot == OneShot_Past))
791 return S_FALSE;
792 for (idx = 0; idx < nSamples; idx++)
793 SampleGrabber_callback(This, samples[idx]);
794 return This->memOutput ? IMemInputPin_ReceiveMultiple(This->memOutput, samples, nSamples, nProcessed) : S_OK;
797 /* IMemInputPin */
798 static HRESULT WINAPI
799 SampleGrabber_IMemInputPin_ReceiveCanBlock(IMemInputPin *iface)
801 SG_Impl *This = impl_from_IMemInputPin(iface);
802 TRACE("(%p)\n", This);
803 return This->memOutput ? IMemInputPin_ReceiveCanBlock(This->memOutput) : S_OK;
807 /* SampleGrabber member pin implementation */
809 /* IUnknown */
810 static ULONG WINAPI
811 SampleGrabber_IPin_AddRef(IPin *iface)
813 SG_Pin *This = impl_from_IPin(iface);
814 return ISampleGrabber_AddRef(&This->sg->ISampleGrabber_iface);
817 /* IUnknown */
818 static ULONG WINAPI
819 SampleGrabber_IPin_Release(IPin *iface)
821 SG_Pin *This = impl_from_IPin(iface);
822 return ISampleGrabber_Release(&This->sg->ISampleGrabber_iface);
825 /* IUnknown */
826 static HRESULT WINAPI
827 SampleGrabber_IPin_QueryInterface(IPin *iface, REFIID riid, void **ppv)
829 SG_Pin *This = impl_from_IPin(iface);
830 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppv);
832 *ppv = NULL;
833 if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IPin))
834 *ppv = iface;
835 else if (IsEqualIID(riid, &IID_IMemInputPin))
836 *ppv = &This->sg->IMemInputPin_iface;
837 else if (IsEqualIID(riid, &IID_IMediaSeeking))
838 return IUnknown_QueryInterface(&This->sg->IUnknown_inner, riid, ppv);
839 else if (IsEqualIID(riid, &IID_IMediaPosition))
840 return IUnknown_QueryInterface(&This->sg->IUnknown_inner, riid, ppv);
841 else {
842 WARN("(%p, %s,%p): not found\n", This, debugstr_guid(riid), ppv);
843 return E_NOINTERFACE;
846 IUnknown_AddRef((IUnknown*)*ppv);
847 return S_OK;
850 /* IPin - input pin */
851 static HRESULT WINAPI
852 SampleGrabber_In_IPin_Connect(IPin *iface, IPin *receiver, const AM_MEDIA_TYPE *mtype)
854 WARN("(%p, %p): unexpected\n", receiver, mtype);
855 return E_UNEXPECTED;
858 /* IPin - output pin */
859 static HRESULT WINAPI
860 SampleGrabber_Out_IPin_Connect(IPin *iface, IPin *receiver, const AM_MEDIA_TYPE *type)
862 SG_Pin *This = impl_from_IPin(iface);
863 HRESULT hr;
865 TRACE("(%p)->(%p, %p)\n", This, receiver, type);
866 if (!receiver)
867 return E_POINTER;
868 if (This->pair)
869 return VFW_E_ALREADY_CONNECTED;
870 if (This->sg->filter.state != State_Stopped)
871 return VFW_E_NOT_STOPPED;
872 if (type) {
873 TRACE("Media type: %s/%s ssize: %u format: %s (%u bytes)\n",
874 debugstr_guid(&type->majortype), debugstr_guid(&type->subtype),
875 type->lSampleSize,
876 debugstr_guid(&type->formattype), type->cbFormat);
877 if (!IsEqualGUID(&This->sg->mtype.majortype,&GUID_NULL) &&
878 !IsEqualGUID(&This->sg->mtype.majortype,&type->majortype))
879 return VFW_E_TYPE_NOT_ACCEPTED;
880 if (!IsEqualGUID(&This->sg->mtype.subtype,&MEDIASUBTYPE_None) &&
881 !IsEqualGUID(&This->sg->mtype.subtype,&type->subtype))
882 return VFW_E_TYPE_NOT_ACCEPTED;
883 if (!IsEqualGUID(&This->sg->mtype.formattype,&GUID_NULL) &&
884 !IsEqualGUID(&This->sg->mtype.formattype,&FORMAT_None) &&
885 !IsEqualGUID(&This->sg->mtype.formattype,&type->formattype))
886 return VFW_E_TYPE_NOT_ACCEPTED;
888 else
889 type = &This->sg->mtype;
890 if (!IsEqualGUID(&type->formattype, &FORMAT_None) &&
891 !IsEqualGUID(&type->formattype, &GUID_NULL) &&
892 !type->pbFormat)
893 return VFW_E_TYPE_NOT_ACCEPTED;
894 hr = IPin_ReceiveConnection(receiver, &This->IPin_iface, type);
895 if (FAILED(hr))
896 return hr;
897 This->pair = receiver;
898 if (This->sg->memOutput) {
899 IMemInputPin_Release(This->sg->memOutput);
900 This->sg->memOutput = NULL;
902 IPin_QueryInterface(receiver,&IID_IMemInputPin,(void **)&(This->sg->memOutput));
903 TRACE("(%p) Accepted IPin %p, IMemInputPin %p\n", This, receiver, This->sg->memOutput);
904 return S_OK;
907 /* IPin - input pin */
908 static HRESULT WINAPI
909 SampleGrabber_In_IPin_ReceiveConnection(IPin *iface, IPin *connector, const AM_MEDIA_TYPE *type)
911 SG_Pin *This = impl_from_IPin(iface);
913 TRACE("(%p)->(%p, %p)\n", This, connector, type);
914 if (!connector)
915 return E_POINTER;
916 if (This->pair)
917 return VFW_E_ALREADY_CONNECTED;
918 if (This->sg->filter.state != State_Stopped)
919 return VFW_E_NOT_STOPPED;
920 if (type) {
921 TRACE("Media type: %s/%s ssize: %u format: %s (%u bytes)\n",
922 debugstr_guid(&type->majortype), debugstr_guid(&type->subtype),
923 type->lSampleSize,
924 debugstr_guid(&type->formattype), type->cbFormat);
925 if (!IsEqualGUID(&type->formattype, &FORMAT_None) &&
926 !IsEqualGUID(&type->formattype, &GUID_NULL) &&
927 !type->pbFormat)
928 return VFW_E_INVALIDMEDIATYPE;
929 if (!IsEqualGUID(&This->sg->mtype.majortype,&GUID_NULL) &&
930 !IsEqualGUID(&This->sg->mtype.majortype,&type->majortype))
931 return VFW_E_TYPE_NOT_ACCEPTED;
932 if (!IsEqualGUID(&This->sg->mtype.subtype,&MEDIASUBTYPE_None) &&
933 !IsEqualGUID(&This->sg->mtype.subtype,&type->subtype))
934 return VFW_E_TYPE_NOT_ACCEPTED;
935 if (!IsEqualGUID(&This->sg->mtype.formattype,&GUID_NULL) &&
936 !IsEqualGUID(&This->sg->mtype.formattype,&FORMAT_None) &&
937 !IsEqualGUID(&This->sg->mtype.formattype,&type->formattype))
938 return VFW_E_TYPE_NOT_ACCEPTED;
939 if (This->sg->mtype.pbFormat)
940 CoTaskMemFree(This->sg->mtype.pbFormat);
941 This->sg->mtype = *type;
942 This->sg->mtype.pUnk = NULL;
943 if (type->cbFormat) {
944 This->sg->mtype.pbFormat = CoTaskMemAlloc(type->cbFormat);
945 CopyMemory(This->sg->mtype.pbFormat, type->pbFormat, type->cbFormat);
947 else
948 This->sg->mtype.pbFormat = NULL;
950 This->pair = connector;
951 TRACE("(%p) Accepted IPin %p\n", This, connector);
952 return S_OK;
955 /* IPin - output pin */
956 static HRESULT WINAPI
957 SampleGrabber_Out_IPin_ReceiveConnection(IPin *iface, IPin *connector, const AM_MEDIA_TYPE *mtype)
959 WARN("(%p, %p): unexpected\n", connector, mtype);
960 return E_UNEXPECTED;
963 /* IPin - input pin */
964 static HRESULT WINAPI
965 SampleGrabber_In_IPin_Disconnect(IPin *iface)
967 SG_Pin *This = impl_from_IPin(iface);
969 TRACE("(%p)->() pair = %p\n", This, This->pair);
970 if (This->sg->filter.state != State_Stopped)
971 return VFW_E_NOT_STOPPED;
972 if (This->pair) {
973 This->pair = NULL;
974 return S_OK;
976 return S_FALSE;
979 /* IPin - output pin */
980 static HRESULT WINAPI
981 SampleGrabber_Out_IPin_Disconnect(IPin *iface)
983 SG_Pin *This = impl_from_IPin(iface);
985 TRACE("(%p)->() pair = %p\n", This, This->pair);
986 if (This->sg->filter.state != State_Stopped)
987 return VFW_E_NOT_STOPPED;
988 if (This->pair) {
989 This->pair = NULL;
990 if (This->sg->memOutput) {
991 IMemInputPin_Release(This->sg->memOutput);
992 This->sg->memOutput = NULL;
994 return S_OK;
996 return S_FALSE;
999 /* IPin */
1000 static HRESULT WINAPI
1001 SampleGrabber_IPin_ConnectedTo(IPin *iface, IPin **pin)
1003 SG_Pin *This = impl_from_IPin(iface);
1005 TRACE("(%p)->(%p) pair = %p\n", This, pin, This->pair);
1006 if (!pin)
1007 return E_POINTER;
1008 *pin = This->pair;
1009 if (*pin) {
1010 IPin_AddRef(*pin);
1011 return S_OK;
1013 return VFW_E_NOT_CONNECTED;
1016 /* IPin */
1017 static HRESULT WINAPI
1018 SampleGrabber_IPin_ConnectionMediaType(IPin *iface, AM_MEDIA_TYPE *mtype)
1020 SG_Pin *This = impl_from_IPin(iface);
1022 TRACE("(%p)->(%p)\n", This, mtype);
1023 if (!mtype)
1024 return E_POINTER;
1025 if (!This->pair)
1026 return VFW_E_NOT_CONNECTED;
1027 *mtype = This->sg->mtype;
1028 if (mtype->cbFormat) {
1029 mtype->pbFormat = CoTaskMemAlloc(mtype->cbFormat);
1030 CopyMemory(mtype->pbFormat, This->sg->mtype.pbFormat, mtype->cbFormat);
1032 return S_OK;
1035 /* IPin */
1036 static HRESULT WINAPI
1037 SampleGrabber_IPin_QueryPinInfo(IPin *iface, PIN_INFO *info)
1039 SG_Pin *This = impl_from_IPin(iface);
1041 TRACE("(%p)->(%p)\n", This, info);
1042 if (!info)
1043 return E_POINTER;
1044 info->pFilter = &This->sg->filter.IBaseFilter_iface;
1045 IBaseFilter_AddRef(info->pFilter);
1046 info->dir = This->dir;
1047 lstrcpynW(info->achName,This->name,MAX_PIN_NAME);
1048 return S_OK;
1051 /* IPin */
1052 static HRESULT WINAPI
1053 SampleGrabber_IPin_QueryDirection(IPin *iface, PIN_DIRECTION *dir)
1055 SG_Pin *This = impl_from_IPin(iface);
1057 TRACE("(%p)->(%p)\n", This, dir);
1058 if (!dir)
1059 return E_POINTER;
1060 *dir = This->dir;
1061 return S_OK;
1064 /* IPin */
1065 static HRESULT WINAPI
1066 SampleGrabber_IPin_QueryId(IPin *iface, LPWSTR *id)
1068 SG_Pin *This = impl_from_IPin(iface);
1070 int len;
1071 TRACE("(%p)->(%p)\n", This, id);
1072 if (!id)
1073 return E_POINTER;
1074 len = sizeof(WCHAR)*(1+lstrlenW(This->name));
1075 *id = CoTaskMemAlloc(len);
1076 CopyMemory(*id, This->name, len);
1077 return S_OK;
1080 /* IPin */
1081 static HRESULT WINAPI
1082 SampleGrabber_IPin_QueryAccept(IPin *iface, const AM_MEDIA_TYPE *mtype)
1084 TRACE("(%p)\n", mtype);
1085 return S_OK;
1088 /* IPin */
1089 static HRESULT WINAPI
1090 SampleGrabber_IPin_EnumMediaTypes(IPin *iface, IEnumMediaTypes **mtypes)
1092 SG_Pin *This = impl_from_IPin(iface);
1094 TRACE("(%p)->(%p)\n", This, mtypes);
1095 if (!mtypes)
1096 return E_POINTER;
1097 *mtypes = mediaenum_create(This->sg->pin_in.pair ? &This->sg->mtype : NULL, FALSE);
1098 return *mtypes ? S_OK : E_OUTOFMEMORY;
1101 /* IPin - input pin */
1102 static HRESULT WINAPI
1103 SampleGrabber_In_IPin_QueryInternalConnections(IPin *iface, IPin **pins, ULONG *nPins)
1105 SG_Pin *This = impl_from_IPin(iface);
1107 TRACE("(%p)->(%p, %p) size = %u\n", This, pins, nPins, (nPins ? *nPins : 0));
1108 if (!nPins)
1109 return E_POINTER;
1110 if (*nPins) {
1111 if (!pins)
1112 return E_POINTER;
1113 IPin_AddRef(&This->sg->pin_out.IPin_iface);
1114 *pins = &This->sg->pin_out.IPin_iface;
1115 *nPins = 1;
1116 return S_OK;
1118 *nPins = 1;
1119 return S_FALSE;
1122 /* IPin - output pin */
1123 static HRESULT WINAPI
1124 SampleGrabber_Out_IPin_QueryInternalConnections(IPin *iface, IPin **pins, ULONG *nPins)
1126 WARN("(%p, %p): unexpected\n", pins, nPins);
1127 if (nPins)
1128 *nPins = 0;
1129 return E_NOTIMPL;
1132 /* IPin */
1133 static HRESULT WINAPI
1134 SampleGrabber_IPin_EndOfStream(IPin *iface)
1136 FIXME(": stub\n");
1137 return S_OK;
1140 /* IPin */
1141 static HRESULT WINAPI
1142 SampleGrabber_IPin_BeginFlush(IPin *iface)
1144 FIXME(": stub\n");
1145 return S_OK;
1148 /* IPin */
1149 static HRESULT WINAPI
1150 SampleGrabber_IPin_EndFlush(IPin *iface)
1152 FIXME(": stub\n");
1153 return S_OK;
1156 /* IPin */
1157 static HRESULT WINAPI
1158 SampleGrabber_IPin_NewSegment(IPin *iface, REFERENCE_TIME tStart, REFERENCE_TIME tStop, double rate)
1160 FIXME(": stub\n");
1161 return S_OK;
1165 /* SampleGrabber vtables and constructor */
1167 static const IBaseFilterVtbl IBaseFilter_VTable =
1169 SampleGrabber_IBaseFilter_QueryInterface,
1170 SampleGrabber_IBaseFilter_AddRef,
1171 SampleGrabber_IBaseFilter_Release,
1172 BaseFilterImpl_GetClassID,
1173 SampleGrabber_IBaseFilter_Stop,
1174 SampleGrabber_IBaseFilter_Pause,
1175 SampleGrabber_IBaseFilter_Run,
1176 BaseFilterImpl_GetState,
1177 BaseFilterImpl_SetSyncSource,
1178 BaseFilterImpl_GetSyncSource,
1179 BaseFilterImpl_EnumPins,
1180 SampleGrabber_IBaseFilter_FindPin,
1181 BaseFilterImpl_QueryFilterInfo,
1182 SampleGrabber_IBaseFilter_JoinFilterGraph,
1183 SampleGrabber_IBaseFilter_QueryVendorInfo,
1186 static const ISampleGrabberVtbl ISampleGrabber_VTable =
1188 SampleGrabber_ISampleGrabber_QueryInterface,
1189 SampleGrabber_ISampleGrabber_AddRef,
1190 SampleGrabber_ISampleGrabber_Release,
1191 SampleGrabber_ISampleGrabber_SetOneShot,
1192 SampleGrabber_ISampleGrabber_SetMediaType,
1193 SampleGrabber_ISampleGrabber_GetConnectedMediaType,
1194 SampleGrabber_ISampleGrabber_SetBufferSamples,
1195 SampleGrabber_ISampleGrabber_GetCurrentBuffer,
1196 SampleGrabber_ISampleGrabber_GetCurrentSample,
1197 SampleGrabber_ISampleGrabber_SetCallback,
1200 static const IMemInputPinVtbl IMemInputPin_VTable =
1202 SampleGrabber_IMemInputPin_QueryInterface,
1203 SampleGrabber_IMemInputPin_AddRef,
1204 SampleGrabber_IMemInputPin_Release,
1205 SampleGrabber_IMemInputPin_GetAllocator,
1206 SampleGrabber_IMemInputPin_NotifyAllocator,
1207 SampleGrabber_IMemInputPin_GetAllocatorRequirements,
1208 SampleGrabber_IMemInputPin_Receive,
1209 SampleGrabber_IMemInputPin_ReceiveMultiple,
1210 SampleGrabber_IMemInputPin_ReceiveCanBlock,
1213 static const IPinVtbl IPin_In_VTable =
1215 SampleGrabber_IPin_QueryInterface,
1216 SampleGrabber_IPin_AddRef,
1217 SampleGrabber_IPin_Release,
1218 SampleGrabber_In_IPin_Connect,
1219 SampleGrabber_In_IPin_ReceiveConnection,
1220 SampleGrabber_In_IPin_Disconnect,
1221 SampleGrabber_IPin_ConnectedTo,
1222 SampleGrabber_IPin_ConnectionMediaType,
1223 SampleGrabber_IPin_QueryPinInfo,
1224 SampleGrabber_IPin_QueryDirection,
1225 SampleGrabber_IPin_QueryId,
1226 SampleGrabber_IPin_QueryAccept,
1227 SampleGrabber_IPin_EnumMediaTypes,
1228 SampleGrabber_In_IPin_QueryInternalConnections,
1229 SampleGrabber_IPin_EndOfStream,
1230 SampleGrabber_IPin_BeginFlush,
1231 SampleGrabber_IPin_EndFlush,
1232 SampleGrabber_IPin_NewSegment,
1235 static const IPinVtbl IPin_Out_VTable =
1237 SampleGrabber_IPin_QueryInterface,
1238 SampleGrabber_IPin_AddRef,
1239 SampleGrabber_IPin_Release,
1240 SampleGrabber_Out_IPin_Connect,
1241 SampleGrabber_Out_IPin_ReceiveConnection,
1242 SampleGrabber_Out_IPin_Disconnect,
1243 SampleGrabber_IPin_ConnectedTo,
1244 SampleGrabber_IPin_ConnectionMediaType,
1245 SampleGrabber_IPin_QueryPinInfo,
1246 SampleGrabber_IPin_QueryDirection,
1247 SampleGrabber_IPin_QueryId,
1248 SampleGrabber_IPin_QueryAccept,
1249 SampleGrabber_IPin_EnumMediaTypes,
1250 SampleGrabber_Out_IPin_QueryInternalConnections,
1251 SampleGrabber_IPin_EndOfStream,
1252 SampleGrabber_IPin_BeginFlush,
1253 SampleGrabber_IPin_EndFlush,
1254 SampleGrabber_IPin_NewSegment,
1257 HRESULT SampleGrabber_create(IUnknown *pUnkOuter, LPVOID *ppv)
1259 SG_Impl* obj = NULL;
1260 ISeekingPassThru *passthru;
1261 HRESULT hr;
1263 TRACE("(%p,%p)\n", pUnkOuter, ppv);
1265 obj = CoTaskMemAlloc(sizeof(SG_Impl));
1266 if (NULL == obj) {
1267 *ppv = NULL;
1268 return E_OUTOFMEMORY;
1270 ZeroMemory(obj, sizeof(SG_Impl));
1272 BaseFilter_Init(&obj->filter, &IBaseFilter_VTable, &CLSID_SampleGrabber,
1273 (DWORD_PTR)(__FILE__ ": SG_Impl.csFilter"), &basefunc_vtbl);
1274 obj->IUnknown_inner.lpVtbl = &samplegrabber_vtbl;
1275 obj->ISampleGrabber_iface.lpVtbl = &ISampleGrabber_VTable;
1276 obj->IMemInputPin_iface.lpVtbl = &IMemInputPin_VTable;
1277 obj->pin_in.IPin_iface.lpVtbl = &IPin_In_VTable;
1278 obj->pin_in.dir = PINDIR_INPUT;
1279 obj->pin_in.name = pin_in_name;
1280 obj->pin_in.sg = obj;
1281 obj->pin_in.pair = NULL;
1282 obj->pin_out.IPin_iface.lpVtbl = &IPin_Out_VTable;
1283 obj->pin_out.dir = PINDIR_OUTPUT;
1284 obj->pin_out.name = pin_out_name;
1285 obj->pin_out.sg = obj;
1286 obj->pin_out.pair = NULL;
1287 obj->mtype.majortype = GUID_NULL;
1288 obj->mtype.subtype = MEDIASUBTYPE_None;
1289 obj->mtype.formattype = FORMAT_None;
1290 obj->allocator = NULL;
1291 obj->memOutput = NULL;
1292 obj->grabberIface = NULL;
1293 obj->grabberMethod = -1;
1294 obj->oneShot = OneShot_None;
1295 obj->bufferLen = -1;
1296 obj->bufferData = NULL;
1298 if (pUnkOuter)
1299 obj->outer_unk = pUnkOuter;
1300 else
1301 obj->outer_unk = &obj->IUnknown_inner;
1303 hr = CoCreateInstance(&CLSID_SeekingPassThru, (IUnknown*)obj, CLSCTX_INPROC_SERVER, &IID_IUnknown, (void**)&obj->seekthru_unk);
1304 if(hr)
1305 return hr;
1306 IUnknown_QueryInterface(obj->seekthru_unk, &IID_ISeekingPassThru, (void**)&passthru);
1307 ISeekingPassThru_Init(passthru, FALSE, &obj->pin_in.IPin_iface);
1308 ISeekingPassThru_Release(passthru);
1310 *ppv = &obj->IUnknown_inner;
1311 return S_OK;