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
;
52 static inline AVICompressor
*impl_from_BaseFilter(BaseFilter
*filter
)
54 return CONTAINING_RECORD(filter
, AVICompressor
, filter
);
57 static inline AVICompressor
*impl_from_IBaseFilter(IBaseFilter
*iface
)
59 BaseFilter
*filter
= CONTAINING_RECORD(iface
, BaseFilter
, IBaseFilter_iface
);
60 return impl_from_BaseFilter(filter
);
63 static inline AVICompressor
*impl_from_BasePin(BasePin
*pin
)
65 return impl_from_IBaseFilter(pin
->pinInfo
.pFilter
);
68 static HRESULT
ensure_driver(AVICompressor
*This
)
73 This
->hic
= ICOpen(FCC('v','i','d','c'), This
->fcc_handler
, ICMODE_COMPRESS
);
75 FIXME("ICOpen failed\n");
82 static HRESULT
fill_format_info(AVICompressor
*This
, VIDEOINFOHEADER
*src_videoinfo
)
88 hres
= ensure_driver(This
);
92 size
= ICGetInfo(This
->hic
, &icinfo
, sizeof(icinfo
));
93 if(size
!= sizeof(icinfo
))
96 size
= ICCompressGetFormatSize(This
->hic
, &src_videoinfo
->bmiHeader
);
98 FIXME("ICCompressGetFormatSize failed\n");
102 size
+= FIELD_OFFSET(VIDEOINFOHEADER
, bmiHeader
);
103 This
->videoinfo
= heap_alloc(size
);
105 return E_OUTOFMEMORY
;
107 This
->videoinfo_size
= size
;
108 This
->driver_flags
= icinfo
.dwFlags
;
109 memset(This
->videoinfo
, 0, sizeof(*This
->videoinfo
));
110 ICCompressGetFormat(This
->hic
, &src_videoinfo
->bmiHeader
, &This
->videoinfo
->bmiHeader
);
112 This
->videoinfo
->dwBitRate
= 10000000/src_videoinfo
->AvgTimePerFrame
* This
->videoinfo
->bmiHeader
.biSizeImage
* 8;
113 This
->videoinfo
->AvgTimePerFrame
= src_videoinfo
->AvgTimePerFrame
;
117 static HRESULT WINAPI
AVICompressor_QueryInterface(IBaseFilter
*iface
, REFIID riid
, void **ppv
)
119 AVICompressor
*This
= impl_from_IBaseFilter(iface
);
121 if(IsEqualIID(riid
, &IID_IUnknown
)) {
122 TRACE("(%p)->(IID_IUnknown %p)\n", This
, ppv
);
123 *ppv
= &This
->filter
.IBaseFilter_iface
;
124 }else if(IsEqualIID(riid
, &IID_IPersist
)) {
125 TRACE("(%p)->(IID_IPersist %p)\n", This
, ppv
);
126 *ppv
= &This
->filter
.IBaseFilter_iface
;
127 }else if(IsEqualIID(riid
, &IID_IMediaFilter
)) {
128 TRACE("(%p)->(IID_IMediaFilter %p)\n", This
, ppv
);
129 *ppv
= &This
->filter
.IBaseFilter_iface
;
130 }else if(IsEqualIID(riid
, &IID_IBaseFilter
)) {
131 TRACE("(%p)->(IID_IBaseFilter %p)\n", This
, ppv
);
132 *ppv
= &This
->filter
.IBaseFilter_iface
;
133 }else if(IsEqualIID(riid
, &IID_IPersistPropertyBag
)) {
134 TRACE("(%p)->(IID_IPersistPropertyBag %p)\n", This
, ppv
);
135 *ppv
= &This
->IPersistPropertyBag_iface
;
137 FIXME("no interface for %s\n", debugstr_guid(riid
));
139 return E_NOINTERFACE
;
142 IUnknown_AddRef((IUnknown
*)*ppv
);
147 static ULONG WINAPI
AVICompressor_Release(IBaseFilter
*iface
)
149 AVICompressor
*This
= impl_from_IBaseFilter(iface
);
150 ULONG ref
= BaseFilterImpl_Release(&This
->filter
.IBaseFilter_iface
);
152 TRACE("(%p) ref=%d\n", This
, ref
);
157 heap_free(This
->videoinfo
);
159 BaseInputPinImpl_Release(&This
->in
->pin
.IPin_iface
);
161 BaseOutputPinImpl_Release(&This
->out
->pin
.IPin_iface
);
168 static HRESULT WINAPI
AVICompressor_Stop(IBaseFilter
*iface
)
170 AVICompressor
*This
= impl_from_IBaseFilter(iface
);
172 TRACE("(%p)\n", This
);
174 if(This
->filter
.state
== State_Stopped
)
177 ICCompressEnd(This
->hic
);
178 This
->filter
.state
= State_Stopped
;
182 static HRESULT WINAPI
AVICompressor_Pause(IBaseFilter
*iface
)
184 AVICompressor
*This
= impl_from_IBaseFilter(iface
);
185 FIXME("(%p)\n", This
);
189 static HRESULT WINAPI
AVICompressor_Run(IBaseFilter
*iface
, REFERENCE_TIME tStart
)
191 AVICompressor
*This
= impl_from_IBaseFilter(iface
);
194 TRACE("(%p)->(%s)\n", This
, wine_dbgstr_longlong(tStart
));
196 if(This
->filter
.state
== State_Running
)
199 hres
= IMemAllocator_Commit(This
->out
->pAllocator
);
201 FIXME("Commit failed: %08x\n", hres
);
207 This
->filter
.state
= State_Running
;
211 static HRESULT WINAPI
AVICompressor_FindPin(IBaseFilter
*iface
, LPCWSTR Id
, IPin
**ppPin
)
213 AVICompressor
*This
= impl_from_IBaseFilter(iface
);
214 FIXME("(%p)->(%s %p)\n", This
, debugstr_w(Id
), ppPin
);
215 return VFW_E_NOT_FOUND
;
218 static HRESULT WINAPI
AVICompressor_QueryFilterInfo(IBaseFilter
*iface
, FILTER_INFO
*pInfo
)
220 AVICompressor
*This
= impl_from_IBaseFilter(iface
);
221 FIXME("(%p)->(%p)\n", This
, pInfo
);
225 static HRESULT WINAPI
AVICompressor_QueryVendorInfo(IBaseFilter
*iface
, LPWSTR
*pVendorInfo
)
227 AVICompressor
*This
= impl_from_IBaseFilter(iface
);
228 FIXME("(%p)->(%p)\n", This
, pVendorInfo
);
232 static const IBaseFilterVtbl AVICompressorVtbl
= {
233 AVICompressor_QueryInterface
,
234 BaseFilterImpl_AddRef
,
235 AVICompressor_Release
,
236 BaseFilterImpl_GetClassID
,
240 BaseFilterImpl_GetState
,
241 BaseFilterImpl_SetSyncSource
,
242 BaseFilterImpl_GetSyncSource
,
243 BaseFilterImpl_EnumPins
,
244 AVICompressor_FindPin
,
245 AVICompressor_QueryFilterInfo
,
246 BaseFilterImpl_JoinFilterGraph
,
247 AVICompressor_QueryVendorInfo
250 static IPin
* WINAPI
AVICompressor_GetPin(BaseFilter
*iface
, int pos
)
252 AVICompressor
*This
= impl_from_BaseFilter(iface
);
255 TRACE("(%p)->(%d)\n", This
, pos
);
259 ret
= &This
->in
->pin
.IPin_iface
;
262 ret
= &This
->out
->pin
.IPin_iface
;
265 TRACE("No pin %d\n", pos
);
273 static LONG WINAPI
AVICompressor_GetPinCount(BaseFilter
*iface
)
278 static const BaseFilterFuncTable filter_func_table
= {
279 AVICompressor_GetPin
,
280 AVICompressor_GetPinCount
283 static AVICompressor
*impl_from_IPersistPropertyBag(IPersistPropertyBag
*iface
)
285 return CONTAINING_RECORD(iface
, AVICompressor
, IPersistPropertyBag_iface
);
288 static HRESULT WINAPI
AVICompressorPropertyBag_QueryInterface(IPersistPropertyBag
*iface
, REFIID riid
, void **ppv
)
290 AVICompressor
*This
= impl_from_IPersistPropertyBag(iface
);
291 return IBaseFilter_QueryInterface(&This
->filter
.IBaseFilter_iface
, riid
, ppv
);
294 static ULONG WINAPI
AVICompressorPropertyBag_AddRef(IPersistPropertyBag
*iface
)
296 AVICompressor
*This
= impl_from_IPersistPropertyBag(iface
);
297 return IBaseFilter_AddRef(&This
->filter
.IBaseFilter_iface
);
300 static ULONG WINAPI
AVICompressorPropertyBag_Release(IPersistPropertyBag
*iface
)
302 AVICompressor
*This
= impl_from_IPersistPropertyBag(iface
);
303 return IBaseFilter_Release(&This
->filter
.IBaseFilter_iface
);
306 static HRESULT WINAPI
AVICompressorPropertyBag_GetClassID(IPersistPropertyBag
*iface
, CLSID
*pClassID
)
308 AVICompressor
*This
= impl_from_IPersistPropertyBag(iface
);
309 return IBaseFilter_GetClassID(&This
->filter
.IBaseFilter_iface
, pClassID
);
312 static HRESULT WINAPI
AVICompressorPropertyBag_InitNew(IPersistPropertyBag
*iface
)
314 AVICompressor
*This
= impl_from_IPersistPropertyBag(iface
);
315 FIXME("(%p)->()\n", This
);
319 static HRESULT WINAPI
AVICompressorPropertyBag_Load(IPersistPropertyBag
*iface
, IPropertyBag
*pPropBag
, IErrorLog
*pErrorLog
)
321 AVICompressor
*This
= impl_from_IPersistPropertyBag(iface
);
326 static const WCHAR fcc_handlerW
[] = {'F','c','c','H','a','n','d','l','e','r',0};
328 TRACE("(%p)->(%p %p)\n", This
, pPropBag
, pErrorLog
);
331 hres
= IPropertyBag_Read(pPropBag
, fcc_handlerW
, &v
, NULL
);
333 WARN("Could not read FccHandler: %08x\n", hres
);
337 if(V_VT(&v
) != VT_BSTR
) {
338 FIXME("Got vt %d\n", V_VT(&v
));
344 TRACE("FccHandler = %s\n", debugstr_w(str
));
345 if(SysStringLen(str
) != 4) {
346 FIXME("Invalid FccHandler len\n");
351 This
->fcc_handler
= FCC(str
[0], str
[1], str
[2], str
[3]);
356 static HRESULT WINAPI
AVICompressorPropertyBag_Save(IPersistPropertyBag
*iface
, IPropertyBag
*pPropBag
,
357 BOOL fClearDirty
, BOOL fSaveAllProperties
)
359 AVICompressor
*This
= impl_from_IPersistPropertyBag(iface
);
360 FIXME("(%p)->(%p %x %x)\n", This
, pPropBag
, fClearDirty
, fSaveAllProperties
);
364 static const IPersistPropertyBagVtbl PersistPropertyBagVtbl
= {
365 AVICompressorPropertyBag_QueryInterface
,
366 AVICompressorPropertyBag_AddRef
,
367 AVICompressorPropertyBag_Release
,
368 AVICompressorPropertyBag_GetClassID
,
369 AVICompressorPropertyBag_InitNew
,
370 AVICompressorPropertyBag_Load
,
371 AVICompressorPropertyBag_Save
374 static inline AVICompressor
*impl_from_IPin(IPin
*iface
)
376 BasePin
*bp
= CONTAINING_RECORD(iface
, BasePin
, IPin_iface
);
377 return impl_from_IBaseFilter(bp
->pinInfo
.pFilter
);
380 static HRESULT WINAPI
AVICompressorIn_QueryInterface(IPin
*iface
, REFIID riid
, void **ppv
)
382 return BaseInputPinImpl_QueryInterface(iface
, riid
, ppv
);
385 static ULONG WINAPI
AVICompressorIn_AddRef(IPin
*iface
)
387 AVICompressor
*This
= impl_from_IPin(iface
);
388 return IBaseFilter_AddRef(&This
->filter
.IBaseFilter_iface
);
391 static ULONG WINAPI
AVICompressorIn_Release(IPin
*iface
)
393 AVICompressor
*This
= impl_from_IPin(iface
);
394 return IBaseFilter_Release(&This
->filter
.IBaseFilter_iface
);
397 static HRESULT WINAPI
AVICompressorIn_ReceiveConnection(IPin
*iface
,
398 IPin
*pConnector
, const AM_MEDIA_TYPE
*pmt
)
400 AVICompressor
*This
= impl_from_IPin(iface
);
403 TRACE("(%p)->(%p AM_MEDIA_TYPE(%p))\n", This
, pConnector
, pmt
);
404 dump_AM_MEDIA_TYPE(pmt
);
406 hres
= BaseInputPinImpl_ReceiveConnection(iface
, pConnector
, pmt
);
410 hres
= fill_format_info(This
, (VIDEOINFOHEADER
*)pmt
->pbFormat
);
412 BasePinImpl_Disconnect(iface
);
416 static HRESULT WINAPI
AVICompressorIn_Disconnect(IPin
*iface
)
418 AVICompressor
*This
= impl_from_IPin(iface
);
419 FIXME("(%p)\n", This
);
423 static const IPinVtbl AVICompressorInputPinVtbl
= {
424 AVICompressorIn_QueryInterface
,
425 AVICompressorIn_AddRef
,
426 AVICompressorIn_Release
,
427 BaseInputPinImpl_Connect
,
428 AVICompressorIn_ReceiveConnection
,
429 AVICompressorIn_Disconnect
,
430 BasePinImpl_ConnectedTo
,
431 BasePinImpl_ConnectionMediaType
,
432 BasePinImpl_QueryPinInfo
,
433 BasePinImpl_QueryDirection
,
435 BasePinImpl_QueryAccept
,
436 BasePinImpl_EnumMediaTypes
,
437 BasePinImpl_QueryInternalConnections
,
438 BaseInputPinImpl_EndOfStream
,
439 BaseInputPinImpl_BeginFlush
,
440 BaseInputPinImpl_EndFlush
,
441 BaseInputPinImpl_NewSegment
444 static HRESULT WINAPI
AVICompressorIn_CheckMediaType(BasePin
*base
, const AM_MEDIA_TYPE
*pmt
)
446 AVICompressor
*This
= impl_from_BasePin(base
);
447 VIDEOINFOHEADER
*videoinfo
;
451 TRACE("(%p)->(AM_MEDIA_TYPE(%p))\n", base
, pmt
);
452 dump_AM_MEDIA_TYPE(pmt
);
454 if(!IsEqualIID(&pmt
->majortype
, &MEDIATYPE_Video
))
457 if(!IsEqualIID(&pmt
->formattype
, &FORMAT_VideoInfo
)) {
458 FIXME("formattype %s unsupported\n", debugstr_guid(&pmt
->formattype
));
462 hres
= ensure_driver(This
);
466 videoinfo
= (VIDEOINFOHEADER
*)pmt
->pbFormat
;
467 res
= ICCompressQuery(This
->hic
, &videoinfo
->bmiHeader
, NULL
);
468 return res
== ICERR_OK
? S_OK
: S_FALSE
;
471 static LONG WINAPI
AVICompressorIn_GetMediaTypeVersion(BasePin
*base
)
476 static HRESULT WINAPI
AVICompressorIn_GetMediaType(BasePin
*base
, int iPosition
, AM_MEDIA_TYPE
*amt
)
478 TRACE("(%p)->(%d %p)\n", base
, iPosition
, amt
);
482 static HRESULT WINAPI
AVICompressorIn_Receive(BaseInputPin
*base
, IMediaSample
*pSample
)
484 AVICompressor
*This
= impl_from_BasePin(&base
->pin
);
485 VIDEOINFOHEADER
*src_videoinfo
;
486 REFERENCE_TIME start
, stop
;
487 IMediaSample
*out_sample
;
489 IMediaSample2
*sample2
;
490 DWORD comp_flags
= 0;
497 TRACE("(%p)->(%p)\n", base
, pSample
);
500 FIXME("Driver not loaded\n");
504 hres
= IMediaSample_QueryInterface(pSample
, &IID_IMediaSample2
, (void**)&sample2
);
505 if(SUCCEEDED(hres
)) {
506 FIXME("Use IMediaSample2\n");
507 IMediaSample2_Release(sample2
);
510 is_preroll
= IMediaSample_IsPreroll(pSample
) == S_OK
;
511 sync_point
= IMediaSample_IsSyncPoint(pSample
) == S_OK
;
513 hres
= IMediaSample_GetTime(pSample
, &start
, &stop
);
515 WARN("GetTime failed: %08x\n", hres
);
519 hres
= IMediaSample_GetMediaType(pSample
, &mt
);
523 hres
= IMediaSample_GetPointer(pSample
, &ptr
);
525 WARN("GetPointer failed: %08x\n", hres
);
529 hres
= BaseOutputPinImpl_GetDeliveryBuffer(This
->out
, &out_sample
, &start
, &stop
, 0);
533 hres
= IMediaSample_GetPointer(out_sample
, &buf
);
537 if((This
->driver_flags
& VIDCF_TEMPORAL
) && !(This
->driver_flags
& VIDCF_FASTTEMPORALC
))
538 FIXME("Unsupported temporal compression\n");
540 src_videoinfo
= (VIDEOINFOHEADER
*)This
->in
->pin
.mtCurrent
.pbFormat
;
541 res
= ICCompress(This
->hic
, sync_point
? ICCOMPRESS_KEYFRAME
: 0, &This
->videoinfo
->bmiHeader
, buf
,
542 &src_videoinfo
->bmiHeader
, ptr
, 0, &comp_flags
, This
->frame_cnt
, 0, 0, NULL
, NULL
);
543 if(res
!= ICERR_OK
) {
544 WARN("ICCompress failed: %d\n", res
);
545 IMediaSample_Release(out_sample
);
549 IMediaSample_SetActualDataLength(out_sample
, This
->videoinfo
->bmiHeader
.biSizeImage
);
550 IMediaSample_SetPreroll(out_sample
, is_preroll
);
551 IMediaSample_SetSyncPoint(out_sample
, (comp_flags
&AVIIF_KEYFRAME
) != 0);
552 IMediaSample_SetDiscontinuity(out_sample
, (IMediaSample_IsDiscontinuity(pSample
) == S_OK
));
554 if (IMediaSample_GetMediaTime(pSample
, &start
, &stop
) == S_OK
)
555 IMediaSample_SetMediaTime(out_sample
, &start
, &stop
);
557 IMediaSample_SetMediaTime(out_sample
, NULL
, NULL
);
559 hres
= BaseOutputPinImpl_Deliver(This
->out
, out_sample
);
561 WARN("Deliver failed: %08x\n", hres
);
563 IMediaSample_Release(out_sample
);
568 static const BaseInputPinFuncTable AVICompressorBaseInputPinVtbl
= {
570 AVICompressorIn_CheckMediaType
,
572 AVICompressorIn_GetMediaTypeVersion
,
573 AVICompressorIn_GetMediaType
575 AVICompressorIn_Receive
578 static HRESULT WINAPI
AVICompressorOut_QueryInterface(IPin
*iface
, REFIID riid
, void **ppv
)
580 return BaseInputPinImpl_QueryInterface(iface
, riid
, ppv
);
583 static ULONG WINAPI
AVICompressorOut_AddRef(IPin
*iface
)
585 AVICompressor
*This
= impl_from_IPin(iface
);
586 return IBaseFilter_AddRef(&This
->filter
.IBaseFilter_iface
);
589 static ULONG WINAPI
AVICompressorOut_Release(IPin
*iface
)
591 AVICompressor
*This
= impl_from_IPin(iface
);
592 return IBaseFilter_Release(&This
->filter
.IBaseFilter_iface
);
595 static const IPinVtbl AVICompressorOutputPinVtbl
= {
596 AVICompressorOut_QueryInterface
,
597 AVICompressorOut_AddRef
,
598 AVICompressorOut_Release
,
599 BaseOutputPinImpl_Connect
,
600 BaseOutputPinImpl_ReceiveConnection
,
601 BaseOutputPinImpl_Disconnect
,
602 BasePinImpl_ConnectedTo
,
603 BasePinImpl_ConnectionMediaType
,
604 BasePinImpl_QueryPinInfo
,
605 BasePinImpl_QueryDirection
,
607 BasePinImpl_QueryAccept
,
608 BasePinImpl_EnumMediaTypes
,
609 BasePinImpl_QueryInternalConnections
,
610 BaseOutputPinImpl_EndOfStream
,
611 BaseOutputPinImpl_BeginFlush
,
612 BaseOutputPinImpl_EndFlush
,
613 BasePinImpl_NewSegment
616 static LONG WINAPI
AVICompressorOut_GetMediaTypeVersion(BasePin
*base
)
618 FIXME("(%p)\n", base
);
622 static HRESULT WINAPI
AVICompressorOut_GetMediaType(BasePin
*base
, int iPosition
, AM_MEDIA_TYPE
*amt
)
624 AVICompressor
*This
= impl_from_IBaseFilter(base
->pinInfo
.pFilter
);
626 TRACE("(%p)->(%d %p)\n", base
, iPosition
, amt
);
628 if(iPosition
|| !This
->videoinfo
)
631 amt
->majortype
= MEDIATYPE_Video
;
632 amt
->subtype
= MEDIASUBTYPE_PCM
;
633 amt
->bFixedSizeSamples
= FALSE
;
634 amt
->bTemporalCompression
= (This
->driver_flags
& VIDCF_TEMPORAL
) != 0;
635 amt
->lSampleSize
= This
->in
->pin
.mtCurrent
.lSampleSize
;
636 amt
->formattype
= FORMAT_VideoInfo
;
638 amt
->cbFormat
= This
->videoinfo_size
;
639 amt
->pbFormat
= (BYTE
*)This
->videoinfo
;
643 static HRESULT WINAPI
AVICompressorOut_DecideBufferSize(BaseOutputPin
*base
, IMemAllocator
*alloc
, ALLOCATOR_PROPERTIES
*ppropInputRequest
)
645 AVICompressor
*This
= impl_from_BasePin(&base
->pin
);
646 ALLOCATOR_PROPERTIES actual
;
648 TRACE("(%p)\n", This
);
650 if (!ppropInputRequest
->cBuffers
)
651 ppropInputRequest
->cBuffers
= 1;
652 if (ppropInputRequest
->cbBuffer
< This
->videoinfo
->bmiHeader
.biSizeImage
)
653 ppropInputRequest
->cbBuffer
= This
->videoinfo
->bmiHeader
.biSizeImage
;
654 if (!ppropInputRequest
->cbAlign
)
655 ppropInputRequest
->cbAlign
= 1;
657 return IMemAllocator_SetProperties(alloc
, ppropInputRequest
, &actual
);
660 static HRESULT WINAPI
AVICompressorOut_DecideAllocator(BaseOutputPin
*base
,
661 IMemInputPin
*pPin
, IMemAllocator
**pAlloc
)
663 TRACE("(%p)->(%p %p)\n", base
, pPin
, pAlloc
);
664 return BaseOutputPinImpl_DecideAllocator(base
, pPin
, pAlloc
);
667 static HRESULT WINAPI
AVICompressorOut_BreakConnect(BaseOutputPin
*base
)
669 FIXME("(%p)\n", base
);
673 static const BaseOutputPinFuncTable AVICompressorBaseOutputPinVtbl
= {
676 BaseOutputPinImpl_AttemptConnection
,
677 AVICompressorOut_GetMediaTypeVersion
,
678 AVICompressorOut_GetMediaType
680 AVICompressorOut_DecideBufferSize
,
681 AVICompressorOut_DecideAllocator
,
682 AVICompressorOut_BreakConnect
685 IUnknown
* WINAPI
QCAP_createAVICompressor(IUnknown
*outer
, HRESULT
*phr
)
687 PIN_INFO in_pin_info
= {NULL
, PINDIR_INPUT
, {'I','n','p','u','t',0}};
688 PIN_INFO out_pin_info
= {NULL
, PINDIR_OUTPUT
, {'O','u','t','p','u','t',0}};
689 AVICompressor
*compressor
;
694 compressor
= heap_alloc_zero(sizeof(*compressor
));
696 *phr
= E_NOINTERFACE
;
700 BaseFilter_Init(&compressor
->filter
, &AVICompressorVtbl
, &CLSID_AVICo
,
701 (DWORD_PTR
)(__FILE__
": AVICompressor.csFilter"), &filter_func_table
);
703 compressor
->IPersistPropertyBag_iface
.lpVtbl
= &PersistPropertyBagVtbl
;
705 in_pin_info
.pFilter
= &compressor
->filter
.IBaseFilter_iface
;
706 hres
= BaseInputPin_Construct(&AVICompressorInputPinVtbl
, sizeof(BaseInputPin
), &in_pin_info
,
707 &AVICompressorBaseInputPinVtbl
, &compressor
->filter
.csFilter
, NULL
, (IPin
**)&compressor
->in
);
709 IBaseFilter_Release(&compressor
->filter
.IBaseFilter_iface
);
714 out_pin_info
.pFilter
= &compressor
->filter
.IBaseFilter_iface
;
715 hres
= BaseOutputPin_Construct(&AVICompressorOutputPinVtbl
, sizeof(BaseOutputPin
), &out_pin_info
,
716 &AVICompressorBaseOutputPinVtbl
, &compressor
->filter
.csFilter
, (IPin
**)&compressor
->out
);
718 IBaseFilter_Release(&compressor
->filter
.IBaseFilter_iface
);
724 return (IUnknown
*)&compressor
->filter
.IBaseFilter_iface
;