d3d10/effect: Add a helper to read raw variable values.
[wine.git] / dlls / mf / evr.c
blob9552990006d2ddfa4133f662343d6fa649d050fa
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 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 EnterCriticalSection(&renderer->cs);
1295 if (renderer->flags & EVR_SHUT_DOWN)
1296 hr = MF_E_SHUTDOWN;
1297 else if (!count)
1298 hr = E_POINTER;
1299 else
1300 *count = renderer->stream_count;
1301 LeaveCriticalSection(&renderer->cs);
1303 return hr;
1306 static HRESULT WINAPI video_renderer_sink_GetStreamSinkByIndex(IMFMediaSink *iface, DWORD index,
1307 IMFStreamSink **stream)
1309 struct video_renderer *renderer = impl_from_IMFMediaSink(iface);
1310 HRESULT hr = S_OK;
1312 TRACE("%p, %u, %p.\n", iface, index, stream);
1314 EnterCriticalSection(&renderer->cs);
1315 if (renderer->flags & EVR_SHUT_DOWN)
1316 hr = MF_E_SHUTDOWN;
1317 else if (!stream)
1318 hr = E_POINTER;
1319 else if (index >= renderer->stream_count)
1320 hr = E_INVALIDARG;
1321 else
1323 *stream = &renderer->streams[index]->IMFStreamSink_iface;
1324 IMFStreamSink_AddRef(*stream);
1326 LeaveCriticalSection(&renderer->cs);
1328 return hr;
1331 static HRESULT WINAPI video_renderer_sink_GetStreamSinkById(IMFMediaSink *iface, DWORD id,
1332 IMFStreamSink **stream)
1334 struct video_renderer *renderer = impl_from_IMFMediaSink(iface);
1335 HRESULT hr = S_OK;
1336 size_t i;
1338 TRACE("%p, %#x, %p.\n", iface, id, stream);
1340 EnterCriticalSection(&renderer->cs);
1341 if (renderer->flags & EVR_SHUT_DOWN)
1342 hr = MF_E_SHUTDOWN;
1343 else if (!stream)
1344 hr = E_POINTER;
1345 else
1347 for (i = 0; i < renderer->stream_count; ++i)
1349 if (renderer->streams[i]->id == id)
1350 break;
1353 if (i == renderer->stream_count)
1354 hr = MF_E_INVALIDSTREAMNUMBER;
1355 else
1357 *stream = &renderer->streams[i]->IMFStreamSink_iface;
1358 IMFStreamSink_AddRef(*stream);
1361 LeaveCriticalSection(&renderer->cs);
1363 return hr;
1366 static void video_renderer_set_presentation_clock(struct video_renderer *renderer, IMFPresentationClock *clock)
1368 if (renderer->clock)
1370 IMFPresentationClock_RemoveClockStateSink(renderer->clock, &renderer->IMFClockStateSink_iface);
1371 IMFPresentationClock_Release(renderer->clock);
1373 video_renderer_release_presenter_services(renderer);
1375 renderer->clock = clock;
1376 if (renderer->clock)
1378 IMFPresentationClock_AddRef(renderer->clock);
1379 IMFPresentationClock_AddClockStateSink(renderer->clock, &renderer->IMFClockStateSink_iface);
1381 video_renderer_init_presenter_services(renderer);
1384 static HRESULT WINAPI video_renderer_sink_SetPresentationClock(IMFMediaSink *iface, IMFPresentationClock *clock)
1386 struct video_renderer *renderer = impl_from_IMFMediaSink(iface);
1387 HRESULT hr = S_OK;
1389 TRACE("%p, %p.\n", iface, clock);
1391 EnterCriticalSection(&renderer->cs);
1393 if (renderer->flags & EVR_SHUT_DOWN)
1394 hr = MF_E_SHUTDOWN;
1395 else
1396 video_renderer_set_presentation_clock(renderer, clock);
1398 LeaveCriticalSection(&renderer->cs);
1400 return hr;
1403 static HRESULT WINAPI video_renderer_sink_GetPresentationClock(IMFMediaSink *iface, IMFPresentationClock **clock)
1405 struct video_renderer *renderer = impl_from_IMFMediaSink(iface);
1406 HRESULT hr = S_OK;
1408 TRACE("%p, %p.\n", iface, clock);
1410 if (!clock)
1411 return E_POINTER;
1413 EnterCriticalSection(&renderer->cs);
1415 if (renderer->flags & EVR_SHUT_DOWN)
1416 hr = MF_E_SHUTDOWN;
1417 else if (renderer->clock)
1419 *clock = renderer->clock;
1420 IMFPresentationClock_AddRef(*clock);
1422 else
1423 hr = MF_E_NO_CLOCK;
1425 LeaveCriticalSection(&renderer->cs);
1427 return hr;
1430 static HRESULT WINAPI video_renderer_sink_Shutdown(IMFMediaSink *iface)
1432 struct video_renderer *renderer = impl_from_IMFMediaSink(iface);
1433 size_t i;
1435 TRACE("%p.\n", iface);
1437 if (renderer->flags & EVR_SHUT_DOWN)
1438 return MF_E_SHUTDOWN;
1440 EnterCriticalSection(&renderer->cs);
1441 renderer->flags |= EVR_SHUT_DOWN;
1442 /* Detach streams from the sink. */
1443 for (i = 0; i < renderer->stream_count; ++i)
1445 struct video_stream *stream = renderer->streams[i];
1447 EnterCriticalSection(&stream->cs);
1448 stream->parent = NULL;
1449 LeaveCriticalSection(&stream->cs);
1451 IMFMediaEventQueue_Shutdown(stream->event_queue);
1452 IMFStreamSink_Release(&stream->IMFStreamSink_iface);
1453 IMFMediaSink_Release(iface);
1454 renderer->streams[i] = NULL;
1456 free(renderer->streams);
1457 renderer->stream_count = 0;
1458 renderer->stream_size = 0;
1459 IMFMediaEventQueue_Shutdown(renderer->event_queue);
1460 video_renderer_set_presentation_clock(renderer, NULL);
1461 video_renderer_release_services(renderer);
1462 LeaveCriticalSection(&renderer->cs);
1464 return S_OK;
1467 static const IMFMediaSinkVtbl video_renderer_sink_vtbl =
1469 video_renderer_sink_QueryInterface,
1470 video_renderer_sink_AddRef,
1471 video_renderer_sink_Release,
1472 video_renderer_sink_GetCharacteristics,
1473 video_renderer_sink_AddStreamSink,
1474 video_renderer_sink_RemoveStreamSink,
1475 video_renderer_sink_GetStreamSinkCount,
1476 video_renderer_sink_GetStreamSinkByIndex,
1477 video_renderer_sink_GetStreamSinkById,
1478 video_renderer_sink_SetPresentationClock,
1479 video_renderer_sink_GetPresentationClock,
1480 video_renderer_sink_Shutdown,
1483 static HRESULT WINAPI video_renderer_preroll_QueryInterface(IMFMediaSinkPreroll *iface, REFIID riid, void **obj)
1485 struct video_renderer *renderer = impl_from_IMFMediaSinkPreroll(iface);
1486 return IMFMediaSink_QueryInterface(&renderer->IMFMediaSink_iface, riid, obj);
1489 static ULONG WINAPI video_renderer_preroll_AddRef(IMFMediaSinkPreroll *iface)
1491 struct video_renderer *renderer = impl_from_IMFMediaSinkPreroll(iface);
1492 return IMFMediaSink_AddRef(&renderer->IMFMediaSink_iface);
1495 static ULONG WINAPI video_renderer_preroll_Release(IMFMediaSinkPreroll *iface)
1497 struct video_renderer *renderer = impl_from_IMFMediaSinkPreroll(iface);
1498 return IMFMediaSink_Release(&renderer->IMFMediaSink_iface);
1501 static HRESULT WINAPI video_renderer_preroll_NotifyPreroll(IMFMediaSinkPreroll *iface, MFTIME start_time)
1503 struct video_renderer *renderer = impl_from_IMFMediaSinkPreroll(iface);
1504 HRESULT hr = S_OK;
1505 size_t i;
1507 TRACE("%p, %s.\n", iface, debugstr_time(start_time));
1509 EnterCriticalSection(&renderer->cs);
1510 if (renderer->flags & EVR_SHUT_DOWN)
1511 hr = MF_E_SHUTDOWN;
1512 else
1514 for (i = 0; i < renderer->stream_count; ++i)
1516 struct video_stream *stream = renderer->streams[i];
1518 EnterCriticalSection(&stream->cs);
1519 if (!(stream->flags & (EVR_STREAM_PREROLLING | EVR_STREAM_PREROLLED)))
1521 IMFMediaEventQueue_QueueEventParamVar(stream->event_queue, MEStreamSinkRequestSample,
1522 &GUID_NULL, S_OK, NULL);
1523 stream->flags |= EVR_STREAM_PREROLLING;
1525 LeaveCriticalSection(&stream->cs);
1528 LeaveCriticalSection(&renderer->cs);
1530 return hr;
1533 static const IMFMediaSinkPrerollVtbl video_renderer_preroll_vtbl =
1535 video_renderer_preroll_QueryInterface,
1536 video_renderer_preroll_AddRef,
1537 video_renderer_preroll_Release,
1538 video_renderer_preroll_NotifyPreroll,
1541 static HRESULT WINAPI video_renderer_QueryInterface(IMFVideoRenderer *iface, REFIID riid, void **obj)
1543 struct video_renderer *renderer = impl_from_IMFVideoRenderer(iface);
1544 return IMFMediaSink_QueryInterface(&renderer->IMFMediaSink_iface, riid, obj);
1547 static ULONG WINAPI video_renderer_AddRef(IMFVideoRenderer *iface)
1549 struct video_renderer *renderer = impl_from_IMFVideoRenderer(iface);
1550 return IMFMediaSink_AddRef(&renderer->IMFMediaSink_iface);
1553 static ULONG WINAPI video_renderer_Release(IMFVideoRenderer *iface)
1555 struct video_renderer *renderer = impl_from_IMFVideoRenderer(iface);
1556 return IMFMediaSink_Release(&renderer->IMFMediaSink_iface);
1559 static HRESULT video_renderer_create_mixer(IMFAttributes *attributes, IMFTransform **out)
1561 unsigned int flags = 0;
1562 IMFActivate *activate;
1563 CLSID clsid;
1564 HRESULT hr;
1566 if (attributes && SUCCEEDED(hr = IMFAttributes_GetUnknown(attributes, &MF_ACTIVATE_CUSTOM_VIDEO_MIXER_ACTIVATE,
1567 &IID_IMFActivate, (void **)&activate)))
1569 IMFAttributes_GetUINT32(attributes, &MF_ACTIVATE_CUSTOM_VIDEO_MIXER_FLAGS, &flags);
1570 hr = IMFActivate_ActivateObject(activate, &IID_IMFTransform, (void **)out);
1571 IMFActivate_Release(activate);
1572 if (SUCCEEDED(hr) || !(flags & MF_ACTIVATE_CUSTOM_MIXER_ALLOWFAIL))
1573 return hr;
1576 if (!attributes || FAILED(IMFAttributes_GetGUID(attributes, &MF_ACTIVATE_CUSTOM_VIDEO_MIXER_CLSID, &clsid)))
1577 memcpy(&clsid, &CLSID_MFVideoMixer9, sizeof(clsid));
1579 return CoCreateInstance(&clsid, NULL, CLSCTX_INPROC_SERVER, &IID_IMFTransform, (void **)out);
1582 static HRESULT video_renderer_create_presenter(struct video_renderer *renderer, IMFAttributes *attributes,
1583 IMFVideoPresenter **out)
1585 unsigned int flags = 0;
1586 IMFActivate *activate;
1587 UINT64 value;
1588 CLSID clsid;
1589 HRESULT hr;
1591 if (attributes && SUCCEEDED(IMFAttributes_GetUINT64(attributes, &MF_ACTIVATE_VIDEO_WINDOW, &value)))
1592 renderer->window = UlongToHandle(value);
1594 if (attributes && SUCCEEDED(IMFAttributes_GetUnknown(attributes, &MF_ACTIVATE_CUSTOM_VIDEO_PRESENTER_ACTIVATE,
1595 &IID_IMFActivate, (void **)&activate)))
1597 IMFAttributes_GetUINT32(attributes, &MF_ACTIVATE_CUSTOM_VIDEO_PRESENTER_FLAGS, &flags);
1598 hr = IMFActivate_ActivateObject(activate, &IID_IMFVideoPresenter, (void **)out);
1599 IMFActivate_Release(activate);
1600 if (SUCCEEDED(hr) || !(flags & MF_ACTIVATE_CUSTOM_PRESENTER_ALLOWFAIL))
1601 return hr;
1604 if (!attributes || FAILED(IMFAttributes_GetGUID(attributes, &MF_ACTIVATE_CUSTOM_VIDEO_PRESENTER_CLSID, &clsid)))
1605 memcpy(&clsid, &CLSID_MFVideoPresenter9, sizeof(clsid));
1607 return CoCreateInstance(&clsid, NULL, CLSCTX_INPROC_SERVER, &IID_IMFVideoPresenter, (void **)out);
1610 static HRESULT video_renderer_get_device_manager(struct video_renderer *renderer, IUnknown **device_manager)
1612 return MFGetService((IUnknown *)renderer->presenter, &MR_VIDEO_RENDER_SERVICE,
1613 &IID_IDirect3DDeviceManager9, (void **)device_manager);
1616 static HRESULT video_renderer_configure_mixer(struct video_renderer *renderer)
1618 IMFTopologyServiceLookupClient *lookup_client;
1619 HRESULT hr;
1621 if (SUCCEEDED(hr = IMFTransform_QueryInterface(renderer->mixer, &IID_IMFTopologyServiceLookupClient,
1622 (void **)&lookup_client)))
1624 renderer->flags |= EVR_INIT_SERVICES;
1625 if (SUCCEEDED(hr = IMFTopologyServiceLookupClient_InitServicePointers(lookup_client,
1626 &renderer->IMFTopologyServiceLookup_iface)))
1628 renderer->flags |= EVR_MIXER_INITED_SERVICES;
1630 renderer->flags &= ~EVR_INIT_SERVICES;
1631 IMFTopologyServiceLookupClient_Release(lookup_client);
1634 if (SUCCEEDED(hr))
1636 unsigned int input_count, output_count;
1637 unsigned int *ids, *oids;
1638 size_t i;
1640 /* Create stream sinks for inputs that mixer already has by default. */
1641 if (SUCCEEDED(IMFTransform_GetStreamCount(renderer->mixer, &input_count, &output_count)))
1643 ids = calloc(input_count, sizeof(*ids));
1644 oids = calloc(output_count, sizeof(*oids));
1646 if (ids && oids)
1648 if (SUCCEEDED(IMFTransform_GetStreamIDs(renderer->mixer, input_count, ids, output_count, oids)))
1650 for (i = 0; i < input_count; ++i)
1652 video_renderer_add_stream(renderer, ids[i], NULL);
1658 free(ids);
1659 free(oids);
1663 /* Set device manager that presenter should have created. */
1664 if (video_renderer_is_mixer_d3d_aware(renderer))
1666 IUnknown *device_manager;
1668 if (SUCCEEDED(video_renderer_get_device_manager(renderer, &device_manager)))
1670 IMFTransform_ProcessMessage(renderer->mixer, MFT_MESSAGE_SET_D3D_MANAGER, (ULONG_PTR)device_manager);
1671 IUnknown_Release(device_manager);
1675 return hr;
1678 static HRESULT video_renderer_configure_presenter(struct video_renderer *renderer)
1680 IMFVideoDisplayControl *control;
1681 RECT rect = { 0 };
1682 HRESULT hr;
1684 if (SUCCEEDED(IMFVideoPresenter_QueryInterface(renderer->presenter, &IID_IMFVideoDisplayControl, (void **)&control)))
1686 GetClientRect(renderer->window, &rect);
1688 if (SUCCEEDED(hr = IMFVideoDisplayControl_SetVideoWindow(control, renderer->window)))
1689 hr = IMFVideoDisplayControl_SetVideoPosition(control, NULL, &rect);
1690 IMFVideoDisplayControl_Release(control);
1693 hr = video_renderer_init_presenter_services(renderer);
1695 if (FAILED(video_renderer_get_device_manager(renderer, &renderer->device_manager)))
1697 WARN("Failed to get device manager from the presenter.\n");
1700 return hr;
1703 static HRESULT video_renderer_initialize(struct video_renderer *renderer, IMFTransform *mixer,
1704 IMFVideoPresenter *presenter)
1706 HRESULT hr;
1708 if (renderer->mixer)
1710 IMFTransform_Release(renderer->mixer);
1711 renderer->mixer = NULL;
1714 if (renderer->presenter)
1716 IMFVideoPresenter_Release(renderer->presenter);
1717 renderer->presenter = NULL;
1720 if (renderer->device_manager)
1722 IUnknown_Release(renderer->device_manager);
1723 renderer->device_manager = NULL;
1726 renderer->mixer = mixer;
1727 IMFTransform_AddRef(renderer->mixer);
1729 renderer->presenter = presenter;
1730 IMFVideoPresenter_AddRef(renderer->presenter);
1732 if (SUCCEEDED(hr = video_renderer_configure_mixer(renderer)))
1733 hr = video_renderer_configure_presenter(renderer);
1735 return hr;
1738 static HRESULT WINAPI video_renderer_InitializeRenderer(IMFVideoRenderer *iface, IMFTransform *mixer,
1739 IMFVideoPresenter *presenter)
1741 struct video_renderer *renderer = impl_from_IMFVideoRenderer(iface);
1742 HRESULT hr;
1744 TRACE("%p, %p, %p.\n", iface, mixer, presenter);
1746 if (mixer)
1747 IMFTransform_AddRef(mixer);
1748 else if (FAILED(hr = video_renderer_create_mixer(NULL, &mixer)))
1750 WARN("Failed to create default mixer object, hr %#x.\n", hr);
1751 return hr;
1754 if (presenter)
1755 IMFVideoPresenter_AddRef(presenter);
1756 else if (FAILED(hr = video_renderer_create_presenter(renderer, NULL, &presenter)))
1758 WARN("Failed to create default presenter, hr %#x.\n", hr);
1759 IMFTransform_Release(mixer);
1760 return hr;
1763 EnterCriticalSection(&renderer->cs);
1765 if (renderer->flags & EVR_SHUT_DOWN)
1766 hr = MF_E_SHUTDOWN;
1767 else
1769 /* FIXME: check clock state */
1770 /* FIXME: check that streams are not initialized */
1772 hr = video_renderer_initialize(renderer, mixer, presenter);
1775 LeaveCriticalSection(&renderer->cs);
1777 IMFTransform_Release(mixer);
1778 IMFVideoPresenter_Release(presenter);
1780 return hr;
1783 static const IMFVideoRendererVtbl video_renderer_vtbl =
1785 video_renderer_QueryInterface,
1786 video_renderer_AddRef,
1787 video_renderer_Release,
1788 video_renderer_InitializeRenderer,
1791 static HRESULT WINAPI video_renderer_events_QueryInterface(IMFMediaEventGenerator *iface, REFIID riid, void **obj)
1793 struct video_renderer *renderer = impl_from_IMFMediaEventGenerator(iface);
1794 return IMFMediaSink_QueryInterface(&renderer->IMFMediaSink_iface, riid, obj);
1797 static ULONG WINAPI video_renderer_events_AddRef(IMFMediaEventGenerator *iface)
1799 struct video_renderer *renderer = impl_from_IMFMediaEventGenerator(iface);
1800 return IMFMediaSink_AddRef(&renderer->IMFMediaSink_iface);
1803 static ULONG WINAPI video_renderer_events_Release(IMFMediaEventGenerator *iface)
1805 struct video_renderer *renderer = impl_from_IMFMediaEventGenerator(iface);
1806 return IMFMediaSink_Release(&renderer->IMFMediaSink_iface);
1809 static HRESULT WINAPI video_renderer_events_GetEvent(IMFMediaEventGenerator *iface, DWORD flags, IMFMediaEvent **event)
1811 struct video_renderer *renderer = impl_from_IMFMediaEventGenerator(iface);
1813 TRACE("%p, %#x, %p.\n", iface, flags, event);
1815 return IMFMediaEventQueue_GetEvent(renderer->event_queue, flags, event);
1818 static HRESULT WINAPI video_renderer_events_BeginGetEvent(IMFMediaEventGenerator *iface, IMFAsyncCallback *callback,
1819 IUnknown *state)
1821 struct video_renderer *renderer = impl_from_IMFMediaEventGenerator(iface);
1823 TRACE("%p, %p, %p.\n", iface, callback, state);
1825 return IMFMediaEventQueue_BeginGetEvent(renderer->event_queue, callback, state);
1828 static HRESULT WINAPI video_renderer_events_EndGetEvent(IMFMediaEventGenerator *iface, IMFAsyncResult *result,
1829 IMFMediaEvent **event)
1831 struct video_renderer *renderer = impl_from_IMFMediaEventGenerator(iface);
1833 TRACE("%p, %p, %p.\n", iface, result, event);
1835 return IMFMediaEventQueue_EndGetEvent(renderer->event_queue, result, event);
1838 static HRESULT WINAPI video_renderer_events_QueueEvent(IMFMediaEventGenerator *iface, MediaEventType event_type,
1839 REFGUID ext_type, HRESULT hr, const PROPVARIANT *value)
1841 struct video_renderer *renderer = impl_from_IMFMediaEventGenerator(iface);
1843 TRACE("%p, %u, %s, %#x, %p.\n", iface, event_type, debugstr_guid(ext_type), hr, value);
1845 return IMFMediaEventQueue_QueueEventParamVar(renderer->event_queue, event_type, ext_type, hr, value);
1848 static const IMFMediaEventGeneratorVtbl video_renderer_events_vtbl =
1850 video_renderer_events_QueryInterface,
1851 video_renderer_events_AddRef,
1852 video_renderer_events_Release,
1853 video_renderer_events_GetEvent,
1854 video_renderer_events_BeginGetEvent,
1855 video_renderer_events_EndGetEvent,
1856 video_renderer_events_QueueEvent,
1859 static HRESULT WINAPI video_renderer_clock_sink_QueryInterface(IMFClockStateSink *iface, REFIID riid, void **obj)
1861 struct video_renderer *renderer = impl_from_IMFClockStateSink(iface);
1862 return IMFMediaSink_QueryInterface(&renderer->IMFMediaSink_iface, riid, obj);
1865 static ULONG WINAPI video_renderer_clock_sink_AddRef(IMFClockStateSink *iface)
1867 struct video_renderer *renderer = impl_from_IMFClockStateSink(iface);
1868 return IMFMediaSink_AddRef(&renderer->IMFMediaSink_iface);
1871 static ULONG WINAPI video_renderer_clock_sink_Release(IMFClockStateSink *iface)
1873 struct video_renderer *renderer = impl_from_IMFClockStateSink(iface);
1874 return IMFMediaSink_Release(&renderer->IMFMediaSink_iface);
1877 static HRESULT WINAPI video_renderer_clock_sink_OnClockStart(IMFClockStateSink *iface, MFTIME systime, LONGLONG offset)
1879 struct video_renderer *renderer = impl_from_IMFClockStateSink(iface);
1880 unsigned int state, request_sample;
1881 size_t i;
1883 TRACE("%p, %s, %s.\n", iface, debugstr_time(systime), debugstr_time(offset));
1885 EnterCriticalSection(&renderer->cs);
1887 state = renderer->state;
1889 /* Update sink state before sending sample requests, to avoid potentially receiving new sample in stopped state */
1890 renderer->state = EVR_STATE_RUNNING;
1892 if (state == EVR_STATE_STOPPED)
1894 IMFTransform_ProcessMessage(renderer->mixer, MFT_MESSAGE_NOTIFY_BEGIN_STREAMING, 0);
1895 IMFVideoPresenter_ProcessMessage(renderer->presenter, MFVP_MESSAGE_BEGINSTREAMING, 0);
1897 for (i = 0; i < renderer->stream_count; ++i)
1899 struct video_stream *stream = renderer->streams[i];
1901 EnterCriticalSection(&stream->cs);
1902 request_sample = !(stream->flags & EVR_STREAM_PREROLLED) || (stream->flags & EVR_STREAM_SAMPLE_NEEDED);
1903 stream->flags |= EVR_STREAM_PREROLLED;
1904 stream->flags &= ~EVR_STREAM_SAMPLE_NEEDED;
1905 LeaveCriticalSection(&stream->cs);
1907 IMFMediaEventQueue_QueueEventParamVar(stream->event_queue, MEStreamSinkStarted, &GUID_NULL, S_OK, NULL);
1908 if (request_sample)
1909 IMFMediaEventQueue_QueueEventParamVar(stream->event_queue, MEStreamSinkRequestSample,
1910 &GUID_NULL, S_OK, NULL);
1914 IMFVideoPresenter_OnClockStart(renderer->presenter, systime, offset);
1916 LeaveCriticalSection(&renderer->cs);
1918 return S_OK;
1921 static HRESULT WINAPI video_renderer_clock_sink_OnClockStop(IMFClockStateSink *iface, MFTIME systime)
1923 struct video_renderer *renderer = impl_from_IMFClockStateSink(iface);
1924 size_t i;
1926 TRACE("%p, %s.\n", iface, debugstr_time(systime));
1928 EnterCriticalSection(&renderer->cs);
1930 IMFVideoPresenter_OnClockStop(renderer->presenter, systime);
1932 IMFTransform_ProcessMessage(renderer->mixer, MFT_MESSAGE_COMMAND_FLUSH, 0);
1933 IMFVideoPresenter_ProcessMessage(renderer->presenter, MFVP_MESSAGE_FLUSH, 0);
1935 if (renderer->state == EVR_STATE_RUNNING ||
1936 renderer->state == EVR_STATE_PAUSED)
1938 IMFTransform_ProcessMessage(renderer->mixer, MFT_MESSAGE_NOTIFY_END_STREAMING, 0);
1939 IMFVideoPresenter_ProcessMessage(renderer->presenter, MFVP_MESSAGE_ENDSTREAMING, 0);
1941 for (i = 0; i < renderer->stream_count; ++i)
1943 struct video_stream *stream = renderer->streams[i];
1944 IMFMediaEventQueue_QueueEventParamVar(stream->event_queue, MEStreamSinkStopped, &GUID_NULL, S_OK, NULL);
1946 EnterCriticalSection(&stream->cs);
1947 stream->flags &= ~(EVR_STREAM_PREROLLED | EVR_STREAM_SAMPLE_NEEDED);
1948 LeaveCriticalSection(&stream->cs);
1950 renderer->state = EVR_STATE_STOPPED;
1953 LeaveCriticalSection(&renderer->cs);
1955 return S_OK;
1958 static HRESULT WINAPI video_renderer_clock_sink_OnClockPause(IMFClockStateSink *iface, MFTIME systime)
1960 struct video_renderer *renderer = impl_from_IMFClockStateSink(iface);
1961 size_t i;
1963 TRACE("%p, %s.\n", iface, debugstr_time(systime));
1965 EnterCriticalSection(&renderer->cs);
1967 IMFVideoPresenter_OnClockPause(renderer->presenter, systime);
1969 if (renderer->state == EVR_STATE_RUNNING)
1971 for (i = 0; i < renderer->stream_count; ++i)
1973 struct video_stream *stream = renderer->streams[i];
1974 IMFMediaEventQueue_QueueEventParamVar(stream->event_queue, MEStreamSinkPaused, &GUID_NULL, S_OK, NULL);
1978 renderer->state = EVR_STATE_PAUSED;
1980 LeaveCriticalSection(&renderer->cs);
1982 return S_OK;
1985 static HRESULT WINAPI video_renderer_clock_sink_OnClockRestart(IMFClockStateSink *iface, MFTIME systime)
1987 struct video_renderer *renderer = impl_from_IMFClockStateSink(iface);
1988 size_t i;
1990 TRACE("%p, %s.\n", iface, debugstr_time(systime));
1992 EnterCriticalSection(&renderer->cs);
1994 IMFVideoPresenter_OnClockRestart(renderer->presenter, systime);
1996 for (i = 0; i < renderer->stream_count; ++i)
1998 struct video_stream *stream = renderer->streams[i];
1999 IMFMediaEventQueue_QueueEventParamVar(stream->event_queue, MEStreamSinkStarted, &GUID_NULL, S_OK, NULL);
2001 renderer->state = EVR_STATE_RUNNING;
2003 LeaveCriticalSection(&renderer->cs);
2005 return S_OK;
2008 static HRESULT WINAPI video_renderer_clock_sink_OnClockSetRate(IMFClockStateSink *iface, MFTIME systime, float rate)
2010 struct video_renderer *renderer = impl_from_IMFClockStateSink(iface);
2011 IMFClockStateSink *sink;
2013 TRACE("%p, %s, %f.\n", iface, debugstr_time(systime), rate);
2015 EnterCriticalSection(&renderer->cs);
2017 IMFVideoPresenter_OnClockSetRate(renderer->presenter, systime, rate);
2018 if (SUCCEEDED(IMFTransform_QueryInterface(renderer->mixer, &IID_IMFClockStateSink, (void **)&sink)))
2020 IMFClockStateSink_OnClockSetRate(sink, systime, rate);
2021 IMFClockStateSink_Release(sink);
2024 LeaveCriticalSection(&renderer->cs);
2026 return S_OK;
2029 static const IMFClockStateSinkVtbl video_renderer_clock_sink_vtbl =
2031 video_renderer_clock_sink_QueryInterface,
2032 video_renderer_clock_sink_AddRef,
2033 video_renderer_clock_sink_Release,
2034 video_renderer_clock_sink_OnClockStart,
2035 video_renderer_clock_sink_OnClockStop,
2036 video_renderer_clock_sink_OnClockPause,
2037 video_renderer_clock_sink_OnClockRestart,
2038 video_renderer_clock_sink_OnClockSetRate,
2041 static HRESULT WINAPI video_renderer_get_service_QueryInterface(IMFGetService *iface, REFIID riid, void **obj)
2043 struct video_renderer *renderer = impl_from_IMFGetService(iface);
2044 return IMFMediaSink_QueryInterface(&renderer->IMFMediaSink_iface, riid, obj);
2047 static ULONG WINAPI video_renderer_get_service_AddRef(IMFGetService *iface)
2049 struct video_renderer *renderer = impl_from_IMFGetService(iface);
2050 return IMFMediaSink_AddRef(&renderer->IMFMediaSink_iface);
2053 static ULONG WINAPI video_renderer_get_service_Release(IMFGetService *iface)
2055 struct video_renderer *renderer = impl_from_IMFGetService(iface);
2056 return IMFMediaSink_Release(&renderer->IMFMediaSink_iface);
2059 static HRESULT WINAPI video_renderer_get_service_GetService(IMFGetService *iface, REFGUID service, REFIID riid, void **obj)
2061 struct video_renderer *renderer = impl_from_IMFGetService(iface);
2062 HRESULT hr = E_NOINTERFACE;
2063 IMFGetService *gs = NULL;
2065 TRACE("%p, %s, %s, %p.\n", iface, debugstr_guid(service), debugstr_guid(riid), obj);
2067 EnterCriticalSection(&renderer->cs);
2069 if (IsEqualGUID(service, &MR_VIDEO_MIXER_SERVICE))
2071 hr = IMFTransform_QueryInterface(renderer->mixer, &IID_IMFGetService, (void **)&gs);
2073 else if (IsEqualGUID(service, &MR_VIDEO_RENDER_SERVICE))
2075 hr = IMFVideoPresenter_QueryInterface(renderer->presenter, &IID_IMFGetService, (void **)&gs);
2077 else if (IsEqualGUID(service, &MR_VIDEO_ACCELERATION_SERVICE) && IsEqualIID(riid, &IID_IDirect3DDeviceManager9))
2079 if (renderer->device_manager)
2080 hr = IUnknown_QueryInterface(renderer->device_manager, riid, obj);
2082 else if (IsEqualGUID(service, &MF_RATE_CONTROL_SERVICE) && IsEqualIID(riid, &IID_IMFRateSupport))
2084 hr = IMFVideoRenderer_QueryInterface(&renderer->IMFVideoRenderer_iface, riid, obj);
2086 else
2088 FIXME("Unsupported service %s.\n", debugstr_guid(service));
2091 LeaveCriticalSection(&renderer->cs);
2093 if (gs)
2095 hr = IMFGetService_GetService(gs, service, riid, obj);
2096 IMFGetService_Release(gs);
2099 return hr;
2102 static const IMFGetServiceVtbl video_renderer_get_service_vtbl =
2104 video_renderer_get_service_QueryInterface,
2105 video_renderer_get_service_AddRef,
2106 video_renderer_get_service_Release,
2107 video_renderer_get_service_GetService,
2110 static HRESULT WINAPI video_renderer_service_lookup_QueryInterface(IMFTopologyServiceLookup *iface, REFIID riid, void **obj)
2112 TRACE("%p, %s, %p.\n", iface, debugstr_guid(riid), obj);
2114 if (IsEqualIID(riid, &IID_IMFTopologyServiceLookup) ||
2115 IsEqualIID(riid, &IID_IUnknown))
2117 *obj = iface;
2118 IMFTopologyServiceLookup_AddRef(iface);
2119 return S_OK;
2122 WARN("Unsupported interface %s.\n", debugstr_guid(riid));
2123 *obj = NULL;
2124 return E_NOINTERFACE;
2127 static ULONG WINAPI video_renderer_service_lookup_AddRef(IMFTopologyServiceLookup *iface)
2129 struct video_renderer *renderer = impl_from_IMFTopologyServiceLookup(iface);
2130 return IMFMediaSink_AddRef(&renderer->IMFMediaSink_iface);
2133 static ULONG WINAPI video_renderer_service_lookup_Release(IMFTopologyServiceLookup *iface)
2135 struct video_renderer *renderer = impl_from_IMFTopologyServiceLookup(iface);
2136 return IMFMediaSink_Release(&renderer->IMFMediaSink_iface);
2139 static HRESULT WINAPI video_renderer_service_lookup_LookupService(IMFTopologyServiceLookup *iface,
2140 MF_SERVICE_LOOKUP_TYPE lookup_type, DWORD index, REFGUID service, REFIID riid,
2141 void **objects, DWORD *num_objects)
2143 struct video_renderer *renderer = impl_from_IMFTopologyServiceLookup(iface);
2144 HRESULT hr = S_OK;
2146 TRACE("%p, %u, %u, %s, %s, %p, %p.\n", iface, lookup_type, index, debugstr_guid(service), debugstr_guid(riid),
2147 objects, num_objects);
2149 EnterCriticalSection(&renderer->cs);
2151 if (!(renderer->flags & EVR_INIT_SERVICES))
2152 hr = MF_E_NOTACCEPTING;
2153 else if (IsEqualGUID(service, &MR_VIDEO_RENDER_SERVICE))
2155 if (IsEqualIID(riid, &IID_IMediaEventSink))
2157 *objects = &renderer->IMediaEventSink_iface;
2158 IUnknown_AddRef((IUnknown *)*objects);
2160 else if (IsEqualIID(riid, &IID_IMFClock))
2162 *objects = renderer->clock;
2163 if (*objects)
2164 IUnknown_AddRef((IUnknown *)*objects);
2165 hr = *objects ? S_OK : E_NOINTERFACE;
2167 else
2169 FIXME("Unsupported interface %s for render service.\n", debugstr_guid(riid));
2170 hr = E_NOINTERFACE;
2173 else if (IsEqualGUID(service, &MR_VIDEO_MIXER_SERVICE))
2175 if (IsEqualIID(riid, &IID_IMFTransform))
2177 *objects = renderer->mixer;
2178 IUnknown_AddRef((IUnknown *)*objects);
2180 else
2182 FIXME("Unsupported interface %s for mixer service.\n", debugstr_guid(riid));
2183 hr = E_NOINTERFACE;
2186 else
2188 WARN("Unsupported service %s.\n", debugstr_guid(service));
2189 hr = MF_E_UNSUPPORTED_SERVICE;
2192 LeaveCriticalSection(&renderer->cs);
2194 return hr;
2197 static const IMFTopologyServiceLookupVtbl video_renderer_service_lookup_vtbl =
2199 video_renderer_service_lookup_QueryInterface,
2200 video_renderer_service_lookup_AddRef,
2201 video_renderer_service_lookup_Release,
2202 video_renderer_service_lookup_LookupService,
2205 static HRESULT WINAPI video_renderer_event_sink_QueryInterface(IMediaEventSink *iface, REFIID riid, void **obj)
2207 TRACE("%p, %s, %p.\n", iface, debugstr_guid(riid), obj);
2209 if (IsEqualIID(riid, &IID_IMediaEventSink) ||
2210 IsEqualIID(riid, &IID_IUnknown))
2212 *obj = iface;
2213 IMediaEventSink_AddRef(iface);
2214 return S_OK;
2217 WARN("Unsupported interface %s.\n", debugstr_guid(riid));
2218 *obj = NULL;
2219 return E_NOINTERFACE;
2222 static ULONG WINAPI video_renderer_event_sink_AddRef(IMediaEventSink *iface)
2224 struct video_renderer *renderer = impl_from_IMediaEventSink(iface);
2225 return IMFMediaSink_AddRef(&renderer->IMFMediaSink_iface);
2228 static ULONG WINAPI video_renderer_event_sink_Release(IMediaEventSink *iface)
2230 struct video_renderer *renderer = impl_from_IMediaEventSink(iface);
2231 return IMFMediaSink_Release(&renderer->IMFMediaSink_iface);
2234 static HRESULT WINAPI video_renderer_event_sink_Notify(IMediaEventSink *iface, LONG event, LONG_PTR param1, LONG_PTR param2)
2236 struct video_renderer *renderer = impl_from_IMediaEventSink(iface);
2237 HRESULT hr = S_OK;
2238 unsigned int idx;
2240 TRACE("%p, %d, %ld, %ld.\n", iface, event, param1, param2);
2242 EnterCriticalSection(&renderer->cs);
2244 if (event == EC_SAMPLE_NEEDED)
2246 idx = param1;
2247 if (idx >= renderer->stream_count)
2248 hr = MF_E_INVALIDSTREAMNUMBER;
2249 else if (renderer->state == EVR_STATE_RUNNING)
2251 hr = IMFMediaEventQueue_QueueEventParamVar(renderer->streams[idx]->event_queue,
2252 MEStreamSinkRequestSample, &GUID_NULL, S_OK, NULL);
2254 else
2256 /* Mixer asks for more input right after preroll too, before renderer finished running state transition.
2257 Mark such streams here, and issue requests later in OnClockStart(). */
2258 renderer->streams[idx]->flags |= EVR_STREAM_SAMPLE_NEEDED;
2261 else if (event == EC_DISPLAY_CHANGED)
2263 for (idx = 0; idx < renderer->stream_count; ++idx)
2264 IMFMediaEventQueue_QueueEventParamVar(renderer->streams[idx]->event_queue,
2265 MEStreamSinkDeviceChanged, &GUID_NULL, S_OK, NULL);
2267 else if (event >= EC_USER)
2269 PROPVARIANT code;
2271 code.vt = VT_I4;
2272 code.lVal = event;
2273 hr = IMFMediaEventQueue_QueueEventParamVar(renderer->event_queue, MERendererEvent,
2274 &GUID_NULL, S_OK, &code);
2276 else
2278 WARN("Unhandled event %d.\n", event);
2279 hr = MF_E_UNEXPECTED;
2282 LeaveCriticalSection(&renderer->cs);
2284 return hr;
2287 static const IMediaEventSinkVtbl media_event_sink_vtbl =
2289 video_renderer_event_sink_QueryInterface,
2290 video_renderer_event_sink_AddRef,
2291 video_renderer_event_sink_Release,
2292 video_renderer_event_sink_Notify,
2295 static HRESULT WINAPI video_renderer_attributes_QueryInterface(IMFAttributes *iface, REFIID riid, void **obj)
2297 struct video_renderer *renderer = impl_from_IMFAttributes(iface);
2298 return IMFMediaSink_QueryInterface(&renderer->IMFMediaSink_iface, riid, obj);
2301 static ULONG WINAPI video_renderer_attributes_AddRef(IMFAttributes *iface)
2303 struct video_renderer *renderer = impl_from_IMFAttributes(iface);
2304 return IMFMediaSink_AddRef(&renderer->IMFMediaSink_iface);
2307 static ULONG WINAPI video_renderer_attributes_Release(IMFAttributes *iface)
2309 struct video_renderer *renderer = impl_from_IMFAttributes(iface);
2310 return IMFMediaSink_Release(&renderer->IMFMediaSink_iface);
2313 static HRESULT WINAPI video_renderer_attributes_GetItem(IMFAttributes *iface, REFGUID key, PROPVARIANT *value)
2315 struct video_renderer *renderer = impl_from_IMFAttributes(iface);
2317 TRACE("%p, %s, %p.\n", iface, debugstr_guid(key), value);
2319 return IMFAttributes_GetItem(renderer->attributes, key, value);
2322 static HRESULT WINAPI video_renderer_attributes_GetItemType(IMFAttributes *iface, REFGUID key, MF_ATTRIBUTE_TYPE *type)
2324 struct video_renderer *renderer = impl_from_IMFAttributes(iface);
2326 TRACE("%p, %s, %p.\n", iface, debugstr_guid(key), type);
2328 return IMFAttributes_GetItemType(renderer->attributes, key, type);
2331 static HRESULT WINAPI video_renderer_attributes_CompareItem(IMFAttributes *iface, REFGUID key, REFPROPVARIANT value,
2332 BOOL *result)
2334 struct video_renderer *renderer = impl_from_IMFAttributes(iface);
2336 TRACE("%p, %s, %p, %p.\n", iface, debugstr_guid(key), value, result);
2338 return IMFAttributes_CompareItem(renderer->attributes, key, value, result);
2341 static HRESULT WINAPI video_renderer_attributes_Compare(IMFAttributes *iface, IMFAttributes *theirs,
2342 MF_ATTRIBUTES_MATCH_TYPE type, BOOL *result)
2344 struct video_renderer *renderer = impl_from_IMFAttributes(iface);
2346 TRACE("%p, %p, %d, %p.\n", iface, theirs, type, result);
2348 return IMFAttributes_Compare(renderer->attributes, theirs, type, result);
2351 static HRESULT WINAPI video_renderer_attributes_GetUINT32(IMFAttributes *iface, REFGUID key, UINT32 *value)
2353 struct video_renderer *renderer = impl_from_IMFAttributes(iface);
2355 TRACE("%p, %s, %p.\n", iface, debugstr_guid(key), value);
2357 return IMFAttributes_GetUINT32(renderer->attributes, key, value);
2360 static HRESULT WINAPI video_renderer_attributes_GetUINT64(IMFAttributes *iface, REFGUID key, UINT64 *value)
2362 struct video_renderer *renderer = impl_from_IMFAttributes(iface);
2364 TRACE("%p, %s, %p.\n", iface, debugstr_guid(key), value);
2366 return IMFAttributes_GetUINT64(renderer->attributes, key, value);
2369 static HRESULT WINAPI video_renderer_attributes_GetDouble(IMFAttributes *iface, REFGUID key, double *value)
2371 struct video_renderer *renderer = impl_from_IMFAttributes(iface);
2373 TRACE("%p, %s, %p.\n", iface, debugstr_guid(key), value);
2375 return IMFAttributes_GetDouble(renderer->attributes, key, value);
2378 static HRESULT WINAPI video_renderer_attributes_GetGUID(IMFAttributes *iface, REFGUID key, GUID *value)
2380 struct video_renderer *renderer = impl_from_IMFAttributes(iface);
2382 TRACE("%p, %s, %p.\n", iface, debugstr_guid(key), value);
2384 return IMFAttributes_GetGUID(renderer->attributes, key, value);
2387 static HRESULT WINAPI video_renderer_attributes_GetStringLength(IMFAttributes *iface, REFGUID key,
2388 UINT32 *length)
2390 struct video_renderer *renderer = impl_from_IMFAttributes(iface);
2392 TRACE("%p, %s, %p.\n", iface, debugstr_guid(key), length);
2394 return IMFAttributes_GetStringLength(renderer->attributes, key, length);
2397 static HRESULT WINAPI video_renderer_attributes_GetString(IMFAttributes *iface, REFGUID key, WCHAR *value,
2398 UINT32 size, UINT32 *length)
2400 struct video_renderer *renderer = impl_from_IMFAttributes(iface);
2402 TRACE("%p, %s, %p, %u, %p.\n", iface, debugstr_guid(key), value, size, length);
2404 return IMFAttributes_GetString(renderer->attributes, key, value, size, length);
2407 static HRESULT WINAPI video_renderer_attributes_GetAllocatedString(IMFAttributes *iface, REFGUID key,
2408 WCHAR **value, UINT32 *length)
2410 struct video_renderer *renderer = impl_from_IMFAttributes(iface);
2412 TRACE("%p, %s, %p, %p.\n", iface, debugstr_guid(key), value, length);
2414 return IMFAttributes_GetAllocatedString(renderer->attributes, key, value, length);
2417 static HRESULT WINAPI video_renderer_attributes_GetBlobSize(IMFAttributes *iface, REFGUID key, UINT32 *size)
2419 struct video_renderer *renderer = impl_from_IMFAttributes(iface);
2421 TRACE("%p, %s, %p.\n", iface, debugstr_guid(key), size);
2423 return IMFAttributes_GetBlobSize(renderer->attributes, key, size);
2426 static HRESULT WINAPI video_renderer_attributes_GetBlob(IMFAttributes *iface, REFGUID key, UINT8 *buf,
2427 UINT32 bufsize, UINT32 *blobsize)
2429 struct video_renderer *renderer = impl_from_IMFAttributes(iface);
2431 TRACE("%p, %s, %p, %u, %p.\n", iface, debugstr_guid(key), buf, bufsize, blobsize);
2433 return IMFAttributes_GetBlob(renderer->attributes, key, buf, bufsize, blobsize);
2436 static HRESULT WINAPI video_renderer_attributes_GetAllocatedBlob(IMFAttributes *iface, REFGUID key,
2437 UINT8 **buf, UINT32 *size)
2439 struct video_renderer *renderer = impl_from_IMFAttributes(iface);
2441 TRACE("%p, %s, %p, %p.\n", iface, debugstr_guid(key), buf, size);
2443 return IMFAttributes_GetAllocatedBlob(renderer->attributes, key, buf, size);
2446 static HRESULT WINAPI video_renderer_attributes_GetUnknown(IMFAttributes *iface, REFGUID key, REFIID riid, void **out)
2448 struct video_renderer *renderer = impl_from_IMFAttributes(iface);
2450 TRACE("%p, %s, %s, %p.\n", iface, debugstr_guid(key), debugstr_guid(riid), out);
2452 return IMFAttributes_GetUnknown(renderer->attributes, key, riid, out);
2455 static HRESULT WINAPI video_renderer_attributes_SetItem(IMFAttributes *iface, REFGUID key, REFPROPVARIANT value)
2457 struct video_renderer *renderer = impl_from_IMFAttributes(iface);
2459 TRACE("%p, %s, %p.\n", iface, debugstr_guid(key), value);
2461 return IMFAttributes_SetItem(renderer->attributes, key, value);
2464 static HRESULT WINAPI video_renderer_attributes_DeleteItem(IMFAttributes *iface, REFGUID key)
2466 struct video_renderer *renderer = impl_from_IMFAttributes(iface);
2468 TRACE("%p, %s.\n", iface, debugstr_guid(key));
2470 return IMFAttributes_DeleteItem(renderer->attributes, key);
2473 static HRESULT WINAPI video_renderer_attributes_DeleteAllItems(IMFAttributes *iface)
2475 struct video_renderer *renderer = impl_from_IMFAttributes(iface);
2477 TRACE("%p.\n", iface);
2479 return IMFAttributes_DeleteAllItems(renderer->attributes);
2482 static HRESULT WINAPI video_renderer_attributes_SetUINT32(IMFAttributes *iface, REFGUID key, UINT32 value)
2484 struct video_renderer *renderer = impl_from_IMFAttributes(iface);
2486 TRACE("%p, %s, %u.\n", iface, debugstr_guid(key), value);
2488 return IMFAttributes_SetUINT32(renderer->attributes, key, value);
2491 static HRESULT WINAPI video_renderer_attributes_SetUINT64(IMFAttributes *iface, REFGUID key, UINT64 value)
2493 struct video_renderer *renderer = impl_from_IMFAttributes(iface);
2495 TRACE("%p, %s, %s.\n", iface, debugstr_guid(key), wine_dbgstr_longlong(value));
2497 return IMFAttributes_SetUINT64(renderer->attributes, key, value);
2500 static HRESULT WINAPI video_renderer_attributes_SetDouble(IMFAttributes *iface, REFGUID key, double value)
2502 struct video_renderer *renderer = impl_from_IMFAttributes(iface);
2504 TRACE("%p, %s, %f.\n", iface, debugstr_guid(key), value);
2506 return IMFAttributes_SetDouble(renderer->attributes, key, value);
2509 static HRESULT WINAPI video_renderer_attributes_SetGUID(IMFAttributes *iface, REFGUID key, REFGUID value)
2511 struct video_renderer *renderer = impl_from_IMFAttributes(iface);
2513 TRACE("%p, %s, %s.\n", iface, debugstr_guid(key), debugstr_guid(value));
2515 return IMFAttributes_SetGUID(renderer->attributes, key, value);
2518 static HRESULT WINAPI video_renderer_attributes_SetString(IMFAttributes *iface, REFGUID key,
2519 const WCHAR *value)
2521 struct video_renderer *renderer = impl_from_IMFAttributes(iface);
2523 TRACE("%p, %s, %s.\n", iface, debugstr_guid(key), debugstr_w(value));
2525 return IMFAttributes_SetString(renderer->attributes, key, value);
2528 static HRESULT WINAPI video_renderer_attributes_SetBlob(IMFAttributes *iface, REFGUID key,
2529 const UINT8 *buf, UINT32 size)
2531 struct video_renderer *renderer = impl_from_IMFAttributes(iface);
2533 TRACE("%p, %s, %p, %u.\n", iface, debugstr_guid(key), buf, size);
2535 return IMFAttributes_SetBlob(renderer->attributes, key, buf, size);
2538 static HRESULT WINAPI video_renderer_attributes_SetUnknown(IMFAttributes *iface, REFGUID key,
2539 IUnknown *unknown)
2541 struct video_renderer *renderer = impl_from_IMFAttributes(iface);
2543 TRACE("%p, %s, %p.\n", iface, debugstr_guid(key), unknown);
2545 return IMFAttributes_SetUnknown(renderer->attributes, key, unknown);
2548 static HRESULT WINAPI video_renderer_attributes_LockStore(IMFAttributes *iface)
2550 struct video_renderer *renderer = impl_from_IMFAttributes(iface);
2552 TRACE("%p.\n", iface);
2554 return IMFAttributes_LockStore(renderer->attributes);
2557 static HRESULT WINAPI video_renderer_attributes_UnlockStore(IMFAttributes *iface)
2559 struct video_renderer *renderer = impl_from_IMFAttributes(iface);
2561 TRACE("%p.\n", iface);
2563 return IMFAttributes_UnlockStore(renderer->attributes);
2566 static HRESULT WINAPI video_renderer_attributes_GetCount(IMFAttributes *iface, UINT32 *count)
2568 struct video_renderer *renderer = impl_from_IMFAttributes(iface);
2570 TRACE("%p, %p.\n", iface, count);
2572 return IMFAttributes_GetCount(renderer->attributes, count);
2575 static HRESULT WINAPI video_renderer_attributes_GetItemByIndex(IMFAttributes *iface, UINT32 index,
2576 GUID *key, PROPVARIANT *value)
2578 struct video_renderer *renderer = impl_from_IMFAttributes(iface);
2580 TRACE("%p, %u, %p, %p.\n", iface, index, key, value);
2582 return IMFAttributes_GetItemByIndex(renderer->attributes, index, key, value);
2585 static HRESULT WINAPI video_renderer_attributes_CopyAllItems(IMFAttributes *iface, IMFAttributes *dest)
2587 struct video_renderer *renderer = impl_from_IMFAttributes(iface);
2589 TRACE("%p, %p.\n", iface, dest);
2591 return IMFAttributes_CopyAllItems(renderer->attributes, dest);
2594 static const IMFAttributesVtbl video_renderer_attributes_vtbl =
2596 video_renderer_attributes_QueryInterface,
2597 video_renderer_attributes_AddRef,
2598 video_renderer_attributes_Release,
2599 video_renderer_attributes_GetItem,
2600 video_renderer_attributes_GetItemType,
2601 video_renderer_attributes_CompareItem,
2602 video_renderer_attributes_Compare,
2603 video_renderer_attributes_GetUINT32,
2604 video_renderer_attributes_GetUINT64,
2605 video_renderer_attributes_GetDouble,
2606 video_renderer_attributes_GetGUID,
2607 video_renderer_attributes_GetStringLength,
2608 video_renderer_attributes_GetString,
2609 video_renderer_attributes_GetAllocatedString,
2610 video_renderer_attributes_GetBlobSize,
2611 video_renderer_attributes_GetBlob,
2612 video_renderer_attributes_GetAllocatedBlob,
2613 video_renderer_attributes_GetUnknown,
2614 video_renderer_attributes_SetItem,
2615 video_renderer_attributes_DeleteItem,
2616 video_renderer_attributes_DeleteAllItems,
2617 video_renderer_attributes_SetUINT32,
2618 video_renderer_attributes_SetUINT64,
2619 video_renderer_attributes_SetDouble,
2620 video_renderer_attributes_SetGUID,
2621 video_renderer_attributes_SetString,
2622 video_renderer_attributes_SetBlob,
2623 video_renderer_attributes_SetUnknown,
2624 video_renderer_attributes_LockStore,
2625 video_renderer_attributes_UnlockStore,
2626 video_renderer_attributes_GetCount,
2627 video_renderer_attributes_GetItemByIndex,
2628 video_renderer_attributes_CopyAllItems,
2631 static HRESULT WINAPI video_renderer_quality_advise_QueryInterface(IMFQualityAdvise *iface, REFIID riid, void **out)
2633 struct video_renderer *renderer = impl_from_IMFQualityAdvise(iface);
2634 return IMFMediaSink_QueryInterface(&renderer->IMFMediaSink_iface, riid, out);
2637 static ULONG WINAPI video_renderer_quality_advise_AddRef(IMFQualityAdvise *iface)
2639 struct video_renderer *renderer = impl_from_IMFQualityAdvise(iface);
2640 return IMFMediaSink_AddRef(&renderer->IMFMediaSink_iface);
2643 static ULONG WINAPI video_renderer_quality_Release(IMFQualityAdvise *iface)
2645 struct video_renderer *renderer = impl_from_IMFQualityAdvise(iface);
2646 return IMFMediaSink_Release(&renderer->IMFMediaSink_iface);
2649 static HRESULT WINAPI video_renderer_quality_advise_SetDropMode(IMFQualityAdvise *iface,
2650 MF_QUALITY_DROP_MODE mode)
2652 FIXME("%p, %u.\n", iface, mode);
2654 return E_NOTIMPL;
2657 static HRESULT WINAPI video_renderer_quality_advise_SetQualityLevel(IMFQualityAdvise *iface,
2658 MF_QUALITY_LEVEL level)
2660 FIXME("%p, %u.\n", iface, level);
2662 return E_NOTIMPL;
2665 static HRESULT WINAPI video_renderer_quality_advise_GetDropMode(IMFQualityAdvise *iface,
2666 MF_QUALITY_DROP_MODE *mode)
2668 FIXME("%p, %p.\n", iface, mode);
2670 return E_NOTIMPL;
2673 static HRESULT WINAPI video_renderer_quality_advise_GetQualityLevel(IMFQualityAdvise *iface,
2674 MF_QUALITY_LEVEL *level)
2676 FIXME("%p, %p.\n", iface, level);
2678 return E_NOTIMPL;
2681 static HRESULT WINAPI video_renderer_quality_advise_DropTime(IMFQualityAdvise *iface, LONGLONG interval)
2683 FIXME("%p, %s.\n", iface, wine_dbgstr_longlong(interval));
2685 return E_NOTIMPL;
2688 static const IMFQualityAdviseVtbl video_renderer_quality_advise_vtbl =
2690 video_renderer_quality_advise_QueryInterface,
2691 video_renderer_quality_advise_AddRef,
2692 video_renderer_quality_Release,
2693 video_renderer_quality_advise_SetDropMode,
2694 video_renderer_quality_advise_SetQualityLevel,
2695 video_renderer_quality_advise_GetDropMode,
2696 video_renderer_quality_advise_GetQualityLevel,
2697 video_renderer_quality_advise_DropTime,
2700 static HRESULT WINAPI video_renderer_rate_support_QueryInterface(IMFRateSupport *iface, REFIID riid, void **out)
2702 struct video_renderer *renderer = impl_from_IMFRateSupport(iface);
2703 return IMFMediaSink_QueryInterface(&renderer->IMFMediaSink_iface, riid, out);
2706 static ULONG WINAPI video_renderer_rate_support_AddRef(IMFRateSupport *iface)
2708 struct video_renderer *renderer = impl_from_IMFRateSupport(iface);
2709 return IMFMediaSink_AddRef(&renderer->IMFMediaSink_iface);
2712 static ULONG WINAPI video_renderer_rate_support_Release(IMFRateSupport *iface)
2714 struct video_renderer *renderer = impl_from_IMFRateSupport(iface);
2715 return IMFMediaSink_Release(&renderer->IMFMediaSink_iface);
2718 static HRESULT WINAPI video_renderer_rate_support_GetSlowestRate(IMFRateSupport *iface, MFRATE_DIRECTION direction,
2719 BOOL thin, float *rate)
2721 struct video_renderer *renderer = impl_from_IMFRateSupport(iface);
2723 TRACE("%p, %d, %d, %p.\n", iface, direction, thin, rate);
2725 if (renderer->flags & EVR_SHUT_DOWN)
2726 return MF_E_SHUTDOWN;
2728 *rate = 0.0f;
2730 return S_OK;
2733 static HRESULT WINAPI video_renderer_rate_support_GetFastestRate(IMFRateSupport *iface, MFRATE_DIRECTION direction,
2734 BOOL thin, float *rate)
2736 struct video_renderer *renderer = impl_from_IMFRateSupport(iface);
2738 TRACE("%p, %d, %d, %p.\n", iface, direction, thin, rate);
2740 return renderer->flags & EVR_SHUT_DOWN ? MF_E_SHUTDOWN : MF_E_INVALIDREQUEST;
2743 static HRESULT WINAPI video_renderer_rate_support_IsRateSupported(IMFRateSupport *iface, BOOL thin, float rate,
2744 float *nearest_supported_rate)
2746 FIXME("%p, %d, %f, %p.\n", iface, thin, rate, nearest_supported_rate);
2748 return E_NOTIMPL;
2751 static const IMFRateSupportVtbl video_renderer_rate_support_vtbl =
2753 video_renderer_rate_support_QueryInterface,
2754 video_renderer_rate_support_AddRef,
2755 video_renderer_rate_support_Release,
2756 video_renderer_rate_support_GetSlowestRate,
2757 video_renderer_rate_support_GetFastestRate,
2758 video_renderer_rate_support_IsRateSupported,
2761 static HRESULT evr_create_object(IMFAttributes *attributes, void *user_context, IUnknown **obj)
2763 struct video_renderer *object;
2764 IMFVideoPresenter *presenter = NULL;
2765 IMFTransform *mixer = NULL;
2766 HRESULT hr;
2768 TRACE("%p, %p, %p.\n", attributes, user_context, obj);
2770 if (!(object = calloc(1, sizeof(*object))))
2771 return E_OUTOFMEMORY;
2773 object->IMFMediaSink_iface.lpVtbl = &video_renderer_sink_vtbl;
2774 object->IMFMediaSinkPreroll_iface.lpVtbl = &video_renderer_preroll_vtbl;
2775 object->IMFVideoRenderer_iface.lpVtbl = &video_renderer_vtbl;
2776 object->IMFMediaEventGenerator_iface.lpVtbl = &video_renderer_events_vtbl;
2777 object->IMFClockStateSink_iface.lpVtbl = &video_renderer_clock_sink_vtbl;
2778 object->IMFGetService_iface.lpVtbl = &video_renderer_get_service_vtbl;
2779 object->IMFTopologyServiceLookup_iface.lpVtbl = &video_renderer_service_lookup_vtbl;
2780 object->IMediaEventSink_iface.lpVtbl = &media_event_sink_vtbl;
2781 object->IMFAttributes_iface.lpVtbl = &video_renderer_attributes_vtbl;
2782 object->IMFQualityAdvise_iface.lpVtbl = &video_renderer_quality_advise_vtbl;
2783 object->IMFRateSupport_iface.lpVtbl = &video_renderer_rate_support_vtbl;
2784 object->refcount = 1;
2785 InitializeCriticalSection(&object->cs);
2787 if (FAILED(hr = MFCreateEventQueue(&object->event_queue)))
2788 goto failed;
2790 if (FAILED(hr = MFCreateAttributes(&object->attributes, 0)))
2791 goto failed;
2793 /* Create mixer and presenter. */
2794 if (FAILED(hr = video_renderer_create_mixer(attributes, &mixer)))
2795 goto failed;
2797 if (FAILED(hr = video_renderer_create_presenter(object, attributes, &presenter)))
2798 goto failed;
2800 if (FAILED(hr = video_renderer_initialize(object, mixer, presenter)))
2801 goto failed;
2803 IMFTransform_Release(mixer);
2804 IMFVideoPresenter_Release(presenter);
2806 /* Default attributes */
2807 IMFAttributes_SetUINT32(object->attributes, &EVRConfig_ForceBob, 0);
2808 IMFAttributes_SetUINT32(object->attributes, &EVRConfig_AllowDropToBob, 0);
2809 IMFAttributes_SetUINT32(object->attributes, &EVRConfig_ForceThrottle, 0);
2810 IMFAttributes_SetUINT32(object->attributes, &EVRConfig_AllowDropToThrottle, 0);
2811 IMFAttributes_SetUINT32(object->attributes, &EVRConfig_ForceHalfInterlace, 0);
2812 IMFAttributes_SetUINT32(object->attributes, &EVRConfig_AllowDropToHalfInterlace, 0);
2813 IMFAttributes_SetUINT32(object->attributes, &EVRConfig_ForceScaling, 0);
2814 IMFAttributes_SetUINT32(object->attributes, &EVRConfig_AllowScaling, 0);
2815 IMFAttributes_SetUINT32(object->attributes, &EVRConfig_ForceBatching, 0);
2816 IMFAttributes_SetUINT32(object->attributes, &EVRConfig_AllowBatching, 0);
2818 *obj = (IUnknown *)&object->IMFMediaSink_iface;
2820 return S_OK;
2822 failed:
2824 if (mixer)
2825 IMFTransform_Release(mixer);
2827 if (presenter)
2828 IMFVideoPresenter_Release(presenter);
2830 video_renderer_release_services(object);
2831 IMFMediaSink_Release(&object->IMFMediaSink_iface);
2833 return hr;
2836 static void evr_shutdown_object(void *user_context, IUnknown *obj)
2838 IMFMediaSink *sink;
2840 if (SUCCEEDED(IUnknown_QueryInterface(obj, &IID_IMFMediaSink, (void **)&sink)))
2842 IMFMediaSink_Shutdown(sink);
2843 IMFMediaSink_Release(sink);
2847 static const struct activate_funcs evr_activate_funcs =
2849 .create_object = evr_create_object,
2850 .shutdown_object = evr_shutdown_object,
2853 /***********************************************************************
2854 * MFCreateVideoRendererActivate (mf.@)
2856 HRESULT WINAPI MFCreateVideoRendererActivate(HWND hwnd, IMFActivate **activate)
2858 HRESULT hr;
2860 TRACE("%p, %p.\n", hwnd, activate);
2862 if (!activate)
2863 return E_POINTER;
2865 hr = create_activation_object(NULL, &evr_activate_funcs, activate);
2866 if (SUCCEEDED(hr))
2867 IMFActivate_SetUINT64(*activate, &MF_ACTIVATE_VIDEO_WINDOW, (ULONG_PTR)hwnd);
2869 return hr;
2872 /***********************************************************************
2873 * MFCreateVideoRenderer (mf.@)
2875 HRESULT WINAPI MFCreateVideoRenderer(REFIID riid, void **renderer)
2877 IUnknown *obj;
2878 HRESULT hr;
2880 TRACE("%s, %p.\n", debugstr_guid(riid), renderer);
2882 *renderer = NULL;
2884 if (SUCCEEDED(hr = evr_create_object(NULL, NULL, &obj)))
2886 hr = IUnknown_QueryInterface(obj, riid, renderer);
2887 IUnknown_Release(obj);
2890 return hr;