Instead of checking the enabled state.
The reasoning here is that we would like to keep the stream enabled—that is, buffer samples instead of discarding them—even when the client is not yet reading samples from it, so that we can avoid wasting CPU power in decoding.
Signed-off-by: Zebediah Figura zfigura@codeweavers.com --- dlls/winegstreamer/wg_format.c | 2 +- dlls/winegstreamer/wg_parser.c | 11 ++++------- 2 files changed, 5 insertions(+), 8 deletions(-)
diff --git a/dlls/winegstreamer/wg_format.c b/dlls/winegstreamer/wg_format.c index b4455a6e6d0..84163f1e5d7 100644 --- a/dlls/winegstreamer/wg_format.c +++ b/dlls/winegstreamer/wg_format.c @@ -495,7 +495,7 @@ GstCaps *wg_format_to_caps(const struct wg_format *format) switch (format->major_type) { case WG_MAJOR_TYPE_UNKNOWN: - return NULL; + return gst_caps_new_any(); case WG_MAJOR_TYPE_WMA: return wg_format_to_caps_wma(format); case WG_MAJOR_TYPE_H264: diff --git a/dlls/winegstreamer/wg_parser.c b/dlls/winegstreamer/wg_parser.c index e7a60ec158a..9b3a5ca796d 100644 --- a/dlls/winegstreamer/wg_parser.c +++ b/dlls/winegstreamer/wg_parser.c @@ -254,6 +254,7 @@ static NTSTATUS wg_parser_stream_disable(void *args)
pthread_mutex_lock(&parser->mutex); stream->enabled = false; + stream->current_format.major_type = WG_MAJOR_TYPE_UNKNOWN; pthread_mutex_unlock(&parser->mutex); pthread_cond_signal(&stream->event_empty_cond); return S_OK; @@ -601,12 +602,7 @@ static gboolean sink_query_cb(GstPad *pad, GstObject *parent, GstQuery *query) gst_query_parse_caps(query, &filter);
pthread_mutex_lock(&parser->mutex); - - if (stream->enabled) - caps = wg_format_to_caps(&stream->current_format); - else - caps = gst_caps_new_any(); - + caps = wg_format_to_caps(&stream->current_format); pthread_mutex_unlock(&parser->mutex);
if (!caps) @@ -636,7 +632,7 @@ static gboolean sink_query_cb(GstPad *pad, GstObject *parent, GstQuery *query)
pthread_mutex_lock(&parser->mutex);
- if (!stream->enabled) + if (stream->current_format.major_type == WG_MAJOR_TYPE_UNKNOWN) { pthread_mutex_unlock(&parser->mutex); gst_query_set_accept_caps_result(query, TRUE); @@ -689,6 +685,7 @@ static struct wg_parser_stream *create_stream(struct wg_parser *parser) gst_segment_init(&stream->segment, GST_FORMAT_UNDEFINED);
stream->parser = parser; + stream->current_format.major_type = WG_MAJOR_TYPE_UNKNOWN; pthread_cond_init(&stream->event_cond, NULL); pthread_cond_init(&stream->event_empty_cond, NULL);
Allow the initial state of a stream to be enabled.
Signed-off-by: Zebediah Figura zfigura@codeweavers.com --- dlls/winegstreamer/media_source.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-)
diff --git a/dlls/winegstreamer/media_source.c b/dlls/winegstreamer/media_source.c index c9f95a8a451..f07b83f413e 100644 --- a/dlls/winegstreamer/media_source.c +++ b/dlls/winegstreamer/media_source.c @@ -363,6 +363,10 @@ static void start_pipeline(struct media_source *source, struct source_async_comm IMFMediaType_Release(current_mt); IMFMediaTypeHandler_Release(mth); } + else + { + wg_parser_stream_disable(stream->wg_stream); + }
if (position->vt != VT_EMPTY) stream->eos = FALSE; @@ -419,10 +423,7 @@ static void stop_pipeline(struct media_source *source) { struct media_stream *stream = source->streams[i]; if (stream->state != STREAM_INACTIVE) - { IMFMediaEventQueue_QueueEventParamVar(stream->event_queue, MEStreamStopped, &GUID_NULL, S_OK, NULL); - wg_parser_stream_disable(stream->wg_stream); - } }
IMFMediaEventQueue_QueueEventParamVar(source->event_queue, MESourceStopped, &GUID_NULL, S_OK, NULL);
Allow the initial state of a stream to be enabled.
Signed-off-by: Zebediah Figura zfigura@codeweavers.com --- dlls/winegstreamer/quartz_parser.c | 35 +++++++++++++++--------------- 1 file changed, 18 insertions(+), 17 deletions(-)
diff --git a/dlls/winegstreamer/quartz_parser.c b/dlls/winegstreamer/quartz_parser.c index f38a0c16215..7b82f3efbc9 100644 --- a/dlls/winegstreamer/quartz_parser.c +++ b/dlls/winegstreamer/quartz_parser.c @@ -961,6 +961,24 @@ static HRESULT parser_init_stream(struct strmbase_filter *iface)
filter->streaming = true;
+ for (i = 0; i < filter->source_count; ++i) + { + struct parser_source *source = filter->sources[i]; + struct wg_format format; + bool ret; + + if (source->pin.pin.peer) + { + ret = amt_to_wg_format(&source->pin.pin.mt, &format); + assert(ret); + wg_parser_stream_enable(source->wg_stream, &format); + } + else + { + wg_parser_stream_disable(source->wg_stream); + } + } + /* DirectShow retains the old seek positions, but resets to them every time * it transitions from stopped -> paused. */
@@ -1529,8 +1547,6 @@ static HRESULT WINAPI GSTOutPin_DecideBufferSize(struct strmbase_source *iface, struct parser_source *pin = impl_source_from_IPin(&iface->pin.IPin_iface); unsigned int buffer_size = 16384; ALLOCATOR_PROPERTIES ret_props; - struct wg_format format; - bool ret;
if (IsEqualGUID(&pin->pin.pin.mt.formattype, &FORMAT_VideoInfo)) { @@ -1545,10 +1561,6 @@ static HRESULT WINAPI GSTOutPin_DecideBufferSize(struct strmbase_source *iface, buffer_size = format->nAvgBytesPerSec; }
- ret = amt_to_wg_format(&pin->pin.pin.mt, &format); - assert(ret); - wg_parser_stream_enable(pin->wg_stream, &format); - /* We do need to drop any buffers that might have been sent with the old * caps, but this will be handled in parser_init_stream(). */
@@ -1558,13 +1570,6 @@ static HRESULT WINAPI GSTOutPin_DecideBufferSize(struct strmbase_source *iface, return IMemAllocator_SetProperties(allocator, props, &ret_props); }
-static void source_disconnect(struct strmbase_source *iface) -{ - struct parser_source *pin = impl_source_from_IPin(&iface->pin.IPin_iface); - - wg_parser_stream_disable(pin->wg_stream); -} - static void free_source_pin(struct parser_source *pin) { if (pin->pin.pin.peer) @@ -1590,7 +1595,6 @@ static const struct strmbase_source_ops source_ops = .pfnAttemptConnection = BaseOutputPinImpl_AttemptConnection, .pfnDecideAllocator = BaseOutputPinImpl_DecideAllocator, .pfnDecideBufferSize = GSTOutPin_DecideBufferSize, - .source_disconnect = source_disconnect, };
static struct parser_source *create_pin(struct parser *filter, @@ -1629,9 +1633,6 @@ static HRESULT GST_RemoveOutputPins(struct parser *This) if (!This->sink_connected) return S_OK;
- /* Disconnecting source pins triggers a call to wg_parser_stream_disable(). - * The stream pointers are no longer valid after wg_parser_disconnect(), so - * make sure we disable the streams first. */ for (i = 0; i < This->source_count; ++i) { if (This->sources[i])
This patch is motivated by Obduction, which creates a Media Foundation source and leaves it open arbitrarily long before actually reading samples from it. Without this patch, we unnecessarily waste CPU, and may reduce graphical performance by taking CPU time that would otherwise be used on performance-critical threads.
Signed-off-by: Zebediah Figura zfigura@codeweavers.com --- dlls/winegstreamer/wg_parser.c | 7 +++++++ 1 file changed, 7 insertions(+)
diff --git a/dlls/winegstreamer/wg_parser.c b/dlls/winegstreamer/wg_parser.c index 9b3a5ca796d..48b88a4b11c 100644 --- a/dlls/winegstreamer/wg_parser.c +++ b/dlls/winegstreamer/wg_parser.c @@ -1293,6 +1293,13 @@ static NTSTATUS wg_parser_connect(void *args) pthread_cond_wait(&parser->init_cond, &parser->mutex); } } + + /* Now that we're fully initialized, enable the stream so that further + * samples get queued instead of being discarded. We don't actually need + * the samples (in particular, the frontend should seek before + * attempting to read anything), but we don't want to waste CPU time + * trying to decode them. */ + stream->enabled = true; }
pthread_mutex_unlock(&parser->mutex);