mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-01-03 14:08:56 +00:00
python: Add support for the GstURIHandlerInterface
Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/1423>
This commit is contained in:
parent
8b82463b01
commit
904bb001c5
3 changed files with 139 additions and 1 deletions
|
@ -15,6 +15,10 @@
|
|||
#
|
||||
# $ export GST_PLUGIN_PATH=$GST_PLUGIN_PATH:$PWD/plugin:$PWD/examples/plugins
|
||||
# $ GST_DEBUG=python:4 gst-launch-1.0 fakesrc num-buffers=10 ! mysink
|
||||
#
|
||||
# Since this implements the `mypysink://` protocol you can also do:
|
||||
#
|
||||
# $ gst-launch-1.0 videotestsrc ! pymysink://
|
||||
|
||||
from gi.repository import Gst, GObject, GstBase
|
||||
Gst.init(None)
|
||||
|
@ -22,7 +26,7 @@ Gst.init(None)
|
|||
#
|
||||
# Simple Sink element created entirely in python
|
||||
#
|
||||
class MySink(GstBase.BaseSink):
|
||||
class MySink(GstBase.BaseSink, Gst.URIHandler):
|
||||
__gstmetadata__ = ('CustomSink','Sink', \
|
||||
'Custom test sink element', 'Edward Hervey')
|
||||
|
||||
|
@ -31,9 +35,23 @@ class MySink(GstBase.BaseSink):
|
|||
Gst.PadPresence.ALWAYS,
|
||||
Gst.Caps.new_any())
|
||||
|
||||
__protocols__ = ("pymysink",)
|
||||
__uritype__ = Gst.URIType.SINK
|
||||
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
# Working around https://gitlab.gnome.org/GNOME/pygobject/-/merge_requests/129
|
||||
self.__dontkillme = self
|
||||
|
||||
def do_render(self, buffer):
|
||||
Gst.info("timestamp(buffer):%s" % (Gst.TIME_ARGS(buffer.pts)))
|
||||
return Gst.FlowReturn.OK
|
||||
|
||||
def do_get_uri(self, uri):
|
||||
return "pymysink://"
|
||||
|
||||
def do_set_uri(self, uri):
|
||||
return True
|
||||
|
||||
GObject.type_register(MySink)
|
||||
__gstelementfactory__ = ("mysink", Gst.Rank.NONE, MySink)
|
||||
|
|
|
@ -48,6 +48,14 @@ python module to use with Gst 0.10"
|
|||
warnings.warn(warn_msg, RuntimeWarning)
|
||||
|
||||
|
||||
# Ensuring that PyGObject loads the URIHandler interface
|
||||
# so we can force our own implementation soon enough (in gstmodule.c)
|
||||
class URIHandler(Gst.URIHandler):
|
||||
pass
|
||||
|
||||
URIHandler = override(URIHandler)
|
||||
__all__.append('URIHandler')
|
||||
|
||||
class Element(Gst.Element):
|
||||
@staticmethod
|
||||
def link_many(*args):
|
||||
|
|
|
@ -32,6 +32,9 @@
|
|||
|
||||
#include <locale.h>
|
||||
|
||||
#define URI_HANDLER_PROTOCOLS_QUARK g_quark_from_static_string("__gst__uri_handler_protocols")
|
||||
#define URI_HANDLER_URITYPE_QUARK g_quark_from_static_string("__gst__uri_handler_uritype")
|
||||
|
||||
#define PYGLIB_MODULE_START(symbol, modname) \
|
||||
static struct PyModuleDef _##symbol##module = { \
|
||||
PyModuleDef_HEAD_INIT, \
|
||||
|
@ -1103,6 +1106,113 @@ static PyMethodDef _gi_gst_functions[] = {
|
|||
{NULL, NULL, 0, NULL}
|
||||
};
|
||||
|
||||
static const gchar *const *
|
||||
py_uri_handler_get_protocols (GType type)
|
||||
{
|
||||
/* FIXME: Ideally we should be able to free the list of protocols on
|
||||
* deinitialization */
|
||||
return g_type_get_qdata (type, URI_HANDLER_PROTOCOLS_QUARK);
|
||||
}
|
||||
|
||||
static GstURIType
|
||||
py_uri_handler_get_type (GType type)
|
||||
{
|
||||
return GPOINTER_TO_INT (g_type_get_qdata (type, URI_HANDLER_URITYPE_QUARK));
|
||||
}
|
||||
|
||||
static const GStrv
|
||||
py_uri_handler_get_protocols_from_pyobject (PyObject * protocols)
|
||||
{
|
||||
GStrv res = NULL;
|
||||
|
||||
if (PyTuple_Check (protocols)) {
|
||||
gint i, len;
|
||||
|
||||
len = PyTuple_Size (protocols);
|
||||
if (len == 0) {
|
||||
PyErr_Format (PyExc_TypeError,
|
||||
"Empty tuple for GstUriHandler.__protocols");
|
||||
goto err;
|
||||
}
|
||||
|
||||
res = g_malloc (len * sizeof (gchar *));
|
||||
for (i = 0; i < len; i++) {
|
||||
PyObject *protocol = (PyObject *) PyTuple_GetItem (protocols, i);
|
||||
|
||||
if (!PyUnicode_Check (protocol)) {
|
||||
Py_DECREF (protocol);
|
||||
goto err;
|
||||
}
|
||||
|
||||
res[i] = g_strdup (PyUnicode_AsUTF8 (protocol));
|
||||
}
|
||||
} else {
|
||||
PyErr_Format (PyExc_TypeError, "invalid type for GstUriHandler.__protocols."
|
||||
" Should be a tuple");
|
||||
goto err;
|
||||
}
|
||||
|
||||
return res;
|
||||
|
||||
err:
|
||||
Py_DECREF (protocols);
|
||||
g_strfreev (res);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
uri_handler_iface_init (GstURIHandlerInterface * iface, PyTypeObject * pytype)
|
||||
{
|
||||
gint uritype;
|
||||
GStrv protocols;
|
||||
PyObject *pyprotocols = pytype ? PyObject_GetAttrString ((PyObject *) pytype,
|
||||
"__protocols__") : NULL;
|
||||
PyObject *pyuritype = pytype ? PyObject_GetAttrString ((PyObject *) pytype,
|
||||
"__uritype__") : NULL;
|
||||
GType gtype = pyg_type_from_object ((PyObject *) pytype);
|
||||
|
||||
if (pyprotocols == NULL) {
|
||||
PyErr_Format (PyExc_KeyError, "__protocols__ missing in %s",
|
||||
pytype->tp_name);
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (pyuritype == NULL) {
|
||||
PyErr_Format (PyExc_KeyError, "__pyuritype__ missing in %s",
|
||||
pytype->tp_name);
|
||||
goto done;
|
||||
}
|
||||
|
||||
protocols = py_uri_handler_get_protocols_from_pyobject (pyprotocols);
|
||||
if (!protocols)
|
||||
goto done;
|
||||
|
||||
if (pyg_enum_get_value (GST_TYPE_URI_TYPE, pyuritype, &uritype) < 0) {
|
||||
PyErr_SetString (PyExc_TypeError,
|
||||
"entry for __uritype__ must be of type GstURIType");
|
||||
goto done;
|
||||
}
|
||||
|
||||
iface->get_protocols = py_uri_handler_get_protocols;
|
||||
g_type_set_qdata (gtype, URI_HANDLER_PROTOCOLS_QUARK, protocols);
|
||||
|
||||
iface->get_type = py_uri_handler_get_type;
|
||||
g_type_set_qdata (gtype, URI_HANDLER_URITYPE_QUARK,
|
||||
GINT_TO_POINTER (uritype));
|
||||
|
||||
done:
|
||||
if (pyprotocols)
|
||||
Py_DECREF (pyprotocols);
|
||||
if (pyuritype)
|
||||
Py_DECREF (pyuritype);
|
||||
}
|
||||
|
||||
static const GInterfaceInfo GstURIHandlerInterfaceInfo = {
|
||||
(GInterfaceInitFunc) uri_handler_iface_init,
|
||||
NULL,
|
||||
NULL
|
||||
};
|
||||
|
||||
PYGLIB_MODULE_START (_gi_gst, "_gi_gst")
|
||||
{
|
||||
PyObject *d;
|
||||
|
@ -1120,6 +1230,8 @@ PYGLIB_MODULE_START (_gi_gst, "_gi_gst")
|
|||
d = PyModule_GetDict (module);
|
||||
gi_gst_register_types (d);
|
||||
pyg_register_class_init (GST_TYPE_ELEMENT, _pygst_element_init);
|
||||
pyg_register_interface_info (GST_TYPE_URI_HANDLER,
|
||||
&GstURIHandlerInterfaceInfo);
|
||||
}
|
||||
|
||||
PYGLIB_MODULE_END;
|
||||
|
|
Loading…
Reference in a new issue