4 * Copyright (C) 2019 Zebediah Figura
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 "qasf_private.h"
23 WINE_DEFAULT_DEBUG_CHANNEL(qasf
);
27 IMediaBuffer IMediaBuffer_iface
;
31 struct dmo_wrapper_source
33 struct strmbase_source pin
;
35 struct strmbase_passthrough passthrough
;
40 struct strmbase_filter filter
;
41 IDMOWrapperFilter IDMOWrapperFilter_iface
;
45 DWORD sink_count
, source_count
;
46 struct strmbase_sink
*sinks
;
47 struct dmo_wrapper_source
*sources
;
48 DMO_OUTPUT_DATA_BUFFER
*buffers
;
49 struct buffer input_buffer
;
52 static struct buffer
*impl_from_IMediaBuffer(IMediaBuffer
*iface
)
54 return CONTAINING_RECORD(iface
, struct buffer
, IMediaBuffer_iface
);
57 static HRESULT WINAPI
buffer_QueryInterface(IMediaBuffer
*iface
, REFIID iid
, void **out
)
59 TRACE("iface %p, iid %s, out %p.\n", iface
, debugstr_guid(iid
), out
);
61 if (IsEqualGUID(iid
, &IID_IUnknown
) || IsEqualGUID(iid
, &IID_IMediaBuffer
))
63 IMediaBuffer_AddRef(iface
);
68 WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(iid
));
73 static ULONG WINAPI
buffer_AddRef(IMediaBuffer
*iface
)
75 TRACE("iface %p.\n", iface
);
79 static ULONG WINAPI
buffer_Release(IMediaBuffer
*iface
)
81 TRACE("iface %p.\n", iface
);
85 static HRESULT WINAPI
buffer_SetLength(IMediaBuffer
*iface
, DWORD len
)
87 struct buffer
*buffer
= impl_from_IMediaBuffer(iface
);
89 TRACE("iface %p, len %u.\n", iface
, len
);
91 return IMediaSample_SetActualDataLength(buffer
->sample
, len
);
94 static HRESULT WINAPI
buffer_GetMaxLength(IMediaBuffer
*iface
, DWORD
*len
)
96 struct buffer
*buffer
= impl_from_IMediaBuffer(iface
);
98 TRACE("iface %p, len %p.\n", iface
, len
);
100 *len
= IMediaSample_GetSize(buffer
->sample
);
104 static HRESULT WINAPI
buffer_GetBufferAndLength(IMediaBuffer
*iface
, BYTE
**data
, DWORD
*len
)
106 struct buffer
*buffer
= impl_from_IMediaBuffer(iface
);
108 TRACE("iface %p, data %p, len %p.\n", iface
, data
, len
);
110 *len
= IMediaSample_GetActualDataLength(buffer
->sample
);
111 return IMediaSample_GetPointer(buffer
->sample
, data
);
114 static const IMediaBufferVtbl buffer_vtbl
=
116 buffer_QueryInterface
,
121 buffer_GetBufferAndLength
,
124 static inline struct dmo_wrapper
*impl_from_strmbase_filter(struct strmbase_filter
*iface
)
126 return CONTAINING_RECORD(iface
, struct dmo_wrapper
, filter
);
129 static inline struct strmbase_sink
*impl_sink_from_strmbase_pin(struct strmbase_pin
*iface
)
131 return CONTAINING_RECORD(iface
, struct strmbase_sink
, pin
);
134 static HRESULT
dmo_wrapper_sink_query_interface(struct strmbase_pin
*iface
, REFIID iid
, void **out
)
136 struct strmbase_sink
*sink
= impl_sink_from_strmbase_pin(iface
);
138 if (IsEqualGUID(iid
, &IID_IMemInputPin
))
139 *out
= &sink
->IMemInputPin_iface
;
141 return E_NOINTERFACE
;
143 IUnknown_AddRef((IUnknown
*)*out
);
147 static HRESULT
dmo_wrapper_sink_query_accept(struct strmbase_pin
*iface
, const AM_MEDIA_TYPE
*mt
)
149 struct dmo_wrapper
*filter
= impl_from_strmbase_filter(iface
->filter
);
153 IUnknown_QueryInterface(filter
->dmo
, &IID_IMediaObject
, (void **)&dmo
);
155 hr
= IMediaObject_SetInputType(dmo
, impl_sink_from_strmbase_pin(iface
) - filter
->sinks
,
156 (const DMO_MEDIA_TYPE
*)mt
, DMO_SET_TYPEF_TEST_ONLY
);
158 IMediaObject_Release(dmo
);
163 static HRESULT
dmo_wrapper_sink_get_media_type(struct strmbase_pin
*iface
, unsigned int index
, AM_MEDIA_TYPE
*mt
)
165 struct dmo_wrapper
*filter
= impl_from_strmbase_filter(iface
->filter
);
169 IUnknown_QueryInterface(filter
->dmo
, &IID_IMediaObject
, (void **)&dmo
);
171 hr
= IMediaObject_GetInputType(dmo
, impl_sink_from_strmbase_pin(iface
) - filter
->sinks
,
172 index
, (DMO_MEDIA_TYPE
*)mt
);
174 IMediaObject_Release(dmo
);
176 return hr
== S_OK
? S_OK
: VFW_S_NO_MORE_ITEMS
;
179 static HRESULT
dmo_wrapper_sink_connect(struct strmbase_sink
*iface
, IPin
*peer
, const AM_MEDIA_TYPE
*mt
)
181 struct dmo_wrapper
*filter
= impl_from_strmbase_filter(iface
->pin
.filter
);
185 IUnknown_QueryInterface(filter
->dmo
, &IID_IMediaObject
, (void **)&dmo
);
187 hr
= IMediaObject_SetInputType(dmo
, iface
- filter
->sinks
, (const DMO_MEDIA_TYPE
*)mt
, 0);
189 IMediaObject_Release(dmo
);
193 static void dmo_wrapper_sink_disconnect(struct strmbase_sink
*iface
)
195 struct dmo_wrapper
*filter
= impl_from_strmbase_filter(iface
->pin
.filter
);
198 IUnknown_QueryInterface(filter
->dmo
, &IID_IMediaObject
, (void **)&dmo
);
200 IMediaObject_SetInputType(dmo
, iface
- filter
->sinks
, NULL
, DMO_SET_TYPEF_CLEAR
);
202 IMediaObject_Release(dmo
);
205 static HRESULT
process_output(struct dmo_wrapper
*filter
, IMediaObject
*dmo
)
207 DMO_OUTPUT_DATA_BUFFER
*buffers
= filter
->buffers
;
212 for (i
= 0; i
< filter
->source_count
; ++i
)
214 if (filter
->sources
[i
].pin
.pin
.peer
)
216 if (FAILED(hr
= IMemAllocator_GetBuffer(filter
->sources
[i
].pin
.pAllocator
,
217 &filter
->sources
[i
].buffer
.sample
, NULL
, NULL
, 0)))
219 ERR("Failed to get sample, hr %#x.\n", hr
);
222 buffers
[i
].pBuffer
= &filter
->sources
[i
].buffer
.IMediaBuffer_iface
;
223 IMediaSample_SetActualDataLength(filter
->sources
[i
].buffer
.sample
, 0);
226 buffers
[i
].pBuffer
= NULL
;
233 hr
= IMediaObject_ProcessOutput(dmo
, DMO_PROCESS_OUTPUT_DISCARD_WHEN_NO_BUFFER
,
234 filter
->source_count
, buffers
, &status
);
238 for (i
= 0; i
< filter
->source_count
; ++i
)
240 IMediaSample
*sample
= filter
->sources
[i
].buffer
.sample
;
242 if (!buffers
[i
].pBuffer
)
245 if (buffers
[i
].dwStatus
& DMO_OUTPUT_DATA_BUFFERF_INCOMPLETE
)
248 if (buffers
[i
].dwStatus
& DMO_OUTPUT_DATA_BUFFERF_TIME
)
250 if (buffers
[i
].dwStatus
& DMO_OUTPUT_DATA_BUFFERF_TIMELENGTH
)
252 REFERENCE_TIME stop
= buffers
[i
].rtTimestamp
+ buffers
[i
].rtTimelength
;
253 IMediaSample_SetTime(sample
, &buffers
[i
].rtTimestamp
, &stop
);
256 IMediaSample_SetTime(sample
, &buffers
[i
].rtTimestamp
, NULL
);
259 if (buffers
[i
].dwStatus
& DMO_OUTPUT_DATA_BUFFERF_SYNCPOINT
)
260 IMediaSample_SetSyncPoint(sample
, TRUE
);
262 if (IMediaSample_GetActualDataLength(sample
))
264 if (FAILED(hr
= IMemInputPin_Receive(filter
->sources
[i
].pin
.pMemInputPin
, sample
)))
266 WARN("Downstream sink returned %#x.\n", hr
);
269 IMediaSample_SetActualDataLength(sample
, 0);
276 for (i
= 0; i
< filter
->source_count
; ++i
)
278 if (filter
->sources
[i
].buffer
.sample
)
280 IMediaSample_Release(filter
->sources
[i
].buffer
.sample
);
281 filter
->sources
[i
].buffer
.sample
= NULL
;
288 static HRESULT WINAPI
dmo_wrapper_sink_Receive(struct strmbase_sink
*iface
, IMediaSample
*sample
)
290 struct dmo_wrapper
*filter
= impl_from_strmbase_filter(iface
->pin
.filter
);
291 DWORD index
= iface
- filter
->sinks
;
292 REFERENCE_TIME start
= 0, stop
= 0;
297 IUnknown_QueryInterface(filter
->dmo
, &IID_IMediaObject
, (void **)&dmo
);
299 if (IMediaSample_IsDiscontinuity(sample
) == S_OK
)
301 if (FAILED(hr
= IMediaObject_Discontinuity(dmo
, index
)))
303 ERR("Discontinuity() failed, hr %#x.\n", hr
);
307 /* Calling Discontinuity() might change the DMO's mind about whether it
308 * has more data to process. The DirectX documentation explicitly
309 * states that we should call ProcessOutput() again in this case. */
310 process_output(filter
, dmo
);
313 if (IMediaSample_IsSyncPoint(sample
) == S_OK
)
314 flags
|= DMO_INPUT_DATA_BUFFERF_SYNCPOINT
;
316 if (SUCCEEDED(hr
= IMediaSample_GetTime(sample
, &start
, &stop
)))
318 flags
|= DMO_INPUT_DATA_BUFFERF_TIME
| DMO_INPUT_DATA_BUFFERF_TIMELENGTH
;
319 if (hr
== VFW_S_NO_STOP_TIME
)
323 filter
->input_buffer
.sample
= sample
;
324 if (FAILED(hr
= IMediaObject_ProcessInput(dmo
, index
,
325 &filter
->input_buffer
.IMediaBuffer_iface
, flags
, start
, stop
- start
)))
327 ERR("ProcessInput() failed, hr %#x.\n", hr
);
331 process_output(filter
, dmo
);
334 filter
->input_buffer
.sample
= NULL
;
335 IMediaObject_Release(dmo
);
339 static HRESULT
dmo_wrapper_sink_eos(struct strmbase_sink
*iface
)
341 struct dmo_wrapper
*filter
= impl_from_strmbase_filter(iface
->pin
.filter
);
342 DWORD index
= iface
- filter
->sinks
, i
;
346 IUnknown_QueryInterface(filter
->dmo
, &IID_IMediaObject
, (void **)&dmo
);
348 if (FAILED(hr
= IMediaObject_Discontinuity(dmo
, index
)))
349 ERR("Discontinuity() failed, hr %#x.\n", hr
);
351 process_output(filter
, dmo
);
352 if (FAILED(hr
= IMediaObject_Flush(dmo
)))
353 ERR("Flush() failed, hr %#x.\n", hr
);
355 for (i
= 0; i
< filter
->source_count
; ++i
)
357 if (filter
->sources
[i
].pin
.pin
.peer
)
358 IPin_EndOfStream(filter
->sources
[i
].pin
.pin
.peer
);
361 IMediaObject_Release(dmo
);
365 static HRESULT
dmo_wrapper_end_flush(struct strmbase_sink
*iface
)
367 struct dmo_wrapper
*filter
= impl_from_strmbase_filter(iface
->pin
.filter
);
372 IUnknown_QueryInterface(filter
->dmo
, &IID_IMediaObject
, (void **)&dmo
);
374 if (FAILED(hr
= IMediaObject_Flush(dmo
)))
375 ERR("Flush() failed, hr %#x.\n", hr
);
377 for (i
= 0; i
< filter
->source_count
; ++i
)
379 if (filter
->sources
[i
].pin
.pin
.peer
)
380 IPin_EndFlush(filter
->sources
[i
].pin
.pin
.peer
);
383 IMediaObject_Release(dmo
);
387 static const struct strmbase_sink_ops sink_ops
=
389 .base
.pin_query_interface
= dmo_wrapper_sink_query_interface
,
390 .base
.pin_query_accept
= dmo_wrapper_sink_query_accept
,
391 .base
.pin_get_media_type
= dmo_wrapper_sink_get_media_type
,
392 .sink_connect
= dmo_wrapper_sink_connect
,
393 .sink_disconnect
= dmo_wrapper_sink_disconnect
,
394 .sink_eos
= dmo_wrapper_sink_eos
,
395 .sink_end_flush
= dmo_wrapper_end_flush
,
396 .pfnReceive
= dmo_wrapper_sink_Receive
,
399 static inline struct dmo_wrapper_source
*impl_source_from_strmbase_pin(struct strmbase_pin
*iface
)
401 return CONTAINING_RECORD(iface
, struct dmo_wrapper_source
, pin
.pin
);
404 static HRESULT
dmo_wrapper_source_query_interface(struct strmbase_pin
*iface
, REFIID iid
, void **out
)
406 struct dmo_wrapper_source
*pin
= impl_source_from_strmbase_pin(iface
);
408 if (IsEqualGUID(iid
, &IID_IMediaPosition
))
409 *out
= &pin
->passthrough
.IMediaPosition_iface
;
410 else if (IsEqualGUID(iid
, &IID_IMediaSeeking
))
411 *out
= &pin
->passthrough
.IMediaSeeking_iface
;
413 return E_NOINTERFACE
;
415 IUnknown_AddRef((IUnknown
*)*out
);
419 static HRESULT
dmo_wrapper_source_query_accept(struct strmbase_pin
*iface
, const AM_MEDIA_TYPE
*mt
)
421 struct dmo_wrapper
*filter
= impl_from_strmbase_filter(iface
->filter
);
425 IUnknown_QueryInterface(filter
->dmo
, &IID_IMediaObject
, (void **)&dmo
);
427 hr
= IMediaObject_SetOutputType(dmo
, impl_source_from_strmbase_pin(iface
) - filter
->sources
,
428 (const DMO_MEDIA_TYPE
*)mt
, DMO_SET_TYPEF_TEST_ONLY
);
430 IMediaObject_Release(dmo
);
435 static HRESULT
dmo_wrapper_source_get_media_type(struct strmbase_pin
*iface
, unsigned int index
, AM_MEDIA_TYPE
*mt
)
437 struct dmo_wrapper
*filter
= impl_from_strmbase_filter(iface
->filter
);
441 IUnknown_QueryInterface(filter
->dmo
, &IID_IMediaObject
, (void **)&dmo
);
443 hr
= IMediaObject_GetOutputType(dmo
, impl_source_from_strmbase_pin(iface
) - filter
->sources
,
444 index
, (DMO_MEDIA_TYPE
*)mt
);
446 IMediaObject_Release(dmo
);
448 return hr
== S_OK
? S_OK
: VFW_S_NO_MORE_ITEMS
;
451 static HRESULT WINAPI
dmo_wrapper_source_DecideBufferSize(struct strmbase_source
*iface
,
452 IMemAllocator
*allocator
, ALLOCATOR_PROPERTIES
*props
)
454 struct dmo_wrapper
*filter
= impl_from_strmbase_filter(iface
->pin
.filter
);
455 DWORD index
= impl_source_from_strmbase_pin(&iface
->pin
) - filter
->sources
;
456 ALLOCATOR_PROPERTIES ret_props
;
457 DWORD size
= 0, alignment
= 0;
461 IUnknown_QueryInterface(filter
->dmo
, &IID_IMediaObject
, (void **)&dmo
);
463 if (SUCCEEDED(hr
= IMediaObject_SetOutputType(dmo
, index
,
464 (const DMO_MEDIA_TYPE
*)&iface
->pin
.mt
, 0)))
465 hr
= IMediaObject_GetOutputSizeInfo(dmo
, index
, &size
, &alignment
);
469 props
->cBuffers
= max(props
->cBuffers
, 1);
470 props
->cbBuffer
= max(max(props
->cbBuffer
, size
), 16384);
471 props
->cbAlign
= max(props
->cbAlign
, alignment
);
472 hr
= IMemAllocator_SetProperties(allocator
, props
, &ret_props
);
475 IMediaObject_Release(dmo
);
480 static void dmo_wrapper_source_disconnect(struct strmbase_source
*iface
)
482 struct dmo_wrapper
*filter
= impl_from_strmbase_filter(iface
->pin
.filter
);
485 IUnknown_QueryInterface(filter
->dmo
, &IID_IMediaObject
, (void **)&dmo
);
487 IMediaObject_SetOutputType(dmo
, impl_source_from_strmbase_pin(&iface
->pin
) - filter
->sources
,
488 NULL
, DMO_SET_TYPEF_CLEAR
);
490 IMediaObject_Release(dmo
);
493 static const struct strmbase_source_ops source_ops
=
495 .base
.pin_query_interface
= dmo_wrapper_source_query_interface
,
496 .base
.pin_query_accept
= dmo_wrapper_source_query_accept
,
497 .base
.pin_get_media_type
= dmo_wrapper_source_get_media_type
,
498 .pfnAttemptConnection
= BaseOutputPinImpl_AttemptConnection
,
499 .pfnDecideAllocator
= BaseOutputPinImpl_DecideAllocator
,
500 .pfnDecideBufferSize
= dmo_wrapper_source_DecideBufferSize
,
501 .source_disconnect
= dmo_wrapper_source_disconnect
,
504 static inline struct dmo_wrapper
*impl_from_IDMOWrapperFilter(IDMOWrapperFilter
*iface
)
506 return CONTAINING_RECORD(iface
, struct dmo_wrapper
, IDMOWrapperFilter_iface
);
509 static HRESULT WINAPI
dmo_wrapper_filter_QueryInterface(IDMOWrapperFilter
*iface
, REFIID iid
, void **out
)
511 struct dmo_wrapper
*filter
= impl_from_IDMOWrapperFilter(iface
);
512 return IUnknown_QueryInterface(filter
->filter
.outer_unk
, iid
, out
);
515 static ULONG WINAPI
dmo_wrapper_filter_AddRef(IDMOWrapperFilter
*iface
)
517 struct dmo_wrapper
*filter
= impl_from_IDMOWrapperFilter(iface
);
518 return IUnknown_AddRef(filter
->filter
.outer_unk
);
521 static ULONG WINAPI
dmo_wrapper_filter_Release(IDMOWrapperFilter
*iface
)
523 struct dmo_wrapper
*filter
= impl_from_IDMOWrapperFilter(iface
);
524 return IUnknown_Release(filter
->filter
.outer_unk
);
527 static HRESULT WINAPI
dmo_wrapper_filter_Init(IDMOWrapperFilter
*iface
, REFCLSID clsid
, REFCLSID category
)
529 struct dmo_wrapper
*filter
= impl_from_IDMOWrapperFilter(iface
);
530 struct dmo_wrapper_source
*sources
;
531 DMO_OUTPUT_DATA_BUFFER
*buffers
;
532 DWORD input_count
, output_count
;
533 struct strmbase_sink
*sinks
;
540 TRACE("filter %p, clsid %s, category %s.\n", filter
, debugstr_guid(clsid
), debugstr_guid(category
));
542 if (FAILED(hr
= CoCreateInstance(clsid
, &filter
->filter
.IUnknown_inner
,
543 CLSCTX_INPROC_SERVER
, &IID_IUnknown
, (void **)&unk
)))
546 if (FAILED(hr
= IUnknown_QueryInterface(unk
, &IID_IMediaObject
, (void **)&dmo
)))
548 IUnknown_Release(unk
);
552 if (FAILED(IMediaObject_GetStreamCount(dmo
, &input_count
, &output_count
)))
553 input_count
= output_count
= 0;
555 sinks
= calloc(sizeof(*sinks
), input_count
);
556 sources
= calloc(sizeof(*sources
), output_count
);
557 buffers
= calloc(sizeof(*buffers
), output_count
);
558 if (!sinks
|| !sources
|| !buffers
)
563 IMediaObject_Release(dmo
);
564 IUnknown_Release(unk
);
568 for (i
= 0; i
< input_count
; ++i
)
570 swprintf(id
, ARRAY_SIZE(id
), L
"in%u", i
);
571 strmbase_sink_init(&sinks
[i
], &filter
->filter
, id
, &sink_ops
, NULL
);
574 for (i
= 0; i
< output_count
; ++i
)
576 swprintf(id
, ARRAY_SIZE(id
), L
"out%u", i
);
577 strmbase_source_init(&sources
[i
].pin
, &filter
->filter
, id
, &source_ops
);
578 sources
[i
].buffer
.IMediaBuffer_iface
.lpVtbl
= &buffer_vtbl
;
580 strmbase_passthrough_init(&sources
[i
].passthrough
, (IUnknown
*)&sources
[i
].pin
.pin
.IPin_iface
);
581 ISeekingPassThru_Init(&sources
[i
].passthrough
.ISeekingPassThru_iface
,
582 FALSE
, &sinks
[0].pin
.IPin_iface
);
585 EnterCriticalSection(&filter
->filter
.filter_cs
);
588 filter
->sink_count
= input_count
;
589 filter
->source_count
= output_count
;
590 filter
->sinks
= sinks
;
591 filter
->sources
= sources
;
592 filter
->buffers
= buffers
;
594 LeaveCriticalSection(&filter
->filter
.filter_cs
);
596 IMediaObject_Release(dmo
);
601 static const IDMOWrapperFilterVtbl dmo_wrapper_filter_vtbl
=
603 dmo_wrapper_filter_QueryInterface
,
604 dmo_wrapper_filter_AddRef
,
605 dmo_wrapper_filter_Release
,
606 dmo_wrapper_filter_Init
,
609 static struct strmbase_pin
*dmo_wrapper_get_pin(struct strmbase_filter
*iface
, unsigned int index
)
611 struct dmo_wrapper
*filter
= impl_from_strmbase_filter(iface
);
613 if (index
< filter
->sink_count
)
614 return &filter
->sinks
[index
].pin
;
615 else if (index
< filter
->sink_count
+ filter
->source_count
)
616 return &filter
->sources
[index
- filter
->sink_count
].pin
.pin
;
620 static void dmo_wrapper_destroy(struct strmbase_filter
*iface
)
622 struct dmo_wrapper
*filter
= impl_from_strmbase_filter(iface
);
626 IUnknown_Release(filter
->dmo
);
627 for (i
= 0; i
< filter
->sink_count
; ++i
)
628 strmbase_sink_cleanup(&filter
->sinks
[i
]);
629 for (i
= 0; i
< filter
->source_count
; ++i
)
631 strmbase_passthrough_cleanup(&filter
->sources
[i
].passthrough
);
632 strmbase_source_cleanup(&filter
->sources
[i
].pin
);
635 free(filter
->sources
);
636 strmbase_filter_cleanup(&filter
->filter
);
640 static HRESULT
dmo_wrapper_query_interface(struct strmbase_filter
*iface
, REFIID iid
, void **out
)
642 struct dmo_wrapper
*filter
= impl_from_strmbase_filter(iface
);
644 if (IsEqualGUID(iid
, &IID_IDMOWrapperFilter
))
646 *out
= &filter
->IDMOWrapperFilter_iface
;
647 IUnknown_AddRef((IUnknown
*)*out
);
651 if (filter
->dmo
&& !IsEqualGUID(iid
, &IID_IUnknown
))
652 return IUnknown_QueryInterface(filter
->dmo
, iid
, out
);
653 return E_NOINTERFACE
;
656 static HRESULT
dmo_wrapper_init_stream(struct strmbase_filter
*iface
)
658 struct dmo_wrapper
*filter
= impl_from_strmbase_filter(iface
);
661 for (i
= 0; i
< filter
->source_count
; ++i
)
663 if (filter
->sources
[i
].pin
.pin
.peer
)
664 IMemAllocator_Commit(filter
->sources
[i
].pin
.pAllocator
);
670 static HRESULT
dmo_wrapper_cleanup_stream(struct strmbase_filter
*iface
)
672 struct dmo_wrapper
*filter
= impl_from_strmbase_filter(iface
);
679 IUnknown_QueryInterface(filter
->dmo
, &IID_IMediaObject
, (void **)&dmo
);
681 for (i
= 0; i
< filter
->source_count
; ++i
)
683 if (filter
->sources
[i
].pin
.pin
.peer
)
684 IMemAllocator_Decommit(filter
->sources
[i
].pin
.pAllocator
);
687 IMediaObject_Flush(dmo
);
689 IMediaObject_Release(dmo
);
693 static struct strmbase_filter_ops filter_ops
=
695 .filter_get_pin
= dmo_wrapper_get_pin
,
696 .filter_destroy
= dmo_wrapper_destroy
,
697 .filter_query_interface
= dmo_wrapper_query_interface
,
698 .filter_init_stream
= dmo_wrapper_init_stream
,
699 .filter_cleanup_stream
= dmo_wrapper_cleanup_stream
,
702 HRESULT
dmo_wrapper_create(IUnknown
*outer
, IUnknown
**out
)
704 struct dmo_wrapper
*object
;
706 if (!(object
= calloc(sizeof(*object
), 1)))
707 return E_OUTOFMEMORY
;
709 /* Always pass NULL as the outer object; see test_aggregation(). */
710 strmbase_filter_init(&object
->filter
, NULL
, &CLSID_DMOWrapperFilter
, &filter_ops
);
712 object
->IDMOWrapperFilter_iface
.lpVtbl
= &dmo_wrapper_filter_vtbl
;
714 object
->input_buffer
.IMediaBuffer_iface
.lpVtbl
= &buffer_vtbl
;
716 TRACE("Created DMO wrapper %p.\n", object
);
717 *out
= &object
->filter
.IUnknown_inner
;