qcap: Added AVICompressorIn_ReceiveConnection implementation.
[wine/multimedia.git] / dlls / qcap / avico.c
blob6c5d53fc8eb82390095a3d7f1388d5e22f08b09e
1 /*
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
19 #include <stdarg.h>
21 #define COBJMACROS
23 #include "windef.h"
24 #include "winbase.h"
25 #include "dshow.h"
26 #include "vfw.h"
27 #include "aviriff.h"
29 #include "qcap_main.h"
31 #include "wine/debug.h"
33 WINE_DEFAULT_DEBUG_CHANNEL(qcap);
35 typedef struct {
36 BaseFilter filter;
37 IPersistPropertyBag IPersistPropertyBag_iface;
39 BaseInputPin *in;
40 BaseOutputPin *out;
42 DWORD fcc_handler;
43 HIC hic;
45 VIDEOINFOHEADER *videoinfo;
46 size_t videoinfo_size;
47 DWORD driver_flags;
48 } AVICompressor;
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)
68 if(This->hic)
69 return S_OK;
71 This->hic = ICOpen(FCC('v','i','d','c'), This->fcc_handler, ICMODE_COMPRESS);
72 if(!This->hic) {
73 FIXME("ICOpen failed\n");
74 return E_FAIL;
77 return S_OK;
80 static HRESULT fill_format_info(AVICompressor *This, VIDEOINFOHEADER *src_videoinfo)
82 DWORD size;
83 ICINFO icinfo;
84 HRESULT hres;
86 hres = ensure_driver(This);
87 if(hres != S_OK)
88 return hres;
90 size = ICGetInfo(This->hic, &icinfo, sizeof(icinfo));
91 if(size != sizeof(icinfo))
92 return E_FAIL;
94 size = ICCompressGetFormatSize(This->hic, &src_videoinfo->bmiHeader);
95 if(!size) {
96 FIXME("ICCompressGetFormatSize failed\n");
97 return E_FAIL;
100 size += FIELD_OFFSET(VIDEOINFOHEADER, bmiHeader);
101 This->videoinfo = heap_alloc(size);
102 if(!This->videoinfo)
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;
112 return S_OK;
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;
134 }else {
135 FIXME("no interface for %s\n", debugstr_guid(riid));
136 *ppv = NULL;
137 return E_NOINTERFACE;
140 IUnknown_AddRef((IUnknown*)*ppv);
141 return S_OK;
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);
152 if(!ref) {
153 if(This->hic)
154 ICClose(This->hic);
155 heap_free(This->videoinfo);
156 if(This->in)
157 BaseInputPinImpl_Release(&This->in->pin.IPin_iface);
158 if(This->out)
159 BaseOutputPinImpl_Release(&This->out->pin.IPin_iface);
160 heap_free(This);
163 return ref;
166 static HRESULT WINAPI AVICompressor_Stop(IBaseFilter *iface)
168 AVICompressor *This = impl_from_IBaseFilter(iface);
169 FIXME("(%p)\n", This);
170 return E_NOTIMPL;
173 static HRESULT WINAPI AVICompressor_Pause(IBaseFilter *iface)
175 AVICompressor *This = impl_from_IBaseFilter(iface);
176 FIXME("(%p)\n", This);
177 return E_NOTIMPL;
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));
184 return E_NOTIMPL;
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);
198 return E_NOTIMPL;
201 static HRESULT WINAPI AVICompressor_QueryVendorInfo(IBaseFilter *iface, LPWSTR *pVendorInfo)
203 AVICompressor *This = impl_from_IBaseFilter(iface);
204 FIXME("(%p)->(%p)\n", This, pVendorInfo);
205 return E_NOTIMPL;
208 static const IBaseFilterVtbl AVICompressorVtbl = {
209 AVICompressor_QueryInterface,
210 BaseFilterImpl_AddRef,
211 AVICompressor_Release,
212 BaseFilterImpl_GetClassID,
213 AVICompressor_Stop,
214 AVICompressor_Pause,
215 AVICompressor_Run,
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);
229 IPin *ret;
231 TRACE("(%p)->(%d)\n", This, pos);
233 switch(pos) {
234 case 0:
235 ret = &This->in->pin.IPin_iface;
236 break;
237 case 1:
238 ret = &This->out->pin.IPin_iface;
239 break;
240 default:
241 TRACE("No pin %d\n", pos);
242 return NULL;
245 IPin_AddRef(ret);
246 return ret;
249 static LONG WINAPI AVICompressor_GetPinCount(BaseFilter *iface)
251 return 2;
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);
292 return E_NOTIMPL;
295 static HRESULT WINAPI AVICompressorPropertyBag_Load(IPersistPropertyBag *iface, IPropertyBag *pPropBag, IErrorLog *pErrorLog)
297 AVICompressor *This = impl_from_IPersistPropertyBag(iface);
298 BSTR str;
299 VARIANT v;
300 HRESULT hres;
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);
306 V_VT(&v) = VT_EMPTY;
307 hres = IPropertyBag_Read(pPropBag, fcc_handlerW, &v, NULL);
308 if(FAILED(hres)) {
309 WARN("Could not read FccHandler: %08x\n", hres);
310 return hres;
313 if(V_VT(&v) != VT_BSTR) {
314 FIXME("Got vt %d\n", V_VT(&v));
315 VariantClear(&v);
316 return E_FAIL;
319 str = V_BSTR(&v);
320 TRACE("FccHandler = %s\n", debugstr_w(str));
321 if(SysStringLen(str) != 4) {
322 FIXME("Invalid FccHandler len\n");
323 SysFreeString(str);
324 return E_FAIL;
327 This->fcc_handler = FCC(str[0], str[1], str[2], str[3]);
328 SysFreeString(str);
329 return S_OK;
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);
337 return E_NOTIMPL;
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);
377 HRESULT hres;
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);
383 if(FAILED(hres))
384 return hres;
386 hres = fill_format_info(This, (VIDEOINFOHEADER*)pmt->pbFormat);
387 if(FAILED(hres))
388 BasePinImpl_Disconnect(iface);
389 return hres;
392 static HRESULT WINAPI AVICompressorIn_Disconnect(IPin *iface)
394 AVICompressor *This = impl_from_IPin(iface);
395 FIXME("(%p)\n", This);
396 return E_NOTIMPL;
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,
410 BasePinImpl_QueryId,
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;
424 HRESULT hres;
425 DWORD res;
427 TRACE("(%p)->(AM_MEDIA_TYPE(%p))\n", base, pmt);
428 dump_AM_MEDIA_TYPE(pmt);
430 if(!IsEqualIID(&pmt->majortype, &MEDIATYPE_Video))
431 return S_FALSE;
433 if(!IsEqualIID(&pmt->formattype, &FORMAT_VideoInfo)) {
434 FIXME("formattype %s unsupported\n", debugstr_guid(&pmt->formattype));
435 return S_FALSE;
438 hres = ensure_driver(This);
439 if(hres != S_OK)
440 return hres;
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)
449 return 0;
452 static HRESULT WINAPI AVICompressorIn_GetMediaType(BasePin *base, int iPosition, AM_MEDIA_TYPE *amt)
454 TRACE("(%p)->(%d %p)\n", base, iPosition, amt);
455 return S_FALSE;
458 static const BasePinFuncTable AVICompressorInputBasePinVtbl = {
459 AVICompressorIn_CheckMediaType,
460 NULL,
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);
469 return E_NOTIMPL;
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,
504 BasePinImpl_QueryId,
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);
517 return 0;
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);
524 return E_NOTIMPL;
527 static const BasePinFuncTable AVICompressorOutputBasePinVtbl = {
528 NULL,
529 BaseOutputPinImpl_AttemptConnection,
530 AVICompressorOut_GetMediaTypeVersion,
531 AVICompressorOut_GetMediaType
534 static HRESULT WINAPI AVICompressorOut_DecideBufferSize(BaseOutputPin *base, IMemAllocator *alloc, ALLOCATOR_PROPERTIES *ppropInputRequest)
536 FIXME("\n");
537 return E_NOTIMPL;
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);
550 return E_NOTIMPL;
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;
564 HRESULT hres;
566 TRACE("\n");
568 compressor = heap_alloc_zero(sizeof(*compressor));
569 if(!compressor) {
570 *phr = E_NOINTERFACE;
571 return NULL;
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);
583 if(FAILED(hres)) {
584 IBaseFilter_Release(&compressor->filter.IBaseFilter_iface);
585 *phr = hres;
586 return NULL;
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);
593 if(FAILED(hres)) {
594 IBaseFilter_Release(&compressor->filter.IBaseFilter_iface);
595 *phr = hres;
596 return NULL;
599 *phr = S_OK;
600 return (IUnknown*)&compressor->filter.IBaseFilter_iface;