mf/evr: Derive stream attributes from mixer input attributes.
[wine.git] / dlls / mf / evr.c
blob47a506a94c64d1902c96ece8df7b566b47e9f04e
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,
52 struct video_renderer;
54 struct video_stream
56 IMFStreamSink IMFStreamSink_iface;
57 IMFMediaTypeHandler IMFMediaTypeHandler_iface;
58 IMFGetService IMFGetService_iface;
59 IMFAttributes IMFAttributes_iface;
60 LONG refcount;
61 unsigned int id;
62 unsigned int flags;
63 struct video_renderer *parent;
64 IMFMediaEventQueue *event_queue;
65 IMFVideoSampleAllocator *allocator;
66 IMFAttributes *attributes;
67 CRITICAL_SECTION cs;
70 struct video_renderer
72 IMFMediaSink IMFMediaSink_iface;
73 IMFMediaSinkPreroll IMFMediaSinkPreroll_iface;
74 IMFVideoRenderer IMFVideoRenderer_iface;
75 IMFClockStateSink IMFClockStateSink_iface;
76 IMFMediaEventGenerator IMFMediaEventGenerator_iface;
77 IMFGetService IMFGetService_iface;
78 IMFTopologyServiceLookup IMFTopologyServiceLookup_iface;
79 IMediaEventSink IMediaEventSink_iface;
80 IMFAttributes IMFAttributes_iface;
81 IMFQualityAdvise IMFQualityAdvise_iface;
82 LONG refcount;
84 IMFMediaEventQueue *event_queue;
85 IMFAttributes *attributes;
86 IMFPresentationClock *clock;
88 IMFTransform *mixer;
89 IMFVideoPresenter *presenter;
90 HWND window;
91 IUnknown *device_manager;
92 unsigned int flags;
93 unsigned int state;
95 struct video_stream **streams;
96 size_t stream_size;
97 size_t stream_count;
99 CRITICAL_SECTION cs;
102 static struct video_renderer *impl_from_IMFMediaSink(IMFMediaSink *iface)
104 return CONTAINING_RECORD(iface, struct video_renderer, IMFMediaSink_iface);
107 static struct video_renderer *impl_from_IMFMediaSinkPreroll(IMFMediaSinkPreroll *iface)
109 return CONTAINING_RECORD(iface, struct video_renderer, IMFMediaSinkPreroll_iface);
112 static struct video_renderer *impl_from_IMFVideoRenderer(IMFVideoRenderer *iface)
114 return CONTAINING_RECORD(iface, struct video_renderer, IMFVideoRenderer_iface);
117 static struct video_renderer *impl_from_IMFMediaEventGenerator(IMFMediaEventGenerator *iface)
119 return CONTAINING_RECORD(iface, struct video_renderer, IMFMediaEventGenerator_iface);
122 static struct video_renderer *impl_from_IMFClockStateSink(IMFClockStateSink *iface)
124 return CONTAINING_RECORD(iface, struct video_renderer, IMFClockStateSink_iface);
127 static struct video_renderer *impl_from_IMFGetService(IMFGetService *iface)
129 return CONTAINING_RECORD(iface, struct video_renderer, IMFGetService_iface);
132 static struct video_renderer *impl_from_IMFTopologyServiceLookup(IMFTopologyServiceLookup *iface)
134 return CONTAINING_RECORD(iface, struct video_renderer, IMFTopologyServiceLookup_iface);
137 static struct video_renderer *impl_from_IMediaEventSink(IMediaEventSink *iface)
139 return CONTAINING_RECORD(iface, struct video_renderer, IMediaEventSink_iface);
142 static struct video_renderer *impl_from_IMFAttributes(IMFAttributes *iface)
144 return CONTAINING_RECORD(iface, struct video_renderer, IMFAttributes_iface);
147 static struct video_renderer *impl_from_IMFQualityAdvise(IMFQualityAdvise *iface)
149 return CONTAINING_RECORD(iface, struct video_renderer, IMFQualityAdvise_iface);
152 static struct video_stream *impl_from_IMFStreamSink(IMFStreamSink *iface)
154 return CONTAINING_RECORD(iface, struct video_stream, IMFStreamSink_iface);
157 static struct video_stream *impl_from_IMFMediaTypeHandler(IMFMediaTypeHandler *iface)
159 return CONTAINING_RECORD(iface, struct video_stream, IMFMediaTypeHandler_iface);
162 static struct video_stream *impl_from_stream_IMFGetService(IMFGetService *iface)
164 return CONTAINING_RECORD(iface, struct video_stream, IMFGetService_iface);
167 static struct video_stream *impl_from_stream_IMFAttributes(IMFAttributes *iface)
169 return CONTAINING_RECORD(iface, struct video_stream, IMFAttributes_iface);
172 static void video_renderer_release_services(struct video_renderer *renderer)
174 IMFTopologyServiceLookupClient *lookup_client;
176 if (renderer->flags & EVR_MIXER_INITED_SERVICES && SUCCEEDED(IMFTransform_QueryInterface(renderer->mixer,
177 &IID_IMFTopologyServiceLookupClient, (void **)&lookup_client)))
179 IMFTopologyServiceLookupClient_ReleaseServicePointers(lookup_client);
180 IMFTopologyServiceLookupClient_Release(lookup_client);
181 renderer->flags &= ~EVR_MIXER_INITED_SERVICES;
184 if (renderer->flags & EVR_PRESENTER_INITED_SERVICES && SUCCEEDED(IMFVideoPresenter_QueryInterface(renderer->presenter,
185 &IID_IMFTopologyServiceLookupClient, (void **)&lookup_client)))
187 IMFTopologyServiceLookupClient_ReleaseServicePointers(lookup_client);
188 IMFTopologyServiceLookupClient_Release(lookup_client);
189 renderer->flags &= ~EVR_PRESENTER_INITED_SERVICES;
193 static HRESULT WINAPI video_stream_sink_QueryInterface(IMFStreamSink *iface, REFIID riid, void **obj)
195 struct video_stream *stream = impl_from_IMFStreamSink(iface);
197 TRACE("%p, %s, %p.\n", iface, debugstr_guid(riid), obj);
199 if (IsEqualIID(riid, &IID_IMFStreamSink) ||
200 IsEqualIID(riid, &IID_IMFMediaEventGenerator) ||
201 IsEqualIID(riid, &IID_IUnknown))
203 *obj = iface;
205 else if (IsEqualIID(riid, &IID_IMFMediaTypeHandler))
207 *obj = &stream->IMFMediaTypeHandler_iface;
209 else if (IsEqualIID(riid, &IID_IMFGetService))
211 *obj = &stream->IMFGetService_iface;
213 else if (IsEqualIID(riid, &IID_IMFAttributes))
215 *obj = &stream->IMFAttributes_iface;
217 else
219 WARN("Unsupported interface %s.\n", debugstr_guid(riid));
220 *obj = NULL;
221 return E_NOINTERFACE;
224 IUnknown_AddRef((IUnknown *)*obj);
226 return S_OK;
229 static ULONG WINAPI video_stream_sink_AddRef(IMFStreamSink *iface)
231 struct video_stream *stream = impl_from_IMFStreamSink(iface);
232 ULONG refcount = InterlockedIncrement(&stream->refcount);
234 TRACE("%p, refcount %u.\n", iface, refcount);
236 return refcount;
239 static ULONG WINAPI video_stream_sink_Release(IMFStreamSink *iface)
241 struct video_stream *stream = impl_from_IMFStreamSink(iface);
242 ULONG refcount = InterlockedDecrement(&stream->refcount);
244 if (!refcount)
246 if (stream->event_queue)
247 IMFMediaEventQueue_Release(stream->event_queue);
248 if (stream->attributes)
249 IMFAttributes_Release(stream->attributes);
250 if (stream->allocator)
251 IMFVideoSampleAllocator_Release(stream->allocator);
252 DeleteCriticalSection(&stream->cs);
253 heap_free(stream);
256 return refcount;
259 static HRESULT WINAPI video_stream_sink_GetEvent(IMFStreamSink *iface, DWORD flags, IMFMediaEvent **event)
261 struct video_stream *stream = impl_from_IMFStreamSink(iface);
263 TRACE("%p, %#x, %p.\n", iface, flags, event);
265 return IMFMediaEventQueue_GetEvent(stream->event_queue, flags, event);
268 static HRESULT WINAPI video_stream_sink_BeginGetEvent(IMFStreamSink *iface, IMFAsyncCallback *callback, IUnknown *state)
270 struct video_stream *stream = impl_from_IMFStreamSink(iface);
272 TRACE("%p, %p, %p.\n", iface, callback, state);
274 return IMFMediaEventQueue_BeginGetEvent(stream->event_queue, callback, state);
277 static HRESULT WINAPI video_stream_sink_EndGetEvent(IMFStreamSink *iface, IMFAsyncResult *result,
278 IMFMediaEvent **event)
280 struct video_stream *stream = impl_from_IMFStreamSink(iface);
282 TRACE("%p, %p, %p.\n", iface, result, event);
284 return IMFMediaEventQueue_EndGetEvent(stream->event_queue, result, event);
287 static HRESULT WINAPI video_stream_sink_QueueEvent(IMFStreamSink *iface, MediaEventType event_type,
288 REFGUID ext_type, HRESULT hr, const PROPVARIANT *value)
290 struct video_stream *stream = impl_from_IMFStreamSink(iface);
292 TRACE("%p, %d, %s, %#x, %p.\n", iface, event_type, debugstr_guid(ext_type), hr, value);
294 return IMFMediaEventQueue_QueueEventParamVar(stream->event_queue, event_type, ext_type, hr, value);
297 static HRESULT WINAPI video_stream_sink_GetMediaSink(IMFStreamSink *iface, IMFMediaSink **sink)
299 struct video_stream *stream = impl_from_IMFStreamSink(iface);
300 HRESULT hr = S_OK;
302 TRACE("%p, %p.\n", iface, sink);
304 EnterCriticalSection(&stream->cs);
305 if (!stream->parent)
306 hr = MF_E_STREAMSINK_REMOVED;
307 else if (!sink)
308 hr = E_POINTER;
309 else
311 *sink = &stream->parent->IMFMediaSink_iface;
312 IMFMediaSink_AddRef(*sink);
314 LeaveCriticalSection(&stream->cs);
316 return hr;
319 static HRESULT WINAPI video_stream_sink_GetIdentifier(IMFStreamSink *iface, DWORD *id)
321 struct video_stream *stream = impl_from_IMFStreamSink(iface);
323 TRACE("%p, %p.\n", iface, id);
325 if (!stream->parent)
326 return MF_E_STREAMSINK_REMOVED;
328 if (!id)
329 return E_INVALIDARG;
331 *id = stream->id;
333 return S_OK;
336 static HRESULT WINAPI video_stream_sink_GetMediaTypeHandler(IMFStreamSink *iface, IMFMediaTypeHandler **handler)
338 struct video_stream *stream = impl_from_IMFStreamSink(iface);
340 TRACE("%p, %p.\n", iface, handler);
342 if (!handler)
343 return E_POINTER;
345 if (!stream->parent)
346 return MF_E_STREAMSINK_REMOVED;
348 *handler = &stream->IMFMediaTypeHandler_iface;
349 IMFMediaTypeHandler_AddRef(*handler);
351 return S_OK;
354 static HRESULT WINAPI video_stream_sink_ProcessSample(IMFStreamSink *iface, IMFSample *sample)
356 struct video_stream *stream = impl_from_IMFStreamSink(iface);
357 LONGLONG timestamp;
358 HRESULT hr = S_OK;
360 TRACE("%p, %p.\n", iface, sample);
362 EnterCriticalSection(&stream->cs);
364 if (!stream->parent)
365 hr = MF_E_STREAMSINK_REMOVED;
366 else if (!stream->parent->clock)
367 hr = MF_E_NO_CLOCK;
368 else if (FAILED(hr = IMFSample_GetSampleTime(sample, &timestamp)))
370 WARN("No sample timestamp, hr %#x.\n", hr);
372 else if (stream->parent->state == EVR_STATE_RUNNING || stream->flags & EVR_STREAM_PREROLLING)
374 if (SUCCEEDED(IMFTransform_ProcessInput(stream->parent->mixer, stream->id, sample, 0)))
375 IMFVideoPresenter_ProcessMessage(stream->parent->presenter, MFVP_MESSAGE_PROCESSINPUTNOTIFY, 0);
377 if (stream->flags & EVR_STREAM_PREROLLING)
379 IMFMediaEventQueue_QueueEventParamVar(stream->event_queue, MEStreamSinkPrerolled, &GUID_NULL, S_OK, NULL);
380 stream->flags &= ~EVR_STREAM_PREROLLING;
381 stream->flags |= EVR_STREAM_PREROLLED;
385 LeaveCriticalSection(&stream->cs);
387 return hr;
390 static HRESULT WINAPI video_stream_sink_PlaceMarker(IMFStreamSink *iface, MFSTREAMSINK_MARKER_TYPE marker_type,
391 const PROPVARIANT *marker_value, const PROPVARIANT *context_value)
393 FIXME("%p, %d, %p, %p.\n", iface, marker_type, marker_value, context_value);
395 return E_NOTIMPL;
398 static HRESULT WINAPI video_stream_sink_Flush(IMFStreamSink *iface)
400 FIXME("%p.\n", iface);
402 return E_NOTIMPL;
405 static const IMFStreamSinkVtbl video_stream_sink_vtbl =
407 video_stream_sink_QueryInterface,
408 video_stream_sink_AddRef,
409 video_stream_sink_Release,
410 video_stream_sink_GetEvent,
411 video_stream_sink_BeginGetEvent,
412 video_stream_sink_EndGetEvent,
413 video_stream_sink_QueueEvent,
414 video_stream_sink_GetMediaSink,
415 video_stream_sink_GetIdentifier,
416 video_stream_sink_GetMediaTypeHandler,
417 video_stream_sink_ProcessSample,
418 video_stream_sink_PlaceMarker,
419 video_stream_sink_Flush,
422 static HRESULT WINAPI video_stream_typehandler_QueryInterface(IMFMediaTypeHandler *iface, REFIID riid,
423 void **obj)
425 struct video_stream *stream = impl_from_IMFMediaTypeHandler(iface);
426 return IMFStreamSink_QueryInterface(&stream->IMFStreamSink_iface, riid, obj);
429 static ULONG WINAPI video_stream_typehandler_AddRef(IMFMediaTypeHandler *iface)
431 struct video_stream *stream = impl_from_IMFMediaTypeHandler(iface);
432 return IMFStreamSink_AddRef(&stream->IMFStreamSink_iface);
435 static ULONG WINAPI video_stream_typehandler_Release(IMFMediaTypeHandler *iface)
437 struct video_stream *stream = impl_from_IMFMediaTypeHandler(iface);
438 return IMFStreamSink_Release(&stream->IMFStreamSink_iface);
441 static HRESULT WINAPI video_stream_typehandler_IsMediaTypeSupported(IMFMediaTypeHandler *iface,
442 IMFMediaType *in_type, IMFMediaType **out_type)
444 struct video_stream *stream = impl_from_IMFMediaTypeHandler(iface);
445 HRESULT hr;
447 TRACE("%p, %p, %p.\n", iface, in_type, out_type);
449 if (!in_type)
450 return E_POINTER;
452 if (!stream->parent)
453 return MF_E_INVALIDMEDIATYPE;
455 if (SUCCEEDED(hr = IMFTransform_SetInputType(stream->parent->mixer, stream->id, in_type,
456 MFT_SET_TYPE_TEST_ONLY)))
458 if (out_type) *out_type = NULL;
461 return hr;
464 static HRESULT WINAPI video_stream_typehandler_GetMediaTypeCount(IMFMediaTypeHandler *iface, DWORD *count)
466 TRACE("%p, %p.\n", iface, count);
468 if (!count)
469 return E_POINTER;
471 *count = 0;
473 return S_OK;
476 static HRESULT WINAPI video_stream_typehandler_GetMediaTypeByIndex(IMFMediaTypeHandler *iface, DWORD index,
477 IMFMediaType **type)
479 TRACE("%p, %u, %p.\n", iface, index, type);
481 return MF_E_NO_MORE_TYPES;
484 static HRESULT WINAPI video_stream_typehandler_SetCurrentMediaType(IMFMediaTypeHandler *iface, IMFMediaType *type)
486 struct video_stream *stream = impl_from_IMFMediaTypeHandler(iface);
487 HRESULT hr;
489 TRACE("%p, %p.\n", iface, type);
491 if (!type)
492 return E_POINTER;
494 if (!stream->parent)
495 return MF_E_STREAMSINK_REMOVED;
497 hr = IMFTransform_SetInputType(stream->parent->mixer, stream->id, type, 0);
498 if (SUCCEEDED(hr) && !stream->id)
499 hr = IMFVideoPresenter_ProcessMessage(stream->parent->presenter, MFVP_MESSAGE_INVALIDATEMEDIATYPE, 0);
501 return hr;
504 static HRESULT WINAPI video_stream_typehandler_GetCurrentMediaType(IMFMediaTypeHandler *iface, IMFMediaType **type)
506 struct video_stream *stream = impl_from_IMFMediaTypeHandler(iface);
508 TRACE("%p, %p.\n", iface, type);
510 if (!type)
511 return E_POINTER;
513 if (!stream->parent)
514 return MF_E_STREAMSINK_REMOVED;
516 return IMFTransform_GetInputCurrentType(stream->parent->mixer, stream->id, type);
519 static HRESULT WINAPI video_stream_typehandler_GetMajorType(IMFMediaTypeHandler *iface, GUID *type)
521 struct video_stream *stream = impl_from_IMFMediaTypeHandler(iface);
523 TRACE("%p, %p.\n", iface, type);
525 if (!stream->parent)
526 return MF_E_STREAMSINK_REMOVED;
528 if (!type)
529 return E_POINTER;
531 memcpy(type, &MFMediaType_Video, sizeof(*type));
532 return S_OK;
535 static const IMFMediaTypeHandlerVtbl video_stream_type_handler_vtbl =
537 video_stream_typehandler_QueryInterface,
538 video_stream_typehandler_AddRef,
539 video_stream_typehandler_Release,
540 video_stream_typehandler_IsMediaTypeSupported,
541 video_stream_typehandler_GetMediaTypeCount,
542 video_stream_typehandler_GetMediaTypeByIndex,
543 video_stream_typehandler_SetCurrentMediaType,
544 video_stream_typehandler_GetCurrentMediaType,
545 video_stream_typehandler_GetMajorType,
548 static HRESULT WINAPI video_stream_get_service_QueryInterface(IMFGetService *iface, REFIID riid, void **obj)
550 struct video_stream *stream = impl_from_stream_IMFGetService(iface);
551 return IMFStreamSink_QueryInterface(&stream->IMFStreamSink_iface, riid, obj);
554 static ULONG WINAPI video_stream_get_service_AddRef(IMFGetService *iface)
556 struct video_stream *stream = impl_from_stream_IMFGetService(iface);
557 return IMFStreamSink_AddRef(&stream->IMFStreamSink_iface);
560 static ULONG WINAPI video_stream_get_service_Release(IMFGetService *iface)
562 struct video_stream *stream = impl_from_stream_IMFGetService(iface);
563 return IMFStreamSink_Release(&stream->IMFStreamSink_iface);
566 static HRESULT WINAPI video_stream_get_service_GetService(IMFGetService *iface, REFGUID service, REFIID riid, void **obj)
568 struct video_stream *stream = impl_from_stream_IMFGetService(iface);
569 HRESULT hr = S_OK;
571 TRACE("%p, %s, %s, %p.\n", iface, debugstr_guid(service), debugstr_guid(riid), obj);
573 if (IsEqualGUID(service, &MR_VIDEO_ACCELERATION_SERVICE))
575 if (IsEqualIID(riid, &IID_IMFVideoSampleAllocator))
577 EnterCriticalSection(&stream->cs);
579 if (!stream->allocator)
581 hr = MFCreateVideoSampleAllocator(&IID_IMFVideoSampleAllocator, (void **)&stream->allocator);
582 if (SUCCEEDED(hr))
583 hr = IMFVideoSampleAllocator_SetDirectXManager(stream->allocator, stream->parent->device_manager);
585 if (SUCCEEDED(hr))
586 hr = IMFVideoSampleAllocator_QueryInterface(stream->allocator, riid, obj);
588 LeaveCriticalSection(&stream->cs);
590 return hr;
593 return E_NOINTERFACE;
596 FIXME("Unsupported service %s.\n", debugstr_guid(service));
598 return E_NOTIMPL;
601 static const IMFGetServiceVtbl video_stream_get_service_vtbl =
603 video_stream_get_service_QueryInterface,
604 video_stream_get_service_AddRef,
605 video_stream_get_service_Release,
606 video_stream_get_service_GetService,
609 static HRESULT WINAPI video_stream_attributes_QueryInterface(IMFAttributes *iface, REFIID riid, void **obj)
611 struct video_stream *stream = impl_from_stream_IMFAttributes(iface);
612 return IMFStreamSink_QueryInterface(&stream->IMFStreamSink_iface, riid, obj);
615 static ULONG WINAPI video_stream_attributes_AddRef(IMFAttributes *iface)
617 struct video_stream *stream = impl_from_stream_IMFAttributes(iface);
618 return IMFStreamSink_AddRef(&stream->IMFStreamSink_iface);
621 static ULONG WINAPI video_stream_attributes_Release(IMFAttributes *iface)
623 struct video_stream *stream = impl_from_stream_IMFAttributes(iface);
624 return IMFStreamSink_Release(&stream->IMFStreamSink_iface);
627 static HRESULT WINAPI video_stream_attributes_GetItem(IMFAttributes *iface, REFGUID key, PROPVARIANT *value)
629 struct video_stream *stream = impl_from_stream_IMFAttributes(iface);
631 TRACE("%p, %s, %p.\n", iface, debugstr_guid(key), value);
633 return IMFAttributes_GetItem(stream->attributes, key, value);
636 static HRESULT WINAPI video_stream_attributes_GetItemType(IMFAttributes *iface, REFGUID key, MF_ATTRIBUTE_TYPE *type)
638 struct video_stream *stream = impl_from_stream_IMFAttributes(iface);
640 TRACE("%p, %s, %p.\n", iface, debugstr_guid(key), type);
642 return IMFAttributes_GetItemType(stream->attributes, key, type);
645 static HRESULT WINAPI video_stream_attributes_CompareItem(IMFAttributes *iface, REFGUID key, REFPROPVARIANT value,
646 BOOL *result)
648 struct video_stream *stream = impl_from_stream_IMFAttributes(iface);
650 TRACE("%p, %s, %p, %p.\n", iface, debugstr_guid(key), value, result);
652 return IMFAttributes_CompareItem(stream->attributes, key, value, result);
655 static HRESULT WINAPI video_stream_attributes_Compare(IMFAttributes *iface, IMFAttributes *theirs,
656 MF_ATTRIBUTES_MATCH_TYPE type, BOOL *result)
658 struct video_stream *stream = impl_from_stream_IMFAttributes(iface);
660 TRACE("%p, %p, %d, %p.\n", iface, theirs, type, result);
662 return IMFAttributes_Compare(stream->attributes, theirs, type, result);
665 static HRESULT WINAPI video_stream_attributes_GetUINT32(IMFAttributes *iface, REFGUID key, UINT32 *value)
667 struct video_stream *stream = impl_from_stream_IMFAttributes(iface);
669 TRACE("%p, %s, %p.\n", iface, debugstr_guid(key), value);
671 return IMFAttributes_GetUINT32(stream->attributes, key, value);
674 static HRESULT WINAPI video_stream_attributes_GetUINT64(IMFAttributes *iface, REFGUID key, UINT64 *value)
676 struct video_stream *stream = impl_from_stream_IMFAttributes(iface);
678 TRACE("%p, %s, %p.\n", iface, debugstr_guid(key), value);
680 return IMFAttributes_GetUINT64(stream->attributes, key, value);
683 static HRESULT WINAPI video_stream_attributes_GetDouble(IMFAttributes *iface, REFGUID key, double *value)
685 struct video_stream *stream = impl_from_stream_IMFAttributes(iface);
687 TRACE("%p, %s, %p.\n", iface, debugstr_guid(key), value);
689 return IMFAttributes_GetDouble(stream->attributes, key, value);
692 static HRESULT WINAPI video_stream_attributes_GetGUID(IMFAttributes *iface, REFGUID key, GUID *value)
694 struct video_stream *stream = impl_from_stream_IMFAttributes(iface);
696 TRACE("%p, %s, %p.\n", iface, debugstr_guid(key), value);
698 return IMFAttributes_GetGUID(stream->attributes, key, value);
701 static HRESULT WINAPI video_stream_attributes_GetStringLength(IMFAttributes *iface, REFGUID key,
702 UINT32 *length)
704 struct video_stream *stream = impl_from_stream_IMFAttributes(iface);
706 TRACE("%p, %s, %p.\n", iface, debugstr_guid(key), length);
708 return IMFAttributes_GetStringLength(stream->attributes, key, length);
711 static HRESULT WINAPI video_stream_attributes_GetString(IMFAttributes *iface, REFGUID key, WCHAR *value,
712 UINT32 size, UINT32 *length)
714 struct video_stream *stream = impl_from_stream_IMFAttributes(iface);
716 TRACE("%p, %s, %p, %u, %p.\n", iface, debugstr_guid(key), value, size, length);
718 return IMFAttributes_GetString(stream->attributes, key, value, size, length);
721 static HRESULT WINAPI video_stream_attributes_GetAllocatedString(IMFAttributes *iface, REFGUID key,
722 WCHAR **value, UINT32 *length)
724 struct video_stream *stream = impl_from_stream_IMFAttributes(iface);
726 TRACE("%p, %s, %p, %p.\n", iface, debugstr_guid(key), value, length);
728 return IMFAttributes_GetAllocatedString(stream->attributes, key, value, length);
731 static HRESULT WINAPI video_stream_attributes_GetBlobSize(IMFAttributes *iface, REFGUID key, UINT32 *size)
733 struct video_stream *stream = impl_from_stream_IMFAttributes(iface);
735 TRACE("%p, %s, %p.\n", iface, debugstr_guid(key), size);
737 return IMFAttributes_GetBlobSize(stream->attributes, key, size);
740 static HRESULT WINAPI video_stream_attributes_GetBlob(IMFAttributes *iface, REFGUID key, UINT8 *buf,
741 UINT32 bufsize, UINT32 *blobsize)
743 struct video_stream *stream = impl_from_stream_IMFAttributes(iface);
745 TRACE("%p, %s, %p, %u, %p.\n", iface, debugstr_guid(key), buf, bufsize, blobsize);
747 return IMFAttributes_GetBlob(stream->attributes, key, buf, bufsize, blobsize);
750 static HRESULT WINAPI video_stream_attributes_GetAllocatedBlob(IMFAttributes *iface, REFGUID key,
751 UINT8 **buf, UINT32 *size)
753 struct video_stream *stream = impl_from_stream_IMFAttributes(iface);
755 TRACE("%p, %s, %p, %p.\n", iface, debugstr_guid(key), buf, size);
757 return IMFAttributes_GetAllocatedBlob(stream->attributes, key, buf, size);
760 static HRESULT WINAPI video_stream_attributes_GetUnknown(IMFAttributes *iface, REFGUID key, REFIID riid, void **out)
762 struct video_stream *stream = impl_from_stream_IMFAttributes(iface);
764 TRACE("%p, %s, %s, %p.\n", iface, debugstr_guid(key), debugstr_guid(riid), out);
766 return IMFAttributes_GetUnknown(stream->attributes, key, riid, out);
769 static HRESULT WINAPI video_stream_attributes_SetItem(IMFAttributes *iface, REFGUID key, REFPROPVARIANT value)
771 struct video_stream *stream = impl_from_stream_IMFAttributes(iface);
773 TRACE("%p, %s, %p.\n", iface, debugstr_guid(key), value);
775 return IMFAttributes_SetItem(stream->attributes, key, value);
778 static HRESULT WINAPI video_stream_attributes_DeleteItem(IMFAttributes *iface, REFGUID key)
780 struct video_stream *stream = impl_from_stream_IMFAttributes(iface);
782 TRACE("%p, %s.\n", iface, debugstr_guid(key));
784 return IMFAttributes_DeleteItem(stream->attributes, key);
787 static HRESULT WINAPI video_stream_attributes_DeleteAllItems(IMFAttributes *iface)
789 struct video_stream *stream = impl_from_stream_IMFAttributes(iface);
791 TRACE("%p.\n", iface);
793 return IMFAttributes_DeleteAllItems(stream->attributes);
796 static HRESULT WINAPI video_stream_attributes_SetUINT32(IMFAttributes *iface, REFGUID key, UINT32 value)
798 struct video_stream *stream = impl_from_stream_IMFAttributes(iface);
800 TRACE("%p, %s, %u.\n", iface, debugstr_guid(key), value);
802 return IMFAttributes_SetUINT32(stream->attributes, key, value);
805 static HRESULT WINAPI video_stream_attributes_SetUINT64(IMFAttributes *iface, REFGUID key, UINT64 value)
807 struct video_stream *stream = impl_from_stream_IMFAttributes(iface);
809 TRACE("%p, %s, %s.\n", iface, debugstr_guid(key), wine_dbgstr_longlong(value));
811 return IMFAttributes_SetUINT64(stream->attributes, key, value);
814 static HRESULT WINAPI video_stream_attributes_SetDouble(IMFAttributes *iface, REFGUID key, double value)
816 struct video_stream *stream = impl_from_stream_IMFAttributes(iface);
818 TRACE("%p, %s, %f.\n", iface, debugstr_guid(key), value);
820 return IMFAttributes_SetDouble(stream->attributes, key, value);
823 static HRESULT WINAPI video_stream_attributes_SetGUID(IMFAttributes *iface, REFGUID key, REFGUID value)
825 struct video_stream *stream = impl_from_stream_IMFAttributes(iface);
827 TRACE("%p, %s, %s.\n", iface, debugstr_guid(key), debugstr_guid(value));
829 return IMFAttributes_SetGUID(stream->attributes, key, value);
832 static HRESULT WINAPI video_stream_attributes_SetString(IMFAttributes *iface, REFGUID key,
833 const WCHAR *value)
835 struct video_stream *stream = impl_from_stream_IMFAttributes(iface);
837 TRACE("%p, %s, %s.\n", iface, debugstr_guid(key), debugstr_w(value));
839 return IMFAttributes_SetString(stream->attributes, key, value);
842 static HRESULT WINAPI video_stream_attributes_SetBlob(IMFAttributes *iface, REFGUID key,
843 const UINT8 *buf, UINT32 size)
845 struct video_stream *stream = impl_from_stream_IMFAttributes(iface);
847 TRACE("%p, %s, %p, %u.\n", iface, debugstr_guid(key), buf, size);
849 return IMFAttributes_SetBlob(stream->attributes, key, buf, size);
852 static HRESULT WINAPI video_stream_attributes_SetUnknown(IMFAttributes *iface, REFGUID key,
853 IUnknown *unknown)
855 struct video_stream *stream = impl_from_stream_IMFAttributes(iface);
857 TRACE("%p, %s, %p.\n", iface, debugstr_guid(key), unknown);
859 return IMFAttributes_SetUnknown(stream->attributes, key, unknown);
862 static HRESULT WINAPI video_stream_attributes_LockStore(IMFAttributes *iface)
864 struct video_stream *stream = impl_from_stream_IMFAttributes(iface);
866 TRACE("%p.\n", iface);
868 return IMFAttributes_LockStore(stream->attributes);
871 static HRESULT WINAPI video_stream_attributes_UnlockStore(IMFAttributes *iface)
873 struct video_stream *stream = impl_from_stream_IMFAttributes(iface);
875 TRACE("%p.\n", iface);
877 return IMFAttributes_UnlockStore(stream->attributes);
880 static HRESULT WINAPI video_stream_attributes_GetCount(IMFAttributes *iface, UINT32 *count)
882 struct video_stream *stream = impl_from_stream_IMFAttributes(iface);
884 TRACE("%p, %p.\n", iface, count);
886 return IMFAttributes_GetCount(stream->attributes, count);
889 static HRESULT WINAPI video_stream_attributes_GetItemByIndex(IMFAttributes *iface, UINT32 index,
890 GUID *key, PROPVARIANT *value)
892 struct video_stream *stream = impl_from_stream_IMFAttributes(iface);
894 TRACE("%p, %u, %p, %p.\n", iface, index, key, value);
896 return IMFAttributes_GetItemByIndex(stream->attributes, index, key, value);
899 static HRESULT WINAPI video_stream_attributes_CopyAllItems(IMFAttributes *iface, IMFAttributes *dest)
901 struct video_stream *stream = impl_from_stream_IMFAttributes(iface);
903 TRACE("%p, %p.\n", iface, dest);
905 return IMFAttributes_CopyAllItems(stream->attributes, dest);
908 static const IMFAttributesVtbl video_stream_attributes_vtbl =
910 video_stream_attributes_QueryInterface,
911 video_stream_attributes_AddRef,
912 video_stream_attributes_Release,
913 video_stream_attributes_GetItem,
914 video_stream_attributes_GetItemType,
915 video_stream_attributes_CompareItem,
916 video_stream_attributes_Compare,
917 video_stream_attributes_GetUINT32,
918 video_stream_attributes_GetUINT64,
919 video_stream_attributes_GetDouble,
920 video_stream_attributes_GetGUID,
921 video_stream_attributes_GetStringLength,
922 video_stream_attributes_GetString,
923 video_stream_attributes_GetAllocatedString,
924 video_stream_attributes_GetBlobSize,
925 video_stream_attributes_GetBlob,
926 video_stream_attributes_GetAllocatedBlob,
927 video_stream_attributes_GetUnknown,
928 video_stream_attributes_SetItem,
929 video_stream_attributes_DeleteItem,
930 video_stream_attributes_DeleteAllItems,
931 video_stream_attributes_SetUINT32,
932 video_stream_attributes_SetUINT64,
933 video_stream_attributes_SetDouble,
934 video_stream_attributes_SetGUID,
935 video_stream_attributes_SetString,
936 video_stream_attributes_SetBlob,
937 video_stream_attributes_SetUnknown,
938 video_stream_attributes_LockStore,
939 video_stream_attributes_UnlockStore,
940 video_stream_attributes_GetCount,
941 video_stream_attributes_GetItemByIndex,
942 video_stream_attributes_CopyAllItems,
945 static BOOL video_renderer_is_mixer_d3d_aware(const struct video_renderer *renderer)
947 IMFAttributes *attributes;
948 unsigned int value = 0;
949 BOOL ret;
951 if (FAILED(IMFTransform_QueryInterface(renderer->mixer, &IID_IMFAttributes, (void **)&attributes)))
952 return FALSE;
954 ret = SUCCEEDED(IMFAttributes_GetUINT32(attributes, &MF_SA_D3D_AWARE, &value)) && value;
955 IMFAttributes_Release(attributes);
956 return ret;
959 static HRESULT video_renderer_stream_create(struct video_renderer *renderer, unsigned int id,
960 struct video_stream **ret)
962 struct video_stream *stream;
963 IMFAttributes *attributes;
964 unsigned int value;
965 HRESULT hr;
967 if (!(stream = heap_alloc_zero(sizeof(*stream))))
968 return E_OUTOFMEMORY;
970 stream->IMFStreamSink_iface.lpVtbl = &video_stream_sink_vtbl;
971 stream->IMFMediaTypeHandler_iface.lpVtbl = &video_stream_type_handler_vtbl;
972 stream->IMFGetService_iface.lpVtbl = &video_stream_get_service_vtbl;
973 stream->IMFAttributes_iface.lpVtbl = &video_stream_attributes_vtbl;
974 stream->refcount = 1;
975 InitializeCriticalSection(&stream->cs);
977 if (FAILED(hr = MFCreateEventQueue(&stream->event_queue)))
978 goto failed;
980 if (FAILED(hr = MFCreateAttributes(&stream->attributes, 0)))
981 goto failed;
983 stream->parent = renderer;
984 IMFMediaSink_AddRef(&stream->parent->IMFMediaSink_iface);
985 stream->id = id;
987 if (video_renderer_is_mixer_d3d_aware(renderer))
988 IMFAttributes_SetUINT32(stream->attributes, &MF_SA_D3D_AWARE, 1);
990 if (SUCCEEDED(IMFTransform_GetInputStreamAttributes(renderer->mixer, id, &attributes)))
992 if (SUCCEEDED(IMFAttributes_GetUINT32(attributes, &MF_SA_REQUIRED_SAMPLE_COUNT, &value)))
993 IMFAttributes_SetUINT32(stream->attributes, &MF_SA_REQUIRED_SAMPLE_COUNT, value);
994 IMFAttributes_Release(attributes);
997 *ret = stream;
999 return S_OK;
1001 failed:
1003 IMFStreamSink_Release(&stream->IMFStreamSink_iface);
1005 return hr;
1008 static HRESULT WINAPI video_renderer_sink_QueryInterface(IMFMediaSink *iface, REFIID riid, void **obj)
1010 struct video_renderer *renderer = impl_from_IMFMediaSink(iface);
1012 TRACE("%p, %s, %p.\n", iface, debugstr_guid(riid), obj);
1014 if (IsEqualIID(riid, &IID_IMFMediaSink) ||
1015 IsEqualIID(riid, &IID_IUnknown))
1017 *obj = &renderer->IMFMediaSink_iface;
1019 else if (IsEqualIID(riid, &IID_IMFMediaSinkPreroll))
1021 *obj = &renderer->IMFMediaSinkPreroll_iface;
1023 else if (IsEqualIID(riid, &IID_IMFVideoRenderer))
1025 *obj = &renderer->IMFVideoRenderer_iface;
1027 else if (IsEqualIID(riid, &IID_IMFMediaEventGenerator))
1029 *obj = &renderer->IMFMediaEventGenerator_iface;
1031 else if (IsEqualIID(riid, &IID_IMFClockStateSink))
1033 *obj = &renderer->IMFClockStateSink_iface;
1035 else if (IsEqualIID(riid, &IID_IMFGetService))
1037 *obj = &renderer->IMFGetService_iface;
1039 else if (IsEqualIID(riid, &IID_IMFAttributes))
1041 *obj = &renderer->IMFAttributes_iface;
1043 else if (IsEqualIID(riid, &IID_IMFQualityAdvise))
1045 *obj = &renderer->IMFQualityAdvise_iface;
1047 else
1049 WARN("Unsupported interface %s.\n", debugstr_guid(riid));
1050 *obj = NULL;
1051 return E_NOINTERFACE;
1054 IUnknown_AddRef((IUnknown *)*obj);
1056 return S_OK;
1059 static ULONG WINAPI video_renderer_sink_AddRef(IMFMediaSink *iface)
1061 struct video_renderer *renderer = impl_from_IMFMediaSink(iface);
1062 ULONG refcount = InterlockedIncrement(&renderer->refcount);
1063 TRACE("%p, refcount %u.\n", iface, refcount);
1064 return refcount;
1067 static ULONG WINAPI video_renderer_sink_Release(IMFMediaSink *iface)
1069 struct video_renderer *renderer = impl_from_IMFMediaSink(iface);
1070 ULONG refcount = InterlockedDecrement(&renderer->refcount);
1072 TRACE("%p, refcount %u.\n", iface, refcount);
1074 if (!refcount)
1076 if (renderer->event_queue)
1077 IMFMediaEventQueue_Release(renderer->event_queue);
1078 if (renderer->mixer)
1079 IMFTransform_Release(renderer->mixer);
1080 if (renderer->presenter)
1081 IMFVideoPresenter_Release(renderer->presenter);
1082 if (renderer->device_manager)
1083 IUnknown_Release(renderer->device_manager);
1084 if (renderer->clock)
1085 IMFPresentationClock_Release(renderer->clock);
1086 if (renderer->attributes)
1087 IMFAttributes_Release(renderer->attributes);
1088 DeleteCriticalSection(&renderer->cs);
1089 heap_free(renderer);
1092 return refcount;
1095 static HRESULT WINAPI video_renderer_sink_GetCharacteristics(IMFMediaSink *iface, DWORD *flags)
1097 struct video_renderer *renderer = impl_from_IMFMediaSink(iface);
1099 TRACE("%p, %p.\n", iface, flags);
1101 if (renderer->flags & EVR_SHUT_DOWN)
1102 return MF_E_SHUTDOWN;
1104 *flags = MEDIASINK_CLOCK_REQUIRED | MEDIASINK_CAN_PREROLL;
1106 return S_OK;
1109 static HRESULT video_renderer_add_stream(struct video_renderer *renderer, unsigned int id,
1110 IMFStreamSink **stream_sink)
1112 struct video_stream *stream;
1113 HRESULT hr;
1115 if (!mf_array_reserve((void **)&renderer->streams, &renderer->stream_size, renderer->stream_count + 1,
1116 sizeof(*renderer->streams)))
1118 return E_OUTOFMEMORY;
1121 if (SUCCEEDED(hr = video_renderer_stream_create(renderer, id, &stream)))
1123 if (stream_sink)
1125 *stream_sink = &stream->IMFStreamSink_iface;
1126 IMFStreamSink_AddRef(*stream_sink);
1128 renderer->streams[renderer->stream_count++] = stream;
1131 return hr;
1134 static HRESULT WINAPI video_renderer_sink_AddStreamSink(IMFMediaSink *iface, DWORD id,
1135 IMFMediaType *media_type, IMFStreamSink **stream_sink)
1137 struct video_renderer *renderer = impl_from_IMFMediaSink(iface);
1138 HRESULT hr;
1140 TRACE("%p, %#x, %p, %p.\n", iface, id, media_type, stream_sink);
1142 /* Rely on mixer for stream id validation. */
1144 EnterCriticalSection(&renderer->cs);
1145 if (renderer->flags & EVR_SHUT_DOWN)
1146 hr = MF_E_SHUTDOWN;
1147 else if (SUCCEEDED(hr = IMFTransform_AddInputStreams(renderer->mixer, 1, &id)))
1149 if (FAILED(hr = video_renderer_add_stream(renderer, id, stream_sink)))
1150 IMFTransform_DeleteInputStream(renderer->mixer, id);
1153 LeaveCriticalSection(&renderer->cs);
1155 return hr;
1158 static HRESULT WINAPI video_renderer_sink_RemoveStreamSink(IMFMediaSink *iface, DWORD id)
1160 struct video_renderer *renderer = impl_from_IMFMediaSink(iface);
1161 HRESULT hr;
1162 size_t i;
1164 TRACE("%p, %#x.\n", iface, id);
1166 /* Rely on mixer for stream id validation. */
1168 EnterCriticalSection(&renderer->cs);
1169 if (renderer->flags & EVR_SHUT_DOWN)
1170 hr = MF_E_SHUTDOWN;
1171 else if (SUCCEEDED(hr = IMFTransform_DeleteInputStream(renderer->mixer, id)))
1173 for (i = 0; i < renderer->stream_count; ++i)
1175 if (renderer->streams[i]->id == id)
1177 IMFStreamSink_Release(&renderer->streams[i]->IMFStreamSink_iface);
1178 renderer->streams[i] = NULL;
1179 if (i < renderer->stream_count - 1)
1181 memmove(&renderer->streams[i], &renderer->streams[i+1],
1182 (renderer->stream_count - i - 1) * sizeof(*renderer->streams));
1184 renderer->stream_count--;
1185 break;
1189 LeaveCriticalSection(&renderer->cs);
1191 return hr;
1194 static HRESULT WINAPI video_renderer_sink_GetStreamSinkCount(IMFMediaSink *iface, DWORD *count)
1196 struct video_renderer *renderer = impl_from_IMFMediaSink(iface);
1197 HRESULT hr = S_OK;
1199 TRACE("%p, %p.\n", iface, count);
1201 if (!count)
1202 return E_POINTER;
1204 EnterCriticalSection(&renderer->cs);
1205 if (renderer->flags & EVR_SHUT_DOWN)
1206 hr = MF_E_SHUTDOWN;
1207 else if (!count)
1208 hr = E_POINTER;
1209 else
1210 *count = renderer->stream_count;
1211 LeaveCriticalSection(&renderer->cs);
1213 return hr;
1216 static HRESULT WINAPI video_renderer_sink_GetStreamSinkByIndex(IMFMediaSink *iface, DWORD index,
1217 IMFStreamSink **stream)
1219 struct video_renderer *renderer = impl_from_IMFMediaSink(iface);
1220 HRESULT hr = S_OK;
1222 TRACE("%p, %u, %p.\n", iface, index, stream);
1224 EnterCriticalSection(&renderer->cs);
1225 if (renderer->flags & EVR_SHUT_DOWN)
1226 hr = MF_E_SHUTDOWN;
1227 else if (!stream)
1228 hr = E_POINTER;
1229 else if (index >= renderer->stream_count)
1230 hr = E_INVALIDARG;
1231 else
1233 *stream = &renderer->streams[index]->IMFStreamSink_iface;
1234 IMFStreamSink_AddRef(*stream);
1236 LeaveCriticalSection(&renderer->cs);
1238 return hr;
1241 static HRESULT WINAPI video_renderer_sink_GetStreamSinkById(IMFMediaSink *iface, DWORD id,
1242 IMFStreamSink **stream)
1244 struct video_renderer *renderer = impl_from_IMFMediaSink(iface);
1245 HRESULT hr = S_OK;
1246 size_t i;
1248 TRACE("%p, %#x, %p.\n", iface, id, stream);
1250 EnterCriticalSection(&renderer->cs);
1251 if (renderer->flags & EVR_SHUT_DOWN)
1252 hr = MF_E_SHUTDOWN;
1253 else if (!stream)
1254 hr = E_POINTER;
1255 else
1257 for (i = 0; i < renderer->stream_count; ++i)
1259 if (renderer->streams[i]->id == id)
1260 break;
1263 if (i == renderer->stream_count)
1264 hr = MF_E_INVALIDSTREAMNUMBER;
1265 else
1267 *stream = &renderer->streams[i]->IMFStreamSink_iface;
1268 IMFStreamSink_AddRef(*stream);
1271 LeaveCriticalSection(&renderer->cs);
1273 return hr;
1276 static void video_renderer_set_presentation_clock(struct video_renderer *renderer, IMFPresentationClock *clock)
1278 if (renderer->clock)
1280 IMFPresentationClock_RemoveClockStateSink(renderer->clock, &renderer->IMFClockStateSink_iface);
1281 IMFPresentationClock_Release(renderer->clock);
1283 renderer->clock = clock;
1284 if (renderer->clock)
1286 IMFPresentationClock_AddRef(renderer->clock);
1287 IMFPresentationClock_AddClockStateSink(renderer->clock, &renderer->IMFClockStateSink_iface);
1291 static HRESULT WINAPI video_renderer_sink_SetPresentationClock(IMFMediaSink *iface, IMFPresentationClock *clock)
1293 struct video_renderer *renderer = impl_from_IMFMediaSink(iface);
1294 HRESULT hr = S_OK;
1296 TRACE("%p, %p.\n", iface, clock);
1298 EnterCriticalSection(&renderer->cs);
1300 if (renderer->flags & EVR_SHUT_DOWN)
1301 hr = MF_E_SHUTDOWN;
1302 else
1303 video_renderer_set_presentation_clock(renderer, clock);
1305 LeaveCriticalSection(&renderer->cs);
1307 return hr;
1310 static HRESULT WINAPI video_renderer_sink_GetPresentationClock(IMFMediaSink *iface, IMFPresentationClock **clock)
1312 struct video_renderer *renderer = impl_from_IMFMediaSink(iface);
1313 HRESULT hr = S_OK;
1315 TRACE("%p, %p.\n", iface, clock);
1317 if (!clock)
1318 return E_POINTER;
1320 EnterCriticalSection(&renderer->cs);
1322 if (renderer->flags & EVR_SHUT_DOWN)
1323 hr = MF_E_SHUTDOWN;
1324 else if (renderer->clock)
1326 *clock = renderer->clock;
1327 IMFPresentationClock_AddRef(*clock);
1329 else
1330 hr = MF_E_NO_CLOCK;
1332 LeaveCriticalSection(&renderer->cs);
1334 return hr;
1337 static HRESULT WINAPI video_renderer_sink_Shutdown(IMFMediaSink *iface)
1339 struct video_renderer *renderer = impl_from_IMFMediaSink(iface);
1340 size_t i;
1342 TRACE("%p.\n", iface);
1344 if (renderer->flags & EVR_SHUT_DOWN)
1345 return MF_E_SHUTDOWN;
1347 EnterCriticalSection(&renderer->cs);
1348 renderer->flags |= EVR_SHUT_DOWN;
1349 /* Detach streams from the sink. */
1350 for (i = 0; i < renderer->stream_count; ++i)
1352 struct video_stream *stream = renderer->streams[i];
1354 EnterCriticalSection(&stream->cs);
1355 stream->parent = NULL;
1356 LeaveCriticalSection(&stream->cs);
1358 IMFMediaEventQueue_Shutdown(stream->event_queue);
1359 IMFStreamSink_Release(&stream->IMFStreamSink_iface);
1360 IMFMediaSink_Release(iface);
1361 renderer->streams[i] = NULL;
1363 heap_free(renderer->streams);
1364 renderer->stream_count = 0;
1365 renderer->stream_size = 0;
1366 IMFMediaEventQueue_Shutdown(renderer->event_queue);
1367 video_renderer_set_presentation_clock(renderer, NULL);
1368 video_renderer_release_services(renderer);
1369 LeaveCriticalSection(&renderer->cs);
1371 return S_OK;
1374 static const IMFMediaSinkVtbl video_renderer_sink_vtbl =
1376 video_renderer_sink_QueryInterface,
1377 video_renderer_sink_AddRef,
1378 video_renderer_sink_Release,
1379 video_renderer_sink_GetCharacteristics,
1380 video_renderer_sink_AddStreamSink,
1381 video_renderer_sink_RemoveStreamSink,
1382 video_renderer_sink_GetStreamSinkCount,
1383 video_renderer_sink_GetStreamSinkByIndex,
1384 video_renderer_sink_GetStreamSinkById,
1385 video_renderer_sink_SetPresentationClock,
1386 video_renderer_sink_GetPresentationClock,
1387 video_renderer_sink_Shutdown,
1390 static HRESULT WINAPI video_renderer_preroll_QueryInterface(IMFMediaSinkPreroll *iface, REFIID riid, void **obj)
1392 struct video_renderer *renderer = impl_from_IMFMediaSinkPreroll(iface);
1393 return IMFMediaSink_QueryInterface(&renderer->IMFMediaSink_iface, riid, obj);
1396 static ULONG WINAPI video_renderer_preroll_AddRef(IMFMediaSinkPreroll *iface)
1398 struct video_renderer *renderer = impl_from_IMFMediaSinkPreroll(iface);
1399 return IMFMediaSink_AddRef(&renderer->IMFMediaSink_iface);
1402 static ULONG WINAPI video_renderer_preroll_Release(IMFMediaSinkPreroll *iface)
1404 struct video_renderer *renderer = impl_from_IMFMediaSinkPreroll(iface);
1405 return IMFMediaSink_Release(&renderer->IMFMediaSink_iface);
1408 static HRESULT WINAPI video_renderer_preroll_NotifyPreroll(IMFMediaSinkPreroll *iface, MFTIME start_time)
1410 struct video_renderer *renderer = impl_from_IMFMediaSinkPreroll(iface);
1411 HRESULT hr = S_OK;
1412 size_t i;
1414 TRACE("%p, %s.\n", iface, debugstr_time(start_time));
1416 EnterCriticalSection(&renderer->cs);
1417 if (renderer->flags & EVR_SHUT_DOWN)
1418 hr = MF_E_SHUTDOWN;
1419 else
1421 for (i = 0; i < renderer->stream_count; ++i)
1423 struct video_stream *stream = renderer->streams[i];
1425 EnterCriticalSection(&stream->cs);
1426 if (!(stream->flags & (EVR_STREAM_PREROLLING | EVR_STREAM_PREROLLED)))
1428 IMFMediaEventQueue_QueueEventParamVar(stream->event_queue, MEStreamSinkRequestSample,
1429 &GUID_NULL, S_OK, NULL);
1430 stream->flags |= EVR_STREAM_PREROLLING;
1432 LeaveCriticalSection(&stream->cs);
1435 LeaveCriticalSection(&renderer->cs);
1437 return hr;
1440 static const IMFMediaSinkPrerollVtbl video_renderer_preroll_vtbl =
1442 video_renderer_preroll_QueryInterface,
1443 video_renderer_preroll_AddRef,
1444 video_renderer_preroll_Release,
1445 video_renderer_preroll_NotifyPreroll,
1448 static HRESULT WINAPI video_renderer_QueryInterface(IMFVideoRenderer *iface, REFIID riid, void **obj)
1450 struct video_renderer *renderer = impl_from_IMFVideoRenderer(iface);
1451 return IMFMediaSink_QueryInterface(&renderer->IMFMediaSink_iface, riid, obj);
1454 static ULONG WINAPI video_renderer_AddRef(IMFVideoRenderer *iface)
1456 struct video_renderer *renderer = impl_from_IMFVideoRenderer(iface);
1457 return IMFMediaSink_AddRef(&renderer->IMFMediaSink_iface);
1460 static ULONG WINAPI video_renderer_Release(IMFVideoRenderer *iface)
1462 struct video_renderer *renderer = impl_from_IMFVideoRenderer(iface);
1463 return IMFMediaSink_Release(&renderer->IMFMediaSink_iface);
1466 static HRESULT video_renderer_create_mixer(IMFAttributes *attributes, IMFTransform **out)
1468 unsigned int flags = 0;
1469 IMFActivate *activate;
1470 CLSID clsid;
1471 HRESULT hr;
1473 if (attributes && SUCCEEDED(hr = IMFAttributes_GetUnknown(attributes, &MF_ACTIVATE_CUSTOM_VIDEO_MIXER_ACTIVATE,
1474 &IID_IMFActivate, (void **)&activate)))
1476 IMFAttributes_GetUINT32(attributes, &MF_ACTIVATE_CUSTOM_VIDEO_MIXER_FLAGS, &flags);
1477 hr = IMFActivate_ActivateObject(activate, &IID_IMFTransform, (void **)out);
1478 IMFActivate_Release(activate);
1479 if (SUCCEEDED(hr) || !(flags & MF_ACTIVATE_CUSTOM_MIXER_ALLOWFAIL))
1480 return hr;
1483 if (!attributes || FAILED(IMFAttributes_GetGUID(attributes, &MF_ACTIVATE_CUSTOM_VIDEO_MIXER_CLSID, &clsid)))
1484 memcpy(&clsid, &CLSID_MFVideoMixer9, sizeof(clsid));
1486 return CoCreateInstance(&clsid, NULL, CLSCTX_INPROC_SERVER, &IID_IMFTransform, (void **)out);
1489 static HRESULT video_renderer_create_presenter(struct video_renderer *renderer, IMFAttributes *attributes,
1490 IMFVideoPresenter **out)
1492 unsigned int flags = 0;
1493 IMFActivate *activate;
1494 UINT64 value;
1495 CLSID clsid;
1496 HRESULT hr;
1498 if (attributes && SUCCEEDED(IMFAttributes_GetUINT64(attributes, &MF_ACTIVATE_VIDEO_WINDOW, &value)))
1499 renderer->window = UlongToHandle(value);
1501 if (attributes && SUCCEEDED(IMFAttributes_GetUnknown(attributes, &MF_ACTIVATE_CUSTOM_VIDEO_PRESENTER_ACTIVATE,
1502 &IID_IMFActivate, (void **)&activate)))
1504 IMFAttributes_GetUINT32(attributes, &MF_ACTIVATE_CUSTOM_VIDEO_PRESENTER_FLAGS, &flags);
1505 hr = IMFActivate_ActivateObject(activate, &IID_IMFVideoPresenter, (void **)out);
1506 IMFActivate_Release(activate);
1507 if (SUCCEEDED(hr) || !(flags & MF_ACTIVATE_CUSTOM_PRESENTER_ALLOWFAIL))
1508 return hr;
1511 if (!attributes || FAILED(IMFAttributes_GetGUID(attributes, &MF_ACTIVATE_CUSTOM_VIDEO_PRESENTER_CLSID, &clsid)))
1512 memcpy(&clsid, &CLSID_MFVideoPresenter9, sizeof(clsid));
1514 return CoCreateInstance(&clsid, NULL, CLSCTX_INPROC_SERVER, &IID_IMFVideoPresenter, (void **)out);
1517 static HRESULT video_renderer_configure_mixer(struct video_renderer *renderer)
1519 IMFTopologyServiceLookupClient *lookup_client;
1520 HRESULT hr;
1522 if (SUCCEEDED(hr = IMFTransform_QueryInterface(renderer->mixer, &IID_IMFTopologyServiceLookupClient,
1523 (void **)&lookup_client)))
1525 renderer->flags |= EVR_INIT_SERVICES;
1526 if (SUCCEEDED(hr = IMFTopologyServiceLookupClient_InitServicePointers(lookup_client,
1527 &renderer->IMFTopologyServiceLookup_iface)))
1529 renderer->flags |= EVR_MIXER_INITED_SERVICES;
1531 renderer->flags &= ~EVR_INIT_SERVICES;
1532 IMFTopologyServiceLookupClient_Release(lookup_client);
1535 if (SUCCEEDED(hr))
1537 unsigned int input_count, output_count;
1538 unsigned int *ids, *oids;
1539 size_t i;
1541 /* Create stream sinks for inputs that mixer already has by default. */
1542 if (SUCCEEDED(IMFTransform_GetStreamCount(renderer->mixer, &input_count, &output_count)))
1544 ids = heap_calloc(input_count, sizeof(*ids));
1545 oids = heap_calloc(output_count, sizeof(*oids));
1547 if (ids && oids)
1549 if (SUCCEEDED(IMFTransform_GetStreamIDs(renderer->mixer, input_count, ids, output_count, oids)))
1551 for (i = 0; i < input_count; ++i)
1553 video_renderer_add_stream(renderer, ids[i], NULL);
1559 heap_free(ids);
1560 heap_free(oids);
1564 /* Set device manager that presenter should have created. */
1565 if (video_renderer_is_mixer_d3d_aware(renderer))
1567 IDirect3DDeviceManager9 *device_manager;
1569 if (SUCCEEDED(MFGetService((IUnknown *)renderer->presenter, &MR_VIDEO_ACCELERATION_SERVICE,
1570 &IID_IDirect3DDeviceManager9, (void **)&device_manager)))
1572 IMFTransform_ProcessMessage(renderer->mixer, MFT_MESSAGE_SET_D3D_MANAGER, (ULONG_PTR)device_manager);
1573 IDirect3DDeviceManager9_Release(device_manager);
1577 return hr;
1580 static HRESULT video_renderer_configure_presenter(struct video_renderer *renderer)
1582 IMFTopologyServiceLookupClient *lookup_client;
1583 IMFVideoDisplayControl *control;
1584 HRESULT hr;
1586 if (SUCCEEDED(IMFVideoPresenter_QueryInterface(renderer->presenter, &IID_IMFVideoDisplayControl, (void **)&control)))
1588 IMFVideoDisplayControl_SetVideoWindow(control, renderer->window);
1589 IMFVideoDisplayControl_Release(control);
1592 if (SUCCEEDED(hr = IMFVideoPresenter_QueryInterface(renderer->presenter, &IID_IMFTopologyServiceLookupClient,
1593 (void **)&lookup_client)))
1595 renderer->flags |= EVR_INIT_SERVICES;
1596 if (SUCCEEDED(hr = IMFTopologyServiceLookupClient_InitServicePointers(lookup_client,
1597 &renderer->IMFTopologyServiceLookup_iface)))
1599 renderer->flags |= EVR_PRESENTER_INITED_SERVICES;
1601 renderer->flags &= ~EVR_INIT_SERVICES;
1602 IMFTopologyServiceLookupClient_Release(lookup_client);
1605 if (FAILED(MFGetService((IUnknown *)renderer->presenter, &MR_VIDEO_ACCELERATION_SERVICE,
1606 &IID_IUnknown, (void **)&renderer->device_manager)))
1608 WARN("Failed to get device manager from the presenter.\n");
1611 return hr;
1614 static HRESULT video_renderer_initialize(struct video_renderer *renderer, IMFTransform *mixer,
1615 IMFVideoPresenter *presenter)
1617 HRESULT hr;
1619 if (renderer->mixer)
1621 IMFTransform_Release(renderer->mixer);
1622 renderer->mixer = NULL;
1625 if (renderer->presenter)
1627 IMFVideoPresenter_Release(renderer->presenter);
1628 renderer->presenter = NULL;
1631 if (renderer->device_manager)
1633 IUnknown_Release(renderer->device_manager);
1634 renderer->device_manager = NULL;
1637 renderer->mixer = mixer;
1638 IMFTransform_AddRef(renderer->mixer);
1640 renderer->presenter = presenter;
1641 IMFVideoPresenter_AddRef(renderer->presenter);
1643 if (SUCCEEDED(hr = video_renderer_configure_mixer(renderer)))
1644 hr = video_renderer_configure_presenter(renderer);
1646 return hr;
1649 static HRESULT WINAPI video_renderer_InitializeRenderer(IMFVideoRenderer *iface, IMFTransform *mixer,
1650 IMFVideoPresenter *presenter)
1652 struct video_renderer *renderer = impl_from_IMFVideoRenderer(iface);
1653 HRESULT hr;
1655 TRACE("%p, %p, %p.\n", iface, mixer, presenter);
1657 if (mixer)
1658 IMFTransform_AddRef(mixer);
1659 else if (FAILED(hr = video_renderer_create_mixer(NULL, &mixer)))
1661 WARN("Failed to create default mixer object, hr %#x.\n", hr);
1662 return hr;
1665 if (presenter)
1666 IMFVideoPresenter_AddRef(presenter);
1667 else if (FAILED(hr = video_renderer_create_presenter(renderer, NULL, &presenter)))
1669 WARN("Failed to create default presenter, hr %#x.\n", hr);
1670 IMFTransform_Release(mixer);
1671 return hr;
1674 EnterCriticalSection(&renderer->cs);
1676 if (renderer->flags & EVR_SHUT_DOWN)
1677 hr = MF_E_SHUTDOWN;
1678 else
1680 /* FIXME: check clock state */
1681 /* FIXME: check that streams are not initialized */
1683 hr = video_renderer_initialize(renderer, mixer, presenter);
1686 LeaveCriticalSection(&renderer->cs);
1688 IMFTransform_Release(mixer);
1689 IMFVideoPresenter_Release(presenter);
1691 return hr;
1694 static const IMFVideoRendererVtbl video_renderer_vtbl =
1696 video_renderer_QueryInterface,
1697 video_renderer_AddRef,
1698 video_renderer_Release,
1699 video_renderer_InitializeRenderer,
1702 static HRESULT WINAPI video_renderer_events_QueryInterface(IMFMediaEventGenerator *iface, REFIID riid, void **obj)
1704 struct video_renderer *renderer = impl_from_IMFMediaEventGenerator(iface);
1705 return IMFMediaSink_QueryInterface(&renderer->IMFMediaSink_iface, riid, obj);
1708 static ULONG WINAPI video_renderer_events_AddRef(IMFMediaEventGenerator *iface)
1710 struct video_renderer *renderer = impl_from_IMFMediaEventGenerator(iface);
1711 return IMFMediaSink_AddRef(&renderer->IMFMediaSink_iface);
1714 static ULONG WINAPI video_renderer_events_Release(IMFMediaEventGenerator *iface)
1716 struct video_renderer *renderer = impl_from_IMFMediaEventGenerator(iface);
1717 return IMFMediaSink_Release(&renderer->IMFMediaSink_iface);
1720 static HRESULT WINAPI video_renderer_events_GetEvent(IMFMediaEventGenerator *iface, DWORD flags, IMFMediaEvent **event)
1722 struct video_renderer *renderer = impl_from_IMFMediaEventGenerator(iface);
1724 TRACE("%p, %#x, %p.\n", iface, flags, event);
1726 return IMFMediaEventQueue_GetEvent(renderer->event_queue, flags, event);
1729 static HRESULT WINAPI video_renderer_events_BeginGetEvent(IMFMediaEventGenerator *iface, IMFAsyncCallback *callback,
1730 IUnknown *state)
1732 struct video_renderer *renderer = impl_from_IMFMediaEventGenerator(iface);
1734 TRACE("%p, %p, %p.\n", iface, callback, state);
1736 return IMFMediaEventQueue_BeginGetEvent(renderer->event_queue, callback, state);
1739 static HRESULT WINAPI video_renderer_events_EndGetEvent(IMFMediaEventGenerator *iface, IMFAsyncResult *result,
1740 IMFMediaEvent **event)
1742 struct video_renderer *renderer = impl_from_IMFMediaEventGenerator(iface);
1744 TRACE("%p, %p, %p.\n", iface, result, event);
1746 return IMFMediaEventQueue_EndGetEvent(renderer->event_queue, result, event);
1749 static HRESULT WINAPI video_renderer_events_QueueEvent(IMFMediaEventGenerator *iface, MediaEventType event_type,
1750 REFGUID ext_type, HRESULT hr, const PROPVARIANT *value)
1752 struct video_renderer *renderer = impl_from_IMFMediaEventGenerator(iface);
1754 TRACE("%p, %u, %s, %#x, %p.\n", iface, event_type, debugstr_guid(ext_type), hr, value);
1756 return IMFMediaEventQueue_QueueEventParamVar(renderer->event_queue, event_type, ext_type, hr, value);
1759 static const IMFMediaEventGeneratorVtbl video_renderer_events_vtbl =
1761 video_renderer_events_QueryInterface,
1762 video_renderer_events_AddRef,
1763 video_renderer_events_Release,
1764 video_renderer_events_GetEvent,
1765 video_renderer_events_BeginGetEvent,
1766 video_renderer_events_EndGetEvent,
1767 video_renderer_events_QueueEvent,
1770 static HRESULT WINAPI video_renderer_clock_sink_QueryInterface(IMFClockStateSink *iface, REFIID riid, void **obj)
1772 struct video_renderer *renderer = impl_from_IMFClockStateSink(iface);
1773 return IMFMediaSink_QueryInterface(&renderer->IMFMediaSink_iface, riid, obj);
1776 static ULONG WINAPI video_renderer_clock_sink_AddRef(IMFClockStateSink *iface)
1778 struct video_renderer *renderer = impl_from_IMFClockStateSink(iface);
1779 return IMFMediaSink_AddRef(&renderer->IMFMediaSink_iface);
1782 static ULONG WINAPI video_renderer_clock_sink_Release(IMFClockStateSink *iface)
1784 struct video_renderer *renderer = impl_from_IMFClockStateSink(iface);
1785 return IMFMediaSink_Release(&renderer->IMFMediaSink_iface);
1788 static HRESULT WINAPI video_renderer_clock_sink_OnClockStart(IMFClockStateSink *iface, MFTIME systime, LONGLONG offset)
1790 struct video_renderer *renderer = impl_from_IMFClockStateSink(iface);
1791 size_t i;
1793 TRACE("%p, %s, %s.\n", iface, debugstr_time(systime), debugstr_time(offset));
1795 EnterCriticalSection(&renderer->cs);
1797 if (renderer->state == EVR_STATE_STOPPED)
1799 IMFTransform_ProcessMessage(renderer->mixer, MFT_MESSAGE_NOTIFY_BEGIN_STREAMING, 0);
1800 IMFVideoPresenter_ProcessMessage(renderer->presenter, MFVP_MESSAGE_BEGINSTREAMING, 0);
1802 for (i = 0; i < renderer->stream_count; ++i)
1804 struct video_stream *stream = renderer->streams[i];
1806 IMFMediaEventQueue_QueueEventParamVar(stream->event_queue, MEStreamSinkStarted, &GUID_NULL, S_OK, NULL);
1808 EnterCriticalSection(&stream->cs);
1809 if (!(stream->flags & EVR_STREAM_PREROLLED))
1810 IMFMediaEventQueue_QueueEventParamVar(stream->event_queue, MEStreamSinkRequestSample,
1811 &GUID_NULL, S_OK, NULL);
1812 stream->flags |= EVR_STREAM_PREROLLED;
1813 LeaveCriticalSection(&stream->cs);
1817 renderer->state = EVR_STATE_RUNNING;
1819 IMFVideoPresenter_OnClockStart(renderer->presenter, systime, offset);
1821 LeaveCriticalSection(&renderer->cs);
1823 return S_OK;
1826 static HRESULT WINAPI video_renderer_clock_sink_OnClockStop(IMFClockStateSink *iface, MFTIME systime)
1828 struct video_renderer *renderer = impl_from_IMFClockStateSink(iface);
1829 size_t i;
1831 TRACE("%p, %s.\n", iface, debugstr_time(systime));
1833 EnterCriticalSection(&renderer->cs);
1835 IMFVideoPresenter_OnClockStop(renderer->presenter, systime);
1837 IMFTransform_ProcessMessage(renderer->mixer, MFT_MESSAGE_COMMAND_FLUSH, 0);
1838 IMFVideoPresenter_ProcessMessage(renderer->presenter, MFVP_MESSAGE_FLUSH, 0);
1840 if (renderer->state == EVR_STATE_RUNNING ||
1841 renderer->state == EVR_STATE_PAUSED)
1843 IMFTransform_ProcessMessage(renderer->mixer, MFT_MESSAGE_NOTIFY_END_STREAMING, 0);
1844 IMFVideoPresenter_ProcessMessage(renderer->presenter, MFVP_MESSAGE_ENDSTREAMING, 0);
1846 for (i = 0; i < renderer->stream_count; ++i)
1848 struct video_stream *stream = renderer->streams[i];
1849 IMFMediaEventQueue_QueueEventParamVar(stream->event_queue, MEStreamSinkStopped, &GUID_NULL, S_OK, NULL);
1851 EnterCriticalSection(&stream->cs);
1852 stream->flags &= ~EVR_STREAM_PREROLLED;
1853 LeaveCriticalSection(&stream->cs);
1855 renderer->state = EVR_STATE_STOPPED;
1858 LeaveCriticalSection(&renderer->cs);
1860 return S_OK;
1863 static HRESULT WINAPI video_renderer_clock_sink_OnClockPause(IMFClockStateSink *iface, MFTIME systime)
1865 struct video_renderer *renderer = impl_from_IMFClockStateSink(iface);
1866 size_t i;
1868 TRACE("%p, %s.\n", iface, debugstr_time(systime));
1870 EnterCriticalSection(&renderer->cs);
1872 IMFVideoPresenter_OnClockPause(renderer->presenter, systime);
1874 if (renderer->state == EVR_STATE_RUNNING)
1876 for (i = 0; i < renderer->stream_count; ++i)
1878 struct video_stream *stream = renderer->streams[i];
1879 IMFMediaEventQueue_QueueEventParamVar(stream->event_queue, MEStreamSinkPaused, &GUID_NULL, S_OK, NULL);
1883 renderer->state = EVR_STATE_PAUSED;
1885 LeaveCriticalSection(&renderer->cs);
1887 return S_OK;
1890 static HRESULT WINAPI video_renderer_clock_sink_OnClockRestart(IMFClockStateSink *iface, MFTIME systime)
1892 struct video_renderer *renderer = impl_from_IMFClockStateSink(iface);
1893 size_t i;
1895 TRACE("%p, %s.\n", iface, debugstr_time(systime));
1897 EnterCriticalSection(&renderer->cs);
1899 IMFVideoPresenter_OnClockRestart(renderer->presenter, systime);
1901 for (i = 0; i < renderer->stream_count; ++i)
1903 struct video_stream *stream = renderer->streams[i];
1904 IMFMediaEventQueue_QueueEventParamVar(stream->event_queue, MEStreamSinkStarted, &GUID_NULL, S_OK, NULL);
1906 renderer->state = EVR_STATE_RUNNING;
1908 LeaveCriticalSection(&renderer->cs);
1910 return S_OK;
1913 static HRESULT WINAPI video_renderer_clock_sink_OnClockSetRate(IMFClockStateSink *iface, MFTIME systime, float rate)
1915 struct video_renderer *renderer = impl_from_IMFClockStateSink(iface);
1916 IMFClockStateSink *sink;
1918 TRACE("%p, %s, %f.\n", iface, debugstr_time(systime), rate);
1920 EnterCriticalSection(&renderer->cs);
1922 IMFVideoPresenter_OnClockSetRate(renderer->presenter, systime, rate);
1923 if (SUCCEEDED(IMFTransform_QueryInterface(renderer->mixer, &IID_IMFClockStateSink, (void **)&sink)))
1925 IMFClockStateSink_OnClockSetRate(sink, systime, rate);
1926 IMFClockStateSink_Release(sink);
1929 LeaveCriticalSection(&renderer->cs);
1931 return S_OK;
1934 static const IMFClockStateSinkVtbl video_renderer_clock_sink_vtbl =
1936 video_renderer_clock_sink_QueryInterface,
1937 video_renderer_clock_sink_AddRef,
1938 video_renderer_clock_sink_Release,
1939 video_renderer_clock_sink_OnClockStart,
1940 video_renderer_clock_sink_OnClockStop,
1941 video_renderer_clock_sink_OnClockPause,
1942 video_renderer_clock_sink_OnClockRestart,
1943 video_renderer_clock_sink_OnClockSetRate,
1946 static HRESULT WINAPI video_renderer_get_service_QueryInterface(IMFGetService *iface, REFIID riid, void **obj)
1948 struct video_renderer *renderer = impl_from_IMFGetService(iface);
1949 return IMFMediaSink_QueryInterface(&renderer->IMFMediaSink_iface, riid, obj);
1952 static ULONG WINAPI video_renderer_get_service_AddRef(IMFGetService *iface)
1954 struct video_renderer *renderer = impl_from_IMFGetService(iface);
1955 return IMFMediaSink_AddRef(&renderer->IMFMediaSink_iface);
1958 static ULONG WINAPI video_renderer_get_service_Release(IMFGetService *iface)
1960 struct video_renderer *renderer = impl_from_IMFGetService(iface);
1961 return IMFMediaSink_Release(&renderer->IMFMediaSink_iface);
1964 static HRESULT WINAPI video_renderer_get_service_GetService(IMFGetService *iface, REFGUID service, REFIID riid, void **obj)
1966 struct video_renderer *renderer = impl_from_IMFGetService(iface);
1967 HRESULT hr = E_NOINTERFACE;
1968 IMFGetService *gs = NULL;
1970 TRACE("%p, %s, %s, %p.\n", iface, debugstr_guid(service), debugstr_guid(riid), obj);
1972 if (IsEqualGUID(service, &MR_VIDEO_MIXER_SERVICE))
1974 hr = IMFTransform_QueryInterface(renderer->mixer, &IID_IMFGetService, (void **)&gs);
1976 else if (IsEqualGUID(service, &MR_VIDEO_RENDER_SERVICE))
1978 hr = IMFVideoPresenter_QueryInterface(renderer->presenter, &IID_IMFGetService, (void **)&gs);
1980 else
1982 FIXME("Unsupported service %s.\n", debugstr_guid(service));
1985 if (gs)
1987 hr = IMFGetService_GetService(gs, service, riid, obj);
1988 IMFGetService_Release(gs);
1991 return hr;
1994 static const IMFGetServiceVtbl video_renderer_get_service_vtbl =
1996 video_renderer_get_service_QueryInterface,
1997 video_renderer_get_service_AddRef,
1998 video_renderer_get_service_Release,
1999 video_renderer_get_service_GetService,
2002 static HRESULT WINAPI video_renderer_service_lookup_QueryInterface(IMFTopologyServiceLookup *iface, REFIID riid, void **obj)
2004 TRACE("%p, %s, %p.\n", iface, debugstr_guid(riid), obj);
2006 if (IsEqualIID(riid, &IID_IMFTopologyServiceLookup) ||
2007 IsEqualIID(riid, &IID_IUnknown))
2009 *obj = iface;
2010 IMFTopologyServiceLookup_AddRef(iface);
2011 return S_OK;
2014 WARN("Unsupported interface %s.\n", debugstr_guid(riid));
2015 *obj = NULL;
2016 return E_NOINTERFACE;
2019 static ULONG WINAPI video_renderer_service_lookup_AddRef(IMFTopologyServiceLookup *iface)
2021 struct video_renderer *renderer = impl_from_IMFTopologyServiceLookup(iface);
2022 return IMFMediaSink_AddRef(&renderer->IMFMediaSink_iface);
2025 static ULONG WINAPI video_renderer_service_lookup_Release(IMFTopologyServiceLookup *iface)
2027 struct video_renderer *renderer = impl_from_IMFTopologyServiceLookup(iface);
2028 return IMFMediaSink_Release(&renderer->IMFMediaSink_iface);
2031 static HRESULT WINAPI video_renderer_service_lookup_LookupService(IMFTopologyServiceLookup *iface,
2032 MF_SERVICE_LOOKUP_TYPE lookup_type, DWORD index, REFGUID service, REFIID riid,
2033 void **objects, DWORD *num_objects)
2035 struct video_renderer *renderer = impl_from_IMFTopologyServiceLookup(iface);
2036 HRESULT hr = S_OK;
2038 TRACE("%p, %u, %u, %s, %s, %p, %p.\n", iface, lookup_type, index, debugstr_guid(service), debugstr_guid(riid),
2039 objects, num_objects);
2041 EnterCriticalSection(&renderer->cs);
2043 if (!(renderer->flags & EVR_INIT_SERVICES))
2044 hr = MF_E_NOTACCEPTING;
2045 else if (IsEqualGUID(service, &MR_VIDEO_RENDER_SERVICE))
2047 if (IsEqualIID(riid, &IID_IMediaEventSink))
2049 *objects = &renderer->IMediaEventSink_iface;
2050 IUnknown_AddRef((IUnknown *)*objects);
2052 else
2054 FIXME("Unsupported interface %s for render service.\n", debugstr_guid(riid));
2055 hr = E_NOINTERFACE;
2058 else if (IsEqualGUID(service, &MR_VIDEO_MIXER_SERVICE))
2060 if (IsEqualIID(riid, &IID_IMFTransform))
2062 *objects = renderer->mixer;
2063 IUnknown_AddRef((IUnknown *)*objects);
2065 else
2067 FIXME("Unsupported interface %s for mixer service.\n", debugstr_guid(riid));
2068 hr = E_NOINTERFACE;
2071 else
2073 WARN("Unsupported service %s.\n", debugstr_guid(service));
2074 hr = MF_E_UNSUPPORTED_SERVICE;
2077 LeaveCriticalSection(&renderer->cs);
2079 return hr;
2082 static const IMFTopologyServiceLookupVtbl video_renderer_service_lookup_vtbl =
2084 video_renderer_service_lookup_QueryInterface,
2085 video_renderer_service_lookup_AddRef,
2086 video_renderer_service_lookup_Release,
2087 video_renderer_service_lookup_LookupService,
2090 static HRESULT WINAPI video_renderer_event_sink_QueryInterface(IMediaEventSink *iface, REFIID riid, void **obj)
2092 TRACE("%p, %s, %p.\n", iface, debugstr_guid(riid), obj);
2094 if (IsEqualIID(riid, &IID_IMediaEventSink) ||
2095 IsEqualIID(riid, &IID_IUnknown))
2097 *obj = iface;
2098 IMediaEventSink_AddRef(iface);
2099 return S_OK;
2102 WARN("Unsupported interface %s.\n", debugstr_guid(riid));
2103 *obj = NULL;
2104 return E_NOINTERFACE;
2107 static ULONG WINAPI video_renderer_event_sink_AddRef(IMediaEventSink *iface)
2109 struct video_renderer *renderer = impl_from_IMediaEventSink(iface);
2110 return IMFMediaSink_AddRef(&renderer->IMFMediaSink_iface);
2113 static ULONG WINAPI video_renderer_event_sink_Release(IMediaEventSink *iface)
2115 struct video_renderer *renderer = impl_from_IMediaEventSink(iface);
2116 return IMFMediaSink_Release(&renderer->IMFMediaSink_iface);
2119 static HRESULT WINAPI video_renderer_event_sink_Notify(IMediaEventSink *iface, LONG event, LONG_PTR param1, LONG_PTR param2)
2121 struct video_renderer *renderer = impl_from_IMediaEventSink(iface);
2122 HRESULT hr = S_OK;
2123 unsigned int idx;
2125 TRACE("%p, %d, %ld, %ld.\n", iface, event, param1, param2);
2127 EnterCriticalSection(&renderer->cs);
2129 if (event == EC_SAMPLE_NEEDED)
2131 idx = param1;
2132 if (idx >= renderer->stream_count)
2133 hr = MF_E_INVALIDSTREAMNUMBER;
2134 else
2136 hr = IMFMediaEventQueue_QueueEventParamVar(renderer->streams[idx]->event_queue,
2137 MEStreamSinkRequestSample, &GUID_NULL, S_OK, NULL);
2140 else if (event >= EC_USER)
2142 PROPVARIANT code;
2144 code.vt = VT_I4;
2145 code.lVal = event;
2146 hr = IMFMediaEventQueue_QueueEventParamVar(renderer->event_queue, MERendererEvent,
2147 &GUID_NULL, S_OK, &code);
2149 else
2151 WARN("Unhandled event %d.\n", event);
2152 hr = MF_E_UNEXPECTED;
2155 LeaveCriticalSection(&renderer->cs);
2157 return hr;
2160 static const IMediaEventSinkVtbl media_event_sink_vtbl =
2162 video_renderer_event_sink_QueryInterface,
2163 video_renderer_event_sink_AddRef,
2164 video_renderer_event_sink_Release,
2165 video_renderer_event_sink_Notify,
2168 static HRESULT WINAPI video_renderer_attributes_QueryInterface(IMFAttributes *iface, REFIID riid, void **obj)
2170 struct video_renderer *renderer = impl_from_IMFAttributes(iface);
2171 return IMFMediaSink_QueryInterface(&renderer->IMFMediaSink_iface, riid, obj);
2174 static ULONG WINAPI video_renderer_attributes_AddRef(IMFAttributes *iface)
2176 struct video_renderer *renderer = impl_from_IMFAttributes(iface);
2177 return IMFMediaSink_AddRef(&renderer->IMFMediaSink_iface);
2180 static ULONG WINAPI video_renderer_attributes_Release(IMFAttributes *iface)
2182 struct video_renderer *renderer = impl_from_IMFAttributes(iface);
2183 return IMFMediaSink_Release(&renderer->IMFMediaSink_iface);
2186 static HRESULT WINAPI video_renderer_attributes_GetItem(IMFAttributes *iface, REFGUID key, PROPVARIANT *value)
2188 struct video_renderer *renderer = impl_from_IMFAttributes(iface);
2190 TRACE("%p, %s, %p.\n", iface, debugstr_guid(key), value);
2192 return IMFAttributes_GetItem(renderer->attributes, key, value);
2195 static HRESULT WINAPI video_renderer_attributes_GetItemType(IMFAttributes *iface, REFGUID key, MF_ATTRIBUTE_TYPE *type)
2197 struct video_renderer *renderer = impl_from_IMFAttributes(iface);
2199 TRACE("%p, %s, %p.\n", iface, debugstr_guid(key), type);
2201 return IMFAttributes_GetItemType(renderer->attributes, key, type);
2204 static HRESULT WINAPI video_renderer_attributes_CompareItem(IMFAttributes *iface, REFGUID key, REFPROPVARIANT value,
2205 BOOL *result)
2207 struct video_renderer *renderer = impl_from_IMFAttributes(iface);
2209 TRACE("%p, %s, %p, %p.\n", iface, debugstr_guid(key), value, result);
2211 return IMFAttributes_CompareItem(renderer->attributes, key, value, result);
2214 static HRESULT WINAPI video_renderer_attributes_Compare(IMFAttributes *iface, IMFAttributes *theirs,
2215 MF_ATTRIBUTES_MATCH_TYPE type, BOOL *result)
2217 struct video_renderer *renderer = impl_from_IMFAttributes(iface);
2219 TRACE("%p, %p, %d, %p.\n", iface, theirs, type, result);
2221 return IMFAttributes_Compare(renderer->attributes, theirs, type, result);
2224 static HRESULT WINAPI video_renderer_attributes_GetUINT32(IMFAttributes *iface, REFGUID key, UINT32 *value)
2226 struct video_renderer *renderer = impl_from_IMFAttributes(iface);
2228 TRACE("%p, %s, %p.\n", iface, debugstr_guid(key), value);
2230 return IMFAttributes_GetUINT32(renderer->attributes, key, value);
2233 static HRESULT WINAPI video_renderer_attributes_GetUINT64(IMFAttributes *iface, REFGUID key, UINT64 *value)
2235 struct video_renderer *renderer = impl_from_IMFAttributes(iface);
2237 TRACE("%p, %s, %p.\n", iface, debugstr_guid(key), value);
2239 return IMFAttributes_GetUINT64(renderer->attributes, key, value);
2242 static HRESULT WINAPI video_renderer_attributes_GetDouble(IMFAttributes *iface, REFGUID key, double *value)
2244 struct video_renderer *renderer = impl_from_IMFAttributes(iface);
2246 TRACE("%p, %s, %p.\n", iface, debugstr_guid(key), value);
2248 return IMFAttributes_GetDouble(renderer->attributes, key, value);
2251 static HRESULT WINAPI video_renderer_attributes_GetGUID(IMFAttributes *iface, REFGUID key, GUID *value)
2253 struct video_renderer *renderer = impl_from_IMFAttributes(iface);
2255 TRACE("%p, %s, %p.\n", iface, debugstr_guid(key), value);
2257 return IMFAttributes_GetGUID(renderer->attributes, key, value);
2260 static HRESULT WINAPI video_renderer_attributes_GetStringLength(IMFAttributes *iface, REFGUID key,
2261 UINT32 *length)
2263 struct video_renderer *renderer = impl_from_IMFAttributes(iface);
2265 TRACE("%p, %s, %p.\n", iface, debugstr_guid(key), length);
2267 return IMFAttributes_GetStringLength(renderer->attributes, key, length);
2270 static HRESULT WINAPI video_renderer_attributes_GetString(IMFAttributes *iface, REFGUID key, WCHAR *value,
2271 UINT32 size, UINT32 *length)
2273 struct video_renderer *renderer = impl_from_IMFAttributes(iface);
2275 TRACE("%p, %s, %p, %u, %p.\n", iface, debugstr_guid(key), value, size, length);
2277 return IMFAttributes_GetString(renderer->attributes, key, value, size, length);
2280 static HRESULT WINAPI video_renderer_attributes_GetAllocatedString(IMFAttributes *iface, REFGUID key,
2281 WCHAR **value, UINT32 *length)
2283 struct video_renderer *renderer = impl_from_IMFAttributes(iface);
2285 TRACE("%p, %s, %p, %p.\n", iface, debugstr_guid(key), value, length);
2287 return IMFAttributes_GetAllocatedString(renderer->attributes, key, value, length);
2290 static HRESULT WINAPI video_renderer_attributes_GetBlobSize(IMFAttributes *iface, REFGUID key, UINT32 *size)
2292 struct video_renderer *renderer = impl_from_IMFAttributes(iface);
2294 TRACE("%p, %s, %p.\n", iface, debugstr_guid(key), size);
2296 return IMFAttributes_GetBlobSize(renderer->attributes, key, size);
2299 static HRESULT WINAPI video_renderer_attributes_GetBlob(IMFAttributes *iface, REFGUID key, UINT8 *buf,
2300 UINT32 bufsize, UINT32 *blobsize)
2302 struct video_renderer *renderer = impl_from_IMFAttributes(iface);
2304 TRACE("%p, %s, %p, %u, %p.\n", iface, debugstr_guid(key), buf, bufsize, blobsize);
2306 return IMFAttributes_GetBlob(renderer->attributes, key, buf, bufsize, blobsize);
2309 static HRESULT WINAPI video_renderer_attributes_GetAllocatedBlob(IMFAttributes *iface, REFGUID key,
2310 UINT8 **buf, UINT32 *size)
2312 struct video_renderer *renderer = impl_from_IMFAttributes(iface);
2314 TRACE("%p, %s, %p, %p.\n", iface, debugstr_guid(key), buf, size);
2316 return IMFAttributes_GetAllocatedBlob(renderer->attributes, key, buf, size);
2319 static HRESULT WINAPI video_renderer_attributes_GetUnknown(IMFAttributes *iface, REFGUID key, REFIID riid, void **out)
2321 struct video_renderer *renderer = impl_from_IMFAttributes(iface);
2323 TRACE("%p, %s, %s, %p.\n", iface, debugstr_guid(key), debugstr_guid(riid), out);
2325 return IMFAttributes_GetUnknown(renderer->attributes, key, riid, out);
2328 static HRESULT WINAPI video_renderer_attributes_SetItem(IMFAttributes *iface, REFGUID key, REFPROPVARIANT value)
2330 struct video_renderer *renderer = impl_from_IMFAttributes(iface);
2332 TRACE("%p, %s, %p.\n", iface, debugstr_guid(key), value);
2334 return IMFAttributes_SetItem(renderer->attributes, key, value);
2337 static HRESULT WINAPI video_renderer_attributes_DeleteItem(IMFAttributes *iface, REFGUID key)
2339 struct video_renderer *renderer = impl_from_IMFAttributes(iface);
2341 TRACE("%p, %s.\n", iface, debugstr_guid(key));
2343 return IMFAttributes_DeleteItem(renderer->attributes, key);
2346 static HRESULT WINAPI video_renderer_attributes_DeleteAllItems(IMFAttributes *iface)
2348 struct video_renderer *renderer = impl_from_IMFAttributes(iface);
2350 TRACE("%p.\n", iface);
2352 return IMFAttributes_DeleteAllItems(renderer->attributes);
2355 static HRESULT WINAPI video_renderer_attributes_SetUINT32(IMFAttributes *iface, REFGUID key, UINT32 value)
2357 struct video_renderer *renderer = impl_from_IMFAttributes(iface);
2359 TRACE("%p, %s, %u.\n", iface, debugstr_guid(key), value);
2361 return IMFAttributes_SetUINT32(renderer->attributes, key, value);
2364 static HRESULT WINAPI video_renderer_attributes_SetUINT64(IMFAttributes *iface, REFGUID key, UINT64 value)
2366 struct video_renderer *renderer = impl_from_IMFAttributes(iface);
2368 TRACE("%p, %s, %s.\n", iface, debugstr_guid(key), wine_dbgstr_longlong(value));
2370 return IMFAttributes_SetUINT64(renderer->attributes, key, value);
2373 static HRESULT WINAPI video_renderer_attributes_SetDouble(IMFAttributes *iface, REFGUID key, double value)
2375 struct video_renderer *renderer = impl_from_IMFAttributes(iface);
2377 TRACE("%p, %s, %f.\n", iface, debugstr_guid(key), value);
2379 return IMFAttributes_SetDouble(renderer->attributes, key, value);
2382 static HRESULT WINAPI video_renderer_attributes_SetGUID(IMFAttributes *iface, REFGUID key, REFGUID value)
2384 struct video_renderer *renderer = impl_from_IMFAttributes(iface);
2386 TRACE("%p, %s, %s.\n", iface, debugstr_guid(key), debugstr_guid(value));
2388 return IMFAttributes_SetGUID(renderer->attributes, key, value);
2391 static HRESULT WINAPI video_renderer_attributes_SetString(IMFAttributes *iface, REFGUID key,
2392 const WCHAR *value)
2394 struct video_renderer *renderer = impl_from_IMFAttributes(iface);
2396 TRACE("%p, %s, %s.\n", iface, debugstr_guid(key), debugstr_w(value));
2398 return IMFAttributes_SetString(renderer->attributes, key, value);
2401 static HRESULT WINAPI video_renderer_attributes_SetBlob(IMFAttributes *iface, REFGUID key,
2402 const UINT8 *buf, UINT32 size)
2404 struct video_renderer *renderer = impl_from_IMFAttributes(iface);
2406 TRACE("%p, %s, %p, %u.\n", iface, debugstr_guid(key), buf, size);
2408 return IMFAttributes_SetBlob(renderer->attributes, key, buf, size);
2411 static HRESULT WINAPI video_renderer_attributes_SetUnknown(IMFAttributes *iface, REFGUID key,
2412 IUnknown *unknown)
2414 struct video_renderer *renderer = impl_from_IMFAttributes(iface);
2416 TRACE("%p, %s, %p.\n", iface, debugstr_guid(key), unknown);
2418 return IMFAttributes_SetUnknown(renderer->attributes, key, unknown);
2421 static HRESULT WINAPI video_renderer_attributes_LockStore(IMFAttributes *iface)
2423 struct video_renderer *renderer = impl_from_IMFAttributes(iface);
2425 TRACE("%p.\n", iface);
2427 return IMFAttributes_LockStore(renderer->attributes);
2430 static HRESULT WINAPI video_renderer_attributes_UnlockStore(IMFAttributes *iface)
2432 struct video_renderer *renderer = impl_from_IMFAttributes(iface);
2434 TRACE("%p.\n", iface);
2436 return IMFAttributes_UnlockStore(renderer->attributes);
2439 static HRESULT WINAPI video_renderer_attributes_GetCount(IMFAttributes *iface, UINT32 *count)
2441 struct video_renderer *renderer = impl_from_IMFAttributes(iface);
2443 TRACE("%p, %p.\n", iface, count);
2445 return IMFAttributes_GetCount(renderer->attributes, count);
2448 static HRESULT WINAPI video_renderer_attributes_GetItemByIndex(IMFAttributes *iface, UINT32 index,
2449 GUID *key, PROPVARIANT *value)
2451 struct video_renderer *renderer = impl_from_IMFAttributes(iface);
2453 TRACE("%p, %u, %p, %p.\n", iface, index, key, value);
2455 return IMFAttributes_GetItemByIndex(renderer->attributes, index, key, value);
2458 static HRESULT WINAPI video_renderer_attributes_CopyAllItems(IMFAttributes *iface, IMFAttributes *dest)
2460 struct video_renderer *renderer = impl_from_IMFAttributes(iface);
2462 TRACE("%p, %p.\n", iface, dest);
2464 return IMFAttributes_CopyAllItems(renderer->attributes, dest);
2467 static const IMFAttributesVtbl video_renderer_attributes_vtbl =
2469 video_renderer_attributes_QueryInterface,
2470 video_renderer_attributes_AddRef,
2471 video_renderer_attributes_Release,
2472 video_renderer_attributes_GetItem,
2473 video_renderer_attributes_GetItemType,
2474 video_renderer_attributes_CompareItem,
2475 video_renderer_attributes_Compare,
2476 video_renderer_attributes_GetUINT32,
2477 video_renderer_attributes_GetUINT64,
2478 video_renderer_attributes_GetDouble,
2479 video_renderer_attributes_GetGUID,
2480 video_renderer_attributes_GetStringLength,
2481 video_renderer_attributes_GetString,
2482 video_renderer_attributes_GetAllocatedString,
2483 video_renderer_attributes_GetBlobSize,
2484 video_renderer_attributes_GetBlob,
2485 video_renderer_attributes_GetAllocatedBlob,
2486 video_renderer_attributes_GetUnknown,
2487 video_renderer_attributes_SetItem,
2488 video_renderer_attributes_DeleteItem,
2489 video_renderer_attributes_DeleteAllItems,
2490 video_renderer_attributes_SetUINT32,
2491 video_renderer_attributes_SetUINT64,
2492 video_renderer_attributes_SetDouble,
2493 video_renderer_attributes_SetGUID,
2494 video_renderer_attributes_SetString,
2495 video_renderer_attributes_SetBlob,
2496 video_renderer_attributes_SetUnknown,
2497 video_renderer_attributes_LockStore,
2498 video_renderer_attributes_UnlockStore,
2499 video_renderer_attributes_GetCount,
2500 video_renderer_attributes_GetItemByIndex,
2501 video_renderer_attributes_CopyAllItems,
2504 static HRESULT WINAPI video_renderer_quality_advise_QueryInterface(IMFQualityAdvise *iface, REFIID riid, void **out)
2506 struct video_renderer *renderer = impl_from_IMFQualityAdvise(iface);
2507 return IMFMediaSink_QueryInterface(&renderer->IMFMediaSink_iface, riid, out);
2510 static ULONG WINAPI video_renderer_quality_advise_AddRef(IMFQualityAdvise *iface)
2512 struct video_renderer *renderer = impl_from_IMFQualityAdvise(iface);
2513 return IMFMediaSink_AddRef(&renderer->IMFMediaSink_iface);
2516 static ULONG WINAPI video_renderer_quality_Release(IMFQualityAdvise *iface)
2518 struct video_renderer *renderer = impl_from_IMFQualityAdvise(iface);
2519 return IMFMediaSink_Release(&renderer->IMFMediaSink_iface);
2522 static HRESULT WINAPI video_renderer_quality_advise_SetDropMode(IMFQualityAdvise *iface,
2523 MF_QUALITY_DROP_MODE mode)
2525 FIXME("%p, %u.\n", iface, mode);
2527 return E_NOTIMPL;
2530 static HRESULT WINAPI video_renderer_quality_advise_SetQualityLevel(IMFQualityAdvise *iface,
2531 MF_QUALITY_LEVEL level)
2533 FIXME("%p, %u.\n", iface, level);
2535 return E_NOTIMPL;
2538 static HRESULT WINAPI video_renderer_quality_advise_GetDropMode(IMFQualityAdvise *iface,
2539 MF_QUALITY_DROP_MODE *mode)
2541 FIXME("%p, %p.\n", iface, mode);
2543 return E_NOTIMPL;
2546 static HRESULT WINAPI video_renderer_quality_advise_GetQualityLevel(IMFQualityAdvise *iface,
2547 MF_QUALITY_LEVEL *level)
2549 FIXME("%p, %p.\n", iface, level);
2551 return E_NOTIMPL;
2554 static HRESULT WINAPI video_renderer_quality_advise_DropTime(IMFQualityAdvise *iface, LONGLONG interval)
2556 FIXME("%p, %s.\n", iface, wine_dbgstr_longlong(interval));
2558 return E_NOTIMPL;
2561 static const IMFQualityAdviseVtbl video_renderer_quality_advise_vtbl =
2563 video_renderer_quality_advise_QueryInterface,
2564 video_renderer_quality_advise_AddRef,
2565 video_renderer_quality_Release,
2566 video_renderer_quality_advise_SetDropMode,
2567 video_renderer_quality_advise_SetQualityLevel,
2568 video_renderer_quality_advise_GetDropMode,
2569 video_renderer_quality_advise_GetQualityLevel,
2570 video_renderer_quality_advise_DropTime,
2573 static HRESULT evr_create_object(IMFAttributes *attributes, void *user_context, IUnknown **obj)
2575 struct video_renderer *object;
2576 IMFVideoPresenter *presenter = NULL;
2577 IMFTransform *mixer = NULL;
2578 HRESULT hr;
2580 TRACE("%p, %p, %p.\n", attributes, user_context, obj);
2582 if (!(object = heap_alloc_zero(sizeof(*object))))
2583 return E_OUTOFMEMORY;
2585 object->IMFMediaSink_iface.lpVtbl = &video_renderer_sink_vtbl;
2586 object->IMFMediaSinkPreroll_iface.lpVtbl = &video_renderer_preroll_vtbl;
2587 object->IMFVideoRenderer_iface.lpVtbl = &video_renderer_vtbl;
2588 object->IMFMediaEventGenerator_iface.lpVtbl = &video_renderer_events_vtbl;
2589 object->IMFClockStateSink_iface.lpVtbl = &video_renderer_clock_sink_vtbl;
2590 object->IMFGetService_iface.lpVtbl = &video_renderer_get_service_vtbl;
2591 object->IMFTopologyServiceLookup_iface.lpVtbl = &video_renderer_service_lookup_vtbl;
2592 object->IMediaEventSink_iface.lpVtbl = &media_event_sink_vtbl;
2593 object->IMFAttributes_iface.lpVtbl = &video_renderer_attributes_vtbl;
2594 object->IMFQualityAdvise_iface.lpVtbl = &video_renderer_quality_advise_vtbl;
2595 object->refcount = 1;
2596 InitializeCriticalSection(&object->cs);
2598 if (FAILED(hr = MFCreateEventQueue(&object->event_queue)))
2599 goto failed;
2601 if (FAILED(hr = MFCreateAttributes(&object->attributes, 0)))
2602 goto failed;
2604 /* Create mixer and presenter. */
2605 if (FAILED(hr = video_renderer_create_mixer(attributes, &mixer)))
2606 goto failed;
2608 if (FAILED(hr = video_renderer_create_presenter(object, attributes, &presenter)))
2609 goto failed;
2611 if (FAILED(hr = video_renderer_initialize(object, mixer, presenter)))
2612 goto failed;
2614 IMFTransform_Release(mixer);
2615 IMFVideoPresenter_Release(presenter);
2617 /* Default attributes */
2618 IMFAttributes_SetUINT32(object->attributes, &EVRConfig_ForceBob, 0);
2619 IMFAttributes_SetUINT32(object->attributes, &EVRConfig_AllowDropToBob, 0);
2620 IMFAttributes_SetUINT32(object->attributes, &EVRConfig_ForceThrottle, 0);
2621 IMFAttributes_SetUINT32(object->attributes, &EVRConfig_AllowDropToThrottle, 0);
2622 IMFAttributes_SetUINT32(object->attributes, &EVRConfig_ForceHalfInterlace, 0);
2623 IMFAttributes_SetUINT32(object->attributes, &EVRConfig_AllowDropToHalfInterlace, 0);
2624 IMFAttributes_SetUINT32(object->attributes, &EVRConfig_ForceScaling, 0);
2625 IMFAttributes_SetUINT32(object->attributes, &EVRConfig_AllowScaling, 0);
2626 IMFAttributes_SetUINT32(object->attributes, &EVRConfig_ForceBatching, 0);
2627 IMFAttributes_SetUINT32(object->attributes, &EVRConfig_AllowBatching, 0);
2629 *obj = (IUnknown *)&object->IMFMediaSink_iface;
2631 return S_OK;
2633 failed:
2635 if (mixer)
2636 IMFTransform_Release(mixer);
2638 if (presenter)
2639 IMFVideoPresenter_Release(presenter);
2641 video_renderer_release_services(object);
2642 IMFMediaSink_Release(&object->IMFMediaSink_iface);
2644 return hr;
2647 static void evr_shutdown_object(void *user_context, IUnknown *obj)
2649 IMFMediaSink *sink;
2651 if (SUCCEEDED(IUnknown_QueryInterface(obj, &IID_IMFMediaSink, (void **)&sink)))
2653 IMFMediaSink_Shutdown(sink);
2654 IMFMediaSink_Release(sink);
2658 static const struct activate_funcs evr_activate_funcs =
2660 .create_object = evr_create_object,
2661 .shutdown_object = evr_shutdown_object,
2664 /***********************************************************************
2665 * MFCreateVideoRendererActivate (mf.@)
2667 HRESULT WINAPI MFCreateVideoRendererActivate(HWND hwnd, IMFActivate **activate)
2669 HRESULT hr;
2671 TRACE("%p, %p.\n", hwnd, activate);
2673 if (!activate)
2674 return E_POINTER;
2676 hr = create_activation_object(NULL, &evr_activate_funcs, activate);
2677 if (SUCCEEDED(hr))
2678 IMFActivate_SetUINT64(*activate, &MF_ACTIVATE_VIDEO_WINDOW, (ULONG_PTR)hwnd);
2680 return hr;
2683 /***********************************************************************
2684 * MFCreateVideoRenderer (mf.@)
2686 HRESULT WINAPI MFCreateVideoRenderer(REFIID riid, void **renderer)
2688 IUnknown *obj;
2689 HRESULT hr;
2691 TRACE("%s, %p.\n", debugstr_guid(riid), renderer);
2693 *renderer = NULL;
2695 if (SUCCEEDED(hr = evr_create_object(NULL, NULL, &obj)))
2697 hr = IUnknown_QueryInterface(obj, riid, renderer);
2698 IUnknown_Release(obj);
2701 return hr;