2 * Copyright 2013 Jacek Caban for CodeWeavers
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
29 #include "qcap_main.h"
31 #include "wine/debug.h"
33 WINE_DEFAULT_DEBUG_CHANNEL(qcap
);
37 IPersistPropertyBag IPersistPropertyBag_iface
;
45 VIDEOINFOHEADER
*videoinfo
;
46 size_t videoinfo_size
;
50 static inline AVICompressor
*impl_from_BaseFilter(BaseFilter
*filter
)
52 return CONTAINING_RECORD(filter
, AVICompressor
, filter
);
55 static inline AVICompressor
*impl_from_IBaseFilter(IBaseFilter
*iface
)
57 BaseFilter
*filter
= CONTAINING_RECORD(iface
, BaseFilter
, IBaseFilter_iface
);
58 return impl_from_BaseFilter(filter
);
61 static inline AVICompressor
*impl_from_BasePin(BasePin
*pin
)
63 return impl_from_IBaseFilter(pin
->pinInfo
.pFilter
);
66 static HRESULT
ensure_driver(AVICompressor
*This
)
71 This
->hic
= ICOpen(FCC('v','i','d','c'), This
->fcc_handler
, ICMODE_COMPRESS
);
73 FIXME("ICOpen failed\n");
80 static HRESULT
fill_format_info(AVICompressor
*This
, VIDEOINFOHEADER
*src_videoinfo
)
86 hres
= ensure_driver(This
);
90 size
= ICGetInfo(This
->hic
, &icinfo
, sizeof(icinfo
));
91 if(size
!= sizeof(icinfo
))
94 size
= ICCompressGetFormatSize(This
->hic
, &src_videoinfo
->bmiHeader
);
96 FIXME("ICCompressGetFormatSize failed\n");
100 size
+= FIELD_OFFSET(VIDEOINFOHEADER
, bmiHeader
);
101 This
->videoinfo
= heap_alloc(size
);
103 return E_OUTOFMEMORY
;
105 This
->videoinfo_size
= size
;
106 This
->driver_flags
= icinfo
.dwFlags
;
107 memset(This
->videoinfo
, 0, sizeof(*This
->videoinfo
));
108 ICCompressGetFormat(This
->hic
, &src_videoinfo
->bmiHeader
, &This
->videoinfo
->bmiHeader
);
110 This
->videoinfo
->dwBitRate
= 10000000/src_videoinfo
->AvgTimePerFrame
* This
->videoinfo
->bmiHeader
.biSizeImage
* 8;
111 This
->videoinfo
->AvgTimePerFrame
= src_videoinfo
->AvgTimePerFrame
;
115 static HRESULT WINAPI
AVICompressor_QueryInterface(IBaseFilter
*iface
, REFIID riid
, void **ppv
)
117 AVICompressor
*This
= impl_from_IBaseFilter(iface
);
119 if(IsEqualIID(riid
, &IID_IUnknown
)) {
120 TRACE("(%p)->(IID_IUnknown %p)\n", This
, ppv
);
121 *ppv
= &This
->filter
.IBaseFilter_iface
;
122 }else if(IsEqualIID(riid
, &IID_IPersist
)) {
123 TRACE("(%p)->(IID_IPersist %p)\n", This
, ppv
);
124 *ppv
= &This
->filter
.IBaseFilter_iface
;
125 }else if(IsEqualIID(riid
, &IID_IMediaFilter
)) {
126 TRACE("(%p)->(IID_IMediaFilter %p)\n", This
, ppv
);
127 *ppv
= &This
->filter
.IBaseFilter_iface
;
128 }else if(IsEqualIID(riid
, &IID_IBaseFilter
)) {
129 TRACE("(%p)->(IID_IBaseFilter %p)\n", This
, ppv
);
130 *ppv
= &This
->filter
.IBaseFilter_iface
;
131 }else if(IsEqualIID(riid
, &IID_IPersistPropertyBag
)) {
132 TRACE("(%p)->(IID_IPersistPropertyBag %p)\n", This
, ppv
);
133 *ppv
= &This
->IPersistPropertyBag_iface
;
135 FIXME("no interface for %s\n", debugstr_guid(riid
));
137 return E_NOINTERFACE
;
140 IUnknown_AddRef((IUnknown
*)*ppv
);
145 static ULONG WINAPI
AVICompressor_Release(IBaseFilter
*iface
)
147 AVICompressor
*This
= impl_from_IBaseFilter(iface
);
148 ULONG ref
= BaseFilterImpl_Release(&This
->filter
.IBaseFilter_iface
);
150 TRACE("(%p) ref=%d\n", This
, ref
);
155 heap_free(This
->videoinfo
);
157 BaseInputPinImpl_Release(&This
->in
->pin
.IPin_iface
);
159 BaseOutputPinImpl_Release(&This
->out
->pin
.IPin_iface
);
166 static HRESULT WINAPI
AVICompressor_Stop(IBaseFilter
*iface
)
168 AVICompressor
*This
= impl_from_IBaseFilter(iface
);
169 FIXME("(%p)\n", This
);
173 static HRESULT WINAPI
AVICompressor_Pause(IBaseFilter
*iface
)
175 AVICompressor
*This
= impl_from_IBaseFilter(iface
);
176 FIXME("(%p)\n", This
);
180 static HRESULT WINAPI
AVICompressor_Run(IBaseFilter
*iface
, REFERENCE_TIME tStart
)
182 AVICompressor
*This
= impl_from_IBaseFilter(iface
);
183 FIXME("(%p)->(%s)\n", This
, wine_dbgstr_longlong(tStart
));
187 static HRESULT WINAPI
AVICompressor_FindPin(IBaseFilter
*iface
, LPCWSTR Id
, IPin
**ppPin
)
189 AVICompressor
*This
= impl_from_IBaseFilter(iface
);
190 FIXME("(%p)->(%s %p)\n", This
, debugstr_w(Id
), ppPin
);
191 return VFW_E_NOT_FOUND
;
194 static HRESULT WINAPI
AVICompressor_QueryFilterInfo(IBaseFilter
*iface
, FILTER_INFO
*pInfo
)
196 AVICompressor
*This
= impl_from_IBaseFilter(iface
);
197 FIXME("(%p)->(%p)\n", This
, pInfo
);
201 static HRESULT WINAPI
AVICompressor_QueryVendorInfo(IBaseFilter
*iface
, LPWSTR
*pVendorInfo
)
203 AVICompressor
*This
= impl_from_IBaseFilter(iface
);
204 FIXME("(%p)->(%p)\n", This
, pVendorInfo
);
208 static const IBaseFilterVtbl AVICompressorVtbl
= {
209 AVICompressor_QueryInterface
,
210 BaseFilterImpl_AddRef
,
211 AVICompressor_Release
,
212 BaseFilterImpl_GetClassID
,
216 BaseFilterImpl_GetState
,
217 BaseFilterImpl_SetSyncSource
,
218 BaseFilterImpl_GetSyncSource
,
219 BaseFilterImpl_EnumPins
,
220 AVICompressor_FindPin
,
221 AVICompressor_QueryFilterInfo
,
222 BaseFilterImpl_JoinFilterGraph
,
223 AVICompressor_QueryVendorInfo
226 static IPin
* WINAPI
AVICompressor_GetPin(BaseFilter
*iface
, int pos
)
228 AVICompressor
*This
= impl_from_BaseFilter(iface
);
231 TRACE("(%p)->(%d)\n", This
, pos
);
235 ret
= &This
->in
->pin
.IPin_iface
;
238 ret
= &This
->out
->pin
.IPin_iface
;
241 TRACE("No pin %d\n", pos
);
249 static LONG WINAPI
AVICompressor_GetPinCount(BaseFilter
*iface
)
254 static const BaseFilterFuncTable filter_func_table
= {
255 AVICompressor_GetPin
,
256 AVICompressor_GetPinCount
259 static AVICompressor
*impl_from_IPersistPropertyBag(IPersistPropertyBag
*iface
)
261 return CONTAINING_RECORD(iface
, AVICompressor
, IPersistPropertyBag_iface
);
264 static HRESULT WINAPI
AVICompressorPropertyBag_QueryInterface(IPersistPropertyBag
*iface
, REFIID riid
, void **ppv
)
266 AVICompressor
*This
= impl_from_IPersistPropertyBag(iface
);
267 return IBaseFilter_QueryInterface(&This
->filter
.IBaseFilter_iface
, riid
, ppv
);
270 static ULONG WINAPI
AVICompressorPropertyBag_AddRef(IPersistPropertyBag
*iface
)
272 AVICompressor
*This
= impl_from_IPersistPropertyBag(iface
);
273 return IBaseFilter_AddRef(&This
->filter
.IBaseFilter_iface
);
276 static ULONG WINAPI
AVICompressorPropertyBag_Release(IPersistPropertyBag
*iface
)
278 AVICompressor
*This
= impl_from_IPersistPropertyBag(iface
);
279 return IBaseFilter_Release(&This
->filter
.IBaseFilter_iface
);
282 static HRESULT WINAPI
AVICompressorPropertyBag_GetClassID(IPersistPropertyBag
*iface
, CLSID
*pClassID
)
284 AVICompressor
*This
= impl_from_IPersistPropertyBag(iface
);
285 return IBaseFilter_GetClassID(&This
->filter
.IBaseFilter_iface
, pClassID
);
288 static HRESULT WINAPI
AVICompressorPropertyBag_InitNew(IPersistPropertyBag
*iface
)
290 AVICompressor
*This
= impl_from_IPersistPropertyBag(iface
);
291 FIXME("(%p)->()\n", This
);
295 static HRESULT WINAPI
AVICompressorPropertyBag_Load(IPersistPropertyBag
*iface
, IPropertyBag
*pPropBag
, IErrorLog
*pErrorLog
)
297 AVICompressor
*This
= impl_from_IPersistPropertyBag(iface
);
302 static const WCHAR fcc_handlerW
[] = {'F','c','c','H','a','n','d','l','e','r',0};
304 TRACE("(%p)->(%p %p)\n", This
, pPropBag
, pErrorLog
);
307 hres
= IPropertyBag_Read(pPropBag
, fcc_handlerW
, &v
, NULL
);
309 WARN("Could not read FccHandler: %08x\n", hres
);
313 if(V_VT(&v
) != VT_BSTR
) {
314 FIXME("Got vt %d\n", V_VT(&v
));
320 TRACE("FccHandler = %s\n", debugstr_w(str
));
321 if(SysStringLen(str
) != 4) {
322 FIXME("Invalid FccHandler len\n");
327 This
->fcc_handler
= FCC(str
[0], str
[1], str
[2], str
[3]);
332 static HRESULT WINAPI
AVICompressorPropertyBag_Save(IPersistPropertyBag
*iface
, IPropertyBag
*pPropBag
,
333 BOOL fClearDirty
, BOOL fSaveAllProperties
)
335 AVICompressor
*This
= impl_from_IPersistPropertyBag(iface
);
336 FIXME("(%p)->(%p %x %x)\n", This
, pPropBag
, fClearDirty
, fSaveAllProperties
);
340 static const IPersistPropertyBagVtbl PersistPropertyBagVtbl
= {
341 AVICompressorPropertyBag_QueryInterface
,
342 AVICompressorPropertyBag_AddRef
,
343 AVICompressorPropertyBag_Release
,
344 AVICompressorPropertyBag_GetClassID
,
345 AVICompressorPropertyBag_InitNew
,
346 AVICompressorPropertyBag_Load
,
347 AVICompressorPropertyBag_Save
350 static inline AVICompressor
*impl_from_IPin(IPin
*iface
)
352 BasePin
*bp
= CONTAINING_RECORD(iface
, BasePin
, IPin_iface
);
353 return impl_from_IBaseFilter(bp
->pinInfo
.pFilter
);
356 static HRESULT WINAPI
AVICompressorIn_QueryInterface(IPin
*iface
, REFIID riid
, void **ppv
)
358 return BaseInputPinImpl_QueryInterface(iface
, riid
, ppv
);
361 static ULONG WINAPI
AVICompressorIn_AddRef(IPin
*iface
)
363 AVICompressor
*This
= impl_from_IPin(iface
);
364 return IBaseFilter_AddRef(&This
->filter
.IBaseFilter_iface
);
367 static ULONG WINAPI
AVICompressorIn_Release(IPin
*iface
)
369 AVICompressor
*This
= impl_from_IPin(iface
);
370 return IBaseFilter_Release(&This
->filter
.IBaseFilter_iface
);
373 static HRESULT WINAPI
AVICompressorIn_ReceiveConnection(IPin
*iface
,
374 IPin
*pConnector
, const AM_MEDIA_TYPE
*pmt
)
376 AVICompressor
*This
= impl_from_IPin(iface
);
379 TRACE("(%p)->(%p AM_MEDIA_TYPE(%p))\n", This
, pConnector
, pmt
);
380 dump_AM_MEDIA_TYPE(pmt
);
382 hres
= BaseInputPinImpl_ReceiveConnection(iface
, pConnector
, pmt
);
386 hres
= fill_format_info(This
, (VIDEOINFOHEADER
*)pmt
->pbFormat
);
388 BasePinImpl_Disconnect(iface
);
392 static HRESULT WINAPI
AVICompressorIn_Disconnect(IPin
*iface
)
394 AVICompressor
*This
= impl_from_IPin(iface
);
395 FIXME("(%p)\n", This
);
399 static const IPinVtbl AVICompressorInputPinVtbl
= {
400 AVICompressorIn_QueryInterface
,
401 AVICompressorIn_AddRef
,
402 AVICompressorIn_Release
,
403 BaseInputPinImpl_Connect
,
404 AVICompressorIn_ReceiveConnection
,
405 AVICompressorIn_Disconnect
,
406 BasePinImpl_ConnectedTo
,
407 BasePinImpl_ConnectionMediaType
,
408 BasePinImpl_QueryPinInfo
,
409 BasePinImpl_QueryDirection
,
411 BasePinImpl_QueryAccept
,
412 BasePinImpl_EnumMediaTypes
,
413 BasePinImpl_QueryInternalConnections
,
414 BaseInputPinImpl_EndOfStream
,
415 BaseInputPinImpl_BeginFlush
,
416 BaseInputPinImpl_EndFlush
,
417 BaseInputPinImpl_NewSegment
420 static HRESULT WINAPI
AVICompressorIn_CheckMediaType(BasePin
*base
, const AM_MEDIA_TYPE
*pmt
)
422 AVICompressor
*This
= impl_from_BasePin(base
);
423 VIDEOINFOHEADER
*videoinfo
;
427 TRACE("(%p)->(AM_MEDIA_TYPE(%p))\n", base
, pmt
);
428 dump_AM_MEDIA_TYPE(pmt
);
430 if(!IsEqualIID(&pmt
->majortype
, &MEDIATYPE_Video
))
433 if(!IsEqualIID(&pmt
->formattype
, &FORMAT_VideoInfo
)) {
434 FIXME("formattype %s unsupported\n", debugstr_guid(&pmt
->formattype
));
438 hres
= ensure_driver(This
);
442 videoinfo
= (VIDEOINFOHEADER
*)pmt
->pbFormat
;
443 res
= ICCompressQuery(This
->hic
, &videoinfo
->bmiHeader
, NULL
);
444 return res
== ICERR_OK
? S_OK
: S_FALSE
;
447 static LONG WINAPI
AVICompressorIn_GetMediaTypeVersion(BasePin
*base
)
452 static HRESULT WINAPI
AVICompressorIn_GetMediaType(BasePin
*base
, int iPosition
, AM_MEDIA_TYPE
*amt
)
454 TRACE("(%p)->(%d %p)\n", base
, iPosition
, amt
);
458 static const BasePinFuncTable AVICompressorInputBasePinVtbl
= {
459 AVICompressorIn_CheckMediaType
,
461 AVICompressorIn_GetMediaTypeVersion
,
462 AVICompressorIn_GetMediaType
465 static HRESULT WINAPI
AVICompressorIn_Receive(BaseInputPin
*base
, IMediaSample
*pSample
)
467 AVICompressor
*This
= impl_from_BasePin(&base
->pin
);
468 FIXME("(%p)->(%p)\n", This
, pSample
);
472 static const BaseInputPinFuncTable AVICompressorBaseInputPinVtbl
= {
473 AVICompressorIn_Receive
476 static HRESULT WINAPI
AVICompressorOut_QueryInterface(IPin
*iface
, REFIID riid
, void **ppv
)
478 return BaseInputPinImpl_QueryInterface(iface
, riid
, ppv
);
481 static ULONG WINAPI
AVICompressorOut_AddRef(IPin
*iface
)
483 AVICompressor
*This
= impl_from_IPin(iface
);
484 return IBaseFilter_AddRef(&This
->filter
.IBaseFilter_iface
);
487 static ULONG WINAPI
AVICompressorOut_Release(IPin
*iface
)
489 AVICompressor
*This
= impl_from_IPin(iface
);
490 return IBaseFilter_Release(&This
->filter
.IBaseFilter_iface
);
493 static const IPinVtbl AVICompressorOutputPinVtbl
= {
494 AVICompressorOut_QueryInterface
,
495 AVICompressorOut_AddRef
,
496 AVICompressorOut_Release
,
497 BaseOutputPinImpl_Connect
,
498 BaseOutputPinImpl_ReceiveConnection
,
499 BaseOutputPinImpl_Disconnect
,
500 BasePinImpl_ConnectedTo
,
501 BasePinImpl_ConnectionMediaType
,
502 BasePinImpl_QueryPinInfo
,
503 BasePinImpl_QueryDirection
,
505 BasePinImpl_QueryAccept
,
506 BasePinImpl_EnumMediaTypes
,
507 BasePinImpl_QueryInternalConnections
,
508 BaseOutputPinImpl_EndOfStream
,
509 BaseOutputPinImpl_BeginFlush
,
510 BaseOutputPinImpl_EndFlush
,
511 BasePinImpl_NewSegment
514 static LONG WINAPI
AVICompressorOut_GetMediaTypeVersion(BasePin
*base
)
516 FIXME("(%p)\n", base
);
520 static HRESULT WINAPI
AVICompressorOut_GetMediaType(BasePin
*base
, int iPosition
, AM_MEDIA_TYPE
*amt
)
522 AVICompressor
*This
= impl_from_IBaseFilter(base
->pinInfo
.pFilter
);
523 FIXME("(%p)->(%d %p)\n", This
, iPosition
, amt
);
527 static const BasePinFuncTable AVICompressorOutputBasePinVtbl
= {
529 BaseOutputPinImpl_AttemptConnection
,
530 AVICompressorOut_GetMediaTypeVersion
,
531 AVICompressorOut_GetMediaType
534 static HRESULT WINAPI
AVICompressorOut_DecideBufferSize(BaseOutputPin
*base
, IMemAllocator
*alloc
, ALLOCATOR_PROPERTIES
*ppropInputRequest
)
540 static HRESULT WINAPI
AVICompressorOut_DecideAllocator(BaseOutputPin
*base
,
541 IMemInputPin
*pPin
, IMemAllocator
**pAlloc
)
543 TRACE("(%p)->(%p %p)\n", base
, pPin
, pAlloc
);
544 return BaseOutputPinImpl_DecideAllocator(base
, pPin
, pAlloc
);
547 static HRESULT WINAPI
AVICompressorOut_BreakConnect(BaseOutputPin
*base
)
549 FIXME("(%p)\n", base
);
553 static const BaseOutputPinFuncTable AVICompressorBaseOutputPinVtbl
= {
554 AVICompressorOut_DecideBufferSize
,
555 AVICompressorOut_DecideAllocator
,
556 AVICompressorOut_BreakConnect
559 IUnknown
* WINAPI
QCAP_createAVICompressor(IUnknown
*outer
, HRESULT
*phr
)
561 PIN_INFO in_pin_info
= {NULL
, PINDIR_INPUT
, {'I','n','p','u','t',0}};
562 PIN_INFO out_pin_info
= {NULL
, PINDIR_OUTPUT
, {'O','u','t','p','u','t',0}};
563 AVICompressor
*compressor
;
568 compressor
= heap_alloc_zero(sizeof(*compressor
));
570 *phr
= E_NOINTERFACE
;
574 BaseFilter_Init(&compressor
->filter
, &AVICompressorVtbl
, &CLSID_AVICo
,
575 (DWORD_PTR
)(__FILE__
": AVICompressor.csFilter"), &filter_func_table
);
577 compressor
->IPersistPropertyBag_iface
.lpVtbl
= &PersistPropertyBagVtbl
;
579 in_pin_info
.pFilter
= &compressor
->filter
.IBaseFilter_iface
;
580 hres
= BaseInputPin_Construct(&AVICompressorInputPinVtbl
, sizeof(BaseInputPin
), &in_pin_info
,
581 &AVICompressorInputBasePinVtbl
, &AVICompressorBaseInputPinVtbl
,
582 &compressor
->filter
.csFilter
, NULL
, (IPin
**)&compressor
->in
);
584 IBaseFilter_Release(&compressor
->filter
.IBaseFilter_iface
);
589 out_pin_info
.pFilter
= &compressor
->filter
.IBaseFilter_iface
;
590 hres
= BaseOutputPin_Construct(&AVICompressorOutputPinVtbl
, sizeof(BaseOutputPin
), &out_pin_info
,
591 &AVICompressorOutputBasePinVtbl
, &AVICompressorBaseOutputPinVtbl
,
592 &compressor
->filter
.csFilter
, (IPin
**)&compressor
->out
);
594 IBaseFilter_Release(&compressor
->filter
.IBaseFilter_iface
);
600 return (IUnknown
*)&compressor
->filter
.IBaseFilter_iface
;