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