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
21 #include "mf_private.h"
29 WINE_DEFAULT_DEBUG_CHANNEL(mfplat
);
31 enum video_renderer_flags
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,
46 enum video_stream_flags
48 EVR_STREAM_PREROLLING
= 0x1,
49 EVR_STREAM_PREROLLED
= 0x2,
52 struct video_renderer
;
56 IMFStreamSink IMFStreamSink_iface
;
57 IMFMediaTypeHandler IMFMediaTypeHandler_iface
;
58 IMFGetService IMFGetService_iface
;
62 struct video_renderer
*parent
;
63 IMFMediaEventQueue
*event_queue
;
64 IMFVideoSampleAllocator
*allocator
;
70 IMFMediaSink IMFMediaSink_iface
;
71 IMFMediaSinkPreroll IMFMediaSinkPreroll_iface
;
72 IMFVideoRenderer IMFVideoRenderer_iface
;
73 IMFClockStateSink IMFClockStateSink_iface
;
74 IMFMediaEventGenerator IMFMediaEventGenerator_iface
;
75 IMFGetService IMFGetService_iface
;
76 IMFTopologyServiceLookup IMFTopologyServiceLookup_iface
;
77 IMediaEventSink IMediaEventSink_iface
;
78 IMFAttributes IMFAttributes_iface
;
79 IMFQualityAdvise IMFQualityAdvise_iface
;
82 IMFMediaEventQueue
*event_queue
;
83 IMFAttributes
*attributes
;
84 IMFPresentationClock
*clock
;
87 IMFVideoPresenter
*presenter
;
89 IUnknown
*device_manager
;
93 struct video_stream
**streams
;
100 static struct video_renderer
*impl_from_IMFMediaSink(IMFMediaSink
*iface
)
102 return CONTAINING_RECORD(iface
, struct video_renderer
, IMFMediaSink_iface
);
105 static struct video_renderer
*impl_from_IMFMediaSinkPreroll(IMFMediaSinkPreroll
*iface
)
107 return CONTAINING_RECORD(iface
, struct video_renderer
, IMFMediaSinkPreroll_iface
);
110 static struct video_renderer
*impl_from_IMFVideoRenderer(IMFVideoRenderer
*iface
)
112 return CONTAINING_RECORD(iface
, struct video_renderer
, IMFVideoRenderer_iface
);
115 static struct video_renderer
*impl_from_IMFMediaEventGenerator(IMFMediaEventGenerator
*iface
)
117 return CONTAINING_RECORD(iface
, struct video_renderer
, IMFMediaEventGenerator_iface
);
120 static struct video_renderer
*impl_from_IMFClockStateSink(IMFClockStateSink
*iface
)
122 return CONTAINING_RECORD(iface
, struct video_renderer
, IMFClockStateSink_iface
);
125 static struct video_renderer
*impl_from_IMFGetService(IMFGetService
*iface
)
127 return CONTAINING_RECORD(iface
, struct video_renderer
, IMFGetService_iface
);
130 static struct video_renderer
*impl_from_IMFTopologyServiceLookup(IMFTopologyServiceLookup
*iface
)
132 return CONTAINING_RECORD(iface
, struct video_renderer
, IMFTopologyServiceLookup_iface
);
135 static struct video_renderer
*impl_from_IMediaEventSink(IMediaEventSink
*iface
)
137 return CONTAINING_RECORD(iface
, struct video_renderer
, IMediaEventSink_iface
);
140 static struct video_renderer
*impl_from_IMFAttributes(IMFAttributes
*iface
)
142 return CONTAINING_RECORD(iface
, struct video_renderer
, IMFAttributes_iface
);
145 static struct video_renderer
*impl_from_IMFQualityAdvise(IMFQualityAdvise
*iface
)
147 return CONTAINING_RECORD(iface
, struct video_renderer
, IMFQualityAdvise_iface
);
150 static struct video_stream
*impl_from_IMFStreamSink(IMFStreamSink
*iface
)
152 return CONTAINING_RECORD(iface
, struct video_stream
, IMFStreamSink_iface
);
155 static struct video_stream
*impl_from_IMFMediaTypeHandler(IMFMediaTypeHandler
*iface
)
157 return CONTAINING_RECORD(iface
, struct video_stream
, IMFMediaTypeHandler_iface
);
160 static struct video_stream
*impl_from_stream_IMFGetService(IMFGetService
*iface
)
162 return CONTAINING_RECORD(iface
, struct video_stream
, IMFGetService_iface
);
165 static void video_renderer_release_services(struct video_renderer
*renderer
)
167 IMFTopologyServiceLookupClient
*lookup_client
;
169 if (renderer
->flags
& EVR_MIXER_INITED_SERVICES
&& SUCCEEDED(IMFTransform_QueryInterface(renderer
->mixer
,
170 &IID_IMFTopologyServiceLookupClient
, (void **)&lookup_client
)))
172 IMFTopologyServiceLookupClient_ReleaseServicePointers(lookup_client
);
173 IMFTopologyServiceLookupClient_Release(lookup_client
);
174 renderer
->flags
&= ~EVR_MIXER_INITED_SERVICES
;
177 if (renderer
->flags
& EVR_PRESENTER_INITED_SERVICES
&& SUCCEEDED(IMFVideoPresenter_QueryInterface(renderer
->presenter
,
178 &IID_IMFTopologyServiceLookupClient
, (void **)&lookup_client
)))
180 IMFTopologyServiceLookupClient_ReleaseServicePointers(lookup_client
);
181 IMFTopologyServiceLookupClient_Release(lookup_client
);
182 renderer
->flags
&= ~EVR_PRESENTER_INITED_SERVICES
;
186 static HRESULT WINAPI
video_stream_sink_QueryInterface(IMFStreamSink
*iface
, REFIID riid
, void **obj
)
188 struct video_stream
*stream
= impl_from_IMFStreamSink(iface
);
190 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(riid
), obj
);
194 if (IsEqualIID(riid
, &IID_IMFStreamSink
) ||
195 IsEqualIID(riid
, &IID_IMFMediaEventGenerator
) ||
196 IsEqualIID(riid
, &IID_IUnknown
))
200 else if (IsEqualIID(riid
, &IID_IMFMediaTypeHandler
))
202 *obj
= &stream
->IMFMediaTypeHandler_iface
;
204 else if (IsEqualIID(riid
, &IID_IMFGetService
))
206 *obj
= &stream
->IMFGetService_iface
;
211 IUnknown_AddRef((IUnknown
*)*obj
);
215 WARN("Unsupported interface %s.\n", debugstr_guid(riid
));
217 return E_NOINTERFACE
;
220 static ULONG WINAPI
video_stream_sink_AddRef(IMFStreamSink
*iface
)
222 struct video_stream
*stream
= impl_from_IMFStreamSink(iface
);
223 ULONG refcount
= InterlockedIncrement(&stream
->refcount
);
225 TRACE("%p, refcount %u.\n", iface
, refcount
);
230 static ULONG WINAPI
video_stream_sink_Release(IMFStreamSink
*iface
)
232 struct video_stream
*stream
= impl_from_IMFStreamSink(iface
);
233 ULONG refcount
= InterlockedDecrement(&stream
->refcount
);
237 if (stream
->event_queue
)
238 IMFMediaEventQueue_Release(stream
->event_queue
);
239 if (stream
->allocator
)
240 IMFVideoSampleAllocator_Release(stream
->allocator
);
241 DeleteCriticalSection(&stream
->cs
);
248 static HRESULT WINAPI
video_stream_sink_GetEvent(IMFStreamSink
*iface
, DWORD flags
, IMFMediaEvent
**event
)
250 struct video_stream
*stream
= impl_from_IMFStreamSink(iface
);
252 TRACE("%p, %#x, %p.\n", iface
, flags
, event
);
254 return IMFMediaEventQueue_GetEvent(stream
->event_queue
, flags
, event
);
257 static HRESULT WINAPI
video_stream_sink_BeginGetEvent(IMFStreamSink
*iface
, IMFAsyncCallback
*callback
, IUnknown
*state
)
259 struct video_stream
*stream
= impl_from_IMFStreamSink(iface
);
261 TRACE("%p, %p, %p.\n", iface
, callback
, state
);
263 return IMFMediaEventQueue_BeginGetEvent(stream
->event_queue
, callback
, state
);
266 static HRESULT WINAPI
video_stream_sink_EndGetEvent(IMFStreamSink
*iface
, IMFAsyncResult
*result
,
267 IMFMediaEvent
**event
)
269 struct video_stream
*stream
= impl_from_IMFStreamSink(iface
);
271 TRACE("%p, %p, %p.\n", iface
, result
, event
);
273 return IMFMediaEventQueue_EndGetEvent(stream
->event_queue
, result
, event
);
276 static HRESULT WINAPI
video_stream_sink_QueueEvent(IMFStreamSink
*iface
, MediaEventType event_type
,
277 REFGUID ext_type
, HRESULT hr
, const PROPVARIANT
*value
)
279 struct video_stream
*stream
= impl_from_IMFStreamSink(iface
);
281 TRACE("%p, %d, %s, %#x, %p.\n", iface
, event_type
, debugstr_guid(ext_type
), hr
, value
);
283 return IMFMediaEventQueue_QueueEventParamVar(stream
->event_queue
, event_type
, ext_type
, hr
, value
);
286 static HRESULT WINAPI
video_stream_sink_GetMediaSink(IMFStreamSink
*iface
, IMFMediaSink
**sink
)
288 struct video_stream
*stream
= impl_from_IMFStreamSink(iface
);
291 TRACE("%p, %p.\n", iface
, sink
);
293 EnterCriticalSection(&stream
->cs
);
295 hr
= MF_E_STREAMSINK_REMOVED
;
300 *sink
= &stream
->parent
->IMFMediaSink_iface
;
301 IMFMediaSink_AddRef(*sink
);
303 LeaveCriticalSection(&stream
->cs
);
308 static HRESULT WINAPI
video_stream_sink_GetIdentifier(IMFStreamSink
*iface
, DWORD
*id
)
310 struct video_stream
*stream
= impl_from_IMFStreamSink(iface
);
312 TRACE("%p, %p.\n", iface
, id
);
315 return MF_E_STREAMSINK_REMOVED
;
325 static HRESULT WINAPI
video_stream_sink_GetMediaTypeHandler(IMFStreamSink
*iface
, IMFMediaTypeHandler
**handler
)
327 struct video_stream
*stream
= impl_from_IMFStreamSink(iface
);
329 TRACE("%p, %p.\n", iface
, handler
);
335 return MF_E_STREAMSINK_REMOVED
;
337 *handler
= &stream
->IMFMediaTypeHandler_iface
;
338 IMFMediaTypeHandler_AddRef(*handler
);
343 static HRESULT WINAPI
video_stream_sink_ProcessSample(IMFStreamSink
*iface
, IMFSample
*sample
)
345 struct video_stream
*stream
= impl_from_IMFStreamSink(iface
);
349 TRACE("%p, %p.\n", iface
, sample
);
351 EnterCriticalSection(&stream
->cs
);
354 hr
= MF_E_STREAMSINK_REMOVED
;
355 else if (!stream
->parent
->clock
)
357 else if (FAILED(hr
= IMFSample_GetSampleTime(sample
, ×tamp
)))
359 WARN("No sample timestamp, hr %#x.\n", hr
);
361 else if (stream
->parent
->state
== EVR_STATE_RUNNING
|| stream
->flags
& EVR_STREAM_PREROLLING
)
363 if (SUCCEEDED(IMFTransform_ProcessInput(stream
->parent
->mixer
, stream
->id
, sample
, 0)))
364 IMFVideoPresenter_ProcessMessage(stream
->parent
->presenter
, MFVP_MESSAGE_PROCESSINPUTNOTIFY
, 0);
366 if (stream
->flags
& EVR_STREAM_PREROLLING
)
368 IMFMediaEventQueue_QueueEventParamVar(stream
->event_queue
, MEStreamSinkPrerolled
, &GUID_NULL
, S_OK
, NULL
);
369 stream
->flags
&= ~EVR_STREAM_PREROLLING
;
370 stream
->flags
|= EVR_STREAM_PREROLLED
;
374 LeaveCriticalSection(&stream
->cs
);
379 static HRESULT WINAPI
video_stream_sink_PlaceMarker(IMFStreamSink
*iface
, MFSTREAMSINK_MARKER_TYPE marker_type
,
380 const PROPVARIANT
*marker_value
, const PROPVARIANT
*context_value
)
382 FIXME("%p, %d, %p, %p.\n", iface
, marker_type
, marker_value
, context_value
);
387 static HRESULT WINAPI
video_stream_sink_Flush(IMFStreamSink
*iface
)
389 FIXME("%p.\n", iface
);
394 static const IMFStreamSinkVtbl video_stream_sink_vtbl
=
396 video_stream_sink_QueryInterface
,
397 video_stream_sink_AddRef
,
398 video_stream_sink_Release
,
399 video_stream_sink_GetEvent
,
400 video_stream_sink_BeginGetEvent
,
401 video_stream_sink_EndGetEvent
,
402 video_stream_sink_QueueEvent
,
403 video_stream_sink_GetMediaSink
,
404 video_stream_sink_GetIdentifier
,
405 video_stream_sink_GetMediaTypeHandler
,
406 video_stream_sink_ProcessSample
,
407 video_stream_sink_PlaceMarker
,
408 video_stream_sink_Flush
,
411 static HRESULT WINAPI
video_stream_typehandler_QueryInterface(IMFMediaTypeHandler
*iface
, REFIID riid
,
414 struct video_stream
*stream
= impl_from_IMFMediaTypeHandler(iface
);
415 return IMFStreamSink_QueryInterface(&stream
->IMFStreamSink_iface
, riid
, obj
);
418 static ULONG WINAPI
video_stream_typehandler_AddRef(IMFMediaTypeHandler
*iface
)
420 struct video_stream
*stream
= impl_from_IMFMediaTypeHandler(iface
);
421 return IMFStreamSink_AddRef(&stream
->IMFStreamSink_iface
);
424 static ULONG WINAPI
video_stream_typehandler_Release(IMFMediaTypeHandler
*iface
)
426 struct video_stream
*stream
= impl_from_IMFMediaTypeHandler(iface
);
427 return IMFStreamSink_Release(&stream
->IMFStreamSink_iface
);
430 static HRESULT WINAPI
video_stream_typehandler_IsMediaTypeSupported(IMFMediaTypeHandler
*iface
,
431 IMFMediaType
*in_type
, IMFMediaType
**out_type
)
433 struct video_stream
*stream
= impl_from_IMFMediaTypeHandler(iface
);
436 TRACE("%p, %p, %p.\n", iface
, in_type
, out_type
);
442 return MF_E_INVALIDMEDIATYPE
;
444 if (SUCCEEDED(hr
= IMFTransform_SetInputType(stream
->parent
->mixer
, stream
->id
, in_type
,
445 MFT_SET_TYPE_TEST_ONLY
)))
447 if (out_type
) *out_type
= NULL
;
453 static HRESULT WINAPI
video_stream_typehandler_GetMediaTypeCount(IMFMediaTypeHandler
*iface
, DWORD
*count
)
455 TRACE("%p, %p.\n", iface
, count
);
465 static HRESULT WINAPI
video_stream_typehandler_GetMediaTypeByIndex(IMFMediaTypeHandler
*iface
, DWORD index
,
468 TRACE("%p, %u, %p.\n", iface
, index
, type
);
470 return MF_E_NO_MORE_TYPES
;
473 static HRESULT WINAPI
video_stream_typehandler_SetCurrentMediaType(IMFMediaTypeHandler
*iface
, IMFMediaType
*type
)
475 struct video_stream
*stream
= impl_from_IMFMediaTypeHandler(iface
);
478 TRACE("%p, %p.\n", iface
, type
);
484 return MF_E_STREAMSINK_REMOVED
;
486 hr
= IMFTransform_SetInputType(stream
->parent
->mixer
, stream
->id
, type
, 0);
487 if (SUCCEEDED(hr
) && !stream
->id
)
488 hr
= IMFVideoPresenter_ProcessMessage(stream
->parent
->presenter
, MFVP_MESSAGE_INVALIDATEMEDIATYPE
, 0);
493 static HRESULT WINAPI
video_stream_typehandler_GetCurrentMediaType(IMFMediaTypeHandler
*iface
, IMFMediaType
**type
)
495 struct video_stream
*stream
= impl_from_IMFMediaTypeHandler(iface
);
497 TRACE("%p, %p.\n", iface
, type
);
503 return MF_E_STREAMSINK_REMOVED
;
505 return IMFTransform_GetInputCurrentType(stream
->parent
->mixer
, stream
->id
, type
);
508 static HRESULT WINAPI
video_stream_typehandler_GetMajorType(IMFMediaTypeHandler
*iface
, GUID
*type
)
510 struct video_stream
*stream
= impl_from_IMFMediaTypeHandler(iface
);
512 TRACE("%p, %p.\n", iface
, type
);
515 return MF_E_STREAMSINK_REMOVED
;
520 memcpy(type
, &MFMediaType_Video
, sizeof(*type
));
524 static const IMFMediaTypeHandlerVtbl video_stream_type_handler_vtbl
=
526 video_stream_typehandler_QueryInterface
,
527 video_stream_typehandler_AddRef
,
528 video_stream_typehandler_Release
,
529 video_stream_typehandler_IsMediaTypeSupported
,
530 video_stream_typehandler_GetMediaTypeCount
,
531 video_stream_typehandler_GetMediaTypeByIndex
,
532 video_stream_typehandler_SetCurrentMediaType
,
533 video_stream_typehandler_GetCurrentMediaType
,
534 video_stream_typehandler_GetMajorType
,
537 static HRESULT WINAPI
video_stream_get_service_QueryInterface(IMFGetService
*iface
, REFIID riid
, void **obj
)
539 struct video_stream
*stream
= impl_from_stream_IMFGetService(iface
);
540 return IMFStreamSink_QueryInterface(&stream
->IMFStreamSink_iface
, riid
, obj
);
543 static ULONG WINAPI
video_stream_get_service_AddRef(IMFGetService
*iface
)
545 struct video_stream
*stream
= impl_from_stream_IMFGetService(iface
);
546 return IMFStreamSink_AddRef(&stream
->IMFStreamSink_iface
);
549 static ULONG WINAPI
video_stream_get_service_Release(IMFGetService
*iface
)
551 struct video_stream
*stream
= impl_from_stream_IMFGetService(iface
);
552 return IMFStreamSink_Release(&stream
->IMFStreamSink_iface
);
555 static HRESULT WINAPI
video_stream_get_service_GetService(IMFGetService
*iface
, REFGUID service
, REFIID riid
, void **obj
)
557 struct video_stream
*stream
= impl_from_stream_IMFGetService(iface
);
560 TRACE("%p, %s, %s, %p.\n", iface
, debugstr_guid(service
), debugstr_guid(riid
), obj
);
562 if (IsEqualGUID(service
, &MR_VIDEO_ACCELERATION_SERVICE
))
564 if (IsEqualIID(riid
, &IID_IMFVideoSampleAllocator
))
566 EnterCriticalSection(&stream
->cs
);
568 if (!stream
->allocator
)
570 hr
= MFCreateVideoSampleAllocator(&IID_IMFVideoSampleAllocator
, (void **)&stream
->allocator
);
572 hr
= IMFVideoSampleAllocator_SetDirectXManager(stream
->allocator
, stream
->parent
->device_manager
);
575 hr
= IMFVideoSampleAllocator_QueryInterface(stream
->allocator
, riid
, obj
);
577 LeaveCriticalSection(&stream
->cs
);
582 return E_NOINTERFACE
;
585 FIXME("Unsupported service %s.\n", debugstr_guid(service
));
590 static const IMFGetServiceVtbl video_stream_get_service_vtbl
=
592 video_stream_get_service_QueryInterface
,
593 video_stream_get_service_AddRef
,
594 video_stream_get_service_Release
,
595 video_stream_get_service_GetService
,
598 static HRESULT
video_renderer_stream_create(struct video_renderer
*renderer
, unsigned int id
,
599 struct video_stream
**ret
)
601 struct video_stream
*stream
;
604 if (!(stream
= heap_alloc_zero(sizeof(*stream
))))
605 return E_OUTOFMEMORY
;
607 stream
->IMFStreamSink_iface
.lpVtbl
= &video_stream_sink_vtbl
;
608 stream
->IMFMediaTypeHandler_iface
.lpVtbl
= &video_stream_type_handler_vtbl
;
609 stream
->IMFGetService_iface
.lpVtbl
= &video_stream_get_service_vtbl
;
610 stream
->refcount
= 1;
611 InitializeCriticalSection(&stream
->cs
);
613 if (FAILED(hr
= MFCreateEventQueue(&stream
->event_queue
)))
616 stream
->parent
= renderer
;
617 IMFMediaSink_AddRef(&stream
->parent
->IMFMediaSink_iface
);
626 IMFStreamSink_Release(&stream
->IMFStreamSink_iface
);
631 static HRESULT WINAPI
video_renderer_sink_QueryInterface(IMFMediaSink
*iface
, REFIID riid
, void **obj
)
633 struct video_renderer
*renderer
= impl_from_IMFMediaSink(iface
);
635 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(riid
), obj
);
637 if (IsEqualIID(riid
, &IID_IMFMediaSink
) ||
638 IsEqualIID(riid
, &IID_IUnknown
))
640 *obj
= &renderer
->IMFMediaSink_iface
;
642 else if (IsEqualIID(riid
, &IID_IMFMediaSinkPreroll
))
644 *obj
= &renderer
->IMFMediaSinkPreroll_iface
;
646 else if (IsEqualIID(riid
, &IID_IMFVideoRenderer
))
648 *obj
= &renderer
->IMFVideoRenderer_iface
;
650 else if (IsEqualIID(riid
, &IID_IMFMediaEventGenerator
))
652 *obj
= &renderer
->IMFMediaEventGenerator_iface
;
654 else if (IsEqualIID(riid
, &IID_IMFClockStateSink
))
656 *obj
= &renderer
->IMFClockStateSink_iface
;
658 else if (IsEqualIID(riid
, &IID_IMFGetService
))
660 *obj
= &renderer
->IMFGetService_iface
;
662 else if (IsEqualIID(riid
, &IID_IMFAttributes
))
664 *obj
= &renderer
->IMFAttributes_iface
;
666 else if (IsEqualIID(riid
, &IID_IMFQualityAdvise
))
668 *obj
= &renderer
->IMFQualityAdvise_iface
;
672 WARN("Unsupported interface %s.\n", debugstr_guid(riid
));
674 return E_NOINTERFACE
;
677 IUnknown_AddRef((IUnknown
*)*obj
);
682 static ULONG WINAPI
video_renderer_sink_AddRef(IMFMediaSink
*iface
)
684 struct video_renderer
*renderer
= impl_from_IMFMediaSink(iface
);
685 ULONG refcount
= InterlockedIncrement(&renderer
->refcount
);
686 TRACE("%p, refcount %u.\n", iface
, refcount
);
690 static ULONG WINAPI
video_renderer_sink_Release(IMFMediaSink
*iface
)
692 struct video_renderer
*renderer
= impl_from_IMFMediaSink(iface
);
693 ULONG refcount
= InterlockedDecrement(&renderer
->refcount
);
695 TRACE("%p, refcount %u.\n", iface
, refcount
);
699 if (renderer
->event_queue
)
700 IMFMediaEventQueue_Release(renderer
->event_queue
);
702 IMFTransform_Release(renderer
->mixer
);
703 if (renderer
->presenter
)
704 IMFVideoPresenter_Release(renderer
->presenter
);
705 if (renderer
->device_manager
)
706 IUnknown_Release(renderer
->device_manager
);
708 IMFPresentationClock_Release(renderer
->clock
);
709 if (renderer
->attributes
)
710 IMFAttributes_Release(renderer
->attributes
);
711 DeleteCriticalSection(&renderer
->cs
);
718 static HRESULT WINAPI
video_renderer_sink_GetCharacteristics(IMFMediaSink
*iface
, DWORD
*flags
)
720 struct video_renderer
*renderer
= impl_from_IMFMediaSink(iface
);
722 TRACE("%p, %p.\n", iface
, flags
);
724 if (renderer
->flags
& EVR_SHUT_DOWN
)
725 return MF_E_SHUTDOWN
;
727 *flags
= MEDIASINK_CLOCK_REQUIRED
| MEDIASINK_CAN_PREROLL
;
732 static HRESULT
video_renderer_add_stream(struct video_renderer
*renderer
, unsigned int id
,
733 IMFStreamSink
**stream_sink
)
735 struct video_stream
*stream
;
738 if (!mf_array_reserve((void **)&renderer
->streams
, &renderer
->stream_size
, renderer
->stream_count
+ 1,
739 sizeof(*renderer
->streams
)))
741 return E_OUTOFMEMORY
;
744 if (SUCCEEDED(hr
= video_renderer_stream_create(renderer
, id
, &stream
)))
748 *stream_sink
= &stream
->IMFStreamSink_iface
;
749 IMFStreamSink_AddRef(*stream_sink
);
751 renderer
->streams
[renderer
->stream_count
++] = stream
;
757 static HRESULT WINAPI
video_renderer_sink_AddStreamSink(IMFMediaSink
*iface
, DWORD id
,
758 IMFMediaType
*media_type
, IMFStreamSink
**stream_sink
)
760 struct video_renderer
*renderer
= impl_from_IMFMediaSink(iface
);
763 TRACE("%p, %#x, %p, %p.\n", iface
, id
, media_type
, stream_sink
);
765 /* Rely on mixer for stream id validation. */
767 EnterCriticalSection(&renderer
->cs
);
768 if (renderer
->flags
& EVR_SHUT_DOWN
)
770 else if (SUCCEEDED(hr
= IMFTransform_AddInputStreams(renderer
->mixer
, 1, &id
)))
772 if (FAILED(hr
= video_renderer_add_stream(renderer
, id
, stream_sink
)))
773 IMFTransform_DeleteInputStream(renderer
->mixer
, id
);
776 LeaveCriticalSection(&renderer
->cs
);
781 static HRESULT WINAPI
video_renderer_sink_RemoveStreamSink(IMFMediaSink
*iface
, DWORD id
)
783 struct video_renderer
*renderer
= impl_from_IMFMediaSink(iface
);
787 TRACE("%p, %#x.\n", iface
, id
);
789 /* Rely on mixer for stream id validation. */
791 EnterCriticalSection(&renderer
->cs
);
792 if (renderer
->flags
& EVR_SHUT_DOWN
)
794 else if (SUCCEEDED(hr
= IMFTransform_DeleteInputStream(renderer
->mixer
, id
)))
796 for (i
= 0; i
< renderer
->stream_count
; ++i
)
798 if (renderer
->streams
[i
]->id
== id
)
800 IMFStreamSink_Release(&renderer
->streams
[i
]->IMFStreamSink_iface
);
801 renderer
->streams
[i
] = NULL
;
802 if (i
< renderer
->stream_count
- 1)
804 memmove(&renderer
->streams
[i
], &renderer
->streams
[i
+1],
805 (renderer
->stream_count
- i
- 1) * sizeof(*renderer
->streams
));
807 renderer
->stream_count
--;
812 LeaveCriticalSection(&renderer
->cs
);
817 static HRESULT WINAPI
video_renderer_sink_GetStreamSinkCount(IMFMediaSink
*iface
, DWORD
*count
)
819 struct video_renderer
*renderer
= impl_from_IMFMediaSink(iface
);
822 TRACE("%p, %p.\n", iface
, count
);
827 EnterCriticalSection(&renderer
->cs
);
828 if (renderer
->flags
& EVR_SHUT_DOWN
)
833 *count
= renderer
->stream_count
;
834 LeaveCriticalSection(&renderer
->cs
);
839 static HRESULT WINAPI
video_renderer_sink_GetStreamSinkByIndex(IMFMediaSink
*iface
, DWORD index
,
840 IMFStreamSink
**stream
)
842 struct video_renderer
*renderer
= impl_from_IMFMediaSink(iface
);
845 TRACE("%p, %u, %p.\n", iface
, index
, stream
);
847 EnterCriticalSection(&renderer
->cs
);
848 if (renderer
->flags
& EVR_SHUT_DOWN
)
852 else if (index
>= renderer
->stream_count
)
856 *stream
= &renderer
->streams
[index
]->IMFStreamSink_iface
;
857 IMFStreamSink_AddRef(*stream
);
859 LeaveCriticalSection(&renderer
->cs
);
864 static HRESULT WINAPI
video_renderer_sink_GetStreamSinkById(IMFMediaSink
*iface
, DWORD id
,
865 IMFStreamSink
**stream
)
867 struct video_renderer
*renderer
= impl_from_IMFMediaSink(iface
);
871 TRACE("%p, %#x, %p.\n", iface
, id
, stream
);
873 EnterCriticalSection(&renderer
->cs
);
874 if (renderer
->flags
& EVR_SHUT_DOWN
)
880 for (i
= 0; i
< renderer
->stream_count
; ++i
)
882 if (renderer
->streams
[i
]->id
== id
)
886 if (i
== renderer
->stream_count
)
887 hr
= MF_E_INVALIDSTREAMNUMBER
;
890 *stream
= &renderer
->streams
[i
]->IMFStreamSink_iface
;
891 IMFStreamSink_AddRef(*stream
);
894 LeaveCriticalSection(&renderer
->cs
);
899 static void video_renderer_set_presentation_clock(struct video_renderer
*renderer
, IMFPresentationClock
*clock
)
903 IMFPresentationClock_RemoveClockStateSink(renderer
->clock
, &renderer
->IMFClockStateSink_iface
);
904 IMFPresentationClock_Release(renderer
->clock
);
906 renderer
->clock
= clock
;
909 IMFPresentationClock_AddRef(renderer
->clock
);
910 IMFPresentationClock_AddClockStateSink(renderer
->clock
, &renderer
->IMFClockStateSink_iface
);
914 static HRESULT WINAPI
video_renderer_sink_SetPresentationClock(IMFMediaSink
*iface
, IMFPresentationClock
*clock
)
916 struct video_renderer
*renderer
= impl_from_IMFMediaSink(iface
);
919 TRACE("%p, %p.\n", iface
, clock
);
921 EnterCriticalSection(&renderer
->cs
);
923 if (renderer
->flags
& EVR_SHUT_DOWN
)
926 video_renderer_set_presentation_clock(renderer
, clock
);
928 LeaveCriticalSection(&renderer
->cs
);
933 static HRESULT WINAPI
video_renderer_sink_GetPresentationClock(IMFMediaSink
*iface
, IMFPresentationClock
**clock
)
935 struct video_renderer
*renderer
= impl_from_IMFMediaSink(iface
);
938 TRACE("%p, %p.\n", iface
, clock
);
943 EnterCriticalSection(&renderer
->cs
);
945 if (renderer
->flags
& EVR_SHUT_DOWN
)
947 else if (renderer
->clock
)
949 *clock
= renderer
->clock
;
950 IMFPresentationClock_AddRef(*clock
);
955 LeaveCriticalSection(&renderer
->cs
);
960 static HRESULT WINAPI
video_renderer_sink_Shutdown(IMFMediaSink
*iface
)
962 struct video_renderer
*renderer
= impl_from_IMFMediaSink(iface
);
965 TRACE("%p.\n", iface
);
967 if (renderer
->flags
& EVR_SHUT_DOWN
)
968 return MF_E_SHUTDOWN
;
970 EnterCriticalSection(&renderer
->cs
);
971 renderer
->flags
|= EVR_SHUT_DOWN
;
972 /* Detach streams from the sink. */
973 for (i
= 0; i
< renderer
->stream_count
; ++i
)
975 struct video_stream
*stream
= renderer
->streams
[i
];
977 EnterCriticalSection(&stream
->cs
);
978 stream
->parent
= NULL
;
979 LeaveCriticalSection(&stream
->cs
);
981 IMFMediaEventQueue_Shutdown(stream
->event_queue
);
982 IMFStreamSink_Release(&stream
->IMFStreamSink_iface
);
983 IMFMediaSink_Release(iface
);
984 renderer
->streams
[i
] = NULL
;
986 heap_free(renderer
->streams
);
987 renderer
->stream_count
= 0;
988 renderer
->stream_size
= 0;
989 IMFMediaEventQueue_Shutdown(renderer
->event_queue
);
990 video_renderer_set_presentation_clock(renderer
, NULL
);
991 video_renderer_release_services(renderer
);
992 LeaveCriticalSection(&renderer
->cs
);
997 static const IMFMediaSinkVtbl video_renderer_sink_vtbl
=
999 video_renderer_sink_QueryInterface
,
1000 video_renderer_sink_AddRef
,
1001 video_renderer_sink_Release
,
1002 video_renderer_sink_GetCharacteristics
,
1003 video_renderer_sink_AddStreamSink
,
1004 video_renderer_sink_RemoveStreamSink
,
1005 video_renderer_sink_GetStreamSinkCount
,
1006 video_renderer_sink_GetStreamSinkByIndex
,
1007 video_renderer_sink_GetStreamSinkById
,
1008 video_renderer_sink_SetPresentationClock
,
1009 video_renderer_sink_GetPresentationClock
,
1010 video_renderer_sink_Shutdown
,
1013 static HRESULT WINAPI
video_renderer_preroll_QueryInterface(IMFMediaSinkPreroll
*iface
, REFIID riid
, void **obj
)
1015 struct video_renderer
*renderer
= impl_from_IMFMediaSinkPreroll(iface
);
1016 return IMFMediaSink_QueryInterface(&renderer
->IMFMediaSink_iface
, riid
, obj
);
1019 static ULONG WINAPI
video_renderer_preroll_AddRef(IMFMediaSinkPreroll
*iface
)
1021 struct video_renderer
*renderer
= impl_from_IMFMediaSinkPreroll(iface
);
1022 return IMFMediaSink_AddRef(&renderer
->IMFMediaSink_iface
);
1025 static ULONG WINAPI
video_renderer_preroll_Release(IMFMediaSinkPreroll
*iface
)
1027 struct video_renderer
*renderer
= impl_from_IMFMediaSinkPreroll(iface
);
1028 return IMFMediaSink_Release(&renderer
->IMFMediaSink_iface
);
1031 static HRESULT WINAPI
video_renderer_preroll_NotifyPreroll(IMFMediaSinkPreroll
*iface
, MFTIME start_time
)
1033 struct video_renderer
*renderer
= impl_from_IMFMediaSinkPreroll(iface
);
1037 TRACE("%p, %s.\n", iface
, debugstr_time(start_time
));
1039 EnterCriticalSection(&renderer
->cs
);
1040 if (renderer
->flags
& EVR_SHUT_DOWN
)
1044 for (i
= 0; i
< renderer
->stream_count
; ++i
)
1046 struct video_stream
*stream
= renderer
->streams
[i
];
1048 EnterCriticalSection(&stream
->cs
);
1049 if (!(stream
->flags
& (EVR_STREAM_PREROLLING
| EVR_STREAM_PREROLLED
)))
1051 IMFMediaEventQueue_QueueEventParamVar(stream
->event_queue
, MEStreamSinkRequestSample
,
1052 &GUID_NULL
, S_OK
, NULL
);
1053 stream
->flags
|= EVR_STREAM_PREROLLING
;
1055 LeaveCriticalSection(&stream
->cs
);
1058 LeaveCriticalSection(&renderer
->cs
);
1063 static const IMFMediaSinkPrerollVtbl video_renderer_preroll_vtbl
=
1065 video_renderer_preroll_QueryInterface
,
1066 video_renderer_preroll_AddRef
,
1067 video_renderer_preroll_Release
,
1068 video_renderer_preroll_NotifyPreroll
,
1071 static HRESULT WINAPI
video_renderer_QueryInterface(IMFVideoRenderer
*iface
, REFIID riid
, void **obj
)
1073 struct video_renderer
*renderer
= impl_from_IMFVideoRenderer(iface
);
1074 return IMFMediaSink_QueryInterface(&renderer
->IMFMediaSink_iface
, riid
, obj
);
1077 static ULONG WINAPI
video_renderer_AddRef(IMFVideoRenderer
*iface
)
1079 struct video_renderer
*renderer
= impl_from_IMFVideoRenderer(iface
);
1080 return IMFMediaSink_AddRef(&renderer
->IMFMediaSink_iface
);
1083 static ULONG WINAPI
video_renderer_Release(IMFVideoRenderer
*iface
)
1085 struct video_renderer
*renderer
= impl_from_IMFVideoRenderer(iface
);
1086 return IMFMediaSink_Release(&renderer
->IMFMediaSink_iface
);
1089 static HRESULT
video_renderer_create_mixer(IMFAttributes
*attributes
, IMFTransform
**out
)
1091 unsigned int flags
= 0;
1092 IMFActivate
*activate
;
1096 if (attributes
&& SUCCEEDED(hr
= IMFAttributes_GetUnknown(attributes
, &MF_ACTIVATE_CUSTOM_VIDEO_MIXER_ACTIVATE
,
1097 &IID_IMFActivate
, (void **)&activate
)))
1099 IMFAttributes_GetUINT32(attributes
, &MF_ACTIVATE_CUSTOM_VIDEO_MIXER_FLAGS
, &flags
);
1100 hr
= IMFActivate_ActivateObject(activate
, &IID_IMFTransform
, (void **)out
);
1101 IMFActivate_Release(activate
);
1102 if (SUCCEEDED(hr
) || !(flags
& MF_ACTIVATE_CUSTOM_MIXER_ALLOWFAIL
))
1106 if (!attributes
|| FAILED(IMFAttributes_GetGUID(attributes
, &MF_ACTIVATE_CUSTOM_VIDEO_MIXER_CLSID
, &clsid
)))
1107 memcpy(&clsid
, &CLSID_MFVideoMixer9
, sizeof(clsid
));
1109 return CoCreateInstance(&clsid
, NULL
, CLSCTX_INPROC_SERVER
, &IID_IMFTransform
, (void **)out
);
1112 static HRESULT
video_renderer_create_presenter(struct video_renderer
*renderer
, IMFAttributes
*attributes
,
1113 IMFVideoPresenter
**out
)
1115 unsigned int flags
= 0;
1116 IMFActivate
*activate
;
1121 if (attributes
&& SUCCEEDED(IMFAttributes_GetUINT64(attributes
, &MF_ACTIVATE_VIDEO_WINDOW
, &value
)))
1122 renderer
->window
= UlongToHandle(value
);
1124 if (attributes
&& SUCCEEDED(IMFAttributes_GetUnknown(attributes
, &MF_ACTIVATE_CUSTOM_VIDEO_PRESENTER_ACTIVATE
,
1125 &IID_IMFActivate
, (void **)&activate
)))
1127 IMFAttributes_GetUINT32(attributes
, &MF_ACTIVATE_CUSTOM_VIDEO_PRESENTER_FLAGS
, &flags
);
1128 hr
= IMFActivate_ActivateObject(activate
, &IID_IMFVideoPresenter
, (void **)out
);
1129 IMFActivate_Release(activate
);
1130 if (SUCCEEDED(hr
) || !(flags
& MF_ACTIVATE_CUSTOM_PRESENTER_ALLOWFAIL
))
1134 if (!attributes
|| FAILED(IMFAttributes_GetGUID(attributes
, &MF_ACTIVATE_CUSTOM_VIDEO_PRESENTER_CLSID
, &clsid
)))
1135 memcpy(&clsid
, &CLSID_MFVideoPresenter9
, sizeof(clsid
));
1137 return CoCreateInstance(&clsid
, NULL
, CLSCTX_INPROC_SERVER
, &IID_IMFVideoPresenter
, (void **)out
);
1140 static HRESULT
video_renderer_configure_mixer(struct video_renderer
*renderer
)
1142 IMFTopologyServiceLookupClient
*lookup_client
;
1143 IMFAttributes
*attributes
;
1146 if (SUCCEEDED(hr
= IMFTransform_QueryInterface(renderer
->mixer
, &IID_IMFTopologyServiceLookupClient
,
1147 (void **)&lookup_client
)))
1149 renderer
->flags
|= EVR_INIT_SERVICES
;
1150 if (SUCCEEDED(hr
= IMFTopologyServiceLookupClient_InitServicePointers(lookup_client
,
1151 &renderer
->IMFTopologyServiceLookup_iface
)))
1153 renderer
->flags
|= EVR_MIXER_INITED_SERVICES
;
1155 renderer
->flags
&= ~EVR_INIT_SERVICES
;
1156 IMFTopologyServiceLookupClient_Release(lookup_client
);
1161 unsigned int input_count
, output_count
;
1162 unsigned int *ids
, *oids
;
1165 /* Create stream sinks for inputs that mixer already has by default. */
1166 if (SUCCEEDED(IMFTransform_GetStreamCount(renderer
->mixer
, &input_count
, &output_count
)))
1168 ids
= heap_calloc(input_count
, sizeof(*ids
));
1169 oids
= heap_calloc(output_count
, sizeof(*oids
));
1173 if (SUCCEEDED(IMFTransform_GetStreamIDs(renderer
->mixer
, input_count
, ids
, output_count
, oids
)))
1175 for (i
= 0; i
< input_count
; ++i
)
1177 video_renderer_add_stream(renderer
, ids
[i
], NULL
);
1188 /* Set device manager that presenter should have created. */
1189 if (SUCCEEDED(IMFTransform_QueryInterface(renderer
->mixer
, &IID_IMFAttributes
, (void **)&attributes
)))
1191 IDirect3DDeviceManager9
*device_manager
;
1194 if (SUCCEEDED(IMFAttributes_GetUINT32(attributes
, &MF_SA_D3D_AWARE
, &value
)) && value
)
1196 if (SUCCEEDED(MFGetService((IUnknown
*)renderer
->presenter
, &MR_VIDEO_ACCELERATION_SERVICE
,
1197 &IID_IDirect3DDeviceManager9
, (void **)&device_manager
)))
1199 IMFTransform_ProcessMessage(renderer
->mixer
, MFT_MESSAGE_SET_D3D_MANAGER
, (ULONG_PTR
)device_manager
);
1200 IDirect3DDeviceManager9_Release(device_manager
);
1203 IMFAttributes_Release(attributes
);
1209 static HRESULT
video_renderer_configure_presenter(struct video_renderer
*renderer
)
1211 IMFTopologyServiceLookupClient
*lookup_client
;
1212 IMFVideoDisplayControl
*control
;
1215 if (SUCCEEDED(IMFVideoPresenter_QueryInterface(renderer
->presenter
, &IID_IMFVideoDisplayControl
, (void **)&control
)))
1217 IMFVideoDisplayControl_SetVideoWindow(control
, renderer
->window
);
1218 IMFVideoDisplayControl_Release(control
);
1221 if (SUCCEEDED(hr
= IMFVideoPresenter_QueryInterface(renderer
->presenter
, &IID_IMFTopologyServiceLookupClient
,
1222 (void **)&lookup_client
)))
1224 renderer
->flags
|= EVR_INIT_SERVICES
;
1225 if (SUCCEEDED(hr
= IMFTopologyServiceLookupClient_InitServicePointers(lookup_client
,
1226 &renderer
->IMFTopologyServiceLookup_iface
)))
1228 renderer
->flags
|= EVR_PRESENTER_INITED_SERVICES
;
1230 renderer
->flags
&= ~EVR_INIT_SERVICES
;
1231 IMFTopologyServiceLookupClient_Release(lookup_client
);
1234 if (FAILED(MFGetService((IUnknown
*)renderer
->presenter
, &MR_VIDEO_ACCELERATION_SERVICE
,
1235 &IID_IUnknown
, (void **)&renderer
->device_manager
)))
1237 WARN("Failed to get device manager from the presenter.\n");
1243 static HRESULT
video_renderer_initialize(struct video_renderer
*renderer
, IMFTransform
*mixer
,
1244 IMFVideoPresenter
*presenter
)
1248 if (renderer
->mixer
)
1250 IMFTransform_Release(renderer
->mixer
);
1251 renderer
->mixer
= NULL
;
1254 if (renderer
->presenter
)
1256 IMFVideoPresenter_Release(renderer
->presenter
);
1257 renderer
->presenter
= NULL
;
1260 if (renderer
->device_manager
)
1262 IUnknown_Release(renderer
->device_manager
);
1263 renderer
->device_manager
= NULL
;
1266 renderer
->mixer
= mixer
;
1267 IMFTransform_AddRef(renderer
->mixer
);
1269 renderer
->presenter
= presenter
;
1270 IMFVideoPresenter_AddRef(renderer
->presenter
);
1272 if (SUCCEEDED(hr
= video_renderer_configure_mixer(renderer
)))
1273 hr
= video_renderer_configure_presenter(renderer
);
1278 static HRESULT WINAPI
video_renderer_InitializeRenderer(IMFVideoRenderer
*iface
, IMFTransform
*mixer
,
1279 IMFVideoPresenter
*presenter
)
1281 struct video_renderer
*renderer
= impl_from_IMFVideoRenderer(iface
);
1284 TRACE("%p, %p, %p.\n", iface
, mixer
, presenter
);
1287 IMFTransform_AddRef(mixer
);
1288 else if (FAILED(hr
= video_renderer_create_mixer(NULL
, &mixer
)))
1290 WARN("Failed to create default mixer object, hr %#x.\n", hr
);
1295 IMFVideoPresenter_AddRef(presenter
);
1296 else if (FAILED(hr
= video_renderer_create_presenter(renderer
, NULL
, &presenter
)))
1298 WARN("Failed to create default presenter, hr %#x.\n", hr
);
1299 IMFTransform_Release(mixer
);
1303 EnterCriticalSection(&renderer
->cs
);
1305 if (renderer
->flags
& EVR_SHUT_DOWN
)
1309 /* FIXME: check clock state */
1310 /* FIXME: check that streams are not initialized */
1312 hr
= video_renderer_initialize(renderer
, mixer
, presenter
);
1315 LeaveCriticalSection(&renderer
->cs
);
1317 IMFTransform_Release(mixer
);
1318 IMFVideoPresenter_Release(presenter
);
1323 static const IMFVideoRendererVtbl video_renderer_vtbl
=
1325 video_renderer_QueryInterface
,
1326 video_renderer_AddRef
,
1327 video_renderer_Release
,
1328 video_renderer_InitializeRenderer
,
1331 static HRESULT WINAPI
video_renderer_events_QueryInterface(IMFMediaEventGenerator
*iface
, REFIID riid
, void **obj
)
1333 struct video_renderer
*renderer
= impl_from_IMFMediaEventGenerator(iface
);
1334 return IMFMediaSink_QueryInterface(&renderer
->IMFMediaSink_iface
, riid
, obj
);
1337 static ULONG WINAPI
video_renderer_events_AddRef(IMFMediaEventGenerator
*iface
)
1339 struct video_renderer
*renderer
= impl_from_IMFMediaEventGenerator(iface
);
1340 return IMFMediaSink_AddRef(&renderer
->IMFMediaSink_iface
);
1343 static ULONG WINAPI
video_renderer_events_Release(IMFMediaEventGenerator
*iface
)
1345 struct video_renderer
*renderer
= impl_from_IMFMediaEventGenerator(iface
);
1346 return IMFMediaSink_Release(&renderer
->IMFMediaSink_iface
);
1349 static HRESULT WINAPI
video_renderer_events_GetEvent(IMFMediaEventGenerator
*iface
, DWORD flags
, IMFMediaEvent
**event
)
1351 struct video_renderer
*renderer
= impl_from_IMFMediaEventGenerator(iface
);
1353 TRACE("%p, %#x, %p.\n", iface
, flags
, event
);
1355 return IMFMediaEventQueue_GetEvent(renderer
->event_queue
, flags
, event
);
1358 static HRESULT WINAPI
video_renderer_events_BeginGetEvent(IMFMediaEventGenerator
*iface
, IMFAsyncCallback
*callback
,
1361 struct video_renderer
*renderer
= impl_from_IMFMediaEventGenerator(iface
);
1363 TRACE("%p, %p, %p.\n", iface
, callback
, state
);
1365 return IMFMediaEventQueue_BeginGetEvent(renderer
->event_queue
, callback
, state
);
1368 static HRESULT WINAPI
video_renderer_events_EndGetEvent(IMFMediaEventGenerator
*iface
, IMFAsyncResult
*result
,
1369 IMFMediaEvent
**event
)
1371 struct video_renderer
*renderer
= impl_from_IMFMediaEventGenerator(iface
);
1373 TRACE("%p, %p, %p.\n", iface
, result
, event
);
1375 return IMFMediaEventQueue_EndGetEvent(renderer
->event_queue
, result
, event
);
1378 static HRESULT WINAPI
video_renderer_events_QueueEvent(IMFMediaEventGenerator
*iface
, MediaEventType event_type
,
1379 REFGUID ext_type
, HRESULT hr
, const PROPVARIANT
*value
)
1381 struct video_renderer
*renderer
= impl_from_IMFMediaEventGenerator(iface
);
1383 TRACE("%p, %u, %s, %#x, %p.\n", iface
, event_type
, debugstr_guid(ext_type
), hr
, value
);
1385 return IMFMediaEventQueue_QueueEventParamVar(renderer
->event_queue
, event_type
, ext_type
, hr
, value
);
1388 static const IMFMediaEventGeneratorVtbl video_renderer_events_vtbl
=
1390 video_renderer_events_QueryInterface
,
1391 video_renderer_events_AddRef
,
1392 video_renderer_events_Release
,
1393 video_renderer_events_GetEvent
,
1394 video_renderer_events_BeginGetEvent
,
1395 video_renderer_events_EndGetEvent
,
1396 video_renderer_events_QueueEvent
,
1399 static HRESULT WINAPI
video_renderer_clock_sink_QueryInterface(IMFClockStateSink
*iface
, REFIID riid
, void **obj
)
1401 struct video_renderer
*renderer
= impl_from_IMFClockStateSink(iface
);
1402 return IMFMediaSink_QueryInterface(&renderer
->IMFMediaSink_iface
, riid
, obj
);
1405 static ULONG WINAPI
video_renderer_clock_sink_AddRef(IMFClockStateSink
*iface
)
1407 struct video_renderer
*renderer
= impl_from_IMFClockStateSink(iface
);
1408 return IMFMediaSink_AddRef(&renderer
->IMFMediaSink_iface
);
1411 static ULONG WINAPI
video_renderer_clock_sink_Release(IMFClockStateSink
*iface
)
1413 struct video_renderer
*renderer
= impl_from_IMFClockStateSink(iface
);
1414 return IMFMediaSink_Release(&renderer
->IMFMediaSink_iface
);
1417 static HRESULT WINAPI
video_renderer_clock_sink_OnClockStart(IMFClockStateSink
*iface
, MFTIME systime
, LONGLONG offset
)
1419 struct video_renderer
*renderer
= impl_from_IMFClockStateSink(iface
);
1422 TRACE("%p, %s, %s.\n", iface
, debugstr_time(systime
), debugstr_time(offset
));
1424 EnterCriticalSection(&renderer
->cs
);
1426 if (renderer
->state
== EVR_STATE_STOPPED
)
1428 IMFTransform_ProcessMessage(renderer
->mixer
, MFT_MESSAGE_NOTIFY_BEGIN_STREAMING
, 0);
1429 IMFVideoPresenter_ProcessMessage(renderer
->presenter
, MFVP_MESSAGE_BEGINSTREAMING
, 0);
1431 for (i
= 0; i
< renderer
->stream_count
; ++i
)
1433 struct video_stream
*stream
= renderer
->streams
[i
];
1435 IMFMediaEventQueue_QueueEventParamVar(stream
->event_queue
, MEStreamSinkStarted
, &GUID_NULL
, S_OK
, NULL
);
1437 EnterCriticalSection(&stream
->cs
);
1438 if (!(stream
->flags
& EVR_STREAM_PREROLLED
))
1439 IMFMediaEventQueue_QueueEventParamVar(stream
->event_queue
, MEStreamSinkRequestSample
,
1440 &GUID_NULL
, S_OK
, NULL
);
1441 stream
->flags
|= EVR_STREAM_PREROLLED
;
1442 LeaveCriticalSection(&stream
->cs
);
1446 renderer
->state
= EVR_STATE_RUNNING
;
1448 IMFVideoPresenter_OnClockStart(renderer
->presenter
, systime
, offset
);
1450 LeaveCriticalSection(&renderer
->cs
);
1455 static HRESULT WINAPI
video_renderer_clock_sink_OnClockStop(IMFClockStateSink
*iface
, MFTIME systime
)
1457 struct video_renderer
*renderer
= impl_from_IMFClockStateSink(iface
);
1460 TRACE("%p, %s.\n", iface
, debugstr_time(systime
));
1462 EnterCriticalSection(&renderer
->cs
);
1464 IMFVideoPresenter_OnClockStop(renderer
->presenter
, systime
);
1466 IMFTransform_ProcessMessage(renderer
->mixer
, MFT_MESSAGE_COMMAND_FLUSH
, 0);
1467 IMFVideoPresenter_ProcessMessage(renderer
->presenter
, MFVP_MESSAGE_FLUSH
, 0);
1469 if (renderer
->state
== EVR_STATE_RUNNING
||
1470 renderer
->state
== EVR_STATE_PAUSED
)
1472 IMFTransform_ProcessMessage(renderer
->mixer
, MFT_MESSAGE_NOTIFY_END_STREAMING
, 0);
1473 IMFVideoPresenter_ProcessMessage(renderer
->presenter
, MFVP_MESSAGE_ENDSTREAMING
, 0);
1475 for (i
= 0; i
< renderer
->stream_count
; ++i
)
1477 struct video_stream
*stream
= renderer
->streams
[i
];
1478 IMFMediaEventQueue_QueueEventParamVar(stream
->event_queue
, MEStreamSinkStopped
, &GUID_NULL
, S_OK
, NULL
);
1480 EnterCriticalSection(&stream
->cs
);
1481 stream
->flags
&= ~EVR_STREAM_PREROLLED
;
1482 LeaveCriticalSection(&stream
->cs
);
1484 renderer
->state
= EVR_STATE_STOPPED
;
1487 LeaveCriticalSection(&renderer
->cs
);
1492 static HRESULT WINAPI
video_renderer_clock_sink_OnClockPause(IMFClockStateSink
*iface
, MFTIME systime
)
1494 struct video_renderer
*renderer
= impl_from_IMFClockStateSink(iface
);
1497 TRACE("%p, %s.\n", iface
, debugstr_time(systime
));
1499 EnterCriticalSection(&renderer
->cs
);
1501 IMFVideoPresenter_OnClockPause(renderer
->presenter
, systime
);
1503 if (renderer
->state
== EVR_STATE_RUNNING
)
1505 for (i
= 0; i
< renderer
->stream_count
; ++i
)
1507 struct video_stream
*stream
= renderer
->streams
[i
];
1508 IMFMediaEventQueue_QueueEventParamVar(stream
->event_queue
, MEStreamSinkPaused
, &GUID_NULL
, S_OK
, NULL
);
1512 renderer
->state
= EVR_STATE_PAUSED
;
1514 LeaveCriticalSection(&renderer
->cs
);
1519 static HRESULT WINAPI
video_renderer_clock_sink_OnClockRestart(IMFClockStateSink
*iface
, MFTIME systime
)
1521 struct video_renderer
*renderer
= impl_from_IMFClockStateSink(iface
);
1524 TRACE("%p, %s.\n", iface
, debugstr_time(systime
));
1526 EnterCriticalSection(&renderer
->cs
);
1528 IMFVideoPresenter_OnClockRestart(renderer
->presenter
, systime
);
1530 for (i
= 0; i
< renderer
->stream_count
; ++i
)
1532 struct video_stream
*stream
= renderer
->streams
[i
];
1533 IMFMediaEventQueue_QueueEventParamVar(stream
->event_queue
, MEStreamSinkStarted
, &GUID_NULL
, S_OK
, NULL
);
1535 renderer
->state
= EVR_STATE_RUNNING
;
1537 LeaveCriticalSection(&renderer
->cs
);
1542 static HRESULT WINAPI
video_renderer_clock_sink_OnClockSetRate(IMFClockStateSink
*iface
, MFTIME systime
, float rate
)
1544 struct video_renderer
*renderer
= impl_from_IMFClockStateSink(iface
);
1545 IMFClockStateSink
*sink
;
1547 TRACE("%p, %s, %f.\n", iface
, debugstr_time(systime
), rate
);
1549 EnterCriticalSection(&renderer
->cs
);
1551 IMFVideoPresenter_OnClockSetRate(renderer
->presenter
, systime
, rate
);
1552 if (SUCCEEDED(IMFTransform_QueryInterface(renderer
->mixer
, &IID_IMFClockStateSink
, (void **)&sink
)))
1554 IMFClockStateSink_OnClockSetRate(sink
, systime
, rate
);
1555 IMFClockStateSink_Release(sink
);
1558 LeaveCriticalSection(&renderer
->cs
);
1563 static const IMFClockStateSinkVtbl video_renderer_clock_sink_vtbl
=
1565 video_renderer_clock_sink_QueryInterface
,
1566 video_renderer_clock_sink_AddRef
,
1567 video_renderer_clock_sink_Release
,
1568 video_renderer_clock_sink_OnClockStart
,
1569 video_renderer_clock_sink_OnClockStop
,
1570 video_renderer_clock_sink_OnClockPause
,
1571 video_renderer_clock_sink_OnClockRestart
,
1572 video_renderer_clock_sink_OnClockSetRate
,
1575 static HRESULT WINAPI
video_renderer_get_service_QueryInterface(IMFGetService
*iface
, REFIID riid
, void **obj
)
1577 struct video_renderer
*renderer
= impl_from_IMFGetService(iface
);
1578 return IMFMediaSink_QueryInterface(&renderer
->IMFMediaSink_iface
, riid
, obj
);
1581 static ULONG WINAPI
video_renderer_get_service_AddRef(IMFGetService
*iface
)
1583 struct video_renderer
*renderer
= impl_from_IMFGetService(iface
);
1584 return IMFMediaSink_AddRef(&renderer
->IMFMediaSink_iface
);
1587 static ULONG WINAPI
video_renderer_get_service_Release(IMFGetService
*iface
)
1589 struct video_renderer
*renderer
= impl_from_IMFGetService(iface
);
1590 return IMFMediaSink_Release(&renderer
->IMFMediaSink_iface
);
1593 static HRESULT WINAPI
video_renderer_get_service_GetService(IMFGetService
*iface
, REFGUID service
, REFIID riid
, void **obj
)
1595 struct video_renderer
*renderer
= impl_from_IMFGetService(iface
);
1596 HRESULT hr
= E_NOINTERFACE
;
1597 IMFGetService
*gs
= NULL
;
1599 TRACE("%p, %s, %s, %p.\n", iface
, debugstr_guid(service
), debugstr_guid(riid
), obj
);
1601 if (IsEqualGUID(service
, &MR_VIDEO_MIXER_SERVICE
))
1603 hr
= IMFTransform_QueryInterface(renderer
->mixer
, &IID_IMFGetService
, (void **)&gs
);
1605 else if (IsEqualGUID(service
, &MR_VIDEO_RENDER_SERVICE
))
1607 hr
= IMFVideoPresenter_QueryInterface(renderer
->presenter
, &IID_IMFGetService
, (void **)&gs
);
1611 FIXME("Unsupported service %s.\n", debugstr_guid(service
));
1616 hr
= IMFGetService_GetService(gs
, service
, riid
, obj
);
1617 IMFGetService_Release(gs
);
1623 static const IMFGetServiceVtbl video_renderer_get_service_vtbl
=
1625 video_renderer_get_service_QueryInterface
,
1626 video_renderer_get_service_AddRef
,
1627 video_renderer_get_service_Release
,
1628 video_renderer_get_service_GetService
,
1631 static HRESULT WINAPI
video_renderer_service_lookup_QueryInterface(IMFTopologyServiceLookup
*iface
, REFIID riid
, void **obj
)
1633 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(riid
), obj
);
1635 if (IsEqualIID(riid
, &IID_IMFTopologyServiceLookup
) ||
1636 IsEqualIID(riid
, &IID_IUnknown
))
1639 IMFTopologyServiceLookup_AddRef(iface
);
1643 WARN("Unsupported interface %s.\n", debugstr_guid(riid
));
1645 return E_NOINTERFACE
;
1648 static ULONG WINAPI
video_renderer_service_lookup_AddRef(IMFTopologyServiceLookup
*iface
)
1650 struct video_renderer
*renderer
= impl_from_IMFTopologyServiceLookup(iface
);
1651 return IMFMediaSink_AddRef(&renderer
->IMFMediaSink_iface
);
1654 static ULONG WINAPI
video_renderer_service_lookup_Release(IMFTopologyServiceLookup
*iface
)
1656 struct video_renderer
*renderer
= impl_from_IMFTopologyServiceLookup(iface
);
1657 return IMFMediaSink_Release(&renderer
->IMFMediaSink_iface
);
1660 static HRESULT WINAPI
video_renderer_service_lookup_LookupService(IMFTopologyServiceLookup
*iface
,
1661 MF_SERVICE_LOOKUP_TYPE lookup_type
, DWORD index
, REFGUID service
, REFIID riid
,
1662 void **objects
, DWORD
*num_objects
)
1664 struct video_renderer
*renderer
= impl_from_IMFTopologyServiceLookup(iface
);
1667 TRACE("%p, %u, %u, %s, %s, %p, %p.\n", iface
, lookup_type
, index
, debugstr_guid(service
), debugstr_guid(riid
),
1668 objects
, num_objects
);
1670 EnterCriticalSection(&renderer
->cs
);
1672 if (!(renderer
->flags
& EVR_INIT_SERVICES
))
1673 hr
= MF_E_NOTACCEPTING
;
1674 else if (IsEqualGUID(service
, &MR_VIDEO_RENDER_SERVICE
))
1676 if (IsEqualIID(riid
, &IID_IMediaEventSink
))
1678 *objects
= &renderer
->IMediaEventSink_iface
;
1679 IUnknown_AddRef((IUnknown
*)*objects
);
1683 FIXME("Unsupported interface %s for render service.\n", debugstr_guid(riid
));
1687 else if (IsEqualGUID(service
, &MR_VIDEO_MIXER_SERVICE
))
1689 if (IsEqualIID(riid
, &IID_IMFTransform
))
1691 *objects
= renderer
->mixer
;
1692 IUnknown_AddRef((IUnknown
*)*objects
);
1696 FIXME("Unsupported interface %s for mixer service.\n", debugstr_guid(riid
));
1702 WARN("Unsupported service %s.\n", debugstr_guid(service
));
1703 hr
= MF_E_UNSUPPORTED_SERVICE
;
1706 LeaveCriticalSection(&renderer
->cs
);
1711 static const IMFTopologyServiceLookupVtbl video_renderer_service_lookup_vtbl
=
1713 video_renderer_service_lookup_QueryInterface
,
1714 video_renderer_service_lookup_AddRef
,
1715 video_renderer_service_lookup_Release
,
1716 video_renderer_service_lookup_LookupService
,
1719 static HRESULT WINAPI
video_renderer_event_sink_QueryInterface(IMediaEventSink
*iface
, REFIID riid
, void **obj
)
1721 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(riid
), obj
);
1723 if (IsEqualIID(riid
, &IID_IMediaEventSink
) ||
1724 IsEqualIID(riid
, &IID_IUnknown
))
1727 IMediaEventSink_AddRef(iface
);
1731 WARN("Unsupported interface %s.\n", debugstr_guid(riid
));
1733 return E_NOINTERFACE
;
1736 static ULONG WINAPI
video_renderer_event_sink_AddRef(IMediaEventSink
*iface
)
1738 struct video_renderer
*renderer
= impl_from_IMediaEventSink(iface
);
1739 return IMFMediaSink_AddRef(&renderer
->IMFMediaSink_iface
);
1742 static ULONG WINAPI
video_renderer_event_sink_Release(IMediaEventSink
*iface
)
1744 struct video_renderer
*renderer
= impl_from_IMediaEventSink(iface
);
1745 return IMFMediaSink_Release(&renderer
->IMFMediaSink_iface
);
1748 static HRESULT WINAPI
video_renderer_event_sink_Notify(IMediaEventSink
*iface
, LONG event
, LONG_PTR param1
, LONG_PTR param2
)
1750 struct video_renderer
*renderer
= impl_from_IMediaEventSink(iface
);
1754 TRACE("%p, %d, %ld, %ld.\n", iface
, event
, param1
, param2
);
1756 EnterCriticalSection(&renderer
->cs
);
1758 if (event
== EC_SAMPLE_NEEDED
)
1761 if (idx
>= renderer
->stream_count
)
1762 hr
= MF_E_INVALIDSTREAMNUMBER
;
1765 hr
= IMFMediaEventQueue_QueueEventParamVar(renderer
->streams
[idx
]->event_queue
,
1766 MEStreamSinkRequestSample
, &GUID_NULL
, S_OK
, NULL
);
1769 else if (event
>= EC_USER
)
1775 hr
= IMFMediaEventQueue_QueueEventParamVar(renderer
->event_queue
, MERendererEvent
,
1776 &GUID_NULL
, S_OK
, &code
);
1780 WARN("Unhandled event %d.\n", event
);
1781 hr
= MF_E_UNEXPECTED
;
1784 LeaveCriticalSection(&renderer
->cs
);
1789 static const IMediaEventSinkVtbl media_event_sink_vtbl
=
1791 video_renderer_event_sink_QueryInterface
,
1792 video_renderer_event_sink_AddRef
,
1793 video_renderer_event_sink_Release
,
1794 video_renderer_event_sink_Notify
,
1797 static HRESULT WINAPI
video_renderer_attributes_QueryInterface(IMFAttributes
*iface
, REFIID riid
, void **obj
)
1799 struct video_renderer
*renderer
= impl_from_IMFAttributes(iface
);
1800 return IMFMediaSink_QueryInterface(&renderer
->IMFMediaSink_iface
, riid
, obj
);
1803 static ULONG WINAPI
video_renderer_attributes_AddRef(IMFAttributes
*iface
)
1805 struct video_renderer
*renderer
= impl_from_IMFAttributes(iface
);
1806 return IMFMediaSink_AddRef(&renderer
->IMFMediaSink_iface
);
1809 static ULONG WINAPI
video_renderer_attributes_Release(IMFAttributes
*iface
)
1811 struct video_renderer
*renderer
= impl_from_IMFAttributes(iface
);
1812 return IMFMediaSink_Release(&renderer
->IMFMediaSink_iface
);
1815 static HRESULT WINAPI
video_renderer_attributes_GetItem(IMFAttributes
*iface
, REFGUID key
, PROPVARIANT
*value
)
1817 struct video_renderer
*renderer
= impl_from_IMFAttributes(iface
);
1819 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(key
), value
);
1821 return IMFAttributes_GetItem(renderer
->attributes
, key
, value
);
1824 static HRESULT WINAPI
video_renderer_attributes_GetItemType(IMFAttributes
*iface
, REFGUID key
, MF_ATTRIBUTE_TYPE
*type
)
1826 struct video_renderer
*renderer
= impl_from_IMFAttributes(iface
);
1828 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(key
), type
);
1830 return IMFAttributes_GetItemType(renderer
->attributes
, key
, type
);
1833 static HRESULT WINAPI
video_renderer_attributes_CompareItem(IMFAttributes
*iface
, REFGUID key
, REFPROPVARIANT value
,
1836 struct video_renderer
*renderer
= impl_from_IMFAttributes(iface
);
1838 TRACE("%p, %s, %p, %p.\n", iface
, debugstr_guid(key
), value
, result
);
1840 return IMFAttributes_CompareItem(renderer
->attributes
, key
, value
, result
);
1843 static HRESULT WINAPI
video_renderer_attributes_Compare(IMFAttributes
*iface
, IMFAttributes
*theirs
,
1844 MF_ATTRIBUTES_MATCH_TYPE type
, BOOL
*result
)
1846 struct video_renderer
*renderer
= impl_from_IMFAttributes(iface
);
1848 TRACE("%p, %p, %d, %p.\n", iface
, theirs
, type
, result
);
1850 return IMFAttributes_Compare(renderer
->attributes
, theirs
, type
, result
);
1853 static HRESULT WINAPI
video_renderer_attributes_GetUINT32(IMFAttributes
*iface
, REFGUID key
, UINT32
*value
)
1855 struct video_renderer
*renderer
= impl_from_IMFAttributes(iface
);
1857 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(key
), value
);
1859 return IMFAttributes_GetUINT32(renderer
->attributes
, key
, value
);
1862 static HRESULT WINAPI
video_renderer_attributes_GetUINT64(IMFAttributes
*iface
, REFGUID key
, UINT64
*value
)
1864 struct video_renderer
*renderer
= impl_from_IMFAttributes(iface
);
1866 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(key
), value
);
1868 return IMFAttributes_GetUINT64(renderer
->attributes
, key
, value
);
1871 static HRESULT WINAPI
video_renderer_attributes_GetDouble(IMFAttributes
*iface
, REFGUID key
, double *value
)
1873 struct video_renderer
*renderer
= impl_from_IMFAttributes(iface
);
1875 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(key
), value
);
1877 return IMFAttributes_GetDouble(renderer
->attributes
, key
, value
);
1880 static HRESULT WINAPI
video_renderer_attributes_GetGUID(IMFAttributes
*iface
, REFGUID key
, GUID
*value
)
1882 struct video_renderer
*renderer
= impl_from_IMFAttributes(iface
);
1884 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(key
), value
);
1886 return IMFAttributes_GetGUID(renderer
->attributes
, key
, value
);
1889 static HRESULT WINAPI
video_renderer_attributes_GetStringLength(IMFAttributes
*iface
, REFGUID key
,
1892 struct video_renderer
*renderer
= impl_from_IMFAttributes(iface
);
1894 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(key
), length
);
1896 return IMFAttributes_GetStringLength(renderer
->attributes
, key
, length
);
1899 static HRESULT WINAPI
video_renderer_attributes_GetString(IMFAttributes
*iface
, REFGUID key
, WCHAR
*value
,
1900 UINT32 size
, UINT32
*length
)
1902 struct video_renderer
*renderer
= impl_from_IMFAttributes(iface
);
1904 TRACE("%p, %s, %p, %u, %p.\n", iface
, debugstr_guid(key
), value
, size
, length
);
1906 return IMFAttributes_GetString(renderer
->attributes
, key
, value
, size
, length
);
1909 static HRESULT WINAPI
video_renderer_attributes_GetAllocatedString(IMFAttributes
*iface
, REFGUID key
,
1910 WCHAR
**value
, UINT32
*length
)
1912 struct video_renderer
*renderer
= impl_from_IMFAttributes(iface
);
1914 TRACE("%p, %s, %p, %p.\n", iface
, debugstr_guid(key
), value
, length
);
1916 return IMFAttributes_GetAllocatedString(renderer
->attributes
, key
, value
, length
);
1919 static HRESULT WINAPI
video_renderer_attributes_GetBlobSize(IMFAttributes
*iface
, REFGUID key
, UINT32
*size
)
1921 struct video_renderer
*renderer
= impl_from_IMFAttributes(iface
);
1923 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(key
), size
);
1925 return IMFAttributes_GetBlobSize(renderer
->attributes
, key
, size
);
1928 static HRESULT WINAPI
video_renderer_attributes_GetBlob(IMFAttributes
*iface
, REFGUID key
, UINT8
*buf
,
1929 UINT32 bufsize
, UINT32
*blobsize
)
1931 struct video_renderer
*renderer
= impl_from_IMFAttributes(iface
);
1933 TRACE("%p, %s, %p, %u, %p.\n", iface
, debugstr_guid(key
), buf
, bufsize
, blobsize
);
1935 return IMFAttributes_GetBlob(renderer
->attributes
, key
, buf
, bufsize
, blobsize
);
1938 static HRESULT WINAPI
video_renderer_attributes_GetAllocatedBlob(IMFAttributes
*iface
, REFGUID key
,
1939 UINT8
**buf
, UINT32
*size
)
1941 struct video_renderer
*renderer
= impl_from_IMFAttributes(iface
);
1943 TRACE("%p, %s, %p, %p.\n", iface
, debugstr_guid(key
), buf
, size
);
1945 return IMFAttributes_GetAllocatedBlob(renderer
->attributes
, key
, buf
, size
);
1948 static HRESULT WINAPI
video_renderer_attributes_GetUnknown(IMFAttributes
*iface
, REFGUID key
, REFIID riid
, void **out
)
1950 struct video_renderer
*renderer
= impl_from_IMFAttributes(iface
);
1952 TRACE("%p, %s, %s, %p.\n", iface
, debugstr_guid(key
), debugstr_guid(riid
), out
);
1954 return IMFAttributes_GetUnknown(renderer
->attributes
, key
, riid
, out
);
1957 static HRESULT WINAPI
video_renderer_attributes_SetItem(IMFAttributes
*iface
, REFGUID key
, REFPROPVARIANT value
)
1959 struct video_renderer
*renderer
= impl_from_IMFAttributes(iface
);
1961 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(key
), value
);
1963 return IMFAttributes_SetItem(renderer
->attributes
, key
, value
);
1966 static HRESULT WINAPI
video_renderer_attributes_DeleteItem(IMFAttributes
*iface
, REFGUID key
)
1968 struct video_renderer
*renderer
= impl_from_IMFAttributes(iface
);
1970 TRACE("%p, %s.\n", iface
, debugstr_guid(key
));
1972 return IMFAttributes_DeleteItem(renderer
->attributes
, key
);
1975 static HRESULT WINAPI
video_renderer_attributes_DeleteAllItems(IMFAttributes
*iface
)
1977 struct video_renderer
*renderer
= impl_from_IMFAttributes(iface
);
1979 TRACE("%p.\n", iface
);
1981 return IMFAttributes_DeleteAllItems(renderer
->attributes
);
1984 static HRESULT WINAPI
video_renderer_attributes_SetUINT32(IMFAttributes
*iface
, REFGUID key
, UINT32 value
)
1986 struct video_renderer
*renderer
= impl_from_IMFAttributes(iface
);
1988 TRACE("%p, %s, %u.\n", iface
, debugstr_guid(key
), value
);
1990 return IMFAttributes_SetUINT32(renderer
->attributes
, key
, value
);
1993 static HRESULT WINAPI
video_renderer_attributes_SetUINT64(IMFAttributes
*iface
, REFGUID key
, UINT64 value
)
1995 struct video_renderer
*renderer
= impl_from_IMFAttributes(iface
);
1997 TRACE("%p, %s, %s.\n", iface
, debugstr_guid(key
), wine_dbgstr_longlong(value
));
1999 return IMFAttributes_SetUINT64(renderer
->attributes
, key
, value
);
2002 static HRESULT WINAPI
video_renderer_attributes_SetDouble(IMFAttributes
*iface
, REFGUID key
, double value
)
2004 struct video_renderer
*renderer
= impl_from_IMFAttributes(iface
);
2006 TRACE("%p, %s, %f.\n", iface
, debugstr_guid(key
), value
);
2008 return IMFAttributes_SetDouble(renderer
->attributes
, key
, value
);
2011 static HRESULT WINAPI
video_renderer_attributes_SetGUID(IMFAttributes
*iface
, REFGUID key
, REFGUID value
)
2013 struct video_renderer
*renderer
= impl_from_IMFAttributes(iface
);
2015 TRACE("%p, %s, %s.\n", iface
, debugstr_guid(key
), debugstr_guid(value
));
2017 return IMFAttributes_SetGUID(renderer
->attributes
, key
, value
);
2020 static HRESULT WINAPI
video_renderer_attributes_SetString(IMFAttributes
*iface
, REFGUID key
,
2023 struct video_renderer
*renderer
= impl_from_IMFAttributes(iface
);
2025 TRACE("%p, %s, %s.\n", iface
, debugstr_guid(key
), debugstr_w(value
));
2027 return IMFAttributes_SetString(renderer
->attributes
, key
, value
);
2030 static HRESULT WINAPI
video_renderer_attributes_SetBlob(IMFAttributes
*iface
, REFGUID key
,
2031 const UINT8
*buf
, UINT32 size
)
2033 struct video_renderer
*renderer
= impl_from_IMFAttributes(iface
);
2035 TRACE("%p, %s, %p, %u.\n", iface
, debugstr_guid(key
), buf
, size
);
2037 return IMFAttributes_SetBlob(renderer
->attributes
, key
, buf
, size
);
2040 static HRESULT WINAPI
video_renderer_attributes_SetUnknown(IMFAttributes
*iface
, REFGUID key
,
2043 struct video_renderer
*renderer
= impl_from_IMFAttributes(iface
);
2045 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(key
), unknown
);
2047 return IMFAttributes_SetUnknown(renderer
->attributes
, key
, unknown
);
2050 static HRESULT WINAPI
video_renderer_attributes_LockStore(IMFAttributes
*iface
)
2052 struct video_renderer
*renderer
= impl_from_IMFAttributes(iface
);
2054 TRACE("%p.\n", iface
);
2056 return IMFAttributes_LockStore(renderer
->attributes
);
2059 static HRESULT WINAPI
video_renderer_attributes_UnlockStore(IMFAttributes
*iface
)
2061 struct video_renderer
*renderer
= impl_from_IMFAttributes(iface
);
2063 TRACE("%p.\n", iface
);
2065 return IMFAttributes_UnlockStore(renderer
->attributes
);
2068 static HRESULT WINAPI
video_renderer_attributes_GetCount(IMFAttributes
*iface
, UINT32
*count
)
2070 struct video_renderer
*renderer
= impl_from_IMFAttributes(iface
);
2072 TRACE("%p, %p.\n", iface
, count
);
2074 return IMFAttributes_GetCount(renderer
->attributes
, count
);
2077 static HRESULT WINAPI
video_renderer_attributes_GetItemByIndex(IMFAttributes
*iface
, UINT32 index
,
2078 GUID
*key
, PROPVARIANT
*value
)
2080 struct video_renderer
*renderer
= impl_from_IMFAttributes(iface
);
2082 TRACE("%p, %u, %p, %p.\n", iface
, index
, key
, value
);
2084 return IMFAttributes_GetItemByIndex(renderer
->attributes
, index
, key
, value
);
2087 static HRESULT WINAPI
video_renderer_attributes_CopyAllItems(IMFAttributes
*iface
, IMFAttributes
*dest
)
2089 struct video_renderer
*renderer
= impl_from_IMFAttributes(iface
);
2091 TRACE("%p, %p.\n", iface
, dest
);
2093 return IMFAttributes_CopyAllItems(renderer
->attributes
, dest
);
2096 static const IMFAttributesVtbl video_renderer_attributes_vtbl
=
2098 video_renderer_attributes_QueryInterface
,
2099 video_renderer_attributes_AddRef
,
2100 video_renderer_attributes_Release
,
2101 video_renderer_attributes_GetItem
,
2102 video_renderer_attributes_GetItemType
,
2103 video_renderer_attributes_CompareItem
,
2104 video_renderer_attributes_Compare
,
2105 video_renderer_attributes_GetUINT32
,
2106 video_renderer_attributes_GetUINT64
,
2107 video_renderer_attributes_GetDouble
,
2108 video_renderer_attributes_GetGUID
,
2109 video_renderer_attributes_GetStringLength
,
2110 video_renderer_attributes_GetString
,
2111 video_renderer_attributes_GetAllocatedString
,
2112 video_renderer_attributes_GetBlobSize
,
2113 video_renderer_attributes_GetBlob
,
2114 video_renderer_attributes_GetAllocatedBlob
,
2115 video_renderer_attributes_GetUnknown
,
2116 video_renderer_attributes_SetItem
,
2117 video_renderer_attributes_DeleteItem
,
2118 video_renderer_attributes_DeleteAllItems
,
2119 video_renderer_attributes_SetUINT32
,
2120 video_renderer_attributes_SetUINT64
,
2121 video_renderer_attributes_SetDouble
,
2122 video_renderer_attributes_SetGUID
,
2123 video_renderer_attributes_SetString
,
2124 video_renderer_attributes_SetBlob
,
2125 video_renderer_attributes_SetUnknown
,
2126 video_renderer_attributes_LockStore
,
2127 video_renderer_attributes_UnlockStore
,
2128 video_renderer_attributes_GetCount
,
2129 video_renderer_attributes_GetItemByIndex
,
2130 video_renderer_attributes_CopyAllItems
,
2133 static HRESULT WINAPI
video_renderer_quality_advise_QueryInterface(IMFQualityAdvise
*iface
, REFIID riid
, void **out
)
2135 struct video_renderer
*renderer
= impl_from_IMFQualityAdvise(iface
);
2136 return IMFMediaSink_QueryInterface(&renderer
->IMFMediaSink_iface
, riid
, out
);
2139 static ULONG WINAPI
video_renderer_quality_advise_AddRef(IMFQualityAdvise
*iface
)
2141 struct video_renderer
*renderer
= impl_from_IMFQualityAdvise(iface
);
2142 return IMFMediaSink_AddRef(&renderer
->IMFMediaSink_iface
);
2145 static ULONG WINAPI
video_renderer_quality_Release(IMFQualityAdvise
*iface
)
2147 struct video_renderer
*renderer
= impl_from_IMFQualityAdvise(iface
);
2148 return IMFMediaSink_Release(&renderer
->IMFMediaSink_iface
);
2151 static HRESULT WINAPI
video_renderer_quality_advise_SetDropMode(IMFQualityAdvise
*iface
,
2152 MF_QUALITY_DROP_MODE mode
)
2154 FIXME("%p, %u.\n", iface
, mode
);
2159 static HRESULT WINAPI
video_renderer_quality_advise_SetQualityLevel(IMFQualityAdvise
*iface
,
2160 MF_QUALITY_LEVEL level
)
2162 FIXME("%p, %u.\n", iface
, level
);
2167 static HRESULT WINAPI
video_renderer_quality_advise_GetDropMode(IMFQualityAdvise
*iface
,
2168 MF_QUALITY_DROP_MODE
*mode
)
2170 FIXME("%p, %p.\n", iface
, mode
);
2175 static HRESULT WINAPI
video_renderer_quality_advise_GetQualityLevel(IMFQualityAdvise
*iface
,
2176 MF_QUALITY_LEVEL
*level
)
2178 FIXME("%p, %p.\n", iface
, level
);
2183 static HRESULT WINAPI
video_renderer_quality_advise_DropTime(IMFQualityAdvise
*iface
, LONGLONG interval
)
2185 FIXME("%p, %s.\n", iface
, wine_dbgstr_longlong(interval
));
2190 static const IMFQualityAdviseVtbl video_renderer_quality_advise_vtbl
=
2192 video_renderer_quality_advise_QueryInterface
,
2193 video_renderer_quality_advise_AddRef
,
2194 video_renderer_quality_Release
,
2195 video_renderer_quality_advise_SetDropMode
,
2196 video_renderer_quality_advise_SetQualityLevel
,
2197 video_renderer_quality_advise_GetDropMode
,
2198 video_renderer_quality_advise_GetQualityLevel
,
2199 video_renderer_quality_advise_DropTime
,
2202 static HRESULT
evr_create_object(IMFAttributes
*attributes
, void *user_context
, IUnknown
**obj
)
2204 struct video_renderer
*object
;
2205 IMFVideoPresenter
*presenter
= NULL
;
2206 IMFTransform
*mixer
= NULL
;
2209 TRACE("%p, %p, %p.\n", attributes
, user_context
, obj
);
2211 if (!(object
= heap_alloc_zero(sizeof(*object
))))
2212 return E_OUTOFMEMORY
;
2214 object
->IMFMediaSink_iface
.lpVtbl
= &video_renderer_sink_vtbl
;
2215 object
->IMFMediaSinkPreroll_iface
.lpVtbl
= &video_renderer_preroll_vtbl
;
2216 object
->IMFVideoRenderer_iface
.lpVtbl
= &video_renderer_vtbl
;
2217 object
->IMFMediaEventGenerator_iface
.lpVtbl
= &video_renderer_events_vtbl
;
2218 object
->IMFClockStateSink_iface
.lpVtbl
= &video_renderer_clock_sink_vtbl
;
2219 object
->IMFGetService_iface
.lpVtbl
= &video_renderer_get_service_vtbl
;
2220 object
->IMFTopologyServiceLookup_iface
.lpVtbl
= &video_renderer_service_lookup_vtbl
;
2221 object
->IMediaEventSink_iface
.lpVtbl
= &media_event_sink_vtbl
;
2222 object
->IMFAttributes_iface
.lpVtbl
= &video_renderer_attributes_vtbl
;
2223 object
->IMFQualityAdvise_iface
.lpVtbl
= &video_renderer_quality_advise_vtbl
;
2224 object
->refcount
= 1;
2225 InitializeCriticalSection(&object
->cs
);
2227 if (FAILED(hr
= MFCreateEventQueue(&object
->event_queue
)))
2230 if (FAILED(hr
= MFCreateAttributes(&object
->attributes
, 0)))
2233 /* Create mixer and presenter. */
2234 if (FAILED(hr
= video_renderer_create_mixer(attributes
, &mixer
)))
2237 if (FAILED(hr
= video_renderer_create_presenter(object
, attributes
, &presenter
)))
2240 if (FAILED(hr
= video_renderer_initialize(object
, mixer
, presenter
)))
2243 IMFTransform_Release(mixer
);
2244 IMFVideoPresenter_Release(presenter
);
2246 /* Default attributes */
2247 IMFAttributes_SetUINT32(object
->attributes
, &EVRConfig_ForceBob
, 0);
2248 IMFAttributes_SetUINT32(object
->attributes
, &EVRConfig_AllowDropToBob
, 0);
2249 IMFAttributes_SetUINT32(object
->attributes
, &EVRConfig_ForceThrottle
, 0);
2250 IMFAttributes_SetUINT32(object
->attributes
, &EVRConfig_AllowDropToThrottle
, 0);
2251 IMFAttributes_SetUINT32(object
->attributes
, &EVRConfig_ForceHalfInterlace
, 0);
2252 IMFAttributes_SetUINT32(object
->attributes
, &EVRConfig_AllowDropToHalfInterlace
, 0);
2253 IMFAttributes_SetUINT32(object
->attributes
, &EVRConfig_ForceScaling
, 0);
2254 IMFAttributes_SetUINT32(object
->attributes
, &EVRConfig_AllowScaling
, 0);
2255 IMFAttributes_SetUINT32(object
->attributes
, &EVRConfig_ForceBatching
, 0);
2256 IMFAttributes_SetUINT32(object
->attributes
, &EVRConfig_AllowBatching
, 0);
2258 *obj
= (IUnknown
*)&object
->IMFMediaSink_iface
;
2265 IMFTransform_Release(mixer
);
2268 IMFVideoPresenter_Release(presenter
);
2270 video_renderer_release_services(object
);
2271 IMFMediaSink_Release(&object
->IMFMediaSink_iface
);
2276 static void evr_shutdown_object(void *user_context
, IUnknown
*obj
)
2280 if (SUCCEEDED(IUnknown_QueryInterface(obj
, &IID_IMFMediaSink
, (void **)&sink
)))
2282 IMFMediaSink_Shutdown(sink
);
2283 IMFMediaSink_Release(sink
);
2287 static const struct activate_funcs evr_activate_funcs
=
2289 .create_object
= evr_create_object
,
2290 .shutdown_object
= evr_shutdown_object
,
2293 /***********************************************************************
2294 * MFCreateVideoRendererActivate (mf.@)
2296 HRESULT WINAPI
MFCreateVideoRendererActivate(HWND hwnd
, IMFActivate
**activate
)
2300 TRACE("%p, %p.\n", hwnd
, activate
);
2305 hr
= create_activation_object(NULL
, &evr_activate_funcs
, activate
);
2307 IMFActivate_SetUINT64(*activate
, &MF_ACTIVATE_VIDEO_WINDOW
, (ULONG_PTR
)hwnd
);
2312 /***********************************************************************
2313 * MFCreateVideoRenderer (mf.@)
2315 HRESULT WINAPI
MFCreateVideoRenderer(REFIID riid
, void **renderer
)
2320 TRACE("%s, %p.\n", debugstr_guid(riid
), renderer
);
2324 if (SUCCEEDED(hr
= evr_create_object(NULL
, NULL
, &obj
)))
2326 hr
= IUnknown_QueryInterface(obj
, riid
, renderer
);
2327 IUnknown_Release(obj
);