ReactOS  0.4.15-dev-1177-g6cb3b62
capturegraph.c
Go to the documentation of this file.
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 
27 #include "windef.h"
28 #include "winbase.h"
29 #include "wingdi.h"
30 #include "winerror.h"
31 #include "objbase.h"
32 
33 #include "evcode.h"
34 #include "strmif.h"
35 #include "control.h"
36 #include "vfwmsgs.h"
37 /*
38  *#include "amvideo.h"
39  *#include "mmreg.h"
40  *#include "dshow.h"
41  *#include "ddraw.h"
42  */
43 #include "uuids.h"
44 #include "qcap_main.h"
45 
46 #include "wine/unicode.h"
47 #include "wine/debug.h"
48 
50 
51 /***********************************************************************
52 * ICaptureGraphBuilder & ICaptureGraphBuilder2 implementation
53 */
54 typedef struct CaptureGraphImpl
55 {
62 
63 static const ICaptureGraphBuilderVtbl builder_Vtbl;
64 static const ICaptureGraphBuilder2Vtbl builder2_Vtbl;
65 
67 {
68  return CONTAINING_RECORD(iface, CaptureGraphImpl, ICaptureGraphBuilder_iface);
69 }
70 
72 {
73  return CONTAINING_RECORD(iface, CaptureGraphImpl, ICaptureGraphBuilder2_iface);
74 }
75 
76 
78  HRESULT *phr)
79 {
80  CaptureGraphImpl * pCapture = NULL;
81 
82  TRACE("(%p, %p)\n", pUnkOuter, phr);
83 
84  *phr = CLASS_E_NOAGGREGATION;
85  if (pUnkOuter)
86  {
87  return NULL;
88  }
89  *phr = E_OUTOFMEMORY;
90 
91  pCapture = CoTaskMemAlloc(sizeof(CaptureGraphImpl));
92  if (pCapture)
93  {
94  pCapture->ICaptureGraphBuilder2_iface.lpVtbl = &builder2_Vtbl;
95  pCapture->ICaptureGraphBuilder_iface.lpVtbl = &builder_Vtbl;
96  pCapture->ref = 1;
97  pCapture->mygraph = NULL;
99  pCapture->csFilter.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": CaptureGraphImpl.csFilter");
100  *phr = S_OK;
102  }
103  return (IUnknown *)&pCapture->ICaptureGraphBuilder_iface;
104 }
105 
106 static HRESULT WINAPI
108  REFIID riid,
109  LPVOID * ppv)
110 {
112 
113  TRACE("(%p/%p)->(%s, %p)\n", This, iface, debugstr_guid(riid), ppv);
114 
115  *ppv = NULL;
117  *ppv = &This->ICaptureGraphBuilder2_iface;
118  else if (IsEqualIID(riid, &IID_ICaptureGraphBuilder))
119  *ppv = &This->ICaptureGraphBuilder_iface;
120  else if (IsEqualIID(riid, &IID_ICaptureGraphBuilder2))
121  *ppv = &This->ICaptureGraphBuilder2_iface;
122 
123  if (*ppv)
124  {
125  IUnknown_AddRef((IUnknown *)(*ppv));
126  TRACE ("-- Interface = %p\n", *ppv);
127  return S_OK;
128  }
129 
130  TRACE ("-- Interface: E_NOINTERFACE\n");
131  return E_NOINTERFACE;
132 }
133 
134 static ULONG WINAPI
136 {
139 
140  TRACE("(%p/%p)->() AddRef from %d\n", This, iface, ref - 1);
141  return ref;
142 }
143 
145 {
148 
149  TRACE("(%p/%p)->() Release from %d\n", This, iface, ref + 1);
150 
151  if (!ref)
152  {
153  This->csFilter.DebugInfo->Spare[0] = 0;
154  DeleteCriticalSection(&This->csFilter);
155  if (This->mygraph)
156  IGraphBuilder_Release(This->mygraph);
159  }
160  return ref;
161 }
162 
163 static HRESULT WINAPI
165  IGraphBuilder *pfg)
166 {
167 /* The graph builder will automatically create a filter graph if you don't call
168  this method. If you call this method after the graph builder has created its
169  own filter graph, the call will fail. */
170  IMediaEvent *pmev;
172 
173  TRACE("(%p/%p)->(%p)\n", This, iface, pfg);
174 
175  if (This->mygraph)
176  return E_UNEXPECTED;
177 
178  if (!pfg)
179  return E_POINTER;
180 
181  This->mygraph = pfg;
182  IGraphBuilder_AddRef(This->mygraph);
183  if (SUCCEEDED(IGraphBuilder_QueryInterface(This->mygraph,
184  &IID_IMediaEvent, (LPVOID *)&pmev)))
185  {
186  IMediaEvent_CancelDefaultHandling(pmev, EC_REPAINT);
187  IMediaEvent_Release(pmev);
188  }
189  return S_OK;
190 }
191 
192 static HRESULT WINAPI
194  IGraphBuilder **pfg)
195 {
197 
198  TRACE("(%p/%p)->(%p)\n", This, iface, pfg);
199 
200  if (!pfg)
201  return E_POINTER;
202 
203  *pfg = This->mygraph;
204  if (!This->mygraph)
205  {
206  TRACE("(%p) Getting NULL filtergraph\n", iface);
207  return E_UNEXPECTED;
208  }
209 
210  IGraphBuilder_AddRef(This->mygraph);
211 
212  TRACE("(%p) return filtergraph %p\n", iface, *pfg);
213  return S_OK;
214 }
215 
216 static HRESULT WINAPI
218  const GUID *pType,
219  LPCOLESTR lpstrFile,
220  IBaseFilter **ppf,
221  IFileSinkFilter **ppSink)
222 {
224 
225  FIXME("(%p/%p)->(%s, %s, %p, %p) Stub!\n", This, iface,
226  debugstr_guid(pType), debugstr_w(lpstrFile), ppf, ppSink);
227 
228  return E_NOTIMPL;
229 }
230 
231 static HRESULT WINAPI
233  const GUID *pCategory,
234  const GUID *pType,
235  IBaseFilter *pf,
236  REFIID riid,
237  void **ppint)
238 {
240 
241  FIXME("(%p/%p)->(%s, %s, %p, %s, %p) - workaround stub!\n", This, iface,
242  debugstr_guid(pCategory), debugstr_guid(pType),
243  pf, debugstr_guid(riid), ppint);
244 
245  return IBaseFilter_QueryInterface(pf, riid, ppint);
246  /* Looks for the specified interface on the filter, upstream and
247  * downstream from the filter, and, optionally, only on the output
248  * pin of the given category.
249  */
250 }
251 
253  const GUID *pCategory,
254  const GUID *pType,
255  IUnknown *pSource,
256  IPin **source_out)
257 {
258  static const WCHAR inputW[] = {'I','n','p','u','t',0};
259  static const WCHAR captureW[] = {'C','a','p','t','u','r','e',0};
260  static const WCHAR previewW[] = {'P','r','e','v','i','e','w',0};
261  IPin *capture = NULL;
262  IPin *preview = NULL;
263  IPin *peer = NULL;
264  IBaseFilter *smartTee = NULL;
265  BOOL needSmartTee = FALSE;
266  HRESULT hr;
267 
268  TRACE("(%p, %s, %s, %p, %p)\n", This, debugstr_guid(pCategory), debugstr_guid(pType), pSource, source_out);
269  hr = ICaptureGraphBuilder2_FindPin(&This->ICaptureGraphBuilder2_iface, pSource,
270  PINDIR_OUTPUT, &PIN_CATEGORY_CAPTURE, pType, FALSE, 0, &capture);
271  if (SUCCEEDED(hr)) {
272  hr = ICaptureGraphBuilder2_FindPin(&This->ICaptureGraphBuilder2_iface, pSource,
273  PINDIR_OUTPUT, &PIN_CATEGORY_PREVIEW, pType, FALSE, 0, &preview);
274  if (FAILED(hr))
275  needSmartTee = TRUE;
276  } else {
277  hr = E_INVALIDARG;
278  goto end;
279  }
280  if (!needSmartTee) {
281  if (IsEqualIID(pCategory, &PIN_CATEGORY_CAPTURE)) {
282  hr = IPin_ConnectedTo(capture, &peer);
283  if (hr == VFW_E_NOT_CONNECTED) {
284  *source_out = capture;
285  IPin_AddRef(*source_out);
286  hr = S_OK;
287  } else
288  hr = E_INVALIDARG;
289  } else {
290  hr = IPin_ConnectedTo(preview, &peer);
291  if (hr == VFW_E_NOT_CONNECTED) {
292  *source_out = preview;
293  IPin_AddRef(*source_out);
294  hr = S_OK;
295  } else
296  hr = E_INVALIDARG;
297  }
298  goto end;
299  }
300  hr = IPin_ConnectedTo(capture, &peer);
301  if (SUCCEEDED(hr)) {
302  PIN_INFO pinInfo;
303  GUID classID;
304  hr = IPin_QueryPinInfo(peer, &pinInfo);
305  if (SUCCEEDED(hr)) {
306  hr = IBaseFilter_GetClassID(pinInfo.pFilter, &classID);
307  if (SUCCEEDED(hr)) {
308  if (IsEqualIID(&classID, &CLSID_SmartTee)) {
309  smartTee = pinInfo.pFilter;
310  IBaseFilter_AddRef(smartTee);
311  }
312  }
313  IBaseFilter_Release(pinInfo.pFilter);
314  }
315  if (!smartTee) {
316  hr = E_INVALIDARG;
317  goto end;
318  }
319  } else if (hr == VFW_E_NOT_CONNECTED) {
320  hr = CoCreateInstance(&CLSID_SmartTee, NULL, CLSCTX_INPROC_SERVER,
321  &IID_IBaseFilter, (LPVOID*)&smartTee);
322  if (SUCCEEDED(hr)) {
323  hr = IGraphBuilder_AddFilter(This->mygraph, smartTee, NULL);
324  if (SUCCEEDED(hr)) {
325  IPin *smartTeeInput = NULL;
326  hr = IBaseFilter_FindPin(smartTee, inputW, &smartTeeInput);
327  if (SUCCEEDED(hr)) {
328  hr = IGraphBuilder_ConnectDirect(This->mygraph, capture, smartTeeInput, NULL);
329  IPin_Release(smartTeeInput);
330  }
331  }
332  }
333  if (FAILED(hr)) {
334  TRACE("adding SmartTee failed with hr=0x%08x\n", hr);
335  hr = E_INVALIDARG;
336  goto end;
337  }
338  } else {
339  hr = E_INVALIDARG;
340  goto end;
341  }
342  if (IsEqualIID(pCategory, &PIN_CATEGORY_CAPTURE))
343  hr = IBaseFilter_FindPin(smartTee, captureW, source_out);
344  else {
345  hr = IBaseFilter_FindPin(smartTee, previewW, source_out);
346  if (SUCCEEDED(hr))
348  }
349 
350 end:
351  if (capture)
352  IPin_Release(capture);
353  if (preview)
354  IPin_Release(preview);
355  if (peer)
356  IPin_Release(peer);
357  if (smartTee)
358  IBaseFilter_Release(smartTee);
359  TRACE("for %s returning hr=0x%08x, *source_out=%p\n", IsEqualIID(pCategory, &PIN_CATEGORY_CAPTURE) ? "capture" : "preview", hr, source_out ? *source_out : 0);
360  return hr;
361 }
362 
364  const GUID *pCategory, const GUID *pType, IUnknown *pSource, IPin **out_pin)
365 {
366  int index = 0;
367  IPin *source_out;
368  HRESULT hr;
369  BOOL usedSmartTeePreviewPin = FALSE;
370 
371  /* depth-first search the graph for the first unconnected pin that matches
372  * the given category and type */
373  for(;;){
374  IPin *nextpin;
375 
376  if (pCategory && (IsEqualIID(pCategory, &PIN_CATEGORY_CAPTURE) || IsEqualIID(pCategory, &PIN_CATEGORY_PREVIEW))){
377  IBaseFilter *sourceFilter = NULL;
378  hr = IUnknown_QueryInterface(pSource, &IID_IBaseFilter, (void**)&sourceFilter);
379  if (SUCCEEDED(hr)) {
380  hr = match_smart_tee_pin(This, pCategory, pType, pSource, &source_out);
381  if (hr == VFW_S_NOPREVIEWPIN)
382  usedSmartTeePreviewPin = TRUE;
383  IBaseFilter_Release(sourceFilter);
384  } else {
385  hr = ICaptureGraphBuilder2_FindPin(&This->ICaptureGraphBuilder2_iface, pSource, PINDIR_OUTPUT, pCategory, pType, FALSE, index, &source_out);
386  }
387  if (FAILED(hr))
388  return E_INVALIDARG;
389  } else {
390  hr = ICaptureGraphBuilder2_FindPin(&This->ICaptureGraphBuilder2_iface, pSource, PINDIR_OUTPUT, pCategory, pType, FALSE, index, &source_out);
391  if (FAILED(hr))
392  return E_INVALIDARG;
393  }
394 
395  hr = IPin_ConnectedTo(source_out, &nextpin);
396  if(SUCCEEDED(hr)){
397  PIN_INFO info;
398 
399  IPin_Release(source_out);
400 
401  hr = IPin_QueryPinInfo(nextpin, &info);
402  if(FAILED(hr) || !info.pFilter){
403  WARN("QueryPinInfo failed: %08x\n", hr);
404  return hr;
405  }
406 
407  hr = find_unconnected_pin(This, pCategory, pType, (IUnknown*)info.pFilter, out_pin);
408 
409  IBaseFilter_Release(info.pFilter);
410 
411  if(SUCCEEDED(hr))
412  return hr;
413  }else{
414  *out_pin = source_out;
415  if(usedSmartTeePreviewPin)
416  return VFW_S_NOPREVIEWPIN;
417  return S_OK;
418  }
419 
420  index++;
421  }
422 }
423 
424 static HRESULT WINAPI
426  const GUID *pCategory,
427  const GUID *pType,
428  IUnknown *pSource,
429  IBaseFilter *pfCompressor,
430  IBaseFilter *pfRenderer)
431 {
433  IPin *source_out = NULL, *renderer_in;
434  BOOL rendererNeedsRelease = FALSE;
435  HRESULT hr, return_hr = S_OK;
436 
437  FIXME("(%p/%p)->(%s, %s, %p, %p, %p) semi-stub!\n", This, iface,
438  debugstr_guid(pCategory), debugstr_guid(pType),
439  pSource, pfCompressor, pfRenderer);
440 
441  if (!This->mygraph)
442  {
443  FIXME("Need a capture graph\n");
444  return E_UNEXPECTED;
445  }
446 
447  if (pCategory && IsEqualIID(pCategory, &PIN_CATEGORY_VBI)) {
448  FIXME("Tee/Sink-to-Sink filter not supported\n");
449  return E_NOTIMPL;
450  }
451 
452  hr = find_unconnected_pin(This, pCategory, pType, pSource, &source_out);
453  if (FAILED(hr))
454  return hr;
455  return_hr = hr;
456 
457  if (!pfRenderer)
458  {
459  IEnumMediaTypes *enumMedia = NULL;
460  hr = IPin_EnumMediaTypes(source_out, &enumMedia);
461  if (SUCCEEDED(hr)) {
462  AM_MEDIA_TYPE *mediaType;
463  hr = IEnumMediaTypes_Next(enumMedia, 1, &mediaType, NULL);
464  if (SUCCEEDED(hr)) {
465  if (IsEqualIID(&mediaType->majortype, &MEDIATYPE_Video)) {
466  hr = CoCreateInstance(&CLSID_VideoRenderer, NULL, CLSCTX_INPROC_SERVER,
467  &IID_IBaseFilter, (void**)&pfRenderer);
468  } else if (IsEqualIID(&mediaType->majortype, &MEDIATYPE_Audio)) {
469  hr = CoCreateInstance(&CLSID_DSoundRender, NULL, CLSCTX_INPROC_SERVER,
470  &IID_IBaseFilter, (void**)&pfRenderer);
471  } else {
472  FIXME("cannot automatically load renderer for majortype %s\n", debugstr_guid(&mediaType->majortype));
473  hr = E_FAIL;
474  }
475  if (SUCCEEDED(hr)) {
476  rendererNeedsRelease = TRUE;
477  hr = IGraphBuilder_AddFilter(This->mygraph, pfRenderer, NULL);
478  }
479  DeleteMediaType(mediaType);
480  }
481  IEnumMediaTypes_Release(enumMedia);
482  }
483  if (FAILED(hr)) {
484  if (rendererNeedsRelease)
485  IBaseFilter_Release(pfRenderer);
486  IPin_Release(source_out);
487  return hr;
488  }
489  }
490 
491  hr = ICaptureGraphBuilder2_FindPin(iface, (IUnknown*)pfRenderer, PINDIR_INPUT, NULL, NULL, TRUE, 0, &renderer_in);
492  if (FAILED(hr))
493  {
494  if (rendererNeedsRelease)
495  IBaseFilter_Release(pfRenderer);
496  IPin_Release(source_out);
497  return hr;
498  }
499 
500  if (!pfCompressor)
501  hr = IGraphBuilder_Connect(This->mygraph, source_out, renderer_in);
502  else
503  {
504  IPin *compressor_in, *compressor_out;
505 
506  hr = ICaptureGraphBuilder2_FindPin(iface, (IUnknown*)pfCompressor,
507  PINDIR_INPUT, NULL, NULL, TRUE, 0, &compressor_in);
508  if (SUCCEEDED(hr))
509  {
510  hr = IGraphBuilder_Connect(This->mygraph, source_out, compressor_in);
511  IPin_Release(compressor_in);
512  }
513 
514  if (SUCCEEDED(hr))
515  {
516  hr = ICaptureGraphBuilder2_FindPin(iface, (IUnknown*)pfCompressor,
517  PINDIR_OUTPUT, NULL, NULL, TRUE, 0, &compressor_out);
518  if (SUCCEEDED(hr))
519  {
520  hr = IGraphBuilder_Connect(This->mygraph, compressor_out, renderer_in);
521  IPin_Release(compressor_out);
522  }
523  }
524  }
525 
526  IPin_Release(source_out);
527  IPin_Release(renderer_in);
528  if (rendererNeedsRelease)
529  IBaseFilter_Release(pfRenderer);
530  if (SUCCEEDED(hr))
531  return return_hr;
532  return hr;
533 }
534 
535 static HRESULT WINAPI
537  const GUID *pCategory,
538  const GUID *pType,
539  IBaseFilter *pFilter,
540  REFERENCE_TIME *pstart,
541  REFERENCE_TIME *pstop,
542  WORD wStartCookie,
543  WORD wStopCookie)
544 {
546 
547  FIXME("(%p/%p)->(%s, %s, %p, %p, %p, %i, %i) Stub!\n", This, iface,
548  debugstr_guid(pCategory), debugstr_guid(pType),
549  pFilter, pstart, pstop, wStartCookie, wStopCookie);
550 
551  return E_NOTIMPL;
552 }
553 
554 static HRESULT WINAPI
556  LPCOLESTR lpwstr,
557  DWORDLONG dwlSize)
558 {
560 
561  FIXME("(%p/%p)->(%s, 0x%s) Stub!\n", This, iface,
562  debugstr_w(lpwstr), wine_dbgstr_longlong(dwlSize));
563 
564  return E_NOTIMPL;
565 }
566 
567 static HRESULT WINAPI
569  LPOLESTR lpwstrOld,
570  LPOLESTR lpwstrNew,
571  int fAllowEscAbort,
572  IAMCopyCaptureFileProgress *pCallback)
573 {
575 
576  FIXME("(%p/%p)->(%s, %s, %i, %p) Stub!\n", This, iface,
577  debugstr_w(lpwstrOld), debugstr_w(lpwstrNew),
578  fAllowEscAbort, pCallback);
579 
580  return E_NOTIMPL;
581 }
582 
583 static HRESULT pin_matches(IPin *pin, PIN_DIRECTION direction, const GUID *cat, const GUID *type, BOOL unconnected)
584 {
585  IPin *partner;
586  PIN_DIRECTION pindir;
587  HRESULT hr;
588 
589  hr = IPin_QueryDirection(pin, &pindir);
590 
591  if (unconnected && IPin_ConnectedTo(pin, &partner) == S_OK && partner!=NULL)
592  {
593  IPin_Release(partner);
594  TRACE("No match, %p already connected to %p\n", pin, partner);
595  return FAILED(hr) ? hr : S_FALSE;
596  }
597 
598  if (FAILED(hr))
599  return hr;
600  if (SUCCEEDED(hr) && pindir != direction)
601  return S_FALSE;
602 
603  if (cat)
604  {
606  GUID category;
607  DWORD fetched;
608 
609  hr = IPin_QueryInterface(pin, &IID_IKsPropertySet, (void**)&props);
610  if (FAILED(hr))
611  return S_FALSE;
612 
613  hr = IKsPropertySet_Get(props, &AMPROPSETID_Pin, 0, NULL,
614  0, &category, sizeof(category), &fetched);
616  if (FAILED(hr) || !IsEqualIID(&category, cat))
617  return S_FALSE;
618  }
619 
620  if (type)
621  {
623  AM_MEDIA_TYPE *media_type;
624  ULONG fetched;
625 
626  hr = IPin_EnumMediaTypes(pin, &types);
627  if (FAILED(hr))
628  return S_FALSE;
629 
630  IEnumMediaTypes_Reset(types);
631  while (1) {
632  if (IEnumMediaTypes_Next(types, 1, &media_type, &fetched) != S_OK || fetched != 1)
633  {
634  IEnumMediaTypes_Release(types);
635  return S_FALSE;
636  }
637 
638  if (IsEqualIID(&media_type->majortype, type))
639  {
640  DeleteMediaType(media_type);
641  break;
642  }
643  DeleteMediaType(media_type);
644  }
645  IEnumMediaTypes_Release(types);
646  }
647 
648  TRACE("Pin matched\n");
649  return S_OK;
650 }
651 
652 static HRESULT WINAPI
654  IUnknown *pSource,
655  PIN_DIRECTION pindir,
656  const GUID *pCategory,
657  const GUID *pType,
658  BOOL fUnconnected,
659  INT num,
660  IPin **ppPin)
661 {
662  HRESULT hr;
663  IEnumPins *enumpins = NULL;
664  IPin *pin;
666 
667  TRACE("(%p/%p)->(%p, %x, %s, %s, %d, %i, %p)\n", This, iface,
668  pSource, pindir, debugstr_guid(pCategory), debugstr_guid(pType),
669  fUnconnected, num, ppPin);
670 
671  pin = NULL;
672 
673  hr = IUnknown_QueryInterface(pSource, &IID_IPin, (void**)&pin);
674  if (hr == E_NOINTERFACE)
675  {
677  int numcurrent = 0;
678 
679  hr = IUnknown_QueryInterface(pSource, &IID_IBaseFilter, (void**)&filter);
680  if (hr == E_NOINTERFACE)
681  {
682  WARN("Input not filter or pin?!\n");
683  return E_NOINTERFACE;
684  }
685 
686  hr = IBaseFilter_EnumPins(filter, &enumpins);
687  if (FAILED(hr))
688  {
689  WARN("Could not enumerate\n");
690  IBaseFilter_Release(filter);
691  return hr;
692  }
693 
694  while (1)
695  {
696  ULONG fetched;
697 
698  hr = IEnumPins_Next(enumpins, 1, &pin, &fetched);
699  if (hr == VFW_E_ENUM_OUT_OF_SYNC)
700  {
701  numcurrent = 0;
702  IEnumPins_Reset(enumpins);
703  pin = NULL;
704  continue;
705  }
706  if (hr != S_OK)
707  break;
708  if (fetched != 1)
709  {
710  hr = E_FAIL;
711  break;
712  }
713 
714  TRACE("Testing match\n");
715  hr = pin_matches(pin, pindir, pCategory, pType, fUnconnected);
716  if (hr == S_OK && numcurrent++ == num)
717  break;
718  IPin_Release(pin);
719  pin = NULL;
720  if (FAILED(hr))
721  break;
722  }
723  IEnumPins_Release(enumpins);
724  IBaseFilter_Release(filter);
725 
726  if (hr != S_OK)
727  {
728  WARN("Could not find %s pin # %d\n", (pindir == PINDIR_OUTPUT ? "output" : "input"), numcurrent);
729  return E_FAIL;
730  }
731  }
732  else if (pin_matches(pin, pindir, pCategory, pType, fUnconnected) != S_OK)
733  {
734  IPin_Release(pin);
735  return E_FAIL;
736  }
737 
738  *ppPin = pin;
739  return S_OK;
740 }
741 
742 static const ICaptureGraphBuilder2Vtbl builder2_Vtbl =
743 {
756 };
757 
758 
759 static HRESULT WINAPI
761  REFIID riid, LPVOID * ppv)
762 {
764  TRACE("%p --> Forwarding to v2 (%p)\n", iface, This);
765  return ICaptureGraphBuilder2_QueryInterface(&This->ICaptureGraphBuilder2_iface, riid, ppv);
766 }
767 
768 static ULONG WINAPI
770 {
772  TRACE("%p --> Forwarding to v2 (%p)\n", iface, This);
773  return ICaptureGraphBuilder2_AddRef(&This->ICaptureGraphBuilder2_iface);
774 }
775 
776 static ULONG WINAPI
778 {
780  TRACE("%p --> Forwarding to v2 (%p)\n", iface, This);
781  return ICaptureGraphBuilder2_Release(&This->ICaptureGraphBuilder2_iface);
782 }
783 
784 static HRESULT WINAPI
786  IGraphBuilder *pfg)
787 {
789  TRACE("%p --> Forwarding to v2 (%p)\n", iface, This);
790  return ICaptureGraphBuilder2_SetFiltergraph(&This->ICaptureGraphBuilder2_iface, pfg);
791 }
792 
793 static HRESULT WINAPI
795  IGraphBuilder **pfg)
796 {
798  TRACE("%p --> Forwarding to v2 (%p)\n", iface, This);
799  return ICaptureGraphBuilder2_GetFiltergraph(&This->ICaptureGraphBuilder2_iface, pfg);
800 }
801 
802 static HRESULT WINAPI
804  const GUID *pType, LPCOLESTR lpstrFile,
805  IBaseFilter **ppf, IFileSinkFilter **ppSink)
806 {
808  TRACE("%p --> Forwarding to v2 (%p)\n", iface, This);
809  return ICaptureGraphBuilder2_SetOutputFileName(&This->ICaptureGraphBuilder2_iface, pType,
810  lpstrFile, ppf, ppSink);
811 }
812 
813 static HRESULT WINAPI
815  const GUID *pCategory, IBaseFilter *pf,
816  REFIID riid, void **ppint)
817 {
819  TRACE("%p --> Forwarding to v2 (%p)\n", iface, This);
820  return ICaptureGraphBuilder2_FindInterface(&This->ICaptureGraphBuilder2_iface, pCategory, NULL,
821  pf, riid, ppint);
822 }
823 
824 static HRESULT WINAPI
826  const GUID *pCategory, IUnknown *pSource,
827  IBaseFilter *pfCompressor, IBaseFilter *pfRenderer)
828 {
830  TRACE("%p --> Forwarding to v2 (%p)\n", iface, This);
831  return ICaptureGraphBuilder2_RenderStream(&This->ICaptureGraphBuilder2_iface, pCategory, NULL,
832  pSource, pfCompressor, pfRenderer);
833 }
834 
835 static HRESULT WINAPI
837  const GUID *pCategory, IBaseFilter *pFilter,
838  REFERENCE_TIME *pstart, REFERENCE_TIME *pstop,
839  WORD wStartCookie, WORD wStopCookie)
840 {
842  TRACE("%p --> Forwarding to v2 (%p)\n", iface, This);
843  return ICaptureGraphBuilder2_ControlStream(&This->ICaptureGraphBuilder2_iface, pCategory, NULL,
844  pFilter, pstart, pstop, wStartCookie, wStopCookie);
845 }
846 
847 static HRESULT WINAPI
849  LPCOLESTR lpstr, DWORDLONG dwlSize)
850 {
852  TRACE("%p --> Forwarding to v2 (%p)\n", iface, This);
853  return ICaptureGraphBuilder2_AllocCapFile(&This->ICaptureGraphBuilder2_iface, lpstr, dwlSize);
854 }
855 
856 static HRESULT WINAPI
858  LPOLESTR lpwstrOld, LPOLESTR lpwstrNew,
859  int fAllowEscAbort,
860  IAMCopyCaptureFileProgress *pCallback)
861 {
863  TRACE("%p --> Forwarding to v2 (%p)\n", iface, This);
864  return ICaptureGraphBuilder2_CopyCaptureFile(&This->ICaptureGraphBuilder2_iface, lpwstrOld,
865  lpwstrNew, fAllowEscAbort, pCallback);
866 }
867 
868 static const ICaptureGraphBuilderVtbl builder_Vtbl =
869 {
881 };
const GUID IID_IBaseFilter
static HRESULT pin_matches(IPin *pin, PIN_DIRECTION direction, const GUID *cat, const GUID *type, BOOL unconnected)
Definition: capturegraph.c:583
static ULONG WINAPI fnCaptureGraphBuilder2_Release(ICaptureGraphBuilder2 *iface)
Definition: capturegraph.c:144
#define REFIID
Definition: guiddef.h:118
#define E_NOINTERFACE
Definition: winerror.h:2364
static HRESULT match_smart_tee_pin(CaptureGraphImpl *This, const GUID *pCategory, const GUID *pType, IUnknown *pSource, IPin **source_out)
Definition: capturegraph.c:252
VOID WINAPI CoTaskMemFree(LPVOID ptr)
Definition: ifs.c:442
#define DWORD_PTR
Definition: treelist.c:76
#define IKsPropertySet_Release(p)
Definition: dsound.h:1150
HRESULT hr
Definition: shlfolder.c:183
ICaptureGraphBuilder ICaptureGraphBuilder_iface
Definition: capturegraph.c:57
#define TRUE
Definition: types.h:120
REFIID riid
Definition: precomp.h:44
static HRESULT WINAPI fnCaptureGraphBuilder_ControlStream(ICaptureGraphBuilder *iface, const GUID *pCategory, IBaseFilter *pFilter, REFERENCE_TIME *pstart, REFERENCE_TIME *pstop, WORD wStartCookie, WORD wStopCookie)
Definition: capturegraph.c:836
#define WARN(fmt,...)
Definition: debug.h:112
static CaptureGraphImpl * impl_from_ICaptureGraphBuilder2(ICaptureGraphBuilder2 *iface)
Definition: capturegraph.c:71
static ULONG WINAPI fnCaptureGraphBuilder_Release(ICaptureGraphBuilder *iface)
Definition: capturegraph.c:777
GLsizei GLenum GLenum * types
Definition: glext.h:7753
#define CALLBACK
Definition: compat.h:35
REFIID LPVOID * ppv
Definition: atlbase.h:39
GLuint GLuint GLsizei GLenum type
Definition: gl.h:1545
static CaptureGraphImpl * impl_from_ICaptureGraphBuilder(ICaptureGraphBuilder *iface)
Definition: capturegraph.c:66
static HRESULT WINAPI fnCaptureGraphBuilder2_CopyCaptureFile(ICaptureGraphBuilder2 *iface, LPOLESTR lpwstrOld, LPOLESTR lpwstrNew, int fAllowEscAbort, IAMCopyCaptureFileProgress *pCallback)
Definition: capturegraph.c:568
GLuint GLuint end
Definition: gl.h:1545
static ULONG WINAPI fnCaptureGraphBuilder2_AddRef(ICaptureGraphBuilder2 *iface)
Definition: capturegraph.c:135
static LPOLESTR
Definition: stg_prop.c:27
#define E_FAIL
Definition: ddrawi.h:102
int32_t INT
Definition: typedefs.h:58
Definition: send.c:48
static HRESULT WINAPI fnCaptureGraphBuilder_AllocCapFile(ICaptureGraphBuilder *iface, LPCOLESTR lpstr, DWORDLONG dwlSize)
Definition: capturegraph.c:848
static ULONG WINAPI fnCaptureGraphBuilder_AddRef(ICaptureGraphBuilder *iface)
Definition: capturegraph.c:769
struct _test_info info[]
Definition: SetCursorPos.c:19
Definition: regsvr.c:103
static void DeleteMediaType(AM_MEDIA_TYPE *pMediaType)
Definition: filtergraph.c:741
struct CaptureGraphImpl CaptureGraphImpl
static HRESULT WINAPI fnCaptureGraphBuilder_SetOutputFileName(ICaptureGraphBuilder *iface, const GUID *pType, LPCOLESTR lpstrFile, IBaseFilter **ppf, IFileSinkFilter **ppSink)
Definition: capturegraph.c:803
#define E_OUTOFMEMORY
Definition: ddrawi.h:100
#define FALSE
Definition: types.h:117
unsigned int BOOL
Definition: ntddk_ex.h:94
long LONG
Definition: pedump.c:60
static const WCHAR inputW[]
Definition: htmlelem.c:31
CRITICAL_SECTION csFilter
Definition: capturegraph.c:60
#define debugstr_w
Definition: kernel32.h:32
GLenum GLint ref
Definition: glext.h:6028
#define FIXME(fmt,...)
Definition: debug.h:111
#define S_FALSE
Definition: winerror.h:2357
#define E_INVALIDARG
Definition: ddrawi.h:101
ICaptureGraphBuilder2 ICaptureGraphBuilder2_iface
Definition: capturegraph.c:56
static HRESULT WINAPI fnCaptureGraphBuilder2_QueryInterface(ICaptureGraphBuilder2 *iface, REFIID riid, LPVOID *ppv)
Definition: capturegraph.c:107
static HRESULT WINAPI fnCaptureGraphBuilder2_FindPin(ICaptureGraphBuilder2 *iface, IUnknown *pSource, PIN_DIRECTION pindir, const GUID *pCategory, const GUID *pType, BOOL fUnconnected, INT num, IPin **ppPin)
Definition: capturegraph.c:653
VOID WINAPI InitializeCriticalSection(OUT LPCRITICAL_SECTION lpCriticalSection)
Definition: synch.c:751
smooth NULL
Definition: ftsmooth.c:416
GLuint index
Definition: glext.h:6031
static HRESULT WINAPI fnCaptureGraphBuilder_CopyCaptureFile(ICaptureGraphBuilder *iface, LPOLESTR lpwstrOld, LPOLESTR lpwstrNew, int fAllowEscAbort, IAMCopyCaptureFileProgress *pCallback)
Definition: capturegraph.c:857
#define VFW_E_NOT_CONNECTED
Definition: vfwmsgs.h:48
#define debugstr_guid
Definition: kernel32.h:35
PFLT_MESSAGE_WAITER_QUEUE CONTAINING_RECORD(Csq, DEVICE_EXTENSION, IrpQueue)) -> WaiterQ.mLock) _IRQL_raises_(DISPATCH_LEVEL) VOID NTAPI FltpAcquireMessageWaiterLock(_In_ PIO_CSQ Csq, _Out_ PKIRQL Irql)
Definition: Messaging.c:560
static HRESULT WINAPI fnCaptureGraphBuilder_GetFiltergraph(ICaptureGraphBuilder *iface, IGraphBuilder **pfg)
Definition: capturegraph.c:794
#define TRACE(s)
Definition: solgame.cpp:4
static HRESULT WINAPI fnCaptureGraphBuilder2_SetFilterGraph(ICaptureGraphBuilder2 *iface, IGraphBuilder *pfg)
Definition: capturegraph.c:164
LONGLONG REFERENCE_TIME
Definition: dmusicks.h:9
Definition: cmds.c:130
__wchar_t WCHAR
Definition: xmlstorage.h:180
void WINAPI DeleteCriticalSection(PCRITICAL_SECTION)
WINE_DEFAULT_DEBUG_CHANNEL(qcap)
LONG HRESULT
Definition: typedefs.h:79
static HRESULT WINAPI fnCaptureGraphBuilder_FindInterface(ICaptureGraphBuilder *iface, const GUID *pCategory, IBaseFilter *pf, REFIID riid, void **ppint)
Definition: capturegraph.c:814
const GUID IID_IUnknown
#define WINAPI
Definition: msvc.h:6
unsigned short WORD
Definition: ntddk_ex.h:93
unsigned long DWORD
Definition: ntddk_ex.h:95
GLuint GLuint num
Definition: glext.h:9618
static HRESULT WINAPI fnCaptureGraphBuilder2_SetOutputFileName(ICaptureGraphBuilder2 *iface, const GUID *pType, LPCOLESTR lpstrFile, IBaseFilter **ppf, IFileSinkFilter **ppSink)
Definition: capturegraph.c:217
PCRITICAL_SECTION_DEBUG DebugInfo
Definition: winbase.h:872
static const ICaptureGraphBuilder2Vtbl builder2_Vtbl
Definition: capturegraph.c:64
#define VFW_S_NOPREVIEWPIN
Definition: vfwmsgs.h:35
IUnknown *CALLBACK QCAP_createCaptureGraphBuilder2(IUnknown *pUnkOuter, HRESULT *phr)
Definition: capturegraph.c:77
#define InterlockedDecrement
Definition: armddk.h:52
static HRESULT WINAPI fnCaptureGraphBuilder2_FindInterface(ICaptureGraphBuilder2 *iface, const GUID *pCategory, const GUID *pType, IBaseFilter *pf, REFIID riid, void **ppint)
Definition: capturegraph.c:232
#define CLASS_E_NOAGGREGATION
Definition: winerror.h:2662
const GUID IID_IKsPropertySet
Definition: controlnode.cpp:13
HRESULT WINAPI DECLSPEC_HOTPATCH CoCreateInstance(REFCLSID rclsid, LPUNKNOWN pUnkOuter, DWORD dwClsContext, REFIID iid, LPVOID *ppv)
Definition: compobj.c:3325
static HRESULT WINAPI fnCaptureGraphBuilder2_RenderStream(ICaptureGraphBuilder2 *iface, const GUID *pCategory, const GUID *pType, IUnknown *pSource, IBaseFilter *pfCompressor, IBaseFilter *pfRenderer)
Definition: capturegraph.c:425
#define IKsPropertySet_Get(p, a, b, c, d, e, f, g)
Definition: dsound.h:1152
#define S_OK
Definition: intsafe.h:51
#define InterlockedIncrement
Definition: armddk.h:53
static HRESULT WINAPI fnCaptureGraphBuilder2_AllocCapFile(ICaptureGraphBuilder2 *iface, LPCOLESTR lpwstr, DWORDLONG dwlSize)
Definition: capturegraph.c:555
DWORD ObjectRefCount(BOOL increment)
Definition: qcap_main.c:193
static previewinfo preview
Definition: print.c:56
#define VFW_E_ENUM_OUT_OF_SYNC
Definition: vfwmsgs.h:42
Definition: axcore.idl:91
static HRESULT WINAPI fnCaptureGraphBuilder_QueryInterface(ICaptureGraphBuilder *iface, REFIID riid, LPVOID *ppv)
Definition: capturegraph.c:760
#define E_NOTIMPL
Definition: ddrawi.h:99
#define EC_REPAINT
Definition: evcode.h:36
static const ICaptureGraphBuilderVtbl builder_Vtbl
Definition: capturegraph.c:63
enum _PinDirection PIN_DIRECTION
static HRESULT WINAPI fnCaptureGraphBuilder2_ControlStream(ICaptureGraphBuilder2 *iface, const GUID *pCategory, const GUID *pType, IBaseFilter *pFilter, REFERENCE_TIME *pstart, REFERENCE_TIME *pstop, WORD wStartCookie, WORD wStopCookie)
Definition: capturegraph.c:536
#define E_UNEXPECTED
Definition: winerror.h:2456
unsigned long long DWORDLONG
Definition: intsafe.h:91
static const WCHAR props[]
Definition: wbemdisp.c:288
unsigned int ULONG
Definition: retypes.h:1
static __inline const char * wine_dbgstr_longlong(ULONGLONG ll)
Definition: compat.h:49
static LPCSTR lpstr
Definition: font.c:51
#define E_POINTER
Definition: winerror.h:2365
IGraphBuilder * mygraph
Definition: capturegraph.c:59
const GUID IID_IPin
Definition: pincontrol.cpp:15
LPVOID WINAPI CoTaskMemAlloc(SIZE_T size)
Definition: ifs.c:426
GLint GLint GLint GLint GLint GLint GLint GLbitfield GLenum filter
Definition: glext.h:7005
static HRESULT WINAPI fnCaptureGraphBuilder2_GetFilterGraph(ICaptureGraphBuilder2 *iface, IGraphBuilder **pfg)
Definition: capturegraph.c:193
static HRESULT WINAPI fnCaptureGraphBuilder_SetFiltergraph(ICaptureGraphBuilder *iface, IGraphBuilder *pfg)
Definition: capturegraph.c:785
static HRESULT find_unconnected_pin(CaptureGraphImpl *This, const GUID *pCategory, const GUID *pType, IUnknown *pSource, IPin **out_pin)
Definition: capturegraph.c:363
#define IsEqualIID(riid1, riid2)
Definition: guiddef.h:95
#define SUCCEEDED(hr)
Definition: intsafe.h:49
DWORD_PTR Spare[8/sizeof(DWORD_PTR)]
Definition: winbase.h:865
static HRESULT WINAPI fnCaptureGraphBuilder_RenderStream(ICaptureGraphBuilder *iface, const GUID *pCategory, IUnknown *pSource, IBaseFilter *pfCompressor, IBaseFilter *pfRenderer)
Definition: capturegraph.c:825