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
23 #include "mf_private.h"
31 WINE_DEFAULT_DEBUG_CHANNEL(mfplat
);
33 enum video_renderer_flags
36 EVR_INIT_SERVICES
= 0x2, /* Currently in InitServices() call. */
37 EVR_MIXER_INITED_SERVICES
= 0x4,
38 EVR_PRESENTER_INITED_SERVICES
= 0x8,
41 enum video_renderer_state
43 EVR_STATE_STOPPED
= 0,
48 enum video_stream_flags
50 EVR_STREAM_PREROLLING
= 0x1,
51 EVR_STREAM_PREROLLED
= 0x2,
52 EVR_STREAM_SAMPLE_NEEDED
= 0x4,
53 EVR_STREAM_STARTED
= 0x8,
56 struct video_renderer
;
60 IMFStreamSink IMFStreamSink_iface
;
61 IMFMediaTypeHandler IMFMediaTypeHandler_iface
;
62 IMFGetService IMFGetService_iface
;
63 IMFAttributes IMFAttributes_iface
;
67 struct video_renderer
*parent
;
68 IMFMediaEventQueue
*event_queue
;
69 IMFVideoSampleAllocator
*allocator
;
70 IMFAttributes
*attributes
;
76 IMFMediaSink IMFMediaSink_iface
;
77 IMFMediaSinkPreroll IMFMediaSinkPreroll_iface
;
78 IMFVideoRenderer IMFVideoRenderer_iface
;
79 IMFClockStateSink IMFClockStateSink_iface
;
80 IMFMediaEventGenerator IMFMediaEventGenerator_iface
;
81 IMFGetService IMFGetService_iface
;
82 IMFTopologyServiceLookup IMFTopologyServiceLookup_iface
;
83 IMediaEventSink IMediaEventSink_iface
;
84 IMFAttributes IMFAttributes_iface
;
85 IMFQualityAdvise IMFQualityAdvise_iface
;
86 IMFRateSupport IMFRateSupport_iface
;
89 IMFMediaEventQueue
*event_queue
;
90 IMFAttributes
*attributes
;
91 IMFPresentationClock
*clock
;
94 IMFVideoPresenter
*presenter
;
96 IUnknown
*device_manager
;
100 struct video_stream
**streams
;
107 static struct video_renderer
*impl_from_IMFMediaSink(IMFMediaSink
*iface
)
109 return CONTAINING_RECORD(iface
, struct video_renderer
, IMFMediaSink_iface
);
112 static struct video_renderer
*impl_from_IMFMediaSinkPreroll(IMFMediaSinkPreroll
*iface
)
114 return CONTAINING_RECORD(iface
, struct video_renderer
, IMFMediaSinkPreroll_iface
);
117 static struct video_renderer
*impl_from_IMFVideoRenderer(IMFVideoRenderer
*iface
)
119 return CONTAINING_RECORD(iface
, struct video_renderer
, IMFVideoRenderer_iface
);
122 static struct video_renderer
*impl_from_IMFMediaEventGenerator(IMFMediaEventGenerator
*iface
)
124 return CONTAINING_RECORD(iface
, struct video_renderer
, IMFMediaEventGenerator_iface
);
127 static struct video_renderer
*impl_from_IMFClockStateSink(IMFClockStateSink
*iface
)
129 return CONTAINING_RECORD(iface
, struct video_renderer
, IMFClockStateSink_iface
);
132 static struct video_renderer
*impl_from_IMFGetService(IMFGetService
*iface
)
134 return CONTAINING_RECORD(iface
, struct video_renderer
, IMFGetService_iface
);
137 static struct video_renderer
*impl_from_IMFTopologyServiceLookup(IMFTopologyServiceLookup
*iface
)
139 return CONTAINING_RECORD(iface
, struct video_renderer
, IMFTopologyServiceLookup_iface
);
142 static struct video_renderer
*impl_from_IMediaEventSink(IMediaEventSink
*iface
)
144 return CONTAINING_RECORD(iface
, struct video_renderer
, IMediaEventSink_iface
);
147 static struct video_renderer
*impl_from_IMFAttributes(IMFAttributes
*iface
)
149 return CONTAINING_RECORD(iface
, struct video_renderer
, IMFAttributes_iface
);
152 static struct video_renderer
*impl_from_IMFQualityAdvise(IMFQualityAdvise
*iface
)
154 return CONTAINING_RECORD(iface
, struct video_renderer
, IMFQualityAdvise_iface
);
157 static struct video_renderer
*impl_from_IMFRateSupport(IMFRateSupport
*iface
)
159 return CONTAINING_RECORD(iface
, struct video_renderer
, IMFRateSupport_iface
);
162 static struct video_stream
*impl_from_IMFStreamSink(IMFStreamSink
*iface
)
164 return CONTAINING_RECORD(iface
, struct video_stream
, IMFStreamSink_iface
);
167 static struct video_stream
*impl_from_IMFMediaTypeHandler(IMFMediaTypeHandler
*iface
)
169 return CONTAINING_RECORD(iface
, struct video_stream
, IMFMediaTypeHandler_iface
);
172 static struct video_stream
*impl_from_stream_IMFGetService(IMFGetService
*iface
)
174 return CONTAINING_RECORD(iface
, struct video_stream
, IMFGetService_iface
);
177 static struct video_stream
*impl_from_stream_IMFAttributes(IMFAttributes
*iface
)
179 return CONTAINING_RECORD(iface
, struct video_stream
, IMFAttributes_iface
);
182 static HRESULT
video_renderer_init_presenter_services(struct video_renderer
*renderer
)
184 IMFTopologyServiceLookupClient
*lookup_client
;
187 if (SUCCEEDED(hr
= IMFVideoPresenter_QueryInterface(renderer
->presenter
, &IID_IMFTopologyServiceLookupClient
,
188 (void **)&lookup_client
)))
190 renderer
->flags
|= EVR_INIT_SERVICES
;
191 if (SUCCEEDED(hr
= IMFTopologyServiceLookupClient_InitServicePointers(lookup_client
,
192 &renderer
->IMFTopologyServiceLookup_iface
)))
194 renderer
->flags
|= EVR_PRESENTER_INITED_SERVICES
;
196 renderer
->flags
&= ~EVR_INIT_SERVICES
;
197 IMFTopologyServiceLookupClient_Release(lookup_client
);
203 static void video_renderer_release_presenter_services(struct video_renderer
*renderer
)
205 IMFTopologyServiceLookupClient
*lookup_client
;
207 if (renderer
->flags
& EVR_PRESENTER_INITED_SERVICES
&& SUCCEEDED(IMFVideoPresenter_QueryInterface(renderer
->presenter
,
208 &IID_IMFTopologyServiceLookupClient
, (void **)&lookup_client
)))
210 IMFTopologyServiceLookupClient_ReleaseServicePointers(lookup_client
);
211 IMFTopologyServiceLookupClient_Release(lookup_client
);
212 renderer
->flags
&= ~EVR_PRESENTER_INITED_SERVICES
;
216 static void video_renderer_release_services(struct video_renderer
*renderer
)
218 IMFTopologyServiceLookupClient
*lookup_client
;
220 if (renderer
->flags
& EVR_MIXER_INITED_SERVICES
&& SUCCEEDED(IMFTransform_QueryInterface(renderer
->mixer
,
221 &IID_IMFTopologyServiceLookupClient
, (void **)&lookup_client
)))
223 IMFTopologyServiceLookupClient_ReleaseServicePointers(lookup_client
);
224 IMFTopologyServiceLookupClient_Release(lookup_client
);
225 renderer
->flags
&= ~EVR_MIXER_INITED_SERVICES
;
228 video_renderer_release_presenter_services(renderer
);
231 static HRESULT WINAPI
video_stream_sink_QueryInterface(IMFStreamSink
*iface
, REFIID riid
, void **obj
)
233 struct video_stream
*stream
= impl_from_IMFStreamSink(iface
);
235 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(riid
), obj
);
237 if (IsEqualIID(riid
, &IID_IMFStreamSink
) ||
238 IsEqualIID(riid
, &IID_IMFMediaEventGenerator
) ||
239 IsEqualIID(riid
, &IID_IUnknown
))
243 else if (IsEqualIID(riid
, &IID_IMFMediaTypeHandler
))
245 *obj
= &stream
->IMFMediaTypeHandler_iface
;
247 else if (IsEqualIID(riid
, &IID_IMFGetService
))
249 *obj
= &stream
->IMFGetService_iface
;
251 else if (IsEqualIID(riid
, &IID_IMFAttributes
))
253 *obj
= &stream
->IMFAttributes_iface
;
257 WARN("Unsupported interface %s.\n", debugstr_guid(riid
));
259 return E_NOINTERFACE
;
262 IUnknown_AddRef((IUnknown
*)*obj
);
267 static ULONG WINAPI
video_stream_sink_AddRef(IMFStreamSink
*iface
)
269 struct video_stream
*stream
= impl_from_IMFStreamSink(iface
);
270 ULONG refcount
= InterlockedIncrement(&stream
->refcount
);
272 TRACE("%p, refcount %lu.\n", iface
, refcount
);
277 static ULONG WINAPI
video_stream_sink_Release(IMFStreamSink
*iface
)
279 struct video_stream
*stream
= impl_from_IMFStreamSink(iface
);
280 ULONG refcount
= InterlockedDecrement(&stream
->refcount
);
284 if (stream
->event_queue
)
285 IMFMediaEventQueue_Release(stream
->event_queue
);
286 if (stream
->attributes
)
287 IMFAttributes_Release(stream
->attributes
);
288 if (stream
->allocator
)
289 IMFVideoSampleAllocator_Release(stream
->allocator
);
290 DeleteCriticalSection(&stream
->cs
);
297 static HRESULT WINAPI
video_stream_sink_GetEvent(IMFStreamSink
*iface
, DWORD flags
, IMFMediaEvent
**event
)
299 struct video_stream
*stream
= impl_from_IMFStreamSink(iface
);
301 TRACE("%p, %#lx, %p.\n", iface
, flags
, event
);
303 return IMFMediaEventQueue_GetEvent(stream
->event_queue
, flags
, event
);
306 static HRESULT WINAPI
video_stream_sink_BeginGetEvent(IMFStreamSink
*iface
, IMFAsyncCallback
*callback
, IUnknown
*state
)
308 struct video_stream
*stream
= impl_from_IMFStreamSink(iface
);
310 TRACE("%p, %p, %p.\n", iface
, callback
, state
);
312 return IMFMediaEventQueue_BeginGetEvent(stream
->event_queue
, callback
, state
);
315 static HRESULT WINAPI
video_stream_sink_EndGetEvent(IMFStreamSink
*iface
, IMFAsyncResult
*result
,
316 IMFMediaEvent
**event
)
318 struct video_stream
*stream
= impl_from_IMFStreamSink(iface
);
320 TRACE("%p, %p, %p.\n", iface
, result
, event
);
322 return IMFMediaEventQueue_EndGetEvent(stream
->event_queue
, result
, event
);
325 static HRESULT WINAPI
video_stream_sink_QueueEvent(IMFStreamSink
*iface
, MediaEventType event_type
,
326 REFGUID ext_type
, HRESULT hr
, const PROPVARIANT
*value
)
328 struct video_stream
*stream
= impl_from_IMFStreamSink(iface
);
330 TRACE("%p, %ld, %s, %#lx, %p.\n", iface
, event_type
, debugstr_guid(ext_type
), hr
, value
);
332 return IMFMediaEventQueue_QueueEventParamVar(stream
->event_queue
, event_type
, ext_type
, hr
, value
);
335 static HRESULT WINAPI
video_stream_sink_GetMediaSink(IMFStreamSink
*iface
, IMFMediaSink
**sink
)
337 struct video_stream
*stream
= impl_from_IMFStreamSink(iface
);
340 TRACE("%p, %p.\n", iface
, sink
);
342 EnterCriticalSection(&stream
->cs
);
344 hr
= MF_E_STREAMSINK_REMOVED
;
349 *sink
= &stream
->parent
->IMFMediaSink_iface
;
350 IMFMediaSink_AddRef(*sink
);
352 LeaveCriticalSection(&stream
->cs
);
357 static HRESULT WINAPI
video_stream_sink_GetIdentifier(IMFStreamSink
*iface
, DWORD
*id
)
359 struct video_stream
*stream
= impl_from_IMFStreamSink(iface
);
361 TRACE("%p, %p.\n", iface
, id
);
364 return MF_E_STREAMSINK_REMOVED
;
374 static HRESULT WINAPI
video_stream_sink_GetMediaTypeHandler(IMFStreamSink
*iface
, IMFMediaTypeHandler
**handler
)
376 struct video_stream
*stream
= impl_from_IMFStreamSink(iface
);
378 TRACE("%p, %p.\n", iface
, handler
);
384 return MF_E_STREAMSINK_REMOVED
;
386 *handler
= &stream
->IMFMediaTypeHandler_iface
;
387 IMFMediaTypeHandler_AddRef(*handler
);
392 static HRESULT WINAPI
video_stream_sink_ProcessSample(IMFStreamSink
*iface
, IMFSample
*sample
)
394 struct video_stream
*stream
= impl_from_IMFStreamSink(iface
);
398 TRACE("%p, %p.\n", iface
, sample
);
400 EnterCriticalSection(&stream
->cs
);
403 hr
= MF_E_STREAMSINK_REMOVED
;
404 else if (!stream
->parent
->clock
)
406 else if (FAILED(hr
= IMFSample_GetSampleTime(sample
, ×tamp
)))
408 WARN("No sample timestamp, hr %#lx.\n", hr
);
410 else if (stream
->parent
->state
== EVR_STATE_RUNNING
|| stream
->flags
& EVR_STREAM_PREROLLING
)
412 if (!(stream
->flags
& EVR_STREAM_STARTED
))
414 IMFTransform_ProcessMessage(stream
->parent
->mixer
, MFT_MESSAGE_NOTIFY_START_OF_STREAM
, stream
->id
);
415 stream
->flags
|= EVR_STREAM_STARTED
;
418 if (SUCCEEDED(IMFTransform_ProcessInput(stream
->parent
->mixer
, stream
->id
, sample
, 0)))
419 IMFVideoPresenter_ProcessMessage(stream
->parent
->presenter
, MFVP_MESSAGE_PROCESSINPUTNOTIFY
, 0);
421 if (stream
->flags
& EVR_STREAM_PREROLLING
)
423 IMFMediaEventQueue_QueueEventParamVar(stream
->event_queue
, MEStreamSinkPrerolled
, &GUID_NULL
, S_OK
, NULL
);
424 stream
->flags
&= ~EVR_STREAM_PREROLLING
;
425 stream
->flags
|= EVR_STREAM_PREROLLED
;
429 LeaveCriticalSection(&stream
->cs
);
434 static void video_stream_end_of_stream(struct video_stream
*stream
)
436 if (!(stream
->flags
& EVR_STREAM_STARTED
))
439 IMFTransform_ProcessMessage(stream
->parent
->mixer
, MFT_MESSAGE_NOTIFY_END_OF_STREAM
, stream
->id
);
440 stream
->flags
&= ~EVR_STREAM_STARTED
;
443 static HRESULT WINAPI
video_stream_sink_PlaceMarker(IMFStreamSink
*iface
, MFSTREAMSINK_MARKER_TYPE marker_type
,
444 const PROPVARIANT
*marker_value
, const PROPVARIANT
*context
)
446 struct video_stream
*stream
= impl_from_IMFStreamSink(iface
);
449 TRACE("%p, %d, %p, %p.\n", iface
, marker_type
, marker_value
, context
);
451 EnterCriticalSection(&stream
->cs
);
453 hr
= MF_E_STREAMSINK_REMOVED
;
456 if (marker_type
== MFSTREAMSINK_MARKER_ENDOFSEGMENT
)
457 video_stream_end_of_stream(stream
);
458 IMFMediaEventQueue_QueueEventParamVar(stream
->event_queue
, MEStreamSinkMarker
, &GUID_NULL
, S_OK
, context
);
460 LeaveCriticalSection(&stream
->cs
);
465 static HRESULT WINAPI
video_stream_sink_Flush(IMFStreamSink
*iface
)
467 struct video_stream
*stream
= impl_from_IMFStreamSink(iface
);
470 TRACE("%p.\n", iface
);
472 EnterCriticalSection(&stream
->cs
);
474 hr
= MF_E_STREAMSINK_REMOVED
;
475 else if (SUCCEEDED(hr
= IMFTransform_ProcessMessage(stream
->parent
->mixer
, MFT_MESSAGE_COMMAND_FLUSH
, 0)))
476 hr
= IMFVideoPresenter_ProcessMessage(stream
->parent
->presenter
, MFVP_MESSAGE_FLUSH
, 0);
477 LeaveCriticalSection(&stream
->cs
);
482 static const IMFStreamSinkVtbl video_stream_sink_vtbl
=
484 video_stream_sink_QueryInterface
,
485 video_stream_sink_AddRef
,
486 video_stream_sink_Release
,
487 video_stream_sink_GetEvent
,
488 video_stream_sink_BeginGetEvent
,
489 video_stream_sink_EndGetEvent
,
490 video_stream_sink_QueueEvent
,
491 video_stream_sink_GetMediaSink
,
492 video_stream_sink_GetIdentifier
,
493 video_stream_sink_GetMediaTypeHandler
,
494 video_stream_sink_ProcessSample
,
495 video_stream_sink_PlaceMarker
,
496 video_stream_sink_Flush
,
499 static HRESULT WINAPI
video_stream_typehandler_QueryInterface(IMFMediaTypeHandler
*iface
, REFIID riid
,
502 struct video_stream
*stream
= impl_from_IMFMediaTypeHandler(iface
);
503 return IMFStreamSink_QueryInterface(&stream
->IMFStreamSink_iface
, riid
, obj
);
506 static ULONG WINAPI
video_stream_typehandler_AddRef(IMFMediaTypeHandler
*iface
)
508 struct video_stream
*stream
= impl_from_IMFMediaTypeHandler(iface
);
509 return IMFStreamSink_AddRef(&stream
->IMFStreamSink_iface
);
512 static ULONG WINAPI
video_stream_typehandler_Release(IMFMediaTypeHandler
*iface
)
514 struct video_stream
*stream
= impl_from_IMFMediaTypeHandler(iface
);
515 return IMFStreamSink_Release(&stream
->IMFStreamSink_iface
);
518 static HRESULT WINAPI
video_stream_typehandler_IsMediaTypeSupported(IMFMediaTypeHandler
*iface
,
519 IMFMediaType
*in_type
, IMFMediaType
**out_type
)
521 struct video_stream
*stream
= impl_from_IMFMediaTypeHandler(iface
);
524 TRACE("%p, %p, %p.\n", iface
, in_type
, out_type
);
530 return MF_E_INVALIDMEDIATYPE
;
532 if (SUCCEEDED(hr
= IMFTransform_SetInputType(stream
->parent
->mixer
, stream
->id
, in_type
,
533 MFT_SET_TYPE_TEST_ONLY
)))
535 if (out_type
) *out_type
= NULL
;
541 static HRESULT WINAPI
video_stream_typehandler_GetMediaTypeCount(IMFMediaTypeHandler
*iface
, DWORD
*count
)
543 TRACE("%p, %p.\n", iface
, count
);
553 static HRESULT WINAPI
video_stream_typehandler_GetMediaTypeByIndex(IMFMediaTypeHandler
*iface
, DWORD index
,
556 TRACE("%p, %lu, %p.\n", iface
, index
, type
);
558 return MF_E_NO_MORE_TYPES
;
561 static HRESULT WINAPI
video_stream_typehandler_SetCurrentMediaType(IMFMediaTypeHandler
*iface
, IMFMediaType
*type
)
563 struct video_stream
*stream
= impl_from_IMFMediaTypeHandler(iface
);
566 TRACE("%p, %p.\n", iface
, type
);
572 return MF_E_STREAMSINK_REMOVED
;
574 hr
= IMFTransform_SetInputType(stream
->parent
->mixer
, stream
->id
, type
, 0);
575 if (SUCCEEDED(hr
) && !stream
->id
)
576 hr
= IMFVideoPresenter_ProcessMessage(stream
->parent
->presenter
, MFVP_MESSAGE_INVALIDATEMEDIATYPE
, 0);
581 static HRESULT WINAPI
video_stream_typehandler_GetCurrentMediaType(IMFMediaTypeHandler
*iface
, IMFMediaType
**type
)
583 struct video_stream
*stream
= impl_from_IMFMediaTypeHandler(iface
);
585 TRACE("%p, %p.\n", iface
, type
);
591 return MF_E_STREAMSINK_REMOVED
;
593 return IMFTransform_GetInputCurrentType(stream
->parent
->mixer
, stream
->id
, type
);
596 static HRESULT WINAPI
video_stream_typehandler_GetMajorType(IMFMediaTypeHandler
*iface
, GUID
*type
)
598 struct video_stream
*stream
= impl_from_IMFMediaTypeHandler(iface
);
600 TRACE("%p, %p.\n", iface
, type
);
603 return MF_E_STREAMSINK_REMOVED
;
608 memcpy(type
, &MFMediaType_Video
, sizeof(*type
));
612 static const IMFMediaTypeHandlerVtbl video_stream_type_handler_vtbl
=
614 video_stream_typehandler_QueryInterface
,
615 video_stream_typehandler_AddRef
,
616 video_stream_typehandler_Release
,
617 video_stream_typehandler_IsMediaTypeSupported
,
618 video_stream_typehandler_GetMediaTypeCount
,
619 video_stream_typehandler_GetMediaTypeByIndex
,
620 video_stream_typehandler_SetCurrentMediaType
,
621 video_stream_typehandler_GetCurrentMediaType
,
622 video_stream_typehandler_GetMajorType
,
625 static HRESULT WINAPI
video_stream_get_service_QueryInterface(IMFGetService
*iface
, REFIID riid
, void **obj
)
627 struct video_stream
*stream
= impl_from_stream_IMFGetService(iface
);
628 return IMFStreamSink_QueryInterface(&stream
->IMFStreamSink_iface
, riid
, obj
);
631 static ULONG WINAPI
video_stream_get_service_AddRef(IMFGetService
*iface
)
633 struct video_stream
*stream
= impl_from_stream_IMFGetService(iface
);
634 return IMFStreamSink_AddRef(&stream
->IMFStreamSink_iface
);
637 static ULONG WINAPI
video_stream_get_service_Release(IMFGetService
*iface
)
639 struct video_stream
*stream
= impl_from_stream_IMFGetService(iface
);
640 return IMFStreamSink_Release(&stream
->IMFStreamSink_iface
);
643 static HRESULT
video_stream_get_service(struct video_stream
*stream
, REFGUID service
, REFIID riid
, void **obj
)
647 if (IsEqualGUID(service
, &MR_VIDEO_ACCELERATION_SERVICE
))
649 if (IsEqualIID(riid
, &IID_IMFVideoSampleAllocator
))
651 if (!stream
->allocator
)
653 hr
= MFCreateVideoSampleAllocator(&IID_IMFVideoSampleAllocator
, (void **)&stream
->allocator
);
655 hr
= IMFVideoSampleAllocator_SetDirectXManager(stream
->allocator
, stream
->parent
->device_manager
);
658 hr
= IMFVideoSampleAllocator_QueryInterface(stream
->allocator
, riid
, obj
);
662 else if (IsEqualIID(riid
, &IID_IDirect3DDeviceManager9
) && stream
->parent
->device_manager
)
664 return IUnknown_QueryInterface(stream
->parent
->device_manager
, riid
, obj
);
667 return E_NOINTERFACE
;
670 FIXME("Unsupported service %s.\n", debugstr_guid(service
));
675 static HRESULT WINAPI
video_stream_get_service_GetService(IMFGetService
*iface
, REFGUID service
, REFIID riid
, void **obj
)
677 struct video_stream
*stream
= impl_from_stream_IMFGetService(iface
);
680 TRACE("%p, %s, %s, %p.\n", iface
, debugstr_guid(service
), debugstr_guid(riid
), obj
);
682 EnterCriticalSection(&stream
->cs
);
684 hr
= MF_E_STREAMSINK_REMOVED
;
686 hr
= video_stream_get_service(stream
, service
, riid
, obj
);
687 LeaveCriticalSection(&stream
->cs
);
692 static const IMFGetServiceVtbl video_stream_get_service_vtbl
=
694 video_stream_get_service_QueryInterface
,
695 video_stream_get_service_AddRef
,
696 video_stream_get_service_Release
,
697 video_stream_get_service_GetService
,
700 static HRESULT WINAPI
video_stream_attributes_QueryInterface(IMFAttributes
*iface
, REFIID riid
, void **obj
)
702 struct video_stream
*stream
= impl_from_stream_IMFAttributes(iface
);
703 return IMFStreamSink_QueryInterface(&stream
->IMFStreamSink_iface
, riid
, obj
);
706 static ULONG WINAPI
video_stream_attributes_AddRef(IMFAttributes
*iface
)
708 struct video_stream
*stream
= impl_from_stream_IMFAttributes(iface
);
709 return IMFStreamSink_AddRef(&stream
->IMFStreamSink_iface
);
712 static ULONG WINAPI
video_stream_attributes_Release(IMFAttributes
*iface
)
714 struct video_stream
*stream
= impl_from_stream_IMFAttributes(iface
);
715 return IMFStreamSink_Release(&stream
->IMFStreamSink_iface
);
718 static HRESULT WINAPI
video_stream_attributes_GetItem(IMFAttributes
*iface
, REFGUID key
, PROPVARIANT
*value
)
720 struct video_stream
*stream
= impl_from_stream_IMFAttributes(iface
);
722 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(key
), value
);
724 return IMFAttributes_GetItem(stream
->attributes
, key
, value
);
727 static HRESULT WINAPI
video_stream_attributes_GetItemType(IMFAttributes
*iface
, REFGUID key
, MF_ATTRIBUTE_TYPE
*type
)
729 struct video_stream
*stream
= impl_from_stream_IMFAttributes(iface
);
731 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(key
), type
);
733 return IMFAttributes_GetItemType(stream
->attributes
, key
, type
);
736 static HRESULT WINAPI
video_stream_attributes_CompareItem(IMFAttributes
*iface
, REFGUID key
, REFPROPVARIANT value
,
739 struct video_stream
*stream
= impl_from_stream_IMFAttributes(iface
);
741 TRACE("%p, %s, %p, %p.\n", iface
, debugstr_guid(key
), value
, result
);
743 return IMFAttributes_CompareItem(stream
->attributes
, key
, value
, result
);
746 static HRESULT WINAPI
video_stream_attributes_Compare(IMFAttributes
*iface
, IMFAttributes
*theirs
,
747 MF_ATTRIBUTES_MATCH_TYPE type
, BOOL
*result
)
749 struct video_stream
*stream
= impl_from_stream_IMFAttributes(iface
);
751 TRACE("%p, %p, %d, %p.\n", iface
, theirs
, type
, result
);
753 return IMFAttributes_Compare(stream
->attributes
, theirs
, type
, result
);
756 static HRESULT WINAPI
video_stream_attributes_GetUINT32(IMFAttributes
*iface
, REFGUID key
, UINT32
*value
)
758 struct video_stream
*stream
= impl_from_stream_IMFAttributes(iface
);
760 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(key
), value
);
762 return IMFAttributes_GetUINT32(stream
->attributes
, key
, value
);
765 static HRESULT WINAPI
video_stream_attributes_GetUINT64(IMFAttributes
*iface
, REFGUID key
, UINT64
*value
)
767 struct video_stream
*stream
= impl_from_stream_IMFAttributes(iface
);
769 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(key
), value
);
771 return IMFAttributes_GetUINT64(stream
->attributes
, key
, value
);
774 static HRESULT WINAPI
video_stream_attributes_GetDouble(IMFAttributes
*iface
, REFGUID key
, double *value
)
776 struct video_stream
*stream
= impl_from_stream_IMFAttributes(iface
);
778 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(key
), value
);
780 return IMFAttributes_GetDouble(stream
->attributes
, key
, value
);
783 static HRESULT WINAPI
video_stream_attributes_GetGUID(IMFAttributes
*iface
, REFGUID key
, GUID
*value
)
785 struct video_stream
*stream
= impl_from_stream_IMFAttributes(iface
);
787 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(key
), value
);
789 return IMFAttributes_GetGUID(stream
->attributes
, key
, value
);
792 static HRESULT WINAPI
video_stream_attributes_GetStringLength(IMFAttributes
*iface
, REFGUID key
,
795 struct video_stream
*stream
= impl_from_stream_IMFAttributes(iface
);
797 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(key
), length
);
799 return IMFAttributes_GetStringLength(stream
->attributes
, key
, length
);
802 static HRESULT WINAPI
video_stream_attributes_GetString(IMFAttributes
*iface
, REFGUID key
, WCHAR
*value
,
803 UINT32 size
, UINT32
*length
)
805 struct video_stream
*stream
= impl_from_stream_IMFAttributes(iface
);
807 TRACE("%p, %s, %p, %u, %p.\n", iface
, debugstr_guid(key
), value
, size
, length
);
809 return IMFAttributes_GetString(stream
->attributes
, key
, value
, size
, length
);
812 static HRESULT WINAPI
video_stream_attributes_GetAllocatedString(IMFAttributes
*iface
, REFGUID key
,
813 WCHAR
**value
, UINT32
*length
)
815 struct video_stream
*stream
= impl_from_stream_IMFAttributes(iface
);
817 TRACE("%p, %s, %p, %p.\n", iface
, debugstr_guid(key
), value
, length
);
819 return IMFAttributes_GetAllocatedString(stream
->attributes
, key
, value
, length
);
822 static HRESULT WINAPI
video_stream_attributes_GetBlobSize(IMFAttributes
*iface
, REFGUID key
, UINT32
*size
)
824 struct video_stream
*stream
= impl_from_stream_IMFAttributes(iface
);
826 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(key
), size
);
828 return IMFAttributes_GetBlobSize(stream
->attributes
, key
, size
);
831 static HRESULT WINAPI
video_stream_attributes_GetBlob(IMFAttributes
*iface
, REFGUID key
, UINT8
*buf
,
832 UINT32 bufsize
, UINT32
*blobsize
)
834 struct video_stream
*stream
= impl_from_stream_IMFAttributes(iface
);
836 TRACE("%p, %s, %p, %u, %p.\n", iface
, debugstr_guid(key
), buf
, bufsize
, blobsize
);
838 return IMFAttributes_GetBlob(stream
->attributes
, key
, buf
, bufsize
, blobsize
);
841 static HRESULT WINAPI
video_stream_attributes_GetAllocatedBlob(IMFAttributes
*iface
, REFGUID key
,
842 UINT8
**buf
, UINT32
*size
)
844 struct video_stream
*stream
= impl_from_stream_IMFAttributes(iface
);
846 TRACE("%p, %s, %p, %p.\n", iface
, debugstr_guid(key
), buf
, size
);
848 return IMFAttributes_GetAllocatedBlob(stream
->attributes
, key
, buf
, size
);
851 static HRESULT WINAPI
video_stream_attributes_GetUnknown(IMFAttributes
*iface
, REFGUID key
, REFIID riid
, void **out
)
853 struct video_stream
*stream
= impl_from_stream_IMFAttributes(iface
);
855 TRACE("%p, %s, %s, %p.\n", iface
, debugstr_guid(key
), debugstr_guid(riid
), out
);
857 return IMFAttributes_GetUnknown(stream
->attributes
, key
, riid
, out
);
860 static HRESULT WINAPI
video_stream_attributes_SetItem(IMFAttributes
*iface
, REFGUID key
, REFPROPVARIANT value
)
862 struct video_stream
*stream
= impl_from_stream_IMFAttributes(iface
);
864 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(key
), value
);
866 return IMFAttributes_SetItem(stream
->attributes
, key
, value
);
869 static HRESULT WINAPI
video_stream_attributes_DeleteItem(IMFAttributes
*iface
, REFGUID key
)
871 struct video_stream
*stream
= impl_from_stream_IMFAttributes(iface
);
873 TRACE("%p, %s.\n", iface
, debugstr_guid(key
));
875 return IMFAttributes_DeleteItem(stream
->attributes
, key
);
878 static HRESULT WINAPI
video_stream_attributes_DeleteAllItems(IMFAttributes
*iface
)
880 struct video_stream
*stream
= impl_from_stream_IMFAttributes(iface
);
882 TRACE("%p.\n", iface
);
884 return IMFAttributes_DeleteAllItems(stream
->attributes
);
887 static HRESULT WINAPI
video_stream_attributes_SetUINT32(IMFAttributes
*iface
, REFGUID key
, UINT32 value
)
889 struct video_stream
*stream
= impl_from_stream_IMFAttributes(iface
);
891 TRACE("%p, %s, %u.\n", iface
, debugstr_guid(key
), value
);
893 return IMFAttributes_SetUINT32(stream
->attributes
, key
, value
);
896 static HRESULT WINAPI
video_stream_attributes_SetUINT64(IMFAttributes
*iface
, REFGUID key
, UINT64 value
)
898 struct video_stream
*stream
= impl_from_stream_IMFAttributes(iface
);
900 TRACE("%p, %s, %s.\n", iface
, debugstr_guid(key
), wine_dbgstr_longlong(value
));
902 return IMFAttributes_SetUINT64(stream
->attributes
, key
, value
);
905 static HRESULT WINAPI
video_stream_attributes_SetDouble(IMFAttributes
*iface
, REFGUID key
, double value
)
907 struct video_stream
*stream
= impl_from_stream_IMFAttributes(iface
);
909 TRACE("%p, %s, %f.\n", iface
, debugstr_guid(key
), value
);
911 return IMFAttributes_SetDouble(stream
->attributes
, key
, value
);
914 static HRESULT WINAPI
video_stream_attributes_SetGUID(IMFAttributes
*iface
, REFGUID key
, REFGUID value
)
916 struct video_stream
*stream
= impl_from_stream_IMFAttributes(iface
);
918 TRACE("%p, %s, %s.\n", iface
, debugstr_guid(key
), debugstr_guid(value
));
920 return IMFAttributes_SetGUID(stream
->attributes
, key
, value
);
923 static HRESULT WINAPI
video_stream_attributes_SetString(IMFAttributes
*iface
, REFGUID key
,
926 struct video_stream
*stream
= impl_from_stream_IMFAttributes(iface
);
928 TRACE("%p, %s, %s.\n", iface
, debugstr_guid(key
), debugstr_w(value
));
930 return IMFAttributes_SetString(stream
->attributes
, key
, value
);
933 static HRESULT WINAPI
video_stream_attributes_SetBlob(IMFAttributes
*iface
, REFGUID key
,
934 const UINT8
*buf
, UINT32 size
)
936 struct video_stream
*stream
= impl_from_stream_IMFAttributes(iface
);
938 TRACE("%p, %s, %p, %u.\n", iface
, debugstr_guid(key
), buf
, size
);
940 return IMFAttributes_SetBlob(stream
->attributes
, key
, buf
, size
);
943 static HRESULT WINAPI
video_stream_attributes_SetUnknown(IMFAttributes
*iface
, REFGUID key
,
946 struct video_stream
*stream
= impl_from_stream_IMFAttributes(iface
);
948 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(key
), unknown
);
950 return IMFAttributes_SetUnknown(stream
->attributes
, key
, unknown
);
953 static HRESULT WINAPI
video_stream_attributes_LockStore(IMFAttributes
*iface
)
955 struct video_stream
*stream
= impl_from_stream_IMFAttributes(iface
);
957 TRACE("%p.\n", iface
);
959 return IMFAttributes_LockStore(stream
->attributes
);
962 static HRESULT WINAPI
video_stream_attributes_UnlockStore(IMFAttributes
*iface
)
964 struct video_stream
*stream
= impl_from_stream_IMFAttributes(iface
);
966 TRACE("%p.\n", iface
);
968 return IMFAttributes_UnlockStore(stream
->attributes
);
971 static HRESULT WINAPI
video_stream_attributes_GetCount(IMFAttributes
*iface
, UINT32
*count
)
973 struct video_stream
*stream
= impl_from_stream_IMFAttributes(iface
);
975 TRACE("%p, %p.\n", iface
, count
);
977 return IMFAttributes_GetCount(stream
->attributes
, count
);
980 static HRESULT WINAPI
video_stream_attributes_GetItemByIndex(IMFAttributes
*iface
, UINT32 index
,
981 GUID
*key
, PROPVARIANT
*value
)
983 struct video_stream
*stream
= impl_from_stream_IMFAttributes(iface
);
985 TRACE("%p, %u, %p, %p.\n", iface
, index
, key
, value
);
987 return IMFAttributes_GetItemByIndex(stream
->attributes
, index
, key
, value
);
990 static HRESULT WINAPI
video_stream_attributes_CopyAllItems(IMFAttributes
*iface
, IMFAttributes
*dest
)
992 struct video_stream
*stream
= impl_from_stream_IMFAttributes(iface
);
994 TRACE("%p, %p.\n", iface
, dest
);
996 return IMFAttributes_CopyAllItems(stream
->attributes
, dest
);
999 static const IMFAttributesVtbl video_stream_attributes_vtbl
=
1001 video_stream_attributes_QueryInterface
,
1002 video_stream_attributes_AddRef
,
1003 video_stream_attributes_Release
,
1004 video_stream_attributes_GetItem
,
1005 video_stream_attributes_GetItemType
,
1006 video_stream_attributes_CompareItem
,
1007 video_stream_attributes_Compare
,
1008 video_stream_attributes_GetUINT32
,
1009 video_stream_attributes_GetUINT64
,
1010 video_stream_attributes_GetDouble
,
1011 video_stream_attributes_GetGUID
,
1012 video_stream_attributes_GetStringLength
,
1013 video_stream_attributes_GetString
,
1014 video_stream_attributes_GetAllocatedString
,
1015 video_stream_attributes_GetBlobSize
,
1016 video_stream_attributes_GetBlob
,
1017 video_stream_attributes_GetAllocatedBlob
,
1018 video_stream_attributes_GetUnknown
,
1019 video_stream_attributes_SetItem
,
1020 video_stream_attributes_DeleteItem
,
1021 video_stream_attributes_DeleteAllItems
,
1022 video_stream_attributes_SetUINT32
,
1023 video_stream_attributes_SetUINT64
,
1024 video_stream_attributes_SetDouble
,
1025 video_stream_attributes_SetGUID
,
1026 video_stream_attributes_SetString
,
1027 video_stream_attributes_SetBlob
,
1028 video_stream_attributes_SetUnknown
,
1029 video_stream_attributes_LockStore
,
1030 video_stream_attributes_UnlockStore
,
1031 video_stream_attributes_GetCount
,
1032 video_stream_attributes_GetItemByIndex
,
1033 video_stream_attributes_CopyAllItems
,
1036 static BOOL
video_renderer_is_mixer_d3d_aware(const struct video_renderer
*renderer
)
1038 IMFAttributes
*attributes
;
1039 unsigned int value
= 0;
1042 if (FAILED(IMFTransform_QueryInterface(renderer
->mixer
, &IID_IMFAttributes
, (void **)&attributes
)))
1045 ret
= SUCCEEDED(IMFAttributes_GetUINT32(attributes
, &MF_SA_D3D_AWARE
, &value
)) && value
;
1046 IMFAttributes_Release(attributes
);
1050 static HRESULT
video_renderer_stream_create(struct video_renderer
*renderer
, unsigned int id
,
1051 struct video_stream
**ret
)
1053 struct video_stream
*stream
;
1054 IMFAttributes
*attributes
;
1058 if (!(stream
= calloc(1, sizeof(*stream
))))
1059 return E_OUTOFMEMORY
;
1061 stream
->IMFStreamSink_iface
.lpVtbl
= &video_stream_sink_vtbl
;
1062 stream
->IMFMediaTypeHandler_iface
.lpVtbl
= &video_stream_type_handler_vtbl
;
1063 stream
->IMFGetService_iface
.lpVtbl
= &video_stream_get_service_vtbl
;
1064 stream
->IMFAttributes_iface
.lpVtbl
= &video_stream_attributes_vtbl
;
1065 stream
->refcount
= 1;
1066 InitializeCriticalSection(&stream
->cs
);
1068 if (FAILED(hr
= MFCreateEventQueue(&stream
->event_queue
)))
1071 if (FAILED(hr
= MFCreateAttributes(&stream
->attributes
, 0)))
1074 stream
->parent
= renderer
;
1075 IMFMediaSink_AddRef(&stream
->parent
->IMFMediaSink_iface
);
1078 if (video_renderer_is_mixer_d3d_aware(renderer
))
1079 IMFAttributes_SetUINT32(stream
->attributes
, &MF_SA_D3D_AWARE
, 1);
1081 if (SUCCEEDED(IMFTransform_GetInputStreamAttributes(renderer
->mixer
, id
, &attributes
)))
1083 if (SUCCEEDED(IMFAttributes_GetUINT32(attributes
, &MF_SA_REQUIRED_SAMPLE_COUNT
, &value
)))
1084 IMFAttributes_SetUINT32(stream
->attributes
, &MF_SA_REQUIRED_SAMPLE_COUNT
, value
);
1085 IMFAttributes_Release(attributes
);
1094 IMFStreamSink_Release(&stream
->IMFStreamSink_iface
);
1099 static HRESULT WINAPI
video_renderer_sink_QueryInterface(IMFMediaSink
*iface
, REFIID riid
, void **obj
)
1101 struct video_renderer
*renderer
= impl_from_IMFMediaSink(iface
);
1103 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(riid
), obj
);
1105 if (IsEqualIID(riid
, &IID_IMFMediaSink
) ||
1106 IsEqualIID(riid
, &IID_IUnknown
))
1108 *obj
= &renderer
->IMFMediaSink_iface
;
1110 else if (IsEqualIID(riid
, &IID_IMFMediaSinkPreroll
))
1112 *obj
= &renderer
->IMFMediaSinkPreroll_iface
;
1114 else if (IsEqualIID(riid
, &IID_IMFVideoRenderer
))
1116 *obj
= &renderer
->IMFVideoRenderer_iface
;
1118 else if (IsEqualIID(riid
, &IID_IMFMediaEventGenerator
))
1120 *obj
= &renderer
->IMFMediaEventGenerator_iface
;
1122 else if (IsEqualIID(riid
, &IID_IMFClockStateSink
))
1124 *obj
= &renderer
->IMFClockStateSink_iface
;
1126 else if (IsEqualIID(riid
, &IID_IMFGetService
))
1128 *obj
= &renderer
->IMFGetService_iface
;
1130 else if (IsEqualIID(riid
, &IID_IMFAttributes
))
1132 *obj
= &renderer
->IMFAttributes_iface
;
1134 else if (IsEqualIID(riid
, &IID_IMFQualityAdvise
))
1136 *obj
= &renderer
->IMFQualityAdvise_iface
;
1138 else if (IsEqualIID(riid
, &IID_IMFRateSupport
))
1140 *obj
= &renderer
->IMFRateSupport_iface
;
1144 WARN("Unsupported interface %s.\n", debugstr_guid(riid
));
1146 return E_NOINTERFACE
;
1149 IUnknown_AddRef((IUnknown
*)*obj
);
1154 static ULONG WINAPI
video_renderer_sink_AddRef(IMFMediaSink
*iface
)
1156 struct video_renderer
*renderer
= impl_from_IMFMediaSink(iface
);
1157 ULONG refcount
= InterlockedIncrement(&renderer
->refcount
);
1158 TRACE("%p, refcount %lu.\n", iface
, refcount
);
1162 static ULONG WINAPI
video_renderer_sink_Release(IMFMediaSink
*iface
)
1164 struct video_renderer
*renderer
= impl_from_IMFMediaSink(iface
);
1165 ULONG refcount
= InterlockedDecrement(&renderer
->refcount
);
1167 TRACE("%p, refcount %lu.\n", iface
, refcount
);
1171 if (renderer
->event_queue
)
1172 IMFMediaEventQueue_Release(renderer
->event_queue
);
1173 if (renderer
->mixer
)
1174 IMFTransform_Release(renderer
->mixer
);
1175 if (renderer
->presenter
)
1176 IMFVideoPresenter_Release(renderer
->presenter
);
1177 if (renderer
->device_manager
)
1178 IUnknown_Release(renderer
->device_manager
);
1179 if (renderer
->clock
)
1180 IMFPresentationClock_Release(renderer
->clock
);
1181 if (renderer
->attributes
)
1182 IMFAttributes_Release(renderer
->attributes
);
1183 DeleteCriticalSection(&renderer
->cs
);
1190 static HRESULT WINAPI
video_renderer_sink_GetCharacteristics(IMFMediaSink
*iface
, DWORD
*flags
)
1192 struct video_renderer
*renderer
= impl_from_IMFMediaSink(iface
);
1194 TRACE("%p, %p.\n", iface
, flags
);
1196 if (renderer
->flags
& EVR_SHUT_DOWN
)
1197 return MF_E_SHUTDOWN
;
1199 *flags
= MEDIASINK_CLOCK_REQUIRED
| MEDIASINK_CAN_PREROLL
;
1204 static HRESULT
video_renderer_add_stream(struct video_renderer
*renderer
, unsigned int id
,
1205 IMFStreamSink
**stream_sink
)
1207 struct video_stream
*stream
;
1210 if (!mf_array_reserve((void **)&renderer
->streams
, &renderer
->stream_size
, renderer
->stream_count
+ 1,
1211 sizeof(*renderer
->streams
)))
1213 return E_OUTOFMEMORY
;
1216 if (SUCCEEDED(hr
= video_renderer_stream_create(renderer
, id
, &stream
)))
1220 *stream_sink
= &stream
->IMFStreamSink_iface
;
1221 IMFStreamSink_AddRef(*stream_sink
);
1223 renderer
->streams
[renderer
->stream_count
++] = stream
;
1229 static HRESULT WINAPI
video_renderer_sink_AddStreamSink(IMFMediaSink
*iface
, DWORD id
,
1230 IMFMediaType
*media_type
, IMFStreamSink
**stream_sink
)
1232 struct video_renderer
*renderer
= impl_from_IMFMediaSink(iface
);
1235 TRACE("%p, %#lx, %p, %p.\n", iface
, id
, media_type
, stream_sink
);
1237 /* Rely on mixer for stream id validation. */
1239 EnterCriticalSection(&renderer
->cs
);
1240 if (renderer
->flags
& EVR_SHUT_DOWN
)
1242 else if (SUCCEEDED(hr
= IMFTransform_AddInputStreams(renderer
->mixer
, 1, &id
)))
1244 if (FAILED(hr
= video_renderer_add_stream(renderer
, id
, stream_sink
)))
1245 IMFTransform_DeleteInputStream(renderer
->mixer
, id
);
1248 LeaveCriticalSection(&renderer
->cs
);
1253 static HRESULT WINAPI
video_renderer_sink_RemoveStreamSink(IMFMediaSink
*iface
, DWORD id
)
1255 struct video_renderer
*renderer
= impl_from_IMFMediaSink(iface
);
1259 TRACE("%p, %#lx.\n", iface
, id
);
1261 /* Rely on mixer for stream id validation. */
1263 EnterCriticalSection(&renderer
->cs
);
1264 if (renderer
->flags
& EVR_SHUT_DOWN
)
1266 else if (SUCCEEDED(hr
= IMFTransform_DeleteInputStream(renderer
->mixer
, id
)))
1268 for (i
= 0; i
< renderer
->stream_count
; ++i
)
1270 if (renderer
->streams
[i
]->id
== id
)
1272 IMFStreamSink_Release(&renderer
->streams
[i
]->IMFStreamSink_iface
);
1273 renderer
->streams
[i
] = NULL
;
1274 if (i
< renderer
->stream_count
- 1)
1276 memmove(&renderer
->streams
[i
], &renderer
->streams
[i
+1],
1277 (renderer
->stream_count
- i
- 1) * sizeof(*renderer
->streams
));
1279 renderer
->stream_count
--;
1284 LeaveCriticalSection(&renderer
->cs
);
1289 static HRESULT WINAPI
video_renderer_sink_GetStreamSinkCount(IMFMediaSink
*iface
, DWORD
*count
)
1291 struct video_renderer
*renderer
= impl_from_IMFMediaSink(iface
);
1294 TRACE("%p, %p.\n", iface
, count
);
1296 EnterCriticalSection(&renderer
->cs
);
1297 if (renderer
->flags
& EVR_SHUT_DOWN
)
1302 *count
= renderer
->stream_count
;
1303 LeaveCriticalSection(&renderer
->cs
);
1308 static HRESULT WINAPI
video_renderer_sink_GetStreamSinkByIndex(IMFMediaSink
*iface
, DWORD index
,
1309 IMFStreamSink
**stream
)
1311 struct video_renderer
*renderer
= impl_from_IMFMediaSink(iface
);
1314 TRACE("%p, %lu, %p.\n", iface
, index
, stream
);
1316 EnterCriticalSection(&renderer
->cs
);
1317 if (renderer
->flags
& EVR_SHUT_DOWN
)
1321 else if (index
>= renderer
->stream_count
)
1325 *stream
= &renderer
->streams
[index
]->IMFStreamSink_iface
;
1326 IMFStreamSink_AddRef(*stream
);
1328 LeaveCriticalSection(&renderer
->cs
);
1333 static HRESULT WINAPI
video_renderer_sink_GetStreamSinkById(IMFMediaSink
*iface
, DWORD id
,
1334 IMFStreamSink
**stream
)
1336 struct video_renderer
*renderer
= impl_from_IMFMediaSink(iface
);
1340 TRACE("%p, %#lx, %p.\n", iface
, id
, stream
);
1342 EnterCriticalSection(&renderer
->cs
);
1343 if (renderer
->flags
& EVR_SHUT_DOWN
)
1349 for (i
= 0; i
< renderer
->stream_count
; ++i
)
1351 if (renderer
->streams
[i
]->id
== id
)
1355 if (i
== renderer
->stream_count
)
1356 hr
= MF_E_INVALIDSTREAMNUMBER
;
1359 *stream
= &renderer
->streams
[i
]->IMFStreamSink_iface
;
1360 IMFStreamSink_AddRef(*stream
);
1363 LeaveCriticalSection(&renderer
->cs
);
1368 static void video_renderer_set_presentation_clock(struct video_renderer
*renderer
, IMFPresentationClock
*clock
)
1370 if (renderer
->clock
)
1372 IMFPresentationClock_RemoveClockStateSink(renderer
->clock
, &renderer
->IMFClockStateSink_iface
);
1373 IMFPresentationClock_Release(renderer
->clock
);
1375 video_renderer_release_presenter_services(renderer
);
1377 renderer
->clock
= clock
;
1378 if (renderer
->clock
)
1380 IMFPresentationClock_AddRef(renderer
->clock
);
1381 IMFPresentationClock_AddClockStateSink(renderer
->clock
, &renderer
->IMFClockStateSink_iface
);
1383 video_renderer_init_presenter_services(renderer
);
1386 static HRESULT WINAPI
video_renderer_sink_SetPresentationClock(IMFMediaSink
*iface
, IMFPresentationClock
*clock
)
1388 struct video_renderer
*renderer
= impl_from_IMFMediaSink(iface
);
1391 TRACE("%p, %p.\n", iface
, clock
);
1393 EnterCriticalSection(&renderer
->cs
);
1395 if (renderer
->flags
& EVR_SHUT_DOWN
)
1398 video_renderer_set_presentation_clock(renderer
, clock
);
1400 LeaveCriticalSection(&renderer
->cs
);
1405 static HRESULT WINAPI
video_renderer_sink_GetPresentationClock(IMFMediaSink
*iface
, IMFPresentationClock
**clock
)
1407 struct video_renderer
*renderer
= impl_from_IMFMediaSink(iface
);
1410 TRACE("%p, %p.\n", iface
, clock
);
1415 EnterCriticalSection(&renderer
->cs
);
1417 if (renderer
->flags
& EVR_SHUT_DOWN
)
1419 else if (renderer
->clock
)
1421 *clock
= renderer
->clock
;
1422 IMFPresentationClock_AddRef(*clock
);
1427 LeaveCriticalSection(&renderer
->cs
);
1432 static HRESULT WINAPI
video_renderer_sink_Shutdown(IMFMediaSink
*iface
)
1434 struct video_renderer
*renderer
= impl_from_IMFMediaSink(iface
);
1438 TRACE("%p.\n", iface
);
1440 EnterCriticalSection(&renderer
->cs
);
1442 if (renderer
->flags
& EVR_SHUT_DOWN
)
1446 renderer
->flags
|= EVR_SHUT_DOWN
;
1447 /* Detach streams from the sink. */
1448 for (i
= 0; i
< renderer
->stream_count
; ++i
)
1450 struct video_stream
*stream
= renderer
->streams
[i
];
1452 EnterCriticalSection(&stream
->cs
);
1453 stream
->parent
= NULL
;
1454 LeaveCriticalSection(&stream
->cs
);
1456 IMFMediaEventQueue_Shutdown(stream
->event_queue
);
1457 IMFStreamSink_Release(&stream
->IMFStreamSink_iface
);
1458 IMFMediaSink_Release(iface
);
1459 renderer
->streams
[i
] = NULL
;
1461 free(renderer
->streams
);
1462 renderer
->stream_count
= 0;
1463 renderer
->stream_size
= 0;
1464 IMFMediaEventQueue_Shutdown(renderer
->event_queue
);
1465 video_renderer_set_presentation_clock(renderer
, NULL
);
1466 video_renderer_release_services(renderer
);
1469 LeaveCriticalSection(&renderer
->cs
);
1474 static const IMFMediaSinkVtbl video_renderer_sink_vtbl
=
1476 video_renderer_sink_QueryInterface
,
1477 video_renderer_sink_AddRef
,
1478 video_renderer_sink_Release
,
1479 video_renderer_sink_GetCharacteristics
,
1480 video_renderer_sink_AddStreamSink
,
1481 video_renderer_sink_RemoveStreamSink
,
1482 video_renderer_sink_GetStreamSinkCount
,
1483 video_renderer_sink_GetStreamSinkByIndex
,
1484 video_renderer_sink_GetStreamSinkById
,
1485 video_renderer_sink_SetPresentationClock
,
1486 video_renderer_sink_GetPresentationClock
,
1487 video_renderer_sink_Shutdown
,
1490 static HRESULT WINAPI
video_renderer_preroll_QueryInterface(IMFMediaSinkPreroll
*iface
, REFIID riid
, void **obj
)
1492 struct video_renderer
*renderer
= impl_from_IMFMediaSinkPreroll(iface
);
1493 return IMFMediaSink_QueryInterface(&renderer
->IMFMediaSink_iface
, riid
, obj
);
1496 static ULONG WINAPI
video_renderer_preroll_AddRef(IMFMediaSinkPreroll
*iface
)
1498 struct video_renderer
*renderer
= impl_from_IMFMediaSinkPreroll(iface
);
1499 return IMFMediaSink_AddRef(&renderer
->IMFMediaSink_iface
);
1502 static ULONG WINAPI
video_renderer_preroll_Release(IMFMediaSinkPreroll
*iface
)
1504 struct video_renderer
*renderer
= impl_from_IMFMediaSinkPreroll(iface
);
1505 return IMFMediaSink_Release(&renderer
->IMFMediaSink_iface
);
1508 static HRESULT WINAPI
video_renderer_preroll_NotifyPreroll(IMFMediaSinkPreroll
*iface
, MFTIME start_time
)
1510 struct video_renderer
*renderer
= impl_from_IMFMediaSinkPreroll(iface
);
1514 TRACE("%p, %s.\n", iface
, debugstr_time(start_time
));
1516 EnterCriticalSection(&renderer
->cs
);
1517 if (renderer
->flags
& EVR_SHUT_DOWN
)
1521 for (i
= 0; i
< renderer
->stream_count
; ++i
)
1523 struct video_stream
*stream
= renderer
->streams
[i
];
1525 EnterCriticalSection(&stream
->cs
);
1526 if (!(stream
->flags
& (EVR_STREAM_PREROLLING
| EVR_STREAM_PREROLLED
)))
1528 IMFMediaEventQueue_QueueEventParamVar(stream
->event_queue
, MEStreamSinkRequestSample
,
1529 &GUID_NULL
, S_OK
, NULL
);
1530 stream
->flags
|= EVR_STREAM_PREROLLING
;
1532 LeaveCriticalSection(&stream
->cs
);
1535 LeaveCriticalSection(&renderer
->cs
);
1540 static const IMFMediaSinkPrerollVtbl video_renderer_preroll_vtbl
=
1542 video_renderer_preroll_QueryInterface
,
1543 video_renderer_preroll_AddRef
,
1544 video_renderer_preroll_Release
,
1545 video_renderer_preroll_NotifyPreroll
,
1548 static HRESULT WINAPI
video_renderer_QueryInterface(IMFVideoRenderer
*iface
, REFIID riid
, void **obj
)
1550 struct video_renderer
*renderer
= impl_from_IMFVideoRenderer(iface
);
1551 return IMFMediaSink_QueryInterface(&renderer
->IMFMediaSink_iface
, riid
, obj
);
1554 static ULONG WINAPI
video_renderer_AddRef(IMFVideoRenderer
*iface
)
1556 struct video_renderer
*renderer
= impl_from_IMFVideoRenderer(iface
);
1557 return IMFMediaSink_AddRef(&renderer
->IMFMediaSink_iface
);
1560 static ULONG WINAPI
video_renderer_Release(IMFVideoRenderer
*iface
)
1562 struct video_renderer
*renderer
= impl_from_IMFVideoRenderer(iface
);
1563 return IMFMediaSink_Release(&renderer
->IMFMediaSink_iface
);
1566 static HRESULT
video_renderer_create_mixer(IMFAttributes
*attributes
, IMFTransform
**out
)
1568 unsigned int flags
= 0;
1569 IMFActivate
*activate
;
1573 if (attributes
&& SUCCEEDED(hr
= IMFAttributes_GetUnknown(attributes
, &MF_ACTIVATE_CUSTOM_VIDEO_MIXER_ACTIVATE
,
1574 &IID_IMFActivate
, (void **)&activate
)))
1576 IMFAttributes_GetUINT32(attributes
, &MF_ACTIVATE_CUSTOM_VIDEO_MIXER_FLAGS
, &flags
);
1577 hr
= IMFActivate_ActivateObject(activate
, &IID_IMFTransform
, (void **)out
);
1578 IMFActivate_Release(activate
);
1579 if (SUCCEEDED(hr
) || !(flags
& MF_ACTIVATE_CUSTOM_MIXER_ALLOWFAIL
))
1583 if (!attributes
|| FAILED(IMFAttributes_GetGUID(attributes
, &MF_ACTIVATE_CUSTOM_VIDEO_MIXER_CLSID
, &clsid
)))
1584 memcpy(&clsid
, &CLSID_MFVideoMixer9
, sizeof(clsid
));
1586 return CoCreateInstance(&clsid
, NULL
, CLSCTX_INPROC_SERVER
, &IID_IMFTransform
, (void **)out
);
1589 static HRESULT
video_renderer_create_presenter(struct video_renderer
*renderer
, IMFAttributes
*attributes
,
1590 IMFVideoPresenter
**out
)
1592 unsigned int flags
= 0;
1593 IMFActivate
*activate
;
1598 if (attributes
&& SUCCEEDED(IMFAttributes_GetUINT64(attributes
, &MF_ACTIVATE_VIDEO_WINDOW
, &value
)))
1599 renderer
->window
= UlongToHandle(value
);
1601 if (attributes
&& SUCCEEDED(IMFAttributes_GetUnknown(attributes
, &MF_ACTIVATE_CUSTOM_VIDEO_PRESENTER_ACTIVATE
,
1602 &IID_IMFActivate
, (void **)&activate
)))
1604 IMFAttributes_GetUINT32(attributes
, &MF_ACTIVATE_CUSTOM_VIDEO_PRESENTER_FLAGS
, &flags
);
1605 hr
= IMFActivate_ActivateObject(activate
, &IID_IMFVideoPresenter
, (void **)out
);
1606 IMFActivate_Release(activate
);
1607 if (SUCCEEDED(hr
) || !(flags
& MF_ACTIVATE_CUSTOM_PRESENTER_ALLOWFAIL
))
1611 if (!attributes
|| FAILED(IMFAttributes_GetGUID(attributes
, &MF_ACTIVATE_CUSTOM_VIDEO_PRESENTER_CLSID
, &clsid
)))
1612 memcpy(&clsid
, &CLSID_MFVideoPresenter9
, sizeof(clsid
));
1614 return CoCreateInstance(&clsid
, NULL
, CLSCTX_INPROC_SERVER
, &IID_IMFVideoPresenter
, (void **)out
);
1617 static HRESULT
video_renderer_get_device_manager(struct video_renderer
*renderer
, IUnknown
**device_manager
)
1619 return MFGetService((IUnknown
*)renderer
->presenter
, &MR_VIDEO_RENDER_SERVICE
,
1620 &IID_IDirect3DDeviceManager9
, (void **)device_manager
);
1623 static HRESULT
video_renderer_configure_mixer(struct video_renderer
*renderer
)
1625 IMFTopologyServiceLookupClient
*lookup_client
;
1628 if (SUCCEEDED(hr
= IMFTransform_QueryInterface(renderer
->mixer
, &IID_IMFTopologyServiceLookupClient
,
1629 (void **)&lookup_client
)))
1631 renderer
->flags
|= EVR_INIT_SERVICES
;
1632 if (SUCCEEDED(hr
= IMFTopologyServiceLookupClient_InitServicePointers(lookup_client
,
1633 &renderer
->IMFTopologyServiceLookup_iface
)))
1635 renderer
->flags
|= EVR_MIXER_INITED_SERVICES
;
1637 renderer
->flags
&= ~EVR_INIT_SERVICES
;
1638 IMFTopologyServiceLookupClient_Release(lookup_client
);
1643 DWORD input_count
, output_count
;
1647 /* Create stream sinks for inputs that mixer already has by default. */
1648 if (SUCCEEDED(IMFTransform_GetStreamCount(renderer
->mixer
, &input_count
, &output_count
)))
1650 ids
= calloc(input_count
, sizeof(*ids
));
1651 oids
= calloc(output_count
, sizeof(*oids
));
1655 if (SUCCEEDED(IMFTransform_GetStreamIDs(renderer
->mixer
, input_count
, ids
, output_count
, oids
)))
1657 for (i
= 0; i
< input_count
; ++i
)
1659 video_renderer_add_stream(renderer
, ids
[i
], NULL
);
1670 /* Set device manager that presenter should have created. */
1671 if (video_renderer_is_mixer_d3d_aware(renderer
))
1673 IUnknown
*device_manager
;
1675 if (SUCCEEDED(video_renderer_get_device_manager(renderer
, &device_manager
)))
1677 IMFTransform_ProcessMessage(renderer
->mixer
, MFT_MESSAGE_SET_D3D_MANAGER
, (ULONG_PTR
)device_manager
);
1678 IUnknown_Release(device_manager
);
1685 static HRESULT
video_renderer_configure_presenter(struct video_renderer
*renderer
)
1687 IMFVideoDisplayControl
*control
;
1691 if (SUCCEEDED(IMFVideoPresenter_QueryInterface(renderer
->presenter
, &IID_IMFVideoDisplayControl
, (void **)&control
)))
1693 GetClientRect(renderer
->window
, &rect
);
1695 if (SUCCEEDED(hr
= IMFVideoDisplayControl_SetVideoWindow(control
, renderer
->window
)))
1696 hr
= IMFVideoDisplayControl_SetVideoPosition(control
, NULL
, &rect
);
1697 IMFVideoDisplayControl_Release(control
);
1700 hr
= video_renderer_init_presenter_services(renderer
);
1702 if (FAILED(video_renderer_get_device_manager(renderer
, &renderer
->device_manager
)))
1704 WARN("Failed to get device manager from the presenter.\n");
1710 static void video_renderer_uninitialize(struct video_renderer
*renderer
)
1712 video_renderer_release_services(renderer
);
1714 if (renderer
->mixer
)
1716 IMFTransform_Release(renderer
->mixer
);
1717 renderer
->mixer
= NULL
;
1720 if (renderer
->presenter
)
1722 IMFVideoPresenter_Release(renderer
->presenter
);
1723 renderer
->presenter
= NULL
;
1726 if (renderer
->device_manager
)
1728 IUnknown_Release(renderer
->device_manager
);
1729 renderer
->device_manager
= NULL
;
1733 static HRESULT
video_renderer_initialize(struct video_renderer
*renderer
, IMFTransform
*mixer
,
1734 IMFVideoPresenter
*presenter
)
1738 renderer
->mixer
= mixer
;
1739 IMFTransform_AddRef(renderer
->mixer
);
1741 renderer
->presenter
= presenter
;
1742 IMFVideoPresenter_AddRef(renderer
->presenter
);
1744 if (SUCCEEDED(hr
= video_renderer_configure_mixer(renderer
)))
1745 hr
= video_renderer_configure_presenter(renderer
);
1750 static HRESULT
video_renderer_create_mixer_and_presenter(struct video_renderer
*renderer
,
1751 IMFTransform
**mixer
, IMFVideoPresenter
**presenter
)
1757 IMFTransform_AddRef(*mixer
);
1759 else if (FAILED(hr
= video_renderer_create_mixer(NULL
, mixer
)))
1761 WARN("Failed to create default mixer object, hr %#lx.\n", hr
);
1767 IMFVideoPresenter_AddRef(*presenter
);
1769 else if (FAILED(hr
= video_renderer_create_presenter(renderer
, NULL
, presenter
)))
1771 WARN("Failed to create default presenter, hr %#lx.\n", hr
);
1772 IMFTransform_Release(*mixer
);
1779 static HRESULT WINAPI
video_renderer_InitializeRenderer(IMFVideoRenderer
*iface
, IMFTransform
*mixer
,
1780 IMFVideoPresenter
*presenter
)
1782 struct video_renderer
*renderer
= impl_from_IMFVideoRenderer(iface
);
1785 TRACE("%p, %p, %p.\n", iface
, mixer
, presenter
);
1787 EnterCriticalSection(&renderer
->cs
);
1789 if (renderer
->flags
& EVR_SHUT_DOWN
)
1793 video_renderer_uninitialize(renderer
);
1795 if (SUCCEEDED(hr
= video_renderer_create_mixer_and_presenter(renderer
, &mixer
, &presenter
)))
1797 /* FIXME: check clock state */
1798 /* FIXME: check that streams are not initialized */
1800 hr
= video_renderer_initialize(renderer
, mixer
, presenter
);
1802 IMFTransform_Release(mixer
);
1803 IMFVideoPresenter_Release(presenter
);
1807 LeaveCriticalSection(&renderer
->cs
);
1812 static const IMFVideoRendererVtbl video_renderer_vtbl
=
1814 video_renderer_QueryInterface
,
1815 video_renderer_AddRef
,
1816 video_renderer_Release
,
1817 video_renderer_InitializeRenderer
,
1820 static HRESULT WINAPI
video_renderer_events_QueryInterface(IMFMediaEventGenerator
*iface
, REFIID riid
, void **obj
)
1822 struct video_renderer
*renderer
= impl_from_IMFMediaEventGenerator(iface
);
1823 return IMFMediaSink_QueryInterface(&renderer
->IMFMediaSink_iface
, riid
, obj
);
1826 static ULONG WINAPI
video_renderer_events_AddRef(IMFMediaEventGenerator
*iface
)
1828 struct video_renderer
*renderer
= impl_from_IMFMediaEventGenerator(iface
);
1829 return IMFMediaSink_AddRef(&renderer
->IMFMediaSink_iface
);
1832 static ULONG WINAPI
video_renderer_events_Release(IMFMediaEventGenerator
*iface
)
1834 struct video_renderer
*renderer
= impl_from_IMFMediaEventGenerator(iface
);
1835 return IMFMediaSink_Release(&renderer
->IMFMediaSink_iface
);
1838 static HRESULT WINAPI
video_renderer_events_GetEvent(IMFMediaEventGenerator
*iface
, DWORD flags
, IMFMediaEvent
**event
)
1840 struct video_renderer
*renderer
= impl_from_IMFMediaEventGenerator(iface
);
1842 TRACE("%p, %#lx, %p.\n", iface
, flags
, event
);
1844 return IMFMediaEventQueue_GetEvent(renderer
->event_queue
, flags
, event
);
1847 static HRESULT WINAPI
video_renderer_events_BeginGetEvent(IMFMediaEventGenerator
*iface
, IMFAsyncCallback
*callback
,
1850 struct video_renderer
*renderer
= impl_from_IMFMediaEventGenerator(iface
);
1852 TRACE("%p, %p, %p.\n", iface
, callback
, state
);
1854 return IMFMediaEventQueue_BeginGetEvent(renderer
->event_queue
, callback
, state
);
1857 static HRESULT WINAPI
video_renderer_events_EndGetEvent(IMFMediaEventGenerator
*iface
, IMFAsyncResult
*result
,
1858 IMFMediaEvent
**event
)
1860 struct video_renderer
*renderer
= impl_from_IMFMediaEventGenerator(iface
);
1862 TRACE("%p, %p, %p.\n", iface
, result
, event
);
1864 return IMFMediaEventQueue_EndGetEvent(renderer
->event_queue
, result
, event
);
1867 static HRESULT WINAPI
video_renderer_events_QueueEvent(IMFMediaEventGenerator
*iface
, MediaEventType event_type
,
1868 REFGUID ext_type
, HRESULT hr
, const PROPVARIANT
*value
)
1870 struct video_renderer
*renderer
= impl_from_IMFMediaEventGenerator(iface
);
1872 TRACE("%p, %lu, %s, %#lx, %p.\n", iface
, event_type
, debugstr_guid(ext_type
), hr
, value
);
1874 return IMFMediaEventQueue_QueueEventParamVar(renderer
->event_queue
, event_type
, ext_type
, hr
, value
);
1877 static const IMFMediaEventGeneratorVtbl video_renderer_events_vtbl
=
1879 video_renderer_events_QueryInterface
,
1880 video_renderer_events_AddRef
,
1881 video_renderer_events_Release
,
1882 video_renderer_events_GetEvent
,
1883 video_renderer_events_BeginGetEvent
,
1884 video_renderer_events_EndGetEvent
,
1885 video_renderer_events_QueueEvent
,
1888 static HRESULT WINAPI
video_renderer_clock_sink_QueryInterface(IMFClockStateSink
*iface
, REFIID riid
, void **obj
)
1890 struct video_renderer
*renderer
= impl_from_IMFClockStateSink(iface
);
1891 return IMFMediaSink_QueryInterface(&renderer
->IMFMediaSink_iface
, riid
, obj
);
1894 static ULONG WINAPI
video_renderer_clock_sink_AddRef(IMFClockStateSink
*iface
)
1896 struct video_renderer
*renderer
= impl_from_IMFClockStateSink(iface
);
1897 return IMFMediaSink_AddRef(&renderer
->IMFMediaSink_iface
);
1900 static ULONG WINAPI
video_renderer_clock_sink_Release(IMFClockStateSink
*iface
)
1902 struct video_renderer
*renderer
= impl_from_IMFClockStateSink(iface
);
1903 return IMFMediaSink_Release(&renderer
->IMFMediaSink_iface
);
1906 static HRESULT WINAPI
video_renderer_clock_sink_OnClockStart(IMFClockStateSink
*iface
, MFTIME systime
, LONGLONG offset
)
1908 struct video_renderer
*renderer
= impl_from_IMFClockStateSink(iface
);
1909 unsigned int state
, request_sample
;
1912 TRACE("%p, %s, %s.\n", iface
, debugstr_time(systime
), debugstr_time(offset
));
1914 EnterCriticalSection(&renderer
->cs
);
1916 state
= renderer
->state
;
1918 /* Update sink state before sending sample requests, to avoid potentially receiving new sample in stopped state */
1919 renderer
->state
= EVR_STATE_RUNNING
;
1921 if (state
== EVR_STATE_STOPPED
)
1923 IMFTransform_ProcessMessage(renderer
->mixer
, MFT_MESSAGE_NOTIFY_BEGIN_STREAMING
, 0);
1924 IMFVideoPresenter_ProcessMessage(renderer
->presenter
, MFVP_MESSAGE_BEGINSTREAMING
, 0);
1926 for (i
= 0; i
< renderer
->stream_count
; ++i
)
1928 struct video_stream
*stream
= renderer
->streams
[i
];
1930 EnterCriticalSection(&stream
->cs
);
1931 request_sample
= !(stream
->flags
& EVR_STREAM_PREROLLED
) || (stream
->flags
& EVR_STREAM_SAMPLE_NEEDED
);
1932 stream
->flags
|= EVR_STREAM_PREROLLED
;
1933 stream
->flags
&= ~EVR_STREAM_SAMPLE_NEEDED
;
1934 LeaveCriticalSection(&stream
->cs
);
1936 IMFMediaEventQueue_QueueEventParamVar(stream
->event_queue
, MEStreamSinkStarted
, &GUID_NULL
, S_OK
, NULL
);
1938 IMFMediaEventQueue_QueueEventParamVar(stream
->event_queue
, MEStreamSinkRequestSample
,
1939 &GUID_NULL
, S_OK
, NULL
);
1943 IMFVideoPresenter_OnClockStart(renderer
->presenter
, systime
, offset
);
1945 LeaveCriticalSection(&renderer
->cs
);
1950 static HRESULT WINAPI
video_renderer_clock_sink_OnClockStop(IMFClockStateSink
*iface
, MFTIME systime
)
1952 struct video_renderer
*renderer
= impl_from_IMFClockStateSink(iface
);
1955 TRACE("%p, %s.\n", iface
, debugstr_time(systime
));
1957 EnterCriticalSection(&renderer
->cs
);
1959 IMFVideoPresenter_OnClockStop(renderer
->presenter
, systime
);
1961 IMFTransform_ProcessMessage(renderer
->mixer
, MFT_MESSAGE_COMMAND_FLUSH
, 0);
1962 IMFVideoPresenter_ProcessMessage(renderer
->presenter
, MFVP_MESSAGE_FLUSH
, 0);
1964 if (renderer
->state
== EVR_STATE_RUNNING
||
1965 renderer
->state
== EVR_STATE_PAUSED
)
1967 IMFTransform_ProcessMessage(renderer
->mixer
, MFT_MESSAGE_NOTIFY_END_STREAMING
, 0);
1968 IMFVideoPresenter_ProcessMessage(renderer
->presenter
, MFVP_MESSAGE_ENDSTREAMING
, 0);
1970 for (i
= 0; i
< renderer
->stream_count
; ++i
)
1972 struct video_stream
*stream
= renderer
->streams
[i
];
1973 IMFMediaEventQueue_QueueEventParamVar(stream
->event_queue
, MEStreamSinkStopped
, &GUID_NULL
, S_OK
, NULL
);
1975 EnterCriticalSection(&stream
->cs
);
1976 stream
->flags
&= ~(EVR_STREAM_PREROLLED
| EVR_STREAM_SAMPLE_NEEDED
);
1977 LeaveCriticalSection(&stream
->cs
);
1979 renderer
->state
= EVR_STATE_STOPPED
;
1982 LeaveCriticalSection(&renderer
->cs
);
1987 static HRESULT WINAPI
video_renderer_clock_sink_OnClockPause(IMFClockStateSink
*iface
, MFTIME systime
)
1989 struct video_renderer
*renderer
= impl_from_IMFClockStateSink(iface
);
1992 TRACE("%p, %s.\n", iface
, debugstr_time(systime
));
1994 EnterCriticalSection(&renderer
->cs
);
1996 IMFVideoPresenter_OnClockPause(renderer
->presenter
, systime
);
1998 if (renderer
->state
== EVR_STATE_RUNNING
)
2000 for (i
= 0; i
< renderer
->stream_count
; ++i
)
2002 struct video_stream
*stream
= renderer
->streams
[i
];
2003 IMFMediaEventQueue_QueueEventParamVar(stream
->event_queue
, MEStreamSinkPaused
, &GUID_NULL
, S_OK
, NULL
);
2007 renderer
->state
= EVR_STATE_PAUSED
;
2009 LeaveCriticalSection(&renderer
->cs
);
2014 static HRESULT WINAPI
video_renderer_clock_sink_OnClockRestart(IMFClockStateSink
*iface
, MFTIME systime
)
2016 struct video_renderer
*renderer
= impl_from_IMFClockStateSink(iface
);
2019 TRACE("%p, %s.\n", iface
, debugstr_time(systime
));
2021 EnterCriticalSection(&renderer
->cs
);
2023 IMFVideoPresenter_OnClockRestart(renderer
->presenter
, systime
);
2025 for (i
= 0; i
< renderer
->stream_count
; ++i
)
2027 struct video_stream
*stream
= renderer
->streams
[i
];
2028 IMFMediaEventQueue_QueueEventParamVar(stream
->event_queue
, MEStreamSinkStarted
, &GUID_NULL
, S_OK
, NULL
);
2030 renderer
->state
= EVR_STATE_RUNNING
;
2032 LeaveCriticalSection(&renderer
->cs
);
2037 static HRESULT WINAPI
video_renderer_clock_sink_OnClockSetRate(IMFClockStateSink
*iface
, MFTIME systime
, float rate
)
2039 struct video_renderer
*renderer
= impl_from_IMFClockStateSink(iface
);
2040 IMFClockStateSink
*sink
;
2042 TRACE("%p, %s, %f.\n", iface
, debugstr_time(systime
), rate
);
2044 EnterCriticalSection(&renderer
->cs
);
2046 IMFVideoPresenter_OnClockSetRate(renderer
->presenter
, systime
, rate
);
2047 if (SUCCEEDED(IMFTransform_QueryInterface(renderer
->mixer
, &IID_IMFClockStateSink
, (void **)&sink
)))
2049 IMFClockStateSink_OnClockSetRate(sink
, systime
, rate
);
2050 IMFClockStateSink_Release(sink
);
2053 LeaveCriticalSection(&renderer
->cs
);
2058 static const IMFClockStateSinkVtbl video_renderer_clock_sink_vtbl
=
2060 video_renderer_clock_sink_QueryInterface
,
2061 video_renderer_clock_sink_AddRef
,
2062 video_renderer_clock_sink_Release
,
2063 video_renderer_clock_sink_OnClockStart
,
2064 video_renderer_clock_sink_OnClockStop
,
2065 video_renderer_clock_sink_OnClockPause
,
2066 video_renderer_clock_sink_OnClockRestart
,
2067 video_renderer_clock_sink_OnClockSetRate
,
2070 static HRESULT WINAPI
video_renderer_get_service_QueryInterface(IMFGetService
*iface
, REFIID riid
, void **obj
)
2072 struct video_renderer
*renderer
= impl_from_IMFGetService(iface
);
2073 return IMFMediaSink_QueryInterface(&renderer
->IMFMediaSink_iface
, riid
, obj
);
2076 static ULONG WINAPI
video_renderer_get_service_AddRef(IMFGetService
*iface
)
2078 struct video_renderer
*renderer
= impl_from_IMFGetService(iface
);
2079 return IMFMediaSink_AddRef(&renderer
->IMFMediaSink_iface
);
2082 static ULONG WINAPI
video_renderer_get_service_Release(IMFGetService
*iface
)
2084 struct video_renderer
*renderer
= impl_from_IMFGetService(iface
);
2085 return IMFMediaSink_Release(&renderer
->IMFMediaSink_iface
);
2088 static HRESULT WINAPI
video_renderer_get_service_GetService(IMFGetService
*iface
, REFGUID service
, REFIID riid
, void **obj
)
2090 struct video_renderer
*renderer
= impl_from_IMFGetService(iface
);
2091 HRESULT hr
= E_NOINTERFACE
;
2092 IMFGetService
*gs
= NULL
;
2094 TRACE("%p, %s, %s, %p.\n", iface
, debugstr_guid(service
), debugstr_guid(riid
), obj
);
2096 EnterCriticalSection(&renderer
->cs
);
2098 if (IsEqualGUID(service
, &MR_VIDEO_MIXER_SERVICE
))
2100 hr
= IMFTransform_QueryInterface(renderer
->mixer
, &IID_IMFGetService
, (void **)&gs
);
2102 else if (IsEqualGUID(service
, &MR_VIDEO_RENDER_SERVICE
))
2104 hr
= IMFVideoPresenter_QueryInterface(renderer
->presenter
, &IID_IMFGetService
, (void **)&gs
);
2106 else if (IsEqualGUID(service
, &MR_VIDEO_ACCELERATION_SERVICE
) && IsEqualIID(riid
, &IID_IDirect3DDeviceManager9
))
2108 if (renderer
->device_manager
)
2109 hr
= IUnknown_QueryInterface(renderer
->device_manager
, riid
, obj
);
2111 else if (IsEqualGUID(service
, &MF_RATE_CONTROL_SERVICE
) && IsEqualIID(riid
, &IID_IMFRateSupport
))
2113 hr
= IMFVideoRenderer_QueryInterface(&renderer
->IMFVideoRenderer_iface
, riid
, obj
);
2117 FIXME("Unsupported service %s.\n", debugstr_guid(service
));
2120 LeaveCriticalSection(&renderer
->cs
);
2124 hr
= IMFGetService_GetService(gs
, service
, riid
, obj
);
2125 IMFGetService_Release(gs
);
2131 static const IMFGetServiceVtbl video_renderer_get_service_vtbl
=
2133 video_renderer_get_service_QueryInterface
,
2134 video_renderer_get_service_AddRef
,
2135 video_renderer_get_service_Release
,
2136 video_renderer_get_service_GetService
,
2139 static HRESULT WINAPI
video_renderer_service_lookup_QueryInterface(IMFTopologyServiceLookup
*iface
, REFIID riid
, void **obj
)
2141 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(riid
), obj
);
2143 if (IsEqualIID(riid
, &IID_IMFTopologyServiceLookup
) ||
2144 IsEqualIID(riid
, &IID_IUnknown
))
2147 IMFTopologyServiceLookup_AddRef(iface
);
2151 WARN("Unsupported interface %s.\n", debugstr_guid(riid
));
2153 return E_NOINTERFACE
;
2156 static ULONG WINAPI
video_renderer_service_lookup_AddRef(IMFTopologyServiceLookup
*iface
)
2158 struct video_renderer
*renderer
= impl_from_IMFTopologyServiceLookup(iface
);
2159 return IMFMediaSink_AddRef(&renderer
->IMFMediaSink_iface
);
2162 static ULONG WINAPI
video_renderer_service_lookup_Release(IMFTopologyServiceLookup
*iface
)
2164 struct video_renderer
*renderer
= impl_from_IMFTopologyServiceLookup(iface
);
2165 return IMFMediaSink_Release(&renderer
->IMFMediaSink_iface
);
2168 static HRESULT WINAPI
video_renderer_service_lookup_LookupService(IMFTopologyServiceLookup
*iface
,
2169 MF_SERVICE_LOOKUP_TYPE lookup_type
, DWORD index
, REFGUID service
, REFIID riid
,
2170 void **objects
, DWORD
*num_objects
)
2172 struct video_renderer
*renderer
= impl_from_IMFTopologyServiceLookup(iface
);
2175 TRACE("%p, %u, %lu, %s, %s, %p, %p.\n", iface
, lookup_type
, index
, debugstr_guid(service
), debugstr_guid(riid
),
2176 objects
, num_objects
);
2178 EnterCriticalSection(&renderer
->cs
);
2180 if (!(renderer
->flags
& EVR_INIT_SERVICES
))
2181 hr
= MF_E_NOTACCEPTING
;
2182 else if (IsEqualGUID(service
, &MR_VIDEO_RENDER_SERVICE
))
2184 if (IsEqualIID(riid
, &IID_IMediaEventSink
))
2186 *objects
= &renderer
->IMediaEventSink_iface
;
2187 IUnknown_AddRef((IUnknown
*)*objects
);
2189 else if (IsEqualIID(riid
, &IID_IMFClock
))
2191 *objects
= renderer
->clock
;
2193 IUnknown_AddRef((IUnknown
*)*objects
);
2194 hr
= *objects
? S_OK
: E_NOINTERFACE
;
2198 FIXME("Unsupported interface %s for render service.\n", debugstr_guid(riid
));
2202 else if (IsEqualGUID(service
, &MR_VIDEO_MIXER_SERVICE
))
2204 if (IsEqualIID(riid
, &IID_IMFTransform
))
2206 *objects
= renderer
->mixer
;
2207 IUnknown_AddRef((IUnknown
*)*objects
);
2211 FIXME("Unsupported interface %s for mixer service.\n", debugstr_guid(riid
));
2217 WARN("Unsupported service %s.\n", debugstr_guid(service
));
2218 hr
= MF_E_UNSUPPORTED_SERVICE
;
2221 LeaveCriticalSection(&renderer
->cs
);
2226 static const IMFTopologyServiceLookupVtbl video_renderer_service_lookup_vtbl
=
2228 video_renderer_service_lookup_QueryInterface
,
2229 video_renderer_service_lookup_AddRef
,
2230 video_renderer_service_lookup_Release
,
2231 video_renderer_service_lookup_LookupService
,
2234 static HRESULT WINAPI
video_renderer_event_sink_QueryInterface(IMediaEventSink
*iface
, REFIID riid
, void **obj
)
2236 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(riid
), obj
);
2238 if (IsEqualIID(riid
, &IID_IMediaEventSink
) ||
2239 IsEqualIID(riid
, &IID_IUnknown
))
2242 IMediaEventSink_AddRef(iface
);
2246 WARN("Unsupported interface %s.\n", debugstr_guid(riid
));
2248 return E_NOINTERFACE
;
2251 static ULONG WINAPI
video_renderer_event_sink_AddRef(IMediaEventSink
*iface
)
2253 struct video_renderer
*renderer
= impl_from_IMediaEventSink(iface
);
2254 return IMFMediaSink_AddRef(&renderer
->IMFMediaSink_iface
);
2257 static ULONG WINAPI
video_renderer_event_sink_Release(IMediaEventSink
*iface
)
2259 struct video_renderer
*renderer
= impl_from_IMediaEventSink(iface
);
2260 return IMFMediaSink_Release(&renderer
->IMFMediaSink_iface
);
2263 static HRESULT WINAPI
video_renderer_event_sink_Notify(IMediaEventSink
*iface
, LONG event
, LONG_PTR param1
, LONG_PTR param2
)
2265 struct video_renderer
*renderer
= impl_from_IMediaEventSink(iface
);
2269 TRACE("%p, %ld, %Id, %Id.\n", iface
, event
, param1
, param2
);
2271 EnterCriticalSection(&renderer
->cs
);
2273 if (event
== EC_SAMPLE_NEEDED
)
2276 if (idx
>= renderer
->stream_count
)
2277 hr
= MF_E_INVALIDSTREAMNUMBER
;
2278 else if (renderer
->state
== EVR_STATE_RUNNING
)
2280 hr
= IMFMediaEventQueue_QueueEventParamVar(renderer
->streams
[idx
]->event_queue
,
2281 MEStreamSinkRequestSample
, &GUID_NULL
, S_OK
, NULL
);
2285 /* Mixer asks for more input right after preroll too, before renderer finished running state transition.
2286 Mark such streams here, and issue requests later in OnClockStart(). */
2287 renderer
->streams
[idx
]->flags
|= EVR_STREAM_SAMPLE_NEEDED
;
2290 else if (event
== EC_DISPLAY_CHANGED
)
2292 for (idx
= 0; idx
< renderer
->stream_count
; ++idx
)
2293 IMFMediaEventQueue_QueueEventParamVar(renderer
->streams
[idx
]->event_queue
,
2294 MEStreamSinkDeviceChanged
, &GUID_NULL
, S_OK
, NULL
);
2296 else if (event
>= EC_USER
)
2302 hr
= IMFMediaEventQueue_QueueEventParamVar(renderer
->event_queue
, MERendererEvent
,
2303 &GUID_NULL
, S_OK
, &code
);
2307 WARN("Unhandled event %ld.\n", event
);
2308 hr
= MF_E_UNEXPECTED
;
2311 LeaveCriticalSection(&renderer
->cs
);
2316 static const IMediaEventSinkVtbl media_event_sink_vtbl
=
2318 video_renderer_event_sink_QueryInterface
,
2319 video_renderer_event_sink_AddRef
,
2320 video_renderer_event_sink_Release
,
2321 video_renderer_event_sink_Notify
,
2324 static HRESULT WINAPI
video_renderer_attributes_QueryInterface(IMFAttributes
*iface
, REFIID riid
, void **obj
)
2326 struct video_renderer
*renderer
= impl_from_IMFAttributes(iface
);
2327 return IMFMediaSink_QueryInterface(&renderer
->IMFMediaSink_iface
, riid
, obj
);
2330 static ULONG WINAPI
video_renderer_attributes_AddRef(IMFAttributes
*iface
)
2332 struct video_renderer
*renderer
= impl_from_IMFAttributes(iface
);
2333 return IMFMediaSink_AddRef(&renderer
->IMFMediaSink_iface
);
2336 static ULONG WINAPI
video_renderer_attributes_Release(IMFAttributes
*iface
)
2338 struct video_renderer
*renderer
= impl_from_IMFAttributes(iface
);
2339 return IMFMediaSink_Release(&renderer
->IMFMediaSink_iface
);
2342 static HRESULT WINAPI
video_renderer_attributes_GetItem(IMFAttributes
*iface
, REFGUID key
, PROPVARIANT
*value
)
2344 struct video_renderer
*renderer
= impl_from_IMFAttributes(iface
);
2346 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(key
), value
);
2348 return IMFAttributes_GetItem(renderer
->attributes
, key
, value
);
2351 static HRESULT WINAPI
video_renderer_attributes_GetItemType(IMFAttributes
*iface
, REFGUID key
, MF_ATTRIBUTE_TYPE
*type
)
2353 struct video_renderer
*renderer
= impl_from_IMFAttributes(iface
);
2355 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(key
), type
);
2357 return IMFAttributes_GetItemType(renderer
->attributes
, key
, type
);
2360 static HRESULT WINAPI
video_renderer_attributes_CompareItem(IMFAttributes
*iface
, REFGUID key
, REFPROPVARIANT value
,
2363 struct video_renderer
*renderer
= impl_from_IMFAttributes(iface
);
2365 TRACE("%p, %s, %p, %p.\n", iface
, debugstr_guid(key
), value
, result
);
2367 return IMFAttributes_CompareItem(renderer
->attributes
, key
, value
, result
);
2370 static HRESULT WINAPI
video_renderer_attributes_Compare(IMFAttributes
*iface
, IMFAttributes
*theirs
,
2371 MF_ATTRIBUTES_MATCH_TYPE type
, BOOL
*result
)
2373 struct video_renderer
*renderer
= impl_from_IMFAttributes(iface
);
2375 TRACE("%p, %p, %d, %p.\n", iface
, theirs
, type
, result
);
2377 return IMFAttributes_Compare(renderer
->attributes
, theirs
, type
, result
);
2380 static HRESULT WINAPI
video_renderer_attributes_GetUINT32(IMFAttributes
*iface
, REFGUID key
, UINT32
*value
)
2382 struct video_renderer
*renderer
= impl_from_IMFAttributes(iface
);
2384 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(key
), value
);
2386 return IMFAttributes_GetUINT32(renderer
->attributes
, key
, value
);
2389 static HRESULT WINAPI
video_renderer_attributes_GetUINT64(IMFAttributes
*iface
, REFGUID key
, UINT64
*value
)
2391 struct video_renderer
*renderer
= impl_from_IMFAttributes(iface
);
2393 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(key
), value
);
2395 return IMFAttributes_GetUINT64(renderer
->attributes
, key
, value
);
2398 static HRESULT WINAPI
video_renderer_attributes_GetDouble(IMFAttributes
*iface
, REFGUID key
, double *value
)
2400 struct video_renderer
*renderer
= impl_from_IMFAttributes(iface
);
2402 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(key
), value
);
2404 return IMFAttributes_GetDouble(renderer
->attributes
, key
, value
);
2407 static HRESULT WINAPI
video_renderer_attributes_GetGUID(IMFAttributes
*iface
, REFGUID key
, GUID
*value
)
2409 struct video_renderer
*renderer
= impl_from_IMFAttributes(iface
);
2411 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(key
), value
);
2413 return IMFAttributes_GetGUID(renderer
->attributes
, key
, value
);
2416 static HRESULT WINAPI
video_renderer_attributes_GetStringLength(IMFAttributes
*iface
, REFGUID key
,
2419 struct video_renderer
*renderer
= impl_from_IMFAttributes(iface
);
2421 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(key
), length
);
2423 return IMFAttributes_GetStringLength(renderer
->attributes
, key
, length
);
2426 static HRESULT WINAPI
video_renderer_attributes_GetString(IMFAttributes
*iface
, REFGUID key
, WCHAR
*value
,
2427 UINT32 size
, UINT32
*length
)
2429 struct video_renderer
*renderer
= impl_from_IMFAttributes(iface
);
2431 TRACE("%p, %s, %p, %u, %p.\n", iface
, debugstr_guid(key
), value
, size
, length
);
2433 return IMFAttributes_GetString(renderer
->attributes
, key
, value
, size
, length
);
2436 static HRESULT WINAPI
video_renderer_attributes_GetAllocatedString(IMFAttributes
*iface
, REFGUID key
,
2437 WCHAR
**value
, UINT32
*length
)
2439 struct video_renderer
*renderer
= impl_from_IMFAttributes(iface
);
2441 TRACE("%p, %s, %p, %p.\n", iface
, debugstr_guid(key
), value
, length
);
2443 return IMFAttributes_GetAllocatedString(renderer
->attributes
, key
, value
, length
);
2446 static HRESULT WINAPI
video_renderer_attributes_GetBlobSize(IMFAttributes
*iface
, REFGUID key
, UINT32
*size
)
2448 struct video_renderer
*renderer
= impl_from_IMFAttributes(iface
);
2450 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(key
), size
);
2452 return IMFAttributes_GetBlobSize(renderer
->attributes
, key
, size
);
2455 static HRESULT WINAPI
video_renderer_attributes_GetBlob(IMFAttributes
*iface
, REFGUID key
, UINT8
*buf
,
2456 UINT32 bufsize
, UINT32
*blobsize
)
2458 struct video_renderer
*renderer
= impl_from_IMFAttributes(iface
);
2460 TRACE("%p, %s, %p, %u, %p.\n", iface
, debugstr_guid(key
), buf
, bufsize
, blobsize
);
2462 return IMFAttributes_GetBlob(renderer
->attributes
, key
, buf
, bufsize
, blobsize
);
2465 static HRESULT WINAPI
video_renderer_attributes_GetAllocatedBlob(IMFAttributes
*iface
, REFGUID key
,
2466 UINT8
**buf
, UINT32
*size
)
2468 struct video_renderer
*renderer
= impl_from_IMFAttributes(iface
);
2470 TRACE("%p, %s, %p, %p.\n", iface
, debugstr_guid(key
), buf
, size
);
2472 return IMFAttributes_GetAllocatedBlob(renderer
->attributes
, key
, buf
, size
);
2475 static HRESULT WINAPI
video_renderer_attributes_GetUnknown(IMFAttributes
*iface
, REFGUID key
, REFIID riid
, void **out
)
2477 struct video_renderer
*renderer
= impl_from_IMFAttributes(iface
);
2479 TRACE("%p, %s, %s, %p.\n", iface
, debugstr_guid(key
), debugstr_guid(riid
), out
);
2481 return IMFAttributes_GetUnknown(renderer
->attributes
, key
, riid
, out
);
2484 static HRESULT WINAPI
video_renderer_attributes_SetItem(IMFAttributes
*iface
, REFGUID key
, REFPROPVARIANT value
)
2486 struct video_renderer
*renderer
= impl_from_IMFAttributes(iface
);
2488 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(key
), value
);
2490 return IMFAttributes_SetItem(renderer
->attributes
, key
, value
);
2493 static HRESULT WINAPI
video_renderer_attributes_DeleteItem(IMFAttributes
*iface
, REFGUID key
)
2495 struct video_renderer
*renderer
= impl_from_IMFAttributes(iface
);
2497 TRACE("%p, %s.\n", iface
, debugstr_guid(key
));
2499 return IMFAttributes_DeleteItem(renderer
->attributes
, key
);
2502 static HRESULT WINAPI
video_renderer_attributes_DeleteAllItems(IMFAttributes
*iface
)
2504 struct video_renderer
*renderer
= impl_from_IMFAttributes(iface
);
2506 TRACE("%p.\n", iface
);
2508 return IMFAttributes_DeleteAllItems(renderer
->attributes
);
2511 static HRESULT WINAPI
video_renderer_attributes_SetUINT32(IMFAttributes
*iface
, REFGUID key
, UINT32 value
)
2513 struct video_renderer
*renderer
= impl_from_IMFAttributes(iface
);
2515 TRACE("%p, %s, %u.\n", iface
, debugstr_guid(key
), value
);
2517 return IMFAttributes_SetUINT32(renderer
->attributes
, key
, value
);
2520 static HRESULT WINAPI
video_renderer_attributes_SetUINT64(IMFAttributes
*iface
, REFGUID key
, UINT64 value
)
2522 struct video_renderer
*renderer
= impl_from_IMFAttributes(iface
);
2524 TRACE("%p, %s, %s.\n", iface
, debugstr_guid(key
), wine_dbgstr_longlong(value
));
2526 return IMFAttributes_SetUINT64(renderer
->attributes
, key
, value
);
2529 static HRESULT WINAPI
video_renderer_attributes_SetDouble(IMFAttributes
*iface
, REFGUID key
, double value
)
2531 struct video_renderer
*renderer
= impl_from_IMFAttributes(iface
);
2533 TRACE("%p, %s, %f.\n", iface
, debugstr_guid(key
), value
);
2535 return IMFAttributes_SetDouble(renderer
->attributes
, key
, value
);
2538 static HRESULT WINAPI
video_renderer_attributes_SetGUID(IMFAttributes
*iface
, REFGUID key
, REFGUID value
)
2540 struct video_renderer
*renderer
= impl_from_IMFAttributes(iface
);
2542 TRACE("%p, %s, %s.\n", iface
, debugstr_guid(key
), debugstr_guid(value
));
2544 return IMFAttributes_SetGUID(renderer
->attributes
, key
, value
);
2547 static HRESULT WINAPI
video_renderer_attributes_SetString(IMFAttributes
*iface
, REFGUID key
,
2550 struct video_renderer
*renderer
= impl_from_IMFAttributes(iface
);
2552 TRACE("%p, %s, %s.\n", iface
, debugstr_guid(key
), debugstr_w(value
));
2554 return IMFAttributes_SetString(renderer
->attributes
, key
, value
);
2557 static HRESULT WINAPI
video_renderer_attributes_SetBlob(IMFAttributes
*iface
, REFGUID key
,
2558 const UINT8
*buf
, UINT32 size
)
2560 struct video_renderer
*renderer
= impl_from_IMFAttributes(iface
);
2562 TRACE("%p, %s, %p, %u.\n", iface
, debugstr_guid(key
), buf
, size
);
2564 return IMFAttributes_SetBlob(renderer
->attributes
, key
, buf
, size
);
2567 static HRESULT WINAPI
video_renderer_attributes_SetUnknown(IMFAttributes
*iface
, REFGUID key
,
2570 struct video_renderer
*renderer
= impl_from_IMFAttributes(iface
);
2572 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(key
), unknown
);
2574 return IMFAttributes_SetUnknown(renderer
->attributes
, key
, unknown
);
2577 static HRESULT WINAPI
video_renderer_attributes_LockStore(IMFAttributes
*iface
)
2579 struct video_renderer
*renderer
= impl_from_IMFAttributes(iface
);
2581 TRACE("%p.\n", iface
);
2583 return IMFAttributes_LockStore(renderer
->attributes
);
2586 static HRESULT WINAPI
video_renderer_attributes_UnlockStore(IMFAttributes
*iface
)
2588 struct video_renderer
*renderer
= impl_from_IMFAttributes(iface
);
2590 TRACE("%p.\n", iface
);
2592 return IMFAttributes_UnlockStore(renderer
->attributes
);
2595 static HRESULT WINAPI
video_renderer_attributes_GetCount(IMFAttributes
*iface
, UINT32
*count
)
2597 struct video_renderer
*renderer
= impl_from_IMFAttributes(iface
);
2599 TRACE("%p, %p.\n", iface
, count
);
2601 return IMFAttributes_GetCount(renderer
->attributes
, count
);
2604 static HRESULT WINAPI
video_renderer_attributes_GetItemByIndex(IMFAttributes
*iface
, UINT32 index
,
2605 GUID
*key
, PROPVARIANT
*value
)
2607 struct video_renderer
*renderer
= impl_from_IMFAttributes(iface
);
2609 TRACE("%p, %u, %p, %p.\n", iface
, index
, key
, value
);
2611 return IMFAttributes_GetItemByIndex(renderer
->attributes
, index
, key
, value
);
2614 static HRESULT WINAPI
video_renderer_attributes_CopyAllItems(IMFAttributes
*iface
, IMFAttributes
*dest
)
2616 struct video_renderer
*renderer
= impl_from_IMFAttributes(iface
);
2618 TRACE("%p, %p.\n", iface
, dest
);
2620 return IMFAttributes_CopyAllItems(renderer
->attributes
, dest
);
2623 static const IMFAttributesVtbl video_renderer_attributes_vtbl
=
2625 video_renderer_attributes_QueryInterface
,
2626 video_renderer_attributes_AddRef
,
2627 video_renderer_attributes_Release
,
2628 video_renderer_attributes_GetItem
,
2629 video_renderer_attributes_GetItemType
,
2630 video_renderer_attributes_CompareItem
,
2631 video_renderer_attributes_Compare
,
2632 video_renderer_attributes_GetUINT32
,
2633 video_renderer_attributes_GetUINT64
,
2634 video_renderer_attributes_GetDouble
,
2635 video_renderer_attributes_GetGUID
,
2636 video_renderer_attributes_GetStringLength
,
2637 video_renderer_attributes_GetString
,
2638 video_renderer_attributes_GetAllocatedString
,
2639 video_renderer_attributes_GetBlobSize
,
2640 video_renderer_attributes_GetBlob
,
2641 video_renderer_attributes_GetAllocatedBlob
,
2642 video_renderer_attributes_GetUnknown
,
2643 video_renderer_attributes_SetItem
,
2644 video_renderer_attributes_DeleteItem
,
2645 video_renderer_attributes_DeleteAllItems
,
2646 video_renderer_attributes_SetUINT32
,
2647 video_renderer_attributes_SetUINT64
,
2648 video_renderer_attributes_SetDouble
,
2649 video_renderer_attributes_SetGUID
,
2650 video_renderer_attributes_SetString
,
2651 video_renderer_attributes_SetBlob
,
2652 video_renderer_attributes_SetUnknown
,
2653 video_renderer_attributes_LockStore
,
2654 video_renderer_attributes_UnlockStore
,
2655 video_renderer_attributes_GetCount
,
2656 video_renderer_attributes_GetItemByIndex
,
2657 video_renderer_attributes_CopyAllItems
,
2660 static HRESULT WINAPI
video_renderer_quality_advise_QueryInterface(IMFQualityAdvise
*iface
, REFIID riid
, void **out
)
2662 struct video_renderer
*renderer
= impl_from_IMFQualityAdvise(iface
);
2663 return IMFMediaSink_QueryInterface(&renderer
->IMFMediaSink_iface
, riid
, out
);
2666 static ULONG WINAPI
video_renderer_quality_advise_AddRef(IMFQualityAdvise
*iface
)
2668 struct video_renderer
*renderer
= impl_from_IMFQualityAdvise(iface
);
2669 return IMFMediaSink_AddRef(&renderer
->IMFMediaSink_iface
);
2672 static ULONG WINAPI
video_renderer_quality_Release(IMFQualityAdvise
*iface
)
2674 struct video_renderer
*renderer
= impl_from_IMFQualityAdvise(iface
);
2675 return IMFMediaSink_Release(&renderer
->IMFMediaSink_iface
);
2678 static HRESULT WINAPI
video_renderer_quality_advise_SetDropMode(IMFQualityAdvise
*iface
,
2679 MF_QUALITY_DROP_MODE mode
)
2681 FIXME("%p, %u.\n", iface
, mode
);
2686 static HRESULT WINAPI
video_renderer_quality_advise_SetQualityLevel(IMFQualityAdvise
*iface
,
2687 MF_QUALITY_LEVEL level
)
2689 FIXME("%p, %u.\n", iface
, level
);
2694 static HRESULT WINAPI
video_renderer_quality_advise_GetDropMode(IMFQualityAdvise
*iface
,
2695 MF_QUALITY_DROP_MODE
*mode
)
2697 FIXME("%p, %p.\n", iface
, mode
);
2702 static HRESULT WINAPI
video_renderer_quality_advise_GetQualityLevel(IMFQualityAdvise
*iface
,
2703 MF_QUALITY_LEVEL
*level
)
2705 FIXME("%p, %p.\n", iface
, level
);
2710 static HRESULT WINAPI
video_renderer_quality_advise_DropTime(IMFQualityAdvise
*iface
, LONGLONG interval
)
2712 FIXME("%p, %s.\n", iface
, wine_dbgstr_longlong(interval
));
2717 static const IMFQualityAdviseVtbl video_renderer_quality_advise_vtbl
=
2719 video_renderer_quality_advise_QueryInterface
,
2720 video_renderer_quality_advise_AddRef
,
2721 video_renderer_quality_Release
,
2722 video_renderer_quality_advise_SetDropMode
,
2723 video_renderer_quality_advise_SetQualityLevel
,
2724 video_renderer_quality_advise_GetDropMode
,
2725 video_renderer_quality_advise_GetQualityLevel
,
2726 video_renderer_quality_advise_DropTime
,
2729 static HRESULT WINAPI
video_renderer_rate_support_QueryInterface(IMFRateSupport
*iface
, REFIID riid
, void **out
)
2731 struct video_renderer
*renderer
= impl_from_IMFRateSupport(iface
);
2732 return IMFMediaSink_QueryInterface(&renderer
->IMFMediaSink_iface
, riid
, out
);
2735 static ULONG WINAPI
video_renderer_rate_support_AddRef(IMFRateSupport
*iface
)
2737 struct video_renderer
*renderer
= impl_from_IMFRateSupport(iface
);
2738 return IMFMediaSink_AddRef(&renderer
->IMFMediaSink_iface
);
2741 static ULONG WINAPI
video_renderer_rate_support_Release(IMFRateSupport
*iface
)
2743 struct video_renderer
*renderer
= impl_from_IMFRateSupport(iface
);
2744 return IMFMediaSink_Release(&renderer
->IMFMediaSink_iface
);
2747 static BOOL
video_renderer_is_main_stream_configured(const struct video_renderer
*renderer
)
2749 IMFMediaType
*media_type
;
2752 if (SUCCEEDED(hr
= IMFTransform_GetInputCurrentType(renderer
->mixer
, 0, &media_type
)))
2753 IMFMediaType_Release(media_type
);
2755 return SUCCEEDED(hr
);
2758 static HRESULT WINAPI
video_renderer_rate_support_GetSlowestRate(IMFRateSupport
*iface
, MFRATE_DIRECTION direction
,
2759 BOOL thin
, float *rate
)
2761 struct video_renderer
*renderer
= impl_from_IMFRateSupport(iface
);
2764 TRACE("%p, %d, %d, %p.\n", iface
, direction
, thin
, rate
);
2766 EnterCriticalSection(&renderer
->cs
);
2767 if (renderer
->flags
& EVR_SHUT_DOWN
)
2775 LeaveCriticalSection(&renderer
->cs
);
2780 static HRESULT WINAPI
video_renderer_rate_support_GetFastestRate(IMFRateSupport
*iface
, MFRATE_DIRECTION direction
,
2781 BOOL thin
, float *rate
)
2783 struct video_renderer
*renderer
= impl_from_IMFRateSupport(iface
);
2786 TRACE("%p, %d, %d, %p.\n", iface
, direction
, thin
, rate
);
2788 EnterCriticalSection(&renderer
->cs
);
2789 if (renderer
->flags
& EVR_SHUT_DOWN
)
2793 else if (video_renderer_is_main_stream_configured(renderer
))
2795 *rate
= direction
== MFRATE_FORWARD
? FLT_MAX
: -FLT_MAX
;
2798 hr
= MF_E_INVALIDREQUEST
;
2799 LeaveCriticalSection(&renderer
->cs
);
2804 static HRESULT WINAPI
video_renderer_rate_support_IsRateSupported(IMFRateSupport
*iface
, BOOL thin
, float rate
,
2805 float *nearest_rate
)
2807 struct video_renderer
*renderer
= impl_from_IMFRateSupport(iface
);
2810 TRACE("%p, %d, %f, %p.\n", iface
, thin
, rate
, nearest_rate
);
2812 EnterCriticalSection(&renderer
->cs
);
2813 if (renderer
->flags
& EVR_SHUT_DOWN
)
2817 if (!thin
&& !video_renderer_is_main_stream_configured(renderer
))
2818 hr
= MF_E_INVALIDREQUEST
;
2821 *nearest_rate
= rate
;
2823 LeaveCriticalSection(&renderer
->cs
);
2828 static const IMFRateSupportVtbl video_renderer_rate_support_vtbl
=
2830 video_renderer_rate_support_QueryInterface
,
2831 video_renderer_rate_support_AddRef
,
2832 video_renderer_rate_support_Release
,
2833 video_renderer_rate_support_GetSlowestRate
,
2834 video_renderer_rate_support_GetFastestRate
,
2835 video_renderer_rate_support_IsRateSupported
,
2838 static HRESULT
evr_create_object(IMFAttributes
*attributes
, void *user_context
, IUnknown
**obj
)
2840 struct video_renderer
*object
;
2841 IMFVideoPresenter
*presenter
= NULL
;
2842 IMFTransform
*mixer
= NULL
;
2845 TRACE("%p, %p, %p.\n", attributes
, user_context
, obj
);
2847 if (!(object
= calloc(1, sizeof(*object
))))
2848 return E_OUTOFMEMORY
;
2850 object
->IMFMediaSink_iface
.lpVtbl
= &video_renderer_sink_vtbl
;
2851 object
->IMFMediaSinkPreroll_iface
.lpVtbl
= &video_renderer_preroll_vtbl
;
2852 object
->IMFVideoRenderer_iface
.lpVtbl
= &video_renderer_vtbl
;
2853 object
->IMFMediaEventGenerator_iface
.lpVtbl
= &video_renderer_events_vtbl
;
2854 object
->IMFClockStateSink_iface
.lpVtbl
= &video_renderer_clock_sink_vtbl
;
2855 object
->IMFGetService_iface
.lpVtbl
= &video_renderer_get_service_vtbl
;
2856 object
->IMFTopologyServiceLookup_iface
.lpVtbl
= &video_renderer_service_lookup_vtbl
;
2857 object
->IMediaEventSink_iface
.lpVtbl
= &media_event_sink_vtbl
;
2858 object
->IMFAttributes_iface
.lpVtbl
= &video_renderer_attributes_vtbl
;
2859 object
->IMFQualityAdvise_iface
.lpVtbl
= &video_renderer_quality_advise_vtbl
;
2860 object
->IMFRateSupport_iface
.lpVtbl
= &video_renderer_rate_support_vtbl
;
2861 object
->refcount
= 1;
2862 InitializeCriticalSection(&object
->cs
);
2864 if (FAILED(hr
= MFCreateEventQueue(&object
->event_queue
)))
2867 if (FAILED(hr
= MFCreateAttributes(&object
->attributes
, 0)))
2870 /* Create mixer and presenter. */
2871 if (FAILED(hr
= video_renderer_create_mixer(attributes
, &mixer
)))
2874 if (FAILED(hr
= video_renderer_create_presenter(object
, attributes
, &presenter
)))
2877 if (FAILED(hr
= video_renderer_initialize(object
, mixer
, presenter
)))
2880 IMFTransform_Release(mixer
);
2881 IMFVideoPresenter_Release(presenter
);
2883 /* Default attributes */
2884 IMFAttributes_SetUINT32(object
->attributes
, &EVRConfig_ForceBob
, 0);
2885 IMFAttributes_SetUINT32(object
->attributes
, &EVRConfig_AllowDropToBob
, 0);
2886 IMFAttributes_SetUINT32(object
->attributes
, &EVRConfig_ForceThrottle
, 0);
2887 IMFAttributes_SetUINT32(object
->attributes
, &EVRConfig_AllowDropToThrottle
, 0);
2888 IMFAttributes_SetUINT32(object
->attributes
, &EVRConfig_ForceHalfInterlace
, 0);
2889 IMFAttributes_SetUINT32(object
->attributes
, &EVRConfig_AllowDropToHalfInterlace
, 0);
2890 IMFAttributes_SetUINT32(object
->attributes
, &EVRConfig_ForceScaling
, 0);
2891 IMFAttributes_SetUINT32(object
->attributes
, &EVRConfig_AllowScaling
, 0);
2892 IMFAttributes_SetUINT32(object
->attributes
, &EVRConfig_ForceBatching
, 0);
2893 IMFAttributes_SetUINT32(object
->attributes
, &EVRConfig_AllowBatching
, 0);
2895 *obj
= (IUnknown
*)&object
->IMFMediaSink_iface
;
2902 IMFTransform_Release(mixer
);
2905 IMFVideoPresenter_Release(presenter
);
2907 video_renderer_release_services(object
);
2908 IMFMediaSink_Release(&object
->IMFMediaSink_iface
);
2913 static void evr_shutdown_object(void *user_context
, IUnknown
*obj
)
2917 if (SUCCEEDED(IUnknown_QueryInterface(obj
, &IID_IMFMediaSink
, (void **)&sink
)))
2919 IMFMediaSink_Shutdown(sink
);
2920 IMFMediaSink_Release(sink
);
2924 static const struct activate_funcs evr_activate_funcs
=
2926 .create_object
= evr_create_object
,
2927 .shutdown_object
= evr_shutdown_object
,
2930 /***********************************************************************
2931 * MFCreateVideoRendererActivate (mf.@)
2933 HRESULT WINAPI
MFCreateVideoRendererActivate(HWND hwnd
, IMFActivate
**activate
)
2937 TRACE("%p, %p.\n", hwnd
, activate
);
2942 hr
= create_activation_object(NULL
, &evr_activate_funcs
, activate
);
2944 IMFActivate_SetUINT64(*activate
, &MF_ACTIVATE_VIDEO_WINDOW
, (ULONG_PTR
)hwnd
);
2949 /***********************************************************************
2950 * MFCreateVideoRenderer (mf.@)
2952 HRESULT WINAPI
MFCreateVideoRenderer(REFIID riid
, void **renderer
)
2957 TRACE("%s, %p.\n", debugstr_guid(riid
), renderer
);
2961 if (SUCCEEDED(hr
= evr_create_object(NULL
, NULL
, &obj
)))
2963 hr
= IUnknown_QueryInterface(obj
, riid
, renderer
);
2964 IUnknown_Release(obj
);