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
;
191 static inline struct filter
*impl_from_IMediaStreamFilter(IMediaStreamFilter
*iface
)
193 return CONTAINING_RECORD(iface
, struct filter
, IMediaStreamFilter_iface
);
196 static HRESULT WINAPI
filter_QueryInterface(IMediaStreamFilter
*iface
, REFIID iid
, void **out
)
198 struct filter
*filter
= impl_from_IMediaStreamFilter(iface
);
200 TRACE("filter %p, iid %s, out %p.\n", filter
, debugstr_guid(iid
), out
);
204 if (IsEqualGUID(iid
, &IID_IUnknown
)
205 || IsEqualGUID(iid
, &IID_IPersist
)
206 || IsEqualGUID(iid
, &IID_IMediaFilter
)
207 || IsEqualGUID(iid
, &IID_IBaseFilter
)
208 || IsEqualGUID(iid
, &IID_IMediaStreamFilter
))
210 else if (IsEqualGUID(iid
, &IID_IMediaSeeking
) && filter
->seekable_stream
)
211 *out
= &filter
->IMediaSeeking_iface
;
213 return E_NOINTERFACE
;
215 IUnknown_AddRef((IUnknown
*)*out
);
219 static ULONG WINAPI
filter_AddRef(IMediaStreamFilter
*iface
)
221 struct filter
*filter
= impl_from_IMediaStreamFilter(iface
);
222 ULONG refcount
= InterlockedIncrement(&filter
->refcount
);
224 TRACE("%p increasing refcount to %u.\n", iface
, refcount
);
229 static ULONG WINAPI
filter_Release(IMediaStreamFilter
*iface
)
231 struct filter
*filter
= impl_from_IMediaStreamFilter(iface
);
232 ULONG refcount
= InterlockedDecrement(&filter
->refcount
);
235 TRACE("%p decreasing refcount to %u.\n", iface
, refcount
);
241 while ((entry
= list_head(&filter
->free_events
)))
243 struct event
*event
= LIST_ENTRY(entry
, struct event
, entry
);
245 CloseHandle(event
->event
);
248 for (i
= 0; i
< filter
->nb_streams
; ++i
)
250 IAMMediaStream_JoinFilter(filter
->streams
[i
], NULL
);
251 IAMMediaStream_Release(filter
->streams
[i
]);
253 heap_free(filter
->streams
);
255 IReferenceClock_Release(filter
->clock
);
256 DeleteCriticalSection(&filter
->cs
);
263 static HRESULT WINAPI
filter_GetClassID(IMediaStreamFilter
*iface
, CLSID
*clsid
)
265 *clsid
= CLSID_MediaStreamFilter
;
269 static void set_state(struct filter
*filter
, FILTER_STATE state
)
271 if (filter
->state
!= state
)
275 for (i
= 0; i
< filter
->nb_streams
; ++i
)
276 IAMMediaStream_SetState(filter
->streams
[i
], state
);
277 filter
->state
= state
;
281 static HRESULT WINAPI
filter_Stop(IMediaStreamFilter
*iface
)
283 struct filter
*filter
= impl_from_IMediaStreamFilter(iface
);
286 TRACE("iface %p.\n", iface
);
288 EnterCriticalSection(&filter
->cs
);
290 set_state(filter
, State_Stopped
);
292 LIST_FOR_EACH_ENTRY(event
, &filter
->used_events
, struct event
, entry
)
294 if (!event
->interrupted
)
296 event
->interrupted
= TRUE
;
297 IReferenceClock_Unadvise(filter
->clock
, event
->cookie
);
298 SetEvent(event
->event
);
302 LeaveCriticalSection(&filter
->cs
);
307 static HRESULT WINAPI
filter_Pause(IMediaStreamFilter
*iface
)
309 struct filter
*filter
= impl_from_IMediaStreamFilter(iface
);
311 TRACE("iface %p.\n", iface
);
313 EnterCriticalSection(&filter
->cs
);
315 set_state(filter
, State_Paused
);
317 LeaveCriticalSection(&filter
->cs
);
322 static HRESULT WINAPI
filter_Run(IMediaStreamFilter
*iface
, REFERENCE_TIME start
)
324 struct filter
*filter
= impl_from_IMediaStreamFilter(iface
);
326 TRACE("iface %p, start %s.\n", iface
, wine_dbgstr_longlong(start
));
328 EnterCriticalSection(&filter
->cs
);
330 filter
->start_time
= start
;
331 set_state(filter
, State_Running
);
333 LeaveCriticalSection(&filter
->cs
);
338 static HRESULT WINAPI
filter_GetState(IMediaStreamFilter
*iface
, DWORD timeout
, FILTER_STATE
*state
)
340 struct filter
*filter
= impl_from_IMediaStreamFilter(iface
);
342 TRACE("iface %p, timeout %u, state %p.\n", iface
, timeout
, state
);
347 EnterCriticalSection(&filter
->cs
);
349 *state
= filter
->state
;
351 LeaveCriticalSection(&filter
->cs
);
356 static HRESULT WINAPI
filter_SetSyncSource(IMediaStreamFilter
*iface
, IReferenceClock
*clock
)
358 struct filter
*filter
= impl_from_IMediaStreamFilter(iface
);
360 TRACE("iface %p, clock %p.\n", iface
, clock
);
362 EnterCriticalSection(&filter
->cs
);
365 IReferenceClock_AddRef(clock
);
367 IReferenceClock_Release(filter
->clock
);
368 filter
->clock
= clock
;
370 LeaveCriticalSection(&filter
->cs
);
375 static HRESULT WINAPI
filter_GetSyncSource(IMediaStreamFilter
*iface
, IReferenceClock
**clock
)
377 struct filter
*filter
= impl_from_IMediaStreamFilter(iface
);
379 TRACE("iface %p, clock %p.\n", iface
, clock
);
381 EnterCriticalSection(&filter
->cs
);
384 IReferenceClock_AddRef(filter
->clock
);
385 *clock
= filter
->clock
;
387 LeaveCriticalSection(&filter
->cs
);
392 static HRESULT WINAPI
filter_EnumPins(IMediaStreamFilter
*iface
, IEnumPins
**enum_pins
)
394 struct filter
*filter
= impl_from_IMediaStreamFilter(iface
);
395 struct enum_pins
*object
;
398 TRACE("iface %p, enum_pins %p.\n", iface
, enum_pins
);
403 if (!(object
= heap_alloc(sizeof(*object
))))
404 return E_OUTOFMEMORY
;
406 EnterCriticalSection(&filter
->cs
);
408 object
->IEnumPins_iface
.lpVtbl
= &enum_pins_vtbl
;
409 object
->refcount
= 1;
410 object
->count
= filter
->nb_streams
;
412 if (!(object
->pins
= heap_alloc(filter
->nb_streams
* sizeof(*object
->pins
))))
415 LeaveCriticalSection(&filter
->cs
);
416 return E_OUTOFMEMORY
;
418 for (i
= 0; i
< filter
->nb_streams
; ++i
)
420 if (FAILED(IAMMediaStream_QueryInterface(filter
->streams
[i
], &IID_IPin
, (void **)&object
->pins
[i
])))
421 WARN("Stream %p does not support IPin.\n", filter
->streams
[i
]);
424 LeaveCriticalSection(&filter
->cs
);
426 *enum_pins
= &object
->IEnumPins_iface
;
430 static HRESULT WINAPI
filter_FindPin(IMediaStreamFilter
*iface
, const WCHAR
*id
, IPin
**out
)
432 struct filter
*filter
= impl_from_IMediaStreamFilter(iface
);
437 TRACE("iface %p, id %s, out %p.\n", iface
, debugstr_w(id
), out
);
439 EnterCriticalSection(&filter
->cs
);
441 for (i
= 0; i
< filter
->nb_streams
; ++i
)
443 if (FAILED(IAMMediaStream_QueryInterface(filter
->streams
[i
], &IID_IPin
, (void **)&pin
)))
445 WARN("Stream %p does not support IPin.\n", filter
->streams
[i
]);
449 if (SUCCEEDED(IPin_QueryId(pin
, &ret_id
)))
451 if (!wcscmp(id
, ret_id
))
453 CoTaskMemFree(ret_id
);
455 LeaveCriticalSection(&filter
->cs
);
458 CoTaskMemFree(ret_id
);
463 LeaveCriticalSection(&filter
->cs
);
465 return VFW_E_NOT_FOUND
;
468 static HRESULT WINAPI
filter_QueryFilterInfo(IMediaStreamFilter
*iface
, FILTER_INFO
*info
)
470 struct filter
*filter
= impl_from_IMediaStreamFilter(iface
);
472 TRACE("iface %p, info %p.\n", iface
, info
);
474 EnterCriticalSection(&filter
->cs
);
476 wcscpy(info
->achName
, filter
->name
);
478 IFilterGraph_AddRef(filter
->graph
);
479 info
->pGraph
= filter
->graph
;
481 LeaveCriticalSection(&filter
->cs
);
486 static HRESULT WINAPI
filter_JoinFilterGraph(IMediaStreamFilter
*iface
,
487 IFilterGraph
*graph
, const WCHAR
*name
)
489 struct filter
*filter
= impl_from_IMediaStreamFilter(iface
);
491 TRACE("iface %p, graph %p, name.%s.\n", iface
, graph
, debugstr_w(name
));
493 EnterCriticalSection(&filter
->cs
);
496 wcsncpy(filter
->name
, name
, ARRAY_SIZE(filter
->name
));
499 filter
->graph
= graph
;
501 LeaveCriticalSection(&filter
->cs
);
506 static HRESULT WINAPI
filter_QueryVendorInfo(IMediaStreamFilter
*iface
, LPWSTR
*vendor_info
)
508 WARN("iface %p, vendor_info %p, stub!\n", iface
, vendor_info
);
512 /*** IMediaStreamFilter methods ***/
514 static HRESULT WINAPI
filter_AddMediaStream(IMediaStreamFilter
*iface
, IAMMediaStream
*pAMMediaStream
)
516 struct filter
*This
= impl_from_IMediaStreamFilter(iface
);
517 IAMMediaStream
** streams
;
520 TRACE("(%p)->(%p)\n", iface
, pAMMediaStream
);
522 streams
= CoTaskMemRealloc(This
->streams
, (This
->nb_streams
+ 1) * sizeof(IAMMediaStream
*));
524 return E_OUTOFMEMORY
;
525 This
->streams
= streams
;
527 hr
= IAMMediaStream_JoinFilter(pAMMediaStream
, iface
);
531 hr
= IAMMediaStream_JoinFilterGraph(pAMMediaStream
, This
->graph
);
535 This
->streams
[This
->nb_streams
] = pAMMediaStream
;
538 IAMMediaStream_AddRef(pAMMediaStream
);
543 static HRESULT WINAPI
filter_GetMediaStream(IMediaStreamFilter
*iface
, REFMSPID idPurpose
, IMediaStream
**ppMediaStream
)
545 struct filter
*This
= impl_from_IMediaStreamFilter(iface
);
549 TRACE("(%p)->(%s,%p)\n", iface
, debugstr_guid(idPurpose
), ppMediaStream
);
554 for (i
= 0; i
< This
->nb_streams
; i
++)
556 IAMMediaStream_GetInformation(This
->streams
[i
], &purpose_id
, NULL
);
557 if (IsEqualIID(&purpose_id
, idPurpose
))
559 *ppMediaStream
= (IMediaStream
*)This
->streams
[i
];
560 IMediaStream_AddRef(*ppMediaStream
);
565 return MS_E_NOSTREAM
;
568 static HRESULT WINAPI
filter_EnumMediaStreams(IMediaStreamFilter
*iface
, LONG index
, IMediaStream
**stream
)
570 struct filter
*filter
= impl_from_IMediaStreamFilter(iface
);
572 TRACE("filter %p, index %d, stream %p.\n", filter
, index
, stream
);
574 if (index
>= filter
->nb_streams
)
580 IMediaStream_AddRef(*stream
= (IMediaStream
*)filter
->streams
[index
]);
584 static IMediaSeeking
*get_seeking(IAMMediaStream
*stream
)
586 IMediaSeeking
*seeking
;
590 if (FAILED(IAMMediaStream_QueryInterface(stream
, &IID_IPin
, (void **)&pin
)))
592 WARN("Stream %p does not support IPin.\n", stream
);
596 hr
= IPin_ConnectedTo(pin
, &peer
);
601 hr
= IPin_QueryInterface(peer
, &IID_IMediaSeeking
, (void **)&seeking
);
609 static HRESULT WINAPI
filter_SupportSeeking(IMediaStreamFilter
*iface
, BOOL renderer
)
611 struct filter
*filter
= impl_from_IMediaStreamFilter(iface
);
614 TRACE("filter %p, renderer %d\n", iface
, renderer
);
617 FIXME("Non-renderer filter support is not yet implemented.\n");
619 EnterCriticalSection(&filter
->cs
);
621 if (filter
->seekable_stream
)
623 LeaveCriticalSection(&filter
->cs
);
624 return HRESULT_FROM_WIN32(ERROR_ALREADY_INITIALIZED
);
627 for (i
= 0; i
< filter
->nb_streams
; ++i
)
629 IMediaSeeking
*seeking
= get_seeking(filter
->streams
[i
]);
635 if (SUCCEEDED(IMediaSeeking_GetDuration(seeking
, &duration
)))
637 filter
->seekable_stream
= filter
->streams
[i
];
638 IMediaSeeking_Release(seeking
);
639 LeaveCriticalSection(&filter
->cs
);
643 IMediaSeeking_Release(seeking
);
646 LeaveCriticalSection(&filter
->cs
);
647 return E_NOINTERFACE
;
650 static HRESULT WINAPI
filter_ReferenceTimeToStreamTime(IMediaStreamFilter
*iface
, REFERENCE_TIME
*time
)
652 struct filter
*filter
= impl_from_IMediaStreamFilter(iface
);
654 TRACE("filter %p, time %p.\n", filter
, time
);
656 EnterCriticalSection(&filter
->cs
);
660 LeaveCriticalSection(&filter
->cs
);
664 *time
-= filter
->start_time
;
666 LeaveCriticalSection(&filter
->cs
);
671 static HRESULT WINAPI
filter_GetCurrentStreamTime(IMediaStreamFilter
*iface
, REFERENCE_TIME
*time
)
673 struct filter
*filter
= impl_from_IMediaStreamFilter(iface
);
675 TRACE("filter %p, time %p.\n", filter
, time
);
680 EnterCriticalSection(&filter
->cs
);
682 if (filter
->state
!= State_Running
|| !filter
->clock
)
685 LeaveCriticalSection(&filter
->cs
);
689 IReferenceClock_GetTime(filter
->clock
, time
);
691 *time
-= filter
->start_time
;
693 LeaveCriticalSection(&filter
->cs
);
698 static HRESULT WINAPI
filter_WaitUntil(IMediaStreamFilter
*iface
, REFERENCE_TIME time
)
700 struct filter
*filter
= impl_from_IMediaStreamFilter(iface
);
705 TRACE("filter %p, time %s.\n", iface
, wine_dbgstr_longlong(time
));
707 EnterCriticalSection(&filter
->cs
);
711 LeaveCriticalSection(&filter
->cs
);
715 if ((entry
= list_head(&filter
->free_events
)))
718 event
= LIST_ENTRY(entry
, struct event
, entry
);
722 event
= calloc(1, sizeof(struct event
));
723 event
->event
= CreateEventW(NULL
, FALSE
, FALSE
, NULL
);
725 entry
= &event
->entry
;
728 hr
= IReferenceClock_AdviseTime(filter
->clock
, time
, filter
->start_time
, (HEVENT
)event
->event
, &event
->cookie
);
731 list_add_tail(&filter
->free_events
, entry
);
732 LeaveCriticalSection(&filter
->cs
);
736 event
->interrupted
= FALSE
;
737 list_add_tail(&filter
->used_events
, entry
);
739 LeaveCriticalSection(&filter
->cs
);
740 WaitForSingleObject(event
->event
, INFINITE
);
741 EnterCriticalSection(&filter
->cs
);
743 hr
= event
->interrupted
? S_FALSE
: S_OK
;
746 list_add_tail(&filter
->free_events
, entry
);
748 LeaveCriticalSection(&filter
->cs
);
753 static HRESULT WINAPI
filter_Flush(IMediaStreamFilter
*iface
, BOOL cancel_eos
)
755 struct filter
*filter
= impl_from_IMediaStreamFilter(iface
);
758 TRACE("filter %p, cancel_eos %d.\n", iface
, cancel_eos
);
760 EnterCriticalSection(&filter
->cs
);
762 LIST_FOR_EACH_ENTRY(event
, &filter
->used_events
, struct event
, entry
)
764 if (!event
->interrupted
)
766 event
->interrupted
= TRUE
;
767 IReferenceClock_Unadvise(filter
->clock
, event
->cookie
);
768 SetEvent(event
->event
);
772 LeaveCriticalSection(&filter
->cs
);
777 static HRESULT WINAPI
filter_EndOfStream(IMediaStreamFilter
*iface
)
779 FIXME("(%p)->(): Stub!\n", iface
);
784 static const IMediaStreamFilterVtbl filter_vtbl
=
786 filter_QueryInterface
,
794 filter_SetSyncSource
,
795 filter_GetSyncSource
,
798 filter_QueryFilterInfo
,
799 filter_JoinFilterGraph
,
800 filter_QueryVendorInfo
,
801 filter_AddMediaStream
,
802 filter_GetMediaStream
,
803 filter_EnumMediaStreams
,
804 filter_SupportSeeking
,
805 filter_ReferenceTimeToStreamTime
,
806 filter_GetCurrentStreamTime
,
812 static inline struct filter
*impl_from_IMediaSeeking(IMediaSeeking
*iface
)
814 return CONTAINING_RECORD(iface
, struct filter
, IMediaSeeking_iface
);
817 static HRESULT WINAPI
filter_seeking_QueryInterface(IMediaSeeking
*iface
, REFIID iid
, void **out
)
819 struct filter
*filter
= impl_from_IMediaSeeking(iface
);
820 return IMediaStreamFilter_QueryInterface(&filter
->IMediaStreamFilter_iface
, iid
, out
);
823 static ULONG WINAPI
filter_seeking_AddRef(IMediaSeeking
*iface
)
825 struct filter
*filter
= impl_from_IMediaSeeking(iface
);
826 return IMediaStreamFilter_AddRef(&filter
->IMediaStreamFilter_iface
);
829 static ULONG WINAPI
filter_seeking_Release(IMediaSeeking
*iface
)
831 struct filter
*filter
= impl_from_IMediaSeeking(iface
);
832 return IMediaStreamFilter_Release(&filter
->IMediaStreamFilter_iface
);
835 static HRESULT WINAPI
filter_seeking_GetCapabilities(IMediaSeeking
*iface
, DWORD
*capabilities
)
837 FIXME("iface %p, capabilities %p, stub!\n", iface
, capabilities
);
842 static HRESULT WINAPI
filter_seeking_CheckCapabilities(IMediaSeeking
*iface
, DWORD
*capabilities
)
844 FIXME("iface %p, capabilities %p, stub!\n", iface
, capabilities
);
849 static HRESULT WINAPI
filter_seeking_IsFormatSupported(IMediaSeeking
*iface
, const GUID
*format
)
851 struct filter
*filter
= impl_from_IMediaSeeking(iface
);
852 IMediaSeeking
*seeking
;
855 TRACE("filter %p, format %s.\n", filter
, debugstr_guid(format
));
857 EnterCriticalSection(&filter
->cs
);
859 seeking
= get_seeking(filter
->seekable_stream
);
861 LeaveCriticalSection(&filter
->cs
);
866 hr
= IMediaSeeking_IsFormatSupported(seeking
, format
);
867 IMediaSeeking_Release(seeking
);
872 static HRESULT WINAPI
filter_seeking_QueryPreferredFormat(IMediaSeeking
*iface
, GUID
*format
)
874 FIXME("iface %p, format %p, stub!\n", iface
, format
);
879 static HRESULT WINAPI
filter_seeking_GetTimeFormat(IMediaSeeking
*iface
, GUID
*format
)
881 FIXME("iface %p, format %p, stub!\n", iface
, format
);
886 static HRESULT WINAPI
filter_seeking_IsUsingTimeFormat(IMediaSeeking
*iface
, const GUID
*format
)
888 FIXME("iface %p, format %s, stub!\n", iface
, debugstr_guid(format
));
893 static HRESULT WINAPI
filter_seeking_SetTimeFormat(IMediaSeeking
*iface
, const GUID
*format
)
895 FIXME("iface %p, format %s, stub!\n", iface
, debugstr_guid(format
));
900 static HRESULT WINAPI
filter_seeking_GetDuration(IMediaSeeking
*iface
, LONGLONG
*duration
)
902 struct filter
*filter
= impl_from_IMediaSeeking(iface
);
903 IMediaSeeking
*seeking
;
906 TRACE("filter %p, duration %p.\n", filter
, duration
);
908 EnterCriticalSection(&filter
->cs
);
910 seeking
= get_seeking(filter
->seekable_stream
);
912 LeaveCriticalSection(&filter
->cs
);
917 hr
= IMediaSeeking_GetDuration(seeking
, duration
);
918 IMediaSeeking_Release(seeking
);
923 static HRESULT WINAPI
filter_seeking_GetStopPosition(IMediaSeeking
*iface
, LONGLONG
*stop
)
925 struct filter
*filter
= impl_from_IMediaSeeking(iface
);
926 IMediaSeeking
*seeking
;
929 TRACE("filter %p, stop %p.\n", filter
, stop
);
931 EnterCriticalSection(&filter
->cs
);
933 seeking
= get_seeking(filter
->seekable_stream
);
935 LeaveCriticalSection(&filter
->cs
);
940 hr
= IMediaSeeking_GetStopPosition(seeking
, stop
);
941 IMediaSeeking_Release(seeking
);
946 static HRESULT WINAPI
filter_seeking_GetCurrentPosition(IMediaSeeking
*iface
, LONGLONG
*current
)
948 FIXME("iface %p, current %p, stub!\n", iface
, current
);
953 static HRESULT WINAPI
filter_seeking_ConvertTimeFormat(IMediaSeeking
*iface
, LONGLONG
*target
,
954 const GUID
*target_format
, LONGLONG source
, const GUID
*source_format
)
956 FIXME("iface %p, target %p, target_format %s, source 0x%s, source_format %s, stub!\n", iface
, target
, debugstr_guid(target_format
),
957 wine_dbgstr_longlong(source
), debugstr_guid(source_format
));
962 static HRESULT WINAPI
filter_seeking_SetPositions(IMediaSeeking
*iface
, LONGLONG
*current_ptr
, DWORD current_flags
,
963 LONGLONG
*stop_ptr
, DWORD stop_flags
)
965 struct filter
*filter
= impl_from_IMediaSeeking(iface
);
966 IMediaSeeking
*seeking
;
969 TRACE("iface %p, current %s, current_flags %#x, stop %s, stop_flags %#x.\n", iface
,
970 current_ptr
? wine_dbgstr_longlong(*current_ptr
) : "<null>", current_flags
,
971 stop_ptr
? wine_dbgstr_longlong(*stop_ptr
): "<null>", stop_flags
);
973 EnterCriticalSection(&filter
->cs
);
975 seeking
= get_seeking(filter
->seekable_stream
);
977 LeaveCriticalSection(&filter
->cs
);
982 hr
= IMediaSeeking_SetPositions(seeking
, current_ptr
, current_flags
, stop_ptr
, stop_flags
);
984 IMediaSeeking_Release(seeking
);
989 static HRESULT WINAPI
filter_seeking_GetPositions(IMediaSeeking
*iface
, LONGLONG
*current
, LONGLONG
*stop
)
991 FIXME("iface %p, current %p, stop %p, stub!\n", iface
, current
, stop
);
996 static HRESULT WINAPI
filter_seeking_GetAvailable(IMediaSeeking
*iface
, LONGLONG
*earliest
, LONGLONG
*latest
)
998 FIXME("iface %p, earliest %p, latest %p, stub!\n", iface
, earliest
, latest
);
1003 static HRESULT WINAPI
filter_seeking_SetRate(IMediaSeeking
*iface
, double rate
)
1005 FIXME("iface %p, rate %f, stub!\n", iface
, rate
);
1010 static HRESULT WINAPI
filter_seeking_GetRate(IMediaSeeking
*iface
, double *rate
)
1012 FIXME("iface %p, rate %p, stub!\n", iface
, rate
);
1017 static HRESULT WINAPI
filter_seeking_GetPreroll(IMediaSeeking
*iface
, LONGLONG
*preroll
)
1019 FIXME("iface %p, preroll %p, stub!\n", iface
, preroll
);
1024 static const IMediaSeekingVtbl filter_seeking_vtbl
=
1026 filter_seeking_QueryInterface
,
1027 filter_seeking_AddRef
,
1028 filter_seeking_Release
,
1029 filter_seeking_GetCapabilities
,
1030 filter_seeking_CheckCapabilities
,
1031 filter_seeking_IsFormatSupported
,
1032 filter_seeking_QueryPreferredFormat
,
1033 filter_seeking_GetTimeFormat
,
1034 filter_seeking_IsUsingTimeFormat
,
1035 filter_seeking_SetTimeFormat
,
1036 filter_seeking_GetDuration
,
1037 filter_seeking_GetStopPosition
,
1038 filter_seeking_GetCurrentPosition
,
1039 filter_seeking_ConvertTimeFormat
,
1040 filter_seeking_SetPositions
,
1041 filter_seeking_GetPositions
,
1042 filter_seeking_GetAvailable
,
1043 filter_seeking_SetRate
,
1044 filter_seeking_GetRate
,
1045 filter_seeking_GetPreroll
,
1048 HRESULT
filter_create(IUnknown
*outer
, void **out
)
1050 struct filter
*object
;
1052 TRACE("outer %p, out %p.\n", outer
, out
);
1055 return CLASS_E_NOAGGREGATION
;
1057 if (!(object
= heap_alloc_zero(sizeof(*object
))))
1058 return E_OUTOFMEMORY
;
1060 object
->IMediaStreamFilter_iface
.lpVtbl
= &filter_vtbl
;
1061 object
->IMediaSeeking_iface
.lpVtbl
= &filter_seeking_vtbl
;
1062 object
->refcount
= 1;
1063 list_init(&object
->free_events
);
1064 list_init(&object
->used_events
);
1065 InitializeCriticalSection(&object
->cs
);
1066 object
->cs
.DebugInfo
->Spare
[0] = (DWORD_PTR
)(__FILE__
": MediaStreamFilter.cs");
1068 TRACE("Created media stream filter %p.\n", object
);
1069 *out
= &object
->IMediaStreamFilter_iface
;