From: Rémi Bernon rbernon@codeweavers.com
--- dlls/winegstreamer/gst_private.h | 2 +- dlls/winegstreamer/main.c | 15 ++++++++++++--- dlls/winegstreamer/media_source.c | 2 +- dlls/winegstreamer/unix_private.h | 1 + dlls/winegstreamer/unixlib.c | 26 ++++++++++++++++++++++++++ dlls/winegstreamer/unixlib.h | 3 +++ dlls/winegstreamer/wg_parser.c | 24 +++++++++++++++++++++++- dlls/winegstreamer/wg_source.c | 10 ++++++++++ 8 files changed, 77 insertions(+), 6 deletions(-)
diff --git a/dlls/winegstreamer/gst_private.h b/dlls/winegstreamer/gst_private.h index fd33ac42c19..b08e3566de4 100644 --- a/dlls/winegstreamer/gst_private.h +++ b/dlls/winegstreamer/gst_private.h @@ -110,7 +110,7 @@ bool wg_transform_get_status(wg_transform_t transform, bool *accepts_input); HRESULT wg_transform_drain(wg_transform_t transform); HRESULT wg_transform_flush(wg_transform_t transform);
-HRESULT wg_source_create(wg_source_t *out); +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);
unsigned int wg_format_get_max_size(const struct wg_format *format); diff --git a/dlls/winegstreamer/main.c b/dlls/winegstreamer/main.c index 8237936891c..30cfe079686 100644 --- a/dlls/winegstreamer/main.c +++ b/dlls/winegstreamer/main.c @@ -456,12 +456,20 @@ HRESULT wg_transform_flush(wg_transform_t transform) return S_OK; }
-HRESULT wg_source_create(wg_source_t *out) +HRESULT wg_source_create(const WCHAR *url, const void *data, uint32_t size, wg_source_t *out) { - struct wg_source_create_params params = {0}; + struct wg_source_create_params params = + { + .data = data, .size = size, + }; + UINT len = url ? WideCharToMultiByte(CP_ACP, 0, url, -1, NULL, 0, NULL, NULL) : 0; + char *tmp = url ? malloc(len) : NULL; NTSTATUS status;
- TRACE("out %p\n", out); + TRACE("url %s, data %p, size %#x\n", debugstr_w(url), data, size); + + if ((params.url = tmp)) + WideCharToMultiByte(CP_ACP, 0, url, -1, tmp, len, NULL, NULL);
if ((status = WINE_UNIX_CALL(unix_wg_source_create, ¶ms))) WARN("wg_source_create returned status %#lx\n", status); @@ -471,6 +479,7 @@ HRESULT wg_source_create(wg_source_t *out) *out = params.source; }
+ free(tmp); return HRESULT_FROM_NT(status); }
diff --git a/dlls/winegstreamer/media_source.c b/dlls/winegstreamer/media_source.c index 58ea8ed0c2b..950c1506152 100644 --- a/dlls/winegstreamer/media_source.c +++ b/dlls/winegstreamer/media_source.c @@ -2024,7 +2024,7 @@ static HRESULT WINAPI stream_handler_callback_Invoke(IMFAsyncCallback *iface, IM
if (FAILED(hr = IMFByteStream_EndRead(context->stream, result, &size))) WARN("Failed to complete stream read, hr %#lx\n", hr); - else if (FAILED(hr = wg_source_create(&context->wg_source))) + 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 = media_source_create(context, (IMFMediaSource **)&object))) WARN("Failed to create media source, hr %#lx\n", hr); diff --git a/dlls/winegstreamer/unix_private.h b/dlls/winegstreamer/unix_private.h index 8574cac797f..5e96d8a144a 100644 --- a/dlls/winegstreamer/unix_private.h +++ b/dlls/winegstreamer/unix_private.h @@ -39,6 +39,7 @@ extern GstElement *find_element(GstElementFactoryListType type, GstCaps *src_cap extern bool append_element(GstElement *container, GstElement *element, GstElement **first, GstElement **last) DECLSPEC_HIDDEN; extern bool link_src_to_element(GstPad *src_pad, GstElement *element) DECLSPEC_HIDDEN; extern bool link_element_to_sink(GstElement *element, GstPad *sink_pad) DECLSPEC_HIDDEN; +extern GstCaps *detect_caps_from_data(const char *url, const void *data, guint size) DECLSPEC_HIDDEN;
/* wg_format.c */
diff --git a/dlls/winegstreamer/unixlib.c b/dlls/winegstreamer/unixlib.c index cb28b76b65e..b926ee1dac3 100644 --- a/dlls/winegstreamer/unixlib.c +++ b/dlls/winegstreamer/unixlib.c @@ -203,6 +203,32 @@ bool link_element_to_sink(GstElement *element, GstPad *sink_pad) return !ret; }
+GstCaps *detect_caps_from_data(const char *url, const void *data, guint size) +{ + const char *extension = url ? strrchr(url, '.') : NULL; + GstTypeFindProbability probability; + GstCaps *caps; + gchar *str; + + if (!(caps = gst_type_find_helper_for_data_with_extension(NULL, data, size, + extension ? extension + 1 : NULL, &probability))) + { + GST_ERROR("Failed to detect caps for url %s, data %p, size %u", url, data, size); + return NULL; + } + + str = gst_caps_to_string(caps); + if (probability > GST_TYPE_FIND_POSSIBLE) + GST_INFO("Detected caps %s with probability %u for url %s, data %p, size %u", + str, probability, url, data, size); + else + GST_FIXME("Detected caps %s with probability %u for url %s, data %p, size %u", + str, probability, url, data, size); + g_free(str); + + return caps; +} + NTSTATUS wg_init_gstreamer(void *arg) { char arg0[] = "wine"; diff --git a/dlls/winegstreamer/unixlib.h b/dlls/winegstreamer/unixlib.h index 7fb177c4ed5..f44774fc06f 100644 --- a/dlls/winegstreamer/unixlib.h +++ b/dlls/winegstreamer/unixlib.h @@ -366,6 +366,9 @@ struct wg_transform_get_status_params
struct wg_source_create_params { + const char *url; + const void *data; + UINT32 size; wg_source_t source; };
diff --git a/dlls/winegstreamer/wg_parser.c b/dlls/winegstreamer/wg_parser.c index 387871d116a..d03900c8afc 100644 --- a/dlls/winegstreamer/wg_parser.c +++ b/dlls/winegstreamer/wg_parser.c @@ -2155,6 +2155,28 @@ NTSTATUS wow64_wg_transform_read_data(void *args) return ret; }
+NTSTATUS wow64_wg_source_create(void *args) +{ + struct + { + PTR32 url; + PTR32 data; + UINT32 size; + wg_source_t source; + } *params32 = args; + struct wg_source_create_params params = + { + .url = ULongToPtr(params32->url), + .data = ULongToPtr(params32->data), + .size = params32->size, + }; + NTSTATUS ret; + + ret = wg_source_create(¶ms); + params32->source = params.source; + return ret; +} + const unixlib_entry_t __wine_unix_call_wow64_funcs[] = { #define X64(name) [unix_ ## name] = wow64_ ## name @@ -2196,7 +2218,7 @@ const unixlib_entry_t __wine_unix_call_wow64_funcs[] = X(wg_transform_drain), X(wg_transform_flush),
- X(wg_source_create), + X64(wg_source_create), X(wg_source_destroy), };
diff --git a/dlls/winegstreamer/wg_source.c b/dlls/winegstreamer/wg_source.c index 52a54196ea9..0cdb3f3fdb7 100644 --- a/dlls/winegstreamer/wg_source.c +++ b/dlls/winegstreamer/wg_source.c @@ -53,9 +53,15 @@ NTSTATUS wg_source_create(void *args) { struct wg_source_create_params *params = args; struct wg_source *source; + GstCaps *src_caps;
+ if (!(src_caps = detect_caps_from_data(params->url, params->data, params->size))) + return STATUS_UNSUCCESSFUL; if (!(source = calloc(1, sizeof(*source)))) + { + gst_caps_unref(src_caps); return STATUS_UNSUCCESSFUL; + }
if (!(source->container = gst_bin_new("wg_source"))) goto error; @@ -64,6 +70,8 @@ NTSTATUS wg_source_create(void *args) if (!gst_element_get_state(source->container, NULL, NULL, -1)) goto error;
+ gst_caps_unref(src_caps); + params->source = (wg_source_t)(ULONG_PTR)source; GST_INFO("Created winegstreamer source %p.", source); return STATUS_SUCCESS; @@ -76,6 +84,8 @@ error: } free(source);
+ gst_caps_unref(src_caps); + GST_ERROR("Failed to create winegstreamer source."); return STATUS_UNSUCCESSFUL; }