%%
headers
+#if ((GST_VERSION_MAJOR > 0) || \
+ (GST_VERSION_MAJOR == 0 && GST_VERSION_MINOR > 10) || \
+ (GST_VERSION_MAJOR == 0 && GST_VERSION_MINOR == 10 && \
+ GST_VERSION_MICRO >= 23) || \
+ (GST_VERSION_MAJOR == 0 && GST_VERSION_MINOR == 10 && \
+ GST_VERSION_MICRO == 22 && GST_VERSION_NANO > 0))
+#define HAVE_SET_BLOCKED_ASYNC_FULL 1
+#else
+#define HAVE_SET_BLOCKED_ASYNC_FULL 0
+#endif
+
/* we need to do this until PyClosures get exception handlers */
#ifndef pyg_closure_set_exception_handler
# define pyg_closure_set_exception_handler(ig, nore)
%%
override gst_pad_set_blocked_async args
+#if HAVE_SET_BLOCKED_ASYNC_FULL
+static void
+pad_block_destroy_data (gpointer data)
+{
+ PyObject *py_data = (PyObject *) data;
+
+ Py_DECREF (py_data);
+}
+#endif
+
static void
pad_block_callback_marshal(GstPad *pad, gboolean blocked, gpointer user_data)
{
if (data == NULL)
return NULL;
pyg_begin_allow_threads;
+#if HAVE_SET_BLOCKED_ASYNC_FULL
+ ret = gst_pad_set_blocked_async_full (GST_PAD (self->obj), blocked,
+ (GstPadBlockCallback) pad_block_callback_marshal, data,
+ pad_block_destroy_data);
+#else
ret = gst_pad_set_blocked_async (GST_PAD (self->obj), blocked,
(GstPadBlockCallback) pad_block_callback_marshal, data);
+#endif
pyg_end_allow_threads;
if (ret)
pret = Py_True;
self.assertEquals(self.gccollect(), 1) # collected the pad
gst.debug('going into teardown')
-# re-enable this test once #514717 is fixed
-
-# class PadBlockRefcountTest(TestCase):
-# def testCallbackRefcount(self):
-# def blocked_cb(pad, blocked):
-# self.assertTrue(pad.set_blocked_async(False, unblocked_cb))
-
-# def unblocked_cb(pad, blocked):
-# pass
-
-# cb_refcount = sys.getrefcount(blocked_cb)
-# # sys.getrefcount() returns refcount + 1
-# self.assertEquals(cb_refcount, 2)
-
-# fakesrc = gst.element_factory_make('fakesrc')
-# fakesrc.props.num_buffers = 2
-# fakesink = gst.element_factory_make('fakesink')
-
-# pipeline = gst.Pipeline()
-# pipeline.add(fakesrc, fakesink)
-
-# fakesrc.link(fakesink)
-
-# pad = fakesrc.get_pad('src')
-# pad.set_blocked_async(True, blocked_cb)
-
-# pipeline.set_state(gst.STATE_PLAYING)
-# pipeline.get_bus().poll(gst.MESSAGE_EOS, -1)
-# pipeline.set_state(gst.STATE_NULL)
-
-# # check that we don't leak a ref to the callback
-# cb_refcount_after = sys.getrefcount(blocked_cb)
-# self.assertEquals(cb_refcount_after, cb_refcount)
+class PadBlockTest(TestCase):
+ def testCallbackFlush(self):
+ # check that the same block callback can be called more than once (weird
+ # test but it was broken)
+
+ def blocked_cb(pad, blocked):
+ pad.push_event(gst.event_new_flush_start())
+
+ pad = gst.Pad('src', gst.PAD_SRC)
+ pad.set_active(True)
+ pad.set_blocked_async(True, blocked_cb)
+
+ for i in xrange(10):
+ buf = gst.Buffer('ciao')
+ pad.push(buf)
+ pad.push_event(gst.event_new_flush_stop())
+
+ def testCallbackRefcount(self):
+ def blocked_cb(pad, blocked):
+ pad.set_blocked_async(False, unblocked_cb)
+
+ def unblocked_cb(pad, blocked):
+ pass
+ cb_refcount = sys.getrefcount(blocked_cb)
+ # sys.getrefcount() returns refcount + 1
+ self.assertEquals(cb_refcount, 2)
+
+ pad = gst.Pad('src', gst.PAD_SRC)
+ pad.set_active(True)
+ pad.set_blocked_async(True, blocked_cb)
+ # set_blocked_async refs the callback
+ self.assertEquals(sys.getrefcount(blocked_cb), 3)
+
+ buf = gst.Buffer('ciao')
+ pad.push(buf)
+
+ # in blocked_cb() we called set_blocked_async() with a different
+ # callback, so blocked_cb() should have been unreffed
+ cb_refcount_after = sys.getrefcount(blocked_cb)
+ self.assertEquals(sys.getrefcount(blocked_cb), cb_refcount)
if __name__ == "__main__":
unittest.main()