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"
24 #include "wine/list.h"
26 WINE_DEFAULT_DEBUG_CHANNEL(amstream
);
30 IEnumPins IEnumPins_iface
;
34 unsigned int count
, index
;
37 static const IEnumPinsVtbl enum_pins_vtbl
;
39 static struct enum_pins
*impl_from_IEnumPins(IEnumPins
*iface
)
41 return CONTAINING_RECORD(iface
, struct enum_pins
, IEnumPins_iface
);
44 static HRESULT WINAPI
enum_pins_QueryInterface(IEnumPins
*iface
, REFIID iid
, void **out
)
46 TRACE("iface %p, iid %s, out %p.\n", iface
, debugstr_guid(iid
), out
);
48 if (IsEqualGUID(iid
, &IID_IUnknown
) || IsEqualGUID(iid
, &IID_IEnumPins
))
50 IEnumPins_AddRef(iface
);
55 WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(iid
));
60 static ULONG WINAPI
enum_pins_AddRef(IEnumPins
*iface
)
62 struct enum_pins
*enum_pins
= impl_from_IEnumPins(iface
);
63 ULONG refcount
= InterlockedIncrement(&enum_pins
->refcount
);
64 TRACE("%p increasing refcount to %u.\n", enum_pins
, refcount
);
68 static ULONG WINAPI
enum_pins_Release(IEnumPins
*iface
)
70 struct enum_pins
*enum_pins
= impl_from_IEnumPins(iface
);
71 ULONG refcount
= InterlockedDecrement(&enum_pins
->refcount
);
74 TRACE("%p decreasing refcount to %u.\n", enum_pins
, refcount
);
77 for (i
= 0; i
< enum_pins
->count
; ++i
)
78 IPin_Release(enum_pins
->pins
[i
]);
79 heap_free(enum_pins
->pins
);
85 static HRESULT WINAPI
enum_pins_Next(IEnumPins
*iface
, ULONG count
, IPin
**pins
, ULONG
*ret_count
)
87 struct enum_pins
*enum_pins
= impl_from_IEnumPins(iface
);
90 TRACE("iface %p, count %u, pins %p, ret_count %p.\n", iface
, count
, pins
, ret_count
);
92 if (!pins
|| (count
> 1 && !ret_count
))
95 for (i
= 0; i
< count
&& enum_pins
->index
< enum_pins
->count
; ++i
)
97 IPin_AddRef(pins
[i
] = enum_pins
->pins
[i
]);
101 if (ret_count
) *ret_count
= i
;
102 return i
== count
? S_OK
: S_FALSE
;
105 static HRESULT WINAPI
enum_pins_Skip(IEnumPins
*iface
, ULONG count
)
107 struct enum_pins
*enum_pins
= impl_from_IEnumPins(iface
);
109 TRACE("iface %p, count %u.\n", iface
, count
);
111 enum_pins
->index
+= count
;
113 return enum_pins
->index
>= enum_pins
->count
? S_FALSE
: S_OK
;
116 static HRESULT WINAPI
enum_pins_Reset(IEnumPins
*iface
)
118 struct enum_pins
*enum_pins
= impl_from_IEnumPins(iface
);
120 TRACE("iface %p.\n", iface
);
122 enum_pins
->index
= 0;
126 static HRESULT WINAPI
enum_pins_Clone(IEnumPins
*iface
, IEnumPins
**out
)
128 struct enum_pins
*enum_pins
= impl_from_IEnumPins(iface
);
129 struct enum_pins
*object
;
132 TRACE("iface %p, out %p.\n", iface
, out
);
134 if (!(object
= heap_alloc(sizeof(*object
))))
135 return E_OUTOFMEMORY
;
137 object
->IEnumPins_iface
.lpVtbl
= &enum_pins_vtbl
;
138 object
->refcount
= 1;
139 object
->count
= enum_pins
->count
;
140 object
->index
= enum_pins
->index
;
141 if (!(object
->pins
= heap_alloc(enum_pins
->count
* sizeof(*object
->pins
))))
144 return E_OUTOFMEMORY
;
146 for (i
= 0; i
< enum_pins
->count
; ++i
)
147 IPin_AddRef(object
->pins
[i
] = enum_pins
->pins
[i
]);
149 *out
= &object
->IEnumPins_iface
;
153 static const IEnumPinsVtbl enum_pins_vtbl
=
155 enum_pins_QueryInterface
,
166 IMediaStreamFilter IMediaStreamFilter_iface
;
167 IMediaSeeking IMediaSeeking_iface
;
171 IReferenceClock
*clock
;
175 IAMMediaStream
**streams
;
176 IAMMediaStream
*seekable_stream
;
178 REFERENCE_TIME start_time
;
179 struct list free_events
;
180 struct list used_events
;
192 static inline struct filter
*impl_from_IMediaStreamFilter(IMediaStreamFilter
*iface
)
194 return CONTAINING_RECORD(iface
, struct filter
, IMediaStreamFilter_iface
);
197 static HRESULT WINAPI
filter_QueryInterface(IMediaStreamFilter
*iface
, REFIID iid
, void **out
)
199 struct filter
*filter
= impl_from_IMediaStreamFilter(iface
);
201 TRACE("filter %p, iid %s, out %p.\n", filter
, debugstr_guid(iid
), out
);
205 if (IsEqualGUID(iid
, &IID_IUnknown
)
206 || IsEqualGUID(iid
, &IID_IPersist
)
207 || IsEqualGUID(iid
, &IID_IMediaFilter
)
208 || IsEqualGUID(iid
, &IID_IBaseFilter
)
209 || IsEqualGUID(iid
, &IID_IMediaStreamFilter
))
211 else if (IsEqualGUID(iid
, &IID_IMediaSeeking
) && filter
->seekable_stream
)
212 *out
= &filter
->IMediaSeeking_iface
;
214 return E_NOINTERFACE
;
216 IUnknown_AddRef((IUnknown
*)*out
);
220 static ULONG WINAPI
filter_AddRef(IMediaStreamFilter
*iface
)
222 struct filter
*filter
= impl_from_IMediaStreamFilter(iface
);
223 ULONG refcount
= InterlockedIncrement(&filter
->refcount
);
225 TRACE("%p increasing refcount to %u.\n", iface
, refcount
);
230 static ULONG WINAPI
filter_Release(IMediaStreamFilter
*iface
)
232 struct filter
*filter
= impl_from_IMediaStreamFilter(iface
);
233 ULONG refcount
= InterlockedDecrement(&filter
->refcount
);
236 TRACE("%p decreasing refcount to %u.\n", iface
, refcount
);
242 while ((entry
= list_head(&filter
->free_events
)))
244 struct event
*event
= LIST_ENTRY(entry
, struct event
, entry
);
246 CloseHandle(event
->event
);
249 for (i
= 0; i
< filter
->nb_streams
; ++i
)
251 IAMMediaStream_JoinFilter(filter
->streams
[i
], NULL
);
252 IAMMediaStream_Release(filter
->streams
[i
]);
254 heap_free(filter
->streams
);
256 IReferenceClock_Release(filter
->clock
);
257 DeleteCriticalSection(&filter
->cs
);
264 static HRESULT WINAPI
filter_GetClassID(IMediaStreamFilter
*iface
, CLSID
*clsid
)
266 *clsid
= CLSID_MediaStreamFilter
;
270 static void send_ec_complete(struct filter
*filter
)
272 IMediaEventSink
*event_sink
;
277 if (FAILED(IFilterGraph_QueryInterface(filter
->graph
, &IID_IMediaEventSink
, (void **)&event_sink
)))
280 IMediaEventSink_Notify(event_sink
, EC_COMPLETE
, S_OK
,
281 (LONG_PTR
)&filter
->IMediaStreamFilter_iface
);
283 IMediaEventSink_Release(event_sink
);
286 static void set_state(struct filter
*filter
, FILTER_STATE state
)
288 if (filter
->state
!= state
)
292 for (i
= 0; i
< filter
->nb_streams
; ++i
)
293 IAMMediaStream_SetState(filter
->streams
[i
], state
);
294 filter
->state
= state
;
298 static HRESULT WINAPI
filter_Stop(IMediaStreamFilter
*iface
)
300 struct filter
*filter
= impl_from_IMediaStreamFilter(iface
);
303 TRACE("iface %p.\n", iface
);
305 EnterCriticalSection(&filter
->cs
);
307 if (filter
->state
!= State_Stopped
)
308 filter
->eos_count
= 0;
310 set_state(filter
, State_Stopped
);
312 LIST_FOR_EACH_ENTRY(event
, &filter
->used_events
, struct event
, entry
)
314 if (!event
->interrupted
)
316 event
->interrupted
= TRUE
;
317 IReferenceClock_Unadvise(filter
->clock
, event
->cookie
);
318 SetEvent(event
->event
);
322 LeaveCriticalSection(&filter
->cs
);
327 static HRESULT WINAPI
filter_Pause(IMediaStreamFilter
*iface
)
329 struct filter
*filter
= impl_from_IMediaStreamFilter(iface
);
331 TRACE("iface %p.\n", iface
);
333 EnterCriticalSection(&filter
->cs
);
335 set_state(filter
, State_Paused
);
337 LeaveCriticalSection(&filter
->cs
);
342 static HRESULT WINAPI
filter_Run(IMediaStreamFilter
*iface
, REFERENCE_TIME start
)
344 struct filter
*filter
= impl_from_IMediaStreamFilter(iface
);
346 TRACE("iface %p, start %s.\n", iface
, wine_dbgstr_longlong(start
));
348 EnterCriticalSection(&filter
->cs
);
350 if (filter
->state
!= State_Running
&& filter
->seekable_stream
351 && filter
->eos_count
== (LONG
)filter
->nb_streams
)
352 send_ec_complete(filter
);
354 filter
->start_time
= start
;
355 set_state(filter
, State_Running
);
357 LeaveCriticalSection(&filter
->cs
);
362 static HRESULT WINAPI
filter_GetState(IMediaStreamFilter
*iface
, DWORD timeout
, FILTER_STATE
*state
)
364 struct filter
*filter
= impl_from_IMediaStreamFilter(iface
);
366 TRACE("iface %p, timeout %u, state %p.\n", iface
, timeout
, state
);
371 EnterCriticalSection(&filter
->cs
);
373 *state
= filter
->state
;
375 LeaveCriticalSection(&filter
->cs
);
380 static HRESULT WINAPI
filter_SetSyncSource(IMediaStreamFilter
*iface
, IReferenceClock
*clock
)
382 struct filter
*filter
= impl_from_IMediaStreamFilter(iface
);
384 TRACE("iface %p, clock %p.\n", iface
, clock
);
386 EnterCriticalSection(&filter
->cs
);
389 IReferenceClock_AddRef(clock
);
391 IReferenceClock_Release(filter
->clock
);
392 filter
->clock
= clock
;
394 LeaveCriticalSection(&filter
->cs
);
399 static HRESULT WINAPI
filter_GetSyncSource(IMediaStreamFilter
*iface
, IReferenceClock
**clock
)
401 struct filter
*filter
= impl_from_IMediaStreamFilter(iface
);
403 TRACE("iface %p, clock %p.\n", iface
, clock
);
405 EnterCriticalSection(&filter
->cs
);
408 IReferenceClock_AddRef(filter
->clock
);
409 *clock
= filter
->clock
;
411 LeaveCriticalSection(&filter
->cs
);
416 static HRESULT WINAPI
filter_EnumPins(IMediaStreamFilter
*iface
, IEnumPins
**enum_pins
)
418 struct filter
*filter
= impl_from_IMediaStreamFilter(iface
);
419 struct enum_pins
*object
;
422 TRACE("iface %p, enum_pins %p.\n", iface
, enum_pins
);
427 if (!(object
= heap_alloc(sizeof(*object
))))
428 return E_OUTOFMEMORY
;
430 EnterCriticalSection(&filter
->cs
);
432 object
->IEnumPins_iface
.lpVtbl
= &enum_pins_vtbl
;
433 object
->refcount
= 1;
434 object
->count
= filter
->nb_streams
;
436 if (!(object
->pins
= heap_alloc(filter
->nb_streams
* sizeof(*object
->pins
))))
439 LeaveCriticalSection(&filter
->cs
);
440 return E_OUTOFMEMORY
;
442 for (i
= 0; i
< filter
->nb_streams
; ++i
)
444 if (FAILED(IAMMediaStream_QueryInterface(filter
->streams
[i
], &IID_IPin
, (void **)&object
->pins
[i
])))
445 WARN("Stream %p does not support IPin.\n", filter
->streams
[i
]);
448 LeaveCriticalSection(&filter
->cs
);
450 *enum_pins
= &object
->IEnumPins_iface
;
454 static HRESULT WINAPI
filter_FindPin(IMediaStreamFilter
*iface
, const WCHAR
*id
, IPin
**out
)
456 struct filter
*filter
= impl_from_IMediaStreamFilter(iface
);
461 TRACE("iface %p, id %s, out %p.\n", iface
, debugstr_w(id
), out
);
463 EnterCriticalSection(&filter
->cs
);
465 for (i
= 0; i
< filter
->nb_streams
; ++i
)
467 if (FAILED(IAMMediaStream_QueryInterface(filter
->streams
[i
], &IID_IPin
, (void **)&pin
)))
469 WARN("Stream %p does not support IPin.\n", filter
->streams
[i
]);
473 if (SUCCEEDED(IPin_QueryId(pin
, &ret_id
)))
475 if (!wcscmp(id
, ret_id
))
477 CoTaskMemFree(ret_id
);
479 LeaveCriticalSection(&filter
->cs
);
482 CoTaskMemFree(ret_id
);
487 LeaveCriticalSection(&filter
->cs
);
489 return VFW_E_NOT_FOUND
;
492 static HRESULT WINAPI
filter_QueryFilterInfo(IMediaStreamFilter
*iface
, FILTER_INFO
*info
)
494 struct filter
*filter
= impl_from_IMediaStreamFilter(iface
);
496 TRACE("iface %p, info %p.\n", iface
, info
);
498 EnterCriticalSection(&filter
->cs
);
500 wcscpy(info
->achName
, filter
->name
);
502 IFilterGraph_AddRef(filter
->graph
);
503 info
->pGraph
= filter
->graph
;
505 LeaveCriticalSection(&filter
->cs
);
510 static HRESULT WINAPI
filter_JoinFilterGraph(IMediaStreamFilter
*iface
,
511 IFilterGraph
*graph
, const WCHAR
*name
)
513 struct filter
*filter
= impl_from_IMediaStreamFilter(iface
);
515 TRACE("iface %p, graph %p, name.%s.\n", iface
, graph
, debugstr_w(name
));
517 EnterCriticalSection(&filter
->cs
);
520 lstrcpynW(filter
->name
, name
, ARRAY_SIZE(filter
->name
));
523 filter
->graph
= graph
;
525 LeaveCriticalSection(&filter
->cs
);
530 static HRESULT WINAPI
filter_QueryVendorInfo(IMediaStreamFilter
*iface
, LPWSTR
*vendor_info
)
532 WARN("iface %p, vendor_info %p, stub!\n", iface
, vendor_info
);
536 /*** IMediaStreamFilter methods ***/
538 static HRESULT WINAPI
filter_AddMediaStream(IMediaStreamFilter
*iface
, IAMMediaStream
*pAMMediaStream
)
540 struct filter
*This
= impl_from_IMediaStreamFilter(iface
);
541 IAMMediaStream
** streams
;
544 TRACE("(%p)->(%p)\n", iface
, pAMMediaStream
);
546 streams
= CoTaskMemRealloc(This
->streams
, (This
->nb_streams
+ 1) * sizeof(IAMMediaStream
*));
548 return E_OUTOFMEMORY
;
549 This
->streams
= streams
;
551 hr
= IAMMediaStream_JoinFilter(pAMMediaStream
, iface
);
555 hr
= IAMMediaStream_JoinFilterGraph(pAMMediaStream
, This
->graph
);
559 This
->streams
[This
->nb_streams
] = pAMMediaStream
;
562 IAMMediaStream_AddRef(pAMMediaStream
);
567 static HRESULT WINAPI
filter_GetMediaStream(IMediaStreamFilter
*iface
, REFMSPID idPurpose
, IMediaStream
**ppMediaStream
)
569 struct filter
*This
= impl_from_IMediaStreamFilter(iface
);
573 TRACE("(%p)->(%s,%p)\n", iface
, debugstr_guid(idPurpose
), ppMediaStream
);
578 for (i
= 0; i
< This
->nb_streams
; i
++)
580 IAMMediaStream_GetInformation(This
->streams
[i
], &purpose_id
, NULL
);
581 if (IsEqualIID(&purpose_id
, idPurpose
))
583 *ppMediaStream
= (IMediaStream
*)This
->streams
[i
];
584 IMediaStream_AddRef(*ppMediaStream
);
589 return MS_E_NOSTREAM
;
592 static HRESULT WINAPI
filter_EnumMediaStreams(IMediaStreamFilter
*iface
, LONG index
, IMediaStream
**stream
)
594 struct filter
*filter
= impl_from_IMediaStreamFilter(iface
);
596 TRACE("filter %p, index %d, stream %p.\n", filter
, index
, stream
);
598 if (index
>= filter
->nb_streams
)
604 IMediaStream_AddRef(*stream
= (IMediaStream
*)filter
->streams
[index
]);
608 static IMediaSeeking
*get_seeking(IAMMediaStream
*stream
)
610 IMediaSeeking
*seeking
;
614 if (FAILED(IAMMediaStream_QueryInterface(stream
, &IID_IPin
, (void **)&pin
)))
616 WARN("Stream %p does not support IPin.\n", stream
);
620 hr
= IPin_ConnectedTo(pin
, &peer
);
625 hr
= IPin_QueryInterface(peer
, &IID_IMediaSeeking
, (void **)&seeking
);
633 static HRESULT WINAPI
filter_SupportSeeking(IMediaStreamFilter
*iface
, BOOL renderer
)
635 struct filter
*filter
= impl_from_IMediaStreamFilter(iface
);
638 TRACE("filter %p, renderer %d\n", iface
, renderer
);
641 FIXME("Non-renderer filter support is not yet implemented.\n");
643 EnterCriticalSection(&filter
->cs
);
645 if (filter
->seekable_stream
)
647 LeaveCriticalSection(&filter
->cs
);
648 return HRESULT_FROM_WIN32(ERROR_ALREADY_INITIALIZED
);
651 for (i
= 0; i
< filter
->nb_streams
; ++i
)
653 IMediaSeeking
*seeking
= get_seeking(filter
->streams
[i
]);
659 if (SUCCEEDED(IMediaSeeking_GetDuration(seeking
, &duration
)))
661 filter
->seekable_stream
= filter
->streams
[i
];
662 IMediaSeeking_Release(seeking
);
663 LeaveCriticalSection(&filter
->cs
);
667 IMediaSeeking_Release(seeking
);
670 LeaveCriticalSection(&filter
->cs
);
671 return E_NOINTERFACE
;
674 static HRESULT WINAPI
filter_ReferenceTimeToStreamTime(IMediaStreamFilter
*iface
, REFERENCE_TIME
*time
)
676 struct filter
*filter
= impl_from_IMediaStreamFilter(iface
);
678 TRACE("filter %p, time %p.\n", filter
, time
);
680 EnterCriticalSection(&filter
->cs
);
684 LeaveCriticalSection(&filter
->cs
);
688 *time
-= filter
->start_time
;
690 LeaveCriticalSection(&filter
->cs
);
695 static HRESULT WINAPI
filter_GetCurrentStreamTime(IMediaStreamFilter
*iface
, REFERENCE_TIME
*time
)
697 struct filter
*filter
= impl_from_IMediaStreamFilter(iface
);
699 TRACE("filter %p, time %p.\n", filter
, time
);
704 EnterCriticalSection(&filter
->cs
);
706 if (filter
->state
!= State_Running
|| !filter
->clock
)
709 LeaveCriticalSection(&filter
->cs
);
713 IReferenceClock_GetTime(filter
->clock
, time
);
715 *time
-= filter
->start_time
;
717 LeaveCriticalSection(&filter
->cs
);
722 static HRESULT WINAPI
filter_WaitUntil(IMediaStreamFilter
*iface
, REFERENCE_TIME time
)
724 struct filter
*filter
= impl_from_IMediaStreamFilter(iface
);
729 TRACE("filter %p, time %s.\n", iface
, wine_dbgstr_longlong(time
));
731 EnterCriticalSection(&filter
->cs
);
735 LeaveCriticalSection(&filter
->cs
);
739 if ((entry
= list_head(&filter
->free_events
)))
742 event
= LIST_ENTRY(entry
, struct event
, entry
);
746 event
= calloc(1, sizeof(struct event
));
747 event
->event
= CreateEventW(NULL
, FALSE
, FALSE
, NULL
);
749 entry
= &event
->entry
;
752 hr
= IReferenceClock_AdviseTime(filter
->clock
, time
, filter
->start_time
, (HEVENT
)event
->event
, &event
->cookie
);
755 list_add_tail(&filter
->free_events
, entry
);
756 LeaveCriticalSection(&filter
->cs
);
760 event
->interrupted
= FALSE
;
761 list_add_tail(&filter
->used_events
, entry
);
763 LeaveCriticalSection(&filter
->cs
);
764 WaitForSingleObject(event
->event
, INFINITE
);
765 EnterCriticalSection(&filter
->cs
);
767 hr
= event
->interrupted
? S_FALSE
: S_OK
;
770 list_add_tail(&filter
->free_events
, entry
);
772 LeaveCriticalSection(&filter
->cs
);
777 static HRESULT WINAPI
filter_Flush(IMediaStreamFilter
*iface
, BOOL cancel_eos
)
779 struct filter
*filter
= impl_from_IMediaStreamFilter(iface
);
782 TRACE("filter %p, cancel_eos %d.\n", iface
, cancel_eos
);
784 EnterCriticalSection(&filter
->cs
);
786 LIST_FOR_EACH_ENTRY(event
, &filter
->used_events
, struct event
, entry
)
788 if (!event
->interrupted
)
790 event
->interrupted
= TRUE
;
791 IReferenceClock_Unadvise(filter
->clock
, event
->cookie
);
792 SetEvent(event
->event
);
799 LeaveCriticalSection(&filter
->cs
);
804 static HRESULT WINAPI
filter_EndOfStream(IMediaStreamFilter
*iface
)
806 struct filter
*filter
= impl_from_IMediaStreamFilter(iface
);
808 TRACE("filter %p.\n", filter
);
810 EnterCriticalSection(&filter
->cs
);
813 if (filter
->state
== State_Running
&& filter
->seekable_stream
&&
814 filter
->eos_count
== (LONG
)filter
->nb_streams
)
815 send_ec_complete(filter
);
817 LeaveCriticalSection(&filter
->cs
);
822 static const IMediaStreamFilterVtbl filter_vtbl
=
824 filter_QueryInterface
,
832 filter_SetSyncSource
,
833 filter_GetSyncSource
,
836 filter_QueryFilterInfo
,
837 filter_JoinFilterGraph
,
838 filter_QueryVendorInfo
,
839 filter_AddMediaStream
,
840 filter_GetMediaStream
,
841 filter_EnumMediaStreams
,
842 filter_SupportSeeking
,
843 filter_ReferenceTimeToStreamTime
,
844 filter_GetCurrentStreamTime
,
850 static inline struct filter
*impl_from_IMediaSeeking(IMediaSeeking
*iface
)
852 return CONTAINING_RECORD(iface
, struct filter
, IMediaSeeking_iface
);
855 static HRESULT WINAPI
filter_seeking_QueryInterface(IMediaSeeking
*iface
, REFIID iid
, void **out
)
857 struct filter
*filter
= impl_from_IMediaSeeking(iface
);
858 return IMediaStreamFilter_QueryInterface(&filter
->IMediaStreamFilter_iface
, iid
, out
);
861 static ULONG WINAPI
filter_seeking_AddRef(IMediaSeeking
*iface
)
863 struct filter
*filter
= impl_from_IMediaSeeking(iface
);
864 return IMediaStreamFilter_AddRef(&filter
->IMediaStreamFilter_iface
);
867 static ULONG WINAPI
filter_seeking_Release(IMediaSeeking
*iface
)
869 struct filter
*filter
= impl_from_IMediaSeeking(iface
);
870 return IMediaStreamFilter_Release(&filter
->IMediaStreamFilter_iface
);
873 static HRESULT WINAPI
filter_seeking_GetCapabilities(IMediaSeeking
*iface
, DWORD
*capabilities
)
875 FIXME("iface %p, capabilities %p, stub!\n", iface
, capabilities
);
880 static HRESULT WINAPI
filter_seeking_CheckCapabilities(IMediaSeeking
*iface
, DWORD
*capabilities
)
882 FIXME("iface %p, capabilities %p, stub!\n", iface
, capabilities
);
887 static HRESULT WINAPI
filter_seeking_IsFormatSupported(IMediaSeeking
*iface
, const GUID
*format
)
889 struct filter
*filter
= impl_from_IMediaSeeking(iface
);
890 IMediaSeeking
*seeking
;
893 TRACE("filter %p, format %s.\n", filter
, debugstr_guid(format
));
895 EnterCriticalSection(&filter
->cs
);
897 seeking
= get_seeking(filter
->seekable_stream
);
899 LeaveCriticalSection(&filter
->cs
);
904 hr
= IMediaSeeking_IsFormatSupported(seeking
, format
);
905 IMediaSeeking_Release(seeking
);
910 static HRESULT WINAPI
filter_seeking_QueryPreferredFormat(IMediaSeeking
*iface
, GUID
*format
)
912 FIXME("iface %p, format %p, stub!\n", iface
, format
);
917 static HRESULT WINAPI
filter_seeking_GetTimeFormat(IMediaSeeking
*iface
, GUID
*format
)
919 FIXME("iface %p, format %p, stub!\n", iface
, format
);
924 static HRESULT WINAPI
filter_seeking_IsUsingTimeFormat(IMediaSeeking
*iface
, const GUID
*format
)
926 FIXME("iface %p, format %s, stub!\n", iface
, debugstr_guid(format
));
931 static HRESULT WINAPI
filter_seeking_SetTimeFormat(IMediaSeeking
*iface
, const GUID
*format
)
933 FIXME("iface %p, format %s, stub!\n", iface
, debugstr_guid(format
));
938 static HRESULT WINAPI
filter_seeking_GetDuration(IMediaSeeking
*iface
, LONGLONG
*duration
)
940 struct filter
*filter
= impl_from_IMediaSeeking(iface
);
941 IMediaSeeking
*seeking
;
944 TRACE("filter %p, duration %p.\n", filter
, duration
);
946 EnterCriticalSection(&filter
->cs
);
948 seeking
= get_seeking(filter
->seekable_stream
);
950 LeaveCriticalSection(&filter
->cs
);
955 hr
= IMediaSeeking_GetDuration(seeking
, duration
);
956 IMediaSeeking_Release(seeking
);
961 static HRESULT WINAPI
filter_seeking_GetStopPosition(IMediaSeeking
*iface
, LONGLONG
*stop
)
963 struct filter
*filter
= impl_from_IMediaSeeking(iface
);
964 IMediaSeeking
*seeking
;
967 TRACE("filter %p, stop %p.\n", filter
, stop
);
969 EnterCriticalSection(&filter
->cs
);
971 seeking
= get_seeking(filter
->seekable_stream
);
973 LeaveCriticalSection(&filter
->cs
);
978 hr
= IMediaSeeking_GetStopPosition(seeking
, stop
);
979 IMediaSeeking_Release(seeking
);
984 static HRESULT WINAPI
filter_seeking_GetCurrentPosition(IMediaSeeking
*iface
, LONGLONG
*current
)
986 FIXME("iface %p, current %p, stub!\n", iface
, current
);
991 static HRESULT WINAPI
filter_seeking_ConvertTimeFormat(IMediaSeeking
*iface
, LONGLONG
*target
,
992 const GUID
*target_format
, LONGLONG source
, const GUID
*source_format
)
994 FIXME("iface %p, target %p, target_format %s, source 0x%s, source_format %s, stub!\n", iface
, target
, debugstr_guid(target_format
),
995 wine_dbgstr_longlong(source
), debugstr_guid(source_format
));
1000 static HRESULT WINAPI
filter_seeking_SetPositions(IMediaSeeking
*iface
, LONGLONG
*current_ptr
, DWORD current_flags
,
1001 LONGLONG
*stop_ptr
, DWORD stop_flags
)
1003 struct filter
*filter
= impl_from_IMediaSeeking(iface
);
1004 IMediaSeeking
*seeking
;
1007 TRACE("iface %p, current %s, current_flags %#x, stop %s, stop_flags %#x.\n", iface
,
1008 current_ptr
? wine_dbgstr_longlong(*current_ptr
) : "<null>", current_flags
,
1009 stop_ptr
? wine_dbgstr_longlong(*stop_ptr
): "<null>", stop_flags
);
1011 EnterCriticalSection(&filter
->cs
);
1013 seeking
= get_seeking(filter
->seekable_stream
);
1015 LeaveCriticalSection(&filter
->cs
);
1020 hr
= IMediaSeeking_SetPositions(seeking
, current_ptr
, current_flags
, stop_ptr
, stop_flags
);
1022 IMediaSeeking_Release(seeking
);
1027 static HRESULT WINAPI
filter_seeking_GetPositions(IMediaSeeking
*iface
, LONGLONG
*current
, LONGLONG
*stop
)
1029 FIXME("iface %p, current %p, stop %p, stub!\n", iface
, current
, stop
);
1034 static HRESULT WINAPI
filter_seeking_GetAvailable(IMediaSeeking
*iface
, LONGLONG
*earliest
, LONGLONG
*latest
)
1036 FIXME("iface %p, earliest %p, latest %p, stub!\n", iface
, earliest
, latest
);
1041 static HRESULT WINAPI
filter_seeking_SetRate(IMediaSeeking
*iface
, double rate
)
1043 FIXME("iface %p, rate %f, stub!\n", iface
, rate
);
1048 static HRESULT WINAPI
filter_seeking_GetRate(IMediaSeeking
*iface
, double *rate
)
1050 FIXME("iface %p, rate %p, stub!\n", iface
, rate
);
1055 static HRESULT WINAPI
filter_seeking_GetPreroll(IMediaSeeking
*iface
, LONGLONG
*preroll
)
1057 FIXME("iface %p, preroll %p, stub!\n", iface
, preroll
);
1062 static const IMediaSeekingVtbl filter_seeking_vtbl
=
1064 filter_seeking_QueryInterface
,
1065 filter_seeking_AddRef
,
1066 filter_seeking_Release
,
1067 filter_seeking_GetCapabilities
,
1068 filter_seeking_CheckCapabilities
,
1069 filter_seeking_IsFormatSupported
,
1070 filter_seeking_QueryPreferredFormat
,
1071 filter_seeking_GetTimeFormat
,
1072 filter_seeking_IsUsingTimeFormat
,
1073 filter_seeking_SetTimeFormat
,
1074 filter_seeking_GetDuration
,
1075 filter_seeking_GetStopPosition
,
1076 filter_seeking_GetCurrentPosition
,
1077 filter_seeking_ConvertTimeFormat
,
1078 filter_seeking_SetPositions
,
1079 filter_seeking_GetPositions
,
1080 filter_seeking_GetAvailable
,
1081 filter_seeking_SetRate
,
1082 filter_seeking_GetRate
,
1083 filter_seeking_GetPreroll
,
1086 HRESULT
filter_create(IUnknown
*outer
, void **out
)
1088 struct filter
*object
;
1090 TRACE("outer %p, out %p.\n", outer
, out
);
1093 return CLASS_E_NOAGGREGATION
;
1095 if (!(object
= heap_alloc_zero(sizeof(*object
))))
1096 return E_OUTOFMEMORY
;
1098 object
->IMediaStreamFilter_iface
.lpVtbl
= &filter_vtbl
;
1099 object
->IMediaSeeking_iface
.lpVtbl
= &filter_seeking_vtbl
;
1100 object
->refcount
= 1;
1101 list_init(&object
->free_events
);
1102 list_init(&object
->used_events
);
1103 InitializeCriticalSection(&object
->cs
);
1104 object
->cs
.DebugInfo
->Spare
[0] = (DWORD_PTR
)(__FILE__
": MediaStreamFilter.cs");
1106 TRACE("Created media stream filter %p.\n", object
);
1107 *out
= &object
->IMediaStreamFilter_iface
;