[PATCH 1/2] winegstreamer: Implement pausing the media source.
Giovanni Mascellani
gmascellani at codeweavers.com
Thu Jun 10 10:33:56 CDT 2021
Signed-off-by: Giovanni Mascellani <gmascellani at codeweavers.com>
---
dlls/winegstreamer/media_source.c | 95 +++++++++++++++++++++++++++----
1 file changed, 85 insertions(+), 10 deletions(-)
diff --git a/dlls/winegstreamer/media_source.c b/dlls/winegstreamer/media_source.c
index 3c87bbb2146..496aab545e7 100644
--- a/dlls/winegstreamer/media_source.c
+++ b/dlls/winegstreamer/media_source.c
@@ -27,6 +27,12 @@
WINE_DEFAULT_DEBUG_CHANNEL(mfplat);
+struct pending_sample
+{
+ struct list entry;
+ IMFSample *sample;
+};
+
struct media_stream
{
IMFMediaStream IMFMediaStream_iface;
@@ -34,6 +40,7 @@ struct media_stream
struct media_source *parent_source;
IMFMediaEventQueue *event_queue;
IMFStreamDescriptor *descriptor;
+ struct list pending_samples;
struct wg_parser_stream *wg_stream;
@@ -50,6 +57,7 @@ struct media_stream
enum source_async_op
{
SOURCE_ASYNC_START,
+ SOURCE_ASYNC_PAUSE,
SOURCE_ASYNC_STOP,
SOURCE_ASYNC_REQUEST_SAMPLE,
};
@@ -96,6 +104,7 @@ struct media_source
{
SOURCE_OPENING,
SOURCE_STOPPED,
+ SOURCE_PAUSED,
SOURCE_RUNNING,
SOURCE_SHUTDOWN,
} state;
@@ -257,6 +266,23 @@ static IMFStreamDescriptor *stream_descriptor_from_id(IMFPresentationDescriptor
return NULL;
}
+static void flush_pending_queue(struct media_stream *stream, BOOL send_events)
+{
+ struct pending_sample *pending, *pending2;
+
+ LIST_FOR_EACH_ENTRY_SAFE(pending, pending2, &stream->pending_samples, struct pending_sample, entry)
+ {
+ if (send_events)
+ {
+ IMFMediaEventQueue_QueueEventParamUnk(stream->event_queue, MEMediaSample,
+ &GUID_NULL, S_OK, (IUnknown *)pending->sample);
+ }
+ IMFSample_Release(pending->sample);
+ list_remove(&pending->entry);
+ free(pending);
+ }
+}
+
static void start_pipeline(struct media_source *source, struct source_async_command *command)
{
PROPVARIANT *position = &command->u.start.position;
@@ -269,7 +295,8 @@ static void start_pipeline(struct media_source *source, struct source_async_comm
position->vt = VT_I8;
position->hVal.QuadPart = 0;
}
- source->start_time = position->hVal.QuadPart;
+ if (position->vt != VT_EMPTY)
+ source->start_time = position->hVal.QuadPart;
for (i = 0; i < source->stream_count; i++)
{
@@ -318,6 +345,8 @@ static void start_pipeline(struct media_source *source, struct source_async_comm
IMFMediaEventQueue_QueueEventParamVar(stream->event_queue,
seek_message ? MEStreamSeeked : MEStreamStarted, &GUID_NULL, S_OK, position);
+
+ flush_pending_queue(stream, TRUE);
}
}
@@ -327,11 +356,30 @@ static void start_pipeline(struct media_source *source, struct source_async_comm
source->state = SOURCE_RUNNING;
- unix_funcs->wg_parser_stream_seek(source->streams[0]->wg_stream, 1.0,
- position->hVal.QuadPart, 0, AM_SEEKING_AbsolutePositioning, AM_SEEKING_NoPositioning);
+ if (position->vt != VT_EMPTY)
+ 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);
}
+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)
{
unsigned int i;
@@ -343,6 +391,7 @@ static void stop_pipeline(struct media_source *source)
struct media_stream *stream = source->streams[i];
if (stream->state != STREAM_INACTIVE)
{
+ flush_pending_queue(stream, FALSE);
IMFMediaEventQueue_QueueEventParamVar(stream->event_queue, MEStreamStopped, &GUID_NULL, S_OK, NULL);
unix_funcs->wg_parser_stream_disable(stream->wg_stream);
}
@@ -437,12 +486,26 @@ static void send_buffer(struct media_stream *stream, const struct wg_parser_even
if (token)
IMFSample_SetUnknown(sample, &MFSampleExtension_Token, token);
- IMFMediaEventQueue_QueueEventParamUnk(stream->event_queue, MEMediaSample,
- &GUID_NULL, S_OK, (IUnknown *)sample);
+ if (stream->parent_source->state == SOURCE_PAUSED)
+ {
+ struct pending_sample *pending = malloc(sizeof(*pending));
+ if (!pending)
+ {
+ ERR("Cannot allocate pending sample\n");
+ goto out;
+ }
+ pending->sample = sample;
+ sample = NULL;
+ list_add_tail(&stream->pending_samples, &pending->entry);
+ }
+ else
+ IMFMediaEventQueue_QueueEventParamUnk(stream->event_queue, MEMediaSample,
+ &GUID_NULL, S_OK, (IUnknown *)sample);
out:
IMFMediaBuffer_Release(buffer);
- IMFSample_Release(sample);
+ if (sample)
+ IMFSample_Release(sample);
}
static void wait_on_sample(struct media_stream *stream, IUnknown *token)
@@ -501,6 +564,9 @@ 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;
@@ -597,6 +663,7 @@ static ULONG WINAPI media_stream_Release(IMFMediaStream *iface)
{
if (stream->event_queue)
IMFMediaEventQueue_Release(stream->event_queue);
+ flush_pending_queue(stream, FALSE);
free(stream);
}
@@ -699,7 +766,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);
}
@@ -738,6 +804,7 @@ static HRESULT new_media_stream(struct media_source *source,
object->state = STREAM_INACTIVE;
object->eos = FALSE;
object->wg_stream = wg_stream;
+ list_init(&object->pending_samples);
if (FAILED(hr = MFCreateEventQueue(&object->event_queue)))
goto fail;
@@ -1123,7 +1190,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;
}
@@ -1187,13 +1254,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 hr;
}
static HRESULT WINAPI media_source_Shutdown(IMFMediaSource *iface)
--
2.32.0
More information about the wine-devel
mailing list