diff --git a/dlls/evr/presenter.c b/dlls/evr/presenter.c index 54ad9fee994..01623815dd3 100644 --- a/dlls/evr/presenter.c +++ b/dlls/evr/presenter.c @@ -40,6 +40,18 @@ enum presenter_state PRESENTER_STATE_PAUSED, }; +enum streaming_thread_message +{ + EVRM_STOP = WM_USER, +}; + +struct streaming_thread +{ + HANDLE hthread; + HANDLE ready_event; + DWORD tid; +}; + struct video_presenter { IMFVideoPresenter IMFVideoPresenter_iface; @@ -58,6 +70,7 @@ struct video_presenter IMediaEventSink *event_sink; IDirect3DDeviceManager9 *device_manager; + struct streaming_thread thread; UINT reset_token; HWND video_window; MFVideoNormalizedRect src_rect; @@ -184,6 +197,80 @@ static HRESULT video_presenter_invalidate_media_type(struct video_presenter *pre return hr; } +static DWORD CALLBACK video_presenter_streaming_thread(void *arg) +{ + struct video_presenter *presenter = arg; + BOOL stop_thread = FALSE; + MSG msg; + + PeekMessageW(&msg, NULL, WM_USER, WM_USER, PM_NOREMOVE); + + SetEvent(presenter->thread.ready_event); + + while (!stop_thread) + { + MsgWaitForMultipleObjects(0, NULL, FALSE, INFINITE, QS_POSTMESSAGE); + + while (PeekMessageW(&msg, NULL, 0, 0, PM_REMOVE)) + { + switch (msg.message) + { + case EVRM_STOP: + stop_thread = TRUE; + break; + + default: + ; + } + } + } + + return 0; +} + +static HRESULT video_presenter_start_streaming(struct video_presenter *presenter) +{ + if (presenter->thread.hthread) + return S_OK; + + if (!(presenter->thread.ready_event = CreateEventW(NULL, FALSE, FALSE, NULL))) + return HRESULT_FROM_WIN32(GetLastError()); + + if (!(presenter->thread.hthread = CreateThread(NULL, 0, video_presenter_streaming_thread, + presenter, 0, &presenter->thread.tid))) + { + WARN("Failed to create streaming thread.\n"); + CloseHandle(presenter->thread.ready_event); + presenter->thread.ready_event = NULL; + return E_FAIL; + } + + WaitForSingleObject(presenter->thread.ready_event, INFINITE); + CloseHandle(presenter->thread.ready_event); + presenter->thread.ready_event = NULL; + + TRACE("Started streaming thread, tid %#x.\n", presenter->thread.tid); + + return S_OK; +} + +static HRESULT video_presenter_end_streaming(struct video_presenter *presenter) +{ + if (!presenter->thread.hthread) + return S_OK; + + PostThreadMessageW(presenter->thread.tid, EVRM_STOP, 0, 0); + + WaitForSingleObject(presenter->thread.hthread, INFINITE); + CloseHandle(presenter->thread.hthread); + + TRACE("Terminated streaming thread tid %#x.\n", presenter->thread.tid); + + memset(&presenter->thread, 0, sizeof(presenter->thread)); + + return S_OK; +} + static HRESULT WINAPI video_presenter_inner_QueryInterface(IUnknown *iface, REFIID riid, void **obj) { struct video_presenter *presenter = impl_from_IUnknown(iface); @@ -266,6 +353,7 @@ static ULONG WINAPI video_presenter_inner_Release(IUnknown *iface) if (!refcount) { + video_presenter_end_streaming(presenter); video_presenter_clear_container(presenter); DeleteCriticalSection(&presenter->cs); if (presenter->device_manager) @@ -374,6 +462,12 @@ static HRESULT WINAPI video_presenter_ProcessMessage(IMFVideoPresenter *iface, M case MFVP_MESSAGE_INVALIDATEMEDIATYPE: hr = video_presenter_invalidate_media_type(presenter); break; + case MFVP_MESSAGE_BEGINSTREAMING: + hr = video_presenter_start_streaming(presenter); + break; + case MFVP_MESSAGE_ENDSTREAMING: + hr = video_presenter_end_streaming(presenter); + break; default: FIXME("Unsupported message %u.\n", message); hr = E_NOTIMPL;