mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-02-20 04:56:24 +00:00
GstPad: Use gst_pad_set_blocked_async_full() if available.
Avoids leaking arguments. Fixes #514717
This commit is contained in:
parent
c09e3207bc
commit
51ac26b86c
2 changed files with 63 additions and 29 deletions
|
@ -24,6 +24,17 @@
|
||||||
%%
|
%%
|
||||||
headers
|
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 */
|
/* we need to do this until PyClosures get exception handlers */
|
||||||
#ifndef pyg_closure_set_exception_handler
|
#ifndef pyg_closure_set_exception_handler
|
||||||
# define pyg_closure_set_exception_handler(ig, nore)
|
# define pyg_closure_set_exception_handler(ig, nore)
|
||||||
|
@ -1331,6 +1342,16 @@ _wrap_gst_pad_get_query_types_default (PyGObject *self)
|
||||||
%%
|
%%
|
||||||
override gst_pad_set_blocked_async args
|
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
|
static void
|
||||||
pad_block_callback_marshal(GstPad *pad, gboolean blocked, gpointer user_data)
|
pad_block_callback_marshal(GstPad *pad, gboolean blocked, gpointer user_data)
|
||||||
{
|
{
|
||||||
|
@ -1397,8 +1418,14 @@ _wrap_gst_pad_set_blocked_async (PyGObject *self, PyObject *args)
|
||||||
if (data == NULL)
|
if (data == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
pyg_begin_allow_threads;
|
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,
|
ret = gst_pad_set_blocked_async (GST_PAD (self->obj), blocked,
|
||||||
(GstPadBlockCallback) pad_block_callback_marshal, data);
|
(GstPadBlockCallback) pad_block_callback_marshal, data);
|
||||||
|
#endif
|
||||||
pyg_end_allow_threads;
|
pyg_end_allow_threads;
|
||||||
if (ret)
|
if (ret)
|
||||||
pret = Py_True;
|
pret = Py_True;
|
||||||
|
|
|
@ -516,40 +516,47 @@ class PadRefCountTest(TestCase):
|
||||||
self.assertEquals(self.gccollect(), 1) # collected the pad
|
self.assertEquals(self.gccollect(), 1) # collected the pad
|
||||||
gst.debug('going into teardown')
|
gst.debug('going into teardown')
|
||||||
|
|
||||||
# re-enable this test once #514717 is fixed
|
class PadBlockTest(TestCase):
|
||||||
|
def testCallbackFlush(self):
|
||||||
|
# check that the same block callback can be called more than once (weird
|
||||||
|
# test but it was broken)
|
||||||
|
|
||||||
# class PadBlockRefcountTest(TestCase):
|
def blocked_cb(pad, blocked):
|
||||||
# def testCallbackRefcount(self):
|
pad.push_event(gst.event_new_flush_start())
|
||||||
# def blocked_cb(pad, blocked):
|
|
||||||
# self.assertTrue(pad.set_blocked_async(False, unblocked_cb))
|
pad = gst.Pad('src', gst.PAD_SRC)
|
||||||
|
pad.set_active(True)
|
||||||
|
pad.set_blocked_async(True, blocked_cb)
|
||||||
|
|
||||||
# def unblocked_cb(pad, blocked):
|
for i in xrange(10):
|
||||||
# pass
|
buf = gst.Buffer('ciao')
|
||||||
|
pad.push(buf)
|
||||||
|
pad.push_event(gst.event_new_flush_stop())
|
||||||
|
|
||||||
# cb_refcount = sys.getrefcount(blocked_cb)
|
def testCallbackRefcount(self):
|
||||||
# # sys.getrefcount() returns refcount + 1
|
def blocked_cb(pad, blocked):
|
||||||
# self.assertEquals(cb_refcount, 2)
|
pad.set_blocked_async(False, unblocked_cb)
|
||||||
|
|
||||||
# fakesrc = gst.element_factory_make('fakesrc')
|
def unblocked_cb(pad, blocked):
|
||||||
# fakesrc.props.num_buffers = 2
|
pass
|
||||||
# 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)
|
|
||||||
|
|
||||||
|
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__":
|
if __name__ == "__main__":
|
||||||
unittest.main()
|
unittest.main()
|
||||||
|
|
Loading…
Reference in a new issue