2 * Implementation of MediaStream Filter
4 * Copyright 2008, 2012 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
22 #include "amstream_private.h"
23 #include "wine/debug.h"
25 WINE_DEFAULT_DEBUG_CHANNEL(amstream
);
29 IEnumPins IEnumPins_iface
;
33 unsigned int count
, index
;
36 static const IEnumPinsVtbl enum_pins_vtbl
;
38 static struct enum_pins
*impl_from_IEnumPins(IEnumPins
*iface
)
40 return CONTAINING_RECORD(iface
, struct enum_pins
, IEnumPins_iface
);
43 static HRESULT WINAPI
enum_pins_QueryInterface(IEnumPins
*iface
, REFIID iid
, void **out
)
45 TRACE("iface %p, iid %s, out %p.\n", iface
, debugstr_guid(iid
), out
);
47 if (IsEqualGUID(iid
, &IID_IUnknown
) || IsEqualGUID(iid
, &IID_IEnumPins
))
49 IEnumPins_AddRef(iface
);
54 WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(iid
));
59 static ULONG WINAPI
enum_pins_AddRef(IEnumPins
*iface
)
61 struct enum_pins
*enum_pins
= impl_from_IEnumPins(iface
);
62 ULONG refcount
= InterlockedIncrement(&enum_pins
->refcount
);
63 TRACE("%p increasing refcount to %u.\n", enum_pins
, refcount
);
67 static ULONG WINAPI
enum_pins_Release(IEnumPins
*iface
)
69 struct enum_pins
*enum_pins
= impl_from_IEnumPins(iface
);
70 ULONG refcount
= InterlockedDecrement(&enum_pins
->refcount
);
73 TRACE("%p decreasing refcount to %u.\n", enum_pins
, refcount
);
76 for (i
= 0; i
< enum_pins
->count
; ++i
)
77 IPin_Release(enum_pins
->pins
[i
]);
78 heap_free(enum_pins
->pins
);
84 static HRESULT WINAPI
enum_pins_Next(IEnumPins
*iface
, ULONG count
, IPin
**pins
, ULONG
*ret_count
)
86 struct enum_pins
*enum_pins
= impl_from_IEnumPins(iface
);
89 TRACE("iface %p, count %u, pins %p, ret_count %p.\n", iface
, count
, pins
, ret_count
);
91 if (!pins
|| (count
> 1 && !ret_count
))
94 for (i
= 0; i
< count
&& enum_pins
->index
< enum_pins
->count
; ++i
)
96 IPin_AddRef(pins
[i
] = enum_pins
->pins
[i
]);
100 if (ret_count
) *ret_count
= i
;
101 return i
== count
? S_OK
: S_FALSE
;
104 static HRESULT WINAPI
enum_pins_Skip(IEnumPins
*iface
, ULONG count
)
106 struct enum_pins
*enum_pins
= impl_from_IEnumPins(iface
);
108 TRACE("iface %p, count %u.\n", iface
, count
);
110 enum_pins
->index
+= count
;
112 return enum_pins
->index
>= enum_pins
->count
? S_FALSE
: S_OK
;
115 static HRESULT WINAPI
enum_pins_Reset(IEnumPins
*iface
)
117 struct enum_pins
*enum_pins
= impl_from_IEnumPins(iface
);
119 TRACE("iface %p.\n", iface
);
121 enum_pins
->index
= 0;
125 static HRESULT WINAPI
enum_pins_Clone(IEnumPins
*iface
, IEnumPins
**out
)
127 struct enum_pins
*enum_pins
= impl_from_IEnumPins(iface
);
128 struct enum_pins
*object
;
131 TRACE("iface %p, out %p.\n", iface
, out
);
133 if (!(object
= heap_alloc(sizeof(*object
))))
134 return E_OUTOFMEMORY
;
136 object
->IEnumPins_iface
.lpVtbl
= &enum_pins_vtbl
;
137 object
->refcount
= 1;
138 object
->count
= enum_pins
->count
;
139 object
->index
= enum_pins
->index
;
140 if (!(object
->pins
= heap_alloc(enum_pins
->count
* sizeof(*object
->pins
))))
143 return E_OUTOFMEMORY
;
145 for (i
= 0; i
< enum_pins
->count
; ++i
)
146 IPin_AddRef(object
->pins
[i
] = enum_pins
->pins
[i
]);
148 *out
= &object
->IEnumPins_iface
;
152 static const IEnumPinsVtbl enum_pins_vtbl
=
154 enum_pins_QueryInterface
,
165 IMediaStreamFilter IMediaStreamFilter_iface
;
166 IMediaSeeking IMediaSeeking_iface
;
170 IReferenceClock
*clock
;
174 IAMMediaStream
**streams
;
175 IAMMediaStream
*seekable_stream
;
179 static inline struct filter
*impl_from_IMediaStreamFilter(IMediaStreamFilter
*iface
)
181 return CONTAINING_RECORD(iface
, struct filter
, IMediaStreamFilter_iface
);
184 static HRESULT WINAPI
filter_QueryInterface(IMediaStreamFilter
*iface
, REFIID iid
, void **out
)
186 struct filter
*filter
= impl_from_IMediaStreamFilter(iface
);
188 TRACE("filter %p, iid %s, out %p.\n", filter
, debugstr_guid(iid
), out
);
192 if (IsEqualGUID(iid
, &IID_IUnknown
)
193 || IsEqualGUID(iid
, &IID_IPersist
)
194 || IsEqualGUID(iid
, &IID_IMediaFilter
)
195 || IsEqualGUID(iid
, &IID_IBaseFilter
)
196 || IsEqualGUID(iid
, &IID_IMediaStreamFilter
))
198 else if (IsEqualGUID(iid
, &IID_IMediaSeeking
) && filter
->seekable_stream
)
199 *out
= &filter
->IMediaSeeking_iface
;
201 return E_NOINTERFACE
;
203 IUnknown_AddRef((IUnknown
*)*out
);
207 static ULONG WINAPI
filter_AddRef(IMediaStreamFilter
*iface
)
209 struct filter
*filter
= impl_from_IMediaStreamFilter(iface
);
210 ULONG refcount
= InterlockedIncrement(&filter
->refcount
);
212 TRACE("%p increasing refcount to %u.\n", iface
, refcount
);
217 static ULONG WINAPI
filter_Release(IMediaStreamFilter
*iface
)
219 struct filter
*filter
= impl_from_IMediaStreamFilter(iface
);
220 ULONG refcount
= InterlockedDecrement(&filter
->refcount
);
223 TRACE("%p decreasing refcount to %u.\n", iface
, refcount
);
227 for (i
= 0; i
< filter
->nb_streams
; ++i
)
229 IAMMediaStream_JoinFilter(filter
->streams
[i
], NULL
);
230 IAMMediaStream_Release(filter
->streams
[i
]);
232 heap_free(filter
->streams
);
234 IReferenceClock_Release(filter
->clock
);
235 DeleteCriticalSection(&filter
->cs
);
242 static HRESULT WINAPI
filter_GetClassID(IMediaStreamFilter
*iface
, CLSID
*clsid
)
244 *clsid
= CLSID_MediaStreamFilter
;
248 static void set_state(struct filter
*filter
, FILTER_STATE state
)
250 if (filter
->state
!= state
)
254 for (i
= 0; i
< filter
->nb_streams
; ++i
)
255 IAMMediaStream_SetState(filter
->streams
[i
], state
);
256 filter
->state
= state
;
260 static HRESULT WINAPI
filter_Stop(IMediaStreamFilter
*iface
)
262 struct filter
*filter
= impl_from_IMediaStreamFilter(iface
);
264 TRACE("iface %p.\n", iface
);
266 EnterCriticalSection(&filter
->cs
);
268 set_state(filter
, State_Stopped
);
270 LeaveCriticalSection(&filter
->cs
);
275 static HRESULT WINAPI
filter_Pause(IMediaStreamFilter
*iface
)
277 struct filter
*filter
= impl_from_IMediaStreamFilter(iface
);
279 TRACE("iface %p.\n", iface
);
281 EnterCriticalSection(&filter
->cs
);
283 set_state(filter
, State_Paused
);
285 LeaveCriticalSection(&filter
->cs
);
290 static HRESULT WINAPI
filter_Run(IMediaStreamFilter
*iface
, REFERENCE_TIME start
)
292 struct filter
*filter
= impl_from_IMediaStreamFilter(iface
);
294 TRACE("iface %p, start %s.\n", iface
, wine_dbgstr_longlong(start
));
296 EnterCriticalSection(&filter
->cs
);
298 set_state(filter
, State_Running
);
300 LeaveCriticalSection(&filter
->cs
);
305 static HRESULT WINAPI
filter_GetState(IMediaStreamFilter
*iface
, DWORD timeout
, FILTER_STATE
*state
)
307 struct filter
*filter
= impl_from_IMediaStreamFilter(iface
);
309 TRACE("iface %p, timeout %u, state %p.\n", iface
, timeout
, state
);
314 EnterCriticalSection(&filter
->cs
);
316 *state
= filter
->state
;
318 LeaveCriticalSection(&filter
->cs
);
323 static HRESULT WINAPI
filter_SetSyncSource(IMediaStreamFilter
*iface
, IReferenceClock
*clock
)
325 struct filter
*filter
= impl_from_IMediaStreamFilter(iface
);
327 TRACE("iface %p, clock %p.\n", iface
, clock
);
329 EnterCriticalSection(&filter
->cs
);
332 IReferenceClock_AddRef(clock
);
334 IReferenceClock_Release(filter
->clock
);
335 filter
->clock
= clock
;
337 LeaveCriticalSection(&filter
->cs
);
342 static HRESULT WINAPI
filter_GetSyncSource(IMediaStreamFilter
*iface
, IReferenceClock
**clock
)
344 struct filter
*filter
= impl_from_IMediaStreamFilter(iface
);
346 TRACE("iface %p, clock %p.\n", iface
, clock
);
348 EnterCriticalSection(&filter
->cs
);
351 IReferenceClock_AddRef(filter
->clock
);
352 *clock
= filter
->clock
;
354 LeaveCriticalSection(&filter
->cs
);
359 static HRESULT WINAPI
filter_EnumPins(IMediaStreamFilter
*iface
, IEnumPins
**enum_pins
)
361 struct filter
*filter
= impl_from_IMediaStreamFilter(iface
);
362 struct enum_pins
*object
;
365 TRACE("iface %p, enum_pins %p.\n", iface
, enum_pins
);
370 if (!(object
= heap_alloc(sizeof(*object
))))
371 return E_OUTOFMEMORY
;
373 EnterCriticalSection(&filter
->cs
);
375 object
->IEnumPins_iface
.lpVtbl
= &enum_pins_vtbl
;
376 object
->refcount
= 1;
377 object
->count
= filter
->nb_streams
;
379 if (!(object
->pins
= heap_alloc(filter
->nb_streams
* sizeof(*object
->pins
))))
382 LeaveCriticalSection(&filter
->cs
);
383 return E_OUTOFMEMORY
;
385 for (i
= 0; i
< filter
->nb_streams
; ++i
)
387 if (FAILED(IAMMediaStream_QueryInterface(filter
->streams
[i
], &IID_IPin
, (void **)&object
->pins
[i
])))
388 WARN("Stream %p does not support IPin.\n", filter
->streams
[i
]);
391 LeaveCriticalSection(&filter
->cs
);
393 *enum_pins
= &object
->IEnumPins_iface
;
397 static HRESULT WINAPI
filter_FindPin(IMediaStreamFilter
*iface
, const WCHAR
*id
, IPin
**out
)
399 struct filter
*filter
= impl_from_IMediaStreamFilter(iface
);
404 TRACE("iface %p, id %s, out %p.\n", iface
, debugstr_w(id
), out
);
406 EnterCriticalSection(&filter
->cs
);
408 for (i
= 0; i
< filter
->nb_streams
; ++i
)
410 if (FAILED(IAMMediaStream_QueryInterface(filter
->streams
[i
], &IID_IPin
, (void **)&pin
)))
412 WARN("Stream %p does not support IPin.\n", filter
->streams
[i
]);
416 if (SUCCEEDED(IPin_QueryId(pin
, &ret_id
)))
418 if (!wcscmp(id
, ret_id
))
420 CoTaskMemFree(ret_id
);
422 LeaveCriticalSection(&filter
->cs
);
425 CoTaskMemFree(ret_id
);
430 LeaveCriticalSection(&filter
->cs
);
432 return VFW_E_NOT_FOUND
;
435 static HRESULT WINAPI
filter_QueryFilterInfo(IMediaStreamFilter
*iface
, FILTER_INFO
*info
)
437 struct filter
*filter
= impl_from_IMediaStreamFilter(iface
);
439 TRACE("iface %p, info %p.\n", iface
, info
);
441 EnterCriticalSection(&filter
->cs
);
443 wcscpy(info
->achName
, filter
->name
);
445 IFilterGraph_AddRef(filter
->graph
);
446 info
->pGraph
= filter
->graph
;
448 LeaveCriticalSection(&filter
->cs
);
453 static HRESULT WINAPI
filter_JoinFilterGraph(IMediaStreamFilter
*iface
,
454 IFilterGraph
*graph
, const WCHAR
*name
)
456 struct filter
*filter
= impl_from_IMediaStreamFilter(iface
);
458 TRACE("iface %p, graph %p, name.%s.\n", iface
, graph
, debugstr_w(name
));
460 EnterCriticalSection(&filter
->cs
);
463 wcsncpy(filter
->name
, name
, ARRAY_SIZE(filter
->name
));
466 filter
->graph
= graph
;
468 LeaveCriticalSection(&filter
->cs
);
473 static HRESULT WINAPI
filter_QueryVendorInfo(IMediaStreamFilter
*iface
, LPWSTR
*vendor_info
)
475 WARN("iface %p, vendor_info %p, stub!\n", iface
, vendor_info
);
479 /*** IMediaStreamFilter methods ***/
481 static HRESULT WINAPI
filter_AddMediaStream(IMediaStreamFilter
*iface
, IAMMediaStream
*pAMMediaStream
)
483 struct filter
*This
= impl_from_IMediaStreamFilter(iface
);
484 IAMMediaStream
** streams
;
487 TRACE("(%p)->(%p)\n", iface
, pAMMediaStream
);
489 streams
= CoTaskMemRealloc(This
->streams
, (This
->nb_streams
+ 1) * sizeof(IAMMediaStream
*));
491 return E_OUTOFMEMORY
;
492 This
->streams
= streams
;
494 hr
= IAMMediaStream_JoinFilter(pAMMediaStream
, iface
);
498 This
->streams
[This
->nb_streams
] = pAMMediaStream
;
501 IAMMediaStream_AddRef(pAMMediaStream
);
506 static HRESULT WINAPI
filter_GetMediaStream(IMediaStreamFilter
*iface
, REFMSPID idPurpose
, IMediaStream
**ppMediaStream
)
508 struct filter
*This
= impl_from_IMediaStreamFilter(iface
);
512 TRACE("(%p)->(%s,%p)\n", iface
, debugstr_guid(idPurpose
), ppMediaStream
);
514 for (i
= 0; i
< This
->nb_streams
; i
++)
516 IAMMediaStream_GetInformation(This
->streams
[i
], &purpose_id
, NULL
);
517 if (IsEqualIID(&purpose_id
, idPurpose
))
519 *ppMediaStream
= (IMediaStream
*)This
->streams
[i
];
520 IMediaStream_AddRef(*ppMediaStream
);
525 return MS_E_NOSTREAM
;
528 static HRESULT WINAPI
filter_EnumMediaStreams(IMediaStreamFilter
*iface
, LONG index
, IMediaStream
**stream
)
530 struct filter
*filter
= impl_from_IMediaStreamFilter(iface
);
532 TRACE("filter %p, index %d, stream %p.\n", filter
, index
, stream
);
534 if (index
>= filter
->nb_streams
)
540 IMediaStream_AddRef(*stream
= (IMediaStream
*)filter
->streams
[index
]);
544 static IMediaSeeking
*get_seeking(IAMMediaStream
*stream
)
546 IMediaSeeking
*seeking
;
550 if (FAILED(IAMMediaStream_QueryInterface(stream
, &IID_IPin
, (void **)&pin
)))
552 WARN("Stream %p does not support IPin.\n", stream
);
556 hr
= IPin_ConnectedTo(pin
, &peer
);
561 hr
= IPin_QueryInterface(peer
, &IID_IMediaSeeking
, (void **)&seeking
);
569 static HRESULT WINAPI
filter_SupportSeeking(IMediaStreamFilter
*iface
, BOOL renderer
)
571 struct filter
*filter
= impl_from_IMediaStreamFilter(iface
);
574 TRACE("filter %p, renderer %d\n", iface
, renderer
);
577 FIXME("Non-renderer filter support is not yet implemented.\n");
579 EnterCriticalSection(&filter
->cs
);
581 if (filter
->seekable_stream
)
583 LeaveCriticalSection(&filter
->cs
);
584 return HRESULT_FROM_WIN32(ERROR_ALREADY_INITIALIZED
);
587 for (i
= 0; i
< filter
->nb_streams
; ++i
)
589 IMediaSeeking
*seeking
= get_seeking(filter
->streams
[i
]);
595 if (SUCCEEDED(IMediaSeeking_GetDuration(seeking
, &duration
)))
597 filter
->seekable_stream
= filter
->streams
[i
];
598 IMediaSeeking_Release(seeking
);
599 LeaveCriticalSection(&filter
->cs
);
603 IMediaSeeking_Release(seeking
);
606 LeaveCriticalSection(&filter
->cs
);
607 return E_NOINTERFACE
;
610 static HRESULT WINAPI
filter_ReferenceTimeToStreamTime(IMediaStreamFilter
*iface
, REFERENCE_TIME
*pTime
)
612 FIXME("(%p)->(%p): Stub!\n", iface
, pTime
);
617 static HRESULT WINAPI
filter_GetCurrentStreamTime(IMediaStreamFilter
*iface
, REFERENCE_TIME
*pCurrentStreamTime
)
619 FIXME("(%p)->(%p): Stub!\n", iface
, pCurrentStreamTime
);
624 static HRESULT WINAPI
filter_WaitUntil(IMediaStreamFilter
*iface
, REFERENCE_TIME WaitStreamTime
)
626 FIXME("(%p)->(%s): Stub!\n", iface
, wine_dbgstr_longlong(WaitStreamTime
));
631 static HRESULT WINAPI
filter_Flush(IMediaStreamFilter
*iface
, BOOL bCancelEOS
)
633 FIXME("(%p)->(%d): Stub!\n", iface
, bCancelEOS
);
638 static HRESULT WINAPI
filter_EndOfStream(IMediaStreamFilter
*iface
)
640 FIXME("(%p)->(): Stub!\n", iface
);
645 static const IMediaStreamFilterVtbl filter_vtbl
=
647 filter_QueryInterface
,
655 filter_SetSyncSource
,
656 filter_GetSyncSource
,
659 filter_QueryFilterInfo
,
660 filter_JoinFilterGraph
,
661 filter_QueryVendorInfo
,
662 filter_AddMediaStream
,
663 filter_GetMediaStream
,
664 filter_EnumMediaStreams
,
665 filter_SupportSeeking
,
666 filter_ReferenceTimeToStreamTime
,
667 filter_GetCurrentStreamTime
,
673 static inline struct filter
*impl_from_IMediaSeeking(IMediaSeeking
*iface
)
675 return CONTAINING_RECORD(iface
, struct filter
, IMediaSeeking_iface
);
678 static HRESULT WINAPI
filter_seeking_QueryInterface(IMediaSeeking
*iface
, REFIID iid
, void **out
)
680 struct filter
*filter
= impl_from_IMediaSeeking(iface
);
681 return IMediaStreamFilter_QueryInterface(&filter
->IMediaStreamFilter_iface
, iid
, out
);
684 static ULONG WINAPI
filter_seeking_AddRef(IMediaSeeking
*iface
)
686 struct filter
*filter
= impl_from_IMediaSeeking(iface
);
687 return IMediaStreamFilter_AddRef(&filter
->IMediaStreamFilter_iface
);
690 static ULONG WINAPI
filter_seeking_Release(IMediaSeeking
*iface
)
692 struct filter
*filter
= impl_from_IMediaSeeking(iface
);
693 return IMediaStreamFilter_Release(&filter
->IMediaStreamFilter_iface
);
696 static HRESULT WINAPI
filter_seeking_GetCapabilities(IMediaSeeking
*iface
, DWORD
*capabilities
)
698 FIXME("iface %p, capabilities %p, stub!\n", iface
, capabilities
);
703 static HRESULT WINAPI
filter_seeking_CheckCapabilities(IMediaSeeking
*iface
, DWORD
*capabilities
)
705 FIXME("iface %p, capabilities %p, stub!\n", iface
, capabilities
);
710 static HRESULT WINAPI
filter_seeking_IsFormatSupported(IMediaSeeking
*iface
, const GUID
*format
)
712 FIXME("iface %p, format %s, stub!\n", iface
, debugstr_guid(format
));
717 static HRESULT WINAPI
filter_seeking_QueryPreferredFormat(IMediaSeeking
*iface
, GUID
*format
)
719 FIXME("iface %p, format %p, stub!\n", iface
, format
);
724 static HRESULT WINAPI
filter_seeking_GetTimeFormat(IMediaSeeking
*iface
, GUID
*format
)
726 FIXME("iface %p, format %p, stub!\n", iface
, format
);
731 static HRESULT WINAPI
filter_seeking_IsUsingTimeFormat(IMediaSeeking
*iface
, const GUID
*format
)
733 FIXME("iface %p, format %s, stub!\n", iface
, debugstr_guid(format
));
738 static HRESULT WINAPI
filter_seeking_SetTimeFormat(IMediaSeeking
*iface
, const GUID
*format
)
740 FIXME("iface %p, format %s, stub!\n", iface
, debugstr_guid(format
));
745 static HRESULT WINAPI
filter_seeking_GetDuration(IMediaSeeking
*iface
, LONGLONG
*duration
)
747 FIXME("iface %p, duration %p, stub!\n", iface
, duration
);
752 static HRESULT WINAPI
filter_seeking_GetStopPosition(IMediaSeeking
*iface
, LONGLONG
*stop
)
754 FIXME("iface %p, stop %p, stub!\n", iface
, stop
);
759 static HRESULT WINAPI
filter_seeking_GetCurrentPosition(IMediaSeeking
*iface
, LONGLONG
*current
)
761 FIXME("iface %p, current %p, stub!\n", iface
, current
);
766 static HRESULT WINAPI
filter_seeking_ConvertTimeFormat(IMediaSeeking
*iface
, LONGLONG
*target
,
767 const GUID
*target_format
, LONGLONG source
, const GUID
*source_format
)
769 FIXME("iface %p, target %p, target_format %s, source 0x%s, source_format %s, stub!\n", iface
, target
, debugstr_guid(target_format
),
770 wine_dbgstr_longlong(source
), debugstr_guid(source_format
));
775 static HRESULT WINAPI
filter_seeking_SetPositions(IMediaSeeking
*iface
, LONGLONG
*current_ptr
, DWORD current_flags
,
776 LONGLONG
*stop_ptr
, DWORD stop_flags
)
778 FIXME("iface %p, current %s, current_flags %#x, stop %s, stop_flags %#x, stub!\n", iface
,
779 current_ptr
? wine_dbgstr_longlong(*current_ptr
) : "<null>", current_flags
,
780 stop_ptr
? wine_dbgstr_longlong(*stop_ptr
): "<null>", stop_flags
);
785 static HRESULT WINAPI
filter_seeking_GetPositions(IMediaSeeking
*iface
, LONGLONG
*current
, LONGLONG
*stop
)
787 FIXME("iface %p, current %p, stop %p, stub!\n", iface
, current
, stop
);
792 static HRESULT WINAPI
filter_seeking_GetAvailable(IMediaSeeking
*iface
, LONGLONG
*earliest
, LONGLONG
*latest
)
794 FIXME("iface %p, earliest %p, latest %p, stub!\n", iface
, earliest
, latest
);
799 static HRESULT WINAPI
filter_seeking_SetRate(IMediaSeeking
*iface
, double rate
)
801 FIXME("iface %p, rate %f, stub!\n", iface
, rate
);
806 static HRESULT WINAPI
filter_seeking_GetRate(IMediaSeeking
*iface
, double *rate
)
808 FIXME("iface %p, rate %p, stub!\n", iface
, rate
);
813 static HRESULT WINAPI
filter_seeking_GetPreroll(IMediaSeeking
*iface
, LONGLONG
*preroll
)
815 FIXME("iface %p, preroll %p, stub!\n", iface
, preroll
);
820 static const IMediaSeekingVtbl filter_seeking_vtbl
=
822 filter_seeking_QueryInterface
,
823 filter_seeking_AddRef
,
824 filter_seeking_Release
,
825 filter_seeking_GetCapabilities
,
826 filter_seeking_CheckCapabilities
,
827 filter_seeking_IsFormatSupported
,
828 filter_seeking_QueryPreferredFormat
,
829 filter_seeking_GetTimeFormat
,
830 filter_seeking_IsUsingTimeFormat
,
831 filter_seeking_SetTimeFormat
,
832 filter_seeking_GetDuration
,
833 filter_seeking_GetStopPosition
,
834 filter_seeking_GetCurrentPosition
,
835 filter_seeking_ConvertTimeFormat
,
836 filter_seeking_SetPositions
,
837 filter_seeking_GetPositions
,
838 filter_seeking_GetAvailable
,
839 filter_seeking_SetRate
,
840 filter_seeking_GetRate
,
841 filter_seeking_GetPreroll
,
844 HRESULT
filter_create(IUnknown
*outer
, void **out
)
846 struct filter
*object
;
848 TRACE("outer %p, out %p.\n", outer
, out
);
851 return CLASS_E_NOAGGREGATION
;
853 if (!(object
= heap_alloc_zero(sizeof(*object
))))
854 return E_OUTOFMEMORY
;
856 object
->IMediaStreamFilter_iface
.lpVtbl
= &filter_vtbl
;
857 object
->IMediaSeeking_iface
.lpVtbl
= &filter_seeking_vtbl
;
858 object
->refcount
= 1;
859 InitializeCriticalSection(&object
->cs
);
860 object
->cs
.DebugInfo
->Spare
[0] = (DWORD_PTR
)(__FILE__
": MediaStreamFilter.cs");
862 TRACE("Created media stream filter %p.\n", object
);
863 *out
= &object
->IMediaStreamFilter_iface
;