Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/mf/evr.c | 39 +++++++++++++++++++++++++++++++-------- dlls/mf/tests/mf.c | 4 ++++ 2 files changed, 35 insertions(+), 8 deletions(-)
diff --git a/dlls/mf/evr.c b/dlls/mf/evr.c index 79e2f57f9c5..8b4a9c03b5f 100644 --- a/dlls/mf/evr.c +++ b/dlls/mf/evr.c @@ -591,19 +591,14 @@ static ULONG WINAPI video_stream_get_service_Release(IMFGetService *iface) return IMFStreamSink_Release(&stream->IMFStreamSink_iface); }
-static HRESULT WINAPI video_stream_get_service_GetService(IMFGetService *iface, REFGUID service, REFIID riid, void **obj) +static HRESULT WINAPI video_stream_get_service(struct video_stream *stream, REFGUID service, REFIID riid, void **obj) { - struct video_stream *stream = impl_from_stream_IMFGetService(iface); HRESULT hr = S_OK;
- TRACE("%p, %s, %s, %p.\n", iface, debugstr_guid(service), debugstr_guid(riid), obj); - if (IsEqualGUID(service, &MR_VIDEO_ACCELERATION_SERVICE)) { if (IsEqualIID(riid, &IID_IMFVideoSampleAllocator)) { - EnterCriticalSection(&stream->cs); - if (!stream->allocator) { hr = MFCreateVideoSampleAllocator(&IID_IMFVideoSampleAllocator, (void **)&stream->allocator); @@ -613,10 +608,12 @@ static HRESULT WINAPI video_stream_get_service_GetService(IMFGetService *iface, if (SUCCEEDED(hr)) hr = IMFVideoSampleAllocator_QueryInterface(stream->allocator, riid, obj);
- LeaveCriticalSection(&stream->cs); - return hr; } + else if (IsEqualIID(riid, &IID_IDirect3DDeviceManager9) && stream->parent->device_manager) + { + return IUnknown_QueryInterface(stream->parent->device_manager, riid, obj); + }
return E_NOINTERFACE; } @@ -626,6 +623,23 @@ static HRESULT WINAPI video_stream_get_service_GetService(IMFGetService *iface, return E_NOTIMPL; }
+static HRESULT WINAPI video_stream_get_service_GetService(IMFGetService *iface, REFGUID service, REFIID riid, void **obj) +{ + struct video_stream *stream = impl_from_stream_IMFGetService(iface); + HRESULT hr; + + TRACE("%p, %s, %s, %p.\n", iface, debugstr_guid(service), debugstr_guid(riid), obj); + + EnterCriticalSection(&stream->cs); + if (!stream->parent) + hr = MF_E_STREAMSINK_REMOVED; + else + hr = video_stream_get_service(stream, service, riid, obj); + LeaveCriticalSection(&stream->cs); + + return hr; +} + static const IMFGetServiceVtbl video_stream_get_service_vtbl = { video_stream_get_service_QueryInterface, @@ -1992,6 +2006,8 @@ static HRESULT WINAPI video_renderer_get_service_GetService(IMFGetService *iface
TRACE("%p, %s, %s, %p.\n", iface, debugstr_guid(service), debugstr_guid(riid), obj);
+ EnterCriticalSection(&renderer->cs); + if (IsEqualGUID(service, &MR_VIDEO_MIXER_SERVICE)) { hr = IMFTransform_QueryInterface(renderer->mixer, &IID_IMFGetService, (void **)&gs); @@ -2000,11 +2016,18 @@ static HRESULT WINAPI video_renderer_get_service_GetService(IMFGetService *iface { hr = IMFVideoPresenter_QueryInterface(renderer->presenter, &IID_IMFGetService, (void **)&gs); } + else if (IsEqualGUID(service, &MR_VIDEO_ACCELERATION_SERVICE) && IsEqualIID(riid, &IID_IDirect3DDeviceManager9)) + { + if (renderer->device_manager) + hr = IUnknown_QueryInterface(renderer->device_manager, riid, obj); + } else { FIXME("Unsupported service %s.\n", debugstr_guid(service)); }
+ LeaveCriticalSection(&renderer->cs); + if (gs) { hr = IMFGetService_GetService(gs, service, riid, obj); diff --git a/dlls/mf/tests/mf.c b/dlls/mf/tests/mf.c index b990b4614da..39b9d64e729 100644 --- a/dlls/mf/tests/mf.c +++ b/dlls/mf/tests/mf.c @@ -4269,6 +4269,7 @@ static void test_evr(void) check_service_interface(sink, &MR_VIDEO_MIXER_SERVICE, &IID_IMFVideoMixerControl2, TRUE); check_service_interface(sink, &MR_VIDEO_RENDER_SERVICE, &IID_IMFVideoDisplayControl, TRUE); check_service_interface(sink, &MR_VIDEO_RENDER_SERVICE, &IID_IMFVideoPositionMapper, TRUE); + check_service_interface(sink, &MR_VIDEO_ACCELERATION_SERVICE, &IID_IDirect3DDeviceManager9, TRUE);
hr = MFGetService((IUnknown *)sink, &MR_VIDEO_RENDER_SERVICE, &IID_IMFVideoDisplayControl, (void **)&display_control); @@ -4415,6 +4416,9 @@ static void test_evr(void) IMFMediaTypeHandler_Release(type_handler);
/* Stream uses an allocator. */ + check_service_interface(stream_sink, &MR_VIDEO_ACCELERATION_SERVICE, &IID_IMFVideoSampleAllocator, TRUE); + check_service_interface(stream_sink, &MR_VIDEO_ACCELERATION_SERVICE, &IID_IDirect3DDeviceManager9, TRUE); + hr = MFGetService((IUnknown *)stream_sink, &MR_VIDEO_ACCELERATION_SERVICE, &IID_IMFVideoSampleAllocator, (void **)&allocator); ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/mf/evr.c | 33 +++++++++++++++++++++++---------- 1 file changed, 23 insertions(+), 10 deletions(-)
diff --git a/dlls/mf/evr.c b/dlls/mf/evr.c index 8b4a9c03b5f..baa6665853e 100644 --- a/dlls/mf/evr.c +++ b/dlls/mf/evr.c @@ -47,6 +47,7 @@ enum video_stream_flags { EVR_STREAM_PREROLLING = 0x1, EVR_STREAM_PREROLLED = 0x2, + EVR_STREAM_SAMPLE_NEEDED = 0x4, };
struct video_renderer; @@ -1825,13 +1826,19 @@ static ULONG WINAPI video_renderer_clock_sink_Release(IMFClockStateSink *iface) static HRESULT WINAPI video_renderer_clock_sink_OnClockStart(IMFClockStateSink *iface, MFTIME systime, LONGLONG offset) { struct video_renderer *renderer = impl_from_IMFClockStateSink(iface); + unsigned int state, request_sample; size_t i;
TRACE("%p, %s, %s.\n", iface, debugstr_time(systime), debugstr_time(offset));
EnterCriticalSection(&renderer->cs);
- if (renderer->state == EVR_STATE_STOPPED) + state = renderer->state; + + /* Update sink state before sending sample requests, to avoid potentially receiving new sample in stopped state */ + renderer->state = EVR_STATE_RUNNING; + + if (state == EVR_STATE_STOPPED) { IMFTransform_ProcessMessage(renderer->mixer, MFT_MESSAGE_NOTIFY_BEGIN_STREAMING, 0); IMFVideoPresenter_ProcessMessage(renderer->presenter, MFVP_MESSAGE_BEGINSTREAMING, 0); @@ -1840,19 +1847,19 @@ static HRESULT WINAPI video_renderer_clock_sink_OnClockStart(IMFClockStateSink * { 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); + request_sample = !(stream->flags & EVR_STREAM_PREROLLED) || (stream->flags & EVR_STREAM_SAMPLE_NEEDED); stream->flags |= EVR_STREAM_PREROLLED; + stream->flags &= ~EVR_STREAM_SAMPLE_NEEDED; LeaveCriticalSection(&stream->cs); + + IMFMediaEventQueue_QueueEventParamVar(stream->event_queue, MEStreamSinkStarted, &GUID_NULL, S_OK, NULL); + if (request_sample) + IMFMediaEventQueue_QueueEventParamVar(stream->event_queue, MEStreamSinkRequestSample, + &GUID_NULL, S_OK, NULL); } }
- renderer->state = EVR_STATE_RUNNING; - IMFVideoPresenter_OnClockStart(renderer->presenter, systime, offset);
LeaveCriticalSection(&renderer->cs); @@ -1886,7 +1893,7 @@ static HRESULT WINAPI video_renderer_clock_sink_OnClockStop(IMFClockStateSink *i IMFMediaEventQueue_QueueEventParamVar(stream->event_queue, MEStreamSinkStopped, &GUID_NULL, S_OK, NULL);
EnterCriticalSection(&stream->cs); - stream->flags &= ~EVR_STREAM_PREROLLED; + stream->flags &= ~(EVR_STREAM_PREROLLED | EVR_STREAM_SAMPLE_NEEDED); LeaveCriticalSection(&stream->cs); } renderer->state = EVR_STATE_STOPPED; @@ -2184,11 +2191,17 @@ static HRESULT WINAPI video_renderer_event_sink_Notify(IMediaEventSink *iface, L idx = param1; if (idx >= renderer->stream_count) hr = MF_E_INVALIDSTREAMNUMBER; - else + else if (renderer->state == EVR_STATE_RUNNING) { hr = IMFMediaEventQueue_QueueEventParamVar(renderer->streams[idx]->event_queue, MEStreamSinkRequestSample, &GUID_NULL, S_OK, NULL); } + else + { + /* Mixer asks for more input right after preroll too, before renderer finished running state transition. + Mark such streams here, and issue requests later in OnClockStart(). */ + renderer->streams[idx]->flags |= EVR_STREAM_SAMPLE_NEEDED; + } } else if (event == EC_DISPLAY_CHANGED) {
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/mf/evr.c | 67 ++++++++++++++++++++++++++++++++++++++++++++++ dlls/mf/tests/mf.c | 3 +++ 2 files changed, 70 insertions(+)
diff --git a/dlls/mf/evr.c b/dlls/mf/evr.c index baa6665853e..2a529895237 100644 --- a/dlls/mf/evr.c +++ b/dlls/mf/evr.c @@ -80,6 +80,7 @@ struct video_renderer IMediaEventSink IMediaEventSink_iface; IMFAttributes IMFAttributes_iface; IMFQualityAdvise IMFQualityAdvise_iface; + IMFRateSupport IMFRateSupport_iface; LONG refcount;
IMFMediaEventQueue *event_queue; @@ -150,6 +151,11 @@ static struct video_renderer *impl_from_IMFQualityAdvise(IMFQualityAdvise *iface return CONTAINING_RECORD(iface, struct video_renderer, IMFQualityAdvise_iface); }
+static struct video_renderer *impl_from_IMFRateSupport(IMFRateSupport *iface) +{ + return CONTAINING_RECORD(iface, struct video_renderer, IMFRateSupport_iface); +} + static struct video_stream *impl_from_IMFStreamSink(IMFStreamSink *iface) { return CONTAINING_RECORD(iface, struct video_stream, IMFStreamSink_iface); @@ -1087,6 +1093,10 @@ static HRESULT WINAPI video_renderer_sink_QueryInterface(IMFMediaSink *iface, RE { *obj = &renderer->IMFQualityAdvise_iface; } + else if (IsEqualIID(riid, &IID_IMFRateSupport)) + { + *obj = &renderer->IMFRateSupport_iface; + } else { WARN("Unsupported interface %s.\n", debugstr_guid(riid)); @@ -2028,6 +2038,10 @@ static HRESULT WINAPI video_renderer_get_service_GetService(IMFGetService *iface if (renderer->device_manager) hr = IUnknown_QueryInterface(renderer->device_manager, riid, obj); } + else if (IsEqualGUID(service, &MF_RATE_CONTROL_SERVICE) && IsEqualIID(riid, &IID_IMFRateSupport)) + { + hr = IMFVideoRenderer_QueryInterface(&renderer->IMFVideoRenderer_iface, riid, obj); + } else { FIXME("Unsupported service %s.\n", debugstr_guid(service)); @@ -2642,6 +2656,58 @@ static const IMFQualityAdviseVtbl video_renderer_quality_advise_vtbl = video_renderer_quality_advise_DropTime, };
+static HRESULT WINAPI video_renderer_rate_support_QueryInterface(IMFRateSupport *iface, REFIID riid, void **out) +{ + struct video_renderer *renderer = impl_from_IMFRateSupport(iface); + return IMFMediaSink_QueryInterface(&renderer->IMFMediaSink_iface, riid, out); +} + +static ULONG WINAPI video_renderer_rate_support_AddRef(IMFRateSupport *iface) +{ + struct video_renderer *renderer = impl_from_IMFRateSupport(iface); + return IMFMediaSink_AddRef(&renderer->IMFMediaSink_iface); +} + +static ULONG WINAPI video_renderer_rate_support_Release(IMFRateSupport *iface) +{ + struct video_renderer *renderer = impl_from_IMFRateSupport(iface); + return IMFMediaSink_Release(&renderer->IMFMediaSink_iface); +} + +static HRESULT WINAPI video_renderer_rate_support_GetSlowestRate(IMFRateSupport *iface, MFRATE_DIRECTION direction, + BOOL thin, float *rate) +{ + FIXME("%p, %d, %d, %p.\n", iface, direction, thin, rate); + + return E_NOTIMPL; +} + +static HRESULT WINAPI video_renderer_rate_support_GetFastestRate(IMFRateSupport *iface, MFRATE_DIRECTION direction, + BOOL thin, float *rate) +{ + FIXME("%p, %d, %d, %p.\n", iface, direction, thin, rate); + + return E_NOTIMPL; +} + +static HRESULT WINAPI video_renderer_rate_support_IsRateSupported(IMFRateSupport *iface, BOOL thin, float rate, + float *nearest_supported_rate) +{ + FIXME("%p, %d, %f, %p.\n", iface, thin, rate, nearest_supported_rate); + + return E_NOTIMPL; +} + +static const IMFRateSupportVtbl video_renderer_rate_support_vtbl = +{ + video_renderer_rate_support_QueryInterface, + video_renderer_rate_support_AddRef, + video_renderer_rate_support_Release, + video_renderer_rate_support_GetSlowestRate, + video_renderer_rate_support_GetFastestRate, + video_renderer_rate_support_IsRateSupported, +}; + static HRESULT evr_create_object(IMFAttributes *attributes, void *user_context, IUnknown **obj) { struct video_renderer *object; @@ -2664,6 +2730,7 @@ static HRESULT evr_create_object(IMFAttributes *attributes, void *user_context, object->IMediaEventSink_iface.lpVtbl = &media_event_sink_vtbl; object->IMFAttributes_iface.lpVtbl = &video_renderer_attributes_vtbl; object->IMFQualityAdvise_iface.lpVtbl = &video_renderer_quality_advise_vtbl; + object->IMFRateSupport_iface.lpVtbl = &video_renderer_rate_support_vtbl; object->refcount = 1; InitializeCriticalSection(&object->cs);
diff --git a/dlls/mf/tests/mf.c b/dlls/mf/tests/mf.c index 39b9d64e729..89da5d0ab64 100644 --- a/dlls/mf/tests/mf.c +++ b/dlls/mf/tests/mf.c @@ -4263,6 +4263,8 @@ static void test_evr(void) check_interface(sink, &IID_IMFClockStateSink, TRUE); check_interface(sink, &IID_IMFGetService, TRUE); check_interface(sink, &IID_IMFQualityAdvise, TRUE); + check_interface(sink, &IID_IMFRateSupport, TRUE); + check_interface(sink, &IID_IMFRateControl, FALSE); check_service_interface(sink, &MR_VIDEO_MIXER_SERVICE, &IID_IMFVideoProcessor, TRUE); check_service_interface(sink, &MR_VIDEO_MIXER_SERVICE, &IID_IMFVideoMixerBitmap, TRUE); check_service_interface(sink, &MR_VIDEO_MIXER_SERVICE, &IID_IMFVideoMixerControl, TRUE); @@ -4270,6 +4272,7 @@ static void test_evr(void) check_service_interface(sink, &MR_VIDEO_RENDER_SERVICE, &IID_IMFVideoDisplayControl, TRUE); check_service_interface(sink, &MR_VIDEO_RENDER_SERVICE, &IID_IMFVideoPositionMapper, TRUE); check_service_interface(sink, &MR_VIDEO_ACCELERATION_SERVICE, &IID_IDirect3DDeviceManager9, TRUE); + check_service_interface(sink, &MF_RATE_CONTROL_SERVICE, &IID_IMFRateSupport, TRUE);
hr = MFGetService((IUnknown *)sink, &MR_VIDEO_RENDER_SERVICE, &IID_IMFVideoDisplayControl, (void **)&display_control);
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/mf/evr.c | 17 +++++++++++++---- dlls/mf/tests/mf.c | 46 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 59 insertions(+), 4 deletions(-)
diff --git a/dlls/mf/evr.c b/dlls/mf/evr.c index 2a529895237..292e84ddd6b 100644 --- a/dlls/mf/evr.c +++ b/dlls/mf/evr.c @@ -2677,17 +2677,26 @@ static ULONG WINAPI video_renderer_rate_support_Release(IMFRateSupport *iface) static HRESULT WINAPI video_renderer_rate_support_GetSlowestRate(IMFRateSupport *iface, MFRATE_DIRECTION direction, BOOL thin, float *rate) { - FIXME("%p, %d, %d, %p.\n", iface, direction, thin, rate); + struct video_renderer *renderer = impl_from_IMFRateSupport(iface);
- return E_NOTIMPL; + TRACE("%p, %d, %d, %p.\n", iface, direction, thin, rate); + + if (renderer->flags & EVR_SHUT_DOWN) + return MF_E_SHUTDOWN; + + *rate = 0.0f; + + return S_OK; }
static HRESULT WINAPI video_renderer_rate_support_GetFastestRate(IMFRateSupport *iface, MFRATE_DIRECTION direction, BOOL thin, float *rate) { - FIXME("%p, %d, %d, %p.\n", iface, direction, thin, rate); + struct video_renderer *renderer = impl_from_IMFRateSupport(iface);
- return E_NOTIMPL; + TRACE("%p, %d, %d, %p.\n", iface, direction, thin, rate); + + return renderer->flags & EVR_SHUT_DOWN ? MF_E_SHUTDOWN : MF_E_INVALIDREQUEST; }
static HRESULT WINAPI video_renderer_rate_support_IsRateSupported(IMFRateSupport *iface, BOOL thin, float rate, diff --git a/dlls/mf/tests/mf.c b/dlls/mf/tests/mf.c index 89da5d0ab64..c8c7e0569cc 100644 --- a/dlls/mf/tests/mf.c +++ b/dlls/mf/tests/mf.c @@ -4224,10 +4224,12 @@ static void test_evr(void) DWORD flags, count, value; IMFActivate *activate; HWND window, window2; + IMFRateSupport *rs; LONG sample_count; IMFSample *sample; IUnknown *unk; UINT64 window3; + float rate; HRESULT hr; GUID guid;
@@ -4510,6 +4512,50 @@ todo_wine hr = IMFMediaSink_SetPresentationClock(sink, clock); ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
+ hr = IMFMediaSink_QueryInterface(sink, &IID_IMFRateSupport, (void **)&rs); + ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + + rate = 1.0f; + hr = IMFRateSupport_GetSlowestRate(rs, MFRATE_FORWARD, FALSE, &rate); + ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + ok(rate == 0.0f, "Unexpected rate %f.\n", rate); + + rate = 1.0f; + hr = IMFRateSupport_GetSlowestRate(rs, MFRATE_REVERSE, FALSE, &rate); + ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + ok(rate == 0.0f, "Unexpected rate %f.\n", rate); + + rate = 1.0f; + hr = IMFRateSupport_GetSlowestRate(rs, MFRATE_FORWARD, TRUE, &rate); + ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + ok(rate == 0.0f, "Unexpected rate %f.\n", rate); + + rate = 1.0f; + hr = IMFRateSupport_GetSlowestRate(rs, MFRATE_REVERSE, TRUE, &rate); + ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + ok(rate == 0.0f, "Unexpected rate %f.\n", rate); + + hr = IMFRateSupport_GetFastestRate(rs, MFRATE_FORWARD, FALSE, &rate); + ok(hr == MF_E_INVALIDREQUEST, "Unexpected hr %#x.\n", hr); + + hr = IMFRateSupport_GetFastestRate(rs, MFRATE_REVERSE, FALSE, &rate); + ok(hr == MF_E_INVALIDREQUEST, "Unexpected hr %#x.\n", hr); + + hr = IMFRateSupport_GetFastestRate(rs, MFRATE_FORWARD, TRUE, &rate); + ok(hr == MF_E_INVALIDREQUEST, "Unexpected hr %#x.\n", hr); + + hr = IMFRateSupport_GetFastestRate(rs, MFRATE_REVERSE, TRUE, &rate); + ok(hr == MF_E_INVALIDREQUEST, "Unexpected hr %#x.\n", hr); + + hr = IMFMediaSink_Shutdown(sink); + ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + + hr = IMFRateSupport_GetSlowestRate(rs, MFRATE_FORWARD, FALSE, &rate); + ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#x.\n", hr); + + hr = IMFRateSupport_GetFastestRate(rs, MFRATE_FORWARD, FALSE, &rate); + ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#x.\n", hr); + IMFPresentationClock_Release(clock);
IMFActivate_Release(activate);
Hi,
While running your changed tests, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check?
Full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=89323
Your paranoid android.
=== w864 (32 bit report) ===
mf: mf.c:2015: Test failed: Unexpected hr 0x800401f0 on test 2.
On 4/26/21 11:32 AM, Marvin wrote:
Hi,
While running your changed tests, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check?
Full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=89323
Your paranoid android.
=== w864 (32 bit report) ===
mf: mf.c:2015: Test failed: Unexpected hr 0x800401f0 on test 2.
This test is unrelated, and doesn't use a EVR node.