xactengine3_7: Add new dll.
[wine.git] / dlls / amstream / filter.c
blob13fd30c3a51529fb070161f6145945312f79c888
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"
25 WINE_DEFAULT_DEBUG_CHANNEL(amstream);
27 struct enum_pins
29 IEnumPins IEnumPins_iface;
30 LONG refcount;
32 IPin **pins;
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);
50 *out = iface;
51 return S_OK;
54 WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(iid));
55 *out = NULL;
56 return E_NOINTERFACE;
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);
64 return 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);
71 unsigned int i;
73 TRACE("%p decreasing refcount to %u.\n", enum_pins, refcount);
74 if (!refcount)
76 for (i = 0; i < enum_pins->count; ++i)
77 IPin_Release(enum_pins->pins[i]);
78 heap_free(enum_pins->pins);
79 heap_free(enum_pins);
81 return refcount;
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);
87 unsigned int i;
89 TRACE("iface %p, count %u, pins %p, ret_count %p.\n", iface, count, pins, ret_count);
91 if (!pins || (count > 1 && !ret_count))
92 return E_POINTER;
94 for (i = 0; i < count && enum_pins->index < enum_pins->count; ++i)
96 IPin_AddRef(pins[i] = enum_pins->pins[i]);
97 enum_pins->index++;
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;
122 return S_OK;
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;
129 unsigned int i;
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))))
142 heap_free(object);
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;
149 return S_OK;
152 static const IEnumPinsVtbl enum_pins_vtbl =
154 enum_pins_QueryInterface,
155 enum_pins_AddRef,
156 enum_pins_Release,
157 enum_pins_Next,
158 enum_pins_Skip,
159 enum_pins_Reset,
160 enum_pins_Clone,
163 struct filter
165 IMediaStreamFilter IMediaStreamFilter_iface;
166 IMediaSeeking IMediaSeeking_iface;
167 LONG refcount;
168 CRITICAL_SECTION cs;
170 IReferenceClock *clock;
171 WCHAR name[128];
172 IFilterGraph *graph;
173 ULONG nb_streams;
174 IAMMediaStream **streams;
175 IAMMediaStream *seekable_stream;
176 FILTER_STATE state;
177 REFERENCE_TIME start_time;
180 static inline struct filter *impl_from_IMediaStreamFilter(IMediaStreamFilter *iface)
182 return CONTAINING_RECORD(iface, struct filter, IMediaStreamFilter_iface);
185 static HRESULT WINAPI filter_QueryInterface(IMediaStreamFilter *iface, REFIID iid, void **out)
187 struct filter *filter = impl_from_IMediaStreamFilter(iface);
189 TRACE("filter %p, iid %s, out %p.\n", filter, debugstr_guid(iid), out);
191 *out = NULL;
193 if (IsEqualGUID(iid, &IID_IUnknown)
194 || IsEqualGUID(iid, &IID_IPersist)
195 || IsEqualGUID(iid, &IID_IMediaFilter)
196 || IsEqualGUID(iid, &IID_IBaseFilter)
197 || IsEqualGUID(iid, &IID_IMediaStreamFilter))
198 *out = iface;
199 else if (IsEqualGUID(iid, &IID_IMediaSeeking) && filter->seekable_stream)
200 *out = &filter->IMediaSeeking_iface;
201 else
202 return E_NOINTERFACE;
204 IUnknown_AddRef((IUnknown *)*out);
205 return S_OK;
208 static ULONG WINAPI filter_AddRef(IMediaStreamFilter *iface)
210 struct filter *filter = impl_from_IMediaStreamFilter(iface);
211 ULONG refcount = InterlockedIncrement(&filter->refcount);
213 TRACE("%p increasing refcount to %u.\n", iface, refcount);
215 return refcount;
218 static ULONG WINAPI filter_Release(IMediaStreamFilter *iface)
220 struct filter *filter = impl_from_IMediaStreamFilter(iface);
221 ULONG refcount = InterlockedDecrement(&filter->refcount);
222 unsigned int i;
224 TRACE("%p decreasing refcount to %u.\n", iface, refcount);
226 if (!refcount)
228 for (i = 0; i < filter->nb_streams; ++i)
230 IAMMediaStream_JoinFilter(filter->streams[i], NULL);
231 IAMMediaStream_Release(filter->streams[i]);
233 heap_free(filter->streams);
234 if (filter->clock)
235 IReferenceClock_Release(filter->clock);
236 DeleteCriticalSection(&filter->cs);
237 heap_free(filter);
240 return refcount;
243 static HRESULT WINAPI filter_GetClassID(IMediaStreamFilter *iface, CLSID *clsid)
245 *clsid = CLSID_MediaStreamFilter;
246 return S_OK;
249 static void set_state(struct filter *filter, FILTER_STATE state)
251 if (filter->state != state)
253 ULONG i;
255 for (i = 0; i < filter->nb_streams; ++i)
256 IAMMediaStream_SetState(filter->streams[i], state);
257 filter->state = state;
261 static HRESULT WINAPI filter_Stop(IMediaStreamFilter *iface)
263 struct filter *filter = impl_from_IMediaStreamFilter(iface);
265 TRACE("iface %p.\n", iface);
267 EnterCriticalSection(&filter->cs);
269 set_state(filter, State_Stopped);
271 LeaveCriticalSection(&filter->cs);
273 return S_OK;
276 static HRESULT WINAPI filter_Pause(IMediaStreamFilter *iface)
278 struct filter *filter = impl_from_IMediaStreamFilter(iface);
280 TRACE("iface %p.\n", iface);
282 EnterCriticalSection(&filter->cs);
284 set_state(filter, State_Paused);
286 LeaveCriticalSection(&filter->cs);
288 return S_OK;
291 static HRESULT WINAPI filter_Run(IMediaStreamFilter *iface, REFERENCE_TIME start)
293 struct filter *filter = impl_from_IMediaStreamFilter(iface);
295 TRACE("iface %p, start %s.\n", iface, wine_dbgstr_longlong(start));
297 EnterCriticalSection(&filter->cs);
299 filter->start_time = start;
300 set_state(filter, State_Running);
302 LeaveCriticalSection(&filter->cs);
304 return S_OK;
307 static HRESULT WINAPI filter_GetState(IMediaStreamFilter *iface, DWORD timeout, FILTER_STATE *state)
309 struct filter *filter = impl_from_IMediaStreamFilter(iface);
311 TRACE("iface %p, timeout %u, state %p.\n", iface, timeout, state);
313 if (!state)
314 return E_POINTER;
316 EnterCriticalSection(&filter->cs);
318 *state = filter->state;
320 LeaveCriticalSection(&filter->cs);
322 return S_OK;
325 static HRESULT WINAPI filter_SetSyncSource(IMediaStreamFilter *iface, IReferenceClock *clock)
327 struct filter *filter = impl_from_IMediaStreamFilter(iface);
329 TRACE("iface %p, clock %p.\n", iface, clock);
331 EnterCriticalSection(&filter->cs);
333 if (clock)
334 IReferenceClock_AddRef(clock);
335 if (filter->clock)
336 IReferenceClock_Release(filter->clock);
337 filter->clock = clock;
339 LeaveCriticalSection(&filter->cs);
341 return S_OK;
344 static HRESULT WINAPI filter_GetSyncSource(IMediaStreamFilter *iface, IReferenceClock **clock)
346 struct filter *filter = impl_from_IMediaStreamFilter(iface);
348 TRACE("iface %p, clock %p.\n", iface, clock);
350 EnterCriticalSection(&filter->cs);
352 if (filter->clock)
353 IReferenceClock_AddRef(filter->clock);
354 *clock = filter->clock;
356 LeaveCriticalSection(&filter->cs);
358 return S_OK;
361 static HRESULT WINAPI filter_EnumPins(IMediaStreamFilter *iface, IEnumPins **enum_pins)
363 struct filter *filter = impl_from_IMediaStreamFilter(iface);
364 struct enum_pins *object;
365 unsigned int i;
367 TRACE("iface %p, enum_pins %p.\n", iface, enum_pins);
369 if (!enum_pins)
370 return E_POINTER;
372 if (!(object = heap_alloc(sizeof(*object))))
373 return E_OUTOFMEMORY;
375 EnterCriticalSection(&filter->cs);
377 object->IEnumPins_iface.lpVtbl = &enum_pins_vtbl;
378 object->refcount = 1;
379 object->count = filter->nb_streams;
380 object->index = 0;
381 if (!(object->pins = heap_alloc(filter->nb_streams * sizeof(*object->pins))))
383 heap_free(object);
384 LeaveCriticalSection(&filter->cs);
385 return E_OUTOFMEMORY;
387 for (i = 0; i < filter->nb_streams; ++i)
389 if (FAILED(IAMMediaStream_QueryInterface(filter->streams[i], &IID_IPin, (void **)&object->pins[i])))
390 WARN("Stream %p does not support IPin.\n", filter->streams[i]);
393 LeaveCriticalSection(&filter->cs);
395 *enum_pins = &object->IEnumPins_iface;
396 return S_OK;
399 static HRESULT WINAPI filter_FindPin(IMediaStreamFilter *iface, const WCHAR *id, IPin **out)
401 struct filter *filter = impl_from_IMediaStreamFilter(iface);
402 unsigned int i;
403 WCHAR *ret_id;
404 IPin *pin;
406 TRACE("iface %p, id %s, out %p.\n", iface, debugstr_w(id), out);
408 EnterCriticalSection(&filter->cs);
410 for (i = 0; i < filter->nb_streams; ++i)
412 if (FAILED(IAMMediaStream_QueryInterface(filter->streams[i], &IID_IPin, (void **)&pin)))
414 WARN("Stream %p does not support IPin.\n", filter->streams[i]);
415 continue;
418 if (SUCCEEDED(IPin_QueryId(pin, &ret_id)))
420 if (!wcscmp(id, ret_id))
422 CoTaskMemFree(ret_id);
423 *out = pin;
424 LeaveCriticalSection(&filter->cs);
425 return S_OK;
427 CoTaskMemFree(ret_id);
429 IPin_Release(pin);
432 LeaveCriticalSection(&filter->cs);
434 return VFW_E_NOT_FOUND;
437 static HRESULT WINAPI filter_QueryFilterInfo(IMediaStreamFilter *iface, FILTER_INFO *info)
439 struct filter *filter = impl_from_IMediaStreamFilter(iface);
441 TRACE("iface %p, info %p.\n", iface, info);
443 EnterCriticalSection(&filter->cs);
445 wcscpy(info->achName, filter->name);
446 if (filter->graph)
447 IFilterGraph_AddRef(filter->graph);
448 info->pGraph = filter->graph;
450 LeaveCriticalSection(&filter->cs);
452 return S_OK;
455 static HRESULT WINAPI filter_JoinFilterGraph(IMediaStreamFilter *iface,
456 IFilterGraph *graph, const WCHAR *name)
458 struct filter *filter = impl_from_IMediaStreamFilter(iface);
460 TRACE("iface %p, graph %p, name.%s.\n", iface, graph, debugstr_w(name));
462 EnterCriticalSection(&filter->cs);
464 if (name)
465 wcsncpy(filter->name, name, ARRAY_SIZE(filter->name));
466 else
467 filter->name[0] = 0;
468 filter->graph = graph;
470 LeaveCriticalSection(&filter->cs);
472 return S_OK;
475 static HRESULT WINAPI filter_QueryVendorInfo(IMediaStreamFilter *iface, LPWSTR *vendor_info)
477 WARN("iface %p, vendor_info %p, stub!\n", iface, vendor_info);
478 return E_NOTIMPL;
481 /*** IMediaStreamFilter methods ***/
483 static HRESULT WINAPI filter_AddMediaStream(IMediaStreamFilter *iface, IAMMediaStream *pAMMediaStream)
485 struct filter *This = impl_from_IMediaStreamFilter(iface);
486 IAMMediaStream** streams;
487 HRESULT hr;
489 TRACE("(%p)->(%p)\n", iface, pAMMediaStream);
491 streams = CoTaskMemRealloc(This->streams, (This->nb_streams + 1) * sizeof(IAMMediaStream*));
492 if (!streams)
493 return E_OUTOFMEMORY;
494 This->streams = streams;
496 hr = IAMMediaStream_JoinFilter(pAMMediaStream, iface);
497 if (FAILED(hr))
498 return hr;
500 hr = IAMMediaStream_JoinFilterGraph(pAMMediaStream, This->graph);
501 if (FAILED(hr))
502 return hr;
504 This->streams[This->nb_streams] = pAMMediaStream;
505 This->nb_streams++;
507 IAMMediaStream_AddRef(pAMMediaStream);
509 return S_OK;
512 static HRESULT WINAPI filter_GetMediaStream(IMediaStreamFilter *iface, REFMSPID idPurpose, IMediaStream **ppMediaStream)
514 struct filter *This = impl_from_IMediaStreamFilter(iface);
515 MSPID purpose_id;
516 unsigned int i;
518 TRACE("(%p)->(%s,%p)\n", iface, debugstr_guid(idPurpose), ppMediaStream);
520 if (!ppMediaStream)
521 return E_POINTER;
523 for (i = 0; i < This->nb_streams; i++)
525 IAMMediaStream_GetInformation(This->streams[i], &purpose_id, NULL);
526 if (IsEqualIID(&purpose_id, idPurpose))
528 *ppMediaStream = (IMediaStream *)This->streams[i];
529 IMediaStream_AddRef(*ppMediaStream);
530 return S_OK;
534 return MS_E_NOSTREAM;
537 static HRESULT WINAPI filter_EnumMediaStreams(IMediaStreamFilter *iface, LONG index, IMediaStream **stream)
539 struct filter *filter = impl_from_IMediaStreamFilter(iface);
541 TRACE("filter %p, index %d, stream %p.\n", filter, index, stream);
543 if (index >= filter->nb_streams)
544 return S_FALSE;
546 if (!stream)
547 return E_POINTER;
549 IMediaStream_AddRef(*stream = (IMediaStream *)filter->streams[index]);
550 return S_OK;
553 static IMediaSeeking *get_seeking(IAMMediaStream *stream)
555 IMediaSeeking *seeking;
556 IPin *pin, *peer;
557 HRESULT hr;
559 if (FAILED(IAMMediaStream_QueryInterface(stream, &IID_IPin, (void **)&pin)))
561 WARN("Stream %p does not support IPin.\n", stream);
562 return NULL;
565 hr = IPin_ConnectedTo(pin, &peer);
566 IPin_Release(pin);
567 if (FAILED(hr))
568 return NULL;
570 hr = IPin_QueryInterface(peer, &IID_IMediaSeeking, (void **)&seeking);
571 IPin_Release(peer);
572 if (FAILED(hr))
573 return NULL;
575 return seeking;
578 static HRESULT WINAPI filter_SupportSeeking(IMediaStreamFilter *iface, BOOL renderer)
580 struct filter *filter = impl_from_IMediaStreamFilter(iface);
581 unsigned int i;
583 TRACE("filter %p, renderer %d\n", iface, renderer);
585 if (!renderer)
586 FIXME("Non-renderer filter support is not yet implemented.\n");
588 EnterCriticalSection(&filter->cs);
590 if (filter->seekable_stream)
592 LeaveCriticalSection(&filter->cs);
593 return HRESULT_FROM_WIN32(ERROR_ALREADY_INITIALIZED);
596 for (i = 0; i < filter->nb_streams; ++i)
598 IMediaSeeking *seeking = get_seeking(filter->streams[i]);
599 LONGLONG duration;
601 if (!seeking)
602 continue;
604 if (SUCCEEDED(IMediaSeeking_GetDuration(seeking, &duration)))
606 filter->seekable_stream = filter->streams[i];
607 IMediaSeeking_Release(seeking);
608 LeaveCriticalSection(&filter->cs);
609 return S_OK;
612 IMediaSeeking_Release(seeking);
615 LeaveCriticalSection(&filter->cs);
616 return E_NOINTERFACE;
619 static HRESULT WINAPI filter_ReferenceTimeToStreamTime(IMediaStreamFilter *iface, REFERENCE_TIME *pTime)
621 FIXME("(%p)->(%p): Stub!\n", iface, pTime);
623 return E_NOTIMPL;
626 static HRESULT WINAPI filter_GetCurrentStreamTime(IMediaStreamFilter *iface, REFERENCE_TIME *time)
628 struct filter *filter = impl_from_IMediaStreamFilter(iface);
630 TRACE("filter %p, time %p.\n", filter, time);
632 if (!time)
633 return E_POINTER;
635 EnterCriticalSection(&filter->cs);
637 if (filter->state != State_Running || !filter->clock)
639 *time = 0;
640 LeaveCriticalSection(&filter->cs);
641 return S_FALSE;
644 IReferenceClock_GetTime(filter->clock, time);
646 *time -= filter->start_time;
648 LeaveCriticalSection(&filter->cs);
650 return S_OK;
653 static HRESULT WINAPI filter_WaitUntil(IMediaStreamFilter *iface, REFERENCE_TIME WaitStreamTime)
655 FIXME("(%p)->(%s): Stub!\n", iface, wine_dbgstr_longlong(WaitStreamTime));
657 return E_NOTIMPL;
660 static HRESULT WINAPI filter_Flush(IMediaStreamFilter *iface, BOOL bCancelEOS)
662 FIXME("(%p)->(%d): Stub!\n", iface, bCancelEOS);
664 return E_NOTIMPL;
667 static HRESULT WINAPI filter_EndOfStream(IMediaStreamFilter *iface)
669 FIXME("(%p)->(): Stub!\n", iface);
671 return E_NOTIMPL;
674 static const IMediaStreamFilterVtbl filter_vtbl =
676 filter_QueryInterface,
677 filter_AddRef,
678 filter_Release,
679 filter_GetClassID,
680 filter_Stop,
681 filter_Pause,
682 filter_Run,
683 filter_GetState,
684 filter_SetSyncSource,
685 filter_GetSyncSource,
686 filter_EnumPins,
687 filter_FindPin,
688 filter_QueryFilterInfo,
689 filter_JoinFilterGraph,
690 filter_QueryVendorInfo,
691 filter_AddMediaStream,
692 filter_GetMediaStream,
693 filter_EnumMediaStreams,
694 filter_SupportSeeking,
695 filter_ReferenceTimeToStreamTime,
696 filter_GetCurrentStreamTime,
697 filter_WaitUntil,
698 filter_Flush,
699 filter_EndOfStream
702 static inline struct filter *impl_from_IMediaSeeking(IMediaSeeking *iface)
704 return CONTAINING_RECORD(iface, struct filter, IMediaSeeking_iface);
707 static HRESULT WINAPI filter_seeking_QueryInterface(IMediaSeeking *iface, REFIID iid, void **out)
709 struct filter *filter = impl_from_IMediaSeeking(iface);
710 return IMediaStreamFilter_QueryInterface(&filter->IMediaStreamFilter_iface, iid, out);
713 static ULONG WINAPI filter_seeking_AddRef(IMediaSeeking *iface)
715 struct filter *filter = impl_from_IMediaSeeking(iface);
716 return IMediaStreamFilter_AddRef(&filter->IMediaStreamFilter_iface);
719 static ULONG WINAPI filter_seeking_Release(IMediaSeeking *iface)
721 struct filter *filter = impl_from_IMediaSeeking(iface);
722 return IMediaStreamFilter_Release(&filter->IMediaStreamFilter_iface);
725 static HRESULT WINAPI filter_seeking_GetCapabilities(IMediaSeeking *iface, DWORD *capabilities)
727 FIXME("iface %p, capabilities %p, stub!\n", iface, capabilities);
729 return E_NOTIMPL;
732 static HRESULT WINAPI filter_seeking_CheckCapabilities(IMediaSeeking *iface, DWORD *capabilities)
734 FIXME("iface %p, capabilities %p, stub!\n", iface, capabilities);
736 return E_NOTIMPL;
739 static HRESULT WINAPI filter_seeking_IsFormatSupported(IMediaSeeking *iface, const GUID *format)
741 FIXME("iface %p, format %s, stub!\n", iface, debugstr_guid(format));
743 return E_NOTIMPL;
746 static HRESULT WINAPI filter_seeking_QueryPreferredFormat(IMediaSeeking *iface, GUID *format)
748 FIXME("iface %p, format %p, stub!\n", iface, format);
750 return E_NOTIMPL;
753 static HRESULT WINAPI filter_seeking_GetTimeFormat(IMediaSeeking *iface, GUID *format)
755 FIXME("iface %p, format %p, stub!\n", iface, format);
757 return E_NOTIMPL;
760 static HRESULT WINAPI filter_seeking_IsUsingTimeFormat(IMediaSeeking *iface, const GUID *format)
762 FIXME("iface %p, format %s, stub!\n", iface, debugstr_guid(format));
764 return E_NOTIMPL;
767 static HRESULT WINAPI filter_seeking_SetTimeFormat(IMediaSeeking *iface, const GUID *format)
769 FIXME("iface %p, format %s, stub!\n", iface, debugstr_guid(format));
771 return E_NOTIMPL;
774 static HRESULT WINAPI filter_seeking_GetDuration(IMediaSeeking *iface, LONGLONG *duration)
776 struct filter *filter = impl_from_IMediaSeeking(iface);
777 IMediaSeeking *seeking;
778 HRESULT hr;
780 TRACE("filter %p, duration %p.\n", filter, duration);
782 EnterCriticalSection(&filter->cs);
784 if (!(seeking = get_seeking(filter->seekable_stream)))
786 LeaveCriticalSection(&filter->cs);
787 return E_NOTIMPL;
789 hr = IMediaSeeking_GetDuration(seeking, duration);
790 IMediaSeeking_Release(seeking);
792 LeaveCriticalSection(&filter->cs);
793 return hr;
796 static HRESULT WINAPI filter_seeking_GetStopPosition(IMediaSeeking *iface, LONGLONG *stop)
798 struct filter *filter = impl_from_IMediaSeeking(iface);
799 IMediaSeeking *seeking;
800 HRESULT hr;
802 TRACE("filter %p, stop %p.\n", filter, stop);
804 EnterCriticalSection(&filter->cs);
806 if (!(seeking = get_seeking(filter->seekable_stream)))
808 LeaveCriticalSection(&filter->cs);
809 return E_NOTIMPL;
811 hr = IMediaSeeking_GetStopPosition(seeking, stop);
812 IMediaSeeking_Release(seeking);
814 LeaveCriticalSection(&filter->cs);
815 return hr;
818 static HRESULT WINAPI filter_seeking_GetCurrentPosition(IMediaSeeking *iface, LONGLONG *current)
820 FIXME("iface %p, current %p, stub!\n", iface, current);
822 return E_NOTIMPL;
825 static HRESULT WINAPI filter_seeking_ConvertTimeFormat(IMediaSeeking *iface, LONGLONG *target,
826 const GUID *target_format, LONGLONG source, const GUID *source_format)
828 FIXME("iface %p, target %p, target_format %s, source 0x%s, source_format %s, stub!\n", iface, target, debugstr_guid(target_format),
829 wine_dbgstr_longlong(source), debugstr_guid(source_format));
831 return E_NOTIMPL;
834 static HRESULT WINAPI filter_seeking_SetPositions(IMediaSeeking *iface, LONGLONG *current_ptr, DWORD current_flags,
835 LONGLONG *stop_ptr, DWORD stop_flags)
837 struct filter *filter = impl_from_IMediaSeeking(iface);
838 IMediaSeeking *seeking;
839 HRESULT hr;
841 TRACE("iface %p, current %s, current_flags %#x, stop %s, stop_flags %#x.\n", iface,
842 current_ptr ? wine_dbgstr_longlong(*current_ptr) : "<null>", current_flags,
843 stop_ptr ? wine_dbgstr_longlong(*stop_ptr): "<null>", stop_flags);
845 EnterCriticalSection(&filter->cs);
847 seeking = get_seeking(filter->seekable_stream);
849 if (!seeking)
851 LeaveCriticalSection(&filter->cs);
852 return E_NOTIMPL;
855 hr = IMediaSeeking_SetPositions(seeking, current_ptr, current_flags, stop_ptr, stop_flags);
857 IMediaSeeking_Release(seeking);
859 LeaveCriticalSection(&filter->cs);
861 return hr;
864 static HRESULT WINAPI filter_seeking_GetPositions(IMediaSeeking *iface, LONGLONG *current, LONGLONG *stop)
866 FIXME("iface %p, current %p, stop %p, stub!\n", iface, current, stop);
868 return E_NOTIMPL;
871 static HRESULT WINAPI filter_seeking_GetAvailable(IMediaSeeking *iface, LONGLONG *earliest, LONGLONG *latest)
873 FIXME("iface %p, earliest %p, latest %p, stub!\n", iface, earliest, latest);
875 return E_NOTIMPL;
878 static HRESULT WINAPI filter_seeking_SetRate(IMediaSeeking *iface, double rate)
880 FIXME("iface %p, rate %f, stub!\n", iface, rate);
882 return E_NOTIMPL;
885 static HRESULT WINAPI filter_seeking_GetRate(IMediaSeeking *iface, double *rate)
887 FIXME("iface %p, rate %p, stub!\n", iface, rate);
889 return E_NOTIMPL;
892 static HRESULT WINAPI filter_seeking_GetPreroll(IMediaSeeking *iface, LONGLONG *preroll)
894 FIXME("iface %p, preroll %p, stub!\n", iface, preroll);
896 return E_NOTIMPL;
899 static const IMediaSeekingVtbl filter_seeking_vtbl =
901 filter_seeking_QueryInterface,
902 filter_seeking_AddRef,
903 filter_seeking_Release,
904 filter_seeking_GetCapabilities,
905 filter_seeking_CheckCapabilities,
906 filter_seeking_IsFormatSupported,
907 filter_seeking_QueryPreferredFormat,
908 filter_seeking_GetTimeFormat,
909 filter_seeking_IsUsingTimeFormat,
910 filter_seeking_SetTimeFormat,
911 filter_seeking_GetDuration,
912 filter_seeking_GetStopPosition,
913 filter_seeking_GetCurrentPosition,
914 filter_seeking_ConvertTimeFormat,
915 filter_seeking_SetPositions,
916 filter_seeking_GetPositions,
917 filter_seeking_GetAvailable,
918 filter_seeking_SetRate,
919 filter_seeking_GetRate,
920 filter_seeking_GetPreroll,
923 HRESULT filter_create(IUnknown *outer, void **out)
925 struct filter *object;
927 TRACE("outer %p, out %p.\n", outer, out);
929 if (outer)
930 return CLASS_E_NOAGGREGATION;
932 if (!(object = heap_alloc_zero(sizeof(*object))))
933 return E_OUTOFMEMORY;
935 object->IMediaStreamFilter_iface.lpVtbl = &filter_vtbl;
936 object->IMediaSeeking_iface.lpVtbl = &filter_seeking_vtbl;
937 object->refcount = 1;
938 InitializeCriticalSection(&object->cs);
939 object->cs.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": MediaStreamFilter.cs");
941 TRACE("Created media stream filter %p.\n", object);
942 *out = &object->IMediaStreamFilter_iface;
943 return S_OK;