From: Rémi Bernon rbernon@codeweavers.com
--- dlls/winegstreamer/gst_private.h | 1 + dlls/winegstreamer/main.c | 15 ++++++++++ dlls/winegstreamer/media_source.c | 3 ++ dlls/winegstreamer/unix_private.h | 1 + dlls/winegstreamer/unixlib.h | 9 ++++++ dlls/winegstreamer/wg_parser.c | 22 ++++++++++++++ dlls/winegstreamer/wg_source.c | 48 +++++++++++++++++++++++++++++++ 7 files changed, 99 insertions(+)
diff --git a/dlls/winegstreamer/gst_private.h b/dlls/winegstreamer/gst_private.h index 11dfbf8e0b5..527fdf47b07 100644 --- a/dlls/winegstreamer/gst_private.h +++ b/dlls/winegstreamer/gst_private.h @@ -106,6 +106,7 @@ void wg_parser_stream_seek(wg_parser_stream_t stream, double rate,
HRESULT wg_source_create(const WCHAR *url, const void *data, uint32_t size, wg_source_t *out); void wg_source_destroy(wg_source_t source); +HRESULT wg_source_push_data(wg_source_t source, UINT64 offset, const void *data, uint32_t size);
HRESULT wg_transform_create_mf(IMFMediaType *input_type, IMFMediaType *output_type, const struct wg_transform_attrs *attrs, wg_transform_t *transform); diff --git a/dlls/winegstreamer/main.c b/dlls/winegstreamer/main.c index 04bff47bd5c..7caf1fb0782 100644 --- a/dlls/winegstreamer/main.c +++ b/dlls/winegstreamer/main.c @@ -471,6 +471,21 @@ void wg_source_destroy(wg_source_t source) WINE_UNIX_CALL(unix_wg_source_destroy, &source); }
+HRESULT wg_source_push_data(wg_source_t source, UINT64 offset, const void *data, uint32_t size) +{ + struct wg_source_push_data_params params = + { + .source = source, + .offset = offset, + .data = data, + .size = size, + }; + + TRACE("source %#I64x, offset %#I64x, data %p, size %#x\n", source, offset, data, size); + + return HRESULT_FROM_NT(WINE_UNIX_CALL(unix_wg_source_push_data, ¶ms)); +} + HRESULT wg_transform_create_mf(IMFMediaType *input_type, IMFMediaType *output_type, const struct wg_transform_attrs *attrs, wg_transform_t *transform) { diff --git a/dlls/winegstreamer/media_source.c b/dlls/winegstreamer/media_source.c index 7688631f7bf..0cb83437b61 100644 --- a/dlls/winegstreamer/media_source.c +++ b/dlls/winegstreamer/media_source.c @@ -38,6 +38,7 @@ struct object_context WCHAR *url;
wg_source_t wg_source; + UINT64 read_offset; UINT32 buffer_size; BYTE *buffer; }; @@ -2050,6 +2051,8 @@ static HRESULT WINAPI stream_handler_callback_Invoke(IMFAsyncCallback *iface, IM WARN("Failed to complete stream read, hr %#lx\n", hr); else if (FAILED(hr = wg_source_create(context->url, context->buffer, size, &context->wg_source))) WARN("Failed to create wg_source, hr %#lx\n", hr); + else if (FAILED(hr = wg_source_push_data(context->wg_source, context->read_offset, context->buffer, size))) + WARN("Failed to push wg_source data, hr %#lx\n", hr); else if (FAILED(hr = media_source_create(context, (IMFMediaSource **)&object))) WARN("Failed to create media source, hr %#lx\n", hr); else diff --git a/dlls/winegstreamer/unix_private.h b/dlls/winegstreamer/unix_private.h index 52412a283ab..7ae74c13a8c 100644 --- a/dlls/winegstreamer/unix_private.h +++ b/dlls/winegstreamer/unix_private.h @@ -72,6 +72,7 @@ extern NTSTATUS wg_transform_notify_qos(void *args);
extern NTSTATUS wg_source_create(void *args); extern NTSTATUS wg_source_destroy(void *args); +extern NTSTATUS wg_source_push_data(void *args);
/* wg_media_type.c */
diff --git a/dlls/winegstreamer/unixlib.h b/dlls/winegstreamer/unixlib.h index 9eab68e14da..a70ecf9cd25 100644 --- a/dlls/winegstreamer/unixlib.h +++ b/dlls/winegstreamer/unixlib.h @@ -338,6 +338,14 @@ struct wg_source_create_params wg_source_t source; };
+struct wg_source_push_data_params +{ + wg_source_t source; + UINT64 offset; + UINT64 size; + const void *data; +}; + struct wg_transform_attrs { UINT32 output_plane_align; @@ -455,6 +463,7 @@ enum unix_funcs
unix_wg_source_create, unix_wg_source_destroy, + unix_wg_source_push_data,
unix_wg_transform_create, unix_wg_transform_destroy, diff --git a/dlls/winegstreamer/wg_parser.c b/dlls/winegstreamer/wg_parser.c index 60dca79ef16..d2292087544 100644 --- a/dlls/winegstreamer/wg_parser.c +++ b/dlls/winegstreamer/wg_parser.c @@ -1889,6 +1889,7 @@ const unixlib_entry_t __wine_unix_call_funcs[] =
X(wg_source_create), X(wg_source_destroy), + X(wg_source_push_data),
X(wg_transform_create), X(wg_transform_destroy), @@ -2085,6 +2086,26 @@ NTSTATUS wow64_wg_source_create(void *args) return ret; }
+NTSTATUS wow64_wg_source_push_data(void *args) +{ + struct + { + wg_source_t source; + UINT64 offset; + UINT64 size; + PTR32 data; + } *params32 = args; + struct wg_source_push_data_params params = + { + .source = params32->source, + .offset = params32->offset, + .size = params32->size, + .data = ULongToPtr(params32->data), + }; + + return wg_source_push_data(¶ms); +} + NTSTATUS wow64_wg_transform_create(void *args) { struct @@ -2311,6 +2332,7 @@ const unixlib_entry_t __wine_unix_call_wow64_funcs[] =
X64(wg_source_create), X(wg_source_destroy), + X64(wg_source_push_data),
X64(wg_transform_create), X(wg_transform_destroy), diff --git a/dlls/winegstreamer/wg_source.c b/dlls/winegstreamer/wg_source.c index 0731c6f156d..4e11adcd878 100644 --- a/dlls/winegstreamer/wg_source.c +++ b/dlls/winegstreamer/wg_source.c @@ -43,6 +43,7 @@ struct wg_source { GstPad *src_pad; GstElement *container; + GstSegment segment; };
static struct wg_source *get_source(wg_source_t source) @@ -73,6 +74,21 @@ static GstCaps *detect_caps_from_data(const char *url, const void *data, guint s return caps; }
+static GstEvent *create_stream_start_event(const char *stream_id) +{ + GstEvent *event; + + if ((event = gst_event_new_stream_start(stream_id))) + { + GstStream *stream = gst_stream_new(stream_id, NULL, GST_STREAM_TYPE_UNKNOWN, 0); + gst_event_set_stream(event, stream); + gst_event_set_group_id(event, 1); + gst_object_unref(stream); + } + + return event; +} + static GstPad *create_pad_with_caps(GstPadDirection direction, GstCaps *caps) { GstCaps *pad_caps = caps ? gst_caps_ref(caps) : gst_caps_new_any(); @@ -105,6 +121,7 @@ NTSTATUS wg_source_create(void *args) gst_caps_unref(src_caps); return STATUS_UNSUCCESSFUL; } + gst_segment_init(&source->segment, GST_FORMAT_BYTES);
if (!(source->container = gst_bin_new("wg_source"))) goto error; @@ -125,6 +142,11 @@ NTSTATUS wg_source_create(void *args) if (!gst_element_get_state(source->container, NULL, NULL, -1)) goto error;
+ if (!push_event(source->src_pad, create_stream_start_event("wg_source"))) + goto error; + if (!push_event(source->src_pad, gst_event_new_segment(&source->segment))) + goto error; + gst_caps_unref(src_caps);
params->source = (wg_source_t)(ULONG_PTR)source; @@ -160,3 +182,29 @@ NTSTATUS wg_source_destroy(void *args)
return STATUS_SUCCESS; } + +NTSTATUS wg_source_push_data(void *args) +{ + struct wg_source_push_data_params *params = args; + struct wg_source *source = get_source(params->source); + + GST_TRACE("source %p, offset %#" G_GINT64_MODIFIER "x, size %#" G_GINT64_MODIFIER "x, data %p", + source, params->offset, params->size, params->data); + + if (!params->size) + { + push_event(source->src_pad, gst_event_new_eos()); + return STATUS_SUCCESS; + } + + if (params->offset > source->segment.start) + source->segment.start = params->offset; + else if (params->offset < source->segment.start) + { + source->segment.start = params->offset; + push_event(source->src_pad, gst_event_new_segment(&source->segment)); + } + + source->segment.start += params->size; + return STATUS_SUCCESS; +}