wined3d: Pass a wined3d_device_context to wined3d_cs_emit_blt_sub_resource().
[wine/zf.git] / dlls / amstream / filter.c
blob3c0436a294ff34fdfdb91fe99e7ebc440d8f57cb
1 /*
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
21 #define COBJMACROS
22 #include "amstream_private.h"
23 #include "wine/debug.h"
24 #include "wine/list.h"
26 WINE_DEFAULT_DEBUG_CHANNEL(amstream);
28 struct enum_pins
30 IEnumPins IEnumPins_iface;
31 LONG refcount;
33 IPin **pins;
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);
51 *out = iface;
52 return S_OK;
55 WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(iid));
56 *out = NULL;
57 return E_NOINTERFACE;
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);
65 return 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);
72 unsigned int i;
74 TRACE("%p decreasing refcount to %u.\n", enum_pins, refcount);
75 if (!refcount)
77 for (i = 0; i < enum_pins->count; ++i)
78 IPin_Release(enum_pins->pins[i]);
79 heap_free(enum_pins->pins);
80 heap_free(enum_pins);
82 return refcount;
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);
88 unsigned int i;
90 TRACE("iface %p, count %u, pins %p, ret_count %p.\n", iface, count, pins, ret_count);
92 if (!pins || (count > 1 && !ret_count))
93 return E_POINTER;
95 for (i = 0; i < count && enum_pins->index < enum_pins->count; ++i)
97 IPin_AddRef(pins[i] = enum_pins->pins[i]);
98 enum_pins->index++;
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;
123 return S_OK;
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;
130 unsigned int i;
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))))
143 heap_free(object);
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;
150 return S_OK;
153 static const IEnumPinsVtbl enum_pins_vtbl =
155 enum_pins_QueryInterface,
156 enum_pins_AddRef,
157 enum_pins_Release,
158 enum_pins_Next,
159 enum_pins_Skip,
160 enum_pins_Reset,
161 enum_pins_Clone,
164 struct filter
166 IMediaStreamFilter IMediaStreamFilter_iface;
167 IMediaSeeking IMediaSeeking_iface;
168 LONG refcount;
169 CRITICAL_SECTION cs;
171 IReferenceClock *clock;
172 WCHAR name[128];
173 IFilterGraph *graph;
174 ULONG nb_streams;
175 IAMMediaStream **streams;
176 IAMMediaStream *seekable_stream;
177 FILTER_STATE state;
178 REFERENCE_TIME start_time;
179 struct list free_events;
180 struct list used_events;
183 struct event
185 struct list entry;
186 HANDLE event;
187 DWORD_PTR cookie;
188 BOOL interrupted;
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);
202 *out = NULL;
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))
209 *out = iface;
210 else if (IsEqualGUID(iid, &IID_IMediaSeeking) && filter->seekable_stream)
211 *out = &filter->IMediaSeeking_iface;
212 else
213 return E_NOINTERFACE;
215 IUnknown_AddRef((IUnknown *)*out);
216 return S_OK;
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);
226 return refcount;
229 static ULONG WINAPI filter_Release(IMediaStreamFilter *iface)
231 struct filter *filter = impl_from_IMediaStreamFilter(iface);
232 ULONG refcount = InterlockedDecrement(&filter->refcount);
233 unsigned int i;
235 TRACE("%p decreasing refcount to %u.\n", iface, refcount);
237 if (!refcount)
239 struct list *entry;
241 while ((entry = list_head(&filter->free_events)))
243 struct event *event = LIST_ENTRY(entry, struct event, entry);
244 list_remove(entry);
245 CloseHandle(event->event);
246 free(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);
254 if (filter->clock)
255 IReferenceClock_Release(filter->clock);
256 DeleteCriticalSection(&filter->cs);
257 heap_free(filter);
260 return refcount;
263 static HRESULT WINAPI filter_GetClassID(IMediaStreamFilter *iface, CLSID *clsid)
265 *clsid = CLSID_MediaStreamFilter;
266 return S_OK;
269 static void set_state(struct filter *filter, FILTER_STATE state)
271 if (filter->state != state)
273 ULONG i;
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);
284 struct event *event;
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);
304 return S_OK;
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);
319 return S_OK;
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);
335 return S_OK;
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);
344 if (!state)
345 return E_POINTER;
347 EnterCriticalSection(&filter->cs);
349 *state = filter->state;
351 LeaveCriticalSection(&filter->cs);
353 return S_OK;
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);
364 if (clock)
365 IReferenceClock_AddRef(clock);
366 if (filter->clock)
367 IReferenceClock_Release(filter->clock);
368 filter->clock = clock;
370 LeaveCriticalSection(&filter->cs);
372 return S_OK;
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);
383 if (filter->clock)
384 IReferenceClock_AddRef(filter->clock);
385 *clock = filter->clock;
387 LeaveCriticalSection(&filter->cs);
389 return S_OK;
392 static HRESULT WINAPI filter_EnumPins(IMediaStreamFilter *iface, IEnumPins **enum_pins)
394 struct filter *filter = impl_from_IMediaStreamFilter(iface);
395 struct enum_pins *object;
396 unsigned int i;
398 TRACE("iface %p, enum_pins %p.\n", iface, enum_pins);
400 if (!enum_pins)
401 return E_POINTER;
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;
411 object->index = 0;
412 if (!(object->pins = heap_alloc(filter->nb_streams * sizeof(*object->pins))))
414 heap_free(object);
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;
427 return S_OK;
430 static HRESULT WINAPI filter_FindPin(IMediaStreamFilter *iface, const WCHAR *id, IPin **out)
432 struct filter *filter = impl_from_IMediaStreamFilter(iface);
433 unsigned int i;
434 WCHAR *ret_id;
435 IPin *pin;
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]);
446 continue;
449 if (SUCCEEDED(IPin_QueryId(pin, &ret_id)))
451 if (!wcscmp(id, ret_id))
453 CoTaskMemFree(ret_id);
454 *out = pin;
455 LeaveCriticalSection(&filter->cs);
456 return S_OK;
458 CoTaskMemFree(ret_id);
460 IPin_Release(pin);
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);
477 if (filter->graph)
478 IFilterGraph_AddRef(filter->graph);
479 info->pGraph = filter->graph;
481 LeaveCriticalSection(&filter->cs);
483 return S_OK;
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);
495 if (name)
496 wcsncpy(filter->name, name, ARRAY_SIZE(filter->name));
497 else
498 filter->name[0] = 0;
499 filter->graph = graph;
501 LeaveCriticalSection(&filter->cs);
503 return S_OK;
506 static HRESULT WINAPI filter_QueryVendorInfo(IMediaStreamFilter *iface, LPWSTR *vendor_info)
508 WARN("iface %p, vendor_info %p, stub!\n", iface, vendor_info);
509 return E_NOTIMPL;
512 /*** IMediaStreamFilter methods ***/
514 static HRESULT WINAPI filter_AddMediaStream(IMediaStreamFilter *iface, IAMMediaStream *pAMMediaStream)
516 struct filter *This = impl_from_IMediaStreamFilter(iface);
517 IAMMediaStream** streams;
518 HRESULT hr;
520 TRACE("(%p)->(%p)\n", iface, pAMMediaStream);
522 streams = CoTaskMemRealloc(This->streams, (This->nb_streams + 1) * sizeof(IAMMediaStream*));
523 if (!streams)
524 return E_OUTOFMEMORY;
525 This->streams = streams;
527 hr = IAMMediaStream_JoinFilter(pAMMediaStream, iface);
528 if (FAILED(hr))
529 return hr;
531 hr = IAMMediaStream_JoinFilterGraph(pAMMediaStream, This->graph);
532 if (FAILED(hr))
533 return hr;
535 This->streams[This->nb_streams] = pAMMediaStream;
536 This->nb_streams++;
538 IAMMediaStream_AddRef(pAMMediaStream);
540 return S_OK;
543 static HRESULT WINAPI filter_GetMediaStream(IMediaStreamFilter *iface, REFMSPID idPurpose, IMediaStream **ppMediaStream)
545 struct filter *This = impl_from_IMediaStreamFilter(iface);
546 MSPID purpose_id;
547 unsigned int i;
549 TRACE("(%p)->(%s,%p)\n", iface, debugstr_guid(idPurpose), ppMediaStream);
551 if (!ppMediaStream)
552 return E_POINTER;
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);
561 return S_OK;
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)
575 return S_FALSE;
577 if (!stream)
578 return E_POINTER;
580 IMediaStream_AddRef(*stream = (IMediaStream *)filter->streams[index]);
581 return S_OK;
584 static IMediaSeeking *get_seeking(IAMMediaStream *stream)
586 IMediaSeeking *seeking;
587 IPin *pin, *peer;
588 HRESULT hr;
590 if (FAILED(IAMMediaStream_QueryInterface(stream, &IID_IPin, (void **)&pin)))
592 WARN("Stream %p does not support IPin.\n", stream);
593 return NULL;
596 hr = IPin_ConnectedTo(pin, &peer);
597 IPin_Release(pin);
598 if (FAILED(hr))
599 return NULL;
601 hr = IPin_QueryInterface(peer, &IID_IMediaSeeking, (void **)&seeking);
602 IPin_Release(peer);
603 if (FAILED(hr))
604 return NULL;
606 return seeking;
609 static HRESULT WINAPI filter_SupportSeeking(IMediaStreamFilter *iface, BOOL renderer)
611 struct filter *filter = impl_from_IMediaStreamFilter(iface);
612 unsigned int i;
614 TRACE("filter %p, renderer %d\n", iface, renderer);
616 if (!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]);
630 LONGLONG duration;
632 if (!seeking)
633 continue;
635 if (SUCCEEDED(IMediaSeeking_GetDuration(seeking, &duration)))
637 filter->seekable_stream = filter->streams[i];
638 IMediaSeeking_Release(seeking);
639 LeaveCriticalSection(&filter->cs);
640 return S_OK;
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);
658 if (!filter->clock)
660 LeaveCriticalSection(&filter->cs);
661 return S_FALSE;
664 *time -= filter->start_time;
666 LeaveCriticalSection(&filter->cs);
668 return S_OK;
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);
677 if (!time)
678 return E_POINTER;
680 EnterCriticalSection(&filter->cs);
682 if (filter->state != State_Running || !filter->clock)
684 *time = 0;
685 LeaveCriticalSection(&filter->cs);
686 return S_FALSE;
689 IReferenceClock_GetTime(filter->clock, time);
691 *time -= filter->start_time;
693 LeaveCriticalSection(&filter->cs);
695 return S_OK;
698 static HRESULT WINAPI filter_WaitUntil(IMediaStreamFilter *iface, REFERENCE_TIME time)
700 struct filter *filter = impl_from_IMediaStreamFilter(iface);
701 struct event *event;
702 struct list *entry;
703 HRESULT hr;
705 TRACE("filter %p, time %s.\n", iface, wine_dbgstr_longlong(time));
707 EnterCriticalSection(&filter->cs);
709 if (!filter->clock)
711 LeaveCriticalSection(&filter->cs);
712 return E_FAIL;
715 if ((entry = list_head(&filter->free_events)))
717 list_remove(entry);
718 event = LIST_ENTRY(entry, struct event, entry);
720 else
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);
729 if (FAILED(hr))
731 list_add_tail(&filter->free_events, entry);
732 LeaveCriticalSection(&filter->cs);
733 return hr;
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;
745 list_remove(entry);
746 list_add_tail(&filter->free_events, entry);
748 LeaveCriticalSection(&filter->cs);
750 return hr;
753 static HRESULT WINAPI filter_Flush(IMediaStreamFilter *iface, BOOL cancel_eos)
755 struct filter *filter = impl_from_IMediaStreamFilter(iface);
756 struct event *event;
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);
774 return S_OK;
777 static HRESULT WINAPI filter_EndOfStream(IMediaStreamFilter *iface)
779 FIXME("(%p)->(): Stub!\n", iface);
781 return E_NOTIMPL;
784 static const IMediaStreamFilterVtbl filter_vtbl =
786 filter_QueryInterface,
787 filter_AddRef,
788 filter_Release,
789 filter_GetClassID,
790 filter_Stop,
791 filter_Pause,
792 filter_Run,
793 filter_GetState,
794 filter_SetSyncSource,
795 filter_GetSyncSource,
796 filter_EnumPins,
797 filter_FindPin,
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,
807 filter_WaitUntil,
808 filter_Flush,
809 filter_EndOfStream
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);
839 return E_NOTIMPL;
842 static HRESULT WINAPI filter_seeking_CheckCapabilities(IMediaSeeking *iface, DWORD *capabilities)
844 FIXME("iface %p, capabilities %p, stub!\n", iface, capabilities);
846 return E_NOTIMPL;
849 static HRESULT WINAPI filter_seeking_IsFormatSupported(IMediaSeeking *iface, const GUID *format)
851 struct filter *filter = impl_from_IMediaSeeking(iface);
852 IMediaSeeking *seeking;
853 HRESULT hr;
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);
863 if (!seeking)
864 return E_NOTIMPL;
866 hr = IMediaSeeking_IsFormatSupported(seeking, format);
867 IMediaSeeking_Release(seeking);
869 return hr;
872 static HRESULT WINAPI filter_seeking_QueryPreferredFormat(IMediaSeeking *iface, GUID *format)
874 FIXME("iface %p, format %p, stub!\n", iface, format);
876 return E_NOTIMPL;
879 static HRESULT WINAPI filter_seeking_GetTimeFormat(IMediaSeeking *iface, GUID *format)
881 FIXME("iface %p, format %p, stub!\n", iface, format);
883 return E_NOTIMPL;
886 static HRESULT WINAPI filter_seeking_IsUsingTimeFormat(IMediaSeeking *iface, const GUID *format)
888 FIXME("iface %p, format %s, stub!\n", iface, debugstr_guid(format));
890 return E_NOTIMPL;
893 static HRESULT WINAPI filter_seeking_SetTimeFormat(IMediaSeeking *iface, const GUID *format)
895 FIXME("iface %p, format %s, stub!\n", iface, debugstr_guid(format));
897 return E_NOTIMPL;
900 static HRESULT WINAPI filter_seeking_GetDuration(IMediaSeeking *iface, LONGLONG *duration)
902 struct filter *filter = impl_from_IMediaSeeking(iface);
903 IMediaSeeking *seeking;
904 HRESULT hr;
906 TRACE("filter %p, duration %p.\n", filter, duration);
908 EnterCriticalSection(&filter->cs);
910 seeking = get_seeking(filter->seekable_stream);
912 LeaveCriticalSection(&filter->cs);
914 if (!seeking)
915 return E_NOTIMPL;
917 hr = IMediaSeeking_GetDuration(seeking, duration);
918 IMediaSeeking_Release(seeking);
920 return hr;
923 static HRESULT WINAPI filter_seeking_GetStopPosition(IMediaSeeking *iface, LONGLONG *stop)
925 struct filter *filter = impl_from_IMediaSeeking(iface);
926 IMediaSeeking *seeking;
927 HRESULT hr;
929 TRACE("filter %p, stop %p.\n", filter, stop);
931 EnterCriticalSection(&filter->cs);
933 seeking = get_seeking(filter->seekable_stream);
935 LeaveCriticalSection(&filter->cs);
937 if (!seeking)
938 return E_NOTIMPL;
940 hr = IMediaSeeking_GetStopPosition(seeking, stop);
941 IMediaSeeking_Release(seeking);
943 return hr;
946 static HRESULT WINAPI filter_seeking_GetCurrentPosition(IMediaSeeking *iface, LONGLONG *current)
948 FIXME("iface %p, current %p, stub!\n", iface, current);
950 return E_NOTIMPL;
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));
959 return E_NOTIMPL;
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;
967 HRESULT hr;
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);
979 if (!seeking)
980 return E_NOTIMPL;
982 hr = IMediaSeeking_SetPositions(seeking, current_ptr, current_flags, stop_ptr, stop_flags);
984 IMediaSeeking_Release(seeking);
986 return hr;
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);
993 return E_NOTIMPL;
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);
1000 return E_NOTIMPL;
1003 static HRESULT WINAPI filter_seeking_SetRate(IMediaSeeking *iface, double rate)
1005 FIXME("iface %p, rate %f, stub!\n", iface, rate);
1007 return E_NOTIMPL;
1010 static HRESULT WINAPI filter_seeking_GetRate(IMediaSeeking *iface, double *rate)
1012 FIXME("iface %p, rate %p, stub!\n", iface, rate);
1014 return E_NOTIMPL;
1017 static HRESULT WINAPI filter_seeking_GetPreroll(IMediaSeeking *iface, LONGLONG *preroll)
1019 FIXME("iface %p, preroll %p, stub!\n", iface, preroll);
1021 return E_NOTIMPL;
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);
1054 if (outer)
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;
1070 return S_OK;