2 * AVI Decompressor (VFW decompressors wrapper)
4 * Copyright 2004-2005 Christian Costa
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
21 #include "quartz_private.h"
35 #include "wine/debug.h"
37 WINE_DEFAULT_DEBUG_CHANNEL(quartz
);
39 struct avi_decompressor
41 struct strmbase_filter filter
;
42 CRITICAL_SECTION stream_cs
;
44 struct strmbase_source source
;
45 IQualityControl source_IQualityControl_iface
;
46 struct strmbase_passthrough passthrough
;
48 struct strmbase_sink sink
;
51 BITMAPINFOHEADER
* pBihIn
;
55 static struct avi_decompressor
*impl_from_strmbase_filter(struct strmbase_filter
*iface
)
57 return CONTAINING_RECORD(iface
, struct avi_decompressor
, filter
);
60 static HRESULT
avi_decompressor_sink_query_interface(struct strmbase_pin
*iface
, REFIID iid
, void **out
)
62 struct avi_decompressor
*filter
= impl_from_strmbase_filter(iface
->filter
);
64 if (IsEqualGUID(iid
, &IID_IMemInputPin
))
65 *out
= &filter
->sink
.IMemInputPin_iface
;
69 IUnknown_AddRef((IUnknown
*)*out
);
73 static HRESULT
avi_decompressor_sink_query_accept(struct strmbase_pin
*iface
, const AM_MEDIA_TYPE
*mt
)
78 static HRESULT
avi_decompressor_sink_end_flush(struct strmbase_sink
*iface
)
80 struct avi_decompressor
*filter
= impl_from_strmbase_filter(iface
->pin
.filter
);
82 if (filter
->source
.pin
.peer
)
83 return IPin_EndFlush(filter
->source
.pin
.peer
);
87 static int AVIDec_DropSample(struct avi_decompressor
*This
, REFERENCE_TIME tStart
)
92 if (tStart
< This
->late
) {
93 TRACE("Dropping sample\n");
100 static HRESULT WINAPI
avi_decompressor_sink_Receive(struct strmbase_sink
*iface
, IMediaSample
*pSample
)
102 struct avi_decompressor
*This
= impl_from_strmbase_filter(iface
->pin
.filter
);
103 VIDEOINFOHEADER
*source_format
;
106 IMediaSample
* pOutSample
= NULL
;
111 LONGLONG tStart
, tStop
;
114 /* We do not expect pin connection state to change while the filter is
115 * running. This guarantee is necessary, since otherwise we would have to
116 * take the filter lock, and we can't take the filter lock from a streaming
118 if (!This
->source
.pMemInputPin
)
120 WARN("Source is not connected, returning VFW_E_NOT_CONNECTED.\n");
121 return VFW_E_NOT_CONNECTED
;
124 source_format
= (VIDEOINFOHEADER
*)This
->source
.pin
.mt
.pbFormat
;
126 if (This
->filter
.state
== State_Stopped
)
127 return VFW_E_WRONG_STATE
;
129 if (This
->sink
.flushing
)
132 EnterCriticalSection(&This
->stream_cs
);
134 hr
= IMediaSample_GetPointer(pSample
, &pbSrcStream
);
137 ERR("Cannot get pointer to sample data (%x)\n", hr
);
138 LeaveCriticalSection(&This
->stream_cs
);
142 cbSrcStream
= IMediaSample_GetActualDataLength(pSample
);
144 TRACE("Sample data ptr = %p, size = %d\n", pbSrcStream
, cbSrcStream
);
146 /* Update input size to match sample size */
147 This
->pBihIn
->biSizeImage
= cbSrcStream
;
149 hr
= BaseOutputPinImpl_GetDeliveryBuffer(&This
->source
, &pOutSample
, NULL
, NULL
, 0);
151 ERR("Unable to get delivery buffer (%x)\n", hr
);
152 LeaveCriticalSection(&This
->stream_cs
);
156 hr
= IMediaSample_SetActualDataLength(pOutSample
, 0);
159 hr
= IMediaSample_GetPointer(pOutSample
, &pbDstStream
);
161 ERR("Unable to get pointer to buffer (%x)\n", hr
);
162 IMediaSample_Release(pOutSample
);
163 LeaveCriticalSection(&This
->stream_cs
);
166 cbDstStream
= IMediaSample_GetSize(pOutSample
);
167 if (cbDstStream
< source_format
->bmiHeader
.biSizeImage
)
169 ERR("Sample size is too small (%u < %u).\n", cbDstStream
, source_format
->bmiHeader
.biSizeImage
);
170 IMediaSample_Release(pOutSample
);
171 LeaveCriticalSection(&This
->stream_cs
);
175 if (IMediaSample_IsPreroll(pSample
) == S_OK
)
176 flags
|= ICDECOMPRESS_PREROLL
;
177 if (IMediaSample_IsSyncPoint(pSample
) != S_OK
)
178 flags
|= ICDECOMPRESS_NOTKEYFRAME
;
179 hr
= IMediaSample_GetTime(pSample
, &tStart
, &tStop
);
180 if (hr
== S_OK
&& AVIDec_DropSample(This
, tStart
))
181 flags
|= ICDECOMPRESS_HURRYUP
;
183 res
= ICDecompress(This
->hvid
, flags
, This
->pBihIn
, pbSrcStream
, &source_format
->bmiHeader
, pbDstStream
);
185 ERR("Error occurred during the decompression (%x)\n", res
);
187 /* Drop sample if it's intended to be dropped */
188 if (flags
& ICDECOMPRESS_HURRYUP
) {
189 IMediaSample_Release(pOutSample
);
190 LeaveCriticalSection(&This
->stream_cs
);
194 IMediaSample_SetActualDataLength(pOutSample
, source_format
->bmiHeader
.biSizeImage
);
196 IMediaSample_SetPreroll(pOutSample
, (IMediaSample_IsPreroll(pSample
) == S_OK
));
197 IMediaSample_SetDiscontinuity(pOutSample
, (IMediaSample_IsDiscontinuity(pSample
) == S_OK
));
198 IMediaSample_SetSyncPoint(pOutSample
, (IMediaSample_IsSyncPoint(pSample
) == S_OK
));
201 IMediaSample_SetTime(pOutSample
, &tStart
, &tStop
);
202 else if (hr
== VFW_S_NO_STOP_TIME
)
203 IMediaSample_SetTime(pOutSample
, &tStart
, NULL
);
205 IMediaSample_SetTime(pOutSample
, NULL
, NULL
);
207 if (IMediaSample_GetMediaTime(pSample
, &tStart
, &tStop
) == S_OK
)
208 IMediaSample_SetMediaTime(pOutSample
, &tStart
, &tStop
);
210 IMediaSample_SetMediaTime(pOutSample
, NULL
, NULL
);
212 hr
= IMemInputPin_Receive(This
->source
.pMemInputPin
, pOutSample
);
213 if (hr
!= S_OK
&& hr
!= VFW_E_NOT_CONNECTED
)
214 ERR("Error sending sample (%x)\n", hr
);
216 IMediaSample_Release(pOutSample
);
217 LeaveCriticalSection(&This
->stream_cs
);
221 static HRESULT
avi_decompressor_sink_connect(struct strmbase_sink
*iface
, IPin
*peer
, const AM_MEDIA_TYPE
*pmt
)
223 struct avi_decompressor
*This
= impl_from_strmbase_filter(iface
->pin
.filter
);
224 HRESULT hr
= VFW_E_TYPE_NOT_ACCEPTED
;
226 /* Check root (GUID w/o FOURCC) */
227 if ((IsEqualIID(&pmt
->majortype
, &MEDIATYPE_Video
)) &&
228 (!memcmp(((const char *)&pmt
->subtype
)+4, ((const char *)&MEDIATYPE_Video
)+4, sizeof(GUID
)-4)))
230 VIDEOINFOHEADER
*format1
= (VIDEOINFOHEADER
*)pmt
->pbFormat
;
231 VIDEOINFOHEADER2
*format2
= (VIDEOINFOHEADER2
*)pmt
->pbFormat
;
232 BITMAPINFOHEADER
*bmi
;
234 if (IsEqualIID(&pmt
->formattype
, &FORMAT_VideoInfo
))
235 bmi
= &format1
->bmiHeader
;
236 else if (IsEqualIID(&pmt
->formattype
, &FORMAT_VideoInfo2
))
237 bmi
= &format2
->bmiHeader
;
241 This
->hvid
= ICLocate(pmt
->majortype
.Data1
, pmt
->subtype
.Data1
, bmi
, NULL
, ICMODE_DECOMPRESS
);
247 /* Copy bitmap header from media type to 1 for input and 1 for output */
248 bih_size
= bmi
->biSize
+ bmi
->biClrUsed
* 4;
249 This
->pBihIn
= CoTaskMemAlloc(bih_size
);
255 memcpy(This
->pBihIn
, bmi
, bih_size
);
257 if ((result
= ICDecompressQuery(This
->hvid
, This
->pBihIn
, NULL
)))
259 WARN("No decompressor found, error %d.\n", result
);
260 return VFW_E_TYPE_NOT_ACCEPTED
;
263 TRACE("Connection accepted\n");
266 TRACE("Unable to find a suitable VFW decompressor\n");
271 TRACE("Connection refused\n");
275 static void avi_decompressor_sink_disconnect(struct strmbase_sink
*iface
)
277 struct avi_decompressor
*filter
= impl_from_strmbase_filter(iface
->pin
.filter
);
280 ICClose(filter
->hvid
);
281 CoTaskMemFree(filter
->pBihIn
);
283 filter
->pBihIn
= NULL
;
286 static const struct strmbase_sink_ops sink_ops
=
288 .base
.pin_query_interface
= avi_decompressor_sink_query_interface
,
289 .base
.pin_query_accept
= avi_decompressor_sink_query_accept
,
290 .base
.pin_get_media_type
= strmbase_pin_get_media_type
,
291 .pfnReceive
= avi_decompressor_sink_Receive
,
292 .sink_connect
= avi_decompressor_sink_connect
,
293 .sink_disconnect
= avi_decompressor_sink_disconnect
,
294 .sink_end_flush
= avi_decompressor_sink_end_flush
,
297 static HRESULT
avi_decompressor_source_query_interface(struct strmbase_pin
*iface
, REFIID iid
, void **out
)
299 struct avi_decompressor
*filter
= impl_from_strmbase_filter(iface
->filter
);
301 if (IsEqualGUID(iid
, &IID_IQualityControl
))
302 *out
= &filter
->source_IQualityControl_iface
;
303 else if (IsEqualGUID(iid
, &IID_IMediaSeeking
))
304 *out
= &filter
->passthrough
.IMediaSeeking_iface
;
306 return E_NOINTERFACE
;
308 IUnknown_AddRef((IUnknown
*)*out
);
312 static HRESULT
avi_decompressor_source_query_accept(struct strmbase_pin
*iface
, const AM_MEDIA_TYPE
*mt
)
314 struct avi_decompressor
*filter
= impl_from_strmbase_filter(iface
->filter
);
315 VIDEOINFOHEADER
*sink_format
, *format
;
317 if (!filter
->sink
.pin
.peer
|| !IsEqualGUID(&mt
->formattype
, &FORMAT_VideoInfo
))
320 sink_format
= (VIDEOINFOHEADER
*)filter
->sink
.pin
.mt
.pbFormat
;
321 format
= (VIDEOINFOHEADER
*)mt
->pbFormat
;
323 if (ICDecompressQuery(filter
->hvid
, &sink_format
->bmiHeader
, &format
->bmiHeader
))
329 static HRESULT
avi_decompressor_source_get_media_type(struct strmbase_pin
*iface
,
330 unsigned int index
, AM_MEDIA_TYPE
*mt
)
340 {&MEDIASUBTYPE_CLJR
, mmioFOURCC('C','L','J','R'), 8},
341 {&MEDIASUBTYPE_UYVY
, mmioFOURCC('U','Y','V','Y'), 16},
342 {&MEDIASUBTYPE_YUY2
, mmioFOURCC('Y','U','Y','2'), 16},
343 {&MEDIASUBTYPE_RGB32
, BI_RGB
, 32},
344 {&MEDIASUBTYPE_RGB24
, BI_RGB
, 24},
345 {&MEDIASUBTYPE_RGB565
, BI_BITFIELDS
, 16},
346 {&MEDIASUBTYPE_RGB555
, BI_RGB
, 16},
347 {&MEDIASUBTYPE_RGB8
, BI_RGB
, 8},
350 struct avi_decompressor
*filter
= impl_from_strmbase_filter(iface
->filter
);
351 const VIDEOINFOHEADER
*sink_format
;
354 if (!filter
->sink
.pin
.peer
)
355 return VFW_S_NO_MORE_ITEMS
;
357 sink_format
= (VIDEOINFOHEADER
*)filter
->sink
.pin
.mt
.pbFormat
;
359 memset(mt
, 0, sizeof(AM_MEDIA_TYPE
));
361 if (index
< ARRAY_SIZE(formats
))
363 if (!(format
= CoTaskMemAlloc(offsetof(VIDEOINFO
, dwBitMasks
[3]))))
364 return E_OUTOFMEMORY
;
365 memset(format
, 0, offsetof(VIDEOINFO
, dwBitMasks
[3]));
367 format
->rcSource
= sink_format
->rcSource
;
368 format
->rcTarget
= sink_format
->rcTarget
;
369 format
->dwBitRate
= sink_format
->dwBitRate
;
370 format
->dwBitErrorRate
= sink_format
->dwBitErrorRate
;
371 format
->AvgTimePerFrame
= sink_format
->AvgTimePerFrame
;
373 format
->bmiHeader
.biSize
= sizeof(BITMAPINFOHEADER
);
374 format
->bmiHeader
.biWidth
= sink_format
->bmiHeader
.biWidth
;
375 format
->bmiHeader
.biHeight
= sink_format
->bmiHeader
.biHeight
;
376 format
->bmiHeader
.biPlanes
= sink_format
->bmiHeader
.biPlanes
;
377 format
->bmiHeader
.biBitCount
= formats
[index
].bpp
;
378 format
->bmiHeader
.biCompression
= formats
[index
].compression
;
379 format
->bmiHeader
.biSizeImage
= format
->bmiHeader
.biWidth
380 * format
->bmiHeader
.biHeight
* formats
[index
].bpp
/ 8;
382 if (IsEqualGUID(formats
[index
].subtype
, &MEDIASUBTYPE_RGB565
))
384 format
->dwBitMasks
[iRED
] = 0xf800;
385 format
->dwBitMasks
[iGREEN
] = 0x07e0;
386 format
->dwBitMasks
[iBLUE
] = 0x001f;
387 mt
->cbFormat
= offsetof(VIDEOINFO
, dwBitMasks
[3]);
390 mt
->cbFormat
= sizeof(VIDEOINFOHEADER
);
392 mt
->majortype
= MEDIATYPE_Video
;
393 mt
->subtype
= *formats
[index
].subtype
;
394 mt
->bFixedSizeSamples
= TRUE
;
395 mt
->lSampleSize
= format
->bmiHeader
.biSizeImage
;
396 mt
->formattype
= FORMAT_VideoInfo
;
397 mt
->pbFormat
= (BYTE
*)format
;
402 if (index
== ARRAY_SIZE(formats
))
404 size_t size
= ICDecompressGetFormatSize(filter
->hvid
, &sink_format
->bmiHeader
);
407 return VFW_S_NO_MORE_ITEMS
;
409 mt
->cbFormat
= offsetof(VIDEOINFOHEADER
, bmiHeader
) + size
;
410 if (!(format
= CoTaskMemAlloc(mt
->cbFormat
)))
411 return E_OUTOFMEMORY
;
412 memset(format
, 0, mt
->cbFormat
);
414 format
->rcSource
= sink_format
->rcSource
;
415 format
->rcTarget
= sink_format
->rcTarget
;
416 format
->dwBitRate
= sink_format
->dwBitRate
;
417 format
->dwBitErrorRate
= sink_format
->dwBitErrorRate
;
418 format
->AvgTimePerFrame
= sink_format
->AvgTimePerFrame
;
420 if (ICDecompressGetFormat(filter
->hvid
, &sink_format
->bmiHeader
, &format
->bmiHeader
))
422 CoTaskMemFree(format
);
423 return VFW_S_NO_MORE_ITEMS
;
426 mt
->majortype
= MEDIATYPE_Video
;
427 mt
->subtype
= MEDIATYPE_Video
;
428 mt
->subtype
.Data1
= format
->bmiHeader
.biCompression
;
429 mt
->bFixedSizeSamples
= TRUE
;
430 mt
->lSampleSize
= format
->bmiHeader
.biSizeImage
;
431 mt
->formattype
= FORMAT_VideoInfo
;
432 mt
->pbFormat
= (BYTE
*)format
;
437 return VFW_S_NO_MORE_ITEMS
;
440 static HRESULT WINAPI
avi_decompressor_source_DecideBufferSize(struct strmbase_source
*iface
,
441 IMemAllocator
*pAlloc
, ALLOCATOR_PROPERTIES
*ppropInputRequest
)
443 const VIDEOINFOHEADER
*source_format
= (VIDEOINFOHEADER
*)iface
->pin
.mt
.pbFormat
;
444 ALLOCATOR_PROPERTIES actual
;
446 if (!ppropInputRequest
->cbAlign
)
447 ppropInputRequest
->cbAlign
= 1;
449 if (ppropInputRequest
->cbBuffer
< source_format
->bmiHeader
.biSizeImage
)
450 ppropInputRequest
->cbBuffer
= source_format
->bmiHeader
.biSizeImage
;
452 if (!ppropInputRequest
->cBuffers
)
453 ppropInputRequest
->cBuffers
= 1;
455 return IMemAllocator_SetProperties(pAlloc
, ppropInputRequest
, &actual
);
458 static const struct strmbase_source_ops source_ops
=
460 .base
.pin_query_interface
= avi_decompressor_source_query_interface
,
461 .base
.pin_query_accept
= avi_decompressor_source_query_accept
,
462 .base
.pin_get_media_type
= avi_decompressor_source_get_media_type
,
463 .pfnAttemptConnection
= BaseOutputPinImpl_AttemptConnection
,
464 .pfnDecideAllocator
= BaseOutputPinImpl_DecideAllocator
,
465 .pfnDecideBufferSize
= avi_decompressor_source_DecideBufferSize
,
468 static struct avi_decompressor
*impl_from_source_IQualityControl(IQualityControl
*iface
)
470 return CONTAINING_RECORD(iface
, struct avi_decompressor
, source_IQualityControl_iface
);
473 static HRESULT WINAPI
avi_decompressor_source_qc_QueryInterface(IQualityControl
*iface
,
474 REFIID iid
, void **out
)
476 struct avi_decompressor
*filter
= impl_from_source_IQualityControl(iface
);
477 return IPin_QueryInterface(&filter
->source
.pin
.IPin_iface
, iid
, out
);
480 static ULONG WINAPI
avi_decompressor_source_qc_AddRef(IQualityControl
*iface
)
482 struct avi_decompressor
*filter
= impl_from_source_IQualityControl(iface
);
483 return IPin_AddRef(&filter
->source
.pin
.IPin_iface
);
486 static ULONG WINAPI
avi_decompressor_source_qc_Release(IQualityControl
*iface
)
488 struct avi_decompressor
*filter
= impl_from_source_IQualityControl(iface
);
489 return IPin_Release(&filter
->source
.pin
.IPin_iface
);
492 static HRESULT WINAPI
avi_decompressor_source_qc_Notify(IQualityControl
*iface
,
493 IBaseFilter
*sender
, Quality q
)
495 struct avi_decompressor
*filter
= impl_from_source_IQualityControl(iface
);
497 TRACE("filter %p, sender %p, type %#x, proportion %u, late %s, timestamp %s.\n",
498 filter
, sender
, q
.Type
, q
.Proportion
, debugstr_time(q
.Late
), debugstr_time(q
.TimeStamp
));
500 EnterCriticalSection(&filter
->stream_cs
);
502 filter
->late
= q
.Late
+ q
.TimeStamp
;
505 LeaveCriticalSection(&filter
->stream_cs
);
509 static HRESULT WINAPI
avi_decompressor_source_qc_SetSink(IQualityControl
*iface
, IQualityControl
*sink
)
511 struct avi_decompressor
*filter
= impl_from_source_IQualityControl(iface
);
513 TRACE("filter %p, sink %p.\n", filter
, sink
);
518 static const IQualityControlVtbl source_qc_vtbl
=
520 avi_decompressor_source_qc_QueryInterface
,
521 avi_decompressor_source_qc_AddRef
,
522 avi_decompressor_source_qc_Release
,
523 avi_decompressor_source_qc_Notify
,
524 avi_decompressor_source_qc_SetSink
,
527 static struct strmbase_pin
*avi_decompressor_get_pin(struct strmbase_filter
*iface
, unsigned int index
)
529 struct avi_decompressor
*filter
= impl_from_strmbase_filter(iface
);
532 return &filter
->sink
.pin
;
534 return &filter
->source
.pin
;
538 static void avi_decompressor_destroy(struct strmbase_filter
*iface
)
540 struct avi_decompressor
*filter
= impl_from_strmbase_filter(iface
);
542 if (filter
->sink
.pin
.peer
)
543 IPin_Disconnect(filter
->sink
.pin
.peer
);
544 IPin_Disconnect(&filter
->sink
.pin
.IPin_iface
);
546 if (filter
->source
.pin
.peer
)
547 IPin_Disconnect(filter
->source
.pin
.peer
);
548 IPin_Disconnect(&filter
->source
.pin
.IPin_iface
);
550 strmbase_sink_cleanup(&filter
->sink
);
551 strmbase_source_cleanup(&filter
->source
);
552 strmbase_passthrough_cleanup(&filter
->passthrough
);
554 filter
->stream_cs
.DebugInfo
->Spare
[0] = 0;
555 DeleteCriticalSection(&filter
->stream_cs
);
556 strmbase_filter_cleanup(&filter
->filter
);
559 InterlockedDecrement(&object_locks
);
562 static HRESULT
avi_decompressor_init_stream(struct strmbase_filter
*iface
)
564 struct avi_decompressor
*filter
= impl_from_strmbase_filter(iface
);
565 VIDEOINFOHEADER
*source_format
;
570 source_format
= (VIDEOINFOHEADER
*)filter
->sink
.pin
.mt
.pbFormat
;
571 if ((res
= ICDecompressBegin(filter
->hvid
, filter
->pBihIn
, &source_format
->bmiHeader
)))
573 ERR("ICDecompressBegin() failed, error %ld.\n", res
);
577 BaseOutputPinImpl_Active(&filter
->source
);
581 static HRESULT
avi_decompressor_cleanup_stream(struct strmbase_filter
*iface
)
583 struct avi_decompressor
*filter
= impl_from_strmbase_filter(iface
);
586 if (filter
->hvid
&& (res
= ICDecompressEnd(filter
->hvid
)))
588 ERR("ICDecompressEnd() failed, error %ld.\n", res
);
592 BaseOutputPinImpl_Inactive(&filter
->source
);
596 static const struct strmbase_filter_ops filter_ops
=
598 .filter_get_pin
= avi_decompressor_get_pin
,
599 .filter_destroy
= avi_decompressor_destroy
,
600 .filter_init_stream
= avi_decompressor_init_stream
,
601 .filter_cleanup_stream
= avi_decompressor_cleanup_stream
,
604 HRESULT
avi_dec_create(IUnknown
*outer
, IUnknown
**out
)
606 struct avi_decompressor
*object
;
608 if (!(object
= calloc(1, sizeof(*object
))))
609 return E_OUTOFMEMORY
;
611 strmbase_filter_init(&object
->filter
, outer
, &CLSID_AVIDec
, &filter_ops
);
613 InitializeCriticalSection(&object
->stream_cs
);
614 object
->stream_cs
.DebugInfo
->Spare
[0] = (DWORD_PTR
)(__FILE__
": avi_decompressor.stream_cs");
616 strmbase_sink_init(&object
->sink
, &object
->filter
, L
"In", &sink_ops
, NULL
);
618 strmbase_source_init(&object
->source
, &object
->filter
, L
"Out", &source_ops
);
619 object
->source_IQualityControl_iface
.lpVtbl
= &source_qc_vtbl
;
620 strmbase_passthrough_init(&object
->passthrough
, (IUnknown
*)&object
->source
.pin
.IPin_iface
);
621 ISeekingPassThru_Init(&object
->passthrough
.ISeekingPassThru_iface
, FALSE
,
622 &object
->sink
.pin
.IPin_iface
);
624 TRACE("Created AVI decompressor %p.\n", object
);
625 *out
= &object
->filter
.IUnknown_inner
;