[PATCH v3 2/3] mf: Generate missing MEStreamSinkPaused event in the sample grabber.
Giovanni Mascellani
gmascellani at codeweavers.com
Mon May 31 05:11:32 CDT 2021
The following behaviors from Windows are implemented:
* Transitions from STOPPED to PAUSED are forbidden;
* Sample requests are only emitted for transitions from STOPPED to
RUNNING (i.e., not when transitioning from PAUSED);
* Transition events are emitted again when transitioning from a
state to the same state, except when such state is PAUSED.
Signed-off-by: Giovanni Mascellani <gmascellani at codeweavers.com>
---
dlls/mf/samplegrabber.c | 51 ++++++++++++++++++++++++-----------------
1 file changed, 30 insertions(+), 21 deletions(-)
diff --git a/dlls/mf/samplegrabber.c b/dlls/mf/samplegrabber.c
index f60ce2a8433..5961cac7e0f 100644
--- a/dlls/mf/samplegrabber.c
+++ b/dlls/mf/samplegrabber.c
@@ -32,6 +32,7 @@ WINE_DEFAULT_DEBUG_CHANNEL(mfplat);
enum sink_state
{
SINK_STATE_STOPPED = 0,
+ SINK_STATE_PAUSED,
SINK_STATE_RUNNING,
};
@@ -1101,55 +1102,52 @@ static ULONG WINAPI sample_grabber_clock_sink_Release(IMFClockStateSink *iface)
return IMFMediaSink_Release(&grabber->IMFMediaSink_iface);
}
-static void sample_grabber_set_state(struct sample_grabber *grabber, enum sink_state state)
+static HRESULT sample_grabber_set_state(struct sample_grabber *grabber, enum sink_state state)
{
static const DWORD events[] =
{
MEStreamSinkStopped, /* SINK_STATE_STOPPED */
+ MEStreamSinkPaused, /* SINK_STATE_PAUSED */
MEStreamSinkStarted, /* SINK_STATE_RUNNING */
};
- BOOL set_state = FALSE;
+ HRESULT hr = S_OK;
unsigned int i;
EnterCriticalSection(&grabber->cs);
if (!grabber->is_shut_down)
{
- switch (grabber->state)
- {
- case SINK_STATE_STOPPED:
- set_state = state == SINK_STATE_RUNNING;
- break;
- case SINK_STATE_RUNNING:
- set_state = state == SINK_STATE_STOPPED;
- break;
- default:
- ;
- }
-
- if (set_state)
+ if (state == SINK_STATE_PAUSED && grabber->state == SINK_STATE_STOPPED)
+ hr = MF_E_INVALID_STATE_TRANSITION;
+ else
{
- grabber->state = state;
- if (state == SINK_STATE_RUNNING)
+ if (state == SINK_STATE_RUNNING && grabber->state == SINK_STATE_STOPPED)
{
/* Every transition to running state sends a bunch requests to build up initial queue. */
for (i = 0; i < 4; ++i)
sample_grabber_stream_request_sample(grabber);
}
- IMFStreamSink_QueueEvent(&grabber->IMFStreamSink_iface, events[state], &GUID_NULL, S_OK, NULL);
+ if (state != grabber->state || state != SINK_STATE_PAUSED)
+ IMFStreamSink_QueueEvent(&grabber->IMFStreamSink_iface, events[state], &GUID_NULL, S_OK, NULL);
+ grabber->state = state;
}
}
LeaveCriticalSection(&grabber->cs);
+
+ return hr;
}
static HRESULT WINAPI sample_grabber_clock_sink_OnClockStart(IMFClockStateSink *iface, MFTIME systime, LONGLONG offset)
{
struct sample_grabber *grabber = impl_from_IMFClockStateSink(iface);
+ HRESULT hr;
TRACE("%p, %s, %s.\n", iface, debugstr_time(systime), debugstr_time(offset));
- sample_grabber_set_state(grabber, SINK_STATE_RUNNING);
+ hr = sample_grabber_set_state(grabber, SINK_STATE_RUNNING);
+ if (FAILED(hr))
+ return hr;
return IMFSampleGrabberSinkCallback_OnClockStart(sample_grabber_get_callback(grabber), systime, offset);
}
@@ -1157,10 +1155,13 @@ static HRESULT WINAPI sample_grabber_clock_sink_OnClockStart(IMFClockStateSink *
static HRESULT WINAPI sample_grabber_clock_sink_OnClockStop(IMFClockStateSink *iface, MFTIME systime)
{
struct sample_grabber *grabber = impl_from_IMFClockStateSink(iface);
+ HRESULT hr;
TRACE("%p, %s.\n", iface, debugstr_time(systime));
- sample_grabber_set_state(grabber, SINK_STATE_STOPPED);
+ hr = sample_grabber_set_state(grabber, SINK_STATE_STOPPED);
+ if (FAILED(hr))
+ return hr;
return IMFSampleGrabberSinkCallback_OnClockStop(sample_grabber_get_callback(grabber), systime);
}
@@ -1168,19 +1169,27 @@ static HRESULT WINAPI sample_grabber_clock_sink_OnClockStop(IMFClockStateSink *i
static HRESULT WINAPI sample_grabber_clock_sink_OnClockPause(IMFClockStateSink *iface, MFTIME systime)
{
struct sample_grabber *grabber = impl_from_IMFClockStateSink(iface);
+ HRESULT hr;
TRACE("%p, %s.\n", iface, debugstr_time(systime));
+ hr = sample_grabber_set_state(grabber, SINK_STATE_PAUSED);
+ if (FAILED(hr))
+ return hr;
+
return IMFSampleGrabberSinkCallback_OnClockPause(sample_grabber_get_callback(grabber), systime);
}
static HRESULT WINAPI sample_grabber_clock_sink_OnClockRestart(IMFClockStateSink *iface, MFTIME systime)
{
struct sample_grabber *grabber = impl_from_IMFClockStateSink(iface);
+ HRESULT hr;
TRACE("%p, %s.\n", iface, debugstr_time(systime));
- sample_grabber_set_state(grabber, SINK_STATE_RUNNING);
+ hr = sample_grabber_set_state(grabber, SINK_STATE_RUNNING);
+ if (FAILED(hr))
+ return hr;
return IMFSampleGrabberSinkCallback_OnClockRestart(sample_grabber_get_callback(grabber), systime);
}
--
2.32.0.rc0
More information about the wine-devel
mailing list