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 IEnumPins
*pinsenum_create(IBaseFilter
*filter
, IPin
**pins
, ULONG pinCount
);
40 IEnumMediaTypes
*mediaenum_create(AM_MEDIA_TYPE
*mtype
);
42 /* Fixed pins enumerator, holds filter referenced */
43 typedef struct _PE_Impl
{
53 /* IEnumPins interface implementation */
57 Fixed_IEnumPins_AddRef(IEnumPins
*iface
)
59 PE_Impl
*This
= (PE_Impl
*)iface
;
60 ULONG refCount
= InterlockedIncrement(&This
->refCount
);
61 TRACE("(%p) new ref = %u\n", This
, refCount
);
67 Fixed_IEnumPins_Release(IEnumPins
*iface
)
69 PE_Impl
*This
= (PE_Impl
*)iface
;
70 ULONG refCount
= InterlockedDecrement(&This
->refCount
);
71 TRACE("(%p) new ref = %u\n", This
, refCount
);
74 IBaseFilter_Release(This
->filter
);
83 Fixed_IEnumPins_QueryInterface(IEnumPins
*iface
, REFIID riid
, void **ppvObject
)
85 PE_Impl
*This
= (PE_Impl
*)iface
;
86 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), ppvObject
);
88 if (IsEqualIID(riid
, &IID_IUnknown
) ||
89 IsEqualIID(riid
, &IID_IEnumPins
)) {
90 Fixed_IEnumPins_AddRef(iface
);
91 *ppvObject
= &(This
->pins
);
95 WARN("(%p, %s,%p): not found\n", This
, debugstr_guid(riid
), ppvObject
);
100 static HRESULT WINAPI
101 Fixed_IEnumPins_Next(IEnumPins
*iface
, ULONG nPins
, IPin
**pins
, ULONG
*fetched
)
103 PE_Impl
*This
= (PE_Impl
*)iface
;
105 TRACE("(%p)->(%u, %p, %p) index = %u\n", This
, nPins
, pins
, fetched
, This
->index
);
108 if (!pins
|| ((nPins
!= 1) && !fetched
))
110 while ((count
< nPins
) && (This
->index
< This
->numPins
)) {
111 IPin
*pin
= This
->pins
[This
->index
++];
117 return (count
== nPins
) ? S_OK
: S_FALSE
;
121 static HRESULT WINAPI
122 Fixed_IEnumPins_Skip(IEnumPins
*iface
, ULONG nPins
)
124 PE_Impl
*This
= (PE_Impl
*)iface
;
125 TRACE("(%p)->(%u) index = %u\n", This
, nPins
, This
->index
);
126 nPins
+= This
->index
;
127 if (nPins
>= This
->numPins
) {
128 This
->index
= This
->numPins
;
136 static HRESULT WINAPI
137 Fixed_IEnumPins_Reset(IEnumPins
*iface
)
139 PE_Impl
*This
= (PE_Impl
*)iface
;
140 TRACE("(%p)->() index = %u\n", This
, This
->index
);
146 static HRESULT WINAPI
147 Fixed_IEnumPins_Clone(IEnumPins
*iface
, IEnumPins
**pins
)
149 PE_Impl
*This
= (PE_Impl
*)iface
;
150 TRACE("(%p)->(%p) index = %u\n", This
, pins
, This
->index
);
153 *pins
= pinsenum_create(This
->filter
, This
->pins
, This
->numPins
);
155 return E_OUTOFMEMORY
;
156 ((PE_Impl
*)*pins
)->index
= This
->index
;
161 /* Virtual tables and constructor */
163 static const IEnumPinsVtbl IEnumPins_VTable
=
165 Fixed_IEnumPins_QueryInterface
,
166 Fixed_IEnumPins_AddRef
,
167 Fixed_IEnumPins_Release
,
168 Fixed_IEnumPins_Next
,
169 Fixed_IEnumPins_Skip
,
170 Fixed_IEnumPins_Reset
,
171 Fixed_IEnumPins_Clone
,
174 IEnumPins
*pinsenum_create(IBaseFilter
*filter
, IPin
**pins
, ULONG pinCount
)
176 ULONG len
= sizeof(PE_Impl
) + (pinCount
* sizeof(IPin
*));
177 PE_Impl
*obj
= CoTaskMemAlloc(len
);
180 ZeroMemory(obj
, len
);
181 obj
->pe
.lpVtbl
= &IEnumPins_VTable
;
183 obj
->filter
= filter
;
184 obj
->numPins
= pinCount
;
186 for (i
=0; i
<pinCount
; i
++)
187 obj
->pins
[i
] = pins
[i
];
188 IBaseFilter_AddRef(filter
);
194 /* Single media type enumerator */
195 typedef struct _ME_Impl
{
203 /* IEnumMediaTypes interface implementation */
207 Single_IEnumMediaTypes_AddRef(IEnumMediaTypes
*iface
)
209 ME_Impl
*This
= (ME_Impl
*)iface
;
210 ULONG refCount
= InterlockedIncrement(&This
->refCount
);
211 TRACE("(%p) new ref = %u\n", This
, refCount
);
217 Single_IEnumMediaTypes_Release(IEnumMediaTypes
*iface
)
219 ME_Impl
*This
= (ME_Impl
*)iface
;
220 ULONG refCount
= InterlockedDecrement(&This
->refCount
);
221 TRACE("(%p) new ref = %u\n", This
, refCount
);
224 if (This
->mtype
.pbFormat
)
225 CoTaskMemFree(This
->mtype
.pbFormat
);
233 static HRESULT WINAPI
234 Single_IEnumMediaTypes_QueryInterface(IEnumMediaTypes
*iface
, REFIID riid
, void **ppvObject
)
236 ME_Impl
*This
= (ME_Impl
*)iface
;
237 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), ppvObject
);
239 if (IsEqualIID(riid
, &IID_IUnknown
) ||
240 IsEqualIID(riid
, &IID_IEnumMediaTypes
)) {
241 Single_IEnumMediaTypes_AddRef(iface
);
242 *ppvObject
= &(This
->me
);
246 WARN("(%p, %s,%p): not found\n", This
, debugstr_guid(riid
), ppvObject
);
247 return E_NOINTERFACE
;
250 /* IEnumMediaTypes */
251 static HRESULT WINAPI
252 Single_IEnumMediaTypes_Next(IEnumMediaTypes
*iface
, ULONG nTypes
, AM_MEDIA_TYPE
**types
, ULONG
*fetched
)
254 ME_Impl
*This
= (ME_Impl
*)iface
;
256 TRACE("(%p)->(%u, %p, %p)\n", This
, nTypes
, types
, fetched
);
259 if (!types
|| ((nTypes
!= 1) && !fetched
))
262 AM_MEDIA_TYPE
*mtype
= CoTaskMemAlloc(sizeof(AM_MEDIA_TYPE
));
263 *mtype
= This
->mtype
;
264 if (mtype
->cbFormat
) {
265 mtype
->pbFormat
= CoTaskMemAlloc(mtype
->cbFormat
);
266 CopyMemory(mtype
->pbFormat
, This
->mtype
.pbFormat
, mtype
->cbFormat
);
274 return (count
== nTypes
) ? S_OK
: S_FALSE
;
277 /* IEnumMediaTypes */
278 static HRESULT WINAPI
279 Single_IEnumMediaTypes_Skip(IEnumMediaTypes
*iface
, ULONG nTypes
)
281 ME_Impl
*This
= (ME_Impl
*)iface
;
282 TRACE("(%p)->(%u)\n", This
, nTypes
);
285 return This
->past
? S_FALSE
: S_OK
;
288 /* IEnumMediaTypes */
289 static HRESULT WINAPI
290 Single_IEnumMediaTypes_Reset(IEnumMediaTypes
*iface
)
292 ME_Impl
*This
= (ME_Impl
*)iface
;
293 TRACE("(%p)->()\n", This
);
298 /* IEnumMediaTypes */
299 static HRESULT WINAPI
300 Single_IEnumMediaTypes_Clone(IEnumMediaTypes
*iface
, IEnumMediaTypes
**me
)
302 ME_Impl
*This
= (ME_Impl
*)iface
;
303 TRACE("(%p)->(%p)\n", This
, me
);
306 *me
= mediaenum_create(&This
->mtype
);
308 return E_OUTOFMEMORY
;
309 ((ME_Impl
*)*me
)->past
= This
->past
;
314 /* Virtual tables and constructor */
316 static const IEnumMediaTypesVtbl IEnumMediaTypes_VTable
=
318 Single_IEnumMediaTypes_QueryInterface
,
319 Single_IEnumMediaTypes_AddRef
,
320 Single_IEnumMediaTypes_Release
,
321 Single_IEnumMediaTypes_Next
,
322 Single_IEnumMediaTypes_Skip
,
323 Single_IEnumMediaTypes_Reset
,
324 Single_IEnumMediaTypes_Clone
,
327 IEnumMediaTypes
*mediaenum_create(AM_MEDIA_TYPE
*mtype
)
329 ME_Impl
*obj
= CoTaskMemAlloc(sizeof(ME_Impl
));
331 ZeroMemory(obj
, sizeof(ME_Impl
));
332 obj
->me
.lpVtbl
= &IEnumMediaTypes_VTable
;
336 obj
->mtype
.pUnk
= NULL
;
337 if (mtype
->cbFormat
) {
338 obj
->mtype
.pbFormat
= CoTaskMemAlloc(mtype
->cbFormat
);
339 CopyMemory(obj
->mtype
.pbFormat
, mtype
->pbFormat
, mtype
->cbFormat
);
342 obj
->mtype
.pbFormat
= NULL
;
348 /* Sample Grabber pin implementation */
349 typedef struct _SG_Pin
{
350 const IPinVtbl
* lpVtbl
;
357 /* Sample Grabber filter implementation */
358 typedef struct _SG_Impl
{
359 const IBaseFilterVtbl
* IBaseFilter_Vtbl
;
360 const ISampleGrabberVtbl
* ISampleGrabber_Vtbl
;
361 const IMemInputPinVtbl
* IMemInputPin_Vtbl
;
362 /* TODO: IMediaPosition, IMediaSeeking, IQualityControl */
369 IMemAllocator
*allocator
;
370 IReferenceClock
*refClock
;
371 IMemInputPin
*memOutput
;
372 ISampleGrabberCB
*grabberIface
;
383 /* Get the SampleGrabber implementation This pointer from various interface pointers */
384 static inline SG_Impl
*impl_from_IBaseFilter(IBaseFilter
*iface
)
386 return (SG_Impl
*)((char*)iface
- FIELD_OFFSET(SG_Impl
, IBaseFilter_Vtbl
));
389 static inline SG_Impl
*impl_from_ISampleGrabber(ISampleGrabber
*iface
)
391 return (SG_Impl
*)((char*)iface
- FIELD_OFFSET(SG_Impl
, ISampleGrabber_Vtbl
));
394 static inline SG_Impl
*impl_from_IMemInputPin(IMemInputPin
*iface
)
396 return (SG_Impl
*)((char*)iface
- FIELD_OFFSET(SG_Impl
, IMemInputPin_Vtbl
));
400 /* Cleanup at end of life */
401 static void SampleGrabber_cleanup(SG_Impl
*This
)
403 TRACE("(%p)\n", This
);
404 if (This
->info
.pGraph
)
405 WARN("(%p) still joined to filter graph %p\n", This
, This
->info
.pGraph
);
407 IMemAllocator_Release(This
->allocator
);
409 IReferenceClock_Release(This
->refClock
);
411 IMemInputPin_Release(This
->memOutput
);
412 if (This
->grabberIface
)
413 ISampleGrabberCB_Release(This
->grabberIface
);
414 if (This
->mtype
.pbFormat
)
415 CoTaskMemFree(This
->mtype
.pbFormat
);
418 /* Common helper AddRef called from all interfaces */
419 static ULONG
SampleGrabber_addref(SG_Impl
*This
)
421 ULONG refCount
= InterlockedIncrement(&This
->refCount
);
422 TRACE("(%p) new ref = %u\n", This
, refCount
);
426 /* Common helper Release called from all interfaces */
427 static ULONG
SampleGrabber_release(SG_Impl
*This
)
429 ULONG refCount
= InterlockedDecrement(&This
->refCount
);
430 TRACE("(%p) new ref = %u\n", This
, refCount
);
433 SampleGrabber_cleanup(This
);
440 /* Common helper QueryInterface called from all interfaces */
441 static HRESULT
SampleGrabber_query(SG_Impl
*This
, REFIID riid
, void **ppvObject
)
443 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), ppvObject
);
445 if (IsEqualIID(riid
, &IID_IUnknown
) ||
446 IsEqualIID(riid
, &IID_IPersist
) ||
447 IsEqualIID(riid
, &IID_IMediaFilter
) ||
448 IsEqualIID(riid
, &IID_IBaseFilter
)) {
449 SampleGrabber_addref(This
);
450 *ppvObject
= &(This
->IBaseFilter_Vtbl
);
453 else if (IsEqualIID(riid
, &IID_ISampleGrabber
)) {
454 SampleGrabber_addref(This
);
455 *ppvObject
= &(This
->ISampleGrabber_Vtbl
);
458 else if (IsEqualIID(riid
, &IID_IMemInputPin
)) {
459 SampleGrabber_addref(This
);
460 *ppvObject
= &(This
->IMemInputPin_Vtbl
);
463 else if (IsEqualIID(riid
, &IID_IMediaPosition
))
464 FIXME("IMediaPosition not implemented\n");
465 else if (IsEqualIID(riid
, &IID_IMediaSeeking
))
466 FIXME("IMediaSeeking not implemented\n");
467 else if (IsEqualIID(riid
, &IID_IQualityControl
))
468 FIXME("IQualityControl not implemented\n");
470 WARN("(%p, %s,%p): not found\n", This
, debugstr_guid(riid
), ppvObject
);
471 return E_NOINTERFACE
;
474 /* Helper that calls installed sample callbacks */
475 static void SampleGrabber_callback(SG_Impl
*This
, IMediaSample
*sample
)
478 REFERENCE_TIME tStart
, tEnd
;
479 if (SUCCEEDED(IMediaSample_GetTime(sample
, &tStart
, &tEnd
)))
480 time
= 1e-7 * tStart
;
481 switch (This
->grabberMethod
) {
484 ULONG ref
= IMediaSample_AddRef(sample
);
485 ISampleGrabberCB_SampleCB(This
->grabberIface
, time
, sample
);
486 ref
= IMediaSample_Release(sample
) + 1 - ref
;
489 ERR("(%p) Callback referenced sample %p by %u\n", This
, sample
, ref
);
490 /* ugly as hell but some apps are sooo buggy */
492 IMediaSample_Release(sample
);
499 long size
= IMediaSample_GetActualDataLength(sample
);
500 if (size
&& SUCCEEDED(IMediaSample_GetPointer(sample
, &data
)) && data
)
501 ISampleGrabberCB_BufferCB(This
->grabberIface
, time
, data
, size
);
507 FIXME("unsupported method %ld\n", (long int)This
->grabberMethod
);
508 /* do not bother us again */
509 This
->grabberMethod
= -1;
514 /* SampleGrabber implementation of IBaseFilter interface */
517 static HRESULT WINAPI
518 SampleGrabber_IBaseFilter_QueryInterface(IBaseFilter
*iface
, REFIID riid
, void **ppvObject
)
520 return SampleGrabber_query(impl_from_IBaseFilter(iface
), riid
, ppvObject
);
525 SampleGrabber_IBaseFilter_AddRef(IBaseFilter
*iface
)
527 return SampleGrabber_addref(impl_from_IBaseFilter(iface
));
532 SampleGrabber_IBaseFilter_Release(IBaseFilter
*iface
)
534 return SampleGrabber_release(impl_from_IBaseFilter(iface
));
538 static HRESULT WINAPI
539 SampleGrabber_IBaseFilter_GetClassID(IBaseFilter
*iface
, CLSID
*pClassID
)
541 TRACE("(%p)\n", pClassID
);
544 *pClassID
= CLSID_SampleGrabber
;
549 static HRESULT WINAPI
550 SampleGrabber_IBaseFilter_Stop(IBaseFilter
*iface
)
552 SG_Impl
*This
= impl_from_IBaseFilter(iface
);
553 TRACE("(%p)\n", This
);
554 This
->state
= State_Stopped
;
559 static HRESULT WINAPI
560 SampleGrabber_IBaseFilter_Pause(IBaseFilter
*iface
)
562 SG_Impl
*This
= impl_from_IBaseFilter(iface
);
563 TRACE("(%p)\n", This
);
564 This
->state
= State_Paused
;
569 static HRESULT WINAPI
570 SampleGrabber_IBaseFilter_Run(IBaseFilter
*iface
, REFERENCE_TIME tStart
)
572 SG_Impl
*This
= impl_from_IBaseFilter(iface
);
573 TRACE("(%p)\n", This
);
574 This
->state
= State_Running
;
579 static HRESULT WINAPI
580 SampleGrabber_IBaseFilter_GetState(IBaseFilter
*iface
, DWORD msTout
, FILTER_STATE
*state
)
582 SG_Impl
*This
= impl_from_IBaseFilter(iface
);
583 TRACE("(%p)->(%u, %p)\n", This
, msTout
, state
);
586 *state
= This
->state
;
591 static HRESULT WINAPI
592 SampleGrabber_IBaseFilter_SetSyncSource(IBaseFilter
*iface
, IReferenceClock
*clock
)
594 SG_Impl
*This
= impl_from_IBaseFilter(iface
);
595 TRACE("(%p)->(%p)\n", This
, clock
);
596 if (clock
!= This
->refClock
)
599 IReferenceClock_AddRef(clock
);
601 IReferenceClock_Release(This
->refClock
);
602 This
->refClock
= clock
;
608 static HRESULT WINAPI
609 SampleGrabber_IBaseFilter_GetSyncSource(IBaseFilter
*iface
, IReferenceClock
**clock
)
611 SG_Impl
*This
= impl_from_IBaseFilter(iface
);
612 TRACE("(%p)->(%p)\n", This
, clock
);
616 IReferenceClock_AddRef(This
->refClock
);
617 *clock
= This
->refClock
;
622 static HRESULT WINAPI
623 SampleGrabber_IBaseFilter_EnumPins(IBaseFilter
*iface
, IEnumPins
**pins
)
625 SG_Impl
*This
= impl_from_IBaseFilter(iface
);
627 TRACE("(%p)->(%p)\n", This
, pins
);
630 pin
[0] = (IPin
*)&This
->pin_in
.lpVtbl
;
631 pin
[1] = (IPin
*)&This
->pin_out
.lpVtbl
;
632 *pins
= pinsenum_create(iface
, pin
, 2);
633 return *pins
? S_OK
: E_OUTOFMEMORY
;
637 static HRESULT WINAPI
638 SampleGrabber_IBaseFilter_FindPin(IBaseFilter
*iface
, LPCWSTR id
, IPin
**pin
)
640 SG_Impl
*This
= impl_from_IBaseFilter(iface
);
641 TRACE("(%p)->(%s, %p)\n", This
, debugstr_w(id
), pin
);
644 if (!lstrcmpiW(id
,pin_in_name
))
646 SampleGrabber_addref(This
);
647 *pin
= (IPin
*)&(This
->pin_in
.lpVtbl
);
650 else if (!lstrcmpiW(id
,pin_out_name
))
652 SampleGrabber_addref(This
);
653 *pin
= (IPin
*)&(This
->pin_out
.lpVtbl
);
657 return VFW_E_NOT_FOUND
;
661 static HRESULT WINAPI
662 SampleGrabber_IBaseFilter_QueryFilterInfo(IBaseFilter
*iface
, FILTER_INFO
*info
)
664 SG_Impl
*This
= impl_from_IBaseFilter(iface
);
665 TRACE("(%p)->(%p)\n", This
, info
);
668 if (This
->info
.pGraph
)
669 IFilterGraph_AddRef(This
->info
.pGraph
);
675 static HRESULT WINAPI
676 SampleGrabber_IBaseFilter_JoinFilterGraph(IBaseFilter
*iface
, IFilterGraph
*graph
, LPCWSTR name
)
678 SG_Impl
*This
= impl_from_IBaseFilter(iface
);
679 TRACE("(%p)->(%p, %s)\n", This
, graph
, debugstr_w(name
));
680 This
->info
.pGraph
= graph
;
682 lstrcpynW(This
->info
.achName
,name
,MAX_FILTER_NAME
);
683 This
->oneShot
= OneShot_None
;
688 static HRESULT WINAPI
689 SampleGrabber_IBaseFilter_QueryVendorInfo(IBaseFilter
*iface
, LPWSTR
*vendor
)
691 TRACE("(%p)\n", vendor
);
694 *vendor
= CoTaskMemAlloc(sizeof(vendor_name
));
695 CopyMemory(*vendor
, vendor_name
, sizeof(vendor_name
));
700 /* SampleGrabber implementation of ISampleGrabber interface */
703 static HRESULT WINAPI
704 SampleGrabber_ISampleGrabber_QueryInterface(ISampleGrabber
*iface
, REFIID riid
, void **ppvObject
)
706 return SampleGrabber_query(impl_from_ISampleGrabber(iface
), riid
, ppvObject
);
711 SampleGrabber_ISampleGrabber_AddRef(ISampleGrabber
*iface
)
713 return SampleGrabber_addref(impl_from_ISampleGrabber(iface
));
718 SampleGrabber_ISampleGrabber_Release(ISampleGrabber
*iface
)
720 return SampleGrabber_release(impl_from_ISampleGrabber(iface
));
724 static HRESULT WINAPI
725 SampleGrabber_ISampleGrabber_SetOneShot(ISampleGrabber
*iface
, BOOL oneShot
)
727 SG_Impl
*This
= impl_from_ISampleGrabber(iface
);
728 TRACE("(%p)->(%u)\n", This
, oneShot
);
729 This
->oneShot
= oneShot
? OneShot_Wait
: OneShot_None
;
734 static HRESULT WINAPI
735 SampleGrabber_ISampleGrabber_SetMediaType(ISampleGrabber
*iface
, const AM_MEDIA_TYPE
*type
)
737 SG_Impl
*This
= impl_from_ISampleGrabber(iface
);
738 TRACE("(%p)->(%p)\n", This
, type
);
741 TRACE("Media type: %s/%s ssize: %u format: %s (%u bytes)\n",
742 debugstr_guid(&type
->majortype
), debugstr_guid(&type
->subtype
),
744 debugstr_guid(&type
->formattype
), type
->cbFormat
);
745 if (This
->mtype
.pbFormat
)
746 CoTaskMemFree(This
->mtype
.pbFormat
);
748 This
->mtype
.pUnk
= NULL
;
749 if (type
->cbFormat
) {
750 This
->mtype
.pbFormat
= CoTaskMemAlloc(type
->cbFormat
);
751 CopyMemory(This
->mtype
.pbFormat
, type
->pbFormat
, type
->cbFormat
);
754 This
->mtype
.pbFormat
= NULL
;
759 static HRESULT WINAPI
760 SampleGrabber_ISampleGrabber_GetConnectedMediaType(ISampleGrabber
*iface
, AM_MEDIA_TYPE
*type
)
762 SG_Impl
*This
= impl_from_ISampleGrabber(iface
);
763 TRACE("(%p)->(%p)\n", This
, type
);
766 if (!This
->pin_in
.pair
)
767 return VFW_E_NOT_CONNECTED
;
769 if (type
->cbFormat
) {
770 type
->pbFormat
= CoTaskMemAlloc(type
->cbFormat
);
771 CopyMemory(type
->pbFormat
, This
->mtype
.pbFormat
, type
->cbFormat
);
777 static HRESULT WINAPI
778 SampleGrabber_ISampleGrabber_SetBufferSamples(ISampleGrabber
*iface
, BOOL bufferEm
)
780 TRACE("(%u)\n", bufferEm
);
782 FIXME("buffering not implemented\n");
789 static HRESULT WINAPI
790 SampleGrabber_ISampleGrabber_GetCurrentBuffer(ISampleGrabber
*iface
, LONG
*bufSize
, LONG
*buffer
)
792 FIXME("(%p, %p): stub\n", bufSize
, buffer
);
799 static HRESULT WINAPI
800 SampleGrabber_ISampleGrabber_GetCurrentSample(ISampleGrabber
*iface
, IMediaSample
**sample
)
802 /* MS doesn't implement it either, noone should call it */
803 WARN("(%p): not implemented\n", sample
);
808 static HRESULT WINAPI
809 SampleGrabber_ISampleGrabber_SetCallback(ISampleGrabber
*iface
, ISampleGrabberCB
*cb
, LONG whichMethod
)
811 SG_Impl
*This
= impl_from_ISampleGrabber(iface
);
812 TRACE("(%p)->(%p, %u)\n", This
, cb
, whichMethod
);
813 if (This
->grabberIface
)
814 ISampleGrabberCB_Release(This
->grabberIface
);
815 This
->grabberIface
= cb
;
816 This
->grabberMethod
= whichMethod
;
818 ISampleGrabberCB_AddRef(cb
);
823 /* SampleGrabber implementation of IMemInputPin interface */
826 static HRESULT WINAPI
827 SampleGrabber_IMemInputPin_QueryInterface(IMemInputPin
*iface
, REFIID riid
, void **ppvObject
)
829 return SampleGrabber_query(impl_from_IMemInputPin(iface
), riid
, ppvObject
);
834 SampleGrabber_IMemInputPin_AddRef(IMemInputPin
*iface
)
836 return SampleGrabber_addref(impl_from_IMemInputPin(iface
));
841 SampleGrabber_IMemInputPin_Release(IMemInputPin
*iface
)
843 return SampleGrabber_release(impl_from_IMemInputPin(iface
));
847 static HRESULT WINAPI
848 SampleGrabber_IMemInputPin_GetAllocator(IMemInputPin
*iface
, IMemAllocator
**allocator
)
850 SG_Impl
*This
= impl_from_IMemInputPin(iface
);
851 TRACE("(%p)->(%p) allocator = %p\n", This
, allocator
, This
->allocator
);
854 *allocator
= This
->allocator
;
856 return VFW_E_NO_ALLOCATOR
;
857 IMemAllocator_AddRef(*allocator
);
862 static HRESULT WINAPI
863 SampleGrabber_IMemInputPin_NotifyAllocator(IMemInputPin
*iface
, IMemAllocator
*allocator
, BOOL readOnly
)
865 SG_Impl
*This
= impl_from_IMemInputPin(iface
);
866 TRACE("(%p)->(%p, %u) allocator = %p\n", This
, allocator
, readOnly
, This
->allocator
);
867 if (This
->allocator
== allocator
)
870 IMemAllocator_Release(This
->allocator
);
871 This
->allocator
= allocator
;
873 IMemAllocator_AddRef(allocator
);
878 static HRESULT WINAPI
879 SampleGrabber_IMemInputPin_GetAllocatorRequirements(IMemInputPin
*iface
, ALLOCATOR_PROPERTIES
*props
)
881 SG_Impl
*This
= impl_from_IMemInputPin(iface
);
882 FIXME("(%p)->(%p): semi-stub\n", This
, props
);
885 return This
->memOutput
? IMemInputPin_GetAllocatorRequirements(This
->memOutput
, props
) : E_NOTIMPL
;
889 static HRESULT WINAPI
890 SampleGrabber_IMemInputPin_Receive(IMemInputPin
*iface
, IMediaSample
*sample
)
892 SG_Impl
*This
= impl_from_IMemInputPin(iface
);
894 TRACE("(%p)->(%p) output = %p, grabber = %p\n", This
, sample
, This
->memOutput
, This
->grabberIface
);
897 if ((This
->state
!= State_Running
) || (This
->oneShot
== OneShot_Past
))
899 if (This
->grabberIface
)
900 SampleGrabber_callback(This
, sample
);
901 hr
= This
->memOutput
? IMemInputPin_Receive(This
->memOutput
, sample
) : S_OK
;
902 if (This
->oneShot
== OneShot_Wait
) {
903 This
->oneShot
= OneShot_Past
;
905 if (This
->pin_out
.pair
)
906 IPin_EndOfStream(This
->pin_out
.pair
);
912 static HRESULT WINAPI
913 SampleGrabber_IMemInputPin_ReceiveMultiple(IMemInputPin
*iface
, IMediaSample
**samples
, LONG nSamples
, LONG
*nProcessed
)
915 SG_Impl
*This
= impl_from_IMemInputPin(iface
);
916 TRACE("(%p)->(%p, %u, %p) output = %p, grabber = %p\n", This
, samples
, nSamples
, nProcessed
, This
->memOutput
, This
->grabberIface
);
917 if (!samples
|| !nProcessed
)
919 if ((This
->state
!= State_Running
) || (This
->oneShot
== OneShot_Past
))
921 if (This
->grabberIface
) {
923 for (idx
= 0; idx
< nSamples
; idx
++)
924 SampleGrabber_callback(This
, samples
[idx
]);
926 return This
->memOutput
? IMemInputPin_ReceiveMultiple(This
->memOutput
, samples
, nSamples
, nProcessed
) : S_OK
;
930 static HRESULT WINAPI
931 SampleGrabber_IMemInputPin_ReceiveCanBlock(IMemInputPin
*iface
)
933 SG_Impl
*This
= impl_from_IMemInputPin(iface
);
934 TRACE("(%p)\n", This
);
935 return This
->memOutput
? IMemInputPin_ReceiveCanBlock(This
->memOutput
) : S_OK
;
939 /* SampleGrabber member pin implementation */
943 SampleGrabber_IPin_AddRef(IPin
*iface
)
945 return SampleGrabber_addref(((SG_Pin
*)iface
)->sg
);
950 SampleGrabber_IPin_Release(IPin
*iface
)
952 return SampleGrabber_release(((SG_Pin
*)iface
)->sg
);
956 static HRESULT WINAPI
957 SampleGrabber_IPin_QueryInterface(IPin
*iface
, REFIID riid
, void **ppvObject
)
959 SG_Pin
*This
= (SG_Pin
*)iface
;
960 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), ppvObject
);
962 if (IsEqualIID(riid
, &IID_IUnknown
) ||
963 IsEqualIID(riid
, &IID_IPin
)) {
964 SampleGrabber_addref(This
->sg
);
968 else if (IsEqualIID(riid
, &IID_IMemInputPin
)) {
969 SampleGrabber_addref(This
->sg
);
970 *ppvObject
= &(This
->sg
->IMemInputPin_Vtbl
);
974 WARN("(%p, %s,%p): not found\n", This
, debugstr_guid(riid
), ppvObject
);
975 return E_NOINTERFACE
;
978 /* IPin - input pin */
979 static HRESULT WINAPI
980 SampleGrabber_In_IPin_Connect(IPin
*iface
, IPin
*receiver
, const AM_MEDIA_TYPE
*mtype
)
982 WARN("(%p, %p): unexpected\n", receiver
, mtype
);
986 /* IPin - output pin */
987 static HRESULT WINAPI
988 SampleGrabber_Out_IPin_Connect(IPin
*iface
, IPin
*receiver
, const AM_MEDIA_TYPE
*type
)
990 SG_Pin
*This
= (SG_Pin
*)iface
;
992 TRACE("(%p)->(%p, %p)\n", This
, receiver
, type
);
996 return VFW_E_ALREADY_CONNECTED
;
997 if (This
->sg
->state
!= State_Stopped
)
998 return VFW_E_NOT_STOPPED
;
1000 TRACE("Media type: %s/%s ssize: %u format: %s (%u bytes)\n",
1001 debugstr_guid(&type
->majortype
), debugstr_guid(&type
->subtype
),
1003 debugstr_guid(&type
->formattype
), type
->cbFormat
);
1004 if (!IsEqualGUID(&This
->sg
->mtype
.majortype
,&GUID_NULL
) &&
1005 !IsEqualGUID(&This
->sg
->mtype
.majortype
,&type
->majortype
))
1006 return VFW_E_TYPE_NOT_ACCEPTED
;
1007 if (!IsEqualGUID(&This
->sg
->mtype
.subtype
,&MEDIASUBTYPE_None
) &&
1008 !IsEqualGUID(&This
->sg
->mtype
.subtype
,&type
->subtype
))
1009 return VFW_E_TYPE_NOT_ACCEPTED
;
1010 if (!IsEqualGUID(&This
->sg
->mtype
.formattype
,&GUID_NULL
) &&
1011 !IsEqualGUID(&This
->sg
->mtype
.formattype
,&FORMAT_None
) &&
1012 !IsEqualGUID(&This
->sg
->mtype
.formattype
,&type
->formattype
))
1013 return VFW_E_TYPE_NOT_ACCEPTED
;
1016 type
= &This
->sg
->mtype
;
1017 if (!IsEqualGUID(&type
->formattype
, &FORMAT_None
) &&
1018 !IsEqualGUID(&type
->formattype
, &GUID_NULL
) &&
1020 return VFW_E_TYPE_NOT_ACCEPTED
;
1021 hr
= IPin_ReceiveConnection(receiver
,(IPin
*)&This
->lpVtbl
,type
);
1024 This
->pair
= receiver
;
1025 if (This
->sg
->memOutput
) {
1026 IMemInputPin_Release(This
->sg
->memOutput
);
1027 This
->sg
->memOutput
= NULL
;
1029 IPin_QueryInterface(receiver
,&IID_IMemInputPin
,(void **)&(This
->sg
->memOutput
));
1030 TRACE("(%p) Accepted IPin %p, IMemInputPin %p\n", This
, receiver
, This
->sg
->memOutput
);
1034 /* IPin - input pin */
1035 static HRESULT WINAPI
1036 SampleGrabber_In_IPin_ReceiveConnection(IPin
*iface
, IPin
*connector
, const AM_MEDIA_TYPE
*type
)
1038 SG_Pin
*This
= (SG_Pin
*)iface
;
1039 TRACE("(%p)->(%p, %p)\n", This
, connector
, type
);
1043 return VFW_E_ALREADY_CONNECTED
;
1044 if (This
->sg
->state
!= State_Stopped
)
1045 return VFW_E_NOT_STOPPED
;
1047 TRACE("Media type: %s/%s ssize: %u format: %s (%u bytes)\n",
1048 debugstr_guid(&type
->majortype
), debugstr_guid(&type
->subtype
),
1050 debugstr_guid(&type
->formattype
), type
->cbFormat
);
1051 if (!IsEqualGUID(&This
->sg
->mtype
.majortype
,&GUID_NULL
) &&
1052 !IsEqualGUID(&This
->sg
->mtype
.majortype
,&type
->majortype
))
1053 return VFW_E_TYPE_NOT_ACCEPTED
;
1054 if (!IsEqualGUID(&This
->sg
->mtype
.subtype
,&MEDIASUBTYPE_None
) &&
1055 !IsEqualGUID(&This
->sg
->mtype
.subtype
,&type
->subtype
))
1056 return VFW_E_TYPE_NOT_ACCEPTED
;
1057 if (!IsEqualGUID(&This
->sg
->mtype
.formattype
,&GUID_NULL
) &&
1058 !IsEqualGUID(&This
->sg
->mtype
.formattype
,&FORMAT_None
) &&
1059 !IsEqualGUID(&This
->sg
->mtype
.formattype
,&type
->formattype
))
1060 return VFW_E_TYPE_NOT_ACCEPTED
;
1061 if (!IsEqualGUID(&type
->formattype
, &FORMAT_None
) &&
1062 !IsEqualGUID(&type
->formattype
, &GUID_NULL
) &&
1064 return VFW_E_TYPE_NOT_ACCEPTED
;
1065 if (This
->sg
->mtype
.pbFormat
)
1066 CoTaskMemFree(This
->sg
->mtype
.pbFormat
);
1067 This
->sg
->mtype
= *type
;
1068 This
->sg
->mtype
.pUnk
= NULL
;
1069 if (type
->cbFormat
) {
1070 This
->sg
->mtype
.pbFormat
= CoTaskMemAlloc(type
->cbFormat
);
1071 CopyMemory(This
->sg
->mtype
.pbFormat
, type
->pbFormat
, type
->cbFormat
);
1074 This
->sg
->mtype
.pbFormat
= NULL
;
1076 This
->pair
= connector
;
1077 TRACE("(%p) Accepted IPin %p\n", This
, connector
);
1081 /* IPin - output pin */
1082 static HRESULT WINAPI
1083 SampleGrabber_Out_IPin_ReceiveConnection(IPin
*iface
, IPin
*connector
, const AM_MEDIA_TYPE
*mtype
)
1085 WARN("(%p, %p): unexpected\n", connector
, mtype
);
1086 return E_UNEXPECTED
;
1089 /* IPin - input pin */
1090 static HRESULT WINAPI
1091 SampleGrabber_In_IPin_Disconnect(IPin
*iface
)
1093 SG_Pin
*This
= (SG_Pin
*)iface
;
1094 TRACE("(%p)->() pair = %p\n", This
, This
->pair
);
1095 if (This
->sg
->state
!= State_Stopped
)
1096 return VFW_E_NOT_STOPPED
;
1104 /* IPin - output pin */
1105 static HRESULT WINAPI
1106 SampleGrabber_Out_IPin_Disconnect(IPin
*iface
)
1108 SG_Pin
*This
= (SG_Pin
*)iface
;
1109 TRACE("(%p)->() pair = %p\n", This
, This
->pair
);
1110 if (This
->sg
->state
!= State_Stopped
)
1111 return VFW_E_NOT_STOPPED
;
1114 if (This
->sg
->memOutput
) {
1115 IMemInputPin_Release(This
->sg
->memOutput
);
1116 This
->sg
->memOutput
= NULL
;
1124 static HRESULT WINAPI
1125 SampleGrabber_IPin_ConnectedTo(IPin
*iface
, IPin
**pin
)
1127 SG_Pin
*This
= (SG_Pin
*)iface
;
1128 TRACE("(%p)->(%p) pair = %p\n", This
, pin
, This
->pair
);
1136 return VFW_E_NOT_CONNECTED
;
1140 static HRESULT WINAPI
1141 SampleGrabber_IPin_ConnectionMediaType(IPin
*iface
, AM_MEDIA_TYPE
*mtype
)
1143 SG_Pin
*This
= (SG_Pin
*)iface
;
1144 TRACE("(%p)->(%p)\n", This
, mtype
);
1148 return VFW_E_NOT_CONNECTED
;
1149 *mtype
= This
->sg
->mtype
;
1150 if (mtype
->cbFormat
) {
1151 mtype
->pbFormat
= CoTaskMemAlloc(mtype
->cbFormat
);
1152 CopyMemory(mtype
->pbFormat
, This
->sg
->mtype
.pbFormat
, mtype
->cbFormat
);
1158 static HRESULT WINAPI
1159 SampleGrabber_IPin_QueryPinInfo(IPin
*iface
, PIN_INFO
*info
)
1161 SG_Pin
*This
= (SG_Pin
*)iface
;
1162 TRACE("(%p)->(%p)\n", This
, info
);
1165 SampleGrabber_addref(This
->sg
);
1166 info
->pFilter
= (IBaseFilter
*)This
->sg
;
1167 info
->dir
= This
->dir
;
1168 lstrcpynW(info
->achName
,This
->name
,MAX_PIN_NAME
);
1173 static HRESULT WINAPI
1174 SampleGrabber_IPin_QueryDirection(IPin
*iface
, PIN_DIRECTION
*dir
)
1176 SG_Pin
*This
= (SG_Pin
*)iface
;
1177 TRACE("(%p)->(%p)\n", This
, dir
);
1185 static HRESULT WINAPI
1186 SampleGrabber_IPin_QueryId(IPin
*iface
, LPWSTR
*id
)
1188 SG_Pin
*This
= (SG_Pin
*)iface
;
1190 TRACE("(%p)->(%p)\n", This
, id
);
1193 len
= sizeof(WCHAR
)*(1+lstrlenW(This
->name
));
1194 *id
= CoTaskMemAlloc(len
);
1195 CopyMemory(*id
, This
->name
, len
);
1200 static HRESULT WINAPI
1201 SampleGrabber_IPin_QueryAccept(IPin
*iface
, const AM_MEDIA_TYPE
*mtype
)
1203 TRACE("(%p)\n", mtype
);
1208 static HRESULT WINAPI
1209 SampleGrabber_IPin_EnumMediaTypes(IPin
*iface
, IEnumMediaTypes
**mtypes
)
1211 SG_Pin
*This
= (SG_Pin
*)iface
;
1212 TRACE("(%p)->(%p)\n", This
, mtypes
);
1215 *mtypes
= mediaenum_create(&This
->sg
->mtype
);
1216 return *mtypes
? S_OK
: E_OUTOFMEMORY
;
1219 /* IPin - input pin */
1220 static HRESULT WINAPI
1221 SampleGrabber_In_IPin_QueryInternalConnections(IPin
*iface
, IPin
**pins
, ULONG
*nPins
)
1223 SG_Pin
*This
= (SG_Pin
*)iface
;
1224 TRACE("(%p)->(%p, %p) size = %u\n", This
, pins
, nPins
, (nPins
? *nPins
: 0));
1230 IPin_AddRef((IPin
*)&This
->sg
->pin_out
.lpVtbl
);
1231 *pins
= (IPin
*)&This
->sg
->pin_out
.lpVtbl
;
1239 /* IPin - output pin */
1240 static HRESULT WINAPI
1241 SampleGrabber_Out_IPin_QueryInternalConnections(IPin
*iface
, IPin
**pins
, ULONG
*nPins
)
1243 WARN("(%p, %p): unexpected\n", pins
, nPins
);
1250 static HRESULT WINAPI
1251 SampleGrabber_IPin_EndOfStream(IPin
*iface
)
1258 static HRESULT WINAPI
1259 SampleGrabber_IPin_BeginFlush(IPin
*iface
)
1266 static HRESULT WINAPI
1267 SampleGrabber_IPin_EndFlush(IPin
*iface
)
1274 static HRESULT WINAPI
1275 SampleGrabber_IPin_NewSegment(IPin
*iface
, REFERENCE_TIME tStart
, REFERENCE_TIME tStop
, double rate
)
1282 /* SampleGrabber vtables and constructor */
1284 static const IBaseFilterVtbl IBaseFilter_VTable
=
1286 SampleGrabber_IBaseFilter_QueryInterface
,
1287 SampleGrabber_IBaseFilter_AddRef
,
1288 SampleGrabber_IBaseFilter_Release
,
1289 SampleGrabber_IBaseFilter_GetClassID
,
1290 SampleGrabber_IBaseFilter_Stop
,
1291 SampleGrabber_IBaseFilter_Pause
,
1292 SampleGrabber_IBaseFilter_Run
,
1293 SampleGrabber_IBaseFilter_GetState
,
1294 SampleGrabber_IBaseFilter_SetSyncSource
,
1295 SampleGrabber_IBaseFilter_GetSyncSource
,
1296 SampleGrabber_IBaseFilter_EnumPins
,
1297 SampleGrabber_IBaseFilter_FindPin
,
1298 SampleGrabber_IBaseFilter_QueryFilterInfo
,
1299 SampleGrabber_IBaseFilter_JoinFilterGraph
,
1300 SampleGrabber_IBaseFilter_QueryVendorInfo
,
1303 static const ISampleGrabberVtbl ISampleGrabber_VTable
=
1305 SampleGrabber_ISampleGrabber_QueryInterface
,
1306 SampleGrabber_ISampleGrabber_AddRef
,
1307 SampleGrabber_ISampleGrabber_Release
,
1308 SampleGrabber_ISampleGrabber_SetOneShot
,
1309 SampleGrabber_ISampleGrabber_SetMediaType
,
1310 SampleGrabber_ISampleGrabber_GetConnectedMediaType
,
1311 SampleGrabber_ISampleGrabber_SetBufferSamples
,
1312 SampleGrabber_ISampleGrabber_GetCurrentBuffer
,
1313 SampleGrabber_ISampleGrabber_GetCurrentSample
,
1314 SampleGrabber_ISampleGrabber_SetCallback
,
1317 static const IMemInputPinVtbl IMemInputPin_VTable
=
1319 SampleGrabber_IMemInputPin_QueryInterface
,
1320 SampleGrabber_IMemInputPin_AddRef
,
1321 SampleGrabber_IMemInputPin_Release
,
1322 SampleGrabber_IMemInputPin_GetAllocator
,
1323 SampleGrabber_IMemInputPin_NotifyAllocator
,
1324 SampleGrabber_IMemInputPin_GetAllocatorRequirements
,
1325 SampleGrabber_IMemInputPin_Receive
,
1326 SampleGrabber_IMemInputPin_ReceiveMultiple
,
1327 SampleGrabber_IMemInputPin_ReceiveCanBlock
,
1330 static const IPinVtbl IPin_In_VTable
=
1332 SampleGrabber_IPin_QueryInterface
,
1333 SampleGrabber_IPin_AddRef
,
1334 SampleGrabber_IPin_Release
,
1335 SampleGrabber_In_IPin_Connect
,
1336 SampleGrabber_In_IPin_ReceiveConnection
,
1337 SampleGrabber_In_IPin_Disconnect
,
1338 SampleGrabber_IPin_ConnectedTo
,
1339 SampleGrabber_IPin_ConnectionMediaType
,
1340 SampleGrabber_IPin_QueryPinInfo
,
1341 SampleGrabber_IPin_QueryDirection
,
1342 SampleGrabber_IPin_QueryId
,
1343 SampleGrabber_IPin_QueryAccept
,
1344 SampleGrabber_IPin_EnumMediaTypes
,
1345 SampleGrabber_In_IPin_QueryInternalConnections
,
1346 SampleGrabber_IPin_EndOfStream
,
1347 SampleGrabber_IPin_BeginFlush
,
1348 SampleGrabber_IPin_EndFlush
,
1349 SampleGrabber_IPin_NewSegment
,
1352 static const IPinVtbl IPin_Out_VTable
=
1354 SampleGrabber_IPin_QueryInterface
,
1355 SampleGrabber_IPin_AddRef
,
1356 SampleGrabber_IPin_Release
,
1357 SampleGrabber_Out_IPin_Connect
,
1358 SampleGrabber_Out_IPin_ReceiveConnection
,
1359 SampleGrabber_Out_IPin_Disconnect
,
1360 SampleGrabber_IPin_ConnectedTo
,
1361 SampleGrabber_IPin_ConnectionMediaType
,
1362 SampleGrabber_IPin_QueryPinInfo
,
1363 SampleGrabber_IPin_QueryDirection
,
1364 SampleGrabber_IPin_QueryId
,
1365 SampleGrabber_IPin_QueryAccept
,
1366 SampleGrabber_IPin_EnumMediaTypes
,
1367 SampleGrabber_Out_IPin_QueryInternalConnections
,
1368 SampleGrabber_IPin_EndOfStream
,
1369 SampleGrabber_IPin_BeginFlush
,
1370 SampleGrabber_IPin_EndFlush
,
1371 SampleGrabber_IPin_NewSegment
,
1374 HRESULT
SampleGrabber_create(IUnknown
*pUnkOuter
, LPVOID
*ppv
)
1376 SG_Impl
* obj
= NULL
;
1378 TRACE("(%p,%p)\n", ppv
, pUnkOuter
);
1381 return CLASS_E_NOAGGREGATION
;
1383 obj
= CoTaskMemAlloc(sizeof(SG_Impl
));
1386 return E_OUTOFMEMORY
;
1388 ZeroMemory(obj
, sizeof(SG_Impl
));
1391 obj
->IBaseFilter_Vtbl
= &IBaseFilter_VTable
;
1392 obj
->ISampleGrabber_Vtbl
= &ISampleGrabber_VTable
;
1393 obj
->IMemInputPin_Vtbl
= &IMemInputPin_VTable
;
1394 obj
->pin_in
.lpVtbl
= &IPin_In_VTable
;
1395 obj
->pin_in
.dir
= PINDIR_INPUT
;
1396 obj
->pin_in
.name
= pin_in_name
;
1397 obj
->pin_in
.sg
= obj
;
1398 obj
->pin_in
.pair
= NULL
;
1399 obj
->pin_out
.lpVtbl
= &IPin_Out_VTable
;
1400 obj
->pin_out
.dir
= PINDIR_OUTPUT
;
1401 obj
->pin_out
.name
= pin_out_name
;
1402 obj
->pin_out
.sg
= obj
;
1403 obj
->pin_out
.pair
= NULL
;
1404 obj
->info
.achName
[0] = 0;
1405 obj
->info
.pGraph
= NULL
;
1406 obj
->state
= State_Stopped
;
1407 obj
->mtype
.majortype
= GUID_NULL
;
1408 obj
->mtype
.subtype
= MEDIASUBTYPE_None
;
1409 obj
->mtype
.formattype
= FORMAT_None
;
1410 obj
->allocator
= NULL
;
1411 obj
->refClock
= NULL
;
1412 obj
->memOutput
= NULL
;
1413 obj
->grabberIface
= NULL
;
1414 obj
->grabberMethod
= -1;
1415 obj
->oneShot
= OneShot_None
;