evr/presenter: Create dedicated thread to handle presentation time.
Signed-off-by: Nikolay Sivov <nsivov@codeweavers.com> Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
a8a03eb35f
commit
bf8a9613c5
|
@ -40,6 +40,18 @@ enum presenter_state
|
||||||
PRESENTER_STATE_PAUSED,
|
PRESENTER_STATE_PAUSED,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum streaming_thread_message
|
||||||
|
{
|
||||||
|
EVRM_STOP = WM_USER,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct streaming_thread
|
||||||
|
{
|
||||||
|
HANDLE hthread;
|
||||||
|
HANDLE ready_event;
|
||||||
|
DWORD tid;
|
||||||
|
};
|
||||||
|
|
||||||
struct video_presenter
|
struct video_presenter
|
||||||
{
|
{
|
||||||
IMFVideoPresenter IMFVideoPresenter_iface;
|
IMFVideoPresenter IMFVideoPresenter_iface;
|
||||||
|
@ -58,6 +70,7 @@ struct video_presenter
|
||||||
IMediaEventSink *event_sink;
|
IMediaEventSink *event_sink;
|
||||||
|
|
||||||
IDirect3DDeviceManager9 *device_manager;
|
IDirect3DDeviceManager9 *device_manager;
|
||||||
|
struct streaming_thread thread;
|
||||||
UINT reset_token;
|
UINT reset_token;
|
||||||
HWND video_window;
|
HWND video_window;
|
||||||
MFVideoNormalizedRect src_rect;
|
MFVideoNormalizedRect src_rect;
|
||||||
|
@ -184,6 +197,80 @@ static HRESULT video_presenter_invalidate_media_type(struct video_presenter *pre
|
||||||
return hr;
|
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)
|
static HRESULT WINAPI video_presenter_inner_QueryInterface(IUnknown *iface, REFIID riid, void **obj)
|
||||||
{
|
{
|
||||||
struct video_presenter *presenter = impl_from_IUnknown(iface);
|
struct video_presenter *presenter = impl_from_IUnknown(iface);
|
||||||
|
@ -266,6 +353,7 @@ static ULONG WINAPI video_presenter_inner_Release(IUnknown *iface)
|
||||||
|
|
||||||
if (!refcount)
|
if (!refcount)
|
||||||
{
|
{
|
||||||
|
video_presenter_end_streaming(presenter);
|
||||||
video_presenter_clear_container(presenter);
|
video_presenter_clear_container(presenter);
|
||||||
DeleteCriticalSection(&presenter->cs);
|
DeleteCriticalSection(&presenter->cs);
|
||||||
if (presenter->device_manager)
|
if (presenter->device_manager)
|
||||||
|
@ -374,6 +462,12 @@ static HRESULT WINAPI video_presenter_ProcessMessage(IMFVideoPresenter *iface, M
|
||||||
case MFVP_MESSAGE_INVALIDATEMEDIATYPE:
|
case MFVP_MESSAGE_INVALIDATEMEDIATYPE:
|
||||||
hr = video_presenter_invalidate_media_type(presenter);
|
hr = video_presenter_invalidate_media_type(presenter);
|
||||||
break;
|
break;
|
||||||
|
case MFVP_MESSAGE_BEGINSTREAMING:
|
||||||
|
hr = video_presenter_start_streaming(presenter);
|
||||||
|
break;
|
||||||
|
case MFVP_MESSAGE_ENDSTREAMING:
|
||||||
|
hr = video_presenter_end_streaming(presenter);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
FIXME("Unsupported message %u.\n", message);
|
FIXME("Unsupported message %u.\n", message);
|
||||||
hr = E_NOTIMPL;
|
hr = E_NOTIMPL;
|
||||||
|
|
Loading…
Reference in New Issue