msvcrt: Added basic _popen tests.
[wine] / dlls / qcap / capturegraph.c
1 /* Capture Graph Builder, Minimal edition
2  *
3  * Copyright 2005 Maarten Lankhorst
4  * Copyright 2005 Rolf Kalbermatter
5  *
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.
10  *
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.
15  *
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
19  */
20 #include "config.h"
21
22 #include <stdio.h>
23 #include <stdarg.h>
24
25 #define COBJMACROS
26 #define NONAMELESSSTRUCT
27 #define NONAMELESSUNION
28
29 #include "windef.h"
30 #include "winbase.h"
31 #include "wingdi.h"
32 #include "winerror.h"
33 #include "objbase.h"
34
35 #include "evcode.h"
36 #include "strmif.h"
37 #include "control.h"
38 #include "vfwmsgs.h"
39 /*
40  *#include "amvideo.h"
41  *#include "mmreg.h"
42  *#include "dshow.h"
43  *#include "ddraw.h"
44  */
45 #include "qcap_main.h"
46
47 #include "wine/unicode.h"
48 #include "wine/debug.h"
49
50 WINE_DEFAULT_DEBUG_CHANNEL(qcap);
51
52 /***********************************************************************
53 *   ICaptureGraphBuilder & ICaptureGraphBuilder2 implementation
54 */
55 typedef struct CaptureGraphImpl
56 {
57     ICaptureGraphBuilder2 ICaptureGraphBuilder2_iface;
58     ICaptureGraphBuilder ICaptureGraphBuilder_iface;
59     LONG ref;
60     IGraphBuilder *mygraph;
61     CRITICAL_SECTION csFilter;
62 } CaptureGraphImpl;
63
64 static const ICaptureGraphBuilderVtbl builder_Vtbl;
65 static const ICaptureGraphBuilder2Vtbl builder2_Vtbl;
66
67 static inline CaptureGraphImpl *impl_from_ICaptureGraphBuilder(ICaptureGraphBuilder *iface)
68 {
69     return CONTAINING_RECORD(iface, CaptureGraphImpl, ICaptureGraphBuilder_iface);
70 }
71
72 static inline CaptureGraphImpl *impl_from_ICaptureGraphBuilder2(ICaptureGraphBuilder2 *iface)
73 {
74     return CONTAINING_RECORD(iface, CaptureGraphImpl, ICaptureGraphBuilder2_iface);
75 }
76
77
78 IUnknown * CALLBACK QCAP_createCaptureGraphBuilder2(IUnknown *pUnkOuter,
79                                                     HRESULT *phr)
80 {
81     CaptureGraphImpl * pCapture = NULL;
82
83     TRACE("(%p, %p)\n", pUnkOuter, phr);
84
85     *phr = CLASS_E_NOAGGREGATION;
86     if (pUnkOuter)
87     {
88         return NULL;
89     }
90     *phr = E_OUTOFMEMORY;
91
92     pCapture = CoTaskMemAlloc(sizeof(CaptureGraphImpl));
93     if (pCapture)
94     {
95         pCapture->ICaptureGraphBuilder2_iface.lpVtbl = &builder2_Vtbl;
96         pCapture->ICaptureGraphBuilder_iface.lpVtbl = &builder_Vtbl;
97         pCapture->ref = 1;
98         pCapture->mygraph = NULL;
99         InitializeCriticalSection(&pCapture->csFilter);
100         pCapture->csFilter.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": CaptureGraphImpl.csFilter");
101         *phr = S_OK;
102         ObjectRefCount(TRUE);
103     }
104     return (IUnknown *)&pCapture->ICaptureGraphBuilder_iface;
105 }
106
107 static HRESULT WINAPI
108 fnCaptureGraphBuilder2_QueryInterface(ICaptureGraphBuilder2 * iface,
109                                       REFIID riid,
110                                       LPVOID * ppv)
111 {
112     CaptureGraphImpl *This = impl_from_ICaptureGraphBuilder2(iface);
113
114     TRACE("(%p/%p)->(%s, %p)\n", This, iface, debugstr_guid(riid), ppv);
115
116     *ppv = NULL;
117     if (IsEqualIID(riid, &IID_IUnknown))
118         *ppv = &This->ICaptureGraphBuilder2_iface;
119     else if (IsEqualIID(riid, &IID_ICaptureGraphBuilder))
120         *ppv = &This->ICaptureGraphBuilder_iface;
121     else if (IsEqualIID(riid, &IID_ICaptureGraphBuilder2))
122         *ppv = &This->ICaptureGraphBuilder2_iface;
123
124     if (*ppv)
125     {
126         IUnknown_AddRef((IUnknown *)(*ppv));
127         TRACE ("-- Interface = %p\n", *ppv);
128         return S_OK;
129     }
130
131     TRACE ("-- Interface: E_NOINTERFACE\n");
132     return E_NOINTERFACE;
133 }
134
135 static ULONG WINAPI
136 fnCaptureGraphBuilder2_AddRef(ICaptureGraphBuilder2 * iface)
137 {
138     CaptureGraphImpl *This = impl_from_ICaptureGraphBuilder2(iface);
139     DWORD ref = InterlockedIncrement(&This->ref);
140
141     TRACE("(%p/%p)->() AddRef from %d\n", This, iface, ref - 1);
142     return ref;
143 }
144
145 static ULONG WINAPI fnCaptureGraphBuilder2_Release(ICaptureGraphBuilder2 * iface)
146 {
147     CaptureGraphImpl *This = impl_from_ICaptureGraphBuilder2(iface);
148     DWORD ref = InterlockedDecrement(&This->ref);
149
150     TRACE("(%p/%p)->() Release from %d\n", This, iface, ref + 1);
151
152     if (!ref)
153     {
154         This->csFilter.DebugInfo->Spare[0] = 0;
155         DeleteCriticalSection(&This->csFilter);
156         if (This->mygraph)
157             IGraphBuilder_Release(This->mygraph);
158         CoTaskMemFree(This);
159         ObjectRefCount(FALSE);
160     }
161     return ref;
162 }
163
164 static HRESULT WINAPI
165 fnCaptureGraphBuilder2_SetFilterGraph(ICaptureGraphBuilder2 * iface,
166                                       IGraphBuilder *pfg)
167 {
168 /* The graph builder will automatically create a filter graph if you don't call
169    this method. If you call this method after the graph builder has created its
170    own filter graph, the call will fail. */
171     IMediaEvent *pmev;
172     CaptureGraphImpl *This = impl_from_ICaptureGraphBuilder2(iface);
173
174     TRACE("(%p/%p)->(%p)\n", This, iface, pfg);
175
176     if (This->mygraph)
177         return E_UNEXPECTED;
178
179     if (!pfg)
180         return E_POINTER;
181
182     This->mygraph = pfg;
183     IGraphBuilder_AddRef(This->mygraph);
184     if (SUCCEEDED(IGraphBuilder_QueryInterface(This->mygraph,
185                                           &IID_IMediaEvent, (LPVOID *)&pmev)))
186     {
187         IMediaEvent_CancelDefaultHandling(pmev, EC_REPAINT);
188         IMediaEvent_Release(pmev);
189     }
190     return S_OK;
191 }
192
193 static HRESULT WINAPI
194 fnCaptureGraphBuilder2_GetFilterGraph(ICaptureGraphBuilder2 * iface,
195                                       IGraphBuilder **pfg)
196 {
197     CaptureGraphImpl *This = impl_from_ICaptureGraphBuilder2(iface);
198
199     TRACE("(%p/%p)->(%p)\n", This, iface, pfg);
200
201     if (!pfg)
202         return E_POINTER;
203
204     *pfg = This->mygraph;
205     if (!This->mygraph)
206     {
207         TRACE("(%p) Getting NULL filtergraph\n", iface);
208         return E_UNEXPECTED;
209     }
210
211     IGraphBuilder_AddRef(This->mygraph);
212
213     TRACE("(%p) return filtergraph %p\n", iface, *pfg);
214     return S_OK;
215 }
216
217 static HRESULT WINAPI
218 fnCaptureGraphBuilder2_SetOutputFileName(ICaptureGraphBuilder2 * iface,
219                                          const GUID *pType,
220                                          LPCOLESTR lpstrFile,
221                                          IBaseFilter **ppf,
222                                          IFileSinkFilter **ppSink)
223 {
224     CaptureGraphImpl *This = impl_from_ICaptureGraphBuilder2(iface);
225
226     FIXME("(%p/%p)->(%s, %s, %p, %p) Stub!\n", This, iface,
227           debugstr_guid(pType), debugstr_w(lpstrFile), ppf, ppSink);
228
229     return E_NOTIMPL;
230 }
231
232 static HRESULT WINAPI
233 fnCaptureGraphBuilder2_FindInterface(ICaptureGraphBuilder2 * iface,
234                                      const GUID *pCategory,
235                                      const GUID *pType,
236                                      IBaseFilter *pf,
237                                      REFIID riid,
238                                      void **ppint)
239 {
240     CaptureGraphImpl *This = impl_from_ICaptureGraphBuilder2(iface);
241
242     FIXME("(%p/%p)->(%s, %s, %p, %s, %p) - workaround stub!\n", This, iface,
243           debugstr_guid(pCategory), debugstr_guid(pType),
244           pf, debugstr_guid(riid), ppint);
245
246     return IBaseFilter_QueryInterface(pf, riid, ppint);
247     /* Looks for the specified interface on the filter, upstream and
248      * downstream from the filter, and, optionally, only on the output
249      * pin of the given category.
250      */
251 }
252
253 static HRESULT WINAPI
254 fnCaptureGraphBuilder2_RenderStream(ICaptureGraphBuilder2 * iface,
255                                     const GUID *pCategory,
256                                     const GUID *pType,
257                                     IUnknown *pSource,
258                                     IBaseFilter *pfCompressor,
259                                     IBaseFilter *pfRenderer)
260 {
261     CaptureGraphImpl *This = impl_from_ICaptureGraphBuilder2(iface);
262     IPin *pin_in = NULL;
263     IPin *pin_out = NULL;
264     HRESULT hr;
265
266     FIXME("(%p/%p)->(%s, %s, %p, %p, %p) Stub!\n", This, iface,
267           debugstr_guid(pCategory), debugstr_guid(pType),
268           pSource, pfCompressor, pfRenderer);
269
270     if (pfCompressor)
271         FIXME("Intermediate streams not supported yet\n");
272
273     if (!This->mygraph)
274     {
275         FIXME("Need a capture graph\n");
276         return E_UNEXPECTED;
277     }
278
279     ICaptureGraphBuilder2_FindPin(iface, pSource, PINDIR_OUTPUT, pCategory, pType, TRUE, 0, &pin_in);
280     if (!pin_in)
281         return E_FAIL;
282     ICaptureGraphBuilder2_FindPin(iface, (IUnknown*)pfRenderer, PINDIR_INPUT, pCategory, pType, TRUE, 0, &pin_out);
283     if (!pin_out)
284     {
285         IPin_Release(pin_in);
286         return E_FAIL;
287     }
288
289     /* Uses 'Intelligent Connect', so Connect, not ConnectDirect here */
290     hr = IGraphBuilder_Connect(This->mygraph, pin_in, pin_out);
291     IPin_Release(pin_in);
292     IPin_Release(pin_out);
293     return hr;
294 }
295
296 static HRESULT WINAPI
297 fnCaptureGraphBuilder2_ControlStream(ICaptureGraphBuilder2 * iface,
298                                      const GUID *pCategory,
299                                      const GUID *pType,
300                                      IBaseFilter *pFilter,
301                                      REFERENCE_TIME *pstart,
302                                      REFERENCE_TIME *pstop,
303                                      WORD wStartCookie,
304                                      WORD wStopCookie)
305 {
306     CaptureGraphImpl *This = impl_from_ICaptureGraphBuilder2(iface);
307
308     FIXME("(%p/%p)->(%s, %s, %p, %p, %p, %i, %i) Stub!\n", This, iface,
309           debugstr_guid(pCategory), debugstr_guid(pType),
310           pFilter, pstart, pstop, wStartCookie, wStopCookie);
311
312     return E_NOTIMPL;
313 }
314
315 static HRESULT WINAPI
316 fnCaptureGraphBuilder2_AllocCapFile(ICaptureGraphBuilder2 * iface,
317                                     LPCOLESTR lpwstr,
318                                     DWORDLONG dwlSize)
319 {
320     CaptureGraphImpl *This = impl_from_ICaptureGraphBuilder2(iface);
321
322     FIXME("(%p/%p)->(%s, 0x%s) Stub!\n", This, iface,
323           debugstr_w(lpwstr), wine_dbgstr_longlong(dwlSize));
324
325     return E_NOTIMPL;
326 }
327
328 static HRESULT WINAPI
329 fnCaptureGraphBuilder2_CopyCaptureFile(ICaptureGraphBuilder2 * iface,
330                                        LPOLESTR lpwstrOld,
331                                        LPOLESTR lpwstrNew,
332                                        int fAllowEscAbort,
333                                        IAMCopyCaptureFileProgress *pCallback)
334 {
335     CaptureGraphImpl *This = impl_from_ICaptureGraphBuilder2(iface);
336
337     FIXME("(%p/%p)->(%s, %s, %i, %p) Stub!\n", This, iface,
338           debugstr_w(lpwstrOld), debugstr_w(lpwstrNew),
339           fAllowEscAbort, pCallback);
340
341     return E_NOTIMPL;
342 }
343
344 static BOOL pin_matches(IPin *pin, PIN_DIRECTION direction, const GUID *cat, const GUID *type, BOOL unconnected)
345 {
346     IPin *partner;
347     PIN_DIRECTION pindir;
348
349     IPin_QueryDirection(pin, &pindir);
350     if (pindir != direction)
351     {
352         TRACE("No match, wrong direction\n");
353         return FALSE;
354     }
355
356     if (unconnected && IPin_ConnectedTo(pin, &partner) == S_OK)
357     {
358         IPin_Release(partner);
359         TRACE("No match, %p already connected to %p\n", pin, partner);
360         return FALSE;
361     }
362
363     if (cat || type)
364         FIXME("Ignoring category/type\n");
365
366     TRACE("Match made in heaven\n");
367
368     return TRUE;
369 }
370
371 static HRESULT WINAPI
372 fnCaptureGraphBuilder2_FindPin(ICaptureGraphBuilder2 * iface,
373                                IUnknown *pSource,
374                                PIN_DIRECTION pindir,
375                                const GUID *pCategory,
376                                const GUID *pType,
377                                BOOL fUnconnected,
378                                INT num,
379                                IPin **ppPin)
380 {
381     HRESULT hr;
382     IEnumPins *enumpins = NULL;
383     IPin *pin;
384     CaptureGraphImpl *This = impl_from_ICaptureGraphBuilder2(iface);
385
386     TRACE("(%p/%p)->(%p, %x, %s, %s, %d, %i, %p)\n", This, iface,
387           pSource, pindir, debugstr_guid(pCategory), debugstr_guid(pType),
388           fUnconnected, num, ppPin);
389
390     pin = NULL;
391
392     hr = IUnknown_QueryInterface(pSource, &IID_IPin, (void**)&pin);
393     if (hr == E_NOINTERFACE)
394     {
395         IBaseFilter *filter = NULL;
396         int numcurrent = 0;
397
398         hr = IUnknown_QueryInterface(pSource, &IID_IBaseFilter, (void**)&filter);
399         if (hr == E_NOINTERFACE)
400         {
401             WARN("Input not filter or pin?!\n");
402             return E_FAIL;
403         }
404
405         hr = IBaseFilter_EnumPins(filter, &enumpins);
406         if (FAILED(hr))
407         {
408             WARN("Could not enumerate\n");
409             return hr;
410         }
411
412         IEnumPins_Reset(enumpins);
413
414         while (1)
415         {
416             hr = IEnumPins_Next(enumpins, 1, &pin, NULL);
417             if (hr == VFW_E_ENUM_OUT_OF_SYNC)
418             {
419                 numcurrent = 0;
420                 IEnumPins_Reset(enumpins);
421                 pin = NULL;
422                 continue;
423             }
424
425             if (hr != S_OK)
426                 break;
427             TRACE("Testing match\n");
428             if (pin_matches(pin, pindir, pCategory, pType, fUnconnected) && numcurrent++ == num)
429                 break;
430             IPin_Release(pin);
431             pin = NULL;
432         }
433         IEnumPins_Release(enumpins);
434
435         if (hr != S_OK)
436         {
437             WARN("Could not find %s pin # %d\n", (pindir == PINDIR_OUTPUT ? "output" : "input"), numcurrent);
438             return E_FAIL;
439         }
440     }
441     else if (!pin_matches(pin, pindir, pCategory, pType, fUnconnected))
442     {
443         IPin_Release(pin);
444         return E_FAIL;
445     }
446
447     *ppPin = pin;
448     return S_OK;
449 }
450
451 static const ICaptureGraphBuilder2Vtbl builder2_Vtbl =
452 {
453     fnCaptureGraphBuilder2_QueryInterface,
454     fnCaptureGraphBuilder2_AddRef,
455     fnCaptureGraphBuilder2_Release,
456     fnCaptureGraphBuilder2_SetFilterGraph,
457     fnCaptureGraphBuilder2_GetFilterGraph,
458     fnCaptureGraphBuilder2_SetOutputFileName,
459     fnCaptureGraphBuilder2_FindInterface,
460     fnCaptureGraphBuilder2_RenderStream,
461     fnCaptureGraphBuilder2_ControlStream,
462     fnCaptureGraphBuilder2_AllocCapFile,
463     fnCaptureGraphBuilder2_CopyCaptureFile,
464     fnCaptureGraphBuilder2_FindPin
465 };
466
467
468 static HRESULT WINAPI
469 fnCaptureGraphBuilder_QueryInterface(ICaptureGraphBuilder * iface,
470                                      REFIID riid, LPVOID * ppv)
471 {
472     CaptureGraphImpl *This = impl_from_ICaptureGraphBuilder(iface);
473     TRACE("%p --> Forwarding to v2 (%p)\n", iface, This);
474     return ICaptureGraphBuilder2_QueryInterface(&This->ICaptureGraphBuilder2_iface, riid, ppv);
475 }
476
477 static ULONG WINAPI
478 fnCaptureGraphBuilder_AddRef(ICaptureGraphBuilder * iface)
479 {
480     CaptureGraphImpl *This = impl_from_ICaptureGraphBuilder(iface);
481     TRACE("%p --> Forwarding to v2 (%p)\n", iface, This);
482     return ICaptureGraphBuilder2_AddRef(&This->ICaptureGraphBuilder2_iface);
483 }
484
485 static ULONG WINAPI
486 fnCaptureGraphBuilder_Release(ICaptureGraphBuilder * iface)
487 {
488     CaptureGraphImpl *This = impl_from_ICaptureGraphBuilder(iface);
489     TRACE("%p --> Forwarding to v2 (%p)\n", iface, This);
490     return ICaptureGraphBuilder2_Release(&This->ICaptureGraphBuilder2_iface);
491 }
492
493 static HRESULT WINAPI
494 fnCaptureGraphBuilder_SetFiltergraph(ICaptureGraphBuilder * iface,
495                                      IGraphBuilder *pfg)
496 {
497     CaptureGraphImpl *This = impl_from_ICaptureGraphBuilder(iface);
498     TRACE("%p --> Forwarding to v2 (%p)\n", iface, This);
499     return ICaptureGraphBuilder2_SetFiltergraph(&This->ICaptureGraphBuilder2_iface, pfg);
500 }
501
502 static HRESULT WINAPI
503 fnCaptureGraphBuilder_GetFiltergraph(ICaptureGraphBuilder * iface,
504                                      IGraphBuilder **pfg)
505 {
506     CaptureGraphImpl *This = impl_from_ICaptureGraphBuilder(iface);
507     TRACE("%p --> Forwarding to v2 (%p)\n", iface, This);
508     return ICaptureGraphBuilder2_GetFiltergraph(&This->ICaptureGraphBuilder2_iface, pfg);
509 }
510
511 static HRESULT WINAPI
512 fnCaptureGraphBuilder_SetOutputFileName(ICaptureGraphBuilder * iface,
513                                         const GUID *pType, LPCOLESTR lpstrFile,
514                                         IBaseFilter **ppf, IFileSinkFilter **ppSink)
515 {
516     CaptureGraphImpl *This = impl_from_ICaptureGraphBuilder(iface);
517     TRACE("%p --> Forwarding to v2 (%p)\n", iface, This);
518     return ICaptureGraphBuilder2_SetOutputFileName(&This->ICaptureGraphBuilder2_iface, pType,
519                                                    lpstrFile, ppf, ppSink);
520 }
521
522 static HRESULT WINAPI
523 fnCaptureGraphBuilder_FindInterface(ICaptureGraphBuilder * iface,
524                                     const GUID *pCategory, IBaseFilter *pf,
525                                     REFIID riid, void **ppint)
526 {
527     CaptureGraphImpl *This = impl_from_ICaptureGraphBuilder(iface);
528     TRACE("%p --> Forwarding to v2 (%p)\n", iface, This);
529     return ICaptureGraphBuilder2_FindInterface(&This->ICaptureGraphBuilder2_iface, pCategory, NULL,
530                                                pf, riid, ppint);
531 }
532
533 static HRESULT WINAPI
534 fnCaptureGraphBuilder_RenderStream(ICaptureGraphBuilder * iface,
535                                    const GUID *pCategory, IUnknown *pSource,
536                                    IBaseFilter *pfCompressor, IBaseFilter *pfRenderer)
537 {
538     CaptureGraphImpl *This = impl_from_ICaptureGraphBuilder(iface);
539     TRACE("%p --> Forwarding to v2 (%p)\n", iface, This);
540     return ICaptureGraphBuilder2_RenderStream(&This->ICaptureGraphBuilder2_iface, pCategory, NULL,
541                                               pSource, pfCompressor, pfRenderer);
542 }
543
544 static HRESULT WINAPI
545 fnCaptureGraphBuilder_ControlStream(ICaptureGraphBuilder * iface,
546                                     const GUID *pCategory, IBaseFilter *pFilter,
547                                     REFERENCE_TIME *pstart, REFERENCE_TIME *pstop,
548                                     WORD wStartCookie, WORD wStopCookie)
549 {
550     CaptureGraphImpl *This = impl_from_ICaptureGraphBuilder(iface);
551     TRACE("%p --> Forwarding to v2 (%p)\n", iface, This);
552     return ICaptureGraphBuilder2_ControlStream(&This->ICaptureGraphBuilder2_iface, pCategory, NULL,
553                                                pFilter, pstart, pstop, wStartCookie, wStopCookie);
554 }
555
556 static HRESULT WINAPI
557 fnCaptureGraphBuilder_AllocCapFile(ICaptureGraphBuilder * iface,
558                                    LPCOLESTR lpstr, DWORDLONG dwlSize)
559 {
560     CaptureGraphImpl *This = impl_from_ICaptureGraphBuilder(iface);
561     TRACE("%p --> Forwarding to v2 (%p)\n", iface, This);
562     return ICaptureGraphBuilder2_AllocCapFile(&This->ICaptureGraphBuilder2_iface, lpstr, dwlSize);
563 }
564
565 static HRESULT WINAPI
566 fnCaptureGraphBuilder_CopyCaptureFile(ICaptureGraphBuilder * iface,
567                                       LPOLESTR lpwstrOld, LPOLESTR lpwstrNew,
568                                       int fAllowEscAbort,
569                                       IAMCopyCaptureFileProgress *pCallback)
570 {
571     CaptureGraphImpl *This = impl_from_ICaptureGraphBuilder(iface);
572     TRACE("%p --> Forwarding to v2 (%p)\n", iface, This);
573     return ICaptureGraphBuilder2_CopyCaptureFile(&This->ICaptureGraphBuilder2_iface, lpwstrOld,
574                                                  lpwstrNew, fAllowEscAbort, pCallback);
575 }
576
577 static const ICaptureGraphBuilderVtbl builder_Vtbl =
578 {
579    fnCaptureGraphBuilder_QueryInterface,
580    fnCaptureGraphBuilder_AddRef,
581    fnCaptureGraphBuilder_Release,
582    fnCaptureGraphBuilder_SetFiltergraph,
583    fnCaptureGraphBuilder_GetFiltergraph,
584    fnCaptureGraphBuilder_SetOutputFileName,
585    fnCaptureGraphBuilder_FindInterface,
586    fnCaptureGraphBuilder_RenderStream,
587    fnCaptureGraphBuilder_ControlStream,
588    fnCaptureGraphBuilder_AllocCapFile,
589    fnCaptureGraphBuilder_CopyCaptureFile
590 };