From: Charlotte Pabst cpabst@codeweavers.com
--- dlls/winegstreamer/gst_private.h | 1 + dlls/winegstreamer/main.c | 15 ++++++++ dlls/winegstreamer/media_source.c | 13 ++++++- dlls/winegstreamer/unixlib.h | 7 ++++ dlls/winegstreamer/wg_parser.c | 61 +++++++++++++++++++++++++++++++ 5 files changed, 96 insertions(+), 1 deletion(-)
diff --git a/dlls/winegstreamer/gst_private.h b/dlls/winegstreamer/gst_private.h index dac5a88bc5c..01f28956bd8 100644 --- a/dlls/winegstreamer/gst_private.h +++ b/dlls/winegstreamer/gst_private.h @@ -82,6 +82,7 @@ bool wg_parser_get_next_read_offset(wg_parser_t parser, uint64_t *offset, uint32 void wg_parser_push_data(wg_parser_t parser, const void *data, uint32_t size);
void wg_parser_set_thin(wg_parser_t parser, BOOL thin); +bool wg_parser_stream_get_thin_event(wg_parser_stream_t stream, BOOL *thin);
uint32_t wg_parser_get_stream_count(wg_parser_t parser); wg_parser_stream_t wg_parser_get_stream(wg_parser_t parser, uint32_t index); diff --git a/dlls/winegstreamer/main.c b/dlls/winegstreamer/main.c index 94a779bf4fb..815861d47f9 100644 --- a/dlls/winegstreamer/main.c +++ b/dlls/winegstreamer/main.c @@ -252,6 +252,21 @@ void wg_parser_set_thin(wg_parser_t parser, BOOL thin) WINE_UNIX_CALL(unix_wg_parser_set_thin, ¶ms); }
+bool wg_parser_stream_get_thin_event(wg_parser_stream_t stream, BOOL *thin) +{ + struct wg_parser_stream_get_thin_event_params params = + { + .stream = stream, + }; + NTSTATUS status; + TRACE("stream %#I64x, thin %p.\n", stream, thin); + + status = WINE_UNIX_CALL(unix_wg_parser_stream_get_thin_event, ¶ms); + if (status == S_OK) + *thin = params.thin; + return !status; +} + uint32_t wg_parser_get_stream_count(wg_parser_t parser) { struct wg_parser_get_stream_count_params params = diff --git a/dlls/winegstreamer/media_source.c b/dlls/winegstreamer/media_source.c index 4e9372e5d6c..9112b5c040d 100644 --- a/dlls/winegstreamer/media_source.c +++ b/dlls/winegstreamer/media_source.c @@ -796,12 +796,23 @@ static HRESULT wait_on_sample(struct media_stream *stream, IUnknown *token) { struct media_source *source = impl_from_IMFMediaSource(stream->media_source); struct wg_parser_buffer buffer; + PROPVARIANT param; + HRESULT hr; + BOOL thin;
TRACE("%p, %p\n", stream, token);
while (wg_parser_stream_get_buffer(source->wg_parser, stream->wg_stream, &buffer)) { - HRESULT hr = media_stream_send_sample(stream, &buffer, token); + if (wg_parser_stream_get_thin_event(stream->wg_stream, &thin)) + { + param.vt = VT_BOOL; + param.boolVal = thin ? VARIANT_TRUE : VARIANT_FALSE; + if (FAILED(hr = IMFMediaEventQueue_QueueEventParamVar(stream->event_queue, MEStreamThinMode, &GUID_NULL, S_OK, ¶m))) + WARN("Failed to queue MEStreamThinMode event, hr %#lx\n", hr); + } + + hr = media_stream_send_sample(stream, &buffer, token); if (hr != S_FALSE) return hr; } diff --git a/dlls/winegstreamer/unixlib.h b/dlls/winegstreamer/unixlib.h index bde18afd77e..2754e1f1b03 100644 --- a/dlls/winegstreamer/unixlib.h +++ b/dlls/winegstreamer/unixlib.h @@ -252,6 +252,12 @@ struct wg_parser_set_thin_params BOOL thin; };
+struct wg_parser_stream_get_thin_event_params +{ + wg_parser_stream_t stream; + BOOL thin; +}; + struct wg_parser_get_stream_count_params { wg_parser_t parser; @@ -437,6 +443,7 @@ enum unix_funcs unix_wg_parser_push_data,
unix_wg_parser_set_thin, + unix_wg_parser_stream_get_thin_event,
unix_wg_parser_get_stream_count, unix_wg_parser_get_stream, diff --git a/dlls/winegstreamer/wg_parser.c b/dlls/winegstreamer/wg_parser.c index a7988513107..b290a35f29e 100644 --- a/dlls/winegstreamer/wg_parser.c +++ b/dlls/winegstreamer/wg_parser.c @@ -111,6 +111,7 @@ struct wg_parser_stream GstCaps *codec_caps; GstCaps *current_caps; GstCaps *desired_caps; + GstEvent *thin_event[2];
pthread_cond_t event_cond, event_empty_cond; GstBuffer *buffer; @@ -125,6 +126,7 @@ struct wg_parser_stream struct decoder_pad_probe_param { struct wg_parser *parser; + bool thin; };
static struct wg_parser *get_parser(wg_parser_t parser) @@ -244,6 +246,28 @@ static NTSTATUS wg_parser_set_thin(void *args) return S_OK; }
+static NTSTATUS wg_parser_stream_get_thin_event(void *args) +{ + struct wg_parser_stream_get_thin_event_params *params = args; + struct wg_parser_stream *stream = get_stream(params->stream); + struct wg_parser *parser = stream->parser; + GstEvent *event = NULL; + gboolean thin; + + pthread_mutex_lock(&parser->mutex); + event = stream->thin_event[1]; + stream->thin_event[1] = NULL; + pthread_mutex_unlock(&parser->mutex); + + if (!event) + return S_FALSE; + + gst_structure_get_boolean(gst_event_get_structure(event), "thin", &thin); + gst_event_unref(event); + params->thin = thin; + return S_OK; +} + static NTSTATUS wg_parser_stream_get_current_format(void *args) { const struct wg_parser_stream_get_current_format_params *params = args; @@ -628,6 +652,14 @@ static GstPadProbeReturn decoder_pad_probe(GstPad *pad, GstPadProbeInfo *info, g thin = param->parser->thin; pthread_mutex_unlock(¶m->parser->mutex);
+ if (thin != param->thin) + { + GstStructure *structure = gst_structure_new("thin", "thin", G_TYPE_BOOLEAN, thin, NULL); + GstEvent *event = gst_event_new_custom(GST_EVENT_CUSTOM_DOWNSTREAM, structure); + gst_pad_send_event(pad, event); + param->thin = thin; + } + if (thin && (buffer = gst_pad_probe_info_get_buffer(info))) { if (GST_BUFFER_FLAG_IS_SET(buffer, GST_BUFFER_FLAG_DELTA_UNIT)) @@ -657,6 +689,9 @@ static void deep_element_added_cb(GstBin *self, GstBin *sub_bin, GstElement *ele { struct decoder_pad_probe_param *param = malloc(sizeof *param); param->parser = parser; + pthread_mutex_lock(&parser->mutex); + param->thin = parser->thin; + pthread_mutex_unlock(&parser->mutex); gst_pad_add_probe(sink, GST_PAD_PROBE_TYPE_BUFFER, decoder_pad_probe, param, free); }
@@ -759,6 +794,17 @@ static gboolean sink_event_cb(GstPad *pad, GstObject *parent, GstEvent *event) pthread_mutex_unlock(&parser->mutex); break;
+ case GST_EVENT_CUSTOM_DOWNSTREAM: + if (gst_structure_has_name(gst_event_get_structure(event), "thin")) + { + pthread_mutex_lock(&parser->mutex); + if (stream->thin_event[0]) + gst_event_unref(stream->thin_event[0]); + stream->thin_event[0] = gst_event_ref(event); + pthread_mutex_unlock(&parser->mutex); + break; + } + default: GST_WARNING("Ignoring "%s" event.", GST_EVENT_TYPE_NAME(event)); } @@ -811,6 +857,14 @@ static GstFlowReturn sink_chain_cb(GstPad *pad, GstObject *parent, GstBuffer *bu return GST_FLOW_ERROR; }
+ if (stream->thin_event[0]) + { + if (stream->thin_event[1]) + gst_event_unref(stream->thin_event[1]); + stream->thin_event[1] = stream->thin_event[0]; + stream->thin_event[0] = NULL; + } + stream->buffer = buffer;
pthread_mutex_unlock(&parser->mutex); @@ -944,6 +998,11 @@ static void free_stream(struct wg_parser_stream *stream) stream->buffer = NULL; }
+ if (stream->thin_event[0]) + gst_event_unref(stream->thin_event[0]); + if (stream->thin_event[1]) + gst_event_unref(stream->thin_event[1]); + pthread_cond_destroy(&stream->event_cond); pthread_cond_destroy(&stream->event_empty_cond);
@@ -1970,6 +2029,7 @@ const unixlib_entry_t __wine_unix_call_funcs[] = X(wg_parser_push_data),
X(wg_parser_set_thin), + X(wg_parser_stream_get_thin_event),
X(wg_parser_get_stream_count), X(wg_parser_get_stream), @@ -2369,6 +2429,7 @@ const unixlib_entry_t __wine_unix_call_wow64_funcs[] = X64(wg_parser_push_data),
X(wg_parser_set_thin), + X(wg_parser_stream_get_thin_event),
X(wg_parser_get_stream_count), X(wg_parser_get_stream),