ntdll: Get the unix tid on DragonFly BSD.
[wine/multimedia.git] / dlls / qcap / capturegraph.c
blobaa5c0a489c3768ff8547f88abda0c597a1c2dc54
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
20 #include "config.h"
22 #include <stdio.h>
23 #include <stdarg.h>
25 #define COBJMACROS
26 #define NONAMELESSSTRUCT
27 #define NONAMELESSUNION
29 #include "windef.h"
30 #include "winbase.h"
31 #include "wingdi.h"
32 #include "winerror.h"
33 #include "objbase.h"
35 #include "evcode.h"
36 #include "strmif.h"
37 #include "control.h"
38 #include "vfwmsgs.h"
40 *#include "amvideo.h"
41 *#include "mmreg.h"
42 *#include "dshow.h"
43 *#include "ddraw.h"
45 #include "qcap_main.h"
47 #include "wine/unicode.h"
48 #include "wine/debug.h"
50 WINE_DEFAULT_DEBUG_CHANNEL(qcap);
52 /***********************************************************************
53 * ICaptureGraphBuilder & ICaptureGraphBuilder2 implementation
55 typedef struct CaptureGraphImpl
57 ICaptureGraphBuilder2 ICaptureGraphBuilder2_iface;
58 ICaptureGraphBuilder ICaptureGraphBuilder_iface;
59 LONG ref;
60 IGraphBuilder *mygraph;
62 CRITICAL_SECTION csFilter;
63 } CaptureGraphImpl;
65 static const ICaptureGraphBuilderVtbl builder_Vtbl;
66 static const ICaptureGraphBuilder2Vtbl builder2_Vtbl;
68 static inline CaptureGraphImpl *impl_from_ICaptureGraphBuilder(ICaptureGraphBuilder *iface)
70 return CONTAINING_RECORD(iface, CaptureGraphImpl, ICaptureGraphBuilder_iface);
73 static inline CaptureGraphImpl *impl_from_ICaptureGraphBuilder2(ICaptureGraphBuilder2 *iface)
75 return CONTAINING_RECORD(iface, CaptureGraphImpl, ICaptureGraphBuilder2_iface);
79 IUnknown * CALLBACK QCAP_createCaptureGraphBuilder2(IUnknown *pUnkOuter,
80 HRESULT *phr)
82 CaptureGraphImpl * pCapture = NULL;
84 TRACE("(%p, %p)\n", pUnkOuter, phr);
86 *phr = CLASS_E_NOAGGREGATION;
87 if (pUnkOuter)
89 return NULL;
91 *phr = E_OUTOFMEMORY;
93 pCapture = CoTaskMemAlloc(sizeof(CaptureGraphImpl));
94 if (pCapture)
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);
105 return (IUnknown *)&pCapture->ICaptureGraphBuilder_iface;
108 static HRESULT WINAPI
109 fnCaptureGraphBuilder2_QueryInterface(ICaptureGraphBuilder2 * iface,
110 REFIID riid,
111 LPVOID * ppv)
113 CaptureGraphImpl *This = impl_from_ICaptureGraphBuilder2(iface);
115 TRACE("(%p/%p)->(%s, %p)\n", This, iface, debugstr_guid(riid), ppv);
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;
125 if (*ppv)
127 IUnknown_AddRef((IUnknown *)(*ppv));
128 TRACE ("-- Interface = %p\n", *ppv);
129 return S_OK;
132 TRACE ("-- Interface: E_NOINTERFACE\n");
133 return E_NOINTERFACE;
136 static ULONG WINAPI
137 fnCaptureGraphBuilder2_AddRef(ICaptureGraphBuilder2 * iface)
139 CaptureGraphImpl *This = impl_from_ICaptureGraphBuilder2(iface);
140 DWORD ref = InterlockedIncrement(&This->ref);
142 TRACE("(%p/%p)->() AddRef from %d\n", This, iface, ref - 1);
143 return ref;
146 static ULONG WINAPI
147 fnCaptureGraphBuilder2_Release(ICaptureGraphBuilder2 * iface)
149 CaptureGraphImpl *This = impl_from_ICaptureGraphBuilder2(iface);
150 DWORD ref = InterlockedDecrement(&This->ref);
152 TRACE("(%p/%p)->() Release from %d\n", This, iface, ref + 1);
154 if (!ref)
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);
164 return ref;
167 static HRESULT WINAPI
168 fnCaptureGraphBuilder2_SetFilterGraph(ICaptureGraphBuilder2 * iface,
169 IGraphBuilder *pfg)
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);
177 TRACE("(%p/%p)->(%p)\n", This, iface, pfg);
179 if (This->mygraph)
180 return E_UNEXPECTED;
182 if (!pfg)
183 return E_POINTER;
185 This->mygraph = pfg;
186 IGraphBuilder_AddRef(This->mygraph);
187 if (SUCCEEDED(IUnknown_QueryInterface(This->mygraph,
188 &IID_IMediaEvent, (LPVOID *)&pmev)))
190 IMediaEvent_CancelDefaultHandling(pmev, EC_REPAINT);
191 IMediaEvent_Release(pmev);
193 return S_OK;
196 static HRESULT WINAPI
197 fnCaptureGraphBuilder2_GetFilterGraph(ICaptureGraphBuilder2 * iface,
198 IGraphBuilder **pfg)
200 CaptureGraphImpl *This = impl_from_ICaptureGraphBuilder2(iface);
202 TRACE("(%p/%p)->(%p)\n", This, iface, pfg);
204 if (!pfg)
205 return E_POINTER;
207 *pfg = This->mygraph;
208 if (!This->mygraph)
210 TRACE("(%p) Getting NULL filtergraph\n", iface);
211 return E_UNEXPECTED;
214 IGraphBuilder_AddRef(This->mygraph);
216 TRACE("(%p) return filtergraph %p\n", iface, *pfg);
217 return S_OK;
220 static HRESULT WINAPI
221 fnCaptureGraphBuilder2_SetOutputFileName(ICaptureGraphBuilder2 * iface,
222 const GUID *pType,
223 LPCOLESTR lpstrFile,
224 IBaseFilter **ppf,
225 IFileSinkFilter **ppSink)
227 CaptureGraphImpl *This = impl_from_ICaptureGraphBuilder2(iface);
229 FIXME("(%p/%p)->(%s, %s, %p, %p) Stub!\n", This, iface,
230 debugstr_guid(pType), debugstr_w(lpstrFile), ppf, ppSink);
232 return E_NOTIMPL;
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)
243 CaptureGraphImpl *This = impl_from_ICaptureGraphBuilder2(iface);
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);
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.
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)
264 CaptureGraphImpl *This = impl_from_ICaptureGraphBuilder2(iface);
265 IPin *pin_in = NULL;
266 IPin *pin_out = NULL;
267 HRESULT hr;
269 FIXME("(%p/%p)->(%s, %s, %p, %p, %p) Stub!\n", This, iface,
270 debugstr_guid(pCategory), debugstr_guid(pType),
271 pSource, pfCompressor, pfRenderer);
273 if (pfCompressor)
274 FIXME("Intermediate streams not supported yet\n");
276 if (!This->mygraph)
278 FIXME("Need a capture graph\n");
279 return E_UNEXPECTED;
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)
288 IPin_Release(pin_in);
289 return E_FAIL;
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;
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)
309 CaptureGraphImpl *This = impl_from_ICaptureGraphBuilder2(iface);
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);
315 return E_NOTIMPL;
318 static HRESULT WINAPI
319 fnCaptureGraphBuilder2_AllocCapFile(ICaptureGraphBuilder2 * iface,
320 LPCOLESTR lpwstr,
321 DWORDLONG dwlSize)
323 CaptureGraphImpl *This = impl_from_ICaptureGraphBuilder2(iface);
325 FIXME("(%p/%p)->(%s, 0x%s) Stub!\n", This, iface,
326 debugstr_w(lpwstr), wine_dbgstr_longlong(dwlSize));
328 return E_NOTIMPL;
331 static HRESULT WINAPI
332 fnCaptureGraphBuilder2_CopyCaptureFile(ICaptureGraphBuilder2 * iface,
333 LPOLESTR lpwstrOld,
334 LPOLESTR lpwstrNew,
335 int fAllowEscAbort,
336 IAMCopyCaptureFileProgress *pCallback)
338 CaptureGraphImpl *This = impl_from_ICaptureGraphBuilder2(iface);
340 FIXME("(%p/%p)->(%s, %s, %i, %p) Stub!\n", This, iface,
341 debugstr_w(lpwstrOld), debugstr_w(lpwstrNew),
342 fAllowEscAbort, pCallback);
344 return E_NOTIMPL;
347 static BOOL pin_matches(IPin *pin, PIN_DIRECTION direction, const GUID *cat, const GUID *type, BOOL unconnected)
349 IPin *partner;
350 PIN_DIRECTION pindir;
352 IPin_QueryDirection(pin, &pindir);
353 if (pindir != direction)
355 TRACE("No match, wrong direction\n");
356 return FALSE;
359 if (unconnected && IPin_ConnectedTo(pin, &partner) == S_OK)
361 IPin_Release(partner);
362 TRACE("No match, %p already connected to %p\n", pin, partner);
363 return FALSE;
366 if (cat || type)
367 FIXME("Ignoring category/type\n");
369 TRACE("Match made in heaven\n");
371 return TRUE;
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)
384 HRESULT hr;
385 IEnumPins *enumpins = NULL;
386 IPin *pin;
387 CaptureGraphImpl *This = impl_from_ICaptureGraphBuilder2(iface);
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);
393 pin = NULL;
395 hr = IUnknown_QueryInterface(pSource, &IID_IPin, (void**)&pin);
396 if (hr == E_NOINTERFACE)
398 IBaseFilter *filter = NULL;
399 int numcurrent = 0;
401 hr = IUnknown_QueryInterface(pSource, &IID_IBaseFilter, (void**)&filter);
402 if (hr == E_NOINTERFACE)
404 WARN("Input not filter or pin?!\n");
405 return E_FAIL;
408 hr = IBaseFilter_EnumPins(filter, &enumpins);
409 if (FAILED(hr))
411 WARN("Could not enumerate\n");
412 return hr;
415 IEnumPins_Reset(enumpins);
417 while (1)
419 hr = IEnumPins_Next(enumpins, 1, &pin, NULL);
420 if (hr == VFW_E_ENUM_OUT_OF_SYNC)
422 numcurrent = 0;
423 IEnumPins_Reset(enumpins);
424 pin = NULL;
425 continue;
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;
436 IEnumPins_Release(enumpins);
438 if (hr != S_OK)
440 WARN("Could not find %s pin # %d\n", (pindir == PINDIR_OUTPUT ? "output" : "input"), numcurrent);
441 return E_FAIL;
444 else if (!pin_matches(pin, pindir, pCategory, pType, fUnconnected))
446 IPin_Release(pin);
447 return E_FAIL;
450 *ppPin = pin;
451 return S_OK;
454 static const ICaptureGraphBuilder2Vtbl builder2_Vtbl =
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
471 static HRESULT WINAPI
472 fnCaptureGraphBuilder_QueryInterface(ICaptureGraphBuilder * iface,
473 REFIID riid, LPVOID * ppv)
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);
480 static ULONG WINAPI
481 fnCaptureGraphBuilder_AddRef(ICaptureGraphBuilder * iface)
483 CaptureGraphImpl *This = impl_from_ICaptureGraphBuilder(iface);
484 TRACE("%p --> Forwarding to v2 (%p)\n", iface, This);
485 return IUnknown_AddRef(&This->ICaptureGraphBuilder2_iface);
488 static ULONG WINAPI
489 fnCaptureGraphBuilder_Release(ICaptureGraphBuilder * iface)
491 CaptureGraphImpl *This = impl_from_ICaptureGraphBuilder(iface);
492 TRACE("%p --> Forwarding to v2 (%p)\n", iface, This);
493 return IUnknown_Release(&This->ICaptureGraphBuilder2_iface);
496 static HRESULT WINAPI
497 fnCaptureGraphBuilder_SetFiltergraph(ICaptureGraphBuilder * iface,
498 IGraphBuilder *pfg)
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);
505 static HRESULT WINAPI
506 fnCaptureGraphBuilder_GetFiltergraph(ICaptureGraphBuilder * iface,
507 IGraphBuilder **pfg)
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);
514 static HRESULT WINAPI
515 fnCaptureGraphBuilder_SetOutputFileName(ICaptureGraphBuilder * iface,
516 const GUID *pType, LPCOLESTR lpstrFile,
517 IBaseFilter **ppf, IFileSinkFilter **ppSink)
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);
525 static HRESULT WINAPI
526 fnCaptureGraphBuilder_FindInterface(ICaptureGraphBuilder * iface,
527 const GUID *pCategory, IBaseFilter *pf,
528 REFIID riid, void **ppint)
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);
536 static HRESULT WINAPI
537 fnCaptureGraphBuilder_RenderStream(ICaptureGraphBuilder * iface,
538 const GUID *pCategory, IUnknown *pSource,
539 IBaseFilter *pfCompressor, IBaseFilter *pfRenderer)
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);
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)
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);
559 static HRESULT WINAPI
560 fnCaptureGraphBuilder_AllocCapFile(ICaptureGraphBuilder * iface,
561 LPCOLESTR lpstr, DWORDLONG dwlSize)
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);
568 static HRESULT WINAPI
569 fnCaptureGraphBuilder_CopyCaptureFile(ICaptureGraphBuilder * iface,
570 LPOLESTR lpwstrOld, LPOLESTR lpwstrNew,
571 int fAllowEscAbort,
572 IAMCopyCaptureFileProgress *pCallback)
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);
580 static const ICaptureGraphBuilderVtbl builder_Vtbl =
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