Since 1.20, gst_element_request_pad_simple is available and gst_element_get_request_pad is marked as deprecated.
From: Ziqing Hui zhui@codeweavers.com
--- dlls/winegstreamer/unixlib.c | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-)
diff --git a/dlls/winegstreamer/unixlib.c b/dlls/winegstreamer/unixlib.c index 6ed38260536..4fcf7d0d469 100644 --- a/dlls/winegstreamer/unixlib.c +++ b/dlls/winegstreamer/unixlib.c @@ -87,15 +87,21 @@ GstElement *find_element(GstElementFactoryListType type, GstCaps *src_caps, GstC if (!(transforms = gst_element_factory_list_get_elements(type, GST_RANK_MARGINAL))) goto done;
- tmp = gst_element_factory_list_filter(transforms, src_caps, GST_PAD_SINK, FALSE); - gst_plugin_feature_list_free(transforms); - if (!(transforms = tmp)) - goto done; + if (src_caps) + { + tmp = gst_element_factory_list_filter(transforms, src_caps, GST_PAD_SINK, FALSE); + gst_plugin_feature_list_free(transforms); + if (!(transforms = tmp)) + goto done; + }
- tmp = gst_element_factory_list_filter(transforms, sink_caps, GST_PAD_SRC, FALSE); - gst_plugin_feature_list_free(transforms); - if (!(transforms = tmp)) - goto done; + if (sink_caps) + { + tmp = gst_element_factory_list_filter(transforms, sink_caps, GST_PAD_SRC, FALSE); + gst_plugin_feature_list_free(transforms); + if (!(transforms = tmp)) + goto done; + }
transforms = g_list_sort(transforms, gst_plugin_feature_rank_compare_func); for (tmp = transforms; tmp != NULL && element == NULL; tmp = tmp->next)
From: Ziqing Hui zhui@codeweavers.com
--- dlls/winegstreamer/unixlib.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-)
diff --git a/dlls/winegstreamer/unixlib.c b/dlls/winegstreamer/unixlib.c index 4fcf7d0d469..f2e0b1ca2fe 100644 --- a/dlls/winegstreamer/unixlib.c +++ b/dlls/winegstreamer/unixlib.c @@ -145,16 +145,17 @@ bool append_element(GstElement *container, GstElement *element, GstElement **fir
if (!gst_bin_add(GST_BIN(container), element) || !gst_element_sync_state_with_parent(element) || - (*last && !gst_element_link(*last, element))) + (last && *last && !gst_element_link(*last, element))) { GST_ERROR("Failed to link %s element.", name); } else { GST_DEBUG("Linked %s element %p.", name, element); - if (!*first) + if (first && !*first) *first = element; - *last = element; + if (last) + *last = element; success = true; }
From: Ziqing Hui zhui@codeweavers.com
--- dlls/winegstreamer/unix_private.h | 1 + dlls/winegstreamer/unixlib.c | 14 ++++++++++++++ dlls/winegstreamer/wg_parser.c | 12 ++++++------ dlls/winegstreamer/wg_transform.c | 16 ++++++++-------- 4 files changed, 29 insertions(+), 14 deletions(-)
diff --git a/dlls/winegstreamer/unix_private.h b/dlls/winegstreamer/unix_private.h index db6bf3ebb2e..8bef7b2b2bd 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 bool push_event(GstPad *pad, GstEvent *event) DECLSPEC_HIDDEN;
/* wg_format.c */
diff --git a/dlls/winegstreamer/unixlib.c b/dlls/winegstreamer/unixlib.c index f2e0b1ca2fe..eca2bb8aacc 100644 --- a/dlls/winegstreamer/unixlib.c +++ b/dlls/winegstreamer/unixlib.c @@ -209,6 +209,20 @@ bool link_element_to_sink(GstElement *element, GstPad *sink_pad) return !ret; }
+bool push_event(GstPad *pad, GstEvent *event) +{ + if (!gst_pad_push_event(pad, event)) + { + const gchar *type_name = gst_event_type_get_name(GST_EVENT_TYPE(event)); + gchar *pad_name = gst_pad_get_name(pad); + + GST_ERROR("Failed to push %s event %p to pad %s.", type_name, event, pad_name); + g_free(pad_name); + return false; + } + return true; +} + NTSTATUS wg_init_gstreamer(void *arg) { char arg0[] = "wine"; diff --git a/dlls/winegstreamer/wg_parser.c b/dlls/winegstreamer/wg_parser.c index 298c05c6b88..5556b52829c 100644 --- a/dlls/winegstreamer/wg_parser.c +++ b/dlls/winegstreamer/wg_parser.c @@ -258,7 +258,7 @@ static NTSTATUS wg_parser_stream_enable(void *args) gst_util_set_object_arg(G_OBJECT(stream->flip), "method", flip ? "vertical-flip" : "none"); }
- gst_pad_push_event(stream->my_sink, gst_event_new_reconfigure()); + push_event(stream->my_sink, gst_event_new_reconfigure()); return S_OK; }
@@ -450,7 +450,7 @@ static NTSTATUS wg_parser_stream_seek(void *args) if ((stop_flags & AM_SEEKING_PositioningBitsMask) == AM_SEEKING_NoPositioning) stop_type = GST_SEEK_TYPE_NONE;
- if (!gst_pad_push_event(get_stream(params->stream)->my_sink, gst_event_new_seek(params->rate, GST_FORMAT_TIME, + if (!push_event(get_stream(params->stream)->my_sink, gst_event_new_seek(params->rate, GST_FORMAT_TIME, flags, start_type, params->start_pos * 100, stop_type, params->stop_pos * 100))) GST_ERROR("Failed to seek.\n");
@@ -480,7 +480,7 @@ static NTSTATUS wg_parser_stream_notify_qos(void *args) if (!(event = gst_event_new_qos(params->underflow ? GST_QOS_TYPE_UNDERFLOW : GST_QOS_TYPE_OVERFLOW, params->proportion, params->diff * 100, stream_time))) GST_ERROR("Failed to create QOS event.\n"); - gst_pad_push_event(stream->my_sink, event); + push_event(stream->my_sink, event);
return S_OK; } @@ -1292,7 +1292,7 @@ static void *push_data(void *arg)
gst_buffer_unref(buffer);
- gst_pad_push_event(parser->my_src, gst_event_new_eos()); + push_event(parser->my_src, gst_event_new_eos());
GST_DEBUG("Stopping push thread.");
@@ -1421,7 +1421,7 @@ static gboolean src_perform_seek(struct wg_parser *parser, GstEvent *event) { flush_event = gst_event_new_flush_start(); gst_event_set_seqnum(flush_event, seqnum); - gst_pad_push_event(parser->my_src, flush_event); + push_event(parser->my_src, flush_event); if (thread) gst_pad_set_active(parser->my_src, 1); } @@ -1433,7 +1433,7 @@ static gboolean src_perform_seek(struct wg_parser *parser, GstEvent *event) { flush_event = gst_event_new_flush_stop(TRUE); gst_event_set_seqnum(flush_event, seqnum); - gst_pad_push_event(parser->my_src, flush_event); + push_event(parser->my_src, flush_event); if (thread) gst_pad_set_active(parser->my_src, 1); } diff --git a/dlls/winegstreamer/wg_transform.c b/dlls/winegstreamer/wg_transform.c index 775fed7a46c..38adf560892 100644 --- a/dlls/winegstreamer/wg_transform.c +++ b/dlls/winegstreamer/wg_transform.c @@ -443,10 +443,10 @@ NTSTATUS wg_transform_create(void *args) goto out;
if (!(event = gst_event_new_stream_start("stream")) - || !gst_pad_push_event(transform->my_src, event)) + || !push_event(transform->my_src, event)) goto out; if (!(event = gst_event_new_caps(src_caps)) - || !gst_pad_push_event(transform->my_src, event)) + || !push_event(transform->my_src, event)) goto out;
/* We need to use GST_FORMAT_TIME here because it's the only format @@ -455,7 +455,7 @@ NTSTATUS wg_transform_create(void *args) transform->segment.start = 0; transform->segment.stop = -1; if (!(event = gst_event_new_segment(&transform->segment)) - || !gst_pad_push_event(transform->my_src, event)) + || !push_event(transform->my_src, event)) goto out;
gst_caps_unref(src_caps); @@ -531,7 +531,7 @@ NTSTATUS wg_transform_set_output_format(void *args) value = "none"; gst_util_set_object_arg(G_OBJECT(transform->video_flip), "method", value); } - if (!gst_pad_push_event(transform->my_sink, gst_event_new_reconfigure())) + if (!push_event(transform->my_sink, gst_event_new_reconfigure())) { GST_ERROR("Failed to reconfigure transform %p.", transform); return STATUS_UNSUCCESSFUL; @@ -892,16 +892,16 @@ NTSTATUS wg_transform_drain(void *args) }
if (!(event = gst_event_new_segment_done(GST_FORMAT_TIME, -1)) - || !gst_pad_push_event(transform->my_src, event)) + || !push_event(transform->my_src, event)) goto error; if (!(event = gst_event_new_eos()) - || !gst_pad_push_event(transform->my_src, event)) + || !push_event(transform->my_src, event)) goto error; if (!(event = gst_event_new_stream_start("stream")) - || !gst_pad_push_event(transform->my_src, event)) + || !push_event(transform->my_src, event)) goto error; if (!(event = gst_event_new_segment(&transform->segment)) - || !gst_pad_push_event(transform->my_src, event)) + || !push_event(transform->my_src, event)) goto error;
return STATUS_SUCCESS;
From: Ziqing Hui zhui@codeweavers.com
Since 1.20, gst_element_request_pad_simple is available and gst_element_get_request_pad is marked as deprecated. --- configure | 54 +++++++++++++++++++++++++++++++ configure.ac | 3 +- dlls/winegstreamer/unix_private.h | 1 + dlls/winegstreamer/unixlib.c | 35 ++++++++++++++++++++ include/config.h.in | 3 ++ 5 files changed, 95 insertions(+), 1 deletion(-)
diff --git a/configure b/configure index db95cc3588d..3b5dee728ae 100755 --- a/configure +++ b/configure @@ -16992,6 +16992,60 @@ then : : fi
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for -lgstreamer-1.0" >&5 +printf %s "checking for -lgstreamer-1.0... " >&6; } +if test ${ac_cv_lib_soname_gstreamer_1_0+y} +then : + printf %s "(cached) " >&6 +else $as_nop + ac_check_soname_save_LIBS=$LIBS +LIBS="-lgstreamer-1.0 $LIBS" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +char gst_init (); +int +main (void) +{ +return gst_init (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO" +then : + case "$LIBEXT" in + dll) ac_cv_lib_soname_gstreamer_1_0=`$ac_cv_path_LDD conftest.exe | grep "gstreamer-1.0" | sed -e "s/dll.*/dll/"';2,$d'` ;; + dylib) ac_cv_lib_soname_gstreamer_1_0=`$OTOOL -L conftest$ac_exeext | grep "libgstreamer-1.0\.[0-9A-Za-z.]*dylib" | sed -e "s/^.*/(libgstreamer-1.0.[0-9A-Za-z.]*dylib).*$/\1/"';2,$d'` ;; + *) ac_cv_lib_soname_gstreamer_1_0=`$READELF -d conftest$ac_exeext | grep "NEEDED.*libgstreamer-1.0\.$LIBEXT" | sed -e "s/^.*\[\(libgstreamer-1.0\.$LIBEXT[^ ]*\)\].*$/\1/"';2,$d'` + if ${ac_cv_lib_soname_gstreamer_1_0:+false} : +then : + ac_cv_lib_soname_gstreamer_1_0=`$LDD conftest$ac_exeext | grep "libgstreamer-1.0\.$LIBEXT" | sed -e "s/^.*(libgstreamer-1.0.$LIBEXT[^ ]*).*$/\1/"';2,$d'` +fi ;; + esac +else $as_nop + ac_cv_lib_soname_gstreamer_1_0= +fi +rm -f core conftest.err conftest.$ac_objext conftest.beam \ + conftest$ac_exeext conftest.$ac_ext + LIBS=$ac_check_soname_save_LIBS +fi +if ${ac_cv_lib_soname_gstreamer_1_0:+false} : +then : + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: not found" >&5 +printf "%s\n" "not found" >&6; } + +else $as_nop + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_soname_gstreamer_1_0" >&5 +printf "%s\n" "$ac_cv_lib_soname_gstreamer_1_0" >&6; } + +printf "%s\n" "#define SONAME_LIBGSTREAMER_1_0 "$ac_cv_lib_soname_gstreamer_1_0"" >>confdefs.h + + +fi else $as_nop { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } diff --git a/configure.ac b/configure.ac index e17d28c8601..3b6e297528c 100644 --- a/configure.ac +++ b/configure.ac @@ -1588,7 +1588,8 @@ then AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include <gst/gst.h>]], [[static int a[sizeof(gint64) > 4 ? 1 : -1]; if (a[0]) return 0;]])], [AC_MSG_RESULT([yes]) - AC_CHECK_LIB(gstreamer-1.0,gst_pad_new,[:],,[$GSTREAMER_LIBS])], + AC_CHECK_LIB(gstreamer-1.0,gst_pad_new,[:],,[$GSTREAMER_LIBS]) + WINE_CHECK_SONAME(gstreamer-1.0, gst_init)], [AC_MSG_RESULT([no]) ac_glib2_broken=yes enable_winegstreamer=${enable_winegstreamer:-no} diff --git a/dlls/winegstreamer/unix_private.h b/dlls/winegstreamer/unix_private.h index 8bef7b2b2bd..b39252d4d9a 100644 --- a/dlls/winegstreamer/unix_private.h +++ b/dlls/winegstreamer/unix_private.h @@ -40,6 +40,7 @@ extern bool append_element(GstElement *container, GstElement *element, GstElemen 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 bool push_event(GstPad *pad, GstEvent *event) DECLSPEC_HIDDEN; +extern GstPad *request_pad(GstElement *element, const char *name) DECLSPEC_HIDDEN;
/* wg_format.c */
diff --git a/dlls/winegstreamer/unixlib.c b/dlls/winegstreamer/unixlib.c index eca2bb8aacc..32311acaf7d 100644 --- a/dlls/winegstreamer/unixlib.c +++ b/dlls/winegstreamer/unixlib.c @@ -27,6 +27,7 @@ #include <assert.h> #include <stdarg.h> #include <stdio.h> +#include <dlfcn.h>
#include <gst/gst.h> #include <gst/video/video.h> @@ -47,6 +48,9 @@
GST_DEBUG_CATEGORY(wine);
+GstPad * (*pgst_element_request_pad_simple)(GstElement * element, const gchar * name); +GstPad * (*pgst_element_get_request_pad)(GstElement * element, const gchar * name); + GstStreamType stream_type_from_caps(GstCaps *caps) { const gchar *media_type; @@ -223,6 +227,25 @@ bool push_event(GstPad *pad, GstEvent *event) return true; }
+GstPad *request_pad(GstElement *element, const char *name) +{ + GstPad *pad = NULL; + + if (pgst_element_request_pad_simple) + pad = pgst_element_request_pad_simple(element, name); + else if (pgst_element_get_request_pad) + pad = pgst_element_get_request_pad(element, name); + + if (!pad) + { + gchar *element_name = gst_element_get_name(element); + GST_ERROR("Failed to request pad %s from element %s.", name, element_name); + g_free(element_name); + } + + return pad; +} + NTSTATUS wg_init_gstreamer(void *arg) { char arg0[] = "wine"; @@ -230,8 +253,20 @@ NTSTATUS wg_init_gstreamer(void *arg) char *args[] = {arg0, arg1, NULL}; int argc = ARRAY_SIZE(args) - 1; char **argv = args; + void *gst_handle; GError *err;
+ if (!(gst_handle = dlopen(SONAME_LIBGSTREAMER_1_0, RTLD_NOW))) + { + fprintf(stderr, "Failed to find gstreamer library: %s.\n", SONAME_LIBGSTREAMER_1_0); + return STATUS_DLL_NOT_FOUND; + } + +#define LOAD_OPTIONAL_FUNCPTR(f) p##f = dlsym(gst_handle, #f) + LOAD_OPTIONAL_FUNCPTR(gst_element_request_pad_simple); + LOAD_OPTIONAL_FUNCPTR(gst_element_get_request_pad); +#undef LOAD_OPTIONAL_FUNCPTR + if (!gst_init_check(&argc, &argv, &err)) { fprintf(stderr, "winegstreamer: failed to initialize GStreamer: %s\n", err->message); diff --git a/include/config.h.in b/include/config.h.in index fa234a82f84..94684d09b49 100644 --- a/include/config.h.in +++ b/include/config.h.in @@ -744,6 +744,9 @@ /* Define to the soname of the libgssapi_krb5 library. */ #undef SONAME_LIBGSSAPI_KRB5
+/* Define to the soname of the libgstreamer-1.0 library. */ +#undef SONAME_LIBGSTREAMER_1_0 + /* Define to the soname of the libkrb5 library. */ #undef SONAME_LIBKRB5
From: Ziqing Hui zhui@codeweavers.com
--- dlls/winegstreamer/mfplat.c | 11 ++++++++++- dlls/winegstreamer/unixlib.h | 2 ++ dlls/winegstreamer/wg_format.c | 14 ++++++++++++++ 3 files changed, 26 insertions(+), 1 deletion(-)
diff --git a/dlls/winegstreamer/mfplat.c b/dlls/winegstreamer/mfplat.c index 7a37f25fcb2..d85568e5ecd 100644 --- a/dlls/winegstreamer/mfplat.c +++ b/dlls/winegstreamer/mfplat.c @@ -804,8 +804,9 @@ static void mf_media_type_to_wg_format_audio_wma(IMFMediaType *type, const GUID
static void mf_media_type_to_wg_format_video_h264(IMFMediaType *type, struct wg_format *format) { + UINT32 profile, level, codec_data_len; UINT64 frame_rate, frame_size; - UINT32 profile, level; + BYTE *codec_data;
memset(format, 0, sizeof(*format)); format->major_type = WG_MAJOR_TYPE_VIDEO_H264; @@ -832,6 +833,14 @@ static void mf_media_type_to_wg_format_video_h264(IMFMediaType *type, struct wg_
if (SUCCEEDED(IMFMediaType_GetUINT32(type, &MF_MT_MPEG2_LEVEL, &level))) format->u.video_h264.level = level; + + if (SUCCEEDED(IMFMediaType_GetAllocatedBlob(type, &MF_MT_MPEG_SEQUENCE_HEADER, &codec_data, &codec_data_len))) + { + assert(codec_data_len <= sizeof(format->u.video_h264.codec_data)); + format->u.video_h264.codec_data_len = codec_data_len; + memcpy(format->u.video_h264.codec_data, codec_data, codec_data_len); + CoTaskMemFree(codec_data); + } }
static void mf_media_type_to_wg_format_video_indeo(IMFMediaType *type, uint32_t version, struct wg_format *format) diff --git a/dlls/winegstreamer/unixlib.h b/dlls/winegstreamer/unixlib.h index 702bd7aa69b..15e0605fdde 100644 --- a/dlls/winegstreamer/unixlib.h +++ b/dlls/winegstreamer/unixlib.h @@ -148,6 +148,8 @@ struct wg_format uint32_t fps_n, fps_d; uint32_t profile; uint32_t level; + uint32_t codec_data_len; + unsigned char codec_data[64]; } video_h264; struct { diff --git a/dlls/winegstreamer/wg_format.c b/dlls/winegstreamer/wg_format.c index bd0ebf892c1..2353839bbc4 100644 --- a/dlls/winegstreamer/wg_format.c +++ b/dlls/winegstreamer/wg_format.c @@ -553,6 +553,7 @@ static GstCaps *wg_format_to_caps_audio_wma(const struct wg_format *format) static GstCaps *wg_format_to_caps_video_h264(const struct wg_format *format) { const char *profile, *level; + GstBuffer *buffer; GstCaps *caps;
if (!(caps = gst_caps_new_empty_simple("video/x-h264"))) @@ -609,6 +610,19 @@ static GstCaps *wg_format_to_caps_video_h264(const struct wg_format *format) if (level) gst_caps_set_simple(caps, "level", G_TYPE_STRING, level, NULL);
+ if (format->u.video_h264.codec_data_len) + { + if (!(buffer = gst_buffer_new_and_alloc(format->u.video_h264.codec_data_len))) + { + gst_caps_unref(caps); + return NULL; + } + + gst_buffer_fill(buffer, 0, format->u.video_h264.codec_data, format->u.video_h264.codec_data_len); + gst_caps_set_simple(caps, "codec_data", GST_TYPE_BUFFER, buffer, NULL); + gst_buffer_unref(buffer); + } + return caps; }
From: Ziqing Hui zhui@codeweavers.com
--- dlls/mf/tests/mf.c | 37 +++++++++++++++++++++++++++++++------ 1 file changed, 31 insertions(+), 6 deletions(-)
diff --git a/dlls/mf/tests/mf.c b/dlls/mf/tests/mf.c index 4f4a282a9d8..3f1e288a967 100644 --- a/dlls/mf/tests/mf.c +++ b/dlls/mf/tests/mf.c @@ -81,6 +81,20 @@ HRESULT (WINAPI *pMFGetTopoNodeCurrentType)(IMFTopologyNode *node, DWORD stream, HRESULT (WINAPI *pMFCreateDXGIDeviceManager)(UINT *token, IMFDXGIDeviceManager **manager); BOOL has_video_processor;
+const static BYTE test_h264_sequence_header[] = +{ + 0x00, 0x00, 0x01, 0x67, 0x64, 0x00, 0x14, 0xac, 0xd9, 0x46, 0x36, 0xc0, + 0x5a, 0x83, 0x03, 0x03, 0x52, 0x80, 0x00, 0x00, 0x03, 0x00, 0x80, 0x00, + 0x00, 0x03, 0x01, 0x47, 0x8a, 0x14, 0xcb, 0x00, 0x00, 0x01, 0x68, 0xeb, + 0xec, 0xb2, 0x2c, +}; + +const static BYTE test_aac_codec_data[] = +{ + 0x00, 0x00, 0x29, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x12, 0x08, +}; + static BOOL is_vista(void) { return !pMFGetTopoNodeCurrentType; @@ -6756,7 +6770,7 @@ static void test_mpeg4_media_sink(void) { IMFMediaSink *sink = NULL, *sink2 = NULL, *sink_audio = NULL, *sink_video = NULL, *sink_empty = NULL; IMFByteStream *bytestream, *bytestream_audio, *bytestream_video, *bytestream_empty; - DWORD id, count, flags, width = 16, height = 16, fps = 10; + DWORD id, count, flags, width = 96, height = 96, fps = 1; IMFMediaType *audio_type, *video_type, *media_type; IMFMediaTypeHandler *type_handler = NULL; IMFPresentationClock *clock; @@ -6772,23 +6786,34 @@ static void test_mpeg4_media_sink(void)
hr = IMFMediaType_SetGUID(audio_type, &MF_MT_MAJOR_TYPE, &MFMediaType_Audio); ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); - hr = IMFMediaType_SetGUID(audio_type, &MF_MT_SUBTYPE, &MFAudioFormat_PCM); + hr = IMFMediaType_SetGUID(audio_type, &MF_MT_SUBTYPE, &MFAudioFormat_AAC); ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); - hr = IMFMediaType_SetUINT32(audio_type, &MF_MT_AUDIO_NUM_CHANNELS, 2); + hr = IMFMediaType_SetUINT32(audio_type, &MF_MT_AUDIO_NUM_CHANNELS, 1); ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); - hr = IMFMediaType_SetUINT32(audio_type, &MF_MT_AUDIO_SAMPLES_PER_SECOND, 48000); + hr = IMFMediaType_SetUINT32(audio_type, &MF_MT_AUDIO_BITS_PER_SAMPLE, 16); ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); - hr = IMFMediaType_SetUINT32(audio_type, &MF_MT_AUDIO_BITS_PER_SAMPLE, 8); + hr = IMFMediaType_SetUINT32(audio_type, &MF_MT_AUDIO_SAMPLES_PER_SECOND, 44100); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + hr = IMFMediaType_SetUINT32(audio_type, &MF_MT_AUDIO_AVG_BYTES_PER_SECOND, 12000); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + hr = IMFMediaType_SetUINT32(audio_type, &MF_MT_AAC_AUDIO_PROFILE_LEVEL_INDICATION, 41); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + hr = IMFMediaType_SetUINT32(audio_type, &MF_MT_AAC_PAYLOAD_TYPE, 0); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + hr = IMFMediaType_SetBlob(audio_type, &MF_MT_USER_DATA, test_aac_codec_data, sizeof(test_aac_codec_data)); ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
hr = IMFMediaType_SetGUID(video_type, &MF_MT_MAJOR_TYPE, &MFMediaType_Video); ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); - hr = IMFMediaType_SetGUID(video_type, &MF_MT_SUBTYPE, &MFVideoFormat_RGB24); + hr = IMFMediaType_SetGUID(video_type, &MF_MT_SUBTYPE, &MFVideoFormat_H264); ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); hr = IMFMediaType_SetUINT64(video_type, &MF_MT_FRAME_SIZE, ((UINT64)width << 32) | height); ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); hr = IMFMediaType_SetUINT64(video_type, &MF_MT_FRAME_RATE, ((UINT64)fps << 32) | 1); ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + hr = IMFMediaType_SetBlob(video_type, &MF_MT_MPEG_SEQUENCE_HEADER, + test_h264_sequence_header, sizeof(test_h264_sequence_header)); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
hr = MFCreateTempFile(MF_ACCESSMODE_WRITE, MF_OPENMODE_DELETE_IF_EXIST, 0, &bytestream_audio); ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
From: Ziqing Hui zhui@codeweavers.com
--- dlls/mf/tests/mf.c | 43 ++++++++--------- dlls/winegstreamer/gst_private.h | 3 +- dlls/winegstreamer/main.c | 7 ++- dlls/winegstreamer/media_sink.c | 49 ++++++++++++++++---- dlls/winegstreamer/unix_private.h | 1 + dlls/winegstreamer/unixlib.h | 8 ++++ dlls/winegstreamer/wg_format.c | 22 +++++++++ dlls/winegstreamer/winegstreamer_classes.idl | 7 +++ 8 files changed, 105 insertions(+), 35 deletions(-)
diff --git a/dlls/mf/tests/mf.c b/dlls/mf/tests/mf.c index 3f1e288a967..3e6b031f273 100644 --- a/dlls/mf/tests/mf.c +++ b/dlls/mf/tests/mf.c @@ -6825,58 +6825,39 @@ static void test_mpeg4_media_sink(void) ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
hr = MFCreateMPEG4MediaSink(NULL, NULL, NULL, NULL); - todo_wine ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
sink = (void *)0xdeadbeef; hr = MFCreateMPEG4MediaSink(NULL, NULL, NULL, &sink); - todo_wine ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr); ok(sink == (void *)0xdeadbeef, "Unexpected pointer %p.\n", sink); sink = NULL;
hr = MFCreateMPEG4MediaSink(bytestream_empty, NULL, NULL, &sink_empty); - todo_wine ok(hr == S_OK || broken(hr == E_INVALIDARG), "Unexpected hr %#lx.\n", hr);
hr = MFCreateMPEG4MediaSink(bytestream_audio, NULL, audio_type, &sink_audio); - todo_wine ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
hr = MFCreateMPEG4MediaSink(bytestream_video, video_type, NULL, &sink_video); - todo_wine ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
hr = MFCreateMPEG4MediaSink(bytestream, video_type, audio_type, &sink); - todo_wine ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
- if (!sink) - { - if (sink_video) - IMFMediaSink_Release(sink_video); - if (sink_audio) - IMFMediaSink_Release(sink_audio); - if (sink_empty) - IMFMediaSink_Release(sink_empty); - IMFByteStream_Release(bytestream); - IMFByteStream_Release(bytestream_empty); - IMFByteStream_Release(bytestream_video); - IMFByteStream_Release(bytestream_audio); - IMFMediaType_Release(video_type); - IMFMediaType_Release(audio_type); - return; - } - /* Test sink. */ + flags = 0xdeadbeef; hr = IMFMediaSink_GetCharacteristics(sink, &flags); + todo_wine ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + todo_wine ok(flags == MEDIASINK_RATELESS || broken(flags == (MEDIASINK_RATELESS | MEDIASINK_FIXED_STREAMS)), "Unexpected flags %#lx.\n", flags);
check_interface(sink, &IID_IMFMediaEventGenerator, TRUE); check_interface(sink, &IID_IMFFinalizableMediaSink, TRUE); check_interface(sink, &IID_IMFClockStateSink, TRUE); + todo_wine check_interface(sink, &IID_IMFGetService, TRUE);
/* Test sink stream count. */ @@ -6991,8 +6972,11 @@ static void test_mpeg4_media_sink(void) hr = MFCreatePresentationClock(&clock); ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); hr = IMFMediaSink_SetPresentationClock(sink, NULL); + todo_wine ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + todo_wine hr = IMFMediaSink_SetPresentationClock(sink, clock); + todo_wine ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); IMFPresentationClock_Release(clock);
@@ -7011,13 +6995,18 @@ static void test_mpeg4_media_sink(void) ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
hr = IMFMediaTypeHandler_GetMajorType(type_handler, NULL); + todo_wine ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr); hr = IMFMediaTypeHandler_GetMajorType(type_handler, &guid); + todo_wine ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + todo_wine ok(IsEqualGUID(&guid, &MFMediaType_Audio), "Unexpected major type.\n");
hr = IMFMediaTypeHandler_GetMediaTypeCount(type_handler, &count); + todo_wine ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + todo_wine ok(count == 1, "Unexpected count %lu.\n", count);
hr = IMFMediaTypeHandler_GetCurrentMediaType(type_handler, &media_type); @@ -7027,8 +7016,10 @@ static void test_mpeg4_media_sink(void) ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
hr = IMFMediaTypeHandler_SetCurrentMediaType(type_handler, NULL); + todo_wine ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr); hr = IMFMediaTypeHandler_SetCurrentMediaType(type_handler, media_type); + todo_wine ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
IMFMediaType_Release(media_type); @@ -7047,19 +7038,25 @@ static void test_mpeg4_media_sink(void) ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
hr = IMFMediaTypeHandler_GetMajorType(type_handler, NULL); + todo_wine ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr); hr = IMFMediaTypeHandler_GetMajorType(type_handler, &guid); + todo_wine ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
IMFStreamSink_Release(stream_sink);
hr = IMFMediaSink_AddStreamSink(sink, 0, audio_type, &stream_sink); + todo_wine ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#lx.\n", hr); hr = IMFMediaSink_GetStreamSinkByIndex(sink, 0, &stream_sink); + todo_wine ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#lx.\n", hr); hr = IMFMediaSink_GetStreamSinkById(sink, 0, &stream_sink); + todo_wine ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#lx.\n", hr); hr = IMFMediaSink_GetCharacteristics(sink, &flags); + todo_wine ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#lx.\n", hr);
IMFMediaTypeHandler_Release(type_handler); diff --git a/dlls/winegstreamer/gst_private.h b/dlls/winegstreamer/gst_private.h index ed867f741d9..2edd2d19107 100644 --- a/dlls/winegstreamer/gst_private.h +++ b/dlls/winegstreamer/gst_private.h @@ -122,7 +122,8 @@ HRESULT wma_decoder_create(IUnknown *outer, IUnknown **out); HRESULT wmv_decoder_create(IUnknown *outer, IUnknown **out); HRESULT resampler_create(IUnknown *outer, IUnknown **out); HRESULT color_convert_create(IUnknown *outer, IUnknown **out); -HRESULT sink_class_factory_create(IUnknown *outer, IUnknown **out); +HRESULT mp3_sink_class_factory_create(IUnknown *outer, IUnknown **out); +HRESULT mpeg4_sink_class_factory_create(IUnknown *outer, IUnknown **out);
bool amt_from_wg_format(AM_MEDIA_TYPE *mt, const struct wg_format *format, bool wm); bool amt_to_wg_format(const AM_MEDIA_TYPE *mt, struct wg_format *format); diff --git a/dlls/winegstreamer/main.c b/dlls/winegstreamer/main.c index 9624c469314..6a4825a227c 100644 --- a/dlls/winegstreamer/main.c +++ b/dlls/winegstreamer/main.c @@ -612,7 +612,8 @@ static struct class_factory wma_decoder_cf = {{&class_factory_vtbl}, wma_decoder static struct class_factory wmv_decoder_cf = {{&class_factory_vtbl}, wmv_decoder_create}; static struct class_factory resampler_cf = {{&class_factory_vtbl}, resampler_create}; static struct class_factory color_convert_cf = {{&class_factory_vtbl}, color_convert_create}; -static struct class_factory sink_class_factory_cf = {{&class_factory_vtbl}, sink_class_factory_create}; +static struct class_factory mp3_sink_class_factory_cf = {{&class_factory_vtbl}, mp3_sink_class_factory_create}; +static struct class_factory mpeg4_sink_class_factory_cf = {{&class_factory_vtbl}, mpeg4_sink_class_factory_create};
HRESULT WINAPI DllGetClassObject(REFCLSID clsid, REFIID iid, void **out) { @@ -648,7 +649,9 @@ HRESULT WINAPI DllGetClassObject(REFCLSID clsid, REFIID iid, void **out) else if (IsEqualGUID(clsid, &CLSID_CColorConvertDMO)) factory = &color_convert_cf; else if (IsEqualGUID(clsid, &CLSID_MFMP3SinkClassFactory)) - factory = &sink_class_factory_cf; + factory = &mp3_sink_class_factory_cf; + else if (IsEqualGUID(clsid, &CLSID_MFMPEG4SinkClassFactory)) + factory = &mpeg4_sink_class_factory_cf; else { FIXME("%s not implemented, returning CLASS_E_CLASSNOTAVAILABLE.\n", debugstr_guid(clsid)); diff --git a/dlls/winegstreamer/media_sink.c b/dlls/winegstreamer/media_sink.c index fcea67eb8f1..20d345974be 100644 --- a/dlls/winegstreamer/media_sink.c +++ b/dlls/winegstreamer/media_sink.c @@ -72,6 +72,7 @@ struct media_sink STATE_PAUSED, STATE_SHUTDOWN, } state; + wg_container_type type;
IMFByteStream *bytestream; IMFMediaEventQueue *event_queue; @@ -1022,7 +1023,7 @@ static const IMFAsyncCallbackVtbl media_sink_callback_vtbl = media_sink_callback_Invoke, };
-static HRESULT media_sink_create(IMFByteStream *bytestream, struct media_sink **out) +static HRESULT media_sink_create(IMFByteStream *bytestream, wg_container_type type, struct media_sink **out) { struct media_sink *media_sink; HRESULT hr; @@ -1047,6 +1048,7 @@ static HRESULT media_sink_create(IMFByteStream *bytestream, struct media_sink ** media_sink->async_callback.lpVtbl = &media_sink_callback_vtbl; media_sink->refcount = 1; media_sink->state = STATE_OPENED; + media_sink->type = type; InitializeCriticalSection(&media_sink->cs); media_sink->cs.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": cs"); IMFByteStream_AddRef((media_sink->bytestream = bytestream)); @@ -1082,8 +1084,8 @@ static ULONG WINAPI sink_class_factory_Release(IMFSinkClassFactory *iface) return 1; }
-static HRESULT WINAPI sink_class_factory_CreateMediaSink(IMFSinkClassFactory *iface, IMFByteStream *bytestream, - IMFMediaType *video_type, IMFMediaType *audio_type, IMFMediaSink **out) +static HRESULT WINAPI sink_class_factory_create_media_sink(IMFSinkClassFactory *iface, IMFByteStream *bytestream, + wg_container_type type, IMFMediaType *video_type, IMFMediaType *audio_type, IMFMediaSink **out) { IMFFinalizableMediaSink *media_sink_iface; struct media_sink *media_sink; @@ -1092,7 +1094,7 @@ static HRESULT WINAPI sink_class_factory_CreateMediaSink(IMFSinkClassFactory *if TRACE("iface %p, bytestream %p, video_type %p, audio_type %p, out %p.\n", iface, bytestream, video_type, audio_type, out);
- if (FAILED(hr = media_sink_create(bytestream, &media_sink))) + if (FAILED(hr = media_sink_create(bytestream, type, &media_sink))) return hr; media_sink_iface = &media_sink->IMFFinalizableMediaSink_iface;
@@ -1119,18 +1121,47 @@ static HRESULT WINAPI sink_class_factory_CreateMediaSink(IMFSinkClassFactory *if return S_OK; }
-static const IMFSinkClassFactoryVtbl sink_class_factory_vtbl = +static HRESULT WINAPI mp3_sink_class_factory_CreateMediaSink(IMFSinkClassFactory *iface, IMFByteStream *bytestream, + IMFMediaType *video_type, IMFMediaType *audio_type, IMFMediaSink **out) +{ + return sink_class_factory_create_media_sink(iface, + bytestream, WG_CONTAINER_TYPE_ID3, video_type, audio_type, out); +} + +static HRESULT WINAPI mpeg4_sink_class_factory_CreateMediaSink(IMFSinkClassFactory *iface, IMFByteStream *bytestream, + IMFMediaType *video_type, IMFMediaType *audio_type, IMFMediaSink **out) +{ + return sink_class_factory_create_media_sink(iface, + bytestream, WG_CONTAINER_TYPE_QUICKTIME, video_type, audio_type, out); +} + +static const IMFSinkClassFactoryVtbl mp3_sink_class_factory_vtbl = { sink_class_factory_QueryInterface, sink_class_factory_AddRef, sink_class_factory_Release, - sink_class_factory_CreateMediaSink, + mp3_sink_class_factory_CreateMediaSink, };
-static IMFSinkClassFactory sink_class_factory = { &sink_class_factory_vtbl }; +static const IMFSinkClassFactoryVtbl mpeg4_sink_class_factory_vtbl = +{ + sink_class_factory_QueryInterface, + sink_class_factory_AddRef, + sink_class_factory_Release, + mpeg4_sink_class_factory_CreateMediaSink, +}; + +static IMFSinkClassFactory mp3_sink_class_factory = { &mp3_sink_class_factory_vtbl }; +static IMFSinkClassFactory mpeg4_sink_class_factory = { &mpeg4_sink_class_factory_vtbl }; + +HRESULT mp3_sink_class_factory_create(IUnknown *outer, IUnknown **out) +{ + *out = (IUnknown *)&mp3_sink_class_factory; + return S_OK; +}
-HRESULT sink_class_factory_create(IUnknown *outer, IUnknown **out) +HRESULT mpeg4_sink_class_factory_create(IUnknown *outer, IUnknown **out) { - *out = (IUnknown *)&sink_class_factory; + *out = (IUnknown *)&mpeg4_sink_class_factory; return S_OK; } diff --git a/dlls/winegstreamer/unix_private.h b/dlls/winegstreamer/unix_private.h index b39252d4d9a..60819f0a865 100644 --- a/dlls/winegstreamer/unix_private.h +++ b/dlls/winegstreamer/unix_private.h @@ -47,6 +47,7 @@ extern GstPad *request_pad(GstElement *element, const char *name) DECLSPEC_HIDDE extern void wg_format_from_caps(struct wg_format *format, const GstCaps *caps) DECLSPEC_HIDDEN; extern bool wg_format_compare(const struct wg_format *a, const struct wg_format *b) DECLSPEC_HIDDEN; extern GstCaps *wg_format_to_caps(const struct wg_format *format) DECLSPEC_HIDDEN; +extern GstCaps *wg_container_type_to_caps(enum wg_container_type container_type) DECLSPEC_HIDDEN;
/* wg_transform.c */
diff --git a/dlls/winegstreamer/unixlib.h b/dlls/winegstreamer/unixlib.h index 15e0605fdde..a5e1e6ffd0c 100644 --- a/dlls/winegstreamer/unixlib.h +++ b/dlls/winegstreamer/unixlib.h @@ -166,6 +166,14 @@ struct wg_format } u; };
+typedef UINT32 wg_container_type; +enum wg_container_type +{ + WG_CONTAINER_TYPE_UNKNOWN = 0, + WG_CONTAINER_TYPE_ID3, + WG_CONTAINER_TYPE_QUICKTIME, +}; + enum wg_sample_flag { WG_SAMPLE_FLAG_INCOMPLETE = 1, diff --git a/dlls/winegstreamer/wg_format.c b/dlls/winegstreamer/wg_format.c index 2353839bbc4..a1b22ad8abb 100644 --- a/dlls/winegstreamer/wg_format.c +++ b/dlls/winegstreamer/wg_format.c @@ -767,3 +767,25 @@ bool wg_format_compare(const struct wg_format *a, const struct wg_format *b) assert(0); return false; } + +GstCaps *wg_container_type_to_caps(enum wg_container_type container_type) +{ + GstCaps *caps = NULL; + + switch (container_type) + { + case WG_CONTAINER_TYPE_ID3: + caps = gst_caps_new_empty_simple("application/x-id3"); + break; + case WG_CONTAINER_TYPE_QUICKTIME: + caps = gst_caps_new_empty_simple("video/quicktime"); + gst_caps_set_simple(caps, "variant", G_TYPE_STRING, "iso", NULL); + break; + case WG_CONTAINER_TYPE_UNKNOWN: + default: + GST_WARNING("Container type %u not implemented.\n", container_type); + break; + } + + return caps; +} diff --git a/dlls/winegstreamer/winegstreamer_classes.idl b/dlls/winegstreamer/winegstreamer_classes.idl index 2bc85e70b3a..3e9b19c90e9 100644 --- a/dlls/winegstreamer/winegstreamer_classes.idl +++ b/dlls/winegstreamer/winegstreamer_classes.idl @@ -117,3 +117,10 @@ coclass CColorConvertDMO {} uuid(11275a82-5e5a-47fd-a01c-3683c12fb196) ] coclass MFMP3SinkClassFactory {} + +[ + helpstring("MF MPEG4 Sink Class Factory"), + threading(both), + uuid(a22c4fc7-6e91-4e1d-89e9-53b2667b72ba) +] +coclass MFMPEG4SinkClassFactory {}
Hi,
It looks like your patch introduced the new failures shown below. Please investigate and fix them before resubmitting your patch. If they are not new, fixing them anyway would help a lot. Otherwise please ask for the known failures list to be updated.
The tests also ran into some preexisting test failures. If you know how to fix them that would be helpful. See the TestBot job for the details:
The full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=136603
Your paranoid android.
=== debian11b (64 bit WoW report) ===
mfreadwrite: mfplat.c:1472: Test succeeded inside todo block: Unexpected hr 0. mfplat.c:1478: Test succeeded inside todo block: Unexpected hr 0. mfplat.c:1484: Test succeeded inside todo block: Unexpected hr 0. mfplat.c:1490: Test succeeded inside todo block: Unexpected hr 0. mfplat.c:1496: Test succeeded inside todo block: Unexpected hr 0. mfplat.c:1508: Test failed: Unexpected hr 0. mfplat.c:1509: Test failed: Unexpected pointer 0000000003879F10.
user32: msg.c:6898: Test failed: SetFocus(hwnd) on a button: 6: the msg 0x002b was expected, but got msg 0x001c instead msg.c:6898: Test failed: SetFocus(hwnd) on a button: 7: the msg 0x0111 was expected, but got msg 0x0086 instead msg.c:6898: Test failed: SetFocus(hwnd) on a button: 8: the msg 0x8000 was expected, but got msg 0x0006 instead msg.c:6898: Test failed: SetFocus(hwnd) on a button: 9: the msg sequence is not complete: expected 0000 - actual 0009
This patch set is the first several patches of MR !3303 which is too large to get it merged in a single MR. So I plan to split it into 3 MRs, this is the first one.