mf/evr: Handle mixer sample requests during sink state transitions.
Signed-off-by: Nikolay Sivov <nsivov@codeweavers.com> Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
b0118c7c7d
commit
2a6f0a4093
|
@ -47,6 +47,7 @@ enum video_stream_flags
|
||||||
{
|
{
|
||||||
EVR_STREAM_PREROLLING = 0x1,
|
EVR_STREAM_PREROLLING = 0x1,
|
||||||
EVR_STREAM_PREROLLED = 0x2,
|
EVR_STREAM_PREROLLED = 0x2,
|
||||||
|
EVR_STREAM_SAMPLE_NEEDED = 0x4,
|
||||||
};
|
};
|
||||||
|
|
||||||
struct video_renderer;
|
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)
|
static HRESULT WINAPI video_renderer_clock_sink_OnClockStart(IMFClockStateSink *iface, MFTIME systime, LONGLONG offset)
|
||||||
{
|
{
|
||||||
struct video_renderer *renderer = impl_from_IMFClockStateSink(iface);
|
struct video_renderer *renderer = impl_from_IMFClockStateSink(iface);
|
||||||
|
unsigned int state, request_sample;
|
||||||
size_t i;
|
size_t i;
|
||||||
|
|
||||||
TRACE("%p, %s, %s.\n", iface, debugstr_time(systime), debugstr_time(offset));
|
TRACE("%p, %s, %s.\n", iface, debugstr_time(systime), debugstr_time(offset));
|
||||||
|
|
||||||
EnterCriticalSection(&renderer->cs);
|
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);
|
IMFTransform_ProcessMessage(renderer->mixer, MFT_MESSAGE_NOTIFY_BEGIN_STREAMING, 0);
|
||||||
IMFVideoPresenter_ProcessMessage(renderer->presenter, MFVP_MESSAGE_BEGINSTREAMING, 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];
|
struct video_stream *stream = renderer->streams[i];
|
||||||
|
|
||||||
IMFMediaEventQueue_QueueEventParamVar(stream->event_queue, MEStreamSinkStarted, &GUID_NULL, S_OK, NULL);
|
|
||||||
|
|
||||||
EnterCriticalSection(&stream->cs);
|
EnterCriticalSection(&stream->cs);
|
||||||
if (!(stream->flags & EVR_STREAM_PREROLLED))
|
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,
|
IMFMediaEventQueue_QueueEventParamVar(stream->event_queue, MEStreamSinkRequestSample,
|
||||||
&GUID_NULL, S_OK, NULL);
|
&GUID_NULL, S_OK, NULL);
|
||||||
stream->flags |= EVR_STREAM_PREROLLED;
|
|
||||||
LeaveCriticalSection(&stream->cs);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
renderer->state = EVR_STATE_RUNNING;
|
|
||||||
|
|
||||||
IMFVideoPresenter_OnClockStart(renderer->presenter, systime, offset);
|
IMFVideoPresenter_OnClockStart(renderer->presenter, systime, offset);
|
||||||
|
|
||||||
LeaveCriticalSection(&renderer->cs);
|
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);
|
IMFMediaEventQueue_QueueEventParamVar(stream->event_queue, MEStreamSinkStopped, &GUID_NULL, S_OK, NULL);
|
||||||
|
|
||||||
EnterCriticalSection(&stream->cs);
|
EnterCriticalSection(&stream->cs);
|
||||||
stream->flags &= ~EVR_STREAM_PREROLLED;
|
stream->flags &= ~(EVR_STREAM_PREROLLED | EVR_STREAM_SAMPLE_NEEDED);
|
||||||
LeaveCriticalSection(&stream->cs);
|
LeaveCriticalSection(&stream->cs);
|
||||||
}
|
}
|
||||||
renderer->state = EVR_STATE_STOPPED;
|
renderer->state = EVR_STATE_STOPPED;
|
||||||
|
@ -2184,11 +2191,17 @@ static HRESULT WINAPI video_renderer_event_sink_Notify(IMediaEventSink *iface, L
|
||||||
idx = param1;
|
idx = param1;
|
||||||
if (idx >= renderer->stream_count)
|
if (idx >= renderer->stream_count)
|
||||||
hr = MF_E_INVALIDSTREAMNUMBER;
|
hr = MF_E_INVALIDSTREAMNUMBER;
|
||||||
else
|
else if (renderer->state == EVR_STATE_RUNNING)
|
||||||
{
|
{
|
||||||
hr = IMFMediaEventQueue_QueueEventParamVar(renderer->streams[idx]->event_queue,
|
hr = IMFMediaEventQueue_QueueEventParamVar(renderer->streams[idx]->event_queue,
|
||||||
MEStreamSinkRequestSample, &GUID_NULL, S_OK, NULL);
|
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)
|
else if (event == EC_DISPLAY_CHANGED)
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in New Issue