With caps created from the input / output formats.
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=51931 Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=52391 Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- dlls/winegstreamer/gst_private.h | 3 +- dlls/winegstreamer/main.c | 9 ++- dlls/winegstreamer/unix_private.h | 1 + dlls/winegstreamer/unixlib.h | 2 + dlls/winegstreamer/wg_parser.c | 2 +- dlls/winegstreamer/wg_transform.c | 93 +++++++++++++++++++++++++++++++ dlls/winegstreamer/wma_decoder.c | 2 +- 7 files changed, 107 insertions(+), 5 deletions(-)
diff --git a/dlls/winegstreamer/gst_private.h b/dlls/winegstreamer/gst_private.h index cec52e976ec..5d198f57dc7 100644 --- a/dlls/winegstreamer/gst_private.h +++ b/dlls/winegstreamer/gst_private.h @@ -96,7 +96,8 @@ uint64_t wg_parser_stream_get_duration(struct wg_parser_stream *stream) DECLSPEC void wg_parser_stream_seek(struct wg_parser_stream *stream, double rate, uint64_t start_pos, uint64_t stop_pos, DWORD start_flags, DWORD stop_flags) DECLSPEC_HIDDEN;
-struct wg_transform *wg_transform_create(void) DECLSPEC_HIDDEN; +struct wg_transform *wg_transform_create(const struct wg_encoded_format *input_format, + const struct wg_format *output_format) DECLSPEC_HIDDEN; void wg_transform_destroy(struct wg_transform *transform) DECLSPEC_HIDDEN;
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 f23fa3abcdf..6dfa9eb5c82 100644 --- a/dlls/winegstreamer/main.c +++ b/dlls/winegstreamer/main.c @@ -254,9 +254,14 @@ void wg_parser_stream_seek(struct wg_parser_stream *stream, double rate, __wine_unix_call(unix_handle, unix_wg_parser_stream_seek, ¶ms); }
-struct wg_transform *wg_transform_create(void) +struct wg_transform *wg_transform_create(const struct wg_encoded_format *input_format, + const struct wg_format *output_format) { - struct wg_transform_create_params params = {0}; + struct wg_transform_create_params params = + { + .input_format = input_format, + .output_format = output_format, + };
if (__wine_unix_call(unix_handle, unix_wg_transform_create, ¶ms)) return NULL; diff --git a/dlls/winegstreamer/unix_private.h b/dlls/winegstreamer/unix_private.h index 375d33e7728..38349eb5e8d 100644 --- a/dlls/winegstreamer/unix_private.h +++ b/dlls/winegstreamer/unix_private.h @@ -24,6 +24,7 @@ #include "unixlib.h"
extern bool init_gstreamer(void) DECLSPEC_HIDDEN; +extern GstCaps *wg_format_to_caps(const struct wg_format *format) DECLSPEC_HIDDEN;
extern NTSTATUS wg_transform_create(void *args) DECLSPEC_HIDDEN; extern NTSTATUS wg_transform_destroy(void *args) DECLSPEC_HIDDEN; diff --git a/dlls/winegstreamer/unixlib.h b/dlls/winegstreamer/unixlib.h index ea46de4cce1..96cda2e25aa 100644 --- a/dlls/winegstreamer/unixlib.h +++ b/dlls/winegstreamer/unixlib.h @@ -245,6 +245,8 @@ struct wg_parser_stream_seek_params struct wg_transform_create_params { struct wg_transform *transform; + const struct wg_encoded_format *input_format; + const struct wg_format *output_format; };
enum unix_funcs diff --git a/dlls/winegstreamer/wg_parser.c b/dlls/winegstreamer/wg_parser.c index ac8c5a2b95c..e7e80ecfddf 100644 --- a/dlls/winegstreamer/wg_parser.c +++ b/dlls/winegstreamer/wg_parser.c @@ -463,7 +463,7 @@ static GstCaps *wg_format_to_caps_video(const struct wg_format *format) return caps; }
-static GstCaps *wg_format_to_caps(const struct wg_format *format) +GstCaps *wg_format_to_caps(const struct wg_format *format) { switch (format->major_type) { diff --git a/dlls/winegstreamer/wg_transform.c b/dlls/winegstreamer/wg_transform.c index 822740da0d7..146cdd87ae7 100644 --- a/dlls/winegstreamer/wg_transform.c +++ b/dlls/winegstreamer/wg_transform.c @@ -42,12 +42,77 @@ GST_DEBUG_CATEGORY_EXTERN(wine);
struct wg_transform { + GstPad *my_src, *my_sink; };
+static GstCaps *wg_format_to_caps_xwma(const struct wg_encoded_format *format) +{ + GstBuffer *buffer; + GstCaps *caps; + + if (format->encoded_type == WG_ENCODED_TYPE_WMA) + caps = gst_caps_new_empty_simple("audio/x-wma"); + else + caps = gst_caps_new_empty_simple("audio/x-xma"); + + if (format->u.xwma.version) + gst_caps_set_simple(caps, "wmaversion", G_TYPE_INT, format->u.xwma.version, NULL); + if (format->u.xwma.bitrate) + gst_caps_set_simple(caps, "bitrate", G_TYPE_INT, format->u.xwma.bitrate, NULL); + if (format->u.xwma.rate) + gst_caps_set_simple(caps, "rate", G_TYPE_INT, format->u.xwma.rate, NULL); + if (format->u.xwma.depth) + gst_caps_set_simple(caps, "depth", G_TYPE_INT, format->u.xwma.depth, NULL); + if (format->u.xwma.channels) + gst_caps_set_simple(caps, "channels", G_TYPE_INT, format->u.xwma.channels, NULL); + if (format->u.xwma.block_align) + gst_caps_set_simple(caps, "block_align", G_TYPE_INT, format->u.xwma.block_align, NULL); + + if (format->u.xwma.codec_data_len) + { + buffer = gst_buffer_new_and_alloc(format->u.xwma.codec_data_len); + gst_buffer_fill(buffer, 0, format->u.xwma.codec_data, format->u.xwma.codec_data_len); + gst_caps_set_simple(caps, "codec_data", GST_TYPE_BUFFER, buffer, NULL); + gst_buffer_unref(buffer); + } + + return caps; +} + +static GstCaps *wg_encoded_format_to_caps(const struct wg_encoded_format *format) +{ + switch (format->encoded_type) + { + case WG_ENCODED_TYPE_UNKNOWN: + return NULL; + case WG_ENCODED_TYPE_WMA: + case WG_ENCODED_TYPE_XMA: + return wg_format_to_caps_xwma(format); + } + assert(0); + return NULL; +} + +static GstFlowReturn transform_sink_chain_cb(GstPad *pad, GstObject *parent, GstBuffer *buffer) +{ + struct wg_transform *transform = gst_pad_get_element_private(pad); + + GST_INFO("transform %p, buffer %p.", transform, buffer); + + gst_buffer_unref(buffer); + + return GST_FLOW_OK; +} + NTSTATUS wg_transform_destroy(void *args) { struct wg_transform *transform = args;
+ if (transform->my_sink) + g_object_unref(transform->my_sink); + if (transform->my_src) + g_object_unref(transform->my_src); + free(transform); return S_OK; } @@ -55,7 +120,11 @@ NTSTATUS wg_transform_destroy(void *args) NTSTATUS wg_transform_create(void *args) { struct wg_transform_create_params *params = args; + struct wg_encoded_format input_format = *params->input_format; + struct wg_format output_format = *params->output_format; + GstCaps *src_caps, *sink_caps; struct wg_transform *transform; + GstPadTemplate *template;
if (!init_gstreamer()) return E_FAIL; @@ -63,7 +132,31 @@ NTSTATUS wg_transform_create(void *args) if (!(transform = calloc(1, sizeof(*transform)))) return E_OUTOFMEMORY;
+ src_caps = wg_encoded_format_to_caps(&input_format); + assert(src_caps); + sink_caps = wg_format_to_caps(&output_format); + assert(sink_caps); + + template = gst_pad_template_new("src", GST_PAD_SRC, GST_PAD_ALWAYS, src_caps); + assert(template); + transform->my_src = gst_pad_new_from_template(template, "src"); + g_object_unref(template); + assert(transform->my_src); + + template = gst_pad_template_new("sink", GST_PAD_SINK, GST_PAD_ALWAYS, sink_caps); + assert(template); + transform->my_sink = gst_pad_new_from_template(template, "sink"); + g_object_unref(template); + assert(transform->my_sink); + + gst_pad_set_element_private(transform->my_sink, transform); + gst_pad_set_chain_function(transform->my_sink, transform_sink_chain_cb); + GST_INFO("Created winegstreamer transform %p.", transform); params->transform = transform; + + gst_caps_unref(src_caps); + gst_caps_unref(sink_caps); + return S_OK; } diff --git a/dlls/winegstreamer/wma_decoder.c b/dlls/winegstreamer/wma_decoder.c index b037795fc78..4183df43fed 100644 --- a/dlls/winegstreamer/wma_decoder.c +++ b/dlls/winegstreamer/wma_decoder.c @@ -79,7 +79,7 @@ static HRESULT try_create_wg_transform(struct wma_decoder *decoder) if (output_format.major_type == WG_MAJOR_TYPE_UNKNOWN) return MF_E_INVALIDMEDIATYPE;
- decoder->wg_transform = wg_transform_create(); + decoder->wg_transform = wg_transform_create(&input_format, &output_format); if (decoder->wg_transform) return S_OK;