From: Jan Schmidt Subject: [PATCH] winegstreamer: Fixes for video flipping Message-Id: <1468601470-12713-1-git-send-email-jan@centricular.com> Date: Sat, 16 Jul 2016 02:51:10 +1000 The videoflip element doesn't handle all formats, so some formats like Intel Indeo 3 will fail. Add videoconvert to do format conversion when it's needed. Fix some refcount issues too - add a new element to a bin takes ownership of the floating reference, so there's no need to keep pointers around to unref later. Fix state setting of new elements - always just set them to PAUSED. gst_element_sync_state_with_parent() can be problematic, and we only need these in paused or playing anyway. Fixes bug 40764 Signed-off-by: Jan Schmidt --- dlls/winegstreamer/gstdemux.c | 57 +++++++++++++++++++++++++------------------ 1 file changed, 33 insertions(+), 24 deletions(-) diff --git a/dlls/winegstreamer/gstdemux.c b/dlls/winegstreamer/gstdemux.c index 1de9b41..5d0d38b 100644 --- a/dlls/winegstreamer/gstdemux.c +++ b/dlls/winegstreamer/gstdemux.c @@ -65,7 +65,6 @@ typedef struct GSTImpl { BOOL discont, initial, ignore_flush; GstElement *container; - GstElement *gstfilter; GstPad *my_src, *their_sink; GstBus *bus; guint64 start, nextofs, nextpullofs, stop; @@ -422,9 +421,10 @@ static gboolean event_sink(GstPad *pad, GstObject *parent, GstEvent *event) { GSTOutPin *pin = gst_pad_get_element_private(pad); - TRACE("%p %p\n", pad, event); + TRACE("%p %p type %s\n", pad, event, + gst_event_type_get_name(GST_EVENT_TYPE (event))); - switch (event->type) { + switch (GST_EVENT_TYPE (event)) { case GST_EVENT_SEGMENT: { gdouble rate, applied_rate; gint64 stop, pos; @@ -832,11 +832,20 @@ static void init_new_decoded_pad(GstElement *bin, GstPad *pad, GSTImpl *This) gst_segment_init(pin->segment, GST_FORMAT_TIME); if (isvid) { + GstElement *vconv; + TRACE("setting up videoflip filter for pin %p, my_sink: %p, their_src: %p\n", pin, pin->my_sink, pad); /* gstreamer outputs video top-down, but dshow expects bottom-up, so * make new transform filter to invert video */ + vconv = gst_element_factory_make("videoconvert", NULL); + if(!vconv){ + ERR("Missing videoflip filter?\n"); + ret = -1; + goto exit; + } + pin->flipfilter = gst_element_factory_make("videoflip", NULL); if(!pin->flipfilter){ ERR("Missing videoflip filter?\n"); @@ -846,13 +855,16 @@ static void init_new_decoded_pad(GstElement *bin, GstPad *pad, GSTImpl *This) gst_util_set_object_arg(G_OBJECT(pin->flipfilter), "method", "vertical-flip"); - gst_bin_add(GST_BIN(This->container), pin->flipfilter); - gst_element_sync_state_with_parent(pin->flipfilter); + gst_element_set_state (vconv, GST_STATE_PAUSED); + gst_bin_add(GST_BIN(This->container), vconv); /* bin takes ownership */ + gst_element_set_state (pin->flipfilter, GST_STATE_PAUSED); + gst_bin_add(GST_BIN(This->container), pin->flipfilter); /* bin takes ownership */ - pin->flip_sink = gst_element_get_static_pad(pin->flipfilter, "sink"); + gst_element_link (vconv, pin->flipfilter); + + pin->flip_sink = gst_element_get_static_pad(vconv, "sink"); if(!pin->flip_sink){ WARN("Couldn't find sink on flip filter\n"); - gst_object_unref(pin->flipfilter); pin->flipfilter = NULL; ret = -1; goto exit; @@ -863,7 +875,6 @@ static void init_new_decoded_pad(GstElement *bin, GstPad *pad, GSTImpl *This) WARN("gst_pad_link failed: %d\n", ret); gst_object_unref(pin->flip_sink); pin->flip_sink = NULL; - gst_object_unref(pin->flipfilter); pin->flipfilter = NULL; goto exit; } @@ -873,7 +884,6 @@ static void init_new_decoded_pad(GstElement *bin, GstPad *pad, GSTImpl *This) WARN("Couldn't find src on flip filter\n"); gst_object_unref(pin->flip_sink); pin->flip_sink = NULL; - gst_object_unref(pin->flipfilter); pin->flipfilter = NULL; ret = -1; goto exit; @@ -886,7 +896,6 @@ static void init_new_decoded_pad(GstElement *bin, GstPad *pad, GSTImpl *This) pin->flip_src = NULL; gst_object_unref(pin->flip_sink); pin->flip_sink = NULL; - gst_object_unref(pin->flipfilter); pin->flipfilter = NULL; goto exit; } @@ -1091,6 +1100,7 @@ static HRESULT GST_Connect(GSTInPin *pPin, IPin *pConnectPin, ALLOCATOR_PROPERTI GST_PAD_SRC, GST_PAD_ALWAYS, GST_STATIC_CAPS_ANY); + GstElement *gstfilter; TRACE("%p %p %p\n", pPin, pConnectPin, props); @@ -1104,20 +1114,20 @@ static HRESULT GST_Connect(GSTInPin *pPin, IPin *pConnectPin, ALLOCATOR_PROPERTI This->container = gst_bin_new(NULL); - This->gstfilter = gst_element_factory_make("decodebin", NULL); - if (!This->gstfilter) { + gstfilter = gst_element_factory_make("decodebin", NULL); + if (!gstfilter) { FIXME("Could not make source filter, are gstreamer-plugins-* installed for %u bits?\n", 8 * (int)sizeof(void*)); return E_FAIL; } - gst_bin_add(GST_BIN(This->container), This->gstfilter); + gst_bin_add(GST_BIN(This->container), gstfilter); /* takes ownership of the filter */ - gst_element_set_bus(This->gstfilter, This->bus); - g_signal_connect(This->gstfilter, "pad-added", G_CALLBACK(existing_new_pad_wrapper), This); - g_signal_connect(This->gstfilter, "pad-removed", G_CALLBACK(removed_decoded_pad_wrapper), This); - g_signal_connect(This->gstfilter, "autoplug-select", G_CALLBACK(autoplug_blacklist_wrapper), This); - g_signal_connect(This->gstfilter, "unknown-type", G_CALLBACK(unknown_type_wrapper), This); + gst_element_set_bus(This->container, This->bus); + g_signal_connect(gstfilter, "pad-added", G_CALLBACK(existing_new_pad_wrapper), This); + g_signal_connect(gstfilter, "pad-removed", G_CALLBACK(removed_decoded_pad_wrapper), This); + g_signal_connect(gstfilter, "autoplug-select", G_CALLBACK(autoplug_blacklist_wrapper), This); + g_signal_connect(gstfilter, "unknown-type", G_CALLBACK(unknown_type_wrapper), This); This->my_src = gst_pad_new_from_static_template(&src_template, "quartz-src"); gst_pad_set_getrange_function(This->my_src, request_buffer_src_wrapper); @@ -1125,9 +1135,9 @@ static HRESULT GST_Connect(GSTInPin *pPin, IPin *pConnectPin, ALLOCATOR_PROPERTI gst_pad_set_activatemode_function(This->my_src, activate_mode_wrapper); gst_pad_set_event_function(This->my_src, event_src_wrapper); gst_pad_set_element_private (This->my_src, This); - This->their_sink = gst_element_get_static_pad(This->gstfilter, "sink"); + This->their_sink = gst_element_get_static_pad(gstfilter, "sink"); - g_signal_connect(This->gstfilter, "no-more-pads", G_CALLBACK(no_more_pads_wrapper), This); + g_signal_connect(gstfilter, "no-more-pads", G_CALLBACK(no_more_pads_wrapper), This); ret = gst_pad_link(This->my_src, This->their_sink); if (ret < 0) { ERR("Returns: %i\n", ret); @@ -1747,7 +1757,8 @@ static ULONG WINAPI GSTOutPin_Release(IPin *iface) gst_pad_unlink(This->flip_src, This->my_sink); gst_object_unref(This->flip_src); gst_object_unref(This->flip_sink); - gst_object_unref(This->flipfilter); + This->flipfilter = NULL; + This->flip_src = This->flip_sink = NULL; } else gst_pad_unlink(This->their_src, This->my_sink); gst_object_unref(This->their_src); @@ -1902,7 +1913,7 @@ static HRESULT GST_RemoveOutputPins(GSTImpl *This) if (!This->container) return S_OK; - gst_element_set_bus(This->gstfilter, NULL); + gst_element_set_bus(This->container, NULL); gst_element_set_state(This->container, GST_STATE_NULL); gst_pad_unlink(This->my_src, This->their_sink); gst_object_unref(This->my_src); @@ -1916,8 +1927,6 @@ static HRESULT GST_RemoveOutputPins(GSTImpl *This) } This->cStreams = 0; This->ppPins = NULL; - gst_object_unref(This->gstfilter); - This->gstfilter = NULL; gst_object_unref(This->container); This->container = NULL; BaseFilterImpl_IncrementPinVersion((BaseFilter*)This); -- 2.7.4