[PATCH] winegstreamer: Fixes for video flipping

Jan Schmidt jan at centricular.com
Fri Jul 15 11:51:10 CDT 2016


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 <jan at centricular.com>
---
 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




More information about the wine-patches mailing list