mf: Use CRT allocation functions.
[wine.git] / dlls / mf / evr.c
blobd048ea59681e98939a48f8453f895772e303f8f3
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 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 struct video_stream *stream = impl_from_IMFStreamSink(iface);
466 HRESULT hr;
468 TRACE("%p.\n", iface);
470 EnterCriticalSection(&stream->cs);
471 if (!stream->parent)
472 hr = MF_E_STREAMSINK_REMOVED;
473 else if (SUCCEEDED(hr = IMFTransform_ProcessMessage(stream->parent->mixer, MFT_MESSAGE_COMMAND_FLUSH, 0)))
474 hr = IMFVideoPresenter_ProcessMessage(stream->parent->presenter, MFVP_MESSAGE_FLUSH, 0);
475 LeaveCriticalSection(&stream->cs);
477 return hr;
480 static const IMFStreamSinkVtbl video_stream_sink_vtbl =
482 video_stream_sink_QueryInterface,
483 video_stream_sink_AddRef,
484 video_stream_sink_Release,
485 video_stream_sink_GetEvent,
486 video_stream_sink_BeginGetEvent,
487 video_stream_sink_EndGetEvent,
488 video_stream_sink_QueueEvent,
489 video_stream_sink_GetMediaSink,
490 video_stream_sink_GetIdentifier,
491 video_stream_sink_GetMediaTypeHandler,
492 video_stream_sink_ProcessSample,
493 video_stream_sink_PlaceMarker,
494 video_stream_sink_Flush,
497 static HRESULT WINAPI video_stream_typehandler_QueryInterface(IMFMediaTypeHandler *iface, REFIID riid,
498 void **obj)
500 struct video_stream *stream = impl_from_IMFMediaTypeHandler(iface);
501 return IMFStreamSink_QueryInterface(&stream->IMFStreamSink_iface, riid, obj);
504 static ULONG WINAPI video_stream_typehandler_AddRef(IMFMediaTypeHandler *iface)
506 struct video_stream *stream = impl_from_IMFMediaTypeHandler(iface);
507 return IMFStreamSink_AddRef(&stream->IMFStreamSink_iface);
510 static ULONG WINAPI video_stream_typehandler_Release(IMFMediaTypeHandler *iface)
512 struct video_stream *stream = impl_from_IMFMediaTypeHandler(iface);
513 return IMFStreamSink_Release(&stream->IMFStreamSink_iface);
516 static HRESULT WINAPI video_stream_typehandler_IsMediaTypeSupported(IMFMediaTypeHandler *iface,
517 IMFMediaType *in_type, IMFMediaType **out_type)
519 struct video_stream *stream = impl_from_IMFMediaTypeHandler(iface);
520 HRESULT hr;
522 TRACE("%p, %p, %p.\n", iface, in_type, out_type);
524 if (!in_type)
525 return E_POINTER;
527 if (!stream->parent)
528 return MF_E_INVALIDMEDIATYPE;
530 if (SUCCEEDED(hr = IMFTransform_SetInputType(stream->parent->mixer, stream->id, in_type,
531 MFT_SET_TYPE_TEST_ONLY)))
533 if (out_type) *out_type = NULL;
536 return hr;
539 static HRESULT WINAPI video_stream_typehandler_GetMediaTypeCount(IMFMediaTypeHandler *iface, DWORD *count)
541 TRACE("%p, %p.\n", iface, count);
543 if (!count)
544 return E_POINTER;
546 *count = 0;
548 return S_OK;
551 static HRESULT WINAPI video_stream_typehandler_GetMediaTypeByIndex(IMFMediaTypeHandler *iface, DWORD index,
552 IMFMediaType **type)
554 TRACE("%p, %u, %p.\n", iface, index, type);
556 return MF_E_NO_MORE_TYPES;
559 static HRESULT WINAPI video_stream_typehandler_SetCurrentMediaType(IMFMediaTypeHandler *iface, IMFMediaType *type)
561 struct video_stream *stream = impl_from_IMFMediaTypeHandler(iface);
562 HRESULT hr;
564 TRACE("%p, %p.\n", iface, type);
566 if (!type)
567 return E_POINTER;
569 if (!stream->parent)
570 return MF_E_STREAMSINK_REMOVED;
572 hr = IMFTransform_SetInputType(stream->parent->mixer, stream->id, type, 0);
573 if (SUCCEEDED(hr) && !stream->id)
574 hr = IMFVideoPresenter_ProcessMessage(stream->parent->presenter, MFVP_MESSAGE_INVALIDATEMEDIATYPE, 0);
576 return hr;
579 static HRESULT WINAPI video_stream_typehandler_GetCurrentMediaType(IMFMediaTypeHandler *iface, IMFMediaType **type)
581 struct video_stream *stream = impl_from_IMFMediaTypeHandler(iface);
583 TRACE("%p, %p.\n", iface, type);
585 if (!type)
586 return E_POINTER;
588 if (!stream->parent)
589 return MF_E_STREAMSINK_REMOVED;
591 return IMFTransform_GetInputCurrentType(stream->parent->mixer, stream->id, type);
594 static HRESULT WINAPI video_stream_typehandler_GetMajorType(IMFMediaTypeHandler *iface, GUID *type)
596 struct video_stream *stream = impl_from_IMFMediaTypeHandler(iface);
598 TRACE("%p, %p.\n", iface, type);
600 if (!stream->parent)
601 return MF_E_STREAMSINK_REMOVED;
603 if (!type)
604 return E_POINTER;
606 memcpy(type, &MFMediaType_Video, sizeof(*type));
607 return S_OK;
610 static const IMFMediaTypeHandlerVtbl video_stream_type_handler_vtbl =
612 video_stream_typehandler_QueryInterface,
613 video_stream_typehandler_AddRef,
614 video_stream_typehandler_Release,
615 video_stream_typehandler_IsMediaTypeSupported,
616 video_stream_typehandler_GetMediaTypeCount,
617 video_stream_typehandler_GetMediaTypeByIndex,
618 video_stream_typehandler_SetCurrentMediaType,
619 video_stream_typehandler_GetCurrentMediaType,
620 video_stream_typehandler_GetMajorType,
623 static HRESULT WINAPI video_stream_get_service_QueryInterface(IMFGetService *iface, REFIID riid, void **obj)
625 struct video_stream *stream = impl_from_stream_IMFGetService(iface);
626 return IMFStreamSink_QueryInterface(&stream->IMFStreamSink_iface, riid, obj);
629 static ULONG WINAPI video_stream_get_service_AddRef(IMFGetService *iface)
631 struct video_stream *stream = impl_from_stream_IMFGetService(iface);
632 return IMFStreamSink_AddRef(&stream->IMFStreamSink_iface);
635 static ULONG WINAPI video_stream_get_service_Release(IMFGetService *iface)
637 struct video_stream *stream = impl_from_stream_IMFGetService(iface);
638 return IMFStreamSink_Release(&stream->IMFStreamSink_iface);
641 static HRESULT WINAPI video_stream_get_service(struct video_stream *stream, REFGUID service, REFIID riid, void **obj)
643 HRESULT hr = S_OK;
645 if (IsEqualGUID(service, &MR_VIDEO_ACCELERATION_SERVICE))
647 if (IsEqualIID(riid, &IID_IMFVideoSampleAllocator))
649 if (!stream->allocator)
651 hr = MFCreateVideoSampleAllocator(&IID_IMFVideoSampleAllocator, (void **)&stream->allocator);
652 if (SUCCEEDED(hr))
653 hr = IMFVideoSampleAllocator_SetDirectXManager(stream->allocator, stream->parent->device_manager);
655 if (SUCCEEDED(hr))
656 hr = IMFVideoSampleAllocator_QueryInterface(stream->allocator, riid, obj);
658 return hr;
660 else if (IsEqualIID(riid, &IID_IDirect3DDeviceManager9) && stream->parent->device_manager)
662 return IUnknown_QueryInterface(stream->parent->device_manager, riid, obj);
665 return E_NOINTERFACE;
668 FIXME("Unsupported service %s.\n", debugstr_guid(service));
670 return E_NOTIMPL;
673 static HRESULT WINAPI video_stream_get_service_GetService(IMFGetService *iface, REFGUID service, REFIID riid, void **obj)
675 struct video_stream *stream = impl_from_stream_IMFGetService(iface);
676 HRESULT hr;
678 TRACE("%p, %s, %s, %p.\n", iface, debugstr_guid(service), debugstr_guid(riid), obj);
680 EnterCriticalSection(&stream->cs);
681 if (!stream->parent)
682 hr = MF_E_STREAMSINK_REMOVED;
683 else
684 hr = video_stream_get_service(stream, service, riid, obj);
685 LeaveCriticalSection(&stream->cs);
687 return hr;
690 static const IMFGetServiceVtbl video_stream_get_service_vtbl =
692 video_stream_get_service_QueryInterface,
693 video_stream_get_service_AddRef,
694 video_stream_get_service_Release,
695 video_stream_get_service_GetService,
698 static HRESULT WINAPI video_stream_attributes_QueryInterface(IMFAttributes *iface, REFIID riid, void **obj)
700 struct video_stream *stream = impl_from_stream_IMFAttributes(iface);
701 return IMFStreamSink_QueryInterface(&stream->IMFStreamSink_iface, riid, obj);
704 static ULONG WINAPI video_stream_attributes_AddRef(IMFAttributes *iface)
706 struct video_stream *stream = impl_from_stream_IMFAttributes(iface);
707 return IMFStreamSink_AddRef(&stream->IMFStreamSink_iface);
710 static ULONG WINAPI video_stream_attributes_Release(IMFAttributes *iface)
712 struct video_stream *stream = impl_from_stream_IMFAttributes(iface);
713 return IMFStreamSink_Release(&stream->IMFStreamSink_iface);
716 static HRESULT WINAPI video_stream_attributes_GetItem(IMFAttributes *iface, REFGUID key, PROPVARIANT *value)
718 struct video_stream *stream = impl_from_stream_IMFAttributes(iface);
720 TRACE("%p, %s, %p.\n", iface, debugstr_guid(key), value);
722 return IMFAttributes_GetItem(stream->attributes, key, value);
725 static HRESULT WINAPI video_stream_attributes_GetItemType(IMFAttributes *iface, REFGUID key, MF_ATTRIBUTE_TYPE *type)
727 struct video_stream *stream = impl_from_stream_IMFAttributes(iface);
729 TRACE("%p, %s, %p.\n", iface, debugstr_guid(key), type);
731 return IMFAttributes_GetItemType(stream->attributes, key, type);
734 static HRESULT WINAPI video_stream_attributes_CompareItem(IMFAttributes *iface, REFGUID key, REFPROPVARIANT value,
735 BOOL *result)
737 struct video_stream *stream = impl_from_stream_IMFAttributes(iface);
739 TRACE("%p, %s, %p, %p.\n", iface, debugstr_guid(key), value, result);
741 return IMFAttributes_CompareItem(stream->attributes, key, value, result);
744 static HRESULT WINAPI video_stream_attributes_Compare(IMFAttributes *iface, IMFAttributes *theirs,
745 MF_ATTRIBUTES_MATCH_TYPE type, BOOL *result)
747 struct video_stream *stream = impl_from_stream_IMFAttributes(iface);
749 TRACE("%p, %p, %d, %p.\n", iface, theirs, type, result);
751 return IMFAttributes_Compare(stream->attributes, theirs, type, result);
754 static HRESULT WINAPI video_stream_attributes_GetUINT32(IMFAttributes *iface, REFGUID key, UINT32 *value)
756 struct video_stream *stream = impl_from_stream_IMFAttributes(iface);
758 TRACE("%p, %s, %p.\n", iface, debugstr_guid(key), value);
760 return IMFAttributes_GetUINT32(stream->attributes, key, value);
763 static HRESULT WINAPI video_stream_attributes_GetUINT64(IMFAttributes *iface, REFGUID key, UINT64 *value)
765 struct video_stream *stream = impl_from_stream_IMFAttributes(iface);
767 TRACE("%p, %s, %p.\n", iface, debugstr_guid(key), value);
769 return IMFAttributes_GetUINT64(stream->attributes, key, value);
772 static HRESULT WINAPI video_stream_attributes_GetDouble(IMFAttributes *iface, REFGUID key, double *value)
774 struct video_stream *stream = impl_from_stream_IMFAttributes(iface);
776 TRACE("%p, %s, %p.\n", iface, debugstr_guid(key), value);
778 return IMFAttributes_GetDouble(stream->attributes, key, value);
781 static HRESULT WINAPI video_stream_attributes_GetGUID(IMFAttributes *iface, REFGUID key, GUID *value)
783 struct video_stream *stream = impl_from_stream_IMFAttributes(iface);
785 TRACE("%p, %s, %p.\n", iface, debugstr_guid(key), value);
787 return IMFAttributes_GetGUID(stream->attributes, key, value);
790 static HRESULT WINAPI video_stream_attributes_GetStringLength(IMFAttributes *iface, REFGUID key,
791 UINT32 *length)
793 struct video_stream *stream = impl_from_stream_IMFAttributes(iface);
795 TRACE("%p, %s, %p.\n", iface, debugstr_guid(key), length);
797 return IMFAttributes_GetStringLength(stream->attributes, key, length);
800 static HRESULT WINAPI video_stream_attributes_GetString(IMFAttributes *iface, REFGUID key, WCHAR *value,
801 UINT32 size, UINT32 *length)
803 struct video_stream *stream = impl_from_stream_IMFAttributes(iface);
805 TRACE("%p, %s, %p, %u, %p.\n", iface, debugstr_guid(key), value, size, length);
807 return IMFAttributes_GetString(stream->attributes, key, value, size, length);
810 static HRESULT WINAPI video_stream_attributes_GetAllocatedString(IMFAttributes *iface, REFGUID key,
811 WCHAR **value, UINT32 *length)
813 struct video_stream *stream = impl_from_stream_IMFAttributes(iface);
815 TRACE("%p, %s, %p, %p.\n", iface, debugstr_guid(key), value, length);
817 return IMFAttributes_GetAllocatedString(stream->attributes, key, value, length);
820 static HRESULT WINAPI video_stream_attributes_GetBlobSize(IMFAttributes *iface, REFGUID key, UINT32 *size)
822 struct video_stream *stream = impl_from_stream_IMFAttributes(iface);
824 TRACE("%p, %s, %p.\n", iface, debugstr_guid(key), size);
826 return IMFAttributes_GetBlobSize(stream->attributes, key, size);
829 static HRESULT WINAPI video_stream_attributes_GetBlob(IMFAttributes *iface, REFGUID key, UINT8 *buf,
830 UINT32 bufsize, UINT32 *blobsize)
832 struct video_stream *stream = impl_from_stream_IMFAttributes(iface);
834 TRACE("%p, %s, %p, %u, %p.\n", iface, debugstr_guid(key), buf, bufsize, blobsize);
836 return IMFAttributes_GetBlob(stream->attributes, key, buf, bufsize, blobsize);
839 static HRESULT WINAPI video_stream_attributes_GetAllocatedBlob(IMFAttributes *iface, REFGUID key,
840 UINT8 **buf, UINT32 *size)
842 struct video_stream *stream = impl_from_stream_IMFAttributes(iface);
844 TRACE("%p, %s, %p, %p.\n", iface, debugstr_guid(key), buf, size);
846 return IMFAttributes_GetAllocatedBlob(stream->attributes, key, buf, size);
849 static HRESULT WINAPI video_stream_attributes_GetUnknown(IMFAttributes *iface, REFGUID key, REFIID riid, void **out)
851 struct video_stream *stream = impl_from_stream_IMFAttributes(iface);
853 TRACE("%p, %s, %s, %p.\n", iface, debugstr_guid(key), debugstr_guid(riid), out);
855 return IMFAttributes_GetUnknown(stream->attributes, key, riid, out);
858 static HRESULT WINAPI video_stream_attributes_SetItem(IMFAttributes *iface, REFGUID key, REFPROPVARIANT value)
860 struct video_stream *stream = impl_from_stream_IMFAttributes(iface);
862 TRACE("%p, %s, %p.\n", iface, debugstr_guid(key), value);
864 return IMFAttributes_SetItem(stream->attributes, key, value);
867 static HRESULT WINAPI video_stream_attributes_DeleteItem(IMFAttributes *iface, REFGUID key)
869 struct video_stream *stream = impl_from_stream_IMFAttributes(iface);
871 TRACE("%p, %s.\n", iface, debugstr_guid(key));
873 return IMFAttributes_DeleteItem(stream->attributes, key);
876 static HRESULT WINAPI video_stream_attributes_DeleteAllItems(IMFAttributes *iface)
878 struct video_stream *stream = impl_from_stream_IMFAttributes(iface);
880 TRACE("%p.\n", iface);
882 return IMFAttributes_DeleteAllItems(stream->attributes);
885 static HRESULT WINAPI video_stream_attributes_SetUINT32(IMFAttributes *iface, REFGUID key, UINT32 value)
887 struct video_stream *stream = impl_from_stream_IMFAttributes(iface);
889 TRACE("%p, %s, %u.\n", iface, debugstr_guid(key), value);
891 return IMFAttributes_SetUINT32(stream->attributes, key, value);
894 static HRESULT WINAPI video_stream_attributes_SetUINT64(IMFAttributes *iface, REFGUID key, UINT64 value)
896 struct video_stream *stream = impl_from_stream_IMFAttributes(iface);
898 TRACE("%p, %s, %s.\n", iface, debugstr_guid(key), wine_dbgstr_longlong(value));
900 return IMFAttributes_SetUINT64(stream->attributes, key, value);
903 static HRESULT WINAPI video_stream_attributes_SetDouble(IMFAttributes *iface, REFGUID key, double value)
905 struct video_stream *stream = impl_from_stream_IMFAttributes(iface);
907 TRACE("%p, %s, %f.\n", iface, debugstr_guid(key), value);
909 return IMFAttributes_SetDouble(stream->attributes, key, value);
912 static HRESULT WINAPI video_stream_attributes_SetGUID(IMFAttributes *iface, REFGUID key, REFGUID value)
914 struct video_stream *stream = impl_from_stream_IMFAttributes(iface);
916 TRACE("%p, %s, %s.\n", iface, debugstr_guid(key), debugstr_guid(value));
918 return IMFAttributes_SetGUID(stream->attributes, key, value);
921 static HRESULT WINAPI video_stream_attributes_SetString(IMFAttributes *iface, REFGUID key,
922 const WCHAR *value)
924 struct video_stream *stream = impl_from_stream_IMFAttributes(iface);
926 TRACE("%p, %s, %s.\n", iface, debugstr_guid(key), debugstr_w(value));
928 return IMFAttributes_SetString(stream->attributes, key, value);
931 static HRESULT WINAPI video_stream_attributes_SetBlob(IMFAttributes *iface, REFGUID key,
932 const UINT8 *buf, UINT32 size)
934 struct video_stream *stream = impl_from_stream_IMFAttributes(iface);
936 TRACE("%p, %s, %p, %u.\n", iface, debugstr_guid(key), buf, size);
938 return IMFAttributes_SetBlob(stream->attributes, key, buf, size);
941 static HRESULT WINAPI video_stream_attributes_SetUnknown(IMFAttributes *iface, REFGUID key,
942 IUnknown *unknown)
944 struct video_stream *stream = impl_from_stream_IMFAttributes(iface);
946 TRACE("%p, %s, %p.\n", iface, debugstr_guid(key), unknown);
948 return IMFAttributes_SetUnknown(stream->attributes, key, unknown);
951 static HRESULT WINAPI video_stream_attributes_LockStore(IMFAttributes *iface)
953 struct video_stream *stream = impl_from_stream_IMFAttributes(iface);
955 TRACE("%p.\n", iface);
957 return IMFAttributes_LockStore(stream->attributes);
960 static HRESULT WINAPI video_stream_attributes_UnlockStore(IMFAttributes *iface)
962 struct video_stream *stream = impl_from_stream_IMFAttributes(iface);
964 TRACE("%p.\n", iface);
966 return IMFAttributes_UnlockStore(stream->attributes);
969 static HRESULT WINAPI video_stream_attributes_GetCount(IMFAttributes *iface, UINT32 *count)
971 struct video_stream *stream = impl_from_stream_IMFAttributes(iface);
973 TRACE("%p, %p.\n", iface, count);
975 return IMFAttributes_GetCount(stream->attributes, count);
978 static HRESULT WINAPI video_stream_attributes_GetItemByIndex(IMFAttributes *iface, UINT32 index,
979 GUID *key, PROPVARIANT *value)
981 struct video_stream *stream = impl_from_stream_IMFAttributes(iface);
983 TRACE("%p, %u, %p, %p.\n", iface, index, key, value);
985 return IMFAttributes_GetItemByIndex(stream->attributes, index, key, value);
988 static HRESULT WINAPI video_stream_attributes_CopyAllItems(IMFAttributes *iface, IMFAttributes *dest)
990 struct video_stream *stream = impl_from_stream_IMFAttributes(iface);
992 TRACE("%p, %p.\n", iface, dest);
994 return IMFAttributes_CopyAllItems(stream->attributes, dest);
997 static const IMFAttributesVtbl video_stream_attributes_vtbl =
999 video_stream_attributes_QueryInterface,
1000 video_stream_attributes_AddRef,
1001 video_stream_attributes_Release,
1002 video_stream_attributes_GetItem,
1003 video_stream_attributes_GetItemType,
1004 video_stream_attributes_CompareItem,
1005 video_stream_attributes_Compare,
1006 video_stream_attributes_GetUINT32,
1007 video_stream_attributes_GetUINT64,
1008 video_stream_attributes_GetDouble,
1009 video_stream_attributes_GetGUID,
1010 video_stream_attributes_GetStringLength,
1011 video_stream_attributes_GetString,
1012 video_stream_attributes_GetAllocatedString,
1013 video_stream_attributes_GetBlobSize,
1014 video_stream_attributes_GetBlob,
1015 video_stream_attributes_GetAllocatedBlob,
1016 video_stream_attributes_GetUnknown,
1017 video_stream_attributes_SetItem,
1018 video_stream_attributes_DeleteItem,
1019 video_stream_attributes_DeleteAllItems,
1020 video_stream_attributes_SetUINT32,
1021 video_stream_attributes_SetUINT64,
1022 video_stream_attributes_SetDouble,
1023 video_stream_attributes_SetGUID,
1024 video_stream_attributes_SetString,
1025 video_stream_attributes_SetBlob,
1026 video_stream_attributes_SetUnknown,
1027 video_stream_attributes_LockStore,
1028 video_stream_attributes_UnlockStore,
1029 video_stream_attributes_GetCount,
1030 video_stream_attributes_GetItemByIndex,
1031 video_stream_attributes_CopyAllItems,
1034 static BOOL video_renderer_is_mixer_d3d_aware(const struct video_renderer *renderer)
1036 IMFAttributes *attributes;
1037 unsigned int value = 0;
1038 BOOL ret;
1040 if (FAILED(IMFTransform_QueryInterface(renderer->mixer, &IID_IMFAttributes, (void **)&attributes)))
1041 return FALSE;
1043 ret = SUCCEEDED(IMFAttributes_GetUINT32(attributes, &MF_SA_D3D_AWARE, &value)) && value;
1044 IMFAttributes_Release(attributes);
1045 return ret;
1048 static HRESULT video_renderer_stream_create(struct video_renderer *renderer, unsigned int id,
1049 struct video_stream **ret)
1051 struct video_stream *stream;
1052 IMFAttributes *attributes;
1053 unsigned int value;
1054 HRESULT hr;
1056 if (!(stream = calloc(1, sizeof(*stream))))
1057 return E_OUTOFMEMORY;
1059 stream->IMFStreamSink_iface.lpVtbl = &video_stream_sink_vtbl;
1060 stream->IMFMediaTypeHandler_iface.lpVtbl = &video_stream_type_handler_vtbl;
1061 stream->IMFGetService_iface.lpVtbl = &video_stream_get_service_vtbl;
1062 stream->IMFAttributes_iface.lpVtbl = &video_stream_attributes_vtbl;
1063 stream->refcount = 1;
1064 InitializeCriticalSection(&stream->cs);
1066 if (FAILED(hr = MFCreateEventQueue(&stream->event_queue)))
1067 goto failed;
1069 if (FAILED(hr = MFCreateAttributes(&stream->attributes, 0)))
1070 goto failed;
1072 stream->parent = renderer;
1073 IMFMediaSink_AddRef(&stream->parent->IMFMediaSink_iface);
1074 stream->id = id;
1076 if (video_renderer_is_mixer_d3d_aware(renderer))
1077 IMFAttributes_SetUINT32(stream->attributes, &MF_SA_D3D_AWARE, 1);
1079 if (SUCCEEDED(IMFTransform_GetInputStreamAttributes(renderer->mixer, id, &attributes)))
1081 if (SUCCEEDED(IMFAttributes_GetUINT32(attributes, &MF_SA_REQUIRED_SAMPLE_COUNT, &value)))
1082 IMFAttributes_SetUINT32(stream->attributes, &MF_SA_REQUIRED_SAMPLE_COUNT, value);
1083 IMFAttributes_Release(attributes);
1086 *ret = stream;
1088 return S_OK;
1090 failed:
1092 IMFStreamSink_Release(&stream->IMFStreamSink_iface);
1094 return hr;
1097 static HRESULT WINAPI video_renderer_sink_QueryInterface(IMFMediaSink *iface, REFIID riid, void **obj)
1099 struct video_renderer *renderer = impl_from_IMFMediaSink(iface);
1101 TRACE("%p, %s, %p.\n", iface, debugstr_guid(riid), obj);
1103 if (IsEqualIID(riid, &IID_IMFMediaSink) ||
1104 IsEqualIID(riid, &IID_IUnknown))
1106 *obj = &renderer->IMFMediaSink_iface;
1108 else if (IsEqualIID(riid, &IID_IMFMediaSinkPreroll))
1110 *obj = &renderer->IMFMediaSinkPreroll_iface;
1112 else if (IsEqualIID(riid, &IID_IMFVideoRenderer))
1114 *obj = &renderer->IMFVideoRenderer_iface;
1116 else if (IsEqualIID(riid, &IID_IMFMediaEventGenerator))
1118 *obj = &renderer->IMFMediaEventGenerator_iface;
1120 else if (IsEqualIID(riid, &IID_IMFClockStateSink))
1122 *obj = &renderer->IMFClockStateSink_iface;
1124 else if (IsEqualIID(riid, &IID_IMFGetService))
1126 *obj = &renderer->IMFGetService_iface;
1128 else if (IsEqualIID(riid, &IID_IMFAttributes))
1130 *obj = &renderer->IMFAttributes_iface;
1132 else if (IsEqualIID(riid, &IID_IMFQualityAdvise))
1134 *obj = &renderer->IMFQualityAdvise_iface;
1136 else if (IsEqualIID(riid, &IID_IMFRateSupport))
1138 *obj = &renderer->IMFRateSupport_iface;
1140 else
1142 WARN("Unsupported interface %s.\n", debugstr_guid(riid));
1143 *obj = NULL;
1144 return E_NOINTERFACE;
1147 IUnknown_AddRef((IUnknown *)*obj);
1149 return S_OK;
1152 static ULONG WINAPI video_renderer_sink_AddRef(IMFMediaSink *iface)
1154 struct video_renderer *renderer = impl_from_IMFMediaSink(iface);
1155 ULONG refcount = InterlockedIncrement(&renderer->refcount);
1156 TRACE("%p, refcount %u.\n", iface, refcount);
1157 return refcount;
1160 static ULONG WINAPI video_renderer_sink_Release(IMFMediaSink *iface)
1162 struct video_renderer *renderer = impl_from_IMFMediaSink(iface);
1163 ULONG refcount = InterlockedDecrement(&renderer->refcount);
1165 TRACE("%p, refcount %u.\n", iface, refcount);
1167 if (!refcount)
1169 if (renderer->event_queue)
1170 IMFMediaEventQueue_Release(renderer->event_queue);
1171 if (renderer->mixer)
1172 IMFTransform_Release(renderer->mixer);
1173 if (renderer->presenter)
1174 IMFVideoPresenter_Release(renderer->presenter);
1175 if (renderer->device_manager)
1176 IUnknown_Release(renderer->device_manager);
1177 if (renderer->clock)
1178 IMFPresentationClock_Release(renderer->clock);
1179 if (renderer->attributes)
1180 IMFAttributes_Release(renderer->attributes);
1181 DeleteCriticalSection(&renderer->cs);
1182 free(renderer);
1185 return refcount;
1188 static HRESULT WINAPI video_renderer_sink_GetCharacteristics(IMFMediaSink *iface, DWORD *flags)
1190 struct video_renderer *renderer = impl_from_IMFMediaSink(iface);
1192 TRACE("%p, %p.\n", iface, flags);
1194 if (renderer->flags & EVR_SHUT_DOWN)
1195 return MF_E_SHUTDOWN;
1197 *flags = MEDIASINK_CLOCK_REQUIRED | MEDIASINK_CAN_PREROLL;
1199 return S_OK;
1202 static HRESULT video_renderer_add_stream(struct video_renderer *renderer, unsigned int id,
1203 IMFStreamSink **stream_sink)
1205 struct video_stream *stream;
1206 HRESULT hr;
1208 if (!mf_array_reserve((void **)&renderer->streams, &renderer->stream_size, renderer->stream_count + 1,
1209 sizeof(*renderer->streams)))
1211 return E_OUTOFMEMORY;
1214 if (SUCCEEDED(hr = video_renderer_stream_create(renderer, id, &stream)))
1216 if (stream_sink)
1218 *stream_sink = &stream->IMFStreamSink_iface;
1219 IMFStreamSink_AddRef(*stream_sink);
1221 renderer->streams[renderer->stream_count++] = stream;
1224 return hr;
1227 static HRESULT WINAPI video_renderer_sink_AddStreamSink(IMFMediaSink *iface, DWORD id,
1228 IMFMediaType *media_type, IMFStreamSink **stream_sink)
1230 struct video_renderer *renderer = impl_from_IMFMediaSink(iface);
1231 HRESULT hr;
1233 TRACE("%p, %#x, %p, %p.\n", iface, id, media_type, stream_sink);
1235 /* Rely on mixer for stream id validation. */
1237 EnterCriticalSection(&renderer->cs);
1238 if (renderer->flags & EVR_SHUT_DOWN)
1239 hr = MF_E_SHUTDOWN;
1240 else if (SUCCEEDED(hr = IMFTransform_AddInputStreams(renderer->mixer, 1, &id)))
1242 if (FAILED(hr = video_renderer_add_stream(renderer, id, stream_sink)))
1243 IMFTransform_DeleteInputStream(renderer->mixer, id);
1246 LeaveCriticalSection(&renderer->cs);
1248 return hr;
1251 static HRESULT WINAPI video_renderer_sink_RemoveStreamSink(IMFMediaSink *iface, DWORD id)
1253 struct video_renderer *renderer = impl_from_IMFMediaSink(iface);
1254 HRESULT hr;
1255 size_t i;
1257 TRACE("%p, %#x.\n", iface, id);
1259 /* Rely on mixer for stream id validation. */
1261 EnterCriticalSection(&renderer->cs);
1262 if (renderer->flags & EVR_SHUT_DOWN)
1263 hr = MF_E_SHUTDOWN;
1264 else if (SUCCEEDED(hr = IMFTransform_DeleteInputStream(renderer->mixer, id)))
1266 for (i = 0; i < renderer->stream_count; ++i)
1268 if (renderer->streams[i]->id == id)
1270 IMFStreamSink_Release(&renderer->streams[i]->IMFStreamSink_iface);
1271 renderer->streams[i] = NULL;
1272 if (i < renderer->stream_count - 1)
1274 memmove(&renderer->streams[i], &renderer->streams[i+1],
1275 (renderer->stream_count - i - 1) * sizeof(*renderer->streams));
1277 renderer->stream_count--;
1278 break;
1282 LeaveCriticalSection(&renderer->cs);
1284 return hr;
1287 static HRESULT WINAPI video_renderer_sink_GetStreamSinkCount(IMFMediaSink *iface, DWORD *count)
1289 struct video_renderer *renderer = impl_from_IMFMediaSink(iface);
1290 HRESULT hr = S_OK;
1292 TRACE("%p, %p.\n", iface, count);
1294 if (!count)
1295 return E_POINTER;
1297 EnterCriticalSection(&renderer->cs);
1298 if (renderer->flags & EVR_SHUT_DOWN)
1299 hr = MF_E_SHUTDOWN;
1300 else if (!count)
1301 hr = E_POINTER;
1302 else
1303 *count = renderer->stream_count;
1304 LeaveCriticalSection(&renderer->cs);
1306 return hr;
1309 static HRESULT WINAPI video_renderer_sink_GetStreamSinkByIndex(IMFMediaSink *iface, DWORD index,
1310 IMFStreamSink **stream)
1312 struct video_renderer *renderer = impl_from_IMFMediaSink(iface);
1313 HRESULT hr = S_OK;
1315 TRACE("%p, %u, %p.\n", iface, index, stream);
1317 EnterCriticalSection(&renderer->cs);
1318 if (renderer->flags & EVR_SHUT_DOWN)
1319 hr = MF_E_SHUTDOWN;
1320 else if (!stream)
1321 hr = E_POINTER;
1322 else if (index >= renderer->stream_count)
1323 hr = E_INVALIDARG;
1324 else
1326 *stream = &renderer->streams[index]->IMFStreamSink_iface;
1327 IMFStreamSink_AddRef(*stream);
1329 LeaveCriticalSection(&renderer->cs);
1331 return hr;
1334 static HRESULT WINAPI video_renderer_sink_GetStreamSinkById(IMFMediaSink *iface, DWORD id,
1335 IMFStreamSink **stream)
1337 struct video_renderer *renderer = impl_from_IMFMediaSink(iface);
1338 HRESULT hr = S_OK;
1339 size_t i;
1341 TRACE("%p, %#x, %p.\n", iface, id, stream);
1343 EnterCriticalSection(&renderer->cs);
1344 if (renderer->flags & EVR_SHUT_DOWN)
1345 hr = MF_E_SHUTDOWN;
1346 else if (!stream)
1347 hr = E_POINTER;
1348 else
1350 for (i = 0; i < renderer->stream_count; ++i)
1352 if (renderer->streams[i]->id == id)
1353 break;
1356 if (i == renderer->stream_count)
1357 hr = MF_E_INVALIDSTREAMNUMBER;
1358 else
1360 *stream = &renderer->streams[i]->IMFStreamSink_iface;
1361 IMFStreamSink_AddRef(*stream);
1364 LeaveCriticalSection(&renderer->cs);
1366 return hr;
1369 static void video_renderer_set_presentation_clock(struct video_renderer *renderer, IMFPresentationClock *clock)
1371 if (renderer->clock)
1373 IMFPresentationClock_RemoveClockStateSink(renderer->clock, &renderer->IMFClockStateSink_iface);
1374 IMFPresentationClock_Release(renderer->clock);
1376 video_renderer_release_presenter_services(renderer);
1378 renderer->clock = clock;
1379 if (renderer->clock)
1381 IMFPresentationClock_AddRef(renderer->clock);
1382 IMFPresentationClock_AddClockStateSink(renderer->clock, &renderer->IMFClockStateSink_iface);
1384 video_renderer_init_presenter_services(renderer);
1387 static HRESULT WINAPI video_renderer_sink_SetPresentationClock(IMFMediaSink *iface, IMFPresentationClock *clock)
1389 struct video_renderer *renderer = impl_from_IMFMediaSink(iface);
1390 HRESULT hr = S_OK;
1392 TRACE("%p, %p.\n", iface, clock);
1394 EnterCriticalSection(&renderer->cs);
1396 if (renderer->flags & EVR_SHUT_DOWN)
1397 hr = MF_E_SHUTDOWN;
1398 else
1399 video_renderer_set_presentation_clock(renderer, clock);
1401 LeaveCriticalSection(&renderer->cs);
1403 return hr;
1406 static HRESULT WINAPI video_renderer_sink_GetPresentationClock(IMFMediaSink *iface, IMFPresentationClock **clock)
1408 struct video_renderer *renderer = impl_from_IMFMediaSink(iface);
1409 HRESULT hr = S_OK;
1411 TRACE("%p, %p.\n", iface, clock);
1413 if (!clock)
1414 return E_POINTER;
1416 EnterCriticalSection(&renderer->cs);
1418 if (renderer->flags & EVR_SHUT_DOWN)
1419 hr = MF_E_SHUTDOWN;
1420 else if (renderer->clock)
1422 *clock = renderer->clock;
1423 IMFPresentationClock_AddRef(*clock);
1425 else
1426 hr = MF_E_NO_CLOCK;
1428 LeaveCriticalSection(&renderer->cs);
1430 return hr;
1433 static HRESULT WINAPI video_renderer_sink_Shutdown(IMFMediaSink *iface)
1435 struct video_renderer *renderer = impl_from_IMFMediaSink(iface);
1436 size_t i;
1438 TRACE("%p.\n", iface);
1440 if (renderer->flags & EVR_SHUT_DOWN)
1441 return MF_E_SHUTDOWN;
1443 EnterCriticalSection(&renderer->cs);
1444 renderer->flags |= EVR_SHUT_DOWN;
1445 /* Detach streams from the sink. */
1446 for (i = 0; i < renderer->stream_count; ++i)
1448 struct video_stream *stream = renderer->streams[i];
1450 EnterCriticalSection(&stream->cs);
1451 stream->parent = NULL;
1452 LeaveCriticalSection(&stream->cs);
1454 IMFMediaEventQueue_Shutdown(stream->event_queue);
1455 IMFStreamSink_Release(&stream->IMFStreamSink_iface);
1456 IMFMediaSink_Release(iface);
1457 renderer->streams[i] = NULL;
1459 free(renderer->streams);
1460 renderer->stream_count = 0;
1461 renderer->stream_size = 0;
1462 IMFMediaEventQueue_Shutdown(renderer->event_queue);
1463 video_renderer_set_presentation_clock(renderer, NULL);
1464 video_renderer_release_services(renderer);
1465 LeaveCriticalSection(&renderer->cs);
1467 return S_OK;
1470 static const IMFMediaSinkVtbl video_renderer_sink_vtbl =
1472 video_renderer_sink_QueryInterface,
1473 video_renderer_sink_AddRef,
1474 video_renderer_sink_Release,
1475 video_renderer_sink_GetCharacteristics,
1476 video_renderer_sink_AddStreamSink,
1477 video_renderer_sink_RemoveStreamSink,
1478 video_renderer_sink_GetStreamSinkCount,
1479 video_renderer_sink_GetStreamSinkByIndex,
1480 video_renderer_sink_GetStreamSinkById,
1481 video_renderer_sink_SetPresentationClock,
1482 video_renderer_sink_GetPresentationClock,
1483 video_renderer_sink_Shutdown,
1486 static HRESULT WINAPI video_renderer_preroll_QueryInterface(IMFMediaSinkPreroll *iface, REFIID riid, void **obj)
1488 struct video_renderer *renderer = impl_from_IMFMediaSinkPreroll(iface);
1489 return IMFMediaSink_QueryInterface(&renderer->IMFMediaSink_iface, riid, obj);
1492 static ULONG WINAPI video_renderer_preroll_AddRef(IMFMediaSinkPreroll *iface)
1494 struct video_renderer *renderer = impl_from_IMFMediaSinkPreroll(iface);
1495 return IMFMediaSink_AddRef(&renderer->IMFMediaSink_iface);
1498 static ULONG WINAPI video_renderer_preroll_Release(IMFMediaSinkPreroll *iface)
1500 struct video_renderer *renderer = impl_from_IMFMediaSinkPreroll(iface);
1501 return IMFMediaSink_Release(&renderer->IMFMediaSink_iface);
1504 static HRESULT WINAPI video_renderer_preroll_NotifyPreroll(IMFMediaSinkPreroll *iface, MFTIME start_time)
1506 struct video_renderer *renderer = impl_from_IMFMediaSinkPreroll(iface);
1507 HRESULT hr = S_OK;
1508 size_t i;
1510 TRACE("%p, %s.\n", iface, debugstr_time(start_time));
1512 EnterCriticalSection(&renderer->cs);
1513 if (renderer->flags & EVR_SHUT_DOWN)
1514 hr = MF_E_SHUTDOWN;
1515 else
1517 for (i = 0; i < renderer->stream_count; ++i)
1519 struct video_stream *stream = renderer->streams[i];
1521 EnterCriticalSection(&stream->cs);
1522 if (!(stream->flags & (EVR_STREAM_PREROLLING | EVR_STREAM_PREROLLED)))
1524 IMFMediaEventQueue_QueueEventParamVar(stream->event_queue, MEStreamSinkRequestSample,
1525 &GUID_NULL, S_OK, NULL);
1526 stream->flags |= EVR_STREAM_PREROLLING;
1528 LeaveCriticalSection(&stream->cs);
1531 LeaveCriticalSection(&renderer->cs);
1533 return hr;
1536 static const IMFMediaSinkPrerollVtbl video_renderer_preroll_vtbl =
1538 video_renderer_preroll_QueryInterface,
1539 video_renderer_preroll_AddRef,
1540 video_renderer_preroll_Release,
1541 video_renderer_preroll_NotifyPreroll,
1544 static HRESULT WINAPI video_renderer_QueryInterface(IMFVideoRenderer *iface, REFIID riid, void **obj)
1546 struct video_renderer *renderer = impl_from_IMFVideoRenderer(iface);
1547 return IMFMediaSink_QueryInterface(&renderer->IMFMediaSink_iface, riid, obj);
1550 static ULONG WINAPI video_renderer_AddRef(IMFVideoRenderer *iface)
1552 struct video_renderer *renderer = impl_from_IMFVideoRenderer(iface);
1553 return IMFMediaSink_AddRef(&renderer->IMFMediaSink_iface);
1556 static ULONG WINAPI video_renderer_Release(IMFVideoRenderer *iface)
1558 struct video_renderer *renderer = impl_from_IMFVideoRenderer(iface);
1559 return IMFMediaSink_Release(&renderer->IMFMediaSink_iface);
1562 static HRESULT video_renderer_create_mixer(IMFAttributes *attributes, IMFTransform **out)
1564 unsigned int flags = 0;
1565 IMFActivate *activate;
1566 CLSID clsid;
1567 HRESULT hr;
1569 if (attributes && SUCCEEDED(hr = IMFAttributes_GetUnknown(attributes, &MF_ACTIVATE_CUSTOM_VIDEO_MIXER_ACTIVATE,
1570 &IID_IMFActivate, (void **)&activate)))
1572 IMFAttributes_GetUINT32(attributes, &MF_ACTIVATE_CUSTOM_VIDEO_MIXER_FLAGS, &flags);
1573 hr = IMFActivate_ActivateObject(activate, &IID_IMFTransform, (void **)out);
1574 IMFActivate_Release(activate);
1575 if (SUCCEEDED(hr) || !(flags & MF_ACTIVATE_CUSTOM_MIXER_ALLOWFAIL))
1576 return hr;
1579 if (!attributes || FAILED(IMFAttributes_GetGUID(attributes, &MF_ACTIVATE_CUSTOM_VIDEO_MIXER_CLSID, &clsid)))
1580 memcpy(&clsid, &CLSID_MFVideoMixer9, sizeof(clsid));
1582 return CoCreateInstance(&clsid, NULL, CLSCTX_INPROC_SERVER, &IID_IMFTransform, (void **)out);
1585 static HRESULT video_renderer_create_presenter(struct video_renderer *renderer, IMFAttributes *attributes,
1586 IMFVideoPresenter **out)
1588 unsigned int flags = 0;
1589 IMFActivate *activate;
1590 UINT64 value;
1591 CLSID clsid;
1592 HRESULT hr;
1594 if (attributes && SUCCEEDED(IMFAttributes_GetUINT64(attributes, &MF_ACTIVATE_VIDEO_WINDOW, &value)))
1595 renderer->window = UlongToHandle(value);
1597 if (attributes && SUCCEEDED(IMFAttributes_GetUnknown(attributes, &MF_ACTIVATE_CUSTOM_VIDEO_PRESENTER_ACTIVATE,
1598 &IID_IMFActivate, (void **)&activate)))
1600 IMFAttributes_GetUINT32(attributes, &MF_ACTIVATE_CUSTOM_VIDEO_PRESENTER_FLAGS, &flags);
1601 hr = IMFActivate_ActivateObject(activate, &IID_IMFVideoPresenter, (void **)out);
1602 IMFActivate_Release(activate);
1603 if (SUCCEEDED(hr) || !(flags & MF_ACTIVATE_CUSTOM_PRESENTER_ALLOWFAIL))
1604 return hr;
1607 if (!attributes || FAILED(IMFAttributes_GetGUID(attributes, &MF_ACTIVATE_CUSTOM_VIDEO_PRESENTER_CLSID, &clsid)))
1608 memcpy(&clsid, &CLSID_MFVideoPresenter9, sizeof(clsid));
1610 return CoCreateInstance(&clsid, NULL, CLSCTX_INPROC_SERVER, &IID_IMFVideoPresenter, (void **)out);
1613 static HRESULT video_renderer_configure_mixer(struct video_renderer *renderer)
1615 IMFTopologyServiceLookupClient *lookup_client;
1616 HRESULT hr;
1618 if (SUCCEEDED(hr = IMFTransform_QueryInterface(renderer->mixer, &IID_IMFTopologyServiceLookupClient,
1619 (void **)&lookup_client)))
1621 renderer->flags |= EVR_INIT_SERVICES;
1622 if (SUCCEEDED(hr = IMFTopologyServiceLookupClient_InitServicePointers(lookup_client,
1623 &renderer->IMFTopologyServiceLookup_iface)))
1625 renderer->flags |= EVR_MIXER_INITED_SERVICES;
1627 renderer->flags &= ~EVR_INIT_SERVICES;
1628 IMFTopologyServiceLookupClient_Release(lookup_client);
1631 if (SUCCEEDED(hr))
1633 unsigned int input_count, output_count;
1634 unsigned int *ids, *oids;
1635 size_t i;
1637 /* Create stream sinks for inputs that mixer already has by default. */
1638 if (SUCCEEDED(IMFTransform_GetStreamCount(renderer->mixer, &input_count, &output_count)))
1640 ids = calloc(input_count, sizeof(*ids));
1641 oids = calloc(output_count, sizeof(*oids));
1643 if (ids && oids)
1645 if (SUCCEEDED(IMFTransform_GetStreamIDs(renderer->mixer, input_count, ids, output_count, oids)))
1647 for (i = 0; i < input_count; ++i)
1649 video_renderer_add_stream(renderer, ids[i], NULL);
1655 free(ids);
1656 free(oids);
1660 /* Set device manager that presenter should have created. */
1661 if (video_renderer_is_mixer_d3d_aware(renderer))
1663 IDirect3DDeviceManager9 *device_manager;
1665 if (SUCCEEDED(MFGetService((IUnknown *)renderer->presenter, &MR_VIDEO_ACCELERATION_SERVICE,
1666 &IID_IDirect3DDeviceManager9, (void **)&device_manager)))
1668 IMFTransform_ProcessMessage(renderer->mixer, MFT_MESSAGE_SET_D3D_MANAGER, (ULONG_PTR)device_manager);
1669 IDirect3DDeviceManager9_Release(device_manager);
1673 return hr;
1676 static HRESULT video_renderer_configure_presenter(struct video_renderer *renderer)
1678 IMFVideoDisplayControl *control;
1679 RECT rect = { 0 };
1680 HRESULT hr;
1682 if (SUCCEEDED(IMFVideoPresenter_QueryInterface(renderer->presenter, &IID_IMFVideoDisplayControl, (void **)&control)))
1684 GetClientRect(renderer->window, &rect);
1686 if (SUCCEEDED(hr = IMFVideoDisplayControl_SetVideoWindow(control, renderer->window)))
1687 hr = IMFVideoDisplayControl_SetVideoPosition(control, NULL, &rect);
1688 IMFVideoDisplayControl_Release(control);
1691 hr = video_renderer_init_presenter_services(renderer);
1693 if (FAILED(MFGetService((IUnknown *)renderer->presenter, &MR_VIDEO_ACCELERATION_SERVICE,
1694 &IID_IUnknown, (void **)&renderer->device_manager)))
1696 WARN("Failed to get device manager from the presenter.\n");
1699 return hr;
1702 static HRESULT video_renderer_initialize(struct video_renderer *renderer, IMFTransform *mixer,
1703 IMFVideoPresenter *presenter)
1705 HRESULT hr;
1707 if (renderer->mixer)
1709 IMFTransform_Release(renderer->mixer);
1710 renderer->mixer = NULL;
1713 if (renderer->presenter)
1715 IMFVideoPresenter_Release(renderer->presenter);
1716 renderer->presenter = NULL;
1719 if (renderer->device_manager)
1721 IUnknown_Release(renderer->device_manager);
1722 renderer->device_manager = NULL;
1725 renderer->mixer = mixer;
1726 IMFTransform_AddRef(renderer->mixer);
1728 renderer->presenter = presenter;
1729 IMFVideoPresenter_AddRef(renderer->presenter);
1731 if (SUCCEEDED(hr = video_renderer_configure_mixer(renderer)))
1732 hr = video_renderer_configure_presenter(renderer);
1734 return hr;
1737 static HRESULT WINAPI video_renderer_InitializeRenderer(IMFVideoRenderer *iface, IMFTransform *mixer,
1738 IMFVideoPresenter *presenter)
1740 struct video_renderer *renderer = impl_from_IMFVideoRenderer(iface);
1741 HRESULT hr;
1743 TRACE("%p, %p, %p.\n", iface, mixer, presenter);
1745 if (mixer)
1746 IMFTransform_AddRef(mixer);
1747 else if (FAILED(hr = video_renderer_create_mixer(NULL, &mixer)))
1749 WARN("Failed to create default mixer object, hr %#x.\n", hr);
1750 return hr;
1753 if (presenter)
1754 IMFVideoPresenter_AddRef(presenter);
1755 else if (FAILED(hr = video_renderer_create_presenter(renderer, NULL, &presenter)))
1757 WARN("Failed to create default presenter, hr %#x.\n", hr);
1758 IMFTransform_Release(mixer);
1759 return hr;
1762 EnterCriticalSection(&renderer->cs);
1764 if (renderer->flags & EVR_SHUT_DOWN)
1765 hr = MF_E_SHUTDOWN;
1766 else
1768 /* FIXME: check clock state */
1769 /* FIXME: check that streams are not initialized */
1771 hr = video_renderer_initialize(renderer, mixer, presenter);
1774 LeaveCriticalSection(&renderer->cs);
1776 IMFTransform_Release(mixer);
1777 IMFVideoPresenter_Release(presenter);
1779 return hr;
1782 static const IMFVideoRendererVtbl video_renderer_vtbl =
1784 video_renderer_QueryInterface,
1785 video_renderer_AddRef,
1786 video_renderer_Release,
1787 video_renderer_InitializeRenderer,
1790 static HRESULT WINAPI video_renderer_events_QueryInterface(IMFMediaEventGenerator *iface, REFIID riid, void **obj)
1792 struct video_renderer *renderer = impl_from_IMFMediaEventGenerator(iface);
1793 return IMFMediaSink_QueryInterface(&renderer->IMFMediaSink_iface, riid, obj);
1796 static ULONG WINAPI video_renderer_events_AddRef(IMFMediaEventGenerator *iface)
1798 struct video_renderer *renderer = impl_from_IMFMediaEventGenerator(iface);
1799 return IMFMediaSink_AddRef(&renderer->IMFMediaSink_iface);
1802 static ULONG WINAPI video_renderer_events_Release(IMFMediaEventGenerator *iface)
1804 struct video_renderer *renderer = impl_from_IMFMediaEventGenerator(iface);
1805 return IMFMediaSink_Release(&renderer->IMFMediaSink_iface);
1808 static HRESULT WINAPI video_renderer_events_GetEvent(IMFMediaEventGenerator *iface, DWORD flags, IMFMediaEvent **event)
1810 struct video_renderer *renderer = impl_from_IMFMediaEventGenerator(iface);
1812 TRACE("%p, %#x, %p.\n", iface, flags, event);
1814 return IMFMediaEventQueue_GetEvent(renderer->event_queue, flags, event);
1817 static HRESULT WINAPI video_renderer_events_BeginGetEvent(IMFMediaEventGenerator *iface, IMFAsyncCallback *callback,
1818 IUnknown *state)
1820 struct video_renderer *renderer = impl_from_IMFMediaEventGenerator(iface);
1822 TRACE("%p, %p, %p.\n", iface, callback, state);
1824 return IMFMediaEventQueue_BeginGetEvent(renderer->event_queue, callback, state);
1827 static HRESULT WINAPI video_renderer_events_EndGetEvent(IMFMediaEventGenerator *iface, IMFAsyncResult *result,
1828 IMFMediaEvent **event)
1830 struct video_renderer *renderer = impl_from_IMFMediaEventGenerator(iface);
1832 TRACE("%p, %p, %p.\n", iface, result, event);
1834 return IMFMediaEventQueue_EndGetEvent(renderer->event_queue, result, event);
1837 static HRESULT WINAPI video_renderer_events_QueueEvent(IMFMediaEventGenerator *iface, MediaEventType event_type,
1838 REFGUID ext_type, HRESULT hr, const PROPVARIANT *value)
1840 struct video_renderer *renderer = impl_from_IMFMediaEventGenerator(iface);
1842 TRACE("%p, %u, %s, %#x, %p.\n", iface, event_type, debugstr_guid(ext_type), hr, value);
1844 return IMFMediaEventQueue_QueueEventParamVar(renderer->event_queue, event_type, ext_type, hr, value);
1847 static const IMFMediaEventGeneratorVtbl video_renderer_events_vtbl =
1849 video_renderer_events_QueryInterface,
1850 video_renderer_events_AddRef,
1851 video_renderer_events_Release,
1852 video_renderer_events_GetEvent,
1853 video_renderer_events_BeginGetEvent,
1854 video_renderer_events_EndGetEvent,
1855 video_renderer_events_QueueEvent,
1858 static HRESULT WINAPI video_renderer_clock_sink_QueryInterface(IMFClockStateSink *iface, REFIID riid, void **obj)
1860 struct video_renderer *renderer = impl_from_IMFClockStateSink(iface);
1861 return IMFMediaSink_QueryInterface(&renderer->IMFMediaSink_iface, riid, obj);
1864 static ULONG WINAPI video_renderer_clock_sink_AddRef(IMFClockStateSink *iface)
1866 struct video_renderer *renderer = impl_from_IMFClockStateSink(iface);
1867 return IMFMediaSink_AddRef(&renderer->IMFMediaSink_iface);
1870 static ULONG WINAPI video_renderer_clock_sink_Release(IMFClockStateSink *iface)
1872 struct video_renderer *renderer = impl_from_IMFClockStateSink(iface);
1873 return IMFMediaSink_Release(&renderer->IMFMediaSink_iface);
1876 static HRESULT WINAPI video_renderer_clock_sink_OnClockStart(IMFClockStateSink *iface, MFTIME systime, LONGLONG offset)
1878 struct video_renderer *renderer = impl_from_IMFClockStateSink(iface);
1879 unsigned int state, request_sample;
1880 size_t i;
1882 TRACE("%p, %s, %s.\n", iface, debugstr_time(systime), debugstr_time(offset));
1884 EnterCriticalSection(&renderer->cs);
1886 state = renderer->state;
1888 /* Update sink state before sending sample requests, to avoid potentially receiving new sample in stopped state */
1889 renderer->state = EVR_STATE_RUNNING;
1891 if (state == EVR_STATE_STOPPED)
1893 IMFTransform_ProcessMessage(renderer->mixer, MFT_MESSAGE_NOTIFY_BEGIN_STREAMING, 0);
1894 IMFVideoPresenter_ProcessMessage(renderer->presenter, MFVP_MESSAGE_BEGINSTREAMING, 0);
1896 for (i = 0; i < renderer->stream_count; ++i)
1898 struct video_stream *stream = renderer->streams[i];
1900 EnterCriticalSection(&stream->cs);
1901 request_sample = !(stream->flags & EVR_STREAM_PREROLLED) || (stream->flags & EVR_STREAM_SAMPLE_NEEDED);
1902 stream->flags |= EVR_STREAM_PREROLLED;
1903 stream->flags &= ~EVR_STREAM_SAMPLE_NEEDED;
1904 LeaveCriticalSection(&stream->cs);
1906 IMFMediaEventQueue_QueueEventParamVar(stream->event_queue, MEStreamSinkStarted, &GUID_NULL, S_OK, NULL);
1907 if (request_sample)
1908 IMFMediaEventQueue_QueueEventParamVar(stream->event_queue, MEStreamSinkRequestSample,
1909 &GUID_NULL, S_OK, NULL);
1913 IMFVideoPresenter_OnClockStart(renderer->presenter, systime, offset);
1915 LeaveCriticalSection(&renderer->cs);
1917 return S_OK;
1920 static HRESULT WINAPI video_renderer_clock_sink_OnClockStop(IMFClockStateSink *iface, MFTIME systime)
1922 struct video_renderer *renderer = impl_from_IMFClockStateSink(iface);
1923 size_t i;
1925 TRACE("%p, %s.\n", iface, debugstr_time(systime));
1927 EnterCriticalSection(&renderer->cs);
1929 IMFVideoPresenter_OnClockStop(renderer->presenter, systime);
1931 IMFTransform_ProcessMessage(renderer->mixer, MFT_MESSAGE_COMMAND_FLUSH, 0);
1932 IMFVideoPresenter_ProcessMessage(renderer->presenter, MFVP_MESSAGE_FLUSH, 0);
1934 if (renderer->state == EVR_STATE_RUNNING ||
1935 renderer->state == EVR_STATE_PAUSED)
1937 IMFTransform_ProcessMessage(renderer->mixer, MFT_MESSAGE_NOTIFY_END_STREAMING, 0);
1938 IMFVideoPresenter_ProcessMessage(renderer->presenter, MFVP_MESSAGE_ENDSTREAMING, 0);
1940 for (i = 0; i < renderer->stream_count; ++i)
1942 struct video_stream *stream = renderer->streams[i];
1943 IMFMediaEventQueue_QueueEventParamVar(stream->event_queue, MEStreamSinkStopped, &GUID_NULL, S_OK, NULL);
1945 EnterCriticalSection(&stream->cs);
1946 stream->flags &= ~(EVR_STREAM_PREROLLED | EVR_STREAM_SAMPLE_NEEDED);
1947 LeaveCriticalSection(&stream->cs);
1949 renderer->state = EVR_STATE_STOPPED;
1952 LeaveCriticalSection(&renderer->cs);
1954 return S_OK;
1957 static HRESULT WINAPI video_renderer_clock_sink_OnClockPause(IMFClockStateSink *iface, MFTIME systime)
1959 struct video_renderer *renderer = impl_from_IMFClockStateSink(iface);
1960 size_t i;
1962 TRACE("%p, %s.\n", iface, debugstr_time(systime));
1964 EnterCriticalSection(&renderer->cs);
1966 IMFVideoPresenter_OnClockPause(renderer->presenter, systime);
1968 if (renderer->state == EVR_STATE_RUNNING)
1970 for (i = 0; i < renderer->stream_count; ++i)
1972 struct video_stream *stream = renderer->streams[i];
1973 IMFMediaEventQueue_QueueEventParamVar(stream->event_queue, MEStreamSinkPaused, &GUID_NULL, S_OK, NULL);
1977 renderer->state = EVR_STATE_PAUSED;
1979 LeaveCriticalSection(&renderer->cs);
1981 return S_OK;
1984 static HRESULT WINAPI video_renderer_clock_sink_OnClockRestart(IMFClockStateSink *iface, MFTIME systime)
1986 struct video_renderer *renderer = impl_from_IMFClockStateSink(iface);
1987 size_t i;
1989 TRACE("%p, %s.\n", iface, debugstr_time(systime));
1991 EnterCriticalSection(&renderer->cs);
1993 IMFVideoPresenter_OnClockRestart(renderer->presenter, systime);
1995 for (i = 0; i < renderer->stream_count; ++i)
1997 struct video_stream *stream = renderer->streams[i];
1998 IMFMediaEventQueue_QueueEventParamVar(stream->event_queue, MEStreamSinkStarted, &GUID_NULL, S_OK, NULL);
2000 renderer->state = EVR_STATE_RUNNING;
2002 LeaveCriticalSection(&renderer->cs);
2004 return S_OK;
2007 static HRESULT WINAPI video_renderer_clock_sink_OnClockSetRate(IMFClockStateSink *iface, MFTIME systime, float rate)
2009 struct video_renderer *renderer = impl_from_IMFClockStateSink(iface);
2010 IMFClockStateSink *sink;
2012 TRACE("%p, %s, %f.\n", iface, debugstr_time(systime), rate);
2014 EnterCriticalSection(&renderer->cs);
2016 IMFVideoPresenter_OnClockSetRate(renderer->presenter, systime, rate);
2017 if (SUCCEEDED(IMFTransform_QueryInterface(renderer->mixer, &IID_IMFClockStateSink, (void **)&sink)))
2019 IMFClockStateSink_OnClockSetRate(sink, systime, rate);
2020 IMFClockStateSink_Release(sink);
2023 LeaveCriticalSection(&renderer->cs);
2025 return S_OK;
2028 static const IMFClockStateSinkVtbl video_renderer_clock_sink_vtbl =
2030 video_renderer_clock_sink_QueryInterface,
2031 video_renderer_clock_sink_AddRef,
2032 video_renderer_clock_sink_Release,
2033 video_renderer_clock_sink_OnClockStart,
2034 video_renderer_clock_sink_OnClockStop,
2035 video_renderer_clock_sink_OnClockPause,
2036 video_renderer_clock_sink_OnClockRestart,
2037 video_renderer_clock_sink_OnClockSetRate,
2040 static HRESULT WINAPI video_renderer_get_service_QueryInterface(IMFGetService *iface, REFIID riid, void **obj)
2042 struct video_renderer *renderer = impl_from_IMFGetService(iface);
2043 return IMFMediaSink_QueryInterface(&renderer->IMFMediaSink_iface, riid, obj);
2046 static ULONG WINAPI video_renderer_get_service_AddRef(IMFGetService *iface)
2048 struct video_renderer *renderer = impl_from_IMFGetService(iface);
2049 return IMFMediaSink_AddRef(&renderer->IMFMediaSink_iface);
2052 static ULONG WINAPI video_renderer_get_service_Release(IMFGetService *iface)
2054 struct video_renderer *renderer = impl_from_IMFGetService(iface);
2055 return IMFMediaSink_Release(&renderer->IMFMediaSink_iface);
2058 static HRESULT WINAPI video_renderer_get_service_GetService(IMFGetService *iface, REFGUID service, REFIID riid, void **obj)
2060 struct video_renderer *renderer = impl_from_IMFGetService(iface);
2061 HRESULT hr = E_NOINTERFACE;
2062 IMFGetService *gs = NULL;
2064 TRACE("%p, %s, %s, %p.\n", iface, debugstr_guid(service), debugstr_guid(riid), obj);
2066 EnterCriticalSection(&renderer->cs);
2068 if (IsEqualGUID(service, &MR_VIDEO_MIXER_SERVICE))
2070 hr = IMFTransform_QueryInterface(renderer->mixer, &IID_IMFGetService, (void **)&gs);
2072 else if (IsEqualGUID(service, &MR_VIDEO_RENDER_SERVICE))
2074 hr = IMFVideoPresenter_QueryInterface(renderer->presenter, &IID_IMFGetService, (void **)&gs);
2076 else if (IsEqualGUID(service, &MR_VIDEO_ACCELERATION_SERVICE) && IsEqualIID(riid, &IID_IDirect3DDeviceManager9))
2078 if (renderer->device_manager)
2079 hr = IUnknown_QueryInterface(renderer->device_manager, riid, obj);
2081 else if (IsEqualGUID(service, &MF_RATE_CONTROL_SERVICE) && IsEqualIID(riid, &IID_IMFRateSupport))
2083 hr = IMFVideoRenderer_QueryInterface(&renderer->IMFVideoRenderer_iface, riid, obj);
2085 else
2087 FIXME("Unsupported service %s.\n", debugstr_guid(service));
2090 LeaveCriticalSection(&renderer->cs);
2092 if (gs)
2094 hr = IMFGetService_GetService(gs, service, riid, obj);
2095 IMFGetService_Release(gs);
2098 return hr;
2101 static const IMFGetServiceVtbl video_renderer_get_service_vtbl =
2103 video_renderer_get_service_QueryInterface,
2104 video_renderer_get_service_AddRef,
2105 video_renderer_get_service_Release,
2106 video_renderer_get_service_GetService,
2109 static HRESULT WINAPI video_renderer_service_lookup_QueryInterface(IMFTopologyServiceLookup *iface, REFIID riid, void **obj)
2111 TRACE("%p, %s, %p.\n", iface, debugstr_guid(riid), obj);
2113 if (IsEqualIID(riid, &IID_IMFTopologyServiceLookup) ||
2114 IsEqualIID(riid, &IID_IUnknown))
2116 *obj = iface;
2117 IMFTopologyServiceLookup_AddRef(iface);
2118 return S_OK;
2121 WARN("Unsupported interface %s.\n", debugstr_guid(riid));
2122 *obj = NULL;
2123 return E_NOINTERFACE;
2126 static ULONG WINAPI video_renderer_service_lookup_AddRef(IMFTopologyServiceLookup *iface)
2128 struct video_renderer *renderer = impl_from_IMFTopologyServiceLookup(iface);
2129 return IMFMediaSink_AddRef(&renderer->IMFMediaSink_iface);
2132 static ULONG WINAPI video_renderer_service_lookup_Release(IMFTopologyServiceLookup *iface)
2134 struct video_renderer *renderer = impl_from_IMFTopologyServiceLookup(iface);
2135 return IMFMediaSink_Release(&renderer->IMFMediaSink_iface);
2138 static HRESULT WINAPI video_renderer_service_lookup_LookupService(IMFTopologyServiceLookup *iface,
2139 MF_SERVICE_LOOKUP_TYPE lookup_type, DWORD index, REFGUID service, REFIID riid,
2140 void **objects, DWORD *num_objects)
2142 struct video_renderer *renderer = impl_from_IMFTopologyServiceLookup(iface);
2143 HRESULT hr = S_OK;
2145 TRACE("%p, %u, %u, %s, %s, %p, %p.\n", iface, lookup_type, index, debugstr_guid(service), debugstr_guid(riid),
2146 objects, num_objects);
2148 EnterCriticalSection(&renderer->cs);
2150 if (!(renderer->flags & EVR_INIT_SERVICES))
2151 hr = MF_E_NOTACCEPTING;
2152 else if (IsEqualGUID(service, &MR_VIDEO_RENDER_SERVICE))
2154 if (IsEqualIID(riid, &IID_IMediaEventSink))
2156 *objects = &renderer->IMediaEventSink_iface;
2157 IUnknown_AddRef((IUnknown *)*objects);
2159 else if (IsEqualIID(riid, &IID_IMFClock))
2161 *objects = renderer->clock;
2162 if (*objects)
2163 IUnknown_AddRef((IUnknown *)*objects);
2164 hr = *objects ? S_OK : E_NOINTERFACE;
2166 else
2168 FIXME("Unsupported interface %s for render service.\n", debugstr_guid(riid));
2169 hr = E_NOINTERFACE;
2172 else if (IsEqualGUID(service, &MR_VIDEO_MIXER_SERVICE))
2174 if (IsEqualIID(riid, &IID_IMFTransform))
2176 *objects = renderer->mixer;
2177 IUnknown_AddRef((IUnknown *)*objects);
2179 else
2181 FIXME("Unsupported interface %s for mixer service.\n", debugstr_guid(riid));
2182 hr = E_NOINTERFACE;
2185 else
2187 WARN("Unsupported service %s.\n", debugstr_guid(service));
2188 hr = MF_E_UNSUPPORTED_SERVICE;
2191 LeaveCriticalSection(&renderer->cs);
2193 return hr;
2196 static const IMFTopologyServiceLookupVtbl video_renderer_service_lookup_vtbl =
2198 video_renderer_service_lookup_QueryInterface,
2199 video_renderer_service_lookup_AddRef,
2200 video_renderer_service_lookup_Release,
2201 video_renderer_service_lookup_LookupService,
2204 static HRESULT WINAPI video_renderer_event_sink_QueryInterface(IMediaEventSink *iface, REFIID riid, void **obj)
2206 TRACE("%p, %s, %p.\n", iface, debugstr_guid(riid), obj);
2208 if (IsEqualIID(riid, &IID_IMediaEventSink) ||
2209 IsEqualIID(riid, &IID_IUnknown))
2211 *obj = iface;
2212 IMediaEventSink_AddRef(iface);
2213 return S_OK;
2216 WARN("Unsupported interface %s.\n", debugstr_guid(riid));
2217 *obj = NULL;
2218 return E_NOINTERFACE;
2221 static ULONG WINAPI video_renderer_event_sink_AddRef(IMediaEventSink *iface)
2223 struct video_renderer *renderer = impl_from_IMediaEventSink(iface);
2224 return IMFMediaSink_AddRef(&renderer->IMFMediaSink_iface);
2227 static ULONG WINAPI video_renderer_event_sink_Release(IMediaEventSink *iface)
2229 struct video_renderer *renderer = impl_from_IMediaEventSink(iface);
2230 return IMFMediaSink_Release(&renderer->IMFMediaSink_iface);
2233 static HRESULT WINAPI video_renderer_event_sink_Notify(IMediaEventSink *iface, LONG event, LONG_PTR param1, LONG_PTR param2)
2235 struct video_renderer *renderer = impl_from_IMediaEventSink(iface);
2236 HRESULT hr = S_OK;
2237 unsigned int idx;
2239 TRACE("%p, %d, %ld, %ld.\n", iface, event, param1, param2);
2241 EnterCriticalSection(&renderer->cs);
2243 if (event == EC_SAMPLE_NEEDED)
2245 idx = param1;
2246 if (idx >= renderer->stream_count)
2247 hr = MF_E_INVALIDSTREAMNUMBER;
2248 else if (renderer->state == EVR_STATE_RUNNING)
2250 hr = IMFMediaEventQueue_QueueEventParamVar(renderer->streams[idx]->event_queue,
2251 MEStreamSinkRequestSample, &GUID_NULL, S_OK, NULL);
2253 else
2255 /* Mixer asks for more input right after preroll too, before renderer finished running state transition.
2256 Mark such streams here, and issue requests later in OnClockStart(). */
2257 renderer->streams[idx]->flags |= EVR_STREAM_SAMPLE_NEEDED;
2260 else if (event == EC_DISPLAY_CHANGED)
2262 for (idx = 0; idx < renderer->stream_count; ++idx)
2263 IMFMediaEventQueue_QueueEventParamVar(renderer->streams[idx]->event_queue,
2264 MEStreamSinkDeviceChanged, &GUID_NULL, S_OK, NULL);
2266 else if (event >= EC_USER)
2268 PROPVARIANT code;
2270 code.vt = VT_I4;
2271 code.lVal = event;
2272 hr = IMFMediaEventQueue_QueueEventParamVar(renderer->event_queue, MERendererEvent,
2273 &GUID_NULL, S_OK, &code);
2275 else
2277 WARN("Unhandled event %d.\n", event);
2278 hr = MF_E_UNEXPECTED;
2281 LeaveCriticalSection(&renderer->cs);
2283 return hr;
2286 static const IMediaEventSinkVtbl media_event_sink_vtbl =
2288 video_renderer_event_sink_QueryInterface,
2289 video_renderer_event_sink_AddRef,
2290 video_renderer_event_sink_Release,
2291 video_renderer_event_sink_Notify,
2294 static HRESULT WINAPI video_renderer_attributes_QueryInterface(IMFAttributes *iface, REFIID riid, void **obj)
2296 struct video_renderer *renderer = impl_from_IMFAttributes(iface);
2297 return IMFMediaSink_QueryInterface(&renderer->IMFMediaSink_iface, riid, obj);
2300 static ULONG WINAPI video_renderer_attributes_AddRef(IMFAttributes *iface)
2302 struct video_renderer *renderer = impl_from_IMFAttributes(iface);
2303 return IMFMediaSink_AddRef(&renderer->IMFMediaSink_iface);
2306 static ULONG WINAPI video_renderer_attributes_Release(IMFAttributes *iface)
2308 struct video_renderer *renderer = impl_from_IMFAttributes(iface);
2309 return IMFMediaSink_Release(&renderer->IMFMediaSink_iface);
2312 static HRESULT WINAPI video_renderer_attributes_GetItem(IMFAttributes *iface, REFGUID key, PROPVARIANT *value)
2314 struct video_renderer *renderer = impl_from_IMFAttributes(iface);
2316 TRACE("%p, %s, %p.\n", iface, debugstr_guid(key), value);
2318 return IMFAttributes_GetItem(renderer->attributes, key, value);
2321 static HRESULT WINAPI video_renderer_attributes_GetItemType(IMFAttributes *iface, REFGUID key, MF_ATTRIBUTE_TYPE *type)
2323 struct video_renderer *renderer = impl_from_IMFAttributes(iface);
2325 TRACE("%p, %s, %p.\n", iface, debugstr_guid(key), type);
2327 return IMFAttributes_GetItemType(renderer->attributes, key, type);
2330 static HRESULT WINAPI video_renderer_attributes_CompareItem(IMFAttributes *iface, REFGUID key, REFPROPVARIANT value,
2331 BOOL *result)
2333 struct video_renderer *renderer = impl_from_IMFAttributes(iface);
2335 TRACE("%p, %s, %p, %p.\n", iface, debugstr_guid(key), value, result);
2337 return IMFAttributes_CompareItem(renderer->attributes, key, value, result);
2340 static HRESULT WINAPI video_renderer_attributes_Compare(IMFAttributes *iface, IMFAttributes *theirs,
2341 MF_ATTRIBUTES_MATCH_TYPE type, BOOL *result)
2343 struct video_renderer *renderer = impl_from_IMFAttributes(iface);
2345 TRACE("%p, %p, %d, %p.\n", iface, theirs, type, result);
2347 return IMFAttributes_Compare(renderer->attributes, theirs, type, result);
2350 static HRESULT WINAPI video_renderer_attributes_GetUINT32(IMFAttributes *iface, REFGUID key, UINT32 *value)
2352 struct video_renderer *renderer = impl_from_IMFAttributes(iface);
2354 TRACE("%p, %s, %p.\n", iface, debugstr_guid(key), value);
2356 return IMFAttributes_GetUINT32(renderer->attributes, key, value);
2359 static HRESULT WINAPI video_renderer_attributes_GetUINT64(IMFAttributes *iface, REFGUID key, UINT64 *value)
2361 struct video_renderer *renderer = impl_from_IMFAttributes(iface);
2363 TRACE("%p, %s, %p.\n", iface, debugstr_guid(key), value);
2365 return IMFAttributes_GetUINT64(renderer->attributes, key, value);
2368 static HRESULT WINAPI video_renderer_attributes_GetDouble(IMFAttributes *iface, REFGUID key, double *value)
2370 struct video_renderer *renderer = impl_from_IMFAttributes(iface);
2372 TRACE("%p, %s, %p.\n", iface, debugstr_guid(key), value);
2374 return IMFAttributes_GetDouble(renderer->attributes, key, value);
2377 static HRESULT WINAPI video_renderer_attributes_GetGUID(IMFAttributes *iface, REFGUID key, GUID *value)
2379 struct video_renderer *renderer = impl_from_IMFAttributes(iface);
2381 TRACE("%p, %s, %p.\n", iface, debugstr_guid(key), value);
2383 return IMFAttributes_GetGUID(renderer->attributes, key, value);
2386 static HRESULT WINAPI video_renderer_attributes_GetStringLength(IMFAttributes *iface, REFGUID key,
2387 UINT32 *length)
2389 struct video_renderer *renderer = impl_from_IMFAttributes(iface);
2391 TRACE("%p, %s, %p.\n", iface, debugstr_guid(key), length);
2393 return IMFAttributes_GetStringLength(renderer->attributes, key, length);
2396 static HRESULT WINAPI video_renderer_attributes_GetString(IMFAttributes *iface, REFGUID key, WCHAR *value,
2397 UINT32 size, UINT32 *length)
2399 struct video_renderer *renderer = impl_from_IMFAttributes(iface);
2401 TRACE("%p, %s, %p, %u, %p.\n", iface, debugstr_guid(key), value, size, length);
2403 return IMFAttributes_GetString(renderer->attributes, key, value, size, length);
2406 static HRESULT WINAPI video_renderer_attributes_GetAllocatedString(IMFAttributes *iface, REFGUID key,
2407 WCHAR **value, UINT32 *length)
2409 struct video_renderer *renderer = impl_from_IMFAttributes(iface);
2411 TRACE("%p, %s, %p, %p.\n", iface, debugstr_guid(key), value, length);
2413 return IMFAttributes_GetAllocatedString(renderer->attributes, key, value, length);
2416 static HRESULT WINAPI video_renderer_attributes_GetBlobSize(IMFAttributes *iface, REFGUID key, UINT32 *size)
2418 struct video_renderer *renderer = impl_from_IMFAttributes(iface);
2420 TRACE("%p, %s, %p.\n", iface, debugstr_guid(key), size);
2422 return IMFAttributes_GetBlobSize(renderer->attributes, key, size);
2425 static HRESULT WINAPI video_renderer_attributes_GetBlob(IMFAttributes *iface, REFGUID key, UINT8 *buf,
2426 UINT32 bufsize, UINT32 *blobsize)
2428 struct video_renderer *renderer = impl_from_IMFAttributes(iface);
2430 TRACE("%p, %s, %p, %u, %p.\n", iface, debugstr_guid(key), buf, bufsize, blobsize);
2432 return IMFAttributes_GetBlob(renderer->attributes, key, buf, bufsize, blobsize);
2435 static HRESULT WINAPI video_renderer_attributes_GetAllocatedBlob(IMFAttributes *iface, REFGUID key,
2436 UINT8 **buf, UINT32 *size)
2438 struct video_renderer *renderer = impl_from_IMFAttributes(iface);
2440 TRACE("%p, %s, %p, %p.\n", iface, debugstr_guid(key), buf, size);
2442 return IMFAttributes_GetAllocatedBlob(renderer->attributes, key, buf, size);
2445 static HRESULT WINAPI video_renderer_attributes_GetUnknown(IMFAttributes *iface, REFGUID key, REFIID riid, void **out)
2447 struct video_renderer *renderer = impl_from_IMFAttributes(iface);
2449 TRACE("%p, %s, %s, %p.\n", iface, debugstr_guid(key), debugstr_guid(riid), out);
2451 return IMFAttributes_GetUnknown(renderer->attributes, key, riid, out);
2454 static HRESULT WINAPI video_renderer_attributes_SetItem(IMFAttributes *iface, REFGUID key, REFPROPVARIANT value)
2456 struct video_renderer *renderer = impl_from_IMFAttributes(iface);
2458 TRACE("%p, %s, %p.\n", iface, debugstr_guid(key), value);
2460 return IMFAttributes_SetItem(renderer->attributes, key, value);
2463 static HRESULT WINAPI video_renderer_attributes_DeleteItem(IMFAttributes *iface, REFGUID key)
2465 struct video_renderer *renderer = impl_from_IMFAttributes(iface);
2467 TRACE("%p, %s.\n", iface, debugstr_guid(key));
2469 return IMFAttributes_DeleteItem(renderer->attributes, key);
2472 static HRESULT WINAPI video_renderer_attributes_DeleteAllItems(IMFAttributes *iface)
2474 struct video_renderer *renderer = impl_from_IMFAttributes(iface);
2476 TRACE("%p.\n", iface);
2478 return IMFAttributes_DeleteAllItems(renderer->attributes);
2481 static HRESULT WINAPI video_renderer_attributes_SetUINT32(IMFAttributes *iface, REFGUID key, UINT32 value)
2483 struct video_renderer *renderer = impl_from_IMFAttributes(iface);
2485 TRACE("%p, %s, %u.\n", iface, debugstr_guid(key), value);
2487 return IMFAttributes_SetUINT32(renderer->attributes, key, value);
2490 static HRESULT WINAPI video_renderer_attributes_SetUINT64(IMFAttributes *iface, REFGUID key, UINT64 value)
2492 struct video_renderer *renderer = impl_from_IMFAttributes(iface);
2494 TRACE("%p, %s, %s.\n", iface, debugstr_guid(key), wine_dbgstr_longlong(value));
2496 return IMFAttributes_SetUINT64(renderer->attributes, key, value);
2499 static HRESULT WINAPI video_renderer_attributes_SetDouble(IMFAttributes *iface, REFGUID key, double value)
2501 struct video_renderer *renderer = impl_from_IMFAttributes(iface);
2503 TRACE("%p, %s, %f.\n", iface, debugstr_guid(key), value);
2505 return IMFAttributes_SetDouble(renderer->attributes, key, value);
2508 static HRESULT WINAPI video_renderer_attributes_SetGUID(IMFAttributes *iface, REFGUID key, REFGUID value)
2510 struct video_renderer *renderer = impl_from_IMFAttributes(iface);
2512 TRACE("%p, %s, %s.\n", iface, debugstr_guid(key), debugstr_guid(value));
2514 return IMFAttributes_SetGUID(renderer->attributes, key, value);
2517 static HRESULT WINAPI video_renderer_attributes_SetString(IMFAttributes *iface, REFGUID key,
2518 const WCHAR *value)
2520 struct video_renderer *renderer = impl_from_IMFAttributes(iface);
2522 TRACE("%p, %s, %s.\n", iface, debugstr_guid(key), debugstr_w(value));
2524 return IMFAttributes_SetString(renderer->attributes, key, value);
2527 static HRESULT WINAPI video_renderer_attributes_SetBlob(IMFAttributes *iface, REFGUID key,
2528 const UINT8 *buf, UINT32 size)
2530 struct video_renderer *renderer = impl_from_IMFAttributes(iface);
2532 TRACE("%p, %s, %p, %u.\n", iface, debugstr_guid(key), buf, size);
2534 return IMFAttributes_SetBlob(renderer->attributes, key, buf, size);
2537 static HRESULT WINAPI video_renderer_attributes_SetUnknown(IMFAttributes *iface, REFGUID key,
2538 IUnknown *unknown)
2540 struct video_renderer *renderer = impl_from_IMFAttributes(iface);
2542 TRACE("%p, %s, %p.\n", iface, debugstr_guid(key), unknown);
2544 return IMFAttributes_SetUnknown(renderer->attributes, key, unknown);
2547 static HRESULT WINAPI video_renderer_attributes_LockStore(IMFAttributes *iface)
2549 struct video_renderer *renderer = impl_from_IMFAttributes(iface);
2551 TRACE("%p.\n", iface);
2553 return IMFAttributes_LockStore(renderer->attributes);
2556 static HRESULT WINAPI video_renderer_attributes_UnlockStore(IMFAttributes *iface)
2558 struct video_renderer *renderer = impl_from_IMFAttributes(iface);
2560 TRACE("%p.\n", iface);
2562 return IMFAttributes_UnlockStore(renderer->attributes);
2565 static HRESULT WINAPI video_renderer_attributes_GetCount(IMFAttributes *iface, UINT32 *count)
2567 struct video_renderer *renderer = impl_from_IMFAttributes(iface);
2569 TRACE("%p, %p.\n", iface, count);
2571 return IMFAttributes_GetCount(renderer->attributes, count);
2574 static HRESULT WINAPI video_renderer_attributes_GetItemByIndex(IMFAttributes *iface, UINT32 index,
2575 GUID *key, PROPVARIANT *value)
2577 struct video_renderer *renderer = impl_from_IMFAttributes(iface);
2579 TRACE("%p, %u, %p, %p.\n", iface, index, key, value);
2581 return IMFAttributes_GetItemByIndex(renderer->attributes, index, key, value);
2584 static HRESULT WINAPI video_renderer_attributes_CopyAllItems(IMFAttributes *iface, IMFAttributes *dest)
2586 struct video_renderer *renderer = impl_from_IMFAttributes(iface);
2588 TRACE("%p, %p.\n", iface, dest);
2590 return IMFAttributes_CopyAllItems(renderer->attributes, dest);
2593 static const IMFAttributesVtbl video_renderer_attributes_vtbl =
2595 video_renderer_attributes_QueryInterface,
2596 video_renderer_attributes_AddRef,
2597 video_renderer_attributes_Release,
2598 video_renderer_attributes_GetItem,
2599 video_renderer_attributes_GetItemType,
2600 video_renderer_attributes_CompareItem,
2601 video_renderer_attributes_Compare,
2602 video_renderer_attributes_GetUINT32,
2603 video_renderer_attributes_GetUINT64,
2604 video_renderer_attributes_GetDouble,
2605 video_renderer_attributes_GetGUID,
2606 video_renderer_attributes_GetStringLength,
2607 video_renderer_attributes_GetString,
2608 video_renderer_attributes_GetAllocatedString,
2609 video_renderer_attributes_GetBlobSize,
2610 video_renderer_attributes_GetBlob,
2611 video_renderer_attributes_GetAllocatedBlob,
2612 video_renderer_attributes_GetUnknown,
2613 video_renderer_attributes_SetItem,
2614 video_renderer_attributes_DeleteItem,
2615 video_renderer_attributes_DeleteAllItems,
2616 video_renderer_attributes_SetUINT32,
2617 video_renderer_attributes_SetUINT64,
2618 video_renderer_attributes_SetDouble,
2619 video_renderer_attributes_SetGUID,
2620 video_renderer_attributes_SetString,
2621 video_renderer_attributes_SetBlob,
2622 video_renderer_attributes_SetUnknown,
2623 video_renderer_attributes_LockStore,
2624 video_renderer_attributes_UnlockStore,
2625 video_renderer_attributes_GetCount,
2626 video_renderer_attributes_GetItemByIndex,
2627 video_renderer_attributes_CopyAllItems,
2630 static HRESULT WINAPI video_renderer_quality_advise_QueryInterface(IMFQualityAdvise *iface, REFIID riid, void **out)
2632 struct video_renderer *renderer = impl_from_IMFQualityAdvise(iface);
2633 return IMFMediaSink_QueryInterface(&renderer->IMFMediaSink_iface, riid, out);
2636 static ULONG WINAPI video_renderer_quality_advise_AddRef(IMFQualityAdvise *iface)
2638 struct video_renderer *renderer = impl_from_IMFQualityAdvise(iface);
2639 return IMFMediaSink_AddRef(&renderer->IMFMediaSink_iface);
2642 static ULONG WINAPI video_renderer_quality_Release(IMFQualityAdvise *iface)
2644 struct video_renderer *renderer = impl_from_IMFQualityAdvise(iface);
2645 return IMFMediaSink_Release(&renderer->IMFMediaSink_iface);
2648 static HRESULT WINAPI video_renderer_quality_advise_SetDropMode(IMFQualityAdvise *iface,
2649 MF_QUALITY_DROP_MODE mode)
2651 FIXME("%p, %u.\n", iface, mode);
2653 return E_NOTIMPL;
2656 static HRESULT WINAPI video_renderer_quality_advise_SetQualityLevel(IMFQualityAdvise *iface,
2657 MF_QUALITY_LEVEL level)
2659 FIXME("%p, %u.\n", iface, level);
2661 return E_NOTIMPL;
2664 static HRESULT WINAPI video_renderer_quality_advise_GetDropMode(IMFQualityAdvise *iface,
2665 MF_QUALITY_DROP_MODE *mode)
2667 FIXME("%p, %p.\n", iface, mode);
2669 return E_NOTIMPL;
2672 static HRESULT WINAPI video_renderer_quality_advise_GetQualityLevel(IMFQualityAdvise *iface,
2673 MF_QUALITY_LEVEL *level)
2675 FIXME("%p, %p.\n", iface, level);
2677 return E_NOTIMPL;
2680 static HRESULT WINAPI video_renderer_quality_advise_DropTime(IMFQualityAdvise *iface, LONGLONG interval)
2682 FIXME("%p, %s.\n", iface, wine_dbgstr_longlong(interval));
2684 return E_NOTIMPL;
2687 static const IMFQualityAdviseVtbl video_renderer_quality_advise_vtbl =
2689 video_renderer_quality_advise_QueryInterface,
2690 video_renderer_quality_advise_AddRef,
2691 video_renderer_quality_Release,
2692 video_renderer_quality_advise_SetDropMode,
2693 video_renderer_quality_advise_SetQualityLevel,
2694 video_renderer_quality_advise_GetDropMode,
2695 video_renderer_quality_advise_GetQualityLevel,
2696 video_renderer_quality_advise_DropTime,
2699 static HRESULT WINAPI video_renderer_rate_support_QueryInterface(IMFRateSupport *iface, REFIID riid, void **out)
2701 struct video_renderer *renderer = impl_from_IMFRateSupport(iface);
2702 return IMFMediaSink_QueryInterface(&renderer->IMFMediaSink_iface, riid, out);
2705 static ULONG WINAPI video_renderer_rate_support_AddRef(IMFRateSupport *iface)
2707 struct video_renderer *renderer = impl_from_IMFRateSupport(iface);
2708 return IMFMediaSink_AddRef(&renderer->IMFMediaSink_iface);
2711 static ULONG WINAPI video_renderer_rate_support_Release(IMFRateSupport *iface)
2713 struct video_renderer *renderer = impl_from_IMFRateSupport(iface);
2714 return IMFMediaSink_Release(&renderer->IMFMediaSink_iface);
2717 static HRESULT WINAPI video_renderer_rate_support_GetSlowestRate(IMFRateSupport *iface, MFRATE_DIRECTION direction,
2718 BOOL thin, float *rate)
2720 struct video_renderer *renderer = impl_from_IMFRateSupport(iface);
2722 TRACE("%p, %d, %d, %p.\n", iface, direction, thin, rate);
2724 if (renderer->flags & EVR_SHUT_DOWN)
2725 return MF_E_SHUTDOWN;
2727 *rate = 0.0f;
2729 return S_OK;
2732 static HRESULT WINAPI video_renderer_rate_support_GetFastestRate(IMFRateSupport *iface, MFRATE_DIRECTION direction,
2733 BOOL thin, float *rate)
2735 struct video_renderer *renderer = impl_from_IMFRateSupport(iface);
2737 TRACE("%p, %d, %d, %p.\n", iface, direction, thin, rate);
2739 return renderer->flags & EVR_SHUT_DOWN ? MF_E_SHUTDOWN : MF_E_INVALIDREQUEST;
2742 static HRESULT WINAPI video_renderer_rate_support_IsRateSupported(IMFRateSupport *iface, BOOL thin, float rate,
2743 float *nearest_supported_rate)
2745 FIXME("%p, %d, %f, %p.\n", iface, thin, rate, nearest_supported_rate);
2747 return E_NOTIMPL;
2750 static const IMFRateSupportVtbl video_renderer_rate_support_vtbl =
2752 video_renderer_rate_support_QueryInterface,
2753 video_renderer_rate_support_AddRef,
2754 video_renderer_rate_support_Release,
2755 video_renderer_rate_support_GetSlowestRate,
2756 video_renderer_rate_support_GetFastestRate,
2757 video_renderer_rate_support_IsRateSupported,
2760 static HRESULT evr_create_object(IMFAttributes *attributes, void *user_context, IUnknown **obj)
2762 struct video_renderer *object;
2763 IMFVideoPresenter *presenter = NULL;
2764 IMFTransform *mixer = NULL;
2765 HRESULT hr;
2767 TRACE("%p, %p, %p.\n", attributes, user_context, obj);
2769 if (!(object = calloc(1, sizeof(*object))))
2770 return E_OUTOFMEMORY;
2772 object->IMFMediaSink_iface.lpVtbl = &video_renderer_sink_vtbl;
2773 object->IMFMediaSinkPreroll_iface.lpVtbl = &video_renderer_preroll_vtbl;
2774 object->IMFVideoRenderer_iface.lpVtbl = &video_renderer_vtbl;
2775 object->IMFMediaEventGenerator_iface.lpVtbl = &video_renderer_events_vtbl;
2776 object->IMFClockStateSink_iface.lpVtbl = &video_renderer_clock_sink_vtbl;
2777 object->IMFGetService_iface.lpVtbl = &video_renderer_get_service_vtbl;
2778 object->IMFTopologyServiceLookup_iface.lpVtbl = &video_renderer_service_lookup_vtbl;
2779 object->IMediaEventSink_iface.lpVtbl = &media_event_sink_vtbl;
2780 object->IMFAttributes_iface.lpVtbl = &video_renderer_attributes_vtbl;
2781 object->IMFQualityAdvise_iface.lpVtbl = &video_renderer_quality_advise_vtbl;
2782 object->IMFRateSupport_iface.lpVtbl = &video_renderer_rate_support_vtbl;
2783 object->refcount = 1;
2784 InitializeCriticalSection(&object->cs);
2786 if (FAILED(hr = MFCreateEventQueue(&object->event_queue)))
2787 goto failed;
2789 if (FAILED(hr = MFCreateAttributes(&object->attributes, 0)))
2790 goto failed;
2792 /* Create mixer and presenter. */
2793 if (FAILED(hr = video_renderer_create_mixer(attributes, &mixer)))
2794 goto failed;
2796 if (FAILED(hr = video_renderer_create_presenter(object, attributes, &presenter)))
2797 goto failed;
2799 if (FAILED(hr = video_renderer_initialize(object, mixer, presenter)))
2800 goto failed;
2802 IMFTransform_Release(mixer);
2803 IMFVideoPresenter_Release(presenter);
2805 /* Default attributes */
2806 IMFAttributes_SetUINT32(object->attributes, &EVRConfig_ForceBob, 0);
2807 IMFAttributes_SetUINT32(object->attributes, &EVRConfig_AllowDropToBob, 0);
2808 IMFAttributes_SetUINT32(object->attributes, &EVRConfig_ForceThrottle, 0);
2809 IMFAttributes_SetUINT32(object->attributes, &EVRConfig_AllowDropToThrottle, 0);
2810 IMFAttributes_SetUINT32(object->attributes, &EVRConfig_ForceHalfInterlace, 0);
2811 IMFAttributes_SetUINT32(object->attributes, &EVRConfig_AllowDropToHalfInterlace, 0);
2812 IMFAttributes_SetUINT32(object->attributes, &EVRConfig_ForceScaling, 0);
2813 IMFAttributes_SetUINT32(object->attributes, &EVRConfig_AllowScaling, 0);
2814 IMFAttributes_SetUINT32(object->attributes, &EVRConfig_ForceBatching, 0);
2815 IMFAttributes_SetUINT32(object->attributes, &EVRConfig_AllowBatching, 0);
2817 *obj = (IUnknown *)&object->IMFMediaSink_iface;
2819 return S_OK;
2821 failed:
2823 if (mixer)
2824 IMFTransform_Release(mixer);
2826 if (presenter)
2827 IMFVideoPresenter_Release(presenter);
2829 video_renderer_release_services(object);
2830 IMFMediaSink_Release(&object->IMFMediaSink_iface);
2832 return hr;
2835 static void evr_shutdown_object(void *user_context, IUnknown *obj)
2837 IMFMediaSink *sink;
2839 if (SUCCEEDED(IUnknown_QueryInterface(obj, &IID_IMFMediaSink, (void **)&sink)))
2841 IMFMediaSink_Shutdown(sink);
2842 IMFMediaSink_Release(sink);
2846 static const struct activate_funcs evr_activate_funcs =
2848 .create_object = evr_create_object,
2849 .shutdown_object = evr_shutdown_object,
2852 /***********************************************************************
2853 * MFCreateVideoRendererActivate (mf.@)
2855 HRESULT WINAPI MFCreateVideoRendererActivate(HWND hwnd, IMFActivate **activate)
2857 HRESULT hr;
2859 TRACE("%p, %p.\n", hwnd, activate);
2861 if (!activate)
2862 return E_POINTER;
2864 hr = create_activation_object(NULL, &evr_activate_funcs, activate);
2865 if (SUCCEEDED(hr))
2866 IMFActivate_SetUINT64(*activate, &MF_ACTIVATE_VIDEO_WINDOW, (ULONG_PTR)hwnd);
2868 return hr;
2871 /***********************************************************************
2872 * MFCreateVideoRenderer (mf.@)
2874 HRESULT WINAPI MFCreateVideoRenderer(REFIID riid, void **renderer)
2876 IUnknown *obj;
2877 HRESULT hr;
2879 TRACE("%s, %p.\n", debugstr_guid(riid), renderer);
2881 *renderer = NULL;
2883 if (SUCCEEDED(hr = evr_create_object(NULL, NULL, &obj)))
2885 hr = IUnknown_QueryInterface(obj, riid, renderer);
2886 IUnknown_Release(obj);
2889 return hr;