mf/evr: Post sink marker events.
[wine.git] / dlls / mf / evr.c
blob64489ac4c582fb93aa85d6c92ac48bba22bb4616
1 /*
2 * Copyright 2020 Nikolay Sivov for CodeWeavers
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19 #define COBJMACROS
21 #include "mf_private.h"
22 #include "uuids.h"
23 #include "evr.h"
24 #include "evcode.h"
25 #include "d3d9.h"
26 #include "initguid.h"
27 #include "dxva2api.h"
29 WINE_DEFAULT_DEBUG_CHANNEL(mfplat);
31 enum video_renderer_flags
33 EVR_SHUT_DOWN = 0x1,
34 EVR_INIT_SERVICES = 0x2, /* Currently in InitServices() call. */
35 EVR_MIXER_INITED_SERVICES = 0x4,
36 EVR_PRESENTER_INITED_SERVICES = 0x8,
39 enum video_renderer_state
41 EVR_STATE_STOPPED = 0,
42 EVR_STATE_RUNNING,
43 EVR_STATE_PAUSED,
46 enum video_stream_flags
48 EVR_STREAM_PREROLLING = 0x1,
49 EVR_STREAM_PREROLLED = 0x2,
50 EVR_STREAM_SAMPLE_NEEDED = 0x4,
51 EVR_STREAM_STARTED = 0x8,
54 struct video_renderer;
56 struct video_stream
58 IMFStreamSink IMFStreamSink_iface;
59 IMFMediaTypeHandler IMFMediaTypeHandler_iface;
60 IMFGetService IMFGetService_iface;
61 IMFAttributes IMFAttributes_iface;
62 LONG refcount;
63 unsigned int id;
64 unsigned int flags;
65 struct video_renderer *parent;
66 IMFMediaEventQueue *event_queue;
67 IMFVideoSampleAllocator *allocator;
68 IMFAttributes *attributes;
69 CRITICAL_SECTION cs;
72 struct video_renderer
74 IMFMediaSink IMFMediaSink_iface;
75 IMFMediaSinkPreroll IMFMediaSinkPreroll_iface;
76 IMFVideoRenderer IMFVideoRenderer_iface;
77 IMFClockStateSink IMFClockStateSink_iface;
78 IMFMediaEventGenerator IMFMediaEventGenerator_iface;
79 IMFGetService IMFGetService_iface;
80 IMFTopologyServiceLookup IMFTopologyServiceLookup_iface;
81 IMediaEventSink IMediaEventSink_iface;
82 IMFAttributes IMFAttributes_iface;
83 IMFQualityAdvise IMFQualityAdvise_iface;
84 IMFRateSupport IMFRateSupport_iface;
85 LONG refcount;
87 IMFMediaEventQueue *event_queue;
88 IMFAttributes *attributes;
89 IMFPresentationClock *clock;
91 IMFTransform *mixer;
92 IMFVideoPresenter *presenter;
93 HWND window;
94 IUnknown *device_manager;
95 unsigned int flags;
96 unsigned int state;
98 struct video_stream **streams;
99 size_t stream_size;
100 size_t stream_count;
102 CRITICAL_SECTION cs;
105 static struct video_renderer *impl_from_IMFMediaSink(IMFMediaSink *iface)
107 return CONTAINING_RECORD(iface, struct video_renderer, IMFMediaSink_iface);
110 static struct video_renderer *impl_from_IMFMediaSinkPreroll(IMFMediaSinkPreroll *iface)
112 return CONTAINING_RECORD(iface, struct video_renderer, IMFMediaSinkPreroll_iface);
115 static struct video_renderer *impl_from_IMFVideoRenderer(IMFVideoRenderer *iface)
117 return CONTAINING_RECORD(iface, struct video_renderer, IMFVideoRenderer_iface);
120 static struct video_renderer *impl_from_IMFMediaEventGenerator(IMFMediaEventGenerator *iface)
122 return CONTAINING_RECORD(iface, struct video_renderer, IMFMediaEventGenerator_iface);
125 static struct video_renderer *impl_from_IMFClockStateSink(IMFClockStateSink *iface)
127 return CONTAINING_RECORD(iface, struct video_renderer, IMFClockStateSink_iface);
130 static struct video_renderer *impl_from_IMFGetService(IMFGetService *iface)
132 return CONTAINING_RECORD(iface, struct video_renderer, IMFGetService_iface);
135 static struct video_renderer *impl_from_IMFTopologyServiceLookup(IMFTopologyServiceLookup *iface)
137 return CONTAINING_RECORD(iface, struct video_renderer, IMFTopologyServiceLookup_iface);
140 static struct video_renderer *impl_from_IMediaEventSink(IMediaEventSink *iface)
142 return CONTAINING_RECORD(iface, struct video_renderer, IMediaEventSink_iface);
145 static struct video_renderer *impl_from_IMFAttributes(IMFAttributes *iface)
147 return CONTAINING_RECORD(iface, struct video_renderer, IMFAttributes_iface);
150 static struct video_renderer *impl_from_IMFQualityAdvise(IMFQualityAdvise *iface)
152 return CONTAINING_RECORD(iface, struct video_renderer, IMFQualityAdvise_iface);
155 static struct video_renderer *impl_from_IMFRateSupport(IMFRateSupport *iface)
157 return CONTAINING_RECORD(iface, struct video_renderer, IMFRateSupport_iface);
160 static struct video_stream *impl_from_IMFStreamSink(IMFStreamSink *iface)
162 return CONTAINING_RECORD(iface, struct video_stream, IMFStreamSink_iface);
165 static struct video_stream *impl_from_IMFMediaTypeHandler(IMFMediaTypeHandler *iface)
167 return CONTAINING_RECORD(iface, struct video_stream, IMFMediaTypeHandler_iface);
170 static struct video_stream *impl_from_stream_IMFGetService(IMFGetService *iface)
172 return CONTAINING_RECORD(iface, struct video_stream, IMFGetService_iface);
175 static struct video_stream *impl_from_stream_IMFAttributes(IMFAttributes *iface)
177 return CONTAINING_RECORD(iface, struct video_stream, IMFAttributes_iface);
180 static HRESULT video_renderer_init_presenter_services(struct video_renderer *renderer)
182 IMFTopologyServiceLookupClient *lookup_client;
183 HRESULT hr;
185 if (SUCCEEDED(hr = IMFVideoPresenter_QueryInterface(renderer->presenter, &IID_IMFTopologyServiceLookupClient,
186 (void **)&lookup_client)))
188 renderer->flags |= EVR_INIT_SERVICES;
189 if (SUCCEEDED(hr = IMFTopologyServiceLookupClient_InitServicePointers(lookup_client,
190 &renderer->IMFTopologyServiceLookup_iface)))
192 renderer->flags |= EVR_PRESENTER_INITED_SERVICES;
194 renderer->flags &= ~EVR_INIT_SERVICES;
195 IMFTopologyServiceLookupClient_Release(lookup_client);
198 return hr;
201 static void video_renderer_release_presenter_services(struct video_renderer *renderer)
203 IMFTopologyServiceLookupClient *lookup_client;
205 if (renderer->flags & EVR_PRESENTER_INITED_SERVICES && SUCCEEDED(IMFVideoPresenter_QueryInterface(renderer->presenter,
206 &IID_IMFTopologyServiceLookupClient, (void **)&lookup_client)))
208 IMFTopologyServiceLookupClient_ReleaseServicePointers(lookup_client);
209 IMFTopologyServiceLookupClient_Release(lookup_client);
210 renderer->flags &= ~EVR_PRESENTER_INITED_SERVICES;
214 static void video_renderer_release_services(struct video_renderer *renderer)
216 IMFTopologyServiceLookupClient *lookup_client;
218 if (renderer->flags & EVR_MIXER_INITED_SERVICES && SUCCEEDED(IMFTransform_QueryInterface(renderer->mixer,
219 &IID_IMFTopologyServiceLookupClient, (void **)&lookup_client)))
221 IMFTopologyServiceLookupClient_ReleaseServicePointers(lookup_client);
222 IMFTopologyServiceLookupClient_Release(lookup_client);
223 renderer->flags &= ~EVR_MIXER_INITED_SERVICES;
226 video_renderer_release_presenter_services(renderer);
229 static HRESULT WINAPI video_stream_sink_QueryInterface(IMFStreamSink *iface, REFIID riid, void **obj)
231 struct video_stream *stream = impl_from_IMFStreamSink(iface);
233 TRACE("%p, %s, %p.\n", iface, debugstr_guid(riid), obj);
235 if (IsEqualIID(riid, &IID_IMFStreamSink) ||
236 IsEqualIID(riid, &IID_IMFMediaEventGenerator) ||
237 IsEqualIID(riid, &IID_IUnknown))
239 *obj = iface;
241 else if (IsEqualIID(riid, &IID_IMFMediaTypeHandler))
243 *obj = &stream->IMFMediaTypeHandler_iface;
245 else if (IsEqualIID(riid, &IID_IMFGetService))
247 *obj = &stream->IMFGetService_iface;
249 else if (IsEqualIID(riid, &IID_IMFAttributes))
251 *obj = &stream->IMFAttributes_iface;
253 else
255 WARN("Unsupported interface %s.\n", debugstr_guid(riid));
256 *obj = NULL;
257 return E_NOINTERFACE;
260 IUnknown_AddRef((IUnknown *)*obj);
262 return S_OK;
265 static ULONG WINAPI video_stream_sink_AddRef(IMFStreamSink *iface)
267 struct video_stream *stream = impl_from_IMFStreamSink(iface);
268 ULONG refcount = InterlockedIncrement(&stream->refcount);
270 TRACE("%p, refcount %u.\n", iface, refcount);
272 return refcount;
275 static ULONG WINAPI video_stream_sink_Release(IMFStreamSink *iface)
277 struct video_stream *stream = impl_from_IMFStreamSink(iface);
278 ULONG refcount = InterlockedDecrement(&stream->refcount);
280 if (!refcount)
282 if (stream->event_queue)
283 IMFMediaEventQueue_Release(stream->event_queue);
284 if (stream->attributes)
285 IMFAttributes_Release(stream->attributes);
286 if (stream->allocator)
287 IMFVideoSampleAllocator_Release(stream->allocator);
288 DeleteCriticalSection(&stream->cs);
289 heap_free(stream);
292 return refcount;
295 static HRESULT WINAPI video_stream_sink_GetEvent(IMFStreamSink *iface, DWORD flags, IMFMediaEvent **event)
297 struct video_stream *stream = impl_from_IMFStreamSink(iface);
299 TRACE("%p, %#x, %p.\n", iface, flags, event);
301 return IMFMediaEventQueue_GetEvent(stream->event_queue, flags, event);
304 static HRESULT WINAPI video_stream_sink_BeginGetEvent(IMFStreamSink *iface, IMFAsyncCallback *callback, IUnknown *state)
306 struct video_stream *stream = impl_from_IMFStreamSink(iface);
308 TRACE("%p, %p, %p.\n", iface, callback, state);
310 return IMFMediaEventQueue_BeginGetEvent(stream->event_queue, callback, state);
313 static HRESULT WINAPI video_stream_sink_EndGetEvent(IMFStreamSink *iface, IMFAsyncResult *result,
314 IMFMediaEvent **event)
316 struct video_stream *stream = impl_from_IMFStreamSink(iface);
318 TRACE("%p, %p, %p.\n", iface, result, event);
320 return IMFMediaEventQueue_EndGetEvent(stream->event_queue, result, event);
323 static HRESULT WINAPI video_stream_sink_QueueEvent(IMFStreamSink *iface, MediaEventType event_type,
324 REFGUID ext_type, HRESULT hr, const PROPVARIANT *value)
326 struct video_stream *stream = impl_from_IMFStreamSink(iface);
328 TRACE("%p, %d, %s, %#x, %p.\n", iface, event_type, debugstr_guid(ext_type), hr, value);
330 return IMFMediaEventQueue_QueueEventParamVar(stream->event_queue, event_type, ext_type, hr, value);
333 static HRESULT WINAPI video_stream_sink_GetMediaSink(IMFStreamSink *iface, IMFMediaSink **sink)
335 struct video_stream *stream = impl_from_IMFStreamSink(iface);
336 HRESULT hr = S_OK;
338 TRACE("%p, %p.\n", iface, sink);
340 EnterCriticalSection(&stream->cs);
341 if (!stream->parent)
342 hr = MF_E_STREAMSINK_REMOVED;
343 else if (!sink)
344 hr = E_POINTER;
345 else
347 *sink = &stream->parent->IMFMediaSink_iface;
348 IMFMediaSink_AddRef(*sink);
350 LeaveCriticalSection(&stream->cs);
352 return hr;
355 static HRESULT WINAPI video_stream_sink_GetIdentifier(IMFStreamSink *iface, DWORD *id)
357 struct video_stream *stream = impl_from_IMFStreamSink(iface);
359 TRACE("%p, %p.\n", iface, id);
361 if (!stream->parent)
362 return MF_E_STREAMSINK_REMOVED;
364 if (!id)
365 return E_INVALIDARG;
367 *id = stream->id;
369 return S_OK;
372 static HRESULT WINAPI video_stream_sink_GetMediaTypeHandler(IMFStreamSink *iface, IMFMediaTypeHandler **handler)
374 struct video_stream *stream = impl_from_IMFStreamSink(iface);
376 TRACE("%p, %p.\n", iface, handler);
378 if (!handler)
379 return E_POINTER;
381 if (!stream->parent)
382 return MF_E_STREAMSINK_REMOVED;
384 *handler = &stream->IMFMediaTypeHandler_iface;
385 IMFMediaTypeHandler_AddRef(*handler);
387 return S_OK;
390 static HRESULT WINAPI video_stream_sink_ProcessSample(IMFStreamSink *iface, IMFSample *sample)
392 struct video_stream *stream = impl_from_IMFStreamSink(iface);
393 LONGLONG timestamp;
394 HRESULT hr = S_OK;
396 TRACE("%p, %p.\n", iface, sample);
398 EnterCriticalSection(&stream->cs);
400 if (!stream->parent)
401 hr = MF_E_STREAMSINK_REMOVED;
402 else if (!stream->parent->clock)
403 hr = MF_E_NO_CLOCK;
404 else if (FAILED(hr = IMFSample_GetSampleTime(sample, &timestamp)))
406 WARN("No sample timestamp, hr %#x.\n", hr);
408 else if (stream->parent->state == EVR_STATE_RUNNING || stream->flags & EVR_STREAM_PREROLLING)
410 if (!(stream->flags & EVR_STREAM_STARTED))
412 IMFTransform_ProcessMessage(stream->parent->mixer, MFT_MESSAGE_NOTIFY_START_OF_STREAM, stream->id);
413 stream->flags |= EVR_STREAM_STARTED;
416 if (SUCCEEDED(IMFTransform_ProcessInput(stream->parent->mixer, stream->id, sample, 0)))
417 IMFVideoPresenter_ProcessMessage(stream->parent->presenter, MFVP_MESSAGE_PROCESSINPUTNOTIFY, 0);
419 if (stream->flags & EVR_STREAM_PREROLLING)
421 IMFMediaEventQueue_QueueEventParamVar(stream->event_queue, MEStreamSinkPrerolled, &GUID_NULL, S_OK, NULL);
422 stream->flags &= ~EVR_STREAM_PREROLLING;
423 stream->flags |= EVR_STREAM_PREROLLED;
427 LeaveCriticalSection(&stream->cs);
429 return hr;
432 static void video_stream_end_of_stream(struct video_stream *stream)
434 if (!(stream->flags & EVR_STREAM_STARTED))
435 return;
437 IMFTransform_ProcessMessage(stream->parent->mixer, MFT_MESSAGE_NOTIFY_END_OF_STREAM, stream->id);
438 stream->flags &= ~EVR_STREAM_STARTED;
441 static HRESULT WINAPI video_stream_sink_PlaceMarker(IMFStreamSink *iface, MFSTREAMSINK_MARKER_TYPE marker_type,
442 const PROPVARIANT *marker_value, const PROPVARIANT *context)
444 struct video_stream *stream = impl_from_IMFStreamSink(iface);
445 HRESULT hr = S_OK;
447 TRACE("%p, %d, %p, %p.\n", iface, marker_type, marker_value, context);
449 EnterCriticalSection(&stream->cs);
450 if (!stream->parent)
451 hr = MF_E_STREAMSINK_REMOVED;
452 else
454 if (marker_type == MFSTREAMSINK_MARKER_ENDOFSEGMENT)
455 video_stream_end_of_stream(stream);
456 IMFMediaEventQueue_QueueEventParamVar(stream->event_queue, MEStreamSinkMarker, &GUID_NULL, S_OK, context);
458 LeaveCriticalSection(&stream->cs);
460 return hr;
463 static HRESULT WINAPI video_stream_sink_Flush(IMFStreamSink *iface)
465 FIXME("%p.\n", iface);
467 return E_NOTIMPL;
470 static const IMFStreamSinkVtbl video_stream_sink_vtbl =
472 video_stream_sink_QueryInterface,
473 video_stream_sink_AddRef,
474 video_stream_sink_Release,
475 video_stream_sink_GetEvent,
476 video_stream_sink_BeginGetEvent,
477 video_stream_sink_EndGetEvent,
478 video_stream_sink_QueueEvent,
479 video_stream_sink_GetMediaSink,
480 video_stream_sink_GetIdentifier,
481 video_stream_sink_GetMediaTypeHandler,
482 video_stream_sink_ProcessSample,
483 video_stream_sink_PlaceMarker,
484 video_stream_sink_Flush,
487 static HRESULT WINAPI video_stream_typehandler_QueryInterface(IMFMediaTypeHandler *iface, REFIID riid,
488 void **obj)
490 struct video_stream *stream = impl_from_IMFMediaTypeHandler(iface);
491 return IMFStreamSink_QueryInterface(&stream->IMFStreamSink_iface, riid, obj);
494 static ULONG WINAPI video_stream_typehandler_AddRef(IMFMediaTypeHandler *iface)
496 struct video_stream *stream = impl_from_IMFMediaTypeHandler(iface);
497 return IMFStreamSink_AddRef(&stream->IMFStreamSink_iface);
500 static ULONG WINAPI video_stream_typehandler_Release(IMFMediaTypeHandler *iface)
502 struct video_stream *stream = impl_from_IMFMediaTypeHandler(iface);
503 return IMFStreamSink_Release(&stream->IMFStreamSink_iface);
506 static HRESULT WINAPI video_stream_typehandler_IsMediaTypeSupported(IMFMediaTypeHandler *iface,
507 IMFMediaType *in_type, IMFMediaType **out_type)
509 struct video_stream *stream = impl_from_IMFMediaTypeHandler(iface);
510 HRESULT hr;
512 TRACE("%p, %p, %p.\n", iface, in_type, out_type);
514 if (!in_type)
515 return E_POINTER;
517 if (!stream->parent)
518 return MF_E_INVALIDMEDIATYPE;
520 if (SUCCEEDED(hr = IMFTransform_SetInputType(stream->parent->mixer, stream->id, in_type,
521 MFT_SET_TYPE_TEST_ONLY)))
523 if (out_type) *out_type = NULL;
526 return hr;
529 static HRESULT WINAPI video_stream_typehandler_GetMediaTypeCount(IMFMediaTypeHandler *iface, DWORD *count)
531 TRACE("%p, %p.\n", iface, count);
533 if (!count)
534 return E_POINTER;
536 *count = 0;
538 return S_OK;
541 static HRESULT WINAPI video_stream_typehandler_GetMediaTypeByIndex(IMFMediaTypeHandler *iface, DWORD index,
542 IMFMediaType **type)
544 TRACE("%p, %u, %p.\n", iface, index, type);
546 return MF_E_NO_MORE_TYPES;
549 static HRESULT WINAPI video_stream_typehandler_SetCurrentMediaType(IMFMediaTypeHandler *iface, IMFMediaType *type)
551 struct video_stream *stream = impl_from_IMFMediaTypeHandler(iface);
552 HRESULT hr;
554 TRACE("%p, %p.\n", iface, type);
556 if (!type)
557 return E_POINTER;
559 if (!stream->parent)
560 return MF_E_STREAMSINK_REMOVED;
562 hr = IMFTransform_SetInputType(stream->parent->mixer, stream->id, type, 0);
563 if (SUCCEEDED(hr) && !stream->id)
564 hr = IMFVideoPresenter_ProcessMessage(stream->parent->presenter, MFVP_MESSAGE_INVALIDATEMEDIATYPE, 0);
566 return hr;
569 static HRESULT WINAPI video_stream_typehandler_GetCurrentMediaType(IMFMediaTypeHandler *iface, IMFMediaType **type)
571 struct video_stream *stream = impl_from_IMFMediaTypeHandler(iface);
573 TRACE("%p, %p.\n", iface, type);
575 if (!type)
576 return E_POINTER;
578 if (!stream->parent)
579 return MF_E_STREAMSINK_REMOVED;
581 return IMFTransform_GetInputCurrentType(stream->parent->mixer, stream->id, type);
584 static HRESULT WINAPI video_stream_typehandler_GetMajorType(IMFMediaTypeHandler *iface, GUID *type)
586 struct video_stream *stream = impl_from_IMFMediaTypeHandler(iface);
588 TRACE("%p, %p.\n", iface, type);
590 if (!stream->parent)
591 return MF_E_STREAMSINK_REMOVED;
593 if (!type)
594 return E_POINTER;
596 memcpy(type, &MFMediaType_Video, sizeof(*type));
597 return S_OK;
600 static const IMFMediaTypeHandlerVtbl video_stream_type_handler_vtbl =
602 video_stream_typehandler_QueryInterface,
603 video_stream_typehandler_AddRef,
604 video_stream_typehandler_Release,
605 video_stream_typehandler_IsMediaTypeSupported,
606 video_stream_typehandler_GetMediaTypeCount,
607 video_stream_typehandler_GetMediaTypeByIndex,
608 video_stream_typehandler_SetCurrentMediaType,
609 video_stream_typehandler_GetCurrentMediaType,
610 video_stream_typehandler_GetMajorType,
613 static HRESULT WINAPI video_stream_get_service_QueryInterface(IMFGetService *iface, REFIID riid, void **obj)
615 struct video_stream *stream = impl_from_stream_IMFGetService(iface);
616 return IMFStreamSink_QueryInterface(&stream->IMFStreamSink_iface, riid, obj);
619 static ULONG WINAPI video_stream_get_service_AddRef(IMFGetService *iface)
621 struct video_stream *stream = impl_from_stream_IMFGetService(iface);
622 return IMFStreamSink_AddRef(&stream->IMFStreamSink_iface);
625 static ULONG WINAPI video_stream_get_service_Release(IMFGetService *iface)
627 struct video_stream *stream = impl_from_stream_IMFGetService(iface);
628 return IMFStreamSink_Release(&stream->IMFStreamSink_iface);
631 static HRESULT WINAPI video_stream_get_service(struct video_stream *stream, REFGUID service, REFIID riid, void **obj)
633 HRESULT hr = S_OK;
635 if (IsEqualGUID(service, &MR_VIDEO_ACCELERATION_SERVICE))
637 if (IsEqualIID(riid, &IID_IMFVideoSampleAllocator))
639 if (!stream->allocator)
641 hr = MFCreateVideoSampleAllocator(&IID_IMFVideoSampleAllocator, (void **)&stream->allocator);
642 if (SUCCEEDED(hr))
643 hr = IMFVideoSampleAllocator_SetDirectXManager(stream->allocator, stream->parent->device_manager);
645 if (SUCCEEDED(hr))
646 hr = IMFVideoSampleAllocator_QueryInterface(stream->allocator, riid, obj);
648 return hr;
650 else if (IsEqualIID(riid, &IID_IDirect3DDeviceManager9) && stream->parent->device_manager)
652 return IUnknown_QueryInterface(stream->parent->device_manager, riid, obj);
655 return E_NOINTERFACE;
658 FIXME("Unsupported service %s.\n", debugstr_guid(service));
660 return E_NOTIMPL;
663 static HRESULT WINAPI video_stream_get_service_GetService(IMFGetService *iface, REFGUID service, REFIID riid, void **obj)
665 struct video_stream *stream = impl_from_stream_IMFGetService(iface);
666 HRESULT hr;
668 TRACE("%p, %s, %s, %p.\n", iface, debugstr_guid(service), debugstr_guid(riid), obj);
670 EnterCriticalSection(&stream->cs);
671 if (!stream->parent)
672 hr = MF_E_STREAMSINK_REMOVED;
673 else
674 hr = video_stream_get_service(stream, service, riid, obj);
675 LeaveCriticalSection(&stream->cs);
677 return hr;
680 static const IMFGetServiceVtbl video_stream_get_service_vtbl =
682 video_stream_get_service_QueryInterface,
683 video_stream_get_service_AddRef,
684 video_stream_get_service_Release,
685 video_stream_get_service_GetService,
688 static HRESULT WINAPI video_stream_attributes_QueryInterface(IMFAttributes *iface, REFIID riid, void **obj)
690 struct video_stream *stream = impl_from_stream_IMFAttributes(iface);
691 return IMFStreamSink_QueryInterface(&stream->IMFStreamSink_iface, riid, obj);
694 static ULONG WINAPI video_stream_attributes_AddRef(IMFAttributes *iface)
696 struct video_stream *stream = impl_from_stream_IMFAttributes(iface);
697 return IMFStreamSink_AddRef(&stream->IMFStreamSink_iface);
700 static ULONG WINAPI video_stream_attributes_Release(IMFAttributes *iface)
702 struct video_stream *stream = impl_from_stream_IMFAttributes(iface);
703 return IMFStreamSink_Release(&stream->IMFStreamSink_iface);
706 static HRESULT WINAPI video_stream_attributes_GetItem(IMFAttributes *iface, REFGUID key, PROPVARIANT *value)
708 struct video_stream *stream = impl_from_stream_IMFAttributes(iface);
710 TRACE("%p, %s, %p.\n", iface, debugstr_guid(key), value);
712 return IMFAttributes_GetItem(stream->attributes, key, value);
715 static HRESULT WINAPI video_stream_attributes_GetItemType(IMFAttributes *iface, REFGUID key, MF_ATTRIBUTE_TYPE *type)
717 struct video_stream *stream = impl_from_stream_IMFAttributes(iface);
719 TRACE("%p, %s, %p.\n", iface, debugstr_guid(key), type);
721 return IMFAttributes_GetItemType(stream->attributes, key, type);
724 static HRESULT WINAPI video_stream_attributes_CompareItem(IMFAttributes *iface, REFGUID key, REFPROPVARIANT value,
725 BOOL *result)
727 struct video_stream *stream = impl_from_stream_IMFAttributes(iface);
729 TRACE("%p, %s, %p, %p.\n", iface, debugstr_guid(key), value, result);
731 return IMFAttributes_CompareItem(stream->attributes, key, value, result);
734 static HRESULT WINAPI video_stream_attributes_Compare(IMFAttributes *iface, IMFAttributes *theirs,
735 MF_ATTRIBUTES_MATCH_TYPE type, BOOL *result)
737 struct video_stream *stream = impl_from_stream_IMFAttributes(iface);
739 TRACE("%p, %p, %d, %p.\n", iface, theirs, type, result);
741 return IMFAttributes_Compare(stream->attributes, theirs, type, result);
744 static HRESULT WINAPI video_stream_attributes_GetUINT32(IMFAttributes *iface, REFGUID key, UINT32 *value)
746 struct video_stream *stream = impl_from_stream_IMFAttributes(iface);
748 TRACE("%p, %s, %p.\n", iface, debugstr_guid(key), value);
750 return IMFAttributes_GetUINT32(stream->attributes, key, value);
753 static HRESULT WINAPI video_stream_attributes_GetUINT64(IMFAttributes *iface, REFGUID key, UINT64 *value)
755 struct video_stream *stream = impl_from_stream_IMFAttributes(iface);
757 TRACE("%p, %s, %p.\n", iface, debugstr_guid(key), value);
759 return IMFAttributes_GetUINT64(stream->attributes, key, value);
762 static HRESULT WINAPI video_stream_attributes_GetDouble(IMFAttributes *iface, REFGUID key, double *value)
764 struct video_stream *stream = impl_from_stream_IMFAttributes(iface);
766 TRACE("%p, %s, %p.\n", iface, debugstr_guid(key), value);
768 return IMFAttributes_GetDouble(stream->attributes, key, value);
771 static HRESULT WINAPI video_stream_attributes_GetGUID(IMFAttributes *iface, REFGUID key, GUID *value)
773 struct video_stream *stream = impl_from_stream_IMFAttributes(iface);
775 TRACE("%p, %s, %p.\n", iface, debugstr_guid(key), value);
777 return IMFAttributes_GetGUID(stream->attributes, key, value);
780 static HRESULT WINAPI video_stream_attributes_GetStringLength(IMFAttributes *iface, REFGUID key,
781 UINT32 *length)
783 struct video_stream *stream = impl_from_stream_IMFAttributes(iface);
785 TRACE("%p, %s, %p.\n", iface, debugstr_guid(key), length);
787 return IMFAttributes_GetStringLength(stream->attributes, key, length);
790 static HRESULT WINAPI video_stream_attributes_GetString(IMFAttributes *iface, REFGUID key, WCHAR *value,
791 UINT32 size, UINT32 *length)
793 struct video_stream *stream = impl_from_stream_IMFAttributes(iface);
795 TRACE("%p, %s, %p, %u, %p.\n", iface, debugstr_guid(key), value, size, length);
797 return IMFAttributes_GetString(stream->attributes, key, value, size, length);
800 static HRESULT WINAPI video_stream_attributes_GetAllocatedString(IMFAttributes *iface, REFGUID key,
801 WCHAR **value, UINT32 *length)
803 struct video_stream *stream = impl_from_stream_IMFAttributes(iface);
805 TRACE("%p, %s, %p, %p.\n", iface, debugstr_guid(key), value, length);
807 return IMFAttributes_GetAllocatedString(stream->attributes, key, value, length);
810 static HRESULT WINAPI video_stream_attributes_GetBlobSize(IMFAttributes *iface, REFGUID key, UINT32 *size)
812 struct video_stream *stream = impl_from_stream_IMFAttributes(iface);
814 TRACE("%p, %s, %p.\n", iface, debugstr_guid(key), size);
816 return IMFAttributes_GetBlobSize(stream->attributes, key, size);
819 static HRESULT WINAPI video_stream_attributes_GetBlob(IMFAttributes *iface, REFGUID key, UINT8 *buf,
820 UINT32 bufsize, UINT32 *blobsize)
822 struct video_stream *stream = impl_from_stream_IMFAttributes(iface);
824 TRACE("%p, %s, %p, %u, %p.\n", iface, debugstr_guid(key), buf, bufsize, blobsize);
826 return IMFAttributes_GetBlob(stream->attributes, key, buf, bufsize, blobsize);
829 static HRESULT WINAPI video_stream_attributes_GetAllocatedBlob(IMFAttributes *iface, REFGUID key,
830 UINT8 **buf, UINT32 *size)
832 struct video_stream *stream = impl_from_stream_IMFAttributes(iface);
834 TRACE("%p, %s, %p, %p.\n", iface, debugstr_guid(key), buf, size);
836 return IMFAttributes_GetAllocatedBlob(stream->attributes, key, buf, size);
839 static HRESULT WINAPI video_stream_attributes_GetUnknown(IMFAttributes *iface, REFGUID key, REFIID riid, void **out)
841 struct video_stream *stream = impl_from_stream_IMFAttributes(iface);
843 TRACE("%p, %s, %s, %p.\n", iface, debugstr_guid(key), debugstr_guid(riid), out);
845 return IMFAttributes_GetUnknown(stream->attributes, key, riid, out);
848 static HRESULT WINAPI video_stream_attributes_SetItem(IMFAttributes *iface, REFGUID key, REFPROPVARIANT value)
850 struct video_stream *stream = impl_from_stream_IMFAttributes(iface);
852 TRACE("%p, %s, %p.\n", iface, debugstr_guid(key), value);
854 return IMFAttributes_SetItem(stream->attributes, key, value);
857 static HRESULT WINAPI video_stream_attributes_DeleteItem(IMFAttributes *iface, REFGUID key)
859 struct video_stream *stream = impl_from_stream_IMFAttributes(iface);
861 TRACE("%p, %s.\n", iface, debugstr_guid(key));
863 return IMFAttributes_DeleteItem(stream->attributes, key);
866 static HRESULT WINAPI video_stream_attributes_DeleteAllItems(IMFAttributes *iface)
868 struct video_stream *stream = impl_from_stream_IMFAttributes(iface);
870 TRACE("%p.\n", iface);
872 return IMFAttributes_DeleteAllItems(stream->attributes);
875 static HRESULT WINAPI video_stream_attributes_SetUINT32(IMFAttributes *iface, REFGUID key, UINT32 value)
877 struct video_stream *stream = impl_from_stream_IMFAttributes(iface);
879 TRACE("%p, %s, %u.\n", iface, debugstr_guid(key), value);
881 return IMFAttributes_SetUINT32(stream->attributes, key, value);
884 static HRESULT WINAPI video_stream_attributes_SetUINT64(IMFAttributes *iface, REFGUID key, UINT64 value)
886 struct video_stream *stream = impl_from_stream_IMFAttributes(iface);
888 TRACE("%p, %s, %s.\n", iface, debugstr_guid(key), wine_dbgstr_longlong(value));
890 return IMFAttributes_SetUINT64(stream->attributes, key, value);
893 static HRESULT WINAPI video_stream_attributes_SetDouble(IMFAttributes *iface, REFGUID key, double value)
895 struct video_stream *stream = impl_from_stream_IMFAttributes(iface);
897 TRACE("%p, %s, %f.\n", iface, debugstr_guid(key), value);
899 return IMFAttributes_SetDouble(stream->attributes, key, value);
902 static HRESULT WINAPI video_stream_attributes_SetGUID(IMFAttributes *iface, REFGUID key, REFGUID value)
904 struct video_stream *stream = impl_from_stream_IMFAttributes(iface);
906 TRACE("%p, %s, %s.\n", iface, debugstr_guid(key), debugstr_guid(value));
908 return IMFAttributes_SetGUID(stream->attributes, key, value);
911 static HRESULT WINAPI video_stream_attributes_SetString(IMFAttributes *iface, REFGUID key,
912 const WCHAR *value)
914 struct video_stream *stream = impl_from_stream_IMFAttributes(iface);
916 TRACE("%p, %s, %s.\n", iface, debugstr_guid(key), debugstr_w(value));
918 return IMFAttributes_SetString(stream->attributes, key, value);
921 static HRESULT WINAPI video_stream_attributes_SetBlob(IMFAttributes *iface, REFGUID key,
922 const UINT8 *buf, UINT32 size)
924 struct video_stream *stream = impl_from_stream_IMFAttributes(iface);
926 TRACE("%p, %s, %p, %u.\n", iface, debugstr_guid(key), buf, size);
928 return IMFAttributes_SetBlob(stream->attributes, key, buf, size);
931 static HRESULT WINAPI video_stream_attributes_SetUnknown(IMFAttributes *iface, REFGUID key,
932 IUnknown *unknown)
934 struct video_stream *stream = impl_from_stream_IMFAttributes(iface);
936 TRACE("%p, %s, %p.\n", iface, debugstr_guid(key), unknown);
938 return IMFAttributes_SetUnknown(stream->attributes, key, unknown);
941 static HRESULT WINAPI video_stream_attributes_LockStore(IMFAttributes *iface)
943 struct video_stream *stream = impl_from_stream_IMFAttributes(iface);
945 TRACE("%p.\n", iface);
947 return IMFAttributes_LockStore(stream->attributes);
950 static HRESULT WINAPI video_stream_attributes_UnlockStore(IMFAttributes *iface)
952 struct video_stream *stream = impl_from_stream_IMFAttributes(iface);
954 TRACE("%p.\n", iface);
956 return IMFAttributes_UnlockStore(stream->attributes);
959 static HRESULT WINAPI video_stream_attributes_GetCount(IMFAttributes *iface, UINT32 *count)
961 struct video_stream *stream = impl_from_stream_IMFAttributes(iface);
963 TRACE("%p, %p.\n", iface, count);
965 return IMFAttributes_GetCount(stream->attributes, count);
968 static HRESULT WINAPI video_stream_attributes_GetItemByIndex(IMFAttributes *iface, UINT32 index,
969 GUID *key, PROPVARIANT *value)
971 struct video_stream *stream = impl_from_stream_IMFAttributes(iface);
973 TRACE("%p, %u, %p, %p.\n", iface, index, key, value);
975 return IMFAttributes_GetItemByIndex(stream->attributes, index, key, value);
978 static HRESULT WINAPI video_stream_attributes_CopyAllItems(IMFAttributes *iface, IMFAttributes *dest)
980 struct video_stream *stream = impl_from_stream_IMFAttributes(iface);
982 TRACE("%p, %p.\n", iface, dest);
984 return IMFAttributes_CopyAllItems(stream->attributes, dest);
987 static const IMFAttributesVtbl video_stream_attributes_vtbl =
989 video_stream_attributes_QueryInterface,
990 video_stream_attributes_AddRef,
991 video_stream_attributes_Release,
992 video_stream_attributes_GetItem,
993 video_stream_attributes_GetItemType,
994 video_stream_attributes_CompareItem,
995 video_stream_attributes_Compare,
996 video_stream_attributes_GetUINT32,
997 video_stream_attributes_GetUINT64,
998 video_stream_attributes_GetDouble,
999 video_stream_attributes_GetGUID,
1000 video_stream_attributes_GetStringLength,
1001 video_stream_attributes_GetString,
1002 video_stream_attributes_GetAllocatedString,
1003 video_stream_attributes_GetBlobSize,
1004 video_stream_attributes_GetBlob,
1005 video_stream_attributes_GetAllocatedBlob,
1006 video_stream_attributes_GetUnknown,
1007 video_stream_attributes_SetItem,
1008 video_stream_attributes_DeleteItem,
1009 video_stream_attributes_DeleteAllItems,
1010 video_stream_attributes_SetUINT32,
1011 video_stream_attributes_SetUINT64,
1012 video_stream_attributes_SetDouble,
1013 video_stream_attributes_SetGUID,
1014 video_stream_attributes_SetString,
1015 video_stream_attributes_SetBlob,
1016 video_stream_attributes_SetUnknown,
1017 video_stream_attributes_LockStore,
1018 video_stream_attributes_UnlockStore,
1019 video_stream_attributes_GetCount,
1020 video_stream_attributes_GetItemByIndex,
1021 video_stream_attributes_CopyAllItems,
1024 static BOOL video_renderer_is_mixer_d3d_aware(const struct video_renderer *renderer)
1026 IMFAttributes *attributes;
1027 unsigned int value = 0;
1028 BOOL ret;
1030 if (FAILED(IMFTransform_QueryInterface(renderer->mixer, &IID_IMFAttributes, (void **)&attributes)))
1031 return FALSE;
1033 ret = SUCCEEDED(IMFAttributes_GetUINT32(attributes, &MF_SA_D3D_AWARE, &value)) && value;
1034 IMFAttributes_Release(attributes);
1035 return ret;
1038 static HRESULT video_renderer_stream_create(struct video_renderer *renderer, unsigned int id,
1039 struct video_stream **ret)
1041 struct video_stream *stream;
1042 IMFAttributes *attributes;
1043 unsigned int value;
1044 HRESULT hr;
1046 if (!(stream = heap_alloc_zero(sizeof(*stream))))
1047 return E_OUTOFMEMORY;
1049 stream->IMFStreamSink_iface.lpVtbl = &video_stream_sink_vtbl;
1050 stream->IMFMediaTypeHandler_iface.lpVtbl = &video_stream_type_handler_vtbl;
1051 stream->IMFGetService_iface.lpVtbl = &video_stream_get_service_vtbl;
1052 stream->IMFAttributes_iface.lpVtbl = &video_stream_attributes_vtbl;
1053 stream->refcount = 1;
1054 InitializeCriticalSection(&stream->cs);
1056 if (FAILED(hr = MFCreateEventQueue(&stream->event_queue)))
1057 goto failed;
1059 if (FAILED(hr = MFCreateAttributes(&stream->attributes, 0)))
1060 goto failed;
1062 stream->parent = renderer;
1063 IMFMediaSink_AddRef(&stream->parent->IMFMediaSink_iface);
1064 stream->id = id;
1066 if (video_renderer_is_mixer_d3d_aware(renderer))
1067 IMFAttributes_SetUINT32(stream->attributes, &MF_SA_D3D_AWARE, 1);
1069 if (SUCCEEDED(IMFTransform_GetInputStreamAttributes(renderer->mixer, id, &attributes)))
1071 if (SUCCEEDED(IMFAttributes_GetUINT32(attributes, &MF_SA_REQUIRED_SAMPLE_COUNT, &value)))
1072 IMFAttributes_SetUINT32(stream->attributes, &MF_SA_REQUIRED_SAMPLE_COUNT, value);
1073 IMFAttributes_Release(attributes);
1076 *ret = stream;
1078 return S_OK;
1080 failed:
1082 IMFStreamSink_Release(&stream->IMFStreamSink_iface);
1084 return hr;
1087 static HRESULT WINAPI video_renderer_sink_QueryInterface(IMFMediaSink *iface, REFIID riid, void **obj)
1089 struct video_renderer *renderer = impl_from_IMFMediaSink(iface);
1091 TRACE("%p, %s, %p.\n", iface, debugstr_guid(riid), obj);
1093 if (IsEqualIID(riid, &IID_IMFMediaSink) ||
1094 IsEqualIID(riid, &IID_IUnknown))
1096 *obj = &renderer->IMFMediaSink_iface;
1098 else if (IsEqualIID(riid, &IID_IMFMediaSinkPreroll))
1100 *obj = &renderer->IMFMediaSinkPreroll_iface;
1102 else if (IsEqualIID(riid, &IID_IMFVideoRenderer))
1104 *obj = &renderer->IMFVideoRenderer_iface;
1106 else if (IsEqualIID(riid, &IID_IMFMediaEventGenerator))
1108 *obj = &renderer->IMFMediaEventGenerator_iface;
1110 else if (IsEqualIID(riid, &IID_IMFClockStateSink))
1112 *obj = &renderer->IMFClockStateSink_iface;
1114 else if (IsEqualIID(riid, &IID_IMFGetService))
1116 *obj = &renderer->IMFGetService_iface;
1118 else if (IsEqualIID(riid, &IID_IMFAttributes))
1120 *obj = &renderer->IMFAttributes_iface;
1122 else if (IsEqualIID(riid, &IID_IMFQualityAdvise))
1124 *obj = &renderer->IMFQualityAdvise_iface;
1126 else if (IsEqualIID(riid, &IID_IMFRateSupport))
1128 *obj = &renderer->IMFRateSupport_iface;
1130 else
1132 WARN("Unsupported interface %s.\n", debugstr_guid(riid));
1133 *obj = NULL;
1134 return E_NOINTERFACE;
1137 IUnknown_AddRef((IUnknown *)*obj);
1139 return S_OK;
1142 static ULONG WINAPI video_renderer_sink_AddRef(IMFMediaSink *iface)
1144 struct video_renderer *renderer = impl_from_IMFMediaSink(iface);
1145 ULONG refcount = InterlockedIncrement(&renderer->refcount);
1146 TRACE("%p, refcount %u.\n", iface, refcount);
1147 return refcount;
1150 static ULONG WINAPI video_renderer_sink_Release(IMFMediaSink *iface)
1152 struct video_renderer *renderer = impl_from_IMFMediaSink(iface);
1153 ULONG refcount = InterlockedDecrement(&renderer->refcount);
1155 TRACE("%p, refcount %u.\n", iface, refcount);
1157 if (!refcount)
1159 if (renderer->event_queue)
1160 IMFMediaEventQueue_Release(renderer->event_queue);
1161 if (renderer->mixer)
1162 IMFTransform_Release(renderer->mixer);
1163 if (renderer->presenter)
1164 IMFVideoPresenter_Release(renderer->presenter);
1165 if (renderer->device_manager)
1166 IUnknown_Release(renderer->device_manager);
1167 if (renderer->clock)
1168 IMFPresentationClock_Release(renderer->clock);
1169 if (renderer->attributes)
1170 IMFAttributes_Release(renderer->attributes);
1171 DeleteCriticalSection(&renderer->cs);
1172 heap_free(renderer);
1175 return refcount;
1178 static HRESULT WINAPI video_renderer_sink_GetCharacteristics(IMFMediaSink *iface, DWORD *flags)
1180 struct video_renderer *renderer = impl_from_IMFMediaSink(iface);
1182 TRACE("%p, %p.\n", iface, flags);
1184 if (renderer->flags & EVR_SHUT_DOWN)
1185 return MF_E_SHUTDOWN;
1187 *flags = MEDIASINK_CLOCK_REQUIRED | MEDIASINK_CAN_PREROLL;
1189 return S_OK;
1192 static HRESULT video_renderer_add_stream(struct video_renderer *renderer, unsigned int id,
1193 IMFStreamSink **stream_sink)
1195 struct video_stream *stream;
1196 HRESULT hr;
1198 if (!mf_array_reserve((void **)&renderer->streams, &renderer->stream_size, renderer->stream_count + 1,
1199 sizeof(*renderer->streams)))
1201 return E_OUTOFMEMORY;
1204 if (SUCCEEDED(hr = video_renderer_stream_create(renderer, id, &stream)))
1206 if (stream_sink)
1208 *stream_sink = &stream->IMFStreamSink_iface;
1209 IMFStreamSink_AddRef(*stream_sink);
1211 renderer->streams[renderer->stream_count++] = stream;
1214 return hr;
1217 static HRESULT WINAPI video_renderer_sink_AddStreamSink(IMFMediaSink *iface, DWORD id,
1218 IMFMediaType *media_type, IMFStreamSink **stream_sink)
1220 struct video_renderer *renderer = impl_from_IMFMediaSink(iface);
1221 HRESULT hr;
1223 TRACE("%p, %#x, %p, %p.\n", iface, id, media_type, stream_sink);
1225 /* Rely on mixer for stream id validation. */
1227 EnterCriticalSection(&renderer->cs);
1228 if (renderer->flags & EVR_SHUT_DOWN)
1229 hr = MF_E_SHUTDOWN;
1230 else if (SUCCEEDED(hr = IMFTransform_AddInputStreams(renderer->mixer, 1, &id)))
1232 if (FAILED(hr = video_renderer_add_stream(renderer, id, stream_sink)))
1233 IMFTransform_DeleteInputStream(renderer->mixer, id);
1236 LeaveCriticalSection(&renderer->cs);
1238 return hr;
1241 static HRESULT WINAPI video_renderer_sink_RemoveStreamSink(IMFMediaSink *iface, DWORD id)
1243 struct video_renderer *renderer = impl_from_IMFMediaSink(iface);
1244 HRESULT hr;
1245 size_t i;
1247 TRACE("%p, %#x.\n", iface, id);
1249 /* Rely on mixer for stream id validation. */
1251 EnterCriticalSection(&renderer->cs);
1252 if (renderer->flags & EVR_SHUT_DOWN)
1253 hr = MF_E_SHUTDOWN;
1254 else if (SUCCEEDED(hr = IMFTransform_DeleteInputStream(renderer->mixer, id)))
1256 for (i = 0; i < renderer->stream_count; ++i)
1258 if (renderer->streams[i]->id == id)
1260 IMFStreamSink_Release(&renderer->streams[i]->IMFStreamSink_iface);
1261 renderer->streams[i] = NULL;
1262 if (i < renderer->stream_count - 1)
1264 memmove(&renderer->streams[i], &renderer->streams[i+1],
1265 (renderer->stream_count - i - 1) * sizeof(*renderer->streams));
1267 renderer->stream_count--;
1268 break;
1272 LeaveCriticalSection(&renderer->cs);
1274 return hr;
1277 static HRESULT WINAPI video_renderer_sink_GetStreamSinkCount(IMFMediaSink *iface, DWORD *count)
1279 struct video_renderer *renderer = impl_from_IMFMediaSink(iface);
1280 HRESULT hr = S_OK;
1282 TRACE("%p, %p.\n", iface, count);
1284 if (!count)
1285 return E_POINTER;
1287 EnterCriticalSection(&renderer->cs);
1288 if (renderer->flags & EVR_SHUT_DOWN)
1289 hr = MF_E_SHUTDOWN;
1290 else if (!count)
1291 hr = E_POINTER;
1292 else
1293 *count = renderer->stream_count;
1294 LeaveCriticalSection(&renderer->cs);
1296 return hr;
1299 static HRESULT WINAPI video_renderer_sink_GetStreamSinkByIndex(IMFMediaSink *iface, DWORD index,
1300 IMFStreamSink **stream)
1302 struct video_renderer *renderer = impl_from_IMFMediaSink(iface);
1303 HRESULT hr = S_OK;
1305 TRACE("%p, %u, %p.\n", iface, index, stream);
1307 EnterCriticalSection(&renderer->cs);
1308 if (renderer->flags & EVR_SHUT_DOWN)
1309 hr = MF_E_SHUTDOWN;
1310 else if (!stream)
1311 hr = E_POINTER;
1312 else if (index >= renderer->stream_count)
1313 hr = E_INVALIDARG;
1314 else
1316 *stream = &renderer->streams[index]->IMFStreamSink_iface;
1317 IMFStreamSink_AddRef(*stream);
1319 LeaveCriticalSection(&renderer->cs);
1321 return hr;
1324 static HRESULT WINAPI video_renderer_sink_GetStreamSinkById(IMFMediaSink *iface, DWORD id,
1325 IMFStreamSink **stream)
1327 struct video_renderer *renderer = impl_from_IMFMediaSink(iface);
1328 HRESULT hr = S_OK;
1329 size_t i;
1331 TRACE("%p, %#x, %p.\n", iface, id, stream);
1333 EnterCriticalSection(&renderer->cs);
1334 if (renderer->flags & EVR_SHUT_DOWN)
1335 hr = MF_E_SHUTDOWN;
1336 else if (!stream)
1337 hr = E_POINTER;
1338 else
1340 for (i = 0; i < renderer->stream_count; ++i)
1342 if (renderer->streams[i]->id == id)
1343 break;
1346 if (i == renderer->stream_count)
1347 hr = MF_E_INVALIDSTREAMNUMBER;
1348 else
1350 *stream = &renderer->streams[i]->IMFStreamSink_iface;
1351 IMFStreamSink_AddRef(*stream);
1354 LeaveCriticalSection(&renderer->cs);
1356 return hr;
1359 static void video_renderer_set_presentation_clock(struct video_renderer *renderer, IMFPresentationClock *clock)
1361 if (renderer->clock)
1363 IMFPresentationClock_RemoveClockStateSink(renderer->clock, &renderer->IMFClockStateSink_iface);
1364 IMFPresentationClock_Release(renderer->clock);
1366 video_renderer_release_presenter_services(renderer);
1368 renderer->clock = clock;
1369 if (renderer->clock)
1371 IMFPresentationClock_AddRef(renderer->clock);
1372 IMFPresentationClock_AddClockStateSink(renderer->clock, &renderer->IMFClockStateSink_iface);
1374 video_renderer_init_presenter_services(renderer);
1377 static HRESULT WINAPI video_renderer_sink_SetPresentationClock(IMFMediaSink *iface, IMFPresentationClock *clock)
1379 struct video_renderer *renderer = impl_from_IMFMediaSink(iface);
1380 HRESULT hr = S_OK;
1382 TRACE("%p, %p.\n", iface, clock);
1384 EnterCriticalSection(&renderer->cs);
1386 if (renderer->flags & EVR_SHUT_DOWN)
1387 hr = MF_E_SHUTDOWN;
1388 else
1389 video_renderer_set_presentation_clock(renderer, clock);
1391 LeaveCriticalSection(&renderer->cs);
1393 return hr;
1396 static HRESULT WINAPI video_renderer_sink_GetPresentationClock(IMFMediaSink *iface, IMFPresentationClock **clock)
1398 struct video_renderer *renderer = impl_from_IMFMediaSink(iface);
1399 HRESULT hr = S_OK;
1401 TRACE("%p, %p.\n", iface, clock);
1403 if (!clock)
1404 return E_POINTER;
1406 EnterCriticalSection(&renderer->cs);
1408 if (renderer->flags & EVR_SHUT_DOWN)
1409 hr = MF_E_SHUTDOWN;
1410 else if (renderer->clock)
1412 *clock = renderer->clock;
1413 IMFPresentationClock_AddRef(*clock);
1415 else
1416 hr = MF_E_NO_CLOCK;
1418 LeaveCriticalSection(&renderer->cs);
1420 return hr;
1423 static HRESULT WINAPI video_renderer_sink_Shutdown(IMFMediaSink *iface)
1425 struct video_renderer *renderer = impl_from_IMFMediaSink(iface);
1426 size_t i;
1428 TRACE("%p.\n", iface);
1430 if (renderer->flags & EVR_SHUT_DOWN)
1431 return MF_E_SHUTDOWN;
1433 EnterCriticalSection(&renderer->cs);
1434 renderer->flags |= EVR_SHUT_DOWN;
1435 /* Detach streams from the sink. */
1436 for (i = 0; i < renderer->stream_count; ++i)
1438 struct video_stream *stream = renderer->streams[i];
1440 EnterCriticalSection(&stream->cs);
1441 stream->parent = NULL;
1442 LeaveCriticalSection(&stream->cs);
1444 IMFMediaEventQueue_Shutdown(stream->event_queue);
1445 IMFStreamSink_Release(&stream->IMFStreamSink_iface);
1446 IMFMediaSink_Release(iface);
1447 renderer->streams[i] = NULL;
1449 heap_free(renderer->streams);
1450 renderer->stream_count = 0;
1451 renderer->stream_size = 0;
1452 IMFMediaEventQueue_Shutdown(renderer->event_queue);
1453 video_renderer_set_presentation_clock(renderer, NULL);
1454 video_renderer_release_services(renderer);
1455 LeaveCriticalSection(&renderer->cs);
1457 return S_OK;
1460 static const IMFMediaSinkVtbl video_renderer_sink_vtbl =
1462 video_renderer_sink_QueryInterface,
1463 video_renderer_sink_AddRef,
1464 video_renderer_sink_Release,
1465 video_renderer_sink_GetCharacteristics,
1466 video_renderer_sink_AddStreamSink,
1467 video_renderer_sink_RemoveStreamSink,
1468 video_renderer_sink_GetStreamSinkCount,
1469 video_renderer_sink_GetStreamSinkByIndex,
1470 video_renderer_sink_GetStreamSinkById,
1471 video_renderer_sink_SetPresentationClock,
1472 video_renderer_sink_GetPresentationClock,
1473 video_renderer_sink_Shutdown,
1476 static HRESULT WINAPI video_renderer_preroll_QueryInterface(IMFMediaSinkPreroll *iface, REFIID riid, void **obj)
1478 struct video_renderer *renderer = impl_from_IMFMediaSinkPreroll(iface);
1479 return IMFMediaSink_QueryInterface(&renderer->IMFMediaSink_iface, riid, obj);
1482 static ULONG WINAPI video_renderer_preroll_AddRef(IMFMediaSinkPreroll *iface)
1484 struct video_renderer *renderer = impl_from_IMFMediaSinkPreroll(iface);
1485 return IMFMediaSink_AddRef(&renderer->IMFMediaSink_iface);
1488 static ULONG WINAPI video_renderer_preroll_Release(IMFMediaSinkPreroll *iface)
1490 struct video_renderer *renderer = impl_from_IMFMediaSinkPreroll(iface);
1491 return IMFMediaSink_Release(&renderer->IMFMediaSink_iface);
1494 static HRESULT WINAPI video_renderer_preroll_NotifyPreroll(IMFMediaSinkPreroll *iface, MFTIME start_time)
1496 struct video_renderer *renderer = impl_from_IMFMediaSinkPreroll(iface);
1497 HRESULT hr = S_OK;
1498 size_t i;
1500 TRACE("%p, %s.\n", iface, debugstr_time(start_time));
1502 EnterCriticalSection(&renderer->cs);
1503 if (renderer->flags & EVR_SHUT_DOWN)
1504 hr = MF_E_SHUTDOWN;
1505 else
1507 for (i = 0; i < renderer->stream_count; ++i)
1509 struct video_stream *stream = renderer->streams[i];
1511 EnterCriticalSection(&stream->cs);
1512 if (!(stream->flags & (EVR_STREAM_PREROLLING | EVR_STREAM_PREROLLED)))
1514 IMFMediaEventQueue_QueueEventParamVar(stream->event_queue, MEStreamSinkRequestSample,
1515 &GUID_NULL, S_OK, NULL);
1516 stream->flags |= EVR_STREAM_PREROLLING;
1518 LeaveCriticalSection(&stream->cs);
1521 LeaveCriticalSection(&renderer->cs);
1523 return hr;
1526 static const IMFMediaSinkPrerollVtbl video_renderer_preroll_vtbl =
1528 video_renderer_preroll_QueryInterface,
1529 video_renderer_preroll_AddRef,
1530 video_renderer_preroll_Release,
1531 video_renderer_preroll_NotifyPreroll,
1534 static HRESULT WINAPI video_renderer_QueryInterface(IMFVideoRenderer *iface, REFIID riid, void **obj)
1536 struct video_renderer *renderer = impl_from_IMFVideoRenderer(iface);
1537 return IMFMediaSink_QueryInterface(&renderer->IMFMediaSink_iface, riid, obj);
1540 static ULONG WINAPI video_renderer_AddRef(IMFVideoRenderer *iface)
1542 struct video_renderer *renderer = impl_from_IMFVideoRenderer(iface);
1543 return IMFMediaSink_AddRef(&renderer->IMFMediaSink_iface);
1546 static ULONG WINAPI video_renderer_Release(IMFVideoRenderer *iface)
1548 struct video_renderer *renderer = impl_from_IMFVideoRenderer(iface);
1549 return IMFMediaSink_Release(&renderer->IMFMediaSink_iface);
1552 static HRESULT video_renderer_create_mixer(IMFAttributes *attributes, IMFTransform **out)
1554 unsigned int flags = 0;
1555 IMFActivate *activate;
1556 CLSID clsid;
1557 HRESULT hr;
1559 if (attributes && SUCCEEDED(hr = IMFAttributes_GetUnknown(attributes, &MF_ACTIVATE_CUSTOM_VIDEO_MIXER_ACTIVATE,
1560 &IID_IMFActivate, (void **)&activate)))
1562 IMFAttributes_GetUINT32(attributes, &MF_ACTIVATE_CUSTOM_VIDEO_MIXER_FLAGS, &flags);
1563 hr = IMFActivate_ActivateObject(activate, &IID_IMFTransform, (void **)out);
1564 IMFActivate_Release(activate);
1565 if (SUCCEEDED(hr) || !(flags & MF_ACTIVATE_CUSTOM_MIXER_ALLOWFAIL))
1566 return hr;
1569 if (!attributes || FAILED(IMFAttributes_GetGUID(attributes, &MF_ACTIVATE_CUSTOM_VIDEO_MIXER_CLSID, &clsid)))
1570 memcpy(&clsid, &CLSID_MFVideoMixer9, sizeof(clsid));
1572 return CoCreateInstance(&clsid, NULL, CLSCTX_INPROC_SERVER, &IID_IMFTransform, (void **)out);
1575 static HRESULT video_renderer_create_presenter(struct video_renderer *renderer, IMFAttributes *attributes,
1576 IMFVideoPresenter **out)
1578 unsigned int flags = 0;
1579 IMFActivate *activate;
1580 UINT64 value;
1581 CLSID clsid;
1582 HRESULT hr;
1584 if (attributes && SUCCEEDED(IMFAttributes_GetUINT64(attributes, &MF_ACTIVATE_VIDEO_WINDOW, &value)))
1585 renderer->window = UlongToHandle(value);
1587 if (attributes && SUCCEEDED(IMFAttributes_GetUnknown(attributes, &MF_ACTIVATE_CUSTOM_VIDEO_PRESENTER_ACTIVATE,
1588 &IID_IMFActivate, (void **)&activate)))
1590 IMFAttributes_GetUINT32(attributes, &MF_ACTIVATE_CUSTOM_VIDEO_PRESENTER_FLAGS, &flags);
1591 hr = IMFActivate_ActivateObject(activate, &IID_IMFVideoPresenter, (void **)out);
1592 IMFActivate_Release(activate);
1593 if (SUCCEEDED(hr) || !(flags & MF_ACTIVATE_CUSTOM_PRESENTER_ALLOWFAIL))
1594 return hr;
1597 if (!attributes || FAILED(IMFAttributes_GetGUID(attributes, &MF_ACTIVATE_CUSTOM_VIDEO_PRESENTER_CLSID, &clsid)))
1598 memcpy(&clsid, &CLSID_MFVideoPresenter9, sizeof(clsid));
1600 return CoCreateInstance(&clsid, NULL, CLSCTX_INPROC_SERVER, &IID_IMFVideoPresenter, (void **)out);
1603 static HRESULT video_renderer_configure_mixer(struct video_renderer *renderer)
1605 IMFTopologyServiceLookupClient *lookup_client;
1606 HRESULT hr;
1608 if (SUCCEEDED(hr = IMFTransform_QueryInterface(renderer->mixer, &IID_IMFTopologyServiceLookupClient,
1609 (void **)&lookup_client)))
1611 renderer->flags |= EVR_INIT_SERVICES;
1612 if (SUCCEEDED(hr = IMFTopologyServiceLookupClient_InitServicePointers(lookup_client,
1613 &renderer->IMFTopologyServiceLookup_iface)))
1615 renderer->flags |= EVR_MIXER_INITED_SERVICES;
1617 renderer->flags &= ~EVR_INIT_SERVICES;
1618 IMFTopologyServiceLookupClient_Release(lookup_client);
1621 if (SUCCEEDED(hr))
1623 unsigned int input_count, output_count;
1624 unsigned int *ids, *oids;
1625 size_t i;
1627 /* Create stream sinks for inputs that mixer already has by default. */
1628 if (SUCCEEDED(IMFTransform_GetStreamCount(renderer->mixer, &input_count, &output_count)))
1630 ids = heap_calloc(input_count, sizeof(*ids));
1631 oids = heap_calloc(output_count, sizeof(*oids));
1633 if (ids && oids)
1635 if (SUCCEEDED(IMFTransform_GetStreamIDs(renderer->mixer, input_count, ids, output_count, oids)))
1637 for (i = 0; i < input_count; ++i)
1639 video_renderer_add_stream(renderer, ids[i], NULL);
1645 heap_free(ids);
1646 heap_free(oids);
1650 /* Set device manager that presenter should have created. */
1651 if (video_renderer_is_mixer_d3d_aware(renderer))
1653 IDirect3DDeviceManager9 *device_manager;
1655 if (SUCCEEDED(MFGetService((IUnknown *)renderer->presenter, &MR_VIDEO_ACCELERATION_SERVICE,
1656 &IID_IDirect3DDeviceManager9, (void **)&device_manager)))
1658 IMFTransform_ProcessMessage(renderer->mixer, MFT_MESSAGE_SET_D3D_MANAGER, (ULONG_PTR)device_manager);
1659 IDirect3DDeviceManager9_Release(device_manager);
1663 return hr;
1666 static HRESULT video_renderer_configure_presenter(struct video_renderer *renderer)
1668 IMFVideoDisplayControl *control;
1669 RECT rect = { 0 };
1670 HRESULT hr;
1672 if (SUCCEEDED(IMFVideoPresenter_QueryInterface(renderer->presenter, &IID_IMFVideoDisplayControl, (void **)&control)))
1674 GetClientRect(renderer->window, &rect);
1676 if (SUCCEEDED(hr = IMFVideoDisplayControl_SetVideoWindow(control, renderer->window)))
1677 hr = IMFVideoDisplayControl_SetVideoPosition(control, NULL, &rect);
1678 IMFVideoDisplayControl_Release(control);
1681 hr = video_renderer_init_presenter_services(renderer);
1683 if (FAILED(MFGetService((IUnknown *)renderer->presenter, &MR_VIDEO_ACCELERATION_SERVICE,
1684 &IID_IUnknown, (void **)&renderer->device_manager)))
1686 WARN("Failed to get device manager from the presenter.\n");
1689 return hr;
1692 static HRESULT video_renderer_initialize(struct video_renderer *renderer, IMFTransform *mixer,
1693 IMFVideoPresenter *presenter)
1695 HRESULT hr;
1697 if (renderer->mixer)
1699 IMFTransform_Release(renderer->mixer);
1700 renderer->mixer = NULL;
1703 if (renderer->presenter)
1705 IMFVideoPresenter_Release(renderer->presenter);
1706 renderer->presenter = NULL;
1709 if (renderer->device_manager)
1711 IUnknown_Release(renderer->device_manager);
1712 renderer->device_manager = NULL;
1715 renderer->mixer = mixer;
1716 IMFTransform_AddRef(renderer->mixer);
1718 renderer->presenter = presenter;
1719 IMFVideoPresenter_AddRef(renderer->presenter);
1721 if (SUCCEEDED(hr = video_renderer_configure_mixer(renderer)))
1722 hr = video_renderer_configure_presenter(renderer);
1724 return hr;
1727 static HRESULT WINAPI video_renderer_InitializeRenderer(IMFVideoRenderer *iface, IMFTransform *mixer,
1728 IMFVideoPresenter *presenter)
1730 struct video_renderer *renderer = impl_from_IMFVideoRenderer(iface);
1731 HRESULT hr;
1733 TRACE("%p, %p, %p.\n", iface, mixer, presenter);
1735 if (mixer)
1736 IMFTransform_AddRef(mixer);
1737 else if (FAILED(hr = video_renderer_create_mixer(NULL, &mixer)))
1739 WARN("Failed to create default mixer object, hr %#x.\n", hr);
1740 return hr;
1743 if (presenter)
1744 IMFVideoPresenter_AddRef(presenter);
1745 else if (FAILED(hr = video_renderer_create_presenter(renderer, NULL, &presenter)))
1747 WARN("Failed to create default presenter, hr %#x.\n", hr);
1748 IMFTransform_Release(mixer);
1749 return hr;
1752 EnterCriticalSection(&renderer->cs);
1754 if (renderer->flags & EVR_SHUT_DOWN)
1755 hr = MF_E_SHUTDOWN;
1756 else
1758 /* FIXME: check clock state */
1759 /* FIXME: check that streams are not initialized */
1761 hr = video_renderer_initialize(renderer, mixer, presenter);
1764 LeaveCriticalSection(&renderer->cs);
1766 IMFTransform_Release(mixer);
1767 IMFVideoPresenter_Release(presenter);
1769 return hr;
1772 static const IMFVideoRendererVtbl video_renderer_vtbl =
1774 video_renderer_QueryInterface,
1775 video_renderer_AddRef,
1776 video_renderer_Release,
1777 video_renderer_InitializeRenderer,
1780 static HRESULT WINAPI video_renderer_events_QueryInterface(IMFMediaEventGenerator *iface, REFIID riid, void **obj)
1782 struct video_renderer *renderer = impl_from_IMFMediaEventGenerator(iface);
1783 return IMFMediaSink_QueryInterface(&renderer->IMFMediaSink_iface, riid, obj);
1786 static ULONG WINAPI video_renderer_events_AddRef(IMFMediaEventGenerator *iface)
1788 struct video_renderer *renderer = impl_from_IMFMediaEventGenerator(iface);
1789 return IMFMediaSink_AddRef(&renderer->IMFMediaSink_iface);
1792 static ULONG WINAPI video_renderer_events_Release(IMFMediaEventGenerator *iface)
1794 struct video_renderer *renderer = impl_from_IMFMediaEventGenerator(iface);
1795 return IMFMediaSink_Release(&renderer->IMFMediaSink_iface);
1798 static HRESULT WINAPI video_renderer_events_GetEvent(IMFMediaEventGenerator *iface, DWORD flags, IMFMediaEvent **event)
1800 struct video_renderer *renderer = impl_from_IMFMediaEventGenerator(iface);
1802 TRACE("%p, %#x, %p.\n", iface, flags, event);
1804 return IMFMediaEventQueue_GetEvent(renderer->event_queue, flags, event);
1807 static HRESULT WINAPI video_renderer_events_BeginGetEvent(IMFMediaEventGenerator *iface, IMFAsyncCallback *callback,
1808 IUnknown *state)
1810 struct video_renderer *renderer = impl_from_IMFMediaEventGenerator(iface);
1812 TRACE("%p, %p, %p.\n", iface, callback, state);
1814 return IMFMediaEventQueue_BeginGetEvent(renderer->event_queue, callback, state);
1817 static HRESULT WINAPI video_renderer_events_EndGetEvent(IMFMediaEventGenerator *iface, IMFAsyncResult *result,
1818 IMFMediaEvent **event)
1820 struct video_renderer *renderer = impl_from_IMFMediaEventGenerator(iface);
1822 TRACE("%p, %p, %p.\n", iface, result, event);
1824 return IMFMediaEventQueue_EndGetEvent(renderer->event_queue, result, event);
1827 static HRESULT WINAPI video_renderer_events_QueueEvent(IMFMediaEventGenerator *iface, MediaEventType event_type,
1828 REFGUID ext_type, HRESULT hr, const PROPVARIANT *value)
1830 struct video_renderer *renderer = impl_from_IMFMediaEventGenerator(iface);
1832 TRACE("%p, %u, %s, %#x, %p.\n", iface, event_type, debugstr_guid(ext_type), hr, value);
1834 return IMFMediaEventQueue_QueueEventParamVar(renderer->event_queue, event_type, ext_type, hr, value);
1837 static const IMFMediaEventGeneratorVtbl video_renderer_events_vtbl =
1839 video_renderer_events_QueryInterface,
1840 video_renderer_events_AddRef,
1841 video_renderer_events_Release,
1842 video_renderer_events_GetEvent,
1843 video_renderer_events_BeginGetEvent,
1844 video_renderer_events_EndGetEvent,
1845 video_renderer_events_QueueEvent,
1848 static HRESULT WINAPI video_renderer_clock_sink_QueryInterface(IMFClockStateSink *iface, REFIID riid, void **obj)
1850 struct video_renderer *renderer = impl_from_IMFClockStateSink(iface);
1851 return IMFMediaSink_QueryInterface(&renderer->IMFMediaSink_iface, riid, obj);
1854 static ULONG WINAPI video_renderer_clock_sink_AddRef(IMFClockStateSink *iface)
1856 struct video_renderer *renderer = impl_from_IMFClockStateSink(iface);
1857 return IMFMediaSink_AddRef(&renderer->IMFMediaSink_iface);
1860 static ULONG WINAPI video_renderer_clock_sink_Release(IMFClockStateSink *iface)
1862 struct video_renderer *renderer = impl_from_IMFClockStateSink(iface);
1863 return IMFMediaSink_Release(&renderer->IMFMediaSink_iface);
1866 static HRESULT WINAPI video_renderer_clock_sink_OnClockStart(IMFClockStateSink *iface, MFTIME systime, LONGLONG offset)
1868 struct video_renderer *renderer = impl_from_IMFClockStateSink(iface);
1869 unsigned int state, request_sample;
1870 size_t i;
1872 TRACE("%p, %s, %s.\n", iface, debugstr_time(systime), debugstr_time(offset));
1874 EnterCriticalSection(&renderer->cs);
1876 state = renderer->state;
1878 /* Update sink state before sending sample requests, to avoid potentially receiving new sample in stopped state */
1879 renderer->state = EVR_STATE_RUNNING;
1881 if (state == EVR_STATE_STOPPED)
1883 IMFTransform_ProcessMessage(renderer->mixer, MFT_MESSAGE_NOTIFY_BEGIN_STREAMING, 0);
1884 IMFVideoPresenter_ProcessMessage(renderer->presenter, MFVP_MESSAGE_BEGINSTREAMING, 0);
1886 for (i = 0; i < renderer->stream_count; ++i)
1888 struct video_stream *stream = renderer->streams[i];
1890 EnterCriticalSection(&stream->cs);
1891 request_sample = !(stream->flags & EVR_STREAM_PREROLLED) || (stream->flags & EVR_STREAM_SAMPLE_NEEDED);
1892 stream->flags |= EVR_STREAM_PREROLLED;
1893 stream->flags &= ~EVR_STREAM_SAMPLE_NEEDED;
1894 LeaveCriticalSection(&stream->cs);
1896 IMFMediaEventQueue_QueueEventParamVar(stream->event_queue, MEStreamSinkStarted, &GUID_NULL, S_OK, NULL);
1897 if (request_sample)
1898 IMFMediaEventQueue_QueueEventParamVar(stream->event_queue, MEStreamSinkRequestSample,
1899 &GUID_NULL, S_OK, NULL);
1903 IMFVideoPresenter_OnClockStart(renderer->presenter, systime, offset);
1905 LeaveCriticalSection(&renderer->cs);
1907 return S_OK;
1910 static HRESULT WINAPI video_renderer_clock_sink_OnClockStop(IMFClockStateSink *iface, MFTIME systime)
1912 struct video_renderer *renderer = impl_from_IMFClockStateSink(iface);
1913 size_t i;
1915 TRACE("%p, %s.\n", iface, debugstr_time(systime));
1917 EnterCriticalSection(&renderer->cs);
1919 IMFVideoPresenter_OnClockStop(renderer->presenter, systime);
1921 IMFTransform_ProcessMessage(renderer->mixer, MFT_MESSAGE_COMMAND_FLUSH, 0);
1922 IMFVideoPresenter_ProcessMessage(renderer->presenter, MFVP_MESSAGE_FLUSH, 0);
1924 if (renderer->state == EVR_STATE_RUNNING ||
1925 renderer->state == EVR_STATE_PAUSED)
1927 IMFTransform_ProcessMessage(renderer->mixer, MFT_MESSAGE_NOTIFY_END_STREAMING, 0);
1928 IMFVideoPresenter_ProcessMessage(renderer->presenter, MFVP_MESSAGE_ENDSTREAMING, 0);
1930 for (i = 0; i < renderer->stream_count; ++i)
1932 struct video_stream *stream = renderer->streams[i];
1933 IMFMediaEventQueue_QueueEventParamVar(stream->event_queue, MEStreamSinkStopped, &GUID_NULL, S_OK, NULL);
1935 EnterCriticalSection(&stream->cs);
1936 stream->flags &= ~(EVR_STREAM_PREROLLED | EVR_STREAM_SAMPLE_NEEDED);
1937 LeaveCriticalSection(&stream->cs);
1939 renderer->state = EVR_STATE_STOPPED;
1942 LeaveCriticalSection(&renderer->cs);
1944 return S_OK;
1947 static HRESULT WINAPI video_renderer_clock_sink_OnClockPause(IMFClockStateSink *iface, MFTIME systime)
1949 struct video_renderer *renderer = impl_from_IMFClockStateSink(iface);
1950 size_t i;
1952 TRACE("%p, %s.\n", iface, debugstr_time(systime));
1954 EnterCriticalSection(&renderer->cs);
1956 IMFVideoPresenter_OnClockPause(renderer->presenter, systime);
1958 if (renderer->state == EVR_STATE_RUNNING)
1960 for (i = 0; i < renderer->stream_count; ++i)
1962 struct video_stream *stream = renderer->streams[i];
1963 IMFMediaEventQueue_QueueEventParamVar(stream->event_queue, MEStreamSinkPaused, &GUID_NULL, S_OK, NULL);
1967 renderer->state = EVR_STATE_PAUSED;
1969 LeaveCriticalSection(&renderer->cs);
1971 return S_OK;
1974 static HRESULT WINAPI video_renderer_clock_sink_OnClockRestart(IMFClockStateSink *iface, MFTIME systime)
1976 struct video_renderer *renderer = impl_from_IMFClockStateSink(iface);
1977 size_t i;
1979 TRACE("%p, %s.\n", iface, debugstr_time(systime));
1981 EnterCriticalSection(&renderer->cs);
1983 IMFVideoPresenter_OnClockRestart(renderer->presenter, systime);
1985 for (i = 0; i < renderer->stream_count; ++i)
1987 struct video_stream *stream = renderer->streams[i];
1988 IMFMediaEventQueue_QueueEventParamVar(stream->event_queue, MEStreamSinkStarted, &GUID_NULL, S_OK, NULL);
1990 renderer->state = EVR_STATE_RUNNING;
1992 LeaveCriticalSection(&renderer->cs);
1994 return S_OK;
1997 static HRESULT WINAPI video_renderer_clock_sink_OnClockSetRate(IMFClockStateSink *iface, MFTIME systime, float rate)
1999 struct video_renderer *renderer = impl_from_IMFClockStateSink(iface);
2000 IMFClockStateSink *sink;
2002 TRACE("%p, %s, %f.\n", iface, debugstr_time(systime), rate);
2004 EnterCriticalSection(&renderer->cs);
2006 IMFVideoPresenter_OnClockSetRate(renderer->presenter, systime, rate);
2007 if (SUCCEEDED(IMFTransform_QueryInterface(renderer->mixer, &IID_IMFClockStateSink, (void **)&sink)))
2009 IMFClockStateSink_OnClockSetRate(sink, systime, rate);
2010 IMFClockStateSink_Release(sink);
2013 LeaveCriticalSection(&renderer->cs);
2015 return S_OK;
2018 static const IMFClockStateSinkVtbl video_renderer_clock_sink_vtbl =
2020 video_renderer_clock_sink_QueryInterface,
2021 video_renderer_clock_sink_AddRef,
2022 video_renderer_clock_sink_Release,
2023 video_renderer_clock_sink_OnClockStart,
2024 video_renderer_clock_sink_OnClockStop,
2025 video_renderer_clock_sink_OnClockPause,
2026 video_renderer_clock_sink_OnClockRestart,
2027 video_renderer_clock_sink_OnClockSetRate,
2030 static HRESULT WINAPI video_renderer_get_service_QueryInterface(IMFGetService *iface, REFIID riid, void **obj)
2032 struct video_renderer *renderer = impl_from_IMFGetService(iface);
2033 return IMFMediaSink_QueryInterface(&renderer->IMFMediaSink_iface, riid, obj);
2036 static ULONG WINAPI video_renderer_get_service_AddRef(IMFGetService *iface)
2038 struct video_renderer *renderer = impl_from_IMFGetService(iface);
2039 return IMFMediaSink_AddRef(&renderer->IMFMediaSink_iface);
2042 static ULONG WINAPI video_renderer_get_service_Release(IMFGetService *iface)
2044 struct video_renderer *renderer = impl_from_IMFGetService(iface);
2045 return IMFMediaSink_Release(&renderer->IMFMediaSink_iface);
2048 static HRESULT WINAPI video_renderer_get_service_GetService(IMFGetService *iface, REFGUID service, REFIID riid, void **obj)
2050 struct video_renderer *renderer = impl_from_IMFGetService(iface);
2051 HRESULT hr = E_NOINTERFACE;
2052 IMFGetService *gs = NULL;
2054 TRACE("%p, %s, %s, %p.\n", iface, debugstr_guid(service), debugstr_guid(riid), obj);
2056 EnterCriticalSection(&renderer->cs);
2058 if (IsEqualGUID(service, &MR_VIDEO_MIXER_SERVICE))
2060 hr = IMFTransform_QueryInterface(renderer->mixer, &IID_IMFGetService, (void **)&gs);
2062 else if (IsEqualGUID(service, &MR_VIDEO_RENDER_SERVICE))
2064 hr = IMFVideoPresenter_QueryInterface(renderer->presenter, &IID_IMFGetService, (void **)&gs);
2066 else if (IsEqualGUID(service, &MR_VIDEO_ACCELERATION_SERVICE) && IsEqualIID(riid, &IID_IDirect3DDeviceManager9))
2068 if (renderer->device_manager)
2069 hr = IUnknown_QueryInterface(renderer->device_manager, riid, obj);
2071 else if (IsEqualGUID(service, &MF_RATE_CONTROL_SERVICE) && IsEqualIID(riid, &IID_IMFRateSupport))
2073 hr = IMFVideoRenderer_QueryInterface(&renderer->IMFVideoRenderer_iface, riid, obj);
2075 else
2077 FIXME("Unsupported service %s.\n", debugstr_guid(service));
2080 LeaveCriticalSection(&renderer->cs);
2082 if (gs)
2084 hr = IMFGetService_GetService(gs, service, riid, obj);
2085 IMFGetService_Release(gs);
2088 return hr;
2091 static const IMFGetServiceVtbl video_renderer_get_service_vtbl =
2093 video_renderer_get_service_QueryInterface,
2094 video_renderer_get_service_AddRef,
2095 video_renderer_get_service_Release,
2096 video_renderer_get_service_GetService,
2099 static HRESULT WINAPI video_renderer_service_lookup_QueryInterface(IMFTopologyServiceLookup *iface, REFIID riid, void **obj)
2101 TRACE("%p, %s, %p.\n", iface, debugstr_guid(riid), obj);
2103 if (IsEqualIID(riid, &IID_IMFTopologyServiceLookup) ||
2104 IsEqualIID(riid, &IID_IUnknown))
2106 *obj = iface;
2107 IMFTopologyServiceLookup_AddRef(iface);
2108 return S_OK;
2111 WARN("Unsupported interface %s.\n", debugstr_guid(riid));
2112 *obj = NULL;
2113 return E_NOINTERFACE;
2116 static ULONG WINAPI video_renderer_service_lookup_AddRef(IMFTopologyServiceLookup *iface)
2118 struct video_renderer *renderer = impl_from_IMFTopologyServiceLookup(iface);
2119 return IMFMediaSink_AddRef(&renderer->IMFMediaSink_iface);
2122 static ULONG WINAPI video_renderer_service_lookup_Release(IMFTopologyServiceLookup *iface)
2124 struct video_renderer *renderer = impl_from_IMFTopologyServiceLookup(iface);
2125 return IMFMediaSink_Release(&renderer->IMFMediaSink_iface);
2128 static HRESULT WINAPI video_renderer_service_lookup_LookupService(IMFTopologyServiceLookup *iface,
2129 MF_SERVICE_LOOKUP_TYPE lookup_type, DWORD index, REFGUID service, REFIID riid,
2130 void **objects, DWORD *num_objects)
2132 struct video_renderer *renderer = impl_from_IMFTopologyServiceLookup(iface);
2133 HRESULT hr = S_OK;
2135 TRACE("%p, %u, %u, %s, %s, %p, %p.\n", iface, lookup_type, index, debugstr_guid(service), debugstr_guid(riid),
2136 objects, num_objects);
2138 EnterCriticalSection(&renderer->cs);
2140 if (!(renderer->flags & EVR_INIT_SERVICES))
2141 hr = MF_E_NOTACCEPTING;
2142 else if (IsEqualGUID(service, &MR_VIDEO_RENDER_SERVICE))
2144 if (IsEqualIID(riid, &IID_IMediaEventSink))
2146 *objects = &renderer->IMediaEventSink_iface;
2147 IUnknown_AddRef((IUnknown *)*objects);
2149 else if (IsEqualIID(riid, &IID_IMFClock))
2151 *objects = renderer->clock;
2152 if (*objects)
2153 IUnknown_AddRef((IUnknown *)*objects);
2154 hr = *objects ? S_OK : E_NOINTERFACE;
2156 else
2158 FIXME("Unsupported interface %s for render service.\n", debugstr_guid(riid));
2159 hr = E_NOINTERFACE;
2162 else if (IsEqualGUID(service, &MR_VIDEO_MIXER_SERVICE))
2164 if (IsEqualIID(riid, &IID_IMFTransform))
2166 *objects = renderer->mixer;
2167 IUnknown_AddRef((IUnknown *)*objects);
2169 else
2171 FIXME("Unsupported interface %s for mixer service.\n", debugstr_guid(riid));
2172 hr = E_NOINTERFACE;
2175 else
2177 WARN("Unsupported service %s.\n", debugstr_guid(service));
2178 hr = MF_E_UNSUPPORTED_SERVICE;
2181 LeaveCriticalSection(&renderer->cs);
2183 return hr;
2186 static const IMFTopologyServiceLookupVtbl video_renderer_service_lookup_vtbl =
2188 video_renderer_service_lookup_QueryInterface,
2189 video_renderer_service_lookup_AddRef,
2190 video_renderer_service_lookup_Release,
2191 video_renderer_service_lookup_LookupService,
2194 static HRESULT WINAPI video_renderer_event_sink_QueryInterface(IMediaEventSink *iface, REFIID riid, void **obj)
2196 TRACE("%p, %s, %p.\n", iface, debugstr_guid(riid), obj);
2198 if (IsEqualIID(riid, &IID_IMediaEventSink) ||
2199 IsEqualIID(riid, &IID_IUnknown))
2201 *obj = iface;
2202 IMediaEventSink_AddRef(iface);
2203 return S_OK;
2206 WARN("Unsupported interface %s.\n", debugstr_guid(riid));
2207 *obj = NULL;
2208 return E_NOINTERFACE;
2211 static ULONG WINAPI video_renderer_event_sink_AddRef(IMediaEventSink *iface)
2213 struct video_renderer *renderer = impl_from_IMediaEventSink(iface);
2214 return IMFMediaSink_AddRef(&renderer->IMFMediaSink_iface);
2217 static ULONG WINAPI video_renderer_event_sink_Release(IMediaEventSink *iface)
2219 struct video_renderer *renderer = impl_from_IMediaEventSink(iface);
2220 return IMFMediaSink_Release(&renderer->IMFMediaSink_iface);
2223 static HRESULT WINAPI video_renderer_event_sink_Notify(IMediaEventSink *iface, LONG event, LONG_PTR param1, LONG_PTR param2)
2225 struct video_renderer *renderer = impl_from_IMediaEventSink(iface);
2226 HRESULT hr = S_OK;
2227 unsigned int idx;
2229 TRACE("%p, %d, %ld, %ld.\n", iface, event, param1, param2);
2231 EnterCriticalSection(&renderer->cs);
2233 if (event == EC_SAMPLE_NEEDED)
2235 idx = param1;
2236 if (idx >= renderer->stream_count)
2237 hr = MF_E_INVALIDSTREAMNUMBER;
2238 else if (renderer->state == EVR_STATE_RUNNING)
2240 hr = IMFMediaEventQueue_QueueEventParamVar(renderer->streams[idx]->event_queue,
2241 MEStreamSinkRequestSample, &GUID_NULL, S_OK, NULL);
2243 else
2245 /* Mixer asks for more input right after preroll too, before renderer finished running state transition.
2246 Mark such streams here, and issue requests later in OnClockStart(). */
2247 renderer->streams[idx]->flags |= EVR_STREAM_SAMPLE_NEEDED;
2250 else if (event == EC_DISPLAY_CHANGED)
2252 for (idx = 0; idx < renderer->stream_count; ++idx)
2253 IMFMediaEventQueue_QueueEventParamVar(renderer->streams[idx]->event_queue,
2254 MEStreamSinkDeviceChanged, &GUID_NULL, S_OK, NULL);
2256 else if (event >= EC_USER)
2258 PROPVARIANT code;
2260 code.vt = VT_I4;
2261 code.lVal = event;
2262 hr = IMFMediaEventQueue_QueueEventParamVar(renderer->event_queue, MERendererEvent,
2263 &GUID_NULL, S_OK, &code);
2265 else
2267 WARN("Unhandled event %d.\n", event);
2268 hr = MF_E_UNEXPECTED;
2271 LeaveCriticalSection(&renderer->cs);
2273 return hr;
2276 static const IMediaEventSinkVtbl media_event_sink_vtbl =
2278 video_renderer_event_sink_QueryInterface,
2279 video_renderer_event_sink_AddRef,
2280 video_renderer_event_sink_Release,
2281 video_renderer_event_sink_Notify,
2284 static HRESULT WINAPI video_renderer_attributes_QueryInterface(IMFAttributes *iface, REFIID riid, void **obj)
2286 struct video_renderer *renderer = impl_from_IMFAttributes(iface);
2287 return IMFMediaSink_QueryInterface(&renderer->IMFMediaSink_iface, riid, obj);
2290 static ULONG WINAPI video_renderer_attributes_AddRef(IMFAttributes *iface)
2292 struct video_renderer *renderer = impl_from_IMFAttributes(iface);
2293 return IMFMediaSink_AddRef(&renderer->IMFMediaSink_iface);
2296 static ULONG WINAPI video_renderer_attributes_Release(IMFAttributes *iface)
2298 struct video_renderer *renderer = impl_from_IMFAttributes(iface);
2299 return IMFMediaSink_Release(&renderer->IMFMediaSink_iface);
2302 static HRESULT WINAPI video_renderer_attributes_GetItem(IMFAttributes *iface, REFGUID key, PROPVARIANT *value)
2304 struct video_renderer *renderer = impl_from_IMFAttributes(iface);
2306 TRACE("%p, %s, %p.\n", iface, debugstr_guid(key), value);
2308 return IMFAttributes_GetItem(renderer->attributes, key, value);
2311 static HRESULT WINAPI video_renderer_attributes_GetItemType(IMFAttributes *iface, REFGUID key, MF_ATTRIBUTE_TYPE *type)
2313 struct video_renderer *renderer = impl_from_IMFAttributes(iface);
2315 TRACE("%p, %s, %p.\n", iface, debugstr_guid(key), type);
2317 return IMFAttributes_GetItemType(renderer->attributes, key, type);
2320 static HRESULT WINAPI video_renderer_attributes_CompareItem(IMFAttributes *iface, REFGUID key, REFPROPVARIANT value,
2321 BOOL *result)
2323 struct video_renderer *renderer = impl_from_IMFAttributes(iface);
2325 TRACE("%p, %s, %p, %p.\n", iface, debugstr_guid(key), value, result);
2327 return IMFAttributes_CompareItem(renderer->attributes, key, value, result);
2330 static HRESULT WINAPI video_renderer_attributes_Compare(IMFAttributes *iface, IMFAttributes *theirs,
2331 MF_ATTRIBUTES_MATCH_TYPE type, BOOL *result)
2333 struct video_renderer *renderer = impl_from_IMFAttributes(iface);
2335 TRACE("%p, %p, %d, %p.\n", iface, theirs, type, result);
2337 return IMFAttributes_Compare(renderer->attributes, theirs, type, result);
2340 static HRESULT WINAPI video_renderer_attributes_GetUINT32(IMFAttributes *iface, REFGUID key, UINT32 *value)
2342 struct video_renderer *renderer = impl_from_IMFAttributes(iface);
2344 TRACE("%p, %s, %p.\n", iface, debugstr_guid(key), value);
2346 return IMFAttributes_GetUINT32(renderer->attributes, key, value);
2349 static HRESULT WINAPI video_renderer_attributes_GetUINT64(IMFAttributes *iface, REFGUID key, UINT64 *value)
2351 struct video_renderer *renderer = impl_from_IMFAttributes(iface);
2353 TRACE("%p, %s, %p.\n", iface, debugstr_guid(key), value);
2355 return IMFAttributes_GetUINT64(renderer->attributes, key, value);
2358 static HRESULT WINAPI video_renderer_attributes_GetDouble(IMFAttributes *iface, REFGUID key, double *value)
2360 struct video_renderer *renderer = impl_from_IMFAttributes(iface);
2362 TRACE("%p, %s, %p.\n", iface, debugstr_guid(key), value);
2364 return IMFAttributes_GetDouble(renderer->attributes, key, value);
2367 static HRESULT WINAPI video_renderer_attributes_GetGUID(IMFAttributes *iface, REFGUID key, GUID *value)
2369 struct video_renderer *renderer = impl_from_IMFAttributes(iface);
2371 TRACE("%p, %s, %p.\n", iface, debugstr_guid(key), value);
2373 return IMFAttributes_GetGUID(renderer->attributes, key, value);
2376 static HRESULT WINAPI video_renderer_attributes_GetStringLength(IMFAttributes *iface, REFGUID key,
2377 UINT32 *length)
2379 struct video_renderer *renderer = impl_from_IMFAttributes(iface);
2381 TRACE("%p, %s, %p.\n", iface, debugstr_guid(key), length);
2383 return IMFAttributes_GetStringLength(renderer->attributes, key, length);
2386 static HRESULT WINAPI video_renderer_attributes_GetString(IMFAttributes *iface, REFGUID key, WCHAR *value,
2387 UINT32 size, UINT32 *length)
2389 struct video_renderer *renderer = impl_from_IMFAttributes(iface);
2391 TRACE("%p, %s, %p, %u, %p.\n", iface, debugstr_guid(key), value, size, length);
2393 return IMFAttributes_GetString(renderer->attributes, key, value, size, length);
2396 static HRESULT WINAPI video_renderer_attributes_GetAllocatedString(IMFAttributes *iface, REFGUID key,
2397 WCHAR **value, UINT32 *length)
2399 struct video_renderer *renderer = impl_from_IMFAttributes(iface);
2401 TRACE("%p, %s, %p, %p.\n", iface, debugstr_guid(key), value, length);
2403 return IMFAttributes_GetAllocatedString(renderer->attributes, key, value, length);
2406 static HRESULT WINAPI video_renderer_attributes_GetBlobSize(IMFAttributes *iface, REFGUID key, UINT32 *size)
2408 struct video_renderer *renderer = impl_from_IMFAttributes(iface);
2410 TRACE("%p, %s, %p.\n", iface, debugstr_guid(key), size);
2412 return IMFAttributes_GetBlobSize(renderer->attributes, key, size);
2415 static HRESULT WINAPI video_renderer_attributes_GetBlob(IMFAttributes *iface, REFGUID key, UINT8 *buf,
2416 UINT32 bufsize, UINT32 *blobsize)
2418 struct video_renderer *renderer = impl_from_IMFAttributes(iface);
2420 TRACE("%p, %s, %p, %u, %p.\n", iface, debugstr_guid(key), buf, bufsize, blobsize);
2422 return IMFAttributes_GetBlob(renderer->attributes, key, buf, bufsize, blobsize);
2425 static HRESULT WINAPI video_renderer_attributes_GetAllocatedBlob(IMFAttributes *iface, REFGUID key,
2426 UINT8 **buf, UINT32 *size)
2428 struct video_renderer *renderer = impl_from_IMFAttributes(iface);
2430 TRACE("%p, %s, %p, %p.\n", iface, debugstr_guid(key), buf, size);
2432 return IMFAttributes_GetAllocatedBlob(renderer->attributes, key, buf, size);
2435 static HRESULT WINAPI video_renderer_attributes_GetUnknown(IMFAttributes *iface, REFGUID key, REFIID riid, void **out)
2437 struct video_renderer *renderer = impl_from_IMFAttributes(iface);
2439 TRACE("%p, %s, %s, %p.\n", iface, debugstr_guid(key), debugstr_guid(riid), out);
2441 return IMFAttributes_GetUnknown(renderer->attributes, key, riid, out);
2444 static HRESULT WINAPI video_renderer_attributes_SetItem(IMFAttributes *iface, REFGUID key, REFPROPVARIANT value)
2446 struct video_renderer *renderer = impl_from_IMFAttributes(iface);
2448 TRACE("%p, %s, %p.\n", iface, debugstr_guid(key), value);
2450 return IMFAttributes_SetItem(renderer->attributes, key, value);
2453 static HRESULT WINAPI video_renderer_attributes_DeleteItem(IMFAttributes *iface, REFGUID key)
2455 struct video_renderer *renderer = impl_from_IMFAttributes(iface);
2457 TRACE("%p, %s.\n", iface, debugstr_guid(key));
2459 return IMFAttributes_DeleteItem(renderer->attributes, key);
2462 static HRESULT WINAPI video_renderer_attributes_DeleteAllItems(IMFAttributes *iface)
2464 struct video_renderer *renderer = impl_from_IMFAttributes(iface);
2466 TRACE("%p.\n", iface);
2468 return IMFAttributes_DeleteAllItems(renderer->attributes);
2471 static HRESULT WINAPI video_renderer_attributes_SetUINT32(IMFAttributes *iface, REFGUID key, UINT32 value)
2473 struct video_renderer *renderer = impl_from_IMFAttributes(iface);
2475 TRACE("%p, %s, %u.\n", iface, debugstr_guid(key), value);
2477 return IMFAttributes_SetUINT32(renderer->attributes, key, value);
2480 static HRESULT WINAPI video_renderer_attributes_SetUINT64(IMFAttributes *iface, REFGUID key, UINT64 value)
2482 struct video_renderer *renderer = impl_from_IMFAttributes(iface);
2484 TRACE("%p, %s, %s.\n", iface, debugstr_guid(key), wine_dbgstr_longlong(value));
2486 return IMFAttributes_SetUINT64(renderer->attributes, key, value);
2489 static HRESULT WINAPI video_renderer_attributes_SetDouble(IMFAttributes *iface, REFGUID key, double value)
2491 struct video_renderer *renderer = impl_from_IMFAttributes(iface);
2493 TRACE("%p, %s, %f.\n", iface, debugstr_guid(key), value);
2495 return IMFAttributes_SetDouble(renderer->attributes, key, value);
2498 static HRESULT WINAPI video_renderer_attributes_SetGUID(IMFAttributes *iface, REFGUID key, REFGUID value)
2500 struct video_renderer *renderer = impl_from_IMFAttributes(iface);
2502 TRACE("%p, %s, %s.\n", iface, debugstr_guid(key), debugstr_guid(value));
2504 return IMFAttributes_SetGUID(renderer->attributes, key, value);
2507 static HRESULT WINAPI video_renderer_attributes_SetString(IMFAttributes *iface, REFGUID key,
2508 const WCHAR *value)
2510 struct video_renderer *renderer = impl_from_IMFAttributes(iface);
2512 TRACE("%p, %s, %s.\n", iface, debugstr_guid(key), debugstr_w(value));
2514 return IMFAttributes_SetString(renderer->attributes, key, value);
2517 static HRESULT WINAPI video_renderer_attributes_SetBlob(IMFAttributes *iface, REFGUID key,
2518 const UINT8 *buf, UINT32 size)
2520 struct video_renderer *renderer = impl_from_IMFAttributes(iface);
2522 TRACE("%p, %s, %p, %u.\n", iface, debugstr_guid(key), buf, size);
2524 return IMFAttributes_SetBlob(renderer->attributes, key, buf, size);
2527 static HRESULT WINAPI video_renderer_attributes_SetUnknown(IMFAttributes *iface, REFGUID key,
2528 IUnknown *unknown)
2530 struct video_renderer *renderer = impl_from_IMFAttributes(iface);
2532 TRACE("%p, %s, %p.\n", iface, debugstr_guid(key), unknown);
2534 return IMFAttributes_SetUnknown(renderer->attributes, key, unknown);
2537 static HRESULT WINAPI video_renderer_attributes_LockStore(IMFAttributes *iface)
2539 struct video_renderer *renderer = impl_from_IMFAttributes(iface);
2541 TRACE("%p.\n", iface);
2543 return IMFAttributes_LockStore(renderer->attributes);
2546 static HRESULT WINAPI video_renderer_attributes_UnlockStore(IMFAttributes *iface)
2548 struct video_renderer *renderer = impl_from_IMFAttributes(iface);
2550 TRACE("%p.\n", iface);
2552 return IMFAttributes_UnlockStore(renderer->attributes);
2555 static HRESULT WINAPI video_renderer_attributes_GetCount(IMFAttributes *iface, UINT32 *count)
2557 struct video_renderer *renderer = impl_from_IMFAttributes(iface);
2559 TRACE("%p, %p.\n", iface, count);
2561 return IMFAttributes_GetCount(renderer->attributes, count);
2564 static HRESULT WINAPI video_renderer_attributes_GetItemByIndex(IMFAttributes *iface, UINT32 index,
2565 GUID *key, PROPVARIANT *value)
2567 struct video_renderer *renderer = impl_from_IMFAttributes(iface);
2569 TRACE("%p, %u, %p, %p.\n", iface, index, key, value);
2571 return IMFAttributes_GetItemByIndex(renderer->attributes, index, key, value);
2574 static HRESULT WINAPI video_renderer_attributes_CopyAllItems(IMFAttributes *iface, IMFAttributes *dest)
2576 struct video_renderer *renderer = impl_from_IMFAttributes(iface);
2578 TRACE("%p, %p.\n", iface, dest);
2580 return IMFAttributes_CopyAllItems(renderer->attributes, dest);
2583 static const IMFAttributesVtbl video_renderer_attributes_vtbl =
2585 video_renderer_attributes_QueryInterface,
2586 video_renderer_attributes_AddRef,
2587 video_renderer_attributes_Release,
2588 video_renderer_attributes_GetItem,
2589 video_renderer_attributes_GetItemType,
2590 video_renderer_attributes_CompareItem,
2591 video_renderer_attributes_Compare,
2592 video_renderer_attributes_GetUINT32,
2593 video_renderer_attributes_GetUINT64,
2594 video_renderer_attributes_GetDouble,
2595 video_renderer_attributes_GetGUID,
2596 video_renderer_attributes_GetStringLength,
2597 video_renderer_attributes_GetString,
2598 video_renderer_attributes_GetAllocatedString,
2599 video_renderer_attributes_GetBlobSize,
2600 video_renderer_attributes_GetBlob,
2601 video_renderer_attributes_GetAllocatedBlob,
2602 video_renderer_attributes_GetUnknown,
2603 video_renderer_attributes_SetItem,
2604 video_renderer_attributes_DeleteItem,
2605 video_renderer_attributes_DeleteAllItems,
2606 video_renderer_attributes_SetUINT32,
2607 video_renderer_attributes_SetUINT64,
2608 video_renderer_attributes_SetDouble,
2609 video_renderer_attributes_SetGUID,
2610 video_renderer_attributes_SetString,
2611 video_renderer_attributes_SetBlob,
2612 video_renderer_attributes_SetUnknown,
2613 video_renderer_attributes_LockStore,
2614 video_renderer_attributes_UnlockStore,
2615 video_renderer_attributes_GetCount,
2616 video_renderer_attributes_GetItemByIndex,
2617 video_renderer_attributes_CopyAllItems,
2620 static HRESULT WINAPI video_renderer_quality_advise_QueryInterface(IMFQualityAdvise *iface, REFIID riid, void **out)
2622 struct video_renderer *renderer = impl_from_IMFQualityAdvise(iface);
2623 return IMFMediaSink_QueryInterface(&renderer->IMFMediaSink_iface, riid, out);
2626 static ULONG WINAPI video_renderer_quality_advise_AddRef(IMFQualityAdvise *iface)
2628 struct video_renderer *renderer = impl_from_IMFQualityAdvise(iface);
2629 return IMFMediaSink_AddRef(&renderer->IMFMediaSink_iface);
2632 static ULONG WINAPI video_renderer_quality_Release(IMFQualityAdvise *iface)
2634 struct video_renderer *renderer = impl_from_IMFQualityAdvise(iface);
2635 return IMFMediaSink_Release(&renderer->IMFMediaSink_iface);
2638 static HRESULT WINAPI video_renderer_quality_advise_SetDropMode(IMFQualityAdvise *iface,
2639 MF_QUALITY_DROP_MODE mode)
2641 FIXME("%p, %u.\n", iface, mode);
2643 return E_NOTIMPL;
2646 static HRESULT WINAPI video_renderer_quality_advise_SetQualityLevel(IMFQualityAdvise *iface,
2647 MF_QUALITY_LEVEL level)
2649 FIXME("%p, %u.\n", iface, level);
2651 return E_NOTIMPL;
2654 static HRESULT WINAPI video_renderer_quality_advise_GetDropMode(IMFQualityAdvise *iface,
2655 MF_QUALITY_DROP_MODE *mode)
2657 FIXME("%p, %p.\n", iface, mode);
2659 return E_NOTIMPL;
2662 static HRESULT WINAPI video_renderer_quality_advise_GetQualityLevel(IMFQualityAdvise *iface,
2663 MF_QUALITY_LEVEL *level)
2665 FIXME("%p, %p.\n", iface, level);
2667 return E_NOTIMPL;
2670 static HRESULT WINAPI video_renderer_quality_advise_DropTime(IMFQualityAdvise *iface, LONGLONG interval)
2672 FIXME("%p, %s.\n", iface, wine_dbgstr_longlong(interval));
2674 return E_NOTIMPL;
2677 static const IMFQualityAdviseVtbl video_renderer_quality_advise_vtbl =
2679 video_renderer_quality_advise_QueryInterface,
2680 video_renderer_quality_advise_AddRef,
2681 video_renderer_quality_Release,
2682 video_renderer_quality_advise_SetDropMode,
2683 video_renderer_quality_advise_SetQualityLevel,
2684 video_renderer_quality_advise_GetDropMode,
2685 video_renderer_quality_advise_GetQualityLevel,
2686 video_renderer_quality_advise_DropTime,
2689 static HRESULT WINAPI video_renderer_rate_support_QueryInterface(IMFRateSupport *iface, REFIID riid, void **out)
2691 struct video_renderer *renderer = impl_from_IMFRateSupport(iface);
2692 return IMFMediaSink_QueryInterface(&renderer->IMFMediaSink_iface, riid, out);
2695 static ULONG WINAPI video_renderer_rate_support_AddRef(IMFRateSupport *iface)
2697 struct video_renderer *renderer = impl_from_IMFRateSupport(iface);
2698 return IMFMediaSink_AddRef(&renderer->IMFMediaSink_iface);
2701 static ULONG WINAPI video_renderer_rate_support_Release(IMFRateSupport *iface)
2703 struct video_renderer *renderer = impl_from_IMFRateSupport(iface);
2704 return IMFMediaSink_Release(&renderer->IMFMediaSink_iface);
2707 static HRESULT WINAPI video_renderer_rate_support_GetSlowestRate(IMFRateSupport *iface, MFRATE_DIRECTION direction,
2708 BOOL thin, float *rate)
2710 struct video_renderer *renderer = impl_from_IMFRateSupport(iface);
2712 TRACE("%p, %d, %d, %p.\n", iface, direction, thin, rate);
2714 if (renderer->flags & EVR_SHUT_DOWN)
2715 return MF_E_SHUTDOWN;
2717 *rate = 0.0f;
2719 return S_OK;
2722 static HRESULT WINAPI video_renderer_rate_support_GetFastestRate(IMFRateSupport *iface, MFRATE_DIRECTION direction,
2723 BOOL thin, float *rate)
2725 struct video_renderer *renderer = impl_from_IMFRateSupport(iface);
2727 TRACE("%p, %d, %d, %p.\n", iface, direction, thin, rate);
2729 return renderer->flags & EVR_SHUT_DOWN ? MF_E_SHUTDOWN : MF_E_INVALIDREQUEST;
2732 static HRESULT WINAPI video_renderer_rate_support_IsRateSupported(IMFRateSupport *iface, BOOL thin, float rate,
2733 float *nearest_supported_rate)
2735 FIXME("%p, %d, %f, %p.\n", iface, thin, rate, nearest_supported_rate);
2737 return E_NOTIMPL;
2740 static const IMFRateSupportVtbl video_renderer_rate_support_vtbl =
2742 video_renderer_rate_support_QueryInterface,
2743 video_renderer_rate_support_AddRef,
2744 video_renderer_rate_support_Release,
2745 video_renderer_rate_support_GetSlowestRate,
2746 video_renderer_rate_support_GetFastestRate,
2747 video_renderer_rate_support_IsRateSupported,
2750 static HRESULT evr_create_object(IMFAttributes *attributes, void *user_context, IUnknown **obj)
2752 struct video_renderer *object;
2753 IMFVideoPresenter *presenter = NULL;
2754 IMFTransform *mixer = NULL;
2755 HRESULT hr;
2757 TRACE("%p, %p, %p.\n", attributes, user_context, obj);
2759 if (!(object = heap_alloc_zero(sizeof(*object))))
2760 return E_OUTOFMEMORY;
2762 object->IMFMediaSink_iface.lpVtbl = &video_renderer_sink_vtbl;
2763 object->IMFMediaSinkPreroll_iface.lpVtbl = &video_renderer_preroll_vtbl;
2764 object->IMFVideoRenderer_iface.lpVtbl = &video_renderer_vtbl;
2765 object->IMFMediaEventGenerator_iface.lpVtbl = &video_renderer_events_vtbl;
2766 object->IMFClockStateSink_iface.lpVtbl = &video_renderer_clock_sink_vtbl;
2767 object->IMFGetService_iface.lpVtbl = &video_renderer_get_service_vtbl;
2768 object->IMFTopologyServiceLookup_iface.lpVtbl = &video_renderer_service_lookup_vtbl;
2769 object->IMediaEventSink_iface.lpVtbl = &media_event_sink_vtbl;
2770 object->IMFAttributes_iface.lpVtbl = &video_renderer_attributes_vtbl;
2771 object->IMFQualityAdvise_iface.lpVtbl = &video_renderer_quality_advise_vtbl;
2772 object->IMFRateSupport_iface.lpVtbl = &video_renderer_rate_support_vtbl;
2773 object->refcount = 1;
2774 InitializeCriticalSection(&object->cs);
2776 if (FAILED(hr = MFCreateEventQueue(&object->event_queue)))
2777 goto failed;
2779 if (FAILED(hr = MFCreateAttributes(&object->attributes, 0)))
2780 goto failed;
2782 /* Create mixer and presenter. */
2783 if (FAILED(hr = video_renderer_create_mixer(attributes, &mixer)))
2784 goto failed;
2786 if (FAILED(hr = video_renderer_create_presenter(object, attributes, &presenter)))
2787 goto failed;
2789 if (FAILED(hr = video_renderer_initialize(object, mixer, presenter)))
2790 goto failed;
2792 IMFTransform_Release(mixer);
2793 IMFVideoPresenter_Release(presenter);
2795 /* Default attributes */
2796 IMFAttributes_SetUINT32(object->attributes, &EVRConfig_ForceBob, 0);
2797 IMFAttributes_SetUINT32(object->attributes, &EVRConfig_AllowDropToBob, 0);
2798 IMFAttributes_SetUINT32(object->attributes, &EVRConfig_ForceThrottle, 0);
2799 IMFAttributes_SetUINT32(object->attributes, &EVRConfig_AllowDropToThrottle, 0);
2800 IMFAttributes_SetUINT32(object->attributes, &EVRConfig_ForceHalfInterlace, 0);
2801 IMFAttributes_SetUINT32(object->attributes, &EVRConfig_AllowDropToHalfInterlace, 0);
2802 IMFAttributes_SetUINT32(object->attributes, &EVRConfig_ForceScaling, 0);
2803 IMFAttributes_SetUINT32(object->attributes, &EVRConfig_AllowScaling, 0);
2804 IMFAttributes_SetUINT32(object->attributes, &EVRConfig_ForceBatching, 0);
2805 IMFAttributes_SetUINT32(object->attributes, &EVRConfig_AllowBatching, 0);
2807 *obj = (IUnknown *)&object->IMFMediaSink_iface;
2809 return S_OK;
2811 failed:
2813 if (mixer)
2814 IMFTransform_Release(mixer);
2816 if (presenter)
2817 IMFVideoPresenter_Release(presenter);
2819 video_renderer_release_services(object);
2820 IMFMediaSink_Release(&object->IMFMediaSink_iface);
2822 return hr;
2825 static void evr_shutdown_object(void *user_context, IUnknown *obj)
2827 IMFMediaSink *sink;
2829 if (SUCCEEDED(IUnknown_QueryInterface(obj, &IID_IMFMediaSink, (void **)&sink)))
2831 IMFMediaSink_Shutdown(sink);
2832 IMFMediaSink_Release(sink);
2836 static const struct activate_funcs evr_activate_funcs =
2838 .create_object = evr_create_object,
2839 .shutdown_object = evr_shutdown_object,
2842 /***********************************************************************
2843 * MFCreateVideoRendererActivate (mf.@)
2845 HRESULT WINAPI MFCreateVideoRendererActivate(HWND hwnd, IMFActivate **activate)
2847 HRESULT hr;
2849 TRACE("%p, %p.\n", hwnd, activate);
2851 if (!activate)
2852 return E_POINTER;
2854 hr = create_activation_object(NULL, &evr_activate_funcs, activate);
2855 if (SUCCEEDED(hr))
2856 IMFActivate_SetUINT64(*activate, &MF_ACTIVATE_VIDEO_WINDOW, (ULONG_PTR)hwnd);
2858 return hr;
2861 /***********************************************************************
2862 * MFCreateVideoRenderer (mf.@)
2864 HRESULT WINAPI MFCreateVideoRenderer(REFIID riid, void **renderer)
2866 IUnknown *obj;
2867 HRESULT hr;
2869 TRACE("%s, %p.\n", debugstr_guid(riid), renderer);
2871 *renderer = NULL;
2873 if (SUCCEEDED(hr = evr_create_object(NULL, NULL, &obj)))
2875 hr = IUnknown_QueryInterface(obj, riid, renderer);
2876 IUnknown_Release(obj);
2879 return hr;