Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/evr/presenter.c | 68 ++++++++++++++++++++++++++++++++++++++------ dlls/evr/tests/evr.c | 6 ---- 2 files changed, 59 insertions(+), 15 deletions(-)
diff --git a/dlls/evr/presenter.c b/dlls/evr/presenter.c index 027d0338896..a91510b13bc 100644 --- a/dlls/evr/presenter.c +++ b/dlls/evr/presenter.c @@ -31,9 +31,16 @@
WINE_DEFAULT_DEBUG_CHANNEL(evr);
+/* + Initial state represents just created object, presenter never returns to this state. + Shutdown state is entered on ReleaseServicePointers(), terminal state. + Started/stopped/paused states are controlled by clock state changes. +*/ + enum presenter_state { - PRESENTER_STATE_SHUT_DOWN = 0, + PRESENTER_STATE_INITIAL = 0, + PRESENTER_STATE_SHUT_DOWN, PRESENTER_STATE_STARTED, PRESENTER_STATE_STOPPED, PRESENTER_STATE_PAUSED, @@ -603,6 +610,9 @@ static HRESULT video_presenter_process_input(struct video_presenter *presenter) IMFSample *sample; DWORD status;
+ if (presenter->state == PRESENTER_STATE_SHUT_DOWN) + return MF_E_SHUTDOWN; + if (!presenter->media_type) return S_OK;
@@ -708,6 +718,9 @@ static HRESULT video_presenter_start_streaming(struct video_presenter *presenter { HRESULT hr;
+ if (presenter->state == PRESENTER_STATE_SHUT_DOWN) + return MF_E_SHUTDOWN; + if (presenter->thread.hthread) return S_OK;
@@ -968,7 +981,12 @@ static HRESULT WINAPI video_presenter_ProcessMessage(IMFVideoPresenter *iface, M switch (message) { case MFVP_MESSAGE_INVALIDATEMEDIATYPE: - hr = presenter->mixer ? video_presenter_invalidate_media_type(presenter) : MF_E_INVALIDREQUEST; + if (presenter->state == PRESENTER_STATE_SHUT_DOWN) + hr = MF_E_SHUTDOWN; + else if (!presenter->mixer) + hr = MF_E_INVALIDREQUEST; + else + hr = video_presenter_invalidate_media_type(presenter); break; case MFVP_MESSAGE_BEGINSTREAMING: hr = video_presenter_start_streaming(presenter); @@ -1238,6 +1256,7 @@ static HRESULT WINAPI video_presenter_control_GetNativeVideoSize(IMFVideoDisplay SIZE *aspect_ratio) { struct video_presenter *presenter = impl_from_IMFVideoDisplayControl(iface); + HRESULT hr = S_OK;
TRACE("%p, %p, %p.\n", iface, video_size, aspect_ratio);
@@ -1245,21 +1264,40 @@ static HRESULT WINAPI video_presenter_control_GetNativeVideoSize(IMFVideoDisplay return E_POINTER;
EnterCriticalSection(&presenter->cs); - if (video_size) - *video_size = presenter->native_size; - if (aspect_ratio) - *aspect_ratio = presenter->native_ratio; + + if (presenter->state == PRESENTER_STATE_SHUT_DOWN) + hr = MF_E_SHUTDOWN; + else + { + if (video_size) + *video_size = presenter->native_size; + if (aspect_ratio) + *aspect_ratio = presenter->native_ratio; + } + LeaveCriticalSection(&presenter->cs);
- return S_OK; + return hr; }
static HRESULT WINAPI video_presenter_control_GetIdealVideoSize(IMFVideoDisplayControl *iface, SIZE *min_size, SIZE *max_size) { + struct video_presenter *presenter = impl_from_IMFVideoDisplayControl(iface); + HRESULT hr; + FIXME("%p, %p, %p.\n", iface, min_size, max_size);
- return E_NOTIMPL; + EnterCriticalSection(&presenter->cs); + + if (presenter->state == PRESENTER_STATE_SHUT_DOWN) + hr = MF_E_SHUTDOWN; + else + hr = E_NOTIMPL; + + LeaveCriticalSection(&presenter->cs); + + return hr; }
static HRESULT WINAPI video_presenter_control_SetVideoPosition(IMFVideoDisplayControl *iface, @@ -1425,9 +1463,21 @@ static HRESULT WINAPI video_presenter_control_GetVideoWindow(IMFVideoDisplayCont
static HRESULT WINAPI video_presenter_control_RepaintVideo(IMFVideoDisplayControl *iface) { + struct video_presenter *presenter = impl_from_IMFVideoDisplayControl(iface); + HRESULT hr; + FIXME("%p.\n", iface);
- return E_NOTIMPL; + EnterCriticalSection(&presenter->cs); + + if (presenter->state == PRESENTER_STATE_SHUT_DOWN) + hr = MF_E_SHUTDOWN; + else + hr = E_NOTIMPL; + + LeaveCriticalSection(&presenter->cs); + + return hr; }
static HRESULT WINAPI video_presenter_control_GetCurrentImage(IMFVideoDisplayControl *iface, BITMAPINFOHEADER *header, diff --git a/dlls/evr/tests/evr.c b/dlls/evr/tests/evr.c index b7e3ad174df..6a711e30581 100644 --- a/dlls/evr/tests/evr.c +++ b/dlls/evr/tests/evr.c @@ -2353,18 +2353,15 @@ static void test_presenter_shutdown(void) ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
hr = IMFVideoPresenter_ProcessMessage(presenter, MFVP_MESSAGE_INVALIDATEMEDIATYPE, 0); -todo_wine ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#x.\n", hr);
hr = IMFVideoPresenter_ProcessMessage(presenter, MFVP_MESSAGE_BEGINSTREAMING, 0); -todo_wine ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#x.\n", hr);
hr = IMFVideoPresenter_ProcessMessage(presenter, MFVP_MESSAGE_ENDSTREAMING, 0); ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
hr = IMFVideoPresenter_ProcessMessage(presenter, MFVP_MESSAGE_PROCESSINPUTNOTIFY, 0); -todo_wine ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#x.\n", hr);
hr = IMFVideoPresenter_GetCurrentMediaType(presenter, &media_type); @@ -2374,11 +2371,9 @@ todo_wine ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
hr = IMFVideoDisplayControl_GetNativeVideoSize(display_control, &size, &size); -todo_wine ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#x.\n", hr);
hr = IMFVideoDisplayControl_GetIdealVideoSize(display_control, &size, &size); -todo_wine ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#x.\n", hr);
SetRect(&rect, 0, 0, 10, 10); @@ -2404,7 +2399,6 @@ todo_wine ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
hr = IMFVideoDisplayControl_RepaintVideo(display_control); -todo_wine ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#x.\n", hr);
hr = IMFTopologyServiceLookupClient_ReleaseServicePointers(lookup_client);
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/evr/mixer.c | 74 ++++++++++++++++++++++++++++++++++++------------ 1 file changed, 56 insertions(+), 18 deletions(-)
diff --git a/dlls/evr/mixer.c b/dlls/evr/mixer.c index 1db2fd3a9f4..631ee1ba645 100644 --- a/dlls/evr/mixer.c +++ b/dlls/evr/mixer.c @@ -81,6 +81,7 @@ struct video_mixer
struct input_stream inputs[MAX_MIXER_INPUT_STREAMS]; unsigned int input_ids[MAX_MIXER_INPUT_STREAMS]; + struct input_stream *zorder[MAX_MIXER_INPUT_STREAMS]; unsigned int input_count; struct output_stream output;
@@ -183,6 +184,22 @@ static void video_mixer_init_input(struct input_stream *stream) stream->rect.right = stream->rect.bottom = 1.0f; }
+static int __cdecl video_mixer_zorder_sort_compare(const void *a, const void *b) +{ + const struct input_stream *left = *(void **)a, *right = *(void **)b; + return left->zorder != right->zorder ? (left->zorder < right->zorder ? -1 : 1) : 0; +}; + +static void video_mixer_update_zorder_map(struct video_mixer *mixer) +{ + unsigned int i; + + for (i = 0; i < mixer->input_count; ++i) + mixer->zorder[i] = &mixer->inputs[i]; + + qsort(mixer->zorder, mixer->input_count, sizeof(*mixer->zorder), video_mixer_zorder_sort_compare); +} + static void video_mixer_clear_types(struct video_mixer *mixer) { unsigned int i; @@ -501,6 +518,7 @@ static HRESULT WINAPI video_mixer_transform_DeleteInputStream(IMFTransform *ifac memmove(&mixer->inputs[idx], &mixer->inputs[idx + 1], (mixer->input_count - idx) * sizeof(*mixer->inputs)); memmove(&mixer->input_ids[idx], &mixer->input_ids[idx + 1], (mixer->input_count - idx) * sizeof(*mixer->input_ids)); + video_mixer_update_zorder_map(mixer); } }
@@ -570,6 +588,8 @@ static HRESULT WINAPI video_mixer_transform_AddInputStreams(IMFTransform *iface, input->zorder = zorder; zorder++; } + + video_mixer_update_zorder_map(mixer); } } LeaveCriticalSection(&mixer->cs); @@ -1227,13 +1247,13 @@ static void video_mixer_scale_rect(RECT *rect, unsigned int width, unsigned int
static void video_mixer_render(struct video_mixer *mixer, IDirect3DSurface9 *rt) { - DXVA2_VideoSample samples[1] = {{ 0 }}; + DXVA2_VideoSample samples[MAX_MIXER_INPUT_STREAMS] = {{ 0 }}; DXVA2_VideoProcessBltParams params = { 0 }; MFVideoNormalizedRect zoom_rect; struct input_stream *stream; - IDirect3DSurface9 *surface; D3DSURFACE_DESC desc; - HRESULT hr; + HRESULT hr = S_OK; + unsigned int i;
IDirect3DSurface9_GetDesc(rt, &desc);
@@ -1246,26 +1266,40 @@ static void video_mixer_render(struct video_mixer *mixer, IDirect3DSurface9 *rt)
video_mixer_scale_rect(¶ms.TargetRect, desc.Width, desc.Height, &zoom_rect);
- /* FIXME: for now only handle reference stream. */ + for (i = 0; i < mixer->input_count; ++i) + { + IDirect3DSurface9 *surface;
- video_mixer_get_input(mixer, 0, &stream); + stream = mixer->zorder[i];
- if (FAILED(hr = video_mixer_get_sample_surface(stream->sample, &surface))) - { - WARN("Failed to get source surface, hr %#x.\n", hr); - return; - } + if (FAILED(hr = video_mixer_get_sample_surface(stream->sample, &surface))) + { + WARN("Failed to get source surface for stream %u, hr %#x.\n", i, hr); + break; + }
- IDirect3DSurface9_GetDesc(surface, &desc); + IDirect3DSurface9_GetDesc(surface, &desc);
- samples[0].SrcSurface = surface; - SetRect(&samples[0].SrcRect, 0, 0, desc.Width, desc.Height); - video_mixer_scale_rect(&samples[0].DstRect, desc.Width, desc.Height, &stream->rect); + samples[i].SampleFormat.SampleFormat = stream->id == 0 ? DXVA2_SampleProgressiveFrame : DXVA2_SampleSubStream; + samples[i].SrcSurface = surface; + SetRect(&samples[i].SrcRect, 0, 0, desc.Width, desc.Height); + video_mixer_scale_rect(&samples[i].DstRect, desc.Width, desc.Height, &stream->rect); + }
- if (FAILED(hr = IDirectXVideoProcessor_VideoProcessBlt(mixer->processor, rt, ¶ms, samples, 1, NULL))) - WARN("Failed to process samples, hr %#x.\n", hr); + if (SUCCEEDED(hr)) + { + if (FAILED(hr = IDirectXVideoProcessor_VideoProcessBlt(mixer->processor, rt, ¶ms, samples, + mixer->input_count, NULL))) + { + WARN("Failed to process samples, hr %#x.\n", hr); + } + }
- IDirect3DSurface9_Release(surface); + for (i = 0; i < mixer->input_count; ++i) + { + if (samples[i].SrcSurface) + IDirect3DSurface9_Release(samples[i].SrcSurface); + } }
static HRESULT video_mixer_get_sample_desired_time(IMFSample *sample, LONGLONG *timestamp, LONGLONG *duration) @@ -1542,8 +1576,11 @@ static HRESULT WINAPI video_mixer_control_SetStreamZOrder(IMFVideoMixerControl2 /* Lowest zorder only applies to reference stream. */ if (id && !zorder) hr = MF_E_INVALIDREQUEST; - else + else if (stream->zorder != zorder) + { stream->zorder = zorder; + video_mixer_update_zorder_map(mixer); + } }
LeaveCriticalSection(&mixer->cs); @@ -2449,6 +2486,7 @@ HRESULT evr_mixer_create(IUnknown *outer, void **out) object->lower_bound = MFT_OUTPUT_BOUND_LOWER_UNBOUNDED; object->upper_bound = MFT_OUTPUT_BOUND_UPPER_UNBOUNDED; video_mixer_init_input(&object->inputs[0]); + video_mixer_update_zorder_map(object); InitializeCriticalSection(&object->cs); if (FAILED(hr = MFCreateAttributes(&object->attributes, 0))) {