2 * Implementation of the SmartTee filter
4 * Copyright 2015 Damjan Jovanovic
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
32 #include "qcap_main.h"
34 #include "wine/debug.h"
36 WINE_DEFAULT_DEBUG_CHANNEL(qcap
);
39 IUnknown IUnknown_iface
;
40 IUnknown
*outerUnknown
;
43 BaseOutputPin
*capture
;
44 BaseOutputPin
*preview
;
47 static inline SmartTeeFilter
*impl_from_IUnknown(IUnknown
*iface
)
49 return CONTAINING_RECORD(iface
, SmartTeeFilter
, IUnknown_iface
);
52 static inline SmartTeeFilter
*impl_from_BaseFilter(BaseFilter
*filter
)
54 return CONTAINING_RECORD(filter
, SmartTeeFilter
, filter
);
57 static inline SmartTeeFilter
*impl_from_IBaseFilter(IBaseFilter
*iface
)
59 BaseFilter
*filter
= CONTAINING_RECORD(iface
, BaseFilter
, IBaseFilter_iface
);
60 return impl_from_BaseFilter(filter
);
63 static inline SmartTeeFilter
*impl_from_BasePin(BasePin
*pin
)
65 return impl_from_IBaseFilter(pin
->pinInfo
.pFilter
);
68 static inline SmartTeeFilter
*impl_from_IPin(IPin
*iface
)
70 BasePin
*bp
= CONTAINING_RECORD(iface
, BasePin
, IPin_iface
);
71 return impl_from_IBaseFilter(bp
->pinInfo
.pFilter
);
74 static HRESULT WINAPI
Unknown_QueryInterface(IUnknown
*iface
, REFIID riid
, void **ppv
)
76 SmartTeeFilter
*This
= impl_from_IUnknown(iface
);
77 if (IsEqualIID(riid
, &IID_IUnknown
)) {
78 TRACE("(%p)->(IID_IUnknown, %p)\n", This
, ppv
);
79 *ppv
= &This
->IUnknown_iface
;
80 } else if (IsEqualIID(riid
, &IID_IPersist
)) {
81 TRACE("(%p)->(IID_IPersist, %p)\n", This
, ppv
);
82 *ppv
= &This
->filter
.IBaseFilter_iface
;
83 } else if (IsEqualIID(riid
, &IID_IMediaFilter
)) {
84 TRACE("(%p)->(IID_IMediaFilter, %p)\n", This
, ppv
);
85 *ppv
= &This
->filter
.IBaseFilter_iface
;
86 } else if (IsEqualIID(riid
, &IID_IBaseFilter
)) {
87 TRACE("(%p)->(IID_IBaseFilter, %p)\n", This
, ppv
);
88 *ppv
= &This
->filter
.IBaseFilter_iface
;
90 FIXME("(%p): no interface for %s\n", This
, debugstr_guid(riid
));
94 IUnknown_AddRef((IUnknown
*)*ppv
);
98 static ULONG WINAPI
Unknown_AddRef(IUnknown
*iface
)
100 SmartTeeFilter
*This
= impl_from_IUnknown(iface
);
101 return BaseFilterImpl_AddRef(&This
->filter
.IBaseFilter_iface
);
104 static ULONG WINAPI
Unknown_Release(IUnknown
*iface
)
106 SmartTeeFilter
*This
= impl_from_IUnknown(iface
);
107 ULONG ref
= BaseFilterImpl_Release(&This
->filter
.IBaseFilter_iface
);
109 TRACE("(%p)->() ref=%d\n", This
, ref
);
113 BaseInputPinImpl_Release(&This
->input
->pin
.IPin_iface
);
115 BaseOutputPinImpl_Release(&This
->capture
->pin
.IPin_iface
);
117 BaseOutputPinImpl_Release(&This
->preview
->pin
.IPin_iface
);
123 static const IUnknownVtbl UnknownVtbl
= {
124 Unknown_QueryInterface
,
129 static HRESULT WINAPI
SmartTeeFilter_QueryInterface(IBaseFilter
*iface
, REFIID riid
, void **ppv
)
131 SmartTeeFilter
*This
= impl_from_IBaseFilter(iface
);
132 return IUnknown_QueryInterface(This
->outerUnknown
, riid
, ppv
);
135 static ULONG WINAPI
SmartTeeFilter_AddRef(IBaseFilter
*iface
)
137 SmartTeeFilter
*This
= impl_from_IBaseFilter(iface
);
138 return IUnknown_AddRef(This
->outerUnknown
);
141 static ULONG WINAPI
SmartTeeFilter_Release(IBaseFilter
*iface
)
143 SmartTeeFilter
*This
= impl_from_IBaseFilter(iface
);
144 return IUnknown_Release(This
->outerUnknown
);
147 static HRESULT WINAPI
SmartTeeFilter_Stop(IBaseFilter
*iface
)
149 SmartTeeFilter
*This
= impl_from_IBaseFilter(iface
);
150 FIXME("(%p): stub\n", This
);
154 static HRESULT WINAPI
SmartTeeFilter_Pause(IBaseFilter
*iface
)
156 SmartTeeFilter
*This
= impl_from_IBaseFilter(iface
);
157 FIXME("(%p): stub\n", This
);
161 static HRESULT WINAPI
SmartTeeFilter_Run(IBaseFilter
*iface
, REFERENCE_TIME tStart
)
163 FIXME("(%p, %x%08x): stub\n", iface
, (ULONG
)(tStart
>> 32), (ULONG
)tStart
);
167 static HRESULT WINAPI
SmartTeeFilter_FindPin(IBaseFilter
*iface
, LPCWSTR Id
, IPin
**ppPin
)
169 SmartTeeFilter
*This
= impl_from_IBaseFilter(iface
);
170 FIXME("(%p)->(%s, %p): stub\n", This
, debugstr_w(Id
), ppPin
);
171 return VFW_E_NOT_FOUND
;
174 static const IBaseFilterVtbl SmartTeeFilterVtbl
= {
175 SmartTeeFilter_QueryInterface
,
176 SmartTeeFilter_AddRef
,
177 SmartTeeFilter_Release
,
178 BaseFilterImpl_GetClassID
,
180 SmartTeeFilter_Pause
,
182 BaseFilterImpl_GetState
,
183 BaseFilterImpl_SetSyncSource
,
184 BaseFilterImpl_GetSyncSource
,
185 BaseFilterImpl_EnumPins
,
186 SmartTeeFilter_FindPin
,
187 BaseFilterImpl_QueryFilterInfo
,
188 BaseFilterImpl_JoinFilterGraph
,
189 BaseFilterImpl_QueryVendorInfo
192 static IPin
* WINAPI
SmartTeeFilter_GetPin(BaseFilter
*iface
, int pos
)
194 SmartTeeFilter
*This
= impl_from_BaseFilter(iface
);
197 TRACE("(%p)->(%d)\n", This
, pos
);
201 ret
= &This
->input
->pin
.IPin_iface
;
204 ret
= &This
->capture
->pin
.IPin_iface
;
207 ret
= &This
->preview
->pin
.IPin_iface
;
210 TRACE("No pin %d\n", pos
);
218 static LONG WINAPI
SmartTeeFilter_GetPinCount(BaseFilter
*iface
)
222 static const BaseFilterFuncTable SmartTeeFilterFuncs
= {
223 SmartTeeFilter_GetPin
,
224 SmartTeeFilter_GetPinCount
227 static ULONG WINAPI
SmartTeeFilterInput_AddRef(IPin
*iface
)
229 SmartTeeFilter
*This
= impl_from_IPin(iface
);
230 return IBaseFilter_AddRef(&This
->filter
.IBaseFilter_iface
);
233 static ULONG WINAPI
SmartTeeFilterInput_Release(IPin
*iface
)
235 SmartTeeFilter
*This
= impl_from_IPin(iface
);
236 return IBaseFilter_Release(&This
->filter
.IBaseFilter_iface
);
240 static const IPinVtbl SmartTeeFilterInputVtbl
= {
241 BaseInputPinImpl_QueryInterface
,
242 SmartTeeFilterInput_AddRef
,
243 SmartTeeFilterInput_Release
,
244 BaseInputPinImpl_Connect
,
245 BaseInputPinImpl_ReceiveConnection
,
246 BasePinImpl_Disconnect
,
247 BasePinImpl_ConnectedTo
,
248 BasePinImpl_ConnectionMediaType
,
249 BasePinImpl_QueryPinInfo
,
250 BasePinImpl_QueryDirection
,
252 BasePinImpl_QueryAccept
,
253 BasePinImpl_EnumMediaTypes
,
254 BasePinImpl_QueryInternalConnections
,
255 BaseInputPinImpl_EndOfStream
,
256 BaseInputPinImpl_BeginFlush
,
257 BaseInputPinImpl_EndFlush
,
258 BaseInputPinImpl_NewSegment
261 static HRESULT WINAPI
SmartTeeFilterInput_CheckMediaType(BasePin
*base
, const AM_MEDIA_TYPE
*pmt
)
263 SmartTeeFilter
*This
= impl_from_BasePin(base
);
264 FIXME("(%p, AM_MEDIA_TYPE(%p)): stub\n", This
, pmt
);
265 dump_AM_MEDIA_TYPE(pmt
);
269 static LONG WINAPI
SmartTeeFilterInput_GetMediaTypeVersion(BasePin
*base
)
274 static HRESULT WINAPI
SmartTeeFilterInput_GetMediaType(BasePin
*base
, int iPosition
, AM_MEDIA_TYPE
*amt
)
276 SmartTeeFilter
*This
= impl_from_BasePin(base
);
277 FIXME("(%p)->(%d, %p): stub\n", This
, iPosition
, amt
);
281 static HRESULT WINAPI
SmartTeeFilterInput_Receive(BaseInputPin
*base
, IMediaSample
*pSample
)
283 SmartTeeFilter
*This
= impl_from_BasePin(&base
->pin
);
284 FIXME("(%p)->(%p): stub\n", This
, pSample
);
288 static const BaseInputPinFuncTable SmartTeeFilterInputFuncs
= {
290 SmartTeeFilterInput_CheckMediaType
,
292 SmartTeeFilterInput_GetMediaTypeVersion
,
293 SmartTeeFilterInput_GetMediaType
295 SmartTeeFilterInput_Receive
298 static ULONG WINAPI
SmartTeeFilterCapture_AddRef(IPin
*iface
)
300 SmartTeeFilter
*This
= impl_from_IPin(iface
);
301 return IBaseFilter_AddRef(&This
->filter
.IBaseFilter_iface
);
304 static ULONG WINAPI
SmartTeeFilterCapture_Release(IPin
*iface
)
306 SmartTeeFilter
*This
= impl_from_IPin(iface
);
307 return IBaseFilter_Release(&This
->filter
.IBaseFilter_iface
);
310 static const IPinVtbl SmartTeeFilterCaptureVtbl
= {
311 BaseOutputPinImpl_QueryInterface
,
312 SmartTeeFilterCapture_AddRef
,
313 SmartTeeFilterCapture_Release
,
314 BaseOutputPinImpl_Connect
,
315 BaseOutputPinImpl_ReceiveConnection
,
316 BaseOutputPinImpl_Disconnect
,
317 BasePinImpl_ConnectedTo
,
318 BasePinImpl_ConnectionMediaType
,
319 BasePinImpl_QueryPinInfo
,
320 BasePinImpl_QueryDirection
,
322 BasePinImpl_QueryAccept
,
323 BasePinImpl_EnumMediaTypes
,
324 BasePinImpl_QueryInternalConnections
,
325 BaseOutputPinImpl_EndOfStream
,
326 BaseOutputPinImpl_BeginFlush
,
327 BaseOutputPinImpl_EndFlush
,
328 BasePinImpl_NewSegment
331 static LONG WINAPI
SmartTeeFilterCapture_GetMediaTypeVersion(BasePin
*base
)
333 SmartTeeFilter
*This
= impl_from_BasePin(base
);
334 TRACE("(%p)\n", This
);
338 static HRESULT WINAPI
SmartTeeFilterCapture_GetMediaType(BasePin
*base
, int iPosition
, AM_MEDIA_TYPE
*amt
)
340 SmartTeeFilter
*This
= impl_from_BasePin(base
);
341 FIXME("(%p, %d, %p): stub\n", This
, iPosition
, amt
);
345 static HRESULT WINAPI
SmartTeeFilterCapture_DecideBufferSize(BaseOutputPin
*base
, IMemAllocator
*alloc
,
346 ALLOCATOR_PROPERTIES
*ppropInputRequest
)
348 SmartTeeFilter
*This
= impl_from_BasePin(&base
->pin
);
349 FIXME("(%p, %p, %p): stub\n", This
, alloc
, ppropInputRequest
);
353 static HRESULT WINAPI
SmartTeeFilterCapture_BreakConnect(BaseOutputPin
*base
)
355 SmartTeeFilter
*This
= impl_from_BasePin(&base
->pin
);
356 FIXME("(%p): stub\n", This
);
360 static const BaseOutputPinFuncTable SmartTeeFilterCaptureFuncs
= {
363 BaseOutputPinImpl_AttemptConnection
,
364 SmartTeeFilterCapture_GetMediaTypeVersion
,
365 SmartTeeFilterCapture_GetMediaType
367 SmartTeeFilterCapture_DecideBufferSize
,
368 BaseOutputPinImpl_DecideAllocator
,
369 SmartTeeFilterCapture_BreakConnect
372 static ULONG WINAPI
SmartTeeFilterPreview_AddRef(IPin
*iface
)
374 SmartTeeFilter
*This
= impl_from_IPin(iface
);
375 return IBaseFilter_AddRef(&This
->filter
.IBaseFilter_iface
);
378 static ULONG WINAPI
SmartTeeFilterPreview_Release(IPin
*iface
)
380 SmartTeeFilter
*This
= impl_from_IPin(iface
);
381 return IBaseFilter_Release(&This
->filter
.IBaseFilter_iface
);
384 static const IPinVtbl SmartTeeFilterPreviewVtbl
= {
385 BaseOutputPinImpl_QueryInterface
,
386 SmartTeeFilterPreview_AddRef
,
387 SmartTeeFilterPreview_Release
,
388 BaseOutputPinImpl_Connect
,
389 BaseOutputPinImpl_ReceiveConnection
,
390 BaseOutputPinImpl_Disconnect
,
391 BasePinImpl_ConnectedTo
,
392 BasePinImpl_ConnectionMediaType
,
393 BasePinImpl_QueryPinInfo
,
394 BasePinImpl_QueryDirection
,
396 BasePinImpl_QueryAccept
,
397 BasePinImpl_EnumMediaTypes
,
398 BasePinImpl_QueryInternalConnections
,
399 BaseOutputPinImpl_EndOfStream
,
400 BaseOutputPinImpl_BeginFlush
,
401 BaseOutputPinImpl_EndFlush
,
402 BasePinImpl_NewSegment
405 static LONG WINAPI
SmartTeeFilterPreview_GetMediaTypeVersion(BasePin
*base
)
407 SmartTeeFilter
*This
= impl_from_BasePin(base
);
408 TRACE("(%p)\n", This
);
412 static HRESULT WINAPI
SmartTeeFilterPreview_GetMediaType(BasePin
*base
, int iPosition
, AM_MEDIA_TYPE
*amt
)
414 SmartTeeFilter
*This
= impl_from_BasePin(base
);
415 FIXME("(%p, %d, %p): stub\n", This
, iPosition
, amt
);
419 static HRESULT WINAPI
SmartTeeFilterPreview_DecideBufferSize(BaseOutputPin
*base
, IMemAllocator
*alloc
, ALLOCATOR_PROPERTIES
*ppropInputRequest
)
421 SmartTeeFilter
*This
= impl_from_BasePin(&base
->pin
);
422 FIXME("(%p, %p, %p): stub\n", This
, alloc
, ppropInputRequest
);
426 static HRESULT WINAPI
SmartTeeFilterPreview_BreakConnect(BaseOutputPin
*base
)
428 SmartTeeFilter
*This
= impl_from_BasePin(&base
->pin
);
429 FIXME("(%p): stub\n", This
);
433 static const BaseOutputPinFuncTable SmartTeeFilterPreviewFuncs
= {
436 BaseOutputPinImpl_AttemptConnection
,
437 SmartTeeFilterPreview_GetMediaTypeVersion
,
438 SmartTeeFilterPreview_GetMediaType
440 SmartTeeFilterPreview_DecideBufferSize
,
441 BaseOutputPinImpl_DecideAllocator
,
442 SmartTeeFilterPreview_BreakConnect
444 IUnknown
* WINAPI
QCAP_createSmartTeeFilter(IUnknown
*outer
, HRESULT
*phr
)
446 PIN_INFO inputPinInfo
= {NULL
, PINDIR_INPUT
, {'I','n','p','u','t',0}};
447 PIN_INFO capturePinInfo
= {NULL
, PINDIR_OUTPUT
, {'C','a','p','t','u','r','e',0}};
448 PIN_INFO previewPinInfo
= {NULL
, PINDIR_OUTPUT
, {'P','r','e','v','i','e','w',0}};
450 SmartTeeFilter
*This
= NULL
;
452 TRACE("(%p, %p)\n", outer
, phr
);
454 This
= CoTaskMemAlloc(sizeof(*This
));
459 memset(This
, 0, sizeof(*This
));
460 This
->IUnknown_iface
.lpVtbl
= &UnknownVtbl
;
462 This
->outerUnknown
= outer
;
464 This
->outerUnknown
= &This
->IUnknown_iface
;
466 BaseFilter_Init(&This
->filter
, &SmartTeeFilterVtbl
, &CLSID_SmartTee
,
467 (DWORD_PTR
)(__FILE__
": SmartTeeFilter.csFilter"), &SmartTeeFilterFuncs
);
469 inputPinInfo
.pFilter
= &This
->filter
.IBaseFilter_iface
;
470 hr
= BaseInputPin_Construct(&SmartTeeFilterInputVtbl
, sizeof(BaseInputPin
), &inputPinInfo
,
471 &SmartTeeFilterInputFuncs
, &This
->filter
.csFilter
, NULL
, (IPin
**)&This
->input
);
475 capturePinInfo
.pFilter
= &This
->filter
.IBaseFilter_iface
;
476 hr
= BaseOutputPin_Construct(&SmartTeeFilterCaptureVtbl
, sizeof(BaseOutputPin
), &capturePinInfo
,
477 &SmartTeeFilterCaptureFuncs
, &This
->filter
.csFilter
, (IPin
**)&This
->capture
);
481 previewPinInfo
.pFilter
= &This
->filter
.IBaseFilter_iface
;
482 hr
= BaseOutputPin_Construct(&SmartTeeFilterPreviewVtbl
, sizeof(BaseOutputPin
), &previewPinInfo
,
483 &SmartTeeFilterPreviewFuncs
, &This
->filter
.csFilter
, (IPin
**)&This
->preview
);
489 return &This
->IUnknown_iface
;
491 return (IUnknown
*)&This
->filter
.IBaseFilter_iface
;
494 IBaseFilter_Release(&This
->filter
.IBaseFilter_iface
);