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,
50 EVR_STREAM_SAMPLE_NEEDED
= 0x4,
51 EVR_STREAM_STARTED
= 0x8,
54 struct video_renderer
;
58 IMFStreamSink IMFStreamSink_iface
;
59 IMFMediaTypeHandler IMFMediaTypeHandler_iface
;
60 IMFGetService IMFGetService_iface
;
61 IMFAttributes IMFAttributes_iface
;
65 struct video_renderer
*parent
;
66 IMFMediaEventQueue
*event_queue
;
67 IMFVideoSampleAllocator
*allocator
;
68 IMFAttributes
*attributes
;
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
;
87 IMFMediaEventQueue
*event_queue
;
88 IMFAttributes
*attributes
;
89 IMFPresentationClock
*clock
;
92 IMFVideoPresenter
*presenter
;
94 IUnknown
*device_manager
;
98 struct video_stream
**streams
;
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
;
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
);
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
))
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
;
255 WARN("Unsupported interface %s.\n", debugstr_guid(riid
));
257 return E_NOINTERFACE
;
260 IUnknown_AddRef((IUnknown
*)*obj
);
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
);
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
);
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
);
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
);
338 TRACE("%p, %p.\n", iface
, sink
);
340 EnterCriticalSection(&stream
->cs
);
342 hr
= MF_E_STREAMSINK_REMOVED
;
347 *sink
= &stream
->parent
->IMFMediaSink_iface
;
348 IMFMediaSink_AddRef(*sink
);
350 LeaveCriticalSection(&stream
->cs
);
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
);
362 return MF_E_STREAMSINK_REMOVED
;
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
);
382 return MF_E_STREAMSINK_REMOVED
;
384 *handler
= &stream
->IMFMediaTypeHandler_iface
;
385 IMFMediaTypeHandler_AddRef(*handler
);
390 static HRESULT WINAPI
video_stream_sink_ProcessSample(IMFStreamSink
*iface
, IMFSample
*sample
)
392 struct video_stream
*stream
= impl_from_IMFStreamSink(iface
);
396 TRACE("%p, %p.\n", iface
, sample
);
398 EnterCriticalSection(&stream
->cs
);
401 hr
= MF_E_STREAMSINK_REMOVED
;
402 else if (!stream
->parent
->clock
)
404 else if (FAILED(hr
= IMFSample_GetSampleTime(sample
, ×tamp
)))
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
);
432 static void video_stream_end_of_stream(struct video_stream
*stream
)
434 if (!(stream
->flags
& EVR_STREAM_STARTED
))
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
);
447 TRACE("%p, %d, %p, %p.\n", iface
, marker_type
, marker_value
, context
);
449 EnterCriticalSection(&stream
->cs
);
451 hr
= MF_E_STREAMSINK_REMOVED
;
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
);
463 static HRESULT WINAPI
video_stream_sink_Flush(IMFStreamSink
*iface
)
465 struct video_stream
*stream
= impl_from_IMFStreamSink(iface
);
468 TRACE("%p.\n", iface
);
470 EnterCriticalSection(&stream
->cs
);
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
);
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
,
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
);
522 TRACE("%p, %p, %p.\n", iface
, in_type
, out_type
);
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
;
539 static HRESULT WINAPI
video_stream_typehandler_GetMediaTypeCount(IMFMediaTypeHandler
*iface
, DWORD
*count
)
541 TRACE("%p, %p.\n", iface
, count
);
551 static HRESULT WINAPI
video_stream_typehandler_GetMediaTypeByIndex(IMFMediaTypeHandler
*iface
, DWORD index
,
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
);
564 TRACE("%p, %p.\n", iface
, type
);
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);
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
);
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
);
601 return MF_E_STREAMSINK_REMOVED
;
606 memcpy(type
, &MFMediaType_Video
, sizeof(*type
));
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
)
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
);
653 hr
= IMFVideoSampleAllocator_SetDirectXManager(stream
->allocator
, stream
->parent
->device_manager
);
656 hr
= IMFVideoSampleAllocator_QueryInterface(stream
->allocator
, riid
, obj
);
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
));
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
);
678 TRACE("%p, %s, %s, %p.\n", iface
, debugstr_guid(service
), debugstr_guid(riid
), obj
);
680 EnterCriticalSection(&stream
->cs
);
682 hr
= MF_E_STREAMSINK_REMOVED
;
684 hr
= video_stream_get_service(stream
, service
, riid
, obj
);
685 LeaveCriticalSection(&stream
->cs
);
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
,
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
,
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
,
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
,
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;
1040 if (FAILED(IMFTransform_QueryInterface(renderer
->mixer
, &IID_IMFAttributes
, (void **)&attributes
)))
1043 ret
= SUCCEEDED(IMFAttributes_GetUINT32(attributes
, &MF_SA_D3D_AWARE
, &value
)) && value
;
1044 IMFAttributes_Release(attributes
);
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
;
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
)))
1069 if (FAILED(hr
= MFCreateAttributes(&stream
->attributes
, 0)))
1072 stream
->parent
= renderer
;
1073 IMFMediaSink_AddRef(&stream
->parent
->IMFMediaSink_iface
);
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
);
1092 IMFStreamSink_Release(&stream
->IMFStreamSink_iface
);
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
;
1142 WARN("Unsupported interface %s.\n", debugstr_guid(riid
));
1144 return E_NOINTERFACE
;
1147 IUnknown_AddRef((IUnknown
*)*obj
);
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
);
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
);
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
);
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
;
1202 static HRESULT
video_renderer_add_stream(struct video_renderer
*renderer
, unsigned int id
,
1203 IMFStreamSink
**stream_sink
)
1205 struct video_stream
*stream
;
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
)))
1218 *stream_sink
= &stream
->IMFStreamSink_iface
;
1219 IMFStreamSink_AddRef(*stream_sink
);
1221 renderer
->streams
[renderer
->stream_count
++] = stream
;
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
);
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
)
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
);
1251 static HRESULT WINAPI
video_renderer_sink_RemoveStreamSink(IMFMediaSink
*iface
, DWORD id
)
1253 struct video_renderer
*renderer
= impl_from_IMFMediaSink(iface
);
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
)
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
--;
1282 LeaveCriticalSection(&renderer
->cs
);
1287 static HRESULT WINAPI
video_renderer_sink_GetStreamSinkCount(IMFMediaSink
*iface
, DWORD
*count
)
1289 struct video_renderer
*renderer
= impl_from_IMFMediaSink(iface
);
1292 TRACE("%p, %p.\n", iface
, count
);
1294 EnterCriticalSection(&renderer
->cs
);
1295 if (renderer
->flags
& EVR_SHUT_DOWN
)
1300 *count
= renderer
->stream_count
;
1301 LeaveCriticalSection(&renderer
->cs
);
1306 static HRESULT WINAPI
video_renderer_sink_GetStreamSinkByIndex(IMFMediaSink
*iface
, DWORD index
,
1307 IMFStreamSink
**stream
)
1309 struct video_renderer
*renderer
= impl_from_IMFMediaSink(iface
);
1312 TRACE("%p, %u, %p.\n", iface
, index
, stream
);
1314 EnterCriticalSection(&renderer
->cs
);
1315 if (renderer
->flags
& EVR_SHUT_DOWN
)
1319 else if (index
>= renderer
->stream_count
)
1323 *stream
= &renderer
->streams
[index
]->IMFStreamSink_iface
;
1324 IMFStreamSink_AddRef(*stream
);
1326 LeaveCriticalSection(&renderer
->cs
);
1331 static HRESULT WINAPI
video_renderer_sink_GetStreamSinkById(IMFMediaSink
*iface
, DWORD id
,
1332 IMFStreamSink
**stream
)
1334 struct video_renderer
*renderer
= impl_from_IMFMediaSink(iface
);
1338 TRACE("%p, %#x, %p.\n", iface
, id
, stream
);
1340 EnterCriticalSection(&renderer
->cs
);
1341 if (renderer
->flags
& EVR_SHUT_DOWN
)
1347 for (i
= 0; i
< renderer
->stream_count
; ++i
)
1349 if (renderer
->streams
[i
]->id
== id
)
1353 if (i
== renderer
->stream_count
)
1354 hr
= MF_E_INVALIDSTREAMNUMBER
;
1357 *stream
= &renderer
->streams
[i
]->IMFStreamSink_iface
;
1358 IMFStreamSink_AddRef(*stream
);
1361 LeaveCriticalSection(&renderer
->cs
);
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
);
1389 TRACE("%p, %p.\n", iface
, clock
);
1391 EnterCriticalSection(&renderer
->cs
);
1393 if (renderer
->flags
& EVR_SHUT_DOWN
)
1396 video_renderer_set_presentation_clock(renderer
, clock
);
1398 LeaveCriticalSection(&renderer
->cs
);
1403 static HRESULT WINAPI
video_renderer_sink_GetPresentationClock(IMFMediaSink
*iface
, IMFPresentationClock
**clock
)
1405 struct video_renderer
*renderer
= impl_from_IMFMediaSink(iface
);
1408 TRACE("%p, %p.\n", iface
, clock
);
1413 EnterCriticalSection(&renderer
->cs
);
1415 if (renderer
->flags
& EVR_SHUT_DOWN
)
1417 else if (renderer
->clock
)
1419 *clock
= renderer
->clock
;
1420 IMFPresentationClock_AddRef(*clock
);
1425 LeaveCriticalSection(&renderer
->cs
);
1430 static HRESULT WINAPI
video_renderer_sink_Shutdown(IMFMediaSink
*iface
)
1432 struct video_renderer
*renderer
= impl_from_IMFMediaSink(iface
);
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
);
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
);
1507 TRACE("%p, %s.\n", iface
, debugstr_time(start_time
));
1509 EnterCriticalSection(&renderer
->cs
);
1510 if (renderer
->flags
& EVR_SHUT_DOWN
)
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
);
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
;
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
))
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
;
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
))
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
;
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
);
1636 DWORD input_count
, output_count
;
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
));
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
);
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
);
1678 static HRESULT
video_renderer_configure_presenter(struct video_renderer
*renderer
)
1680 IMFVideoDisplayControl
*control
;
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");
1703 static HRESULT
video_renderer_initialize(struct video_renderer
*renderer
, IMFTransform
*mixer
,
1704 IMFVideoPresenter
*presenter
)
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
);
1738 static HRESULT WINAPI
video_renderer_InitializeRenderer(IMFVideoRenderer
*iface
, IMFTransform
*mixer
,
1739 IMFVideoPresenter
*presenter
)
1741 struct video_renderer
*renderer
= impl_from_IMFVideoRenderer(iface
);
1744 TRACE("%p, %p, %p.\n", iface
, mixer
, presenter
);
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
);
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
);
1763 EnterCriticalSection(&renderer
->cs
);
1765 if (renderer
->flags
& EVR_SHUT_DOWN
)
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
);
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
,
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
;
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
);
1909 IMFMediaEventQueue_QueueEventParamVar(stream
->event_queue
, MEStreamSinkRequestSample
,
1910 &GUID_NULL
, S_OK
, NULL
);
1914 IMFVideoPresenter_OnClockStart(renderer
->presenter
, systime
, offset
);
1916 LeaveCriticalSection(&renderer
->cs
);
1921 static HRESULT WINAPI
video_renderer_clock_sink_OnClockStop(IMFClockStateSink
*iface
, MFTIME systime
)
1923 struct video_renderer
*renderer
= impl_from_IMFClockStateSink(iface
);
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
);
1958 static HRESULT WINAPI
video_renderer_clock_sink_OnClockPause(IMFClockStateSink
*iface
, MFTIME systime
)
1960 struct video_renderer
*renderer
= impl_from_IMFClockStateSink(iface
);
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
);
1985 static HRESULT WINAPI
video_renderer_clock_sink_OnClockRestart(IMFClockStateSink
*iface
, MFTIME systime
)
1987 struct video_renderer
*renderer
= impl_from_IMFClockStateSink(iface
);
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
);
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
);
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
);
2088 FIXME("Unsupported service %s.\n", debugstr_guid(service
));
2091 LeaveCriticalSection(&renderer
->cs
);
2095 hr
= IMFGetService_GetService(gs
, service
, riid
, obj
);
2096 IMFGetService_Release(gs
);
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
))
2118 IMFTopologyServiceLookup_AddRef(iface
);
2122 WARN("Unsupported interface %s.\n", debugstr_guid(riid
));
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
);
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
;
2164 IUnknown_AddRef((IUnknown
*)*objects
);
2165 hr
= *objects
? S_OK
: E_NOINTERFACE
;
2169 FIXME("Unsupported interface %s for render service.\n", debugstr_guid(riid
));
2173 else if (IsEqualGUID(service
, &MR_VIDEO_MIXER_SERVICE
))
2175 if (IsEqualIID(riid
, &IID_IMFTransform
))
2177 *objects
= renderer
->mixer
;
2178 IUnknown_AddRef((IUnknown
*)*objects
);
2182 FIXME("Unsupported interface %s for mixer service.\n", debugstr_guid(riid
));
2188 WARN("Unsupported service %s.\n", debugstr_guid(service
));
2189 hr
= MF_E_UNSUPPORTED_SERVICE
;
2192 LeaveCriticalSection(&renderer
->cs
);
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
))
2213 IMediaEventSink_AddRef(iface
);
2217 WARN("Unsupported interface %s.\n", debugstr_guid(riid
));
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
);
2240 TRACE("%p, %d, %ld, %ld.\n", iface
, event
, param1
, param2
);
2242 EnterCriticalSection(&renderer
->cs
);
2244 if (event
== EC_SAMPLE_NEEDED
)
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
);
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
)
2273 hr
= IMFMediaEventQueue_QueueEventParamVar(renderer
->event_queue
, MERendererEvent
,
2274 &GUID_NULL
, S_OK
, &code
);
2278 WARN("Unhandled event %d.\n", event
);
2279 hr
= MF_E_UNEXPECTED
;
2282 LeaveCriticalSection(&renderer
->cs
);
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
,
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
,
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
,
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
,
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
);
2657 static HRESULT WINAPI
video_renderer_quality_advise_SetQualityLevel(IMFQualityAdvise
*iface
,
2658 MF_QUALITY_LEVEL level
)
2660 FIXME("%p, %u.\n", iface
, level
);
2665 static HRESULT WINAPI
video_renderer_quality_advise_GetDropMode(IMFQualityAdvise
*iface
,
2666 MF_QUALITY_DROP_MODE
*mode
)
2668 FIXME("%p, %p.\n", iface
, mode
);
2673 static HRESULT WINAPI
video_renderer_quality_advise_GetQualityLevel(IMFQualityAdvise
*iface
,
2674 MF_QUALITY_LEVEL
*level
)
2676 FIXME("%p, %p.\n", iface
, level
);
2681 static HRESULT WINAPI
video_renderer_quality_advise_DropTime(IMFQualityAdvise
*iface
, LONGLONG interval
)
2683 FIXME("%p, %s.\n", iface
, wine_dbgstr_longlong(interval
));
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
;
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
);
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
;
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
)))
2790 if (FAILED(hr
= MFCreateAttributes(&object
->attributes
, 0)))
2793 /* Create mixer and presenter. */
2794 if (FAILED(hr
= video_renderer_create_mixer(attributes
, &mixer
)))
2797 if (FAILED(hr
= video_renderer_create_presenter(object
, attributes
, &presenter
)))
2800 if (FAILED(hr
= video_renderer_initialize(object
, mixer
, presenter
)))
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
;
2825 IMFTransform_Release(mixer
);
2828 IMFVideoPresenter_Release(presenter
);
2830 video_renderer_release_services(object
);
2831 IMFMediaSink_Release(&object
->IMFMediaSink_iface
);
2836 static void evr_shutdown_object(void *user_context
, IUnknown
*obj
)
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
)
2860 TRACE("%p, %p.\n", hwnd
, activate
);
2865 hr
= create_activation_object(NULL
, &evr_activate_funcs
, activate
);
2867 IMFActivate_SetUINT64(*activate
, &MF_ACTIVATE_VIDEO_WINDOW
, (ULONG_PTR
)hwnd
);
2872 /***********************************************************************
2873 * MFCreateVideoRenderer (mf.@)
2875 HRESULT WINAPI
MFCreateVideoRenderer(REFIID riid
, void **renderer
)
2880 TRACE("%s, %p.\n", debugstr_guid(riid
), renderer
);
2884 if (SUCCEEDED(hr
= evr_create_object(NULL
, NULL
, &obj
)))
2886 hr
= IUnknown_QueryInterface(obj
, riid
, renderer
);
2887 IUnknown_Release(obj
);