Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/mf/tests/mf.c | 11 +++++++++++ 1 file changed, 11 insertions(+)
diff --git a/dlls/mf/tests/mf.c b/dlls/mf/tests/mf.c index 465bd7e3c43..7dc325424a6 100644 --- a/dlls/mf/tests/mf.c +++ b/dlls/mf/tests/mf.c @@ -39,6 +39,7 @@ DEFINE_GUID(MFVideoFormat_ABGR32, 0x00000020, 0x0000, 0x0010, 0x80, 0x00, 0x00, #include "mferror.h" #include "mfidl.h" #include "initguid.h" +#include "uuids.h" #include "mmdeviceapi.h" #include "audioclient.h" #include "evr.h" @@ -3237,6 +3238,7 @@ static void test_evr(void) { IMFVideoSampleAllocatorCallback *allocator_callback; IMFStreamSink *stream_sink, *stream_sink2; + IMFVideoDisplayControl *display_control; IMFMediaType *media_type, *media_type2; IMFMediaEventGenerator *ev_generator; IMFVideoSampleAllocator *allocator; @@ -3292,6 +3294,15 @@ static void test_evr(void) hr = IMFAttributes_GetCount(attributes, &count); ok(hr == S_OK, "Unexpected hr %#x.\n", hr); ok(!!count, "Unexpected count %u.\n", count); + /* Rendering preferences are not immediately propagated to the presenter. */ + hr = IMFAttributes_SetUINT32(attributes, &EVRConfig_ForceBob, 1); + ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + hr = MFGetService((IUnknown *)sink, &MR_VIDEO_RENDER_SERVICE, &IID_IMFVideoDisplayControl, (void **)&display_control); + ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + hr = IMFVideoDisplayControl_GetRenderingPrefs(display_control, &flags); + ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + ok(!flags, "Unexpected flags %#x.\n", flags); + IMFVideoDisplayControl_Release(display_control); IMFAttributes_Release(attributes);
/* Primary stream type handler. */
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/mf/evr.c | 37 ++++++++++++++++++++++++------------- 1 file changed, 24 insertions(+), 13 deletions(-)
diff --git a/dlls/mf/evr.c b/dlls/mf/evr.c index af9bd9e0e42..ac80193ddd6 100644 --- a/dlls/mf/evr.c +++ b/dlls/mf/evr.c @@ -47,6 +47,7 @@ struct video_stream struct video_renderer *parent; IMFMediaEventQueue *event_queue; IMFVideoSampleAllocator *allocator; + CRITICAL_SECTION cs; };
struct video_renderer @@ -213,6 +214,7 @@ static ULONG WINAPI video_stream_sink_Release(IMFStreamSink *iface) IMFMediaEventQueue_Release(stream->event_queue); if (stream->allocator) IMFVideoSampleAllocator_Release(stream->allocator); + DeleteCriticalSection(&stream->cs); heap_free(stream); }
@@ -260,20 +262,23 @@ static HRESULT WINAPI video_stream_sink_QueueEvent(IMFStreamSink *iface, MediaEv static HRESULT WINAPI video_stream_sink_GetMediaSink(IMFStreamSink *iface, IMFMediaSink **sink) { struct video_stream *stream = impl_from_IMFStreamSink(iface); + HRESULT hr = S_OK;
TRACE("%p, %p.\n", iface, sink);
+ EnterCriticalSection(&stream->cs); if (!stream->parent) - return MF_E_STREAMSINK_REMOVED; - - if (!sink) - return E_POINTER; - - /* FIXME: not entirely safe if sink is being shut down. */ - *sink = &stream->parent->IMFMediaSink_iface; - IMFMediaSink_AddRef(*sink); + hr = MF_E_STREAMSINK_REMOVED; + else if (!sink) + hr = E_POINTER; + else + { + *sink = &stream->parent->IMFMediaSink_iface; + IMFMediaSink_AddRef(*sink); + } + LeaveCriticalSection(&stream->cs);
- return S_OK; + return hr; }
static HRESULT WINAPI video_stream_sink_GetIdentifier(IMFStreamSink *iface, DWORD *id) @@ -533,6 +538,7 @@ static HRESULT video_renderer_stream_create(struct video_renderer *renderer, uns stream->IMFMediaTypeHandler_iface.lpVtbl = &video_stream_type_handler_vtbl; stream->IMFGetService_iface.lpVtbl = &video_stream_get_service_vtbl; stream->refcount = 1; + InitializeCriticalSection(&stream->cs);
if (FAILED(hr = MFCreateEventQueue(&stream->event_queue))) goto failed; @@ -894,10 +900,15 @@ static HRESULT WINAPI video_renderer_sink_Shutdown(IMFMediaSink *iface) /* Detach streams from the sink. */ for (i = 0; i < renderer->stream_count; ++i) { - IMFMediaSink_Release(&renderer->streams[i]->parent->IMFMediaSink_iface); - renderer->streams[i]->parent = NULL; - IMFMediaEventQueue_Shutdown(renderer->streams[i]->event_queue); - IMFStreamSink_Release(&renderer->streams[i]->IMFStreamSink_iface); + struct video_stream *stream = renderer->streams[i]; + + EnterCriticalSection(&stream->cs); + stream->parent = NULL; + LeaveCriticalSection(&stream->cs); + + IMFMediaEventQueue_Shutdown(stream->event_queue); + IMFStreamSink_Release(&stream->IMFStreamSink_iface); + IMFMediaSink_Release(iface); renderer->streams[i] = NULL; } heap_free(renderer->streams);
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/mf/evr.c | 47 +++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 45 insertions(+), 2 deletions(-)
diff --git a/dlls/mf/evr.c b/dlls/mf/evr.c index ac80193ddd6..0cd13c25501 100644 --- a/dlls/mf/evr.c +++ b/dlls/mf/evr.c @@ -35,6 +35,12 @@ enum video_renderer_flags EVR_PRESENTER_INITED_SERVICES = 0x8, };
+enum video_stream_flags +{ + EVR_STREAM_PREROLLING = 0x1, + EVR_STREAM_PREROLLED = 0x2, +}; + struct video_renderer;
struct video_stream @@ -44,6 +50,7 @@ struct video_stream IMFGetService IMFGetService_iface; LONG refcount; unsigned int id; + unsigned int flags; struct video_renderer *parent; IMFMediaEventQueue *event_queue; IMFVideoSampleAllocator *allocator; @@ -318,8 +325,19 @@ static HRESULT WINAPI video_stream_sink_GetMediaTypeHandler(IMFStreamSink *iface
static HRESULT WINAPI video_stream_sink_ProcessSample(IMFStreamSink *iface, IMFSample *sample) { + struct video_stream *stream = impl_from_IMFStreamSink(iface); + FIXME("%p, %p.\n", iface, sample);
+ EnterCriticalSection(&stream->cs); + if (stream->flags & EVR_STREAM_PREROLLING) + { + IMFMediaEventQueue_QueueEventParamVar(stream->event_queue, MEStreamSinkPrerolled, &GUID_NULL, S_OK, NULL); + stream->flags &= ~EVR_STREAM_PREROLLING; + stream->flags |= EVR_STREAM_PREROLLED; + } + LeaveCriticalSection(&stream->cs); + return E_NOTIMPL; }
@@ -958,9 +976,34 @@ static ULONG WINAPI video_renderer_preroll_Release(IMFMediaSinkPreroll *iface)
static HRESULT WINAPI video_renderer_preroll_NotifyPreroll(IMFMediaSinkPreroll *iface, MFTIME start_time) { - FIXME("%p, %s.\n", iface, debugstr_time(start_time)); + struct video_renderer *renderer = impl_from_IMFMediaSinkPreroll(iface); + HRESULT hr = S_OK; + size_t i;
- return E_NOTIMPL; + TRACE("%p, %s.\n", iface, debugstr_time(start_time)); + + EnterCriticalSection(&renderer->cs); + if (renderer->flags & EVR_SHUT_DOWN) + hr = MF_E_SHUTDOWN; + else + { + for (i = 0; i < renderer->stream_count; ++i) + { + struct video_stream *stream = renderer->streams[i]; + + EnterCriticalSection(&stream->cs); + if (!(stream->flags & (EVR_STREAM_PREROLLING | EVR_STREAM_PREROLLED))) + { + IMFMediaEventQueue_QueueEventParamVar(stream->event_queue, MEStreamSinkRequestSample, + &GUID_NULL, S_OK, NULL); + stream->flags |= EVR_STREAM_PREROLLING; + } + LeaveCriticalSection(&stream->cs); + } + } + LeaveCriticalSection(&renderer->cs); + + return hr; }
static const IMFMediaSinkPrerollVtbl video_renderer_preroll_vtbl =
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/mf/evr.c | 92 ++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 84 insertions(+), 8 deletions(-)
diff --git a/dlls/mf/evr.c b/dlls/mf/evr.c index 0cd13c25501..957d0e0f797 100644 --- a/dlls/mf/evr.c +++ b/dlls/mf/evr.c @@ -35,6 +35,13 @@ enum video_renderer_flags EVR_PRESENTER_INITED_SERVICES = 0x8, };
+enum video_renderer_state +{ + EVR_STATE_STOPPED = 0, + EVR_STATE_RUNNING, + EVR_STATE_PAUSED, +}; + enum video_stream_flags { EVR_STREAM_PREROLLING = 0x1, @@ -77,6 +84,7 @@ struct video_renderer IMFTransform *mixer; IMFVideoPresenter *presenter; unsigned int flags; + unsigned int state;
struct video_stream **streams; size_t stream_size; @@ -1338,30 +1346,98 @@ static ULONG WINAPI video_renderer_clock_sink_Release(IMFClockStateSink *iface)
static HRESULT WINAPI video_renderer_clock_sink_OnClockStart(IMFClockStateSink *iface, MFTIME systime, LONGLONG offset) { - FIXME("%p, %s, %s.\n", iface, debugstr_time(systime), debugstr_time(offset)); + struct video_renderer *renderer = impl_from_IMFClockStateSink(iface); + size_t i;
- return E_NOTIMPL; + TRACE("%p, %s, %s.\n", iface, debugstr_time(systime), debugstr_time(offset)); + + EnterCriticalSection(&renderer->cs); + + for (i = 0; i < renderer->stream_count; ++i) + { + struct video_stream *stream = renderer->streams[i]; + + IMFMediaEventQueue_QueueEventParamVar(stream->event_queue, MEStreamSinkStarted, &GUID_NULL, S_OK, NULL); + + EnterCriticalSection(&stream->cs); + if (!(stream->flags & EVR_STREAM_PREROLLED)) + IMFMediaEventQueue_QueueEventParamVar(stream->event_queue, MEStreamSinkRequestSample, + &GUID_NULL, S_OK, NULL); + stream->flags |= EVR_STREAM_PREROLLED; + LeaveCriticalSection(&stream->cs); + } + renderer->state = EVR_STATE_RUNNING; + + LeaveCriticalSection(&renderer->cs); + + return S_OK; }
static HRESULT WINAPI video_renderer_clock_sink_OnClockStop(IMFClockStateSink *iface, MFTIME systime) { - FIXME("%p, %s.\n", iface, debugstr_time(systime)); + struct video_renderer *renderer = impl_from_IMFClockStateSink(iface); + size_t i;
- return E_NOTIMPL; + TRACE("%p, %s.\n", iface, debugstr_time(systime)); + + EnterCriticalSection(&renderer->cs); + + for (i = 0; i < renderer->stream_count; ++i) + { + struct video_stream *stream = renderer->streams[i]; + IMFMediaEventQueue_QueueEventParamVar(stream->event_queue, MEStreamSinkStopped, &GUID_NULL, S_OK, NULL); + + EnterCriticalSection(&stream->cs); + stream->flags &= ~EVR_STREAM_PREROLLED; + LeaveCriticalSection(&stream->cs); + } + renderer->state = EVR_STATE_STOPPED; + + LeaveCriticalSection(&renderer->cs); + + return S_OK; }
static HRESULT WINAPI video_renderer_clock_sink_OnClockPause(IMFClockStateSink *iface, MFTIME systime) { - FIXME("%p, %s.\n", iface, debugstr_time(systime)); + struct video_renderer *renderer = impl_from_IMFClockStateSink(iface); + size_t i;
- return E_NOTIMPL; + TRACE("%p, %s.\n", iface, debugstr_time(systime)); + + EnterCriticalSection(&renderer->cs); + + for (i = 0; i < renderer->stream_count; ++i) + { + struct video_stream *stream = renderer->streams[i]; + IMFMediaEventQueue_QueueEventParamVar(stream->event_queue, MEStreamSinkPaused, &GUID_NULL, S_OK, NULL); + } + renderer->state = EVR_STATE_PAUSED; + + LeaveCriticalSection(&renderer->cs); + + return S_OK; }
static HRESULT WINAPI video_renderer_clock_sink_OnClockRestart(IMFClockStateSink *iface, MFTIME systime) { - FIXME("%p, %s.\n", iface, debugstr_time(systime)); + struct video_renderer *renderer = impl_from_IMFClockStateSink(iface); + size_t i;
- return E_NOTIMPL; + TRACE("%p, %s.\n", iface, debugstr_time(systime)); + + EnterCriticalSection(&renderer->cs); + + for (i = 0; i < renderer->stream_count; ++i) + { + struct video_stream *stream = renderer->streams[i]; + IMFMediaEventQueue_QueueEventParamVar(stream->event_queue, MEStreamSinkStarted, &GUID_NULL, S_OK, NULL); + } + renderer->state = EVR_STATE_RUNNING; + + LeaveCriticalSection(&renderer->cs); + + return S_OK; }
static HRESULT WINAPI video_renderer_clock_sink_OnClockSetRate(IMFClockStateSink *iface, MFTIME systime, float rate)