1 /* Capture Graph Builder, Minimal edition
3 * Copyright 2005 Maarten Lankhorst
4 * Copyright 2005 Rolf Kalbermatter
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21 #include "qcap_private.h"
23 WINE_DEFAULT_DEBUG_CHANNEL(qcap
);
25 /***********************************************************************
26 * ICaptureGraphBuilder & ICaptureGraphBuilder2 implementation
28 typedef struct CaptureGraphImpl
30 ICaptureGraphBuilder2 ICaptureGraphBuilder2_iface
;
31 ICaptureGraphBuilder ICaptureGraphBuilder_iface
;
33 IGraphBuilder
*mygraph
;
34 CRITICAL_SECTION csFilter
;
37 static const ICaptureGraphBuilderVtbl builder_Vtbl
;
38 static const ICaptureGraphBuilder2Vtbl builder2_Vtbl
;
40 static inline CaptureGraphImpl
*impl_from_ICaptureGraphBuilder(ICaptureGraphBuilder
*iface
)
42 return CONTAINING_RECORD(iface
, CaptureGraphImpl
, ICaptureGraphBuilder_iface
);
45 static inline CaptureGraphImpl
*impl_from_ICaptureGraphBuilder2(ICaptureGraphBuilder2
*iface
)
47 return CONTAINING_RECORD(iface
, CaptureGraphImpl
, ICaptureGraphBuilder2_iface
);
51 HRESULT
capture_graph_create(IUnknown
*outer
, IUnknown
**out
)
53 CaptureGraphImpl
*object
;
56 return CLASS_E_NOAGGREGATION
;
58 if (!(object
= CoTaskMemAlloc(sizeof(*object
))))
61 object
->ICaptureGraphBuilder2_iface
.lpVtbl
= &builder2_Vtbl
;
62 object
->ICaptureGraphBuilder_iface
.lpVtbl
= &builder_Vtbl
;
64 object
->mygraph
= NULL
;
65 InitializeCriticalSection(&object
->csFilter
);
66 object
->csFilter
.DebugInfo
->Spare
[0] = (DWORD_PTR
)(__FILE__
": CaptureGraphImpl.csFilter");
68 TRACE("Created capture graph builder %p.\n", object
);
70 *out
= (IUnknown
*)&object
->ICaptureGraphBuilder_iface
;
75 fnCaptureGraphBuilder2_QueryInterface(ICaptureGraphBuilder2
* iface
,
79 CaptureGraphImpl
*This
= impl_from_ICaptureGraphBuilder2(iface
);
81 TRACE("(%p/%p)->(%s, %p)\n", This
, iface
, debugstr_guid(riid
), ppv
);
84 if (IsEqualIID(riid
, &IID_IUnknown
))
85 *ppv
= &This
->ICaptureGraphBuilder2_iface
;
86 else if (IsEqualIID(riid
, &IID_ICaptureGraphBuilder
))
87 *ppv
= &This
->ICaptureGraphBuilder_iface
;
88 else if (IsEqualIID(riid
, &IID_ICaptureGraphBuilder2
))
89 *ppv
= &This
->ICaptureGraphBuilder2_iface
;
93 IUnknown_AddRef((IUnknown
*)(*ppv
));
94 TRACE ("-- Interface = %p\n", *ppv
);
98 TRACE ("-- Interface: E_NOINTERFACE\n");
103 fnCaptureGraphBuilder2_AddRef(ICaptureGraphBuilder2
* iface
)
105 CaptureGraphImpl
*This
= impl_from_ICaptureGraphBuilder2(iface
);
106 DWORD ref
= InterlockedIncrement(&This
->ref
);
108 TRACE("(%p/%p)->() AddRef from %d\n", This
, iface
, ref
- 1);
112 static ULONG WINAPI
fnCaptureGraphBuilder2_Release(ICaptureGraphBuilder2
* iface
)
114 CaptureGraphImpl
*This
= impl_from_ICaptureGraphBuilder2(iface
);
115 DWORD ref
= InterlockedDecrement(&This
->ref
);
117 TRACE("(%p/%p)->() Release from %d\n", This
, iface
, ref
+ 1);
121 This
->csFilter
.DebugInfo
->Spare
[0] = 0;
122 DeleteCriticalSection(&This
->csFilter
);
124 IGraphBuilder_Release(This
->mygraph
);
126 ObjectRefCount(FALSE
);
131 static HRESULT WINAPI
132 fnCaptureGraphBuilder2_SetFilterGraph(ICaptureGraphBuilder2
* iface
,
135 /* The graph builder will automatically create a filter graph if you don't call
136 this method. If you call this method after the graph builder has created its
137 own filter graph, the call will fail. */
139 CaptureGraphImpl
*This
= impl_from_ICaptureGraphBuilder2(iface
);
141 TRACE("(%p/%p)->(%p)\n", This
, iface
, pfg
);
150 IGraphBuilder_AddRef(This
->mygraph
);
151 if (SUCCEEDED(IGraphBuilder_QueryInterface(This
->mygraph
,
152 &IID_IMediaEvent
, (LPVOID
*)&pmev
)))
154 IMediaEvent_CancelDefaultHandling(pmev
, EC_REPAINT
);
155 IMediaEvent_Release(pmev
);
160 static HRESULT WINAPI
161 fnCaptureGraphBuilder2_GetFilterGraph(ICaptureGraphBuilder2
* iface
,
164 CaptureGraphImpl
*This
= impl_from_ICaptureGraphBuilder2(iface
);
166 TRACE("(%p/%p)->(%p)\n", This
, iface
, pfg
);
171 *pfg
= This
->mygraph
;
174 TRACE("(%p) Getting NULL filtergraph\n", iface
);
178 IGraphBuilder_AddRef(This
->mygraph
);
180 TRACE("(%p) return filtergraph %p\n", iface
, *pfg
);
184 static HRESULT WINAPI
185 fnCaptureGraphBuilder2_SetOutputFileName(ICaptureGraphBuilder2
* iface
,
189 IFileSinkFilter
**ppSink
)
191 CaptureGraphImpl
*This
= impl_from_ICaptureGraphBuilder2(iface
);
193 FIXME("(%p/%p)->(%s, %s, %p, %p) Stub!\n", This
, iface
,
194 debugstr_guid(pType
), debugstr_w(lpstrFile
), ppf
, ppSink
);
199 static BOOL
pin_has_majortype(IPin
*pin
, const GUID
*majortype
)
201 IEnumMediaTypes
*enummt
;
204 if (FAILED(IPin_EnumMediaTypes(pin
, &enummt
)))
207 while (IEnumMediaTypes_Next(enummt
, 1, &mt
, NULL
) == S_OK
)
209 if (IsEqualGUID(&mt
->majortype
, majortype
))
212 IEnumMediaTypes_Release(enummt
);
217 IEnumMediaTypes_Release(enummt
);
221 static BOOL
pin_matches(IPin
*pin
, PIN_DIRECTION dir
, const GUID
*category
,
222 const GUID
*majortype
, BOOL unconnected
)
224 PIN_DIRECTION candidate_dir
;
228 if (FAILED(hr
= IPin_QueryDirection(pin
, &candidate_dir
)))
229 ERR("Failed to query direction, hr %#x.\n", hr
);
231 if (dir
!= candidate_dir
)
234 if (unconnected
&& IPin_ConnectedTo(pin
, &peer
) == S_OK
&& peer
)
246 if (FAILED(IPin_QueryInterface(pin
, &IID_IKsPropertySet
, (void **)&set
)))
249 hr
= IKsPropertySet_Get(set
, &ROPSETID_Pin
, AMPROPERTY_PIN_CATEGORY
,
250 NULL
, 0, &property
, sizeof(property
), &size
);
251 IKsPropertySet_Release(set
);
252 if (FAILED(hr
) || !IsEqualGUID(&property
, category
))
256 if (majortype
&& !pin_has_majortype(pin
, majortype
))
262 static HRESULT
find_interface_recurse(PIN_DIRECTION dir
, const GUID
*category
,
263 const GUID
*majortype
, IBaseFilter
*filter
, REFIID iid
, void **out
)
265 BOOL found_category
= FALSE
;
271 TRACE("Looking for %s pins, category %s, majortype %s from filter %p.\n",
272 dir
== PINDIR_INPUT
? "sink" : "source", debugstr_guid(category
),
273 debugstr_guid(majortype
), filter
);
275 if (FAILED(hr
= IBaseFilter_EnumPins(filter
, &enumpins
)))
277 ERR("Failed to enumerate pins, hr %#x.\n", hr
);
281 while (IEnumPins_Next(enumpins
, 1, &pin
, NULL
) == S_OK
)
283 if (!pin_matches(pin
, dir
, category
, majortype
, FALSE
))
290 found_category
= TRUE
;
292 if (IPin_QueryInterface(pin
, iid
, out
) == S_OK
)
295 IEnumPins_Release(enumpins
);
299 hr
= IPin_ConnectedTo(pin
, &peer
);
303 if (IPin_QueryInterface(peer
, iid
, out
) == S_OK
)
306 IEnumPins_Release(enumpins
);
310 IPin_QueryPinInfo(peer
, &info
);
313 if (IBaseFilter_QueryInterface(info
.pFilter
, iid
, out
) == S_OK
)
315 IBaseFilter_Release(info
.pFilter
);
316 IEnumPins_Release(enumpins
);
320 hr
= find_interface_recurse(dir
, NULL
, NULL
, info
.pFilter
, iid
, out
);
321 IBaseFilter_Release(info
.pFilter
);
324 IEnumPins_Release(enumpins
);
329 IEnumPins_Release(enumpins
);
331 if (category
&& !found_category
)
332 return E_NOINTERFACE
;
337 static HRESULT WINAPI
fnCaptureGraphBuilder2_FindInterface(ICaptureGraphBuilder2
*iface
,
338 const GUID
*category
, const GUID
*majortype
, IBaseFilter
*filter
, REFIID iid
, void **out
)
340 CaptureGraphImpl
*graph
= impl_from_ICaptureGraphBuilder2(iface
);
343 TRACE("graph %p, category %s, majortype %s, filter %p, iid %s, out %p.\n",
344 graph
, debugstr_guid(category
), debugstr_guid(majortype
), filter
, debugstr_guid(iid
), out
);
349 if (category
&& IsEqualGUID(category
, &LOOK_DOWNSTREAM_ONLY
))
350 return find_interface_recurse(PINDIR_OUTPUT
, NULL
, NULL
, filter
, iid
, out
);
352 if (category
&& IsEqualGUID(category
, &LOOK_UPSTREAM_ONLY
))
353 return find_interface_recurse(PINDIR_INPUT
, NULL
, NULL
, filter
, iid
, out
);
355 if (IBaseFilter_QueryInterface(filter
, iid
, out
) == S_OK
)
361 hr
= find_interface_recurse(PINDIR_OUTPUT
, category
, majortype
, filter
, iid
, out
);
362 if (hr
== S_OK
|| hr
== E_NOINTERFACE
)
365 return find_interface_recurse(PINDIR_INPUT
, NULL
, NULL
, filter
, iid
, out
);
368 static HRESULT
match_smart_tee_pin(CaptureGraphImpl
*This
,
369 const GUID
*pCategory
,
374 static const WCHAR inputW
[] = {'I','n','p','u','t',0};
375 static const WCHAR captureW
[] = {'C','a','p','t','u','r','e',0};
376 static const WCHAR previewW
[] = {'P','r','e','v','i','e','w',0};
377 IPin
*capture
= NULL
;
378 IPin
*preview
= NULL
;
380 IBaseFilter
*smartTee
= NULL
;
381 BOOL needSmartTee
= FALSE
;
384 TRACE("(%p, %s, %s, %p, %p)\n", This
, debugstr_guid(pCategory
), debugstr_guid(pType
), pSource
, source_out
);
385 hr
= ICaptureGraphBuilder2_FindPin(&This
->ICaptureGraphBuilder2_iface
, pSource
,
386 PINDIR_OUTPUT
, &PIN_CATEGORY_CAPTURE
, pType
, FALSE
, 0, &capture
);
388 hr
= ICaptureGraphBuilder2_FindPin(&This
->ICaptureGraphBuilder2_iface
, pSource
,
389 PINDIR_OUTPUT
, &PIN_CATEGORY_PREVIEW
, pType
, FALSE
, 0, &preview
);
397 if (IsEqualIID(pCategory
, &PIN_CATEGORY_CAPTURE
)) {
398 hr
= IPin_ConnectedTo(capture
, &peer
);
399 if (hr
== VFW_E_NOT_CONNECTED
) {
400 *source_out
= capture
;
401 IPin_AddRef(*source_out
);
406 hr
= IPin_ConnectedTo(preview
, &peer
);
407 if (hr
== VFW_E_NOT_CONNECTED
) {
408 *source_out
= preview
;
409 IPin_AddRef(*source_out
);
416 hr
= IPin_ConnectedTo(capture
, &peer
);
420 hr
= IPin_QueryPinInfo(peer
, &pinInfo
);
422 hr
= IBaseFilter_GetClassID(pinInfo
.pFilter
, &classID
);
424 if (IsEqualIID(&classID
, &CLSID_SmartTee
)) {
425 smartTee
= pinInfo
.pFilter
;
426 IBaseFilter_AddRef(smartTee
);
429 IBaseFilter_Release(pinInfo
.pFilter
);
435 } else if (hr
== VFW_E_NOT_CONNECTED
) {
436 hr
= CoCreateInstance(&CLSID_SmartTee
, NULL
, CLSCTX_INPROC_SERVER
,
437 &IID_IBaseFilter
, (LPVOID
*)&smartTee
);
439 hr
= IGraphBuilder_AddFilter(This
->mygraph
, smartTee
, NULL
);
441 IPin
*smartTeeInput
= NULL
;
442 hr
= IBaseFilter_FindPin(smartTee
, inputW
, &smartTeeInput
);
444 hr
= IGraphBuilder_ConnectDirect(This
->mygraph
, capture
, smartTeeInput
, NULL
);
445 IPin_Release(smartTeeInput
);
450 TRACE("adding SmartTee failed with hr=0x%08x\n", hr
);
458 if (IsEqualIID(pCategory
, &PIN_CATEGORY_CAPTURE
))
459 hr
= IBaseFilter_FindPin(smartTee
, captureW
, source_out
);
461 hr
= IBaseFilter_FindPin(smartTee
, previewW
, source_out
);
463 hr
= VFW_S_NOPREVIEWPIN
;
468 IPin_Release(capture
);
470 IPin_Release(preview
);
474 IBaseFilter_Release(smartTee
);
475 TRACE("for %s returning hr=0x%08x, *source_out=%p\n", IsEqualIID(pCategory
, &PIN_CATEGORY_CAPTURE
) ? "capture" : "preview", hr
, source_out
? *source_out
: 0);
479 static HRESULT
find_unconnected_source_from_filter(CaptureGraphImpl
*capture_graph
,
480 const GUID
*category
, const GUID
*majortype
, IBaseFilter
*filter
, IPin
**ret
);
482 static HRESULT
find_unconnected_source_from_pin(CaptureGraphImpl
*capture_graph
,
483 const GUID
*category
, const GUID
*majortype
, IPin
*pin
, IPin
**ret
)
490 IPin_QueryDirection(pin
, &dir
);
491 if (dir
!= PINDIR_OUTPUT
)
492 return VFW_E_INVALID_DIRECTION
;
494 if (category
&& (IsEqualGUID(category
, &PIN_CATEGORY_CAPTURE
)
495 || IsEqualGUID(category
, &PIN_CATEGORY_PREVIEW
)))
497 if (FAILED(hr
= match_smart_tee_pin(capture_graph
, category
, majortype
, (IUnknown
*)pin
, &pin
)))
500 if (FAILED(IPin_ConnectedTo(pin
, &peer
)))
508 if (FAILED(IPin_ConnectedTo(pin
, &peer
)))
510 if (!pin_matches(pin
, PINDIR_OUTPUT
, category
, majortype
, FALSE
))
513 IPin_AddRef(*ret
= pin
);
519 IPin_QueryPinInfo(peer
, &info
);
520 hr
= find_unconnected_source_from_filter(capture_graph
, category
, majortype
, info
.pFilter
, ret
);
521 IBaseFilter_Release(info
.pFilter
);
527 static HRESULT
find_unconnected_source_from_filter(CaptureGraphImpl
*capture_graph
,
528 const GUID
*category
, const GUID
*majortype
, IBaseFilter
*filter
, IPin
**ret
)
534 if (category
&& (IsEqualGUID(category
, &PIN_CATEGORY_CAPTURE
)
535 || IsEqualGUID(category
, &PIN_CATEGORY_PREVIEW
)))
537 if (FAILED(hr
= match_smart_tee_pin(capture_graph
, category
, majortype
, (IUnknown
*)filter
, &pin
)))
540 if (FAILED(IPin_ConnectedTo(pin
, &peer
)))
551 if (FAILED(hr
= IBaseFilter_EnumPins(filter
, &enumpins
)))
554 while (IEnumPins_Next(enumpins
, 1, &pin
, NULL
) == S_OK
)
556 if (SUCCEEDED(hr
= find_unconnected_source_from_pin(capture_graph
, category
, majortype
, pin
, ret
)))
558 IEnumPins_Release(enumpins
);
564 IEnumPins_Release(enumpins
);
569 static HRESULT WINAPI
fnCaptureGraphBuilder2_RenderStream(ICaptureGraphBuilder2
*iface
,
570 const GUID
*category
, const GUID
*majortype
, IUnknown
*source
,
571 IBaseFilter
*pfCompressor
, IBaseFilter
*pfRenderer
)
573 CaptureGraphImpl
*This
= impl_from_ICaptureGraphBuilder2(iface
);
574 IPin
*source_out
= NULL
, *renderer_in
;
575 BOOL rendererNeedsRelease
= FALSE
;
576 HRESULT hr
, return_hr
= S_OK
;
580 TRACE("graph %p, category %s, majortype %s, source %p, intermediate %p, sink %p.\n",
581 This
, debugstr_guid(category
), debugstr_guid(majortype
), source
, pfCompressor
, pfRenderer
);
585 FIXME("Need a capture graph\n");
589 if (category
&& IsEqualGUID(category
, &PIN_CATEGORY_VBI
))
591 FIXME("Tee/Sink-to-Sink filter not supported\n");
595 if (IUnknown_QueryInterface(source
, &IID_IPin
, (void **)&pin
) == S_OK
)
597 hr
= find_unconnected_source_from_pin(This
, category
, majortype
, pin
, &source_out
);
600 else if (IUnknown_QueryInterface(source
, &IID_IBaseFilter
, (void **)&filter
) == S_OK
)
602 hr
= find_unconnected_source_from_filter(This
, category
, majortype
, filter
, &source_out
);
603 IBaseFilter_Release(filter
);
607 WARN("Source object does not expose IBaseFilter or IPin.\n");
616 IEnumMediaTypes
*enumMedia
= NULL
;
617 hr
= IPin_EnumMediaTypes(source_out
, &enumMedia
);
619 AM_MEDIA_TYPE
*mediaType
;
620 hr
= IEnumMediaTypes_Next(enumMedia
, 1, &mediaType
, NULL
);
622 if (IsEqualIID(&mediaType
->majortype
, &MEDIATYPE_Video
)) {
623 hr
= CoCreateInstance(&CLSID_VideoRenderer
, NULL
, CLSCTX_INPROC_SERVER
,
624 &IID_IBaseFilter
, (void**)&pfRenderer
);
625 } else if (IsEqualIID(&mediaType
->majortype
, &MEDIATYPE_Audio
)) {
626 hr
= CoCreateInstance(&CLSID_DSoundRender
, NULL
, CLSCTX_INPROC_SERVER
,
627 &IID_IBaseFilter
, (void**)&pfRenderer
);
629 FIXME("cannot automatically load renderer for majortype %s\n", debugstr_guid(&mediaType
->majortype
));
633 rendererNeedsRelease
= TRUE
;
634 hr
= IGraphBuilder_AddFilter(This
->mygraph
, pfRenderer
, NULL
);
636 DeleteMediaType(mediaType
);
638 IEnumMediaTypes_Release(enumMedia
);
641 if (rendererNeedsRelease
)
642 IBaseFilter_Release(pfRenderer
);
643 IPin_Release(source_out
);
648 hr
= ICaptureGraphBuilder2_FindPin(iface
, (IUnknown
*)pfRenderer
, PINDIR_INPUT
, NULL
, NULL
, TRUE
, 0, &renderer_in
);
651 if (rendererNeedsRelease
)
652 IBaseFilter_Release(pfRenderer
);
653 IPin_Release(source_out
);
658 hr
= IGraphBuilder_Connect(This
->mygraph
, source_out
, renderer_in
);
661 IPin
*compressor_in
, *compressor_out
;
663 hr
= ICaptureGraphBuilder2_FindPin(iface
, (IUnknown
*)pfCompressor
,
664 PINDIR_INPUT
, NULL
, NULL
, TRUE
, 0, &compressor_in
);
667 hr
= IGraphBuilder_Connect(This
->mygraph
, source_out
, compressor_in
);
668 IPin_Release(compressor_in
);
673 hr
= ICaptureGraphBuilder2_FindPin(iface
, (IUnknown
*)pfCompressor
,
674 PINDIR_OUTPUT
, NULL
, NULL
, TRUE
, 0, &compressor_out
);
677 hr
= IGraphBuilder_Connect(This
->mygraph
, compressor_out
, renderer_in
);
678 IPin_Release(compressor_out
);
683 IPin_Release(source_out
);
684 IPin_Release(renderer_in
);
685 if (rendererNeedsRelease
)
686 IBaseFilter_Release(pfRenderer
);
692 static HRESULT WINAPI
693 fnCaptureGraphBuilder2_ControlStream(ICaptureGraphBuilder2
* iface
,
694 const GUID
*pCategory
,
696 IBaseFilter
*pFilter
,
697 REFERENCE_TIME
*pstart
,
698 REFERENCE_TIME
*pstop
,
702 CaptureGraphImpl
*This
= impl_from_ICaptureGraphBuilder2(iface
);
704 FIXME("(%p/%p)->(%s, %s, %p, %p, %p, %i, %i) Stub!\n", This
, iface
,
705 debugstr_guid(pCategory
), debugstr_guid(pType
),
706 pFilter
, pstart
, pstop
, wStartCookie
, wStopCookie
);
711 static HRESULT WINAPI
712 fnCaptureGraphBuilder2_AllocCapFile(ICaptureGraphBuilder2
* iface
,
716 CaptureGraphImpl
*This
= impl_from_ICaptureGraphBuilder2(iface
);
718 FIXME("(%p/%p)->(%s, 0x%s) Stub!\n", This
, iface
,
719 debugstr_w(lpwstr
), wine_dbgstr_longlong(dwlSize
));
724 static HRESULT WINAPI
725 fnCaptureGraphBuilder2_CopyCaptureFile(ICaptureGraphBuilder2
* iface
,
729 IAMCopyCaptureFileProgress
*pCallback
)
731 CaptureGraphImpl
*This
= impl_from_ICaptureGraphBuilder2(iface
);
733 FIXME("(%p/%p)->(%s, %s, %i, %p) Stub!\n", This
, iface
,
734 debugstr_w(lpwstrOld
), debugstr_w(lpwstrNew
),
735 fAllowEscAbort
, pCallback
);
740 static HRESULT WINAPI
741 fnCaptureGraphBuilder2_FindPin(ICaptureGraphBuilder2
* iface
,
743 PIN_DIRECTION pindir
,
744 const GUID
*pCategory
,
751 IEnumPins
*enumpins
= NULL
;
753 CaptureGraphImpl
*This
= impl_from_ICaptureGraphBuilder2(iface
);
755 TRACE("(%p/%p)->(%p, %x, %s, %s, %d, %i, %p)\n", This
, iface
,
756 pSource
, pindir
, debugstr_guid(pCategory
), debugstr_guid(pType
),
757 fUnconnected
, num
, ppPin
);
761 hr
= IUnknown_QueryInterface(pSource
, &IID_IPin
, (void**)&pin
);
762 if (hr
== E_NOINTERFACE
)
764 IBaseFilter
*filter
= NULL
;
767 hr
= IUnknown_QueryInterface(pSource
, &IID_IBaseFilter
, (void**)&filter
);
768 if (hr
== E_NOINTERFACE
)
770 WARN("Input not filter or pin?!\n");
771 return E_NOINTERFACE
;
774 hr
= IBaseFilter_EnumPins(filter
, &enumpins
);
777 WARN("Could not enumerate\n");
778 IBaseFilter_Release(filter
);
786 hr
= IEnumPins_Next(enumpins
, 1, &pin
, &fetched
);
787 if (hr
== VFW_E_ENUM_OUT_OF_SYNC
)
790 IEnumPins_Reset(enumpins
);
802 TRACE("Testing match\n");
803 if (pin_matches(pin
, pindir
, pCategory
, pType
, fUnconnected
) && numcurrent
++ == num
)
808 IEnumPins_Release(enumpins
);
809 IBaseFilter_Release(filter
);
813 WARN("Could not find %s pin # %d\n", (pindir
== PINDIR_OUTPUT
? "output" : "input"), numcurrent
);
817 else if (!pin_matches(pin
, pindir
, pCategory
, pType
, fUnconnected
))
827 static const ICaptureGraphBuilder2Vtbl builder2_Vtbl
=
829 fnCaptureGraphBuilder2_QueryInterface
,
830 fnCaptureGraphBuilder2_AddRef
,
831 fnCaptureGraphBuilder2_Release
,
832 fnCaptureGraphBuilder2_SetFilterGraph
,
833 fnCaptureGraphBuilder2_GetFilterGraph
,
834 fnCaptureGraphBuilder2_SetOutputFileName
,
835 fnCaptureGraphBuilder2_FindInterface
,
836 fnCaptureGraphBuilder2_RenderStream
,
837 fnCaptureGraphBuilder2_ControlStream
,
838 fnCaptureGraphBuilder2_AllocCapFile
,
839 fnCaptureGraphBuilder2_CopyCaptureFile
,
840 fnCaptureGraphBuilder2_FindPin
844 static HRESULT WINAPI
845 fnCaptureGraphBuilder_QueryInterface(ICaptureGraphBuilder
* iface
,
846 REFIID riid
, LPVOID
* ppv
)
848 CaptureGraphImpl
*This
= impl_from_ICaptureGraphBuilder(iface
);
849 TRACE("%p --> Forwarding to v2 (%p)\n", iface
, This
);
850 return ICaptureGraphBuilder2_QueryInterface(&This
->ICaptureGraphBuilder2_iface
, riid
, ppv
);
854 fnCaptureGraphBuilder_AddRef(ICaptureGraphBuilder
* iface
)
856 CaptureGraphImpl
*This
= impl_from_ICaptureGraphBuilder(iface
);
857 TRACE("%p --> Forwarding to v2 (%p)\n", iface
, This
);
858 return ICaptureGraphBuilder2_AddRef(&This
->ICaptureGraphBuilder2_iface
);
862 fnCaptureGraphBuilder_Release(ICaptureGraphBuilder
* iface
)
864 CaptureGraphImpl
*This
= impl_from_ICaptureGraphBuilder(iface
);
865 TRACE("%p --> Forwarding to v2 (%p)\n", iface
, This
);
866 return ICaptureGraphBuilder2_Release(&This
->ICaptureGraphBuilder2_iface
);
869 static HRESULT WINAPI
870 fnCaptureGraphBuilder_SetFiltergraph(ICaptureGraphBuilder
* iface
,
873 CaptureGraphImpl
*This
= impl_from_ICaptureGraphBuilder(iface
);
874 TRACE("%p --> Forwarding to v2 (%p)\n", iface
, This
);
875 return ICaptureGraphBuilder2_SetFiltergraph(&This
->ICaptureGraphBuilder2_iface
, pfg
);
878 static HRESULT WINAPI
879 fnCaptureGraphBuilder_GetFiltergraph(ICaptureGraphBuilder
* iface
,
882 CaptureGraphImpl
*This
= impl_from_ICaptureGraphBuilder(iface
);
883 TRACE("%p --> Forwarding to v2 (%p)\n", iface
, This
);
884 return ICaptureGraphBuilder2_GetFiltergraph(&This
->ICaptureGraphBuilder2_iface
, pfg
);
887 static HRESULT WINAPI
888 fnCaptureGraphBuilder_SetOutputFileName(ICaptureGraphBuilder
* iface
,
889 const GUID
*pType
, LPCOLESTR lpstrFile
,
890 IBaseFilter
**ppf
, IFileSinkFilter
**ppSink
)
892 CaptureGraphImpl
*This
= impl_from_ICaptureGraphBuilder(iface
);
893 TRACE("%p --> Forwarding to v2 (%p)\n", iface
, This
);
894 return ICaptureGraphBuilder2_SetOutputFileName(&This
->ICaptureGraphBuilder2_iface
, pType
,
895 lpstrFile
, ppf
, ppSink
);
898 static HRESULT WINAPI
899 fnCaptureGraphBuilder_FindInterface(ICaptureGraphBuilder
* iface
,
900 const GUID
*pCategory
, IBaseFilter
*pf
,
901 REFIID riid
, void **ppint
)
903 CaptureGraphImpl
*This
= impl_from_ICaptureGraphBuilder(iface
);
904 TRACE("%p --> Forwarding to v2 (%p)\n", iface
, This
);
905 return ICaptureGraphBuilder2_FindInterface(&This
->ICaptureGraphBuilder2_iface
, pCategory
, NULL
,
909 static HRESULT WINAPI
910 fnCaptureGraphBuilder_RenderStream(ICaptureGraphBuilder
* iface
,
911 const GUID
*pCategory
, IUnknown
*pSource
,
912 IBaseFilter
*pfCompressor
, IBaseFilter
*pfRenderer
)
914 CaptureGraphImpl
*This
= impl_from_ICaptureGraphBuilder(iface
);
915 TRACE("%p --> Forwarding to v2 (%p)\n", iface
, This
);
916 return ICaptureGraphBuilder2_RenderStream(&This
->ICaptureGraphBuilder2_iface
, pCategory
, NULL
,
917 pSource
, pfCompressor
, pfRenderer
);
920 static HRESULT WINAPI
921 fnCaptureGraphBuilder_ControlStream(ICaptureGraphBuilder
* iface
,
922 const GUID
*pCategory
, IBaseFilter
*pFilter
,
923 REFERENCE_TIME
*pstart
, REFERENCE_TIME
*pstop
,
924 WORD wStartCookie
, WORD wStopCookie
)
926 CaptureGraphImpl
*This
= impl_from_ICaptureGraphBuilder(iface
);
927 TRACE("%p --> Forwarding to v2 (%p)\n", iface
, This
);
928 return ICaptureGraphBuilder2_ControlStream(&This
->ICaptureGraphBuilder2_iface
, pCategory
, NULL
,
929 pFilter
, pstart
, pstop
, wStartCookie
, wStopCookie
);
932 static HRESULT WINAPI
933 fnCaptureGraphBuilder_AllocCapFile(ICaptureGraphBuilder
* iface
,
934 LPCOLESTR lpstr
, DWORDLONG dwlSize
)
936 CaptureGraphImpl
*This
= impl_from_ICaptureGraphBuilder(iface
);
937 TRACE("%p --> Forwarding to v2 (%p)\n", iface
, This
);
938 return ICaptureGraphBuilder2_AllocCapFile(&This
->ICaptureGraphBuilder2_iface
, lpstr
, dwlSize
);
941 static HRESULT WINAPI
942 fnCaptureGraphBuilder_CopyCaptureFile(ICaptureGraphBuilder
* iface
,
943 LPOLESTR lpwstrOld
, LPOLESTR lpwstrNew
,
945 IAMCopyCaptureFileProgress
*pCallback
)
947 CaptureGraphImpl
*This
= impl_from_ICaptureGraphBuilder(iface
);
948 TRACE("%p --> Forwarding to v2 (%p)\n", iface
, This
);
949 return ICaptureGraphBuilder2_CopyCaptureFile(&This
->ICaptureGraphBuilder2_iface
, lpwstrOld
,
950 lpwstrNew
, fAllowEscAbort
, pCallback
);
953 static const ICaptureGraphBuilderVtbl builder_Vtbl
=
955 fnCaptureGraphBuilder_QueryInterface
,
956 fnCaptureGraphBuilder_AddRef
,
957 fnCaptureGraphBuilder_Release
,
958 fnCaptureGraphBuilder_SetFiltergraph
,
959 fnCaptureGraphBuilder_GetFiltergraph
,
960 fnCaptureGraphBuilder_SetOutputFileName
,
961 fnCaptureGraphBuilder_FindInterface
,
962 fnCaptureGraphBuilder_RenderStream
,
963 fnCaptureGraphBuilder_ControlStream
,
964 fnCaptureGraphBuilder_AllocCapFile
,
965 fnCaptureGraphBuilder_CopyCaptureFile