[PATCH v2 4/4] winegstreamer: Implement pausing the media source.
Giovanni Mascellani
gmascellani at codeweavers.com
Fri Jun 11 05:53:56 CDT 2021
Signed-off-by: Giovanni Mascellani <gmascellani at codeweavers.com>
---
dlls/winegstreamer/media_source.c | 102 ++++++++++++++++++++++++++++--
1 file changed, 97 insertions(+), 5 deletions(-)
diff --git a/dlls/winegstreamer/media_source.c b/dlls/winegstreamer/media_source.c
index 9188a350305..953c0c84e90 100644
--- a/dlls/winegstreamer/media_source.c
+++ b/dlls/winegstreamer/media_source.c
@@ -37,6 +37,10 @@ struct media_stream
struct wg_parser_stream *wg_stream;
+ IUnknown **token_queue;
+ LONG token_queue_count;
+ LONG token_queue_cap;
+
enum
{
STREAM_INACTIVE,
@@ -50,6 +54,7 @@ struct media_stream
enum source_async_op
{
SOURCE_ASYNC_START,
+ SOURCE_ASYNC_PAUSE,
SOURCE_ASYNC_STOP,
SOURCE_ASYNC_REQUEST_SAMPLE,
};
@@ -96,6 +101,7 @@ struct media_source
{
SOURCE_OPENING,
SOURCE_STOPPED,
+ SOURCE_PAUSED,
SOURCE_RUNNING,
SOURCE_SHUTDOWN,
} state;
@@ -255,6 +261,54 @@ static IMFStreamDescriptor *stream_descriptor_from_id(IMFPresentationDescriptor
return NULL;
}
+static BOOL enqueue_token(struct media_stream *stream, IUnknown *token)
+{
+ if (stream->token_queue_count == stream->token_queue_cap)
+ {
+ IUnknown **buf;
+ stream->token_queue_cap = stream->token_queue_cap * 2 + 1;
+ buf = realloc(stream->token_queue, stream->token_queue_cap * sizeof(*buf));
+ if (buf)
+ stream->token_queue = buf;
+ else
+ {
+ stream->token_queue_cap = stream->token_queue_count;
+ return FALSE;
+ }
+ }
+ stream->token_queue[stream->token_queue_count++] = token;
+ return TRUE;
+}
+
+static void flush_token_queue(struct media_stream *stream, BOOL send)
+{
+ LONG i;
+
+ for (i = 0; i < stream->token_queue_count; i++)
+ {
+ if (send)
+ {
+ HRESULT hr;
+ struct source_async_command *command;
+ if (SUCCEEDED(hr = source_create_async_op(SOURCE_ASYNC_REQUEST_SAMPLE, &command)))
+ {
+ command->u.request_sample.stream = stream;
+ command->u.request_sample.token = stream->token_queue[i];
+
+ hr = MFPutWorkItem(stream->parent_source->async_commands_queue, &stream->parent_source->async_commands_callback, &command->IUnknown_iface);
+ }
+ if (FAILED(hr))
+ WARN("Could not enqueue sample request, hr %#x\n", hr);
+ }
+ else if (stream->token_queue[i])
+ IUnknown_Release(stream->token_queue[i]);
+ }
+ free(stream->token_queue);
+ stream->token_queue = NULL;
+ stream->token_queue_count = 0;
+ stream->token_queue_cap = 0;
+}
+
static void start_pipeline(struct media_source *source, struct source_async_command *command)
{
PROPVARIANT *position = &command->u.start.position;
@@ -328,6 +382,27 @@ static void start_pipeline(struct media_source *source, struct source_async_comm
unix_funcs->wg_parser_stream_seek(source->streams[0]->wg_stream, 1.0,
position->hVal.QuadPart, 0, AM_SEEKING_AbsolutePositioning, AM_SEEKING_NoPositioning);
unix_funcs->wg_parser_end_flush(source->wg_parser);
+
+ for (i = 0; i < source->stream_count; i++)
+ flush_token_queue(source->streams[i], position->vt == VT_EMPTY);
+}
+
+static void pause_pipeline(struct media_source *source)
+{
+ unsigned int i;
+
+ for (i = 0; i < source->stream_count; i++)
+ {
+ struct media_stream *stream = source->streams[i];
+ if (stream->state != STREAM_INACTIVE)
+ {
+ IMFMediaEventQueue_QueueEventParamVar(stream->event_queue, MEStreamPaused, &GUID_NULL, S_OK, NULL);
+ }
+ }
+
+ IMFMediaEventQueue_QueueEventParamVar(source->event_queue, MESourcePaused, &GUID_NULL, S_OK, NULL);
+
+ source->state = SOURCE_PAUSED;
}
static void stop_pipeline(struct media_source *source)
@@ -349,6 +424,9 @@ static void stop_pipeline(struct media_source *source)
IMFMediaEventQueue_QueueEventParamVar(source->event_queue, MESourceStopped, &GUID_NULL, S_OK, NULL);
source->state = SOURCE_STOPPED;
+
+ for (i = 0; i < source->stream_count; i++)
+ flush_token_queue(source->streams[i], FALSE);
}
static void dispatch_end_of_presentation(struct media_source *source)
@@ -499,11 +577,17 @@ static HRESULT WINAPI source_async_commands_Invoke(IMFAsyncCallback *iface, IMFA
case SOURCE_ASYNC_START:
start_pipeline(source, command);
break;
+ case SOURCE_ASYNC_PAUSE:
+ pause_pipeline(source);
+ break;
case SOURCE_ASYNC_STOP:
stop_pipeline(source);
break;
case SOURCE_ASYNC_REQUEST_SAMPLE:
- wait_on_sample(command->u.request_sample.stream, command->u.request_sample.token);
+ if (source->state == SOURCE_PAUSED)
+ enqueue_token(command->u.request_sample.stream, command->u.request_sample.token);
+ else
+ wait_on_sample(command->u.request_sample.stream, command->u.request_sample.token);
break;
}
@@ -595,6 +679,7 @@ static ULONG WINAPI media_stream_Release(IMFMediaStream *iface)
{
if (stream->event_queue)
IMFMediaEventQueue_Release(stream->event_queue);
+ flush_token_queue(stream, FALSE);
free(stream);
}
@@ -697,7 +782,6 @@ static HRESULT WINAPI media_stream_RequestSample(IMFMediaStream *iface, IUnknown
IUnknown_AddRef(token);
command->u.request_sample.token = token;
- /* Once pause support is added, this will need to put into a stream queue, and synchronization will need to be added*/
hr = MFPutWorkItem(stream->parent_source->async_commands_queue, &stream->parent_source->async_commands_callback, &command->IUnknown_iface);
}
@@ -1121,7 +1205,7 @@ static HRESULT WINAPI media_source_GetCharacteristics(IMFMediaSource *iface, DWO
if (source->state == SOURCE_SHUTDOWN)
return MF_E_SHUTDOWN;
- *characteristics = MFMEDIASOURCE_CAN_SEEK;
+ *characteristics = MFMEDIASOURCE_CAN_SEEK | MFMEDIASOURCE_CAN_PAUSE;
return S_OK;
}
@@ -1185,13 +1269,21 @@ static HRESULT WINAPI media_source_Stop(IMFMediaSource *iface)
static HRESULT WINAPI media_source_Pause(IMFMediaSource *iface)
{
struct media_source *source = impl_from_IMFMediaSource(iface);
+ struct source_async_command *command;
+ HRESULT hr;
- FIXME("(%p): stub\n", source);
+ TRACE("(%p)\n", source);
if (source->state == SOURCE_SHUTDOWN)
return MF_E_SHUTDOWN;
- return E_NOTIMPL;
+ if (source->state != SOURCE_RUNNING)
+ return MF_E_INVALID_STATE_TRANSITION;
+
+ if (SUCCEEDED(hr = source_create_async_op(SOURCE_ASYNC_PAUSE, &command)))
+ hr = MFPutWorkItem(source->async_commands_queue, &source->async_commands_callback, &command->IUnknown_iface);
+
+ return S_OK;
}
static HRESULT WINAPI media_source_Shutdown(IMFMediaSource *iface)
--
2.32.0
More information about the wine-devel
mailing list