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"
32 #include "wine/heap.h"
34 WINE_DEFAULT_DEBUG_CHANNEL(qcap
);
38 IPersistPropertyBag IPersistPropertyBag_iface
;
46 VIDEOINFOHEADER
*videoinfo
;
47 size_t videoinfo_size
;
54 static inline AVICompressor
*impl_from_BaseFilter(BaseFilter
*filter
)
56 return CONTAINING_RECORD(filter
, AVICompressor
, filter
);
59 static inline AVICompressor
*impl_from_IBaseFilter(IBaseFilter
*iface
)
61 BaseFilter
*filter
= CONTAINING_RECORD(iface
, BaseFilter
, IBaseFilter_iface
);
62 return impl_from_BaseFilter(filter
);
65 static inline AVICompressor
*impl_from_BasePin(BasePin
*pin
)
67 return impl_from_IBaseFilter(pin
->pinInfo
.pFilter
);
70 static HRESULT
ensure_driver(AVICompressor
*This
)
75 This
->hic
= ICOpen(FCC('v','i','d','c'), This
->fcc_handler
, ICMODE_COMPRESS
);
77 FIXME("ICOpen failed\n");
84 static HRESULT
fill_format_info(AVICompressor
*This
, VIDEOINFOHEADER
*src_videoinfo
)
90 hres
= ensure_driver(This
);
94 size
= ICGetInfo(This
->hic
, &icinfo
, sizeof(icinfo
));
95 if(size
!= sizeof(icinfo
))
98 size
= ICCompressGetFormatSize(This
->hic
, &src_videoinfo
->bmiHeader
);
100 FIXME("ICCompressGetFormatSize failed\n");
104 size
+= FIELD_OFFSET(VIDEOINFOHEADER
, bmiHeader
);
105 This
->videoinfo
= heap_alloc(size
);
107 return E_OUTOFMEMORY
;
109 This
->videoinfo_size
= size
;
110 This
->driver_flags
= icinfo
.dwFlags
;
111 memset(This
->videoinfo
, 0, sizeof(*This
->videoinfo
));
112 ICCompressGetFormat(This
->hic
, &src_videoinfo
->bmiHeader
, &This
->videoinfo
->bmiHeader
);
114 This
->videoinfo
->dwBitRate
= 10000000/src_videoinfo
->AvgTimePerFrame
* This
->videoinfo
->bmiHeader
.biSizeImage
* 8;
115 This
->videoinfo
->AvgTimePerFrame
= src_videoinfo
->AvgTimePerFrame
;
116 This
->max_frame_size
= This
->videoinfo
->bmiHeader
.biSizeImage
;
120 static HRESULT WINAPI
AVICompressor_QueryInterface(IBaseFilter
*iface
, REFIID riid
, void **ppv
)
122 AVICompressor
*This
= impl_from_IBaseFilter(iface
);
124 if(IsEqualIID(riid
, &IID_IUnknown
)) {
125 TRACE("(%p)->(IID_IUnknown %p)\n", This
, ppv
);
126 *ppv
= &This
->filter
.IBaseFilter_iface
;
127 }else if(IsEqualIID(riid
, &IID_IPersist
)) {
128 TRACE("(%p)->(IID_IPersist %p)\n", This
, ppv
);
129 *ppv
= &This
->filter
.IBaseFilter_iface
;
130 }else if(IsEqualIID(riid
, &IID_IMediaFilter
)) {
131 TRACE("(%p)->(IID_IMediaFilter %p)\n", This
, ppv
);
132 *ppv
= &This
->filter
.IBaseFilter_iface
;
133 }else if(IsEqualIID(riid
, &IID_IBaseFilter
)) {
134 TRACE("(%p)->(IID_IBaseFilter %p)\n", This
, ppv
);
135 *ppv
= &This
->filter
.IBaseFilter_iface
;
136 }else if(IsEqualIID(riid
, &IID_IPersistPropertyBag
)) {
137 TRACE("(%p)->(IID_IPersistPropertyBag %p)\n", This
, ppv
);
138 *ppv
= &This
->IPersistPropertyBag_iface
;
140 FIXME("no interface for %s\n", debugstr_guid(riid
));
142 return E_NOINTERFACE
;
145 IUnknown_AddRef((IUnknown
*)*ppv
);
150 static ULONG WINAPI
AVICompressor_Release(IBaseFilter
*iface
)
152 AVICompressor
*This
= impl_from_IBaseFilter(iface
);
153 ULONG ref
= BaseFilterImpl_Release(&This
->filter
.IBaseFilter_iface
);
155 TRACE("(%p) ref=%d\n", This
, ref
);
160 heap_free(This
->videoinfo
);
162 BaseInputPinImpl_Release(&This
->in
->pin
.IPin_iface
);
164 BaseOutputPinImpl_Release(&This
->out
->pin
.IPin_iface
);
171 static HRESULT WINAPI
AVICompressor_Stop(IBaseFilter
*iface
)
173 AVICompressor
*This
= impl_from_IBaseFilter(iface
);
175 TRACE("(%p)\n", This
);
177 if(This
->filter
.state
== State_Stopped
)
180 ICCompressEnd(This
->hic
);
181 This
->filter
.state
= State_Stopped
;
185 static HRESULT WINAPI
AVICompressor_Pause(IBaseFilter
*iface
)
187 AVICompressor
*This
= impl_from_IBaseFilter(iface
);
188 FIXME("(%p)\n", This
);
192 static HRESULT WINAPI
AVICompressor_Run(IBaseFilter
*iface
, REFERENCE_TIME tStart
)
194 AVICompressor
*This
= impl_from_IBaseFilter(iface
);
197 TRACE("(%p)->(%s)\n", This
, wine_dbgstr_longlong(tStart
));
199 if(This
->filter
.state
== State_Running
)
202 hres
= IMemAllocator_Commit(This
->out
->pAllocator
);
204 FIXME("Commit failed: %08x\n", hres
);
210 This
->filter
.state
= State_Running
;
214 static HRESULT WINAPI
AVICompressor_QueryFilterInfo(IBaseFilter
*iface
, FILTER_INFO
*pInfo
)
216 AVICompressor
*This
= impl_from_IBaseFilter(iface
);
217 FIXME("(%p)->(%p)\n", This
, pInfo
);
221 static HRESULT WINAPI
AVICompressor_QueryVendorInfo(IBaseFilter
*iface
, LPWSTR
*pVendorInfo
)
223 AVICompressor
*This
= impl_from_IBaseFilter(iface
);
224 FIXME("(%p)->(%p)\n", This
, pVendorInfo
);
228 static const IBaseFilterVtbl AVICompressorVtbl
= {
229 AVICompressor_QueryInterface
,
230 BaseFilterImpl_AddRef
,
231 AVICompressor_Release
,
232 BaseFilterImpl_GetClassID
,
236 BaseFilterImpl_GetState
,
237 BaseFilterImpl_SetSyncSource
,
238 BaseFilterImpl_GetSyncSource
,
239 BaseFilterImpl_EnumPins
,
240 BaseFilterImpl_FindPin
,
241 AVICompressor_QueryFilterInfo
,
242 BaseFilterImpl_JoinFilterGraph
,
243 AVICompressor_QueryVendorInfo
246 static IPin
* WINAPI
AVICompressor_GetPin(BaseFilter
*iface
, int pos
)
248 AVICompressor
*This
= impl_from_BaseFilter(iface
);
251 TRACE("(%p)->(%d)\n", This
, pos
);
255 ret
= &This
->in
->pin
.IPin_iface
;
258 ret
= &This
->out
->pin
.IPin_iface
;
261 TRACE("No pin %d\n", pos
);
269 static LONG WINAPI
AVICompressor_GetPinCount(BaseFilter
*iface
)
274 static const BaseFilterFuncTable filter_func_table
= {
275 AVICompressor_GetPin
,
276 AVICompressor_GetPinCount
279 static AVICompressor
*impl_from_IPersistPropertyBag(IPersistPropertyBag
*iface
)
281 return CONTAINING_RECORD(iface
, AVICompressor
, IPersistPropertyBag_iface
);
284 static HRESULT WINAPI
AVICompressorPropertyBag_QueryInterface(IPersistPropertyBag
*iface
, REFIID riid
, void **ppv
)
286 AVICompressor
*This
= impl_from_IPersistPropertyBag(iface
);
287 return IBaseFilter_QueryInterface(&This
->filter
.IBaseFilter_iface
, riid
, ppv
);
290 static ULONG WINAPI
AVICompressorPropertyBag_AddRef(IPersistPropertyBag
*iface
)
292 AVICompressor
*This
= impl_from_IPersistPropertyBag(iface
);
293 return IBaseFilter_AddRef(&This
->filter
.IBaseFilter_iface
);
296 static ULONG WINAPI
AVICompressorPropertyBag_Release(IPersistPropertyBag
*iface
)
298 AVICompressor
*This
= impl_from_IPersistPropertyBag(iface
);
299 return IBaseFilter_Release(&This
->filter
.IBaseFilter_iface
);
302 static HRESULT WINAPI
AVICompressorPropertyBag_GetClassID(IPersistPropertyBag
*iface
, CLSID
*pClassID
)
304 AVICompressor
*This
= impl_from_IPersistPropertyBag(iface
);
305 return IBaseFilter_GetClassID(&This
->filter
.IBaseFilter_iface
, pClassID
);
308 static HRESULT WINAPI
AVICompressorPropertyBag_InitNew(IPersistPropertyBag
*iface
)
310 AVICompressor
*This
= impl_from_IPersistPropertyBag(iface
);
311 FIXME("(%p)->()\n", This
);
315 static HRESULT WINAPI
AVICompressorPropertyBag_Load(IPersistPropertyBag
*iface
, IPropertyBag
*pPropBag
, IErrorLog
*pErrorLog
)
317 AVICompressor
*This
= impl_from_IPersistPropertyBag(iface
);
322 static const WCHAR fcc_handlerW
[] = {'F','c','c','H','a','n','d','l','e','r',0};
324 TRACE("(%p)->(%p %p)\n", This
, pPropBag
, pErrorLog
);
327 hres
= IPropertyBag_Read(pPropBag
, fcc_handlerW
, &v
, NULL
);
329 WARN("Could not read FccHandler: %08x\n", hres
);
333 if(V_VT(&v
) != VT_BSTR
) {
334 FIXME("Got vt %d\n", V_VT(&v
));
340 TRACE("FccHandler = %s\n", debugstr_w(str
));
341 if(SysStringLen(str
) != 4) {
342 FIXME("Invalid FccHandler len\n");
347 This
->fcc_handler
= FCC(str
[0], str
[1], str
[2], str
[3]);
352 static HRESULT WINAPI
AVICompressorPropertyBag_Save(IPersistPropertyBag
*iface
, IPropertyBag
*pPropBag
,
353 BOOL fClearDirty
, BOOL fSaveAllProperties
)
355 AVICompressor
*This
= impl_from_IPersistPropertyBag(iface
);
356 FIXME("(%p)->(%p %x %x)\n", This
, pPropBag
, fClearDirty
, fSaveAllProperties
);
360 static const IPersistPropertyBagVtbl PersistPropertyBagVtbl
= {
361 AVICompressorPropertyBag_QueryInterface
,
362 AVICompressorPropertyBag_AddRef
,
363 AVICompressorPropertyBag_Release
,
364 AVICompressorPropertyBag_GetClassID
,
365 AVICompressorPropertyBag_InitNew
,
366 AVICompressorPropertyBag_Load
,
367 AVICompressorPropertyBag_Save
370 static inline AVICompressor
*impl_from_IPin(IPin
*iface
)
372 BasePin
*bp
= CONTAINING_RECORD(iface
, BasePin
, IPin_iface
);
373 return impl_from_IBaseFilter(bp
->pinInfo
.pFilter
);
376 static HRESULT WINAPI
AVICompressorIn_QueryInterface(IPin
*iface
, REFIID riid
, void **ppv
)
378 return BaseInputPinImpl_QueryInterface(iface
, riid
, ppv
);
381 static ULONG WINAPI
AVICompressorIn_AddRef(IPin
*iface
)
383 AVICompressor
*This
= impl_from_IPin(iface
);
384 return IBaseFilter_AddRef(&This
->filter
.IBaseFilter_iface
);
387 static ULONG WINAPI
AVICompressorIn_Release(IPin
*iface
)
389 AVICompressor
*This
= impl_from_IPin(iface
);
390 return IBaseFilter_Release(&This
->filter
.IBaseFilter_iface
);
393 static HRESULT WINAPI
AVICompressorIn_ReceiveConnection(IPin
*iface
,
394 IPin
*pConnector
, const AM_MEDIA_TYPE
*pmt
)
396 AVICompressor
*This
= impl_from_IPin(iface
);
399 TRACE("(%p)->(%p AM_MEDIA_TYPE(%p))\n", This
, pConnector
, pmt
);
400 dump_AM_MEDIA_TYPE(pmt
);
402 hres
= BaseInputPinImpl_ReceiveConnection(iface
, pConnector
, pmt
);
406 hres
= fill_format_info(This
, (VIDEOINFOHEADER
*)pmt
->pbFormat
);
408 BasePinImpl_Disconnect(iface
);
412 static HRESULT WINAPI
AVICompressorIn_Disconnect(IPin
*iface
)
414 AVICompressor
*This
= impl_from_IPin(iface
);
417 TRACE("(%p)\n", This
);
419 hres
= BasePinImpl_Disconnect(iface
);
423 heap_free(This
->videoinfo
);
424 This
->videoinfo
= NULL
;
428 static const IPinVtbl AVICompressorInputPinVtbl
= {
429 AVICompressorIn_QueryInterface
,
430 AVICompressorIn_AddRef
,
431 AVICompressorIn_Release
,
432 BaseInputPinImpl_Connect
,
433 AVICompressorIn_ReceiveConnection
,
434 AVICompressorIn_Disconnect
,
435 BasePinImpl_ConnectedTo
,
436 BasePinImpl_ConnectionMediaType
,
437 BasePinImpl_QueryPinInfo
,
438 BasePinImpl_QueryDirection
,
440 BasePinImpl_QueryAccept
,
441 BasePinImpl_EnumMediaTypes
,
442 BasePinImpl_QueryInternalConnections
,
443 BaseInputPinImpl_EndOfStream
,
444 BaseInputPinImpl_BeginFlush
,
445 BaseInputPinImpl_EndFlush
,
446 BaseInputPinImpl_NewSegment
449 static HRESULT WINAPI
AVICompressorIn_CheckMediaType(BasePin
*base
, const AM_MEDIA_TYPE
*pmt
)
451 AVICompressor
*This
= impl_from_BasePin(base
);
452 VIDEOINFOHEADER
*videoinfo
;
456 TRACE("(%p)->(AM_MEDIA_TYPE(%p))\n", base
, pmt
);
457 dump_AM_MEDIA_TYPE(pmt
);
459 if(!IsEqualIID(&pmt
->majortype
, &MEDIATYPE_Video
))
462 if(!IsEqualIID(&pmt
->formattype
, &FORMAT_VideoInfo
)) {
463 FIXME("formattype %s unsupported\n", debugstr_guid(&pmt
->formattype
));
467 hres
= ensure_driver(This
);
471 videoinfo
= (VIDEOINFOHEADER
*)pmt
->pbFormat
;
472 res
= ICCompressQuery(This
->hic
, &videoinfo
->bmiHeader
, NULL
);
473 return res
== ICERR_OK
? S_OK
: S_FALSE
;
476 static LONG WINAPI
AVICompressorIn_GetMediaTypeVersion(BasePin
*base
)
481 static HRESULT WINAPI
AVICompressorIn_GetMediaType(BasePin
*base
, int iPosition
, AM_MEDIA_TYPE
*amt
)
483 TRACE("(%p)->(%d %p)\n", base
, iPosition
, amt
);
487 static HRESULT WINAPI
AVICompressorIn_Receive(BaseInputPin
*base
, IMediaSample
*pSample
)
489 AVICompressor
*This
= impl_from_BasePin(&base
->pin
);
490 VIDEOINFOHEADER
*src_videoinfo
;
491 REFERENCE_TIME start
, stop
;
492 IMediaSample
*out_sample
;
494 IMediaSample2
*sample2
;
495 DWORD comp_flags
= 0;
502 TRACE("(%p)->(%p)\n", base
, pSample
);
505 FIXME("Driver not loaded\n");
509 hres
= IMediaSample_QueryInterface(pSample
, &IID_IMediaSample2
, (void**)&sample2
);
510 if(SUCCEEDED(hres
)) {
511 FIXME("Use IMediaSample2\n");
512 IMediaSample2_Release(sample2
);
515 is_preroll
= IMediaSample_IsPreroll(pSample
) == S_OK
;
516 sync_point
= IMediaSample_IsSyncPoint(pSample
) == S_OK
;
518 hres
= IMediaSample_GetTime(pSample
, &start
, &stop
);
520 WARN("GetTime failed: %08x\n", hres
);
524 hres
= IMediaSample_GetMediaType(pSample
, &mt
);
528 hres
= IMediaSample_GetPointer(pSample
, &ptr
);
530 WARN("GetPointer failed: %08x\n", hres
);
534 hres
= BaseOutputPinImpl_GetDeliveryBuffer(This
->out
, &out_sample
, &start
, &stop
, 0);
538 hres
= IMediaSample_GetPointer(out_sample
, &buf
);
542 if((This
->driver_flags
& VIDCF_TEMPORAL
) && !(This
->driver_flags
& VIDCF_FASTTEMPORALC
))
543 FIXME("Unsupported temporal compression\n");
545 src_videoinfo
= (VIDEOINFOHEADER
*)This
->in
->pin
.mtCurrent
.pbFormat
;
546 This
->videoinfo
->bmiHeader
.biSizeImage
= This
->max_frame_size
;
547 res
= ICCompress(This
->hic
, sync_point
? ICCOMPRESS_KEYFRAME
: 0, &This
->videoinfo
->bmiHeader
, buf
,
548 &src_videoinfo
->bmiHeader
, ptr
, 0, &comp_flags
, This
->frame_cnt
, 0, 0, NULL
, NULL
);
549 if(res
!= ICERR_OK
) {
550 WARN("ICCompress failed: %d\n", res
);
551 IMediaSample_Release(out_sample
);
555 IMediaSample_SetActualDataLength(out_sample
, This
->videoinfo
->bmiHeader
.biSizeImage
);
556 IMediaSample_SetPreroll(out_sample
, is_preroll
);
557 IMediaSample_SetSyncPoint(out_sample
, (comp_flags
&AVIIF_KEYFRAME
) != 0);
558 IMediaSample_SetDiscontinuity(out_sample
, (IMediaSample_IsDiscontinuity(pSample
) == S_OK
));
560 if (IMediaSample_GetMediaTime(pSample
, &start
, &stop
) == S_OK
)
561 IMediaSample_SetMediaTime(out_sample
, &start
, &stop
);
563 IMediaSample_SetMediaTime(out_sample
, NULL
, NULL
);
565 hres
= BaseOutputPinImpl_Deliver(This
->out
, out_sample
);
567 WARN("Deliver failed: %08x\n", hres
);
569 IMediaSample_Release(out_sample
);
574 static const BaseInputPinFuncTable AVICompressorBaseInputPinVtbl
= {
576 AVICompressorIn_CheckMediaType
,
578 AVICompressorIn_GetMediaTypeVersion
,
579 AVICompressorIn_GetMediaType
581 AVICompressorIn_Receive
584 static HRESULT WINAPI
AVICompressorOut_QueryInterface(IPin
*iface
, REFIID riid
, void **ppv
)
586 return BaseInputPinImpl_QueryInterface(iface
, riid
, ppv
);
589 static ULONG WINAPI
AVICompressorOut_AddRef(IPin
*iface
)
591 AVICompressor
*This
= impl_from_IPin(iface
);
592 return IBaseFilter_AddRef(&This
->filter
.IBaseFilter_iface
);
595 static ULONG WINAPI
AVICompressorOut_Release(IPin
*iface
)
597 AVICompressor
*This
= impl_from_IPin(iface
);
598 return IBaseFilter_Release(&This
->filter
.IBaseFilter_iface
);
601 static const IPinVtbl AVICompressorOutputPinVtbl
= {
602 AVICompressorOut_QueryInterface
,
603 AVICompressorOut_AddRef
,
604 AVICompressorOut_Release
,
605 BaseOutputPinImpl_Connect
,
606 BaseOutputPinImpl_ReceiveConnection
,
607 BaseOutputPinImpl_Disconnect
,
608 BasePinImpl_ConnectedTo
,
609 BasePinImpl_ConnectionMediaType
,
610 BasePinImpl_QueryPinInfo
,
611 BasePinImpl_QueryDirection
,
613 BasePinImpl_QueryAccept
,
614 BasePinImpl_EnumMediaTypes
,
615 BasePinImpl_QueryInternalConnections
,
616 BaseOutputPinImpl_EndOfStream
,
617 BaseOutputPinImpl_BeginFlush
,
618 BaseOutputPinImpl_EndFlush
,
619 BasePinImpl_NewSegment
622 static LONG WINAPI
AVICompressorOut_GetMediaTypeVersion(BasePin
*base
)
624 FIXME("(%p)\n", base
);
628 static HRESULT WINAPI
AVICompressorOut_GetMediaType(BasePin
*base
, int iPosition
, AM_MEDIA_TYPE
*amt
)
630 AVICompressor
*This
= impl_from_IBaseFilter(base
->pinInfo
.pFilter
);
632 TRACE("(%p)->(%d %p)\n", base
, iPosition
, amt
);
634 if(iPosition
|| !This
->videoinfo
)
637 amt
->majortype
= MEDIATYPE_Video
;
638 amt
->subtype
= MEDIASUBTYPE_PCM
;
639 amt
->bFixedSizeSamples
= FALSE
;
640 amt
->bTemporalCompression
= (This
->driver_flags
& VIDCF_TEMPORAL
) != 0;
641 amt
->lSampleSize
= This
->in
->pin
.mtCurrent
.lSampleSize
;
642 amt
->formattype
= FORMAT_VideoInfo
;
644 amt
->cbFormat
= This
->videoinfo_size
;
645 amt
->pbFormat
= (BYTE
*)This
->videoinfo
;
649 static HRESULT WINAPI
AVICompressorOut_DecideBufferSize(BaseOutputPin
*base
, IMemAllocator
*alloc
, ALLOCATOR_PROPERTIES
*ppropInputRequest
)
651 AVICompressor
*This
= impl_from_BasePin(&base
->pin
);
652 ALLOCATOR_PROPERTIES actual
;
654 TRACE("(%p)\n", This
);
656 if (!ppropInputRequest
->cBuffers
)
657 ppropInputRequest
->cBuffers
= 1;
658 if (ppropInputRequest
->cbBuffer
< This
->max_frame_size
)
659 ppropInputRequest
->cbBuffer
= This
->max_frame_size
;
660 if (!ppropInputRequest
->cbAlign
)
661 ppropInputRequest
->cbAlign
= 1;
663 return IMemAllocator_SetProperties(alloc
, ppropInputRequest
, &actual
);
666 static HRESULT WINAPI
AVICompressorOut_DecideAllocator(BaseOutputPin
*base
,
667 IMemInputPin
*pPin
, IMemAllocator
**pAlloc
)
669 TRACE("(%p)->(%p %p)\n", base
, pPin
, pAlloc
);
670 return BaseOutputPinImpl_DecideAllocator(base
, pPin
, pAlloc
);
673 static HRESULT WINAPI
AVICompressorOut_BreakConnect(BaseOutputPin
*base
)
675 FIXME("(%p)\n", base
);
679 static const BaseOutputPinFuncTable AVICompressorBaseOutputPinVtbl
= {
682 BaseOutputPinImpl_AttemptConnection
,
683 AVICompressorOut_GetMediaTypeVersion
,
684 AVICompressorOut_GetMediaType
686 AVICompressorOut_DecideBufferSize
,
687 AVICompressorOut_DecideAllocator
,
688 AVICompressorOut_BreakConnect
691 IUnknown
* WINAPI
QCAP_createAVICompressor(IUnknown
*outer
, HRESULT
*phr
)
693 PIN_INFO in_pin_info
= {NULL
, PINDIR_INPUT
, {'I','n','p','u','t',0}};
694 PIN_INFO out_pin_info
= {NULL
, PINDIR_OUTPUT
, {'O','u','t','p','u','t',0}};
695 AVICompressor
*compressor
;
700 compressor
= heap_alloc_zero(sizeof(*compressor
));
702 *phr
= E_NOINTERFACE
;
706 BaseFilter_Init(&compressor
->filter
, &AVICompressorVtbl
, &CLSID_AVICo
,
707 (DWORD_PTR
)(__FILE__
": AVICompressor.csFilter"), &filter_func_table
);
709 compressor
->IPersistPropertyBag_iface
.lpVtbl
= &PersistPropertyBagVtbl
;
711 in_pin_info
.pFilter
= &compressor
->filter
.IBaseFilter_iface
;
712 hres
= BaseInputPin_Construct(&AVICompressorInputPinVtbl
, sizeof(BaseInputPin
), &in_pin_info
,
713 &AVICompressorBaseInputPinVtbl
, &compressor
->filter
.csFilter
, NULL
, (IPin
**)&compressor
->in
);
715 IBaseFilter_Release(&compressor
->filter
.IBaseFilter_iface
);
720 out_pin_info
.pFilter
= &compressor
->filter
.IBaseFilter_iface
;
721 hres
= BaseOutputPin_Construct(&AVICompressorOutputPinVtbl
, sizeof(BaseOutputPin
), &out_pin_info
,
722 &AVICompressorBaseOutputPinVtbl
, &compressor
->filter
.csFilter
, (IPin
**)&compressor
->out
);
724 IBaseFilter_Release(&compressor
->filter
.IBaseFilter_iface
);
730 return (IUnknown
*)&compressor
->filter
.IBaseFilter_iface
;