Help with Gst.Iterator.find_custom() in python

classic Classic list List threaded Threaded
8 messages Options
Reply | Threaded
Open this post in threaded view
|

Help with Gst.Iterator.find_custom() in python

GStreamer-devel mailing list
Hi, I'm trying to create a function in python to find elements in a bin based
on their type (not name).

I have such a function in C which works and I'm trying to convert it to
python but I'm experiencing some issues.

def compare_gtype(element, type):
    print(element)
    print(type)
   
    return 1

def gst_bin_get_by_gtype(bin, type_name):
    factory = Gst.ElementFactory.find(type_name)
    type = factory.get_element_type()
    print(type_name)
    print(type)
   
    print("[" + bin.get_name() + "]: looking up child element of type " +
type.name)

    children = bin.iterate_recurse()        
    if children:
        print(children)
        print(children.type)
        found, elem = children.find_custom(compare_gtype, type)
    else:
        print("Error")

    if found:
        print("Found")
        return elem
    else:
        print("Not Found")
        return None

This is the output I get:

filesink
<GType GstFileSink (140449056935968)>
[pipeline0]: looking up child element of type GstFileSink
<Gst.Iterator object at 0x7fbcded2bdc0 (GstIterator at 0x7fbcd0009220)>
<GType GstElement (140449054520272)>
<GType GstFileSink (140449056935968)>
140448920294640
<GType GstFileSink (140449056935968)>
140448920294640
<GType GstFileSink (140449056935968)>
140448920294640
<GType GstFileSink (140449056935968)>
140448920294640
<GType GstFileSink (140449056935968)>
140448920294640
API Exception: {'type': 'TypeError', 'args': ('unknown type (null)',),
'message': 'unknown type (null)'}
Traceback (most recent call last):
  File "/usr/lib/python3/dist-packages/jsonrpc/manager.py", line 113, in
_get_responses
    result = method(*request.args, **request.kwargs)
  File "/home/msb/QtecGit/python-tests/gst_ctrl.py", line 248, in play
    gst_handler.play(index)
  File "/home/msb/QtecGit/python-tests/gst_ctrl.py", line 69, in play
    elem = gst_bin_get_by_gtype(self.pipeline[index], "filesink")
  File "/home/msb/QtecGit/python-tests/gst_ctrl.py", line 42, in
gst_bin_get_by_gtype
    found, elem = children.find_custom(compare_gtype, type)
TypeError: unknown type (null)

So for me it seems like the find_custom() is not passing the GstElement from
the iterator to the compare_gtype() function...

And this is the pipeline it is searching (no filesink):
filesrc name=replay location=/home/msb/test.ts ! decodebin ! videoconvert !
ximagesink sync=1

And just for reference the code in C:

static gint
compare_gtype(const GValue *velement, GType type)
{
        gint eq = 1;
        GstElement *element = g_value_get_object(velement);

        GST_OBJECT_LOCK(element);
        if (G_OBJECT_TYPE(element) == type)
                eq = 0;
        GST_OBJECT_UNLOCK(element);

        return eq;
}

static GstElement *
gst_bin_get_by_gtype(GstBin *bin, GType type)
{
        GstIterator *children;
        GValue result = { 0, };
        GstElement *element;
        gboolean found;

        g_return_val_if_fail(GST_IS_BIN(bin), NULL);

        QTEC_DEBUG("[%s]: looking up child element of type %s",
                   GST_ELEMENT_NAME(bin), g_type_name(type));

        children = gst_bin_iterate_recurse(bin);
        found = gst_iterator_find_custom(children,
                                         (GCompareFunc) compare_gtype,
                                         &result, (gpointer) type);
        gst_iterator_free(children);

        if (found) {
                element = g_value_dup_object(&result);
                g_value_unset(&result);
        } else {
                element = NULL;
        }

        return element;
}

        GstElementFactory * proxysrc_factory =
gst_element_factory_find("proxysrc");

        if (!proxysrc_factory)
                return FALSE;

        GType proxysrc_type =
gst_element_factory_get_element_type(proxysrc_factory);

        GstElement *psrc = gst_bin_get_by_gtype(GST_BIN(bin), proxysrc_type);



--
Sent from: http://gstreamer-devel.966125.n4.nabble.com/
_______________________________________________
gstreamer-devel mailing list
[hidden email]
https://lists.freedesktop.org/mailman/listinfo/gstreamer-devel
Reply | Threaded
Open this post in threaded view
|

Re: Help with Gst.Iterator.find_custom() in python

GStreamer-devel mailing list
Looks like a bug in pygobject, I tried to pinpoint it but that code base is
a bit of a maze :(

And I think there's actually two bugs: one is the parameters passed back
to the closure as you noticed, the other one is the final return value when
no match was found, these are two separate issues.

Note that the gst-python overrides let you iterate the GstIterator as a normal
python iterator, why don't you simply loop over it to find your object?

> Hi, I'm trying to create a function in python to find elements in a bin based
> on their type (not name).


On 5/21/21 9:24 AM, Marianna S. Buschle via gstreamer-devel wrote:

> Hi, I'm trying to create a function in python to find elements in a bin based
> on their type (not name).
>
> I have such a function in C which works and I'm trying to convert it to
> python but I'm experiencing some issues.
>
> def compare_gtype(element, type):
>     print(element)
>     print(type)
>    
>     return 1
>
> def gst_bin_get_by_gtype(bin, type_name):
>     factory = Gst.ElementFactory.find(type_name)
>     type = factory.get_element_type()
>     print(type_name)
>     print(type)
>    
>     print("[" + bin.get_name() + "]: looking up child element of type " +
> type.name)
>
>     children = bin.iterate_recurse()        
>     if children:
>         print(children)
>         print(children.type)
>         found, elem = children.find_custom(compare_gtype, type)
>     else:
>         print("Error")
>
>     if found:
>         print("Found")
>         return elem
>     else:
>         print("Not Found")
>         return None
>
> This is the output I get:
>
> filesink
> <GType GstFileSink (140449056935968)>
> [pipeline0]: looking up child element of type GstFileSink
> <Gst.Iterator object at 0x7fbcded2bdc0 (GstIterator at 0x7fbcd0009220)>
> <GType GstElement (140449054520272)>
> <GType GstFileSink (140449056935968)>
> 140448920294640
> <GType GstFileSink (140449056935968)>
> 140448920294640
> <GType GstFileSink (140449056935968)>
> 140448920294640
> <GType GstFileSink (140449056935968)>
> 140448920294640
> <GType GstFileSink (140449056935968)>
> 140448920294640
> API Exception: {'type': 'TypeError', 'args': ('unknown type (null)',),
> 'message': 'unknown type (null)'}
> Traceback (most recent call last):
>   File "/usr/lib/python3/dist-packages/jsonrpc/manager.py", line 113, in
> _get_responses
>     result = method(*request.args, **request.kwargs)
>   File "/home/msb/QtecGit/python-tests/gst_ctrl.py", line 248, in play
>     gst_handler.play(index)
>   File "/home/msb/QtecGit/python-tests/gst_ctrl.py", line 69, in play
>     elem = gst_bin_get_by_gtype(self.pipeline[index], "filesink")
>   File "/home/msb/QtecGit/python-tests/gst_ctrl.py", line 42, in
> gst_bin_get_by_gtype
>     found, elem = children.find_custom(compare_gtype, type)
> TypeError: unknown type (null)
>
> So for me it seems like the find_custom() is not passing the GstElement from
> the iterator to the compare_gtype() function...
>
> And this is the pipeline it is searching (no filesink):
> filesrc name=replay location=/home/msb/test.ts ! decodebin ! videoconvert !
> ximagesink sync=1
>
> And just for reference the code in C:
>
> static gint
> compare_gtype(const GValue *velement, GType type)
> {
> gint eq = 1;
> GstElement *element = g_value_get_object(velement);
>
> GST_OBJECT_LOCK(element);
> if (G_OBJECT_TYPE(element) == type)
> eq = 0;
> GST_OBJECT_UNLOCK(element);
>
> return eq;
> }
>
> static GstElement *
> gst_bin_get_by_gtype(GstBin *bin, GType type)
> {
> GstIterator *children;
> GValue result = { 0, };
> GstElement *element;
> gboolean found;
>
> g_return_val_if_fail(GST_IS_BIN(bin), NULL);
>
> QTEC_DEBUG("[%s]: looking up child element of type %s",
>   GST_ELEMENT_NAME(bin), g_type_name(type));
>
> children = gst_bin_iterate_recurse(bin);
> found = gst_iterator_find_custom(children,
> (GCompareFunc) compare_gtype,
> &result, (gpointer) type);
> gst_iterator_free(children);
>
> if (found) {
> element = g_value_dup_object(&result);
> g_value_unset(&result);
> } else {
> element = NULL;
> }
>
> return element;
> }
>
>         GstElementFactory * proxysrc_factory =
> gst_element_factory_find("proxysrc");
>
> if (!proxysrc_factory)
> return FALSE;
>
> GType proxysrc_type =
> gst_element_factory_get_element_type(proxysrc_factory);
>
> GstElement *psrc = gst_bin_get_by_gtype(GST_BIN(bin), proxysrc_type);
>
>
>
> --
> Sent from: http://gstreamer-devel.966125.n4.nabble.com/
> _______________________________________________
> gstreamer-devel mailing list
> [hidden email]
> https://lists.freedesktop.org/mailman/listinfo/gstreamer-devel
_______________________________________________
gstreamer-devel mailing list
[hidden email]
https://lists.freedesktop.org/mailman/listinfo/gstreamer-devel
Reply | Threaded
Open this post in threaded view
|

Re: Help with Gst.Iterator.find_custom() in python

GStreamer-devel mailing list
eg:

def gst_bin_get_by_gtype(b, type_name):
    factory = Gst.ElementFactory.find(type_name)
    return None if factory is None else next(filter(lambda c: c.__gtype__ == factory.get_element_type(), b.iterate_recurse()), None)

On 5/21/21 5:51 PM, Mathieu Duponchelle via gstreamer-devel wrote:
Looks like a bug in pygobject, I tried to pinpoint it but that code base is
a bit of a maze :(

And I think there's actually two bugs: one is the parameters passed back
to the closure as you noticed, the other one is the final return value when
no match was found, these are two separate issues.

Note that the gst-python overrides let you iterate the GstIterator as a normal
python iterator, why don't you simply loop over it to find your object?

Hi, I'm trying to create a function in python to find elements in a bin based
on their type (not name).

On 5/21/21 9:24 AM, Marianna S. Buschle via gstreamer-devel wrote:
Hi, I'm trying to create a function in python to find elements in a bin based
on their type (not name).

I have such a function in C which works and I'm trying to convert it to
python but I'm experiencing some issues.

def compare_gtype(element, type):
    print(element)
    print(type)
    
    return 1

def gst_bin_get_by_gtype(bin, type_name):
    factory = Gst.ElementFactory.find(type_name)
    type = factory.get_element_type()
    print(type_name)
    print(type)
    
    print("[" + bin.get_name() + "]: looking up child element of type " +
type.name)

    children = bin.iterate_recurse()        
    if children:
        print(children)
        print(children.type)
        found, elem = children.find_custom(compare_gtype, type)
    else:
        print("Error")

    if found:
        print("Found")
        return elem
    else:
        print("Not Found")
        return None

This is the output I get:

filesink
<GType GstFileSink (140449056935968)>
[pipeline0]: looking up child element of type GstFileSink
<Gst.Iterator object at 0x7fbcded2bdc0 (GstIterator at 0x7fbcd0009220)>
<GType GstElement (140449054520272)>
<GType GstFileSink (140449056935968)>
140448920294640
<GType GstFileSink (140449056935968)>
140448920294640
<GType GstFileSink (140449056935968)>
140448920294640
<GType GstFileSink (140449056935968)>
140448920294640
<GType GstFileSink (140449056935968)>
140448920294640
API Exception: {'type': 'TypeError', 'args': ('unknown type (null)',),
'message': 'unknown type (null)'}
Traceback (most recent call last):
  File "/usr/lib/python3/dist-packages/jsonrpc/manager.py", line 113, in
_get_responses
    result = method(*request.args, **request.kwargs)
  File "/home/msb/QtecGit/python-tests/gst_ctrl.py", line 248, in play
    gst_handler.play(index)
  File "/home/msb/QtecGit/python-tests/gst_ctrl.py", line 69, in play
    elem = gst_bin_get_by_gtype(self.pipeline[index], "filesink")
  File "/home/msb/QtecGit/python-tests/gst_ctrl.py", line 42, in
gst_bin_get_by_gtype
    found, elem = children.find_custom(compare_gtype, type)
TypeError: unknown type (null)

So for me it seems like the find_custom() is not passing the GstElement from
the iterator to the compare_gtype() function...

And this is the pipeline it is searching (no filesink):
filesrc name=replay location=/home/msb/test.ts ! decodebin ! videoconvert !
ximagesink sync=1

And just for reference the code in C:

static gint
compare_gtype(const GValue *velement, GType type)
{
	gint eq = 1;
	GstElement *element = g_value_get_object(velement);

	GST_OBJECT_LOCK(element);
	if (G_OBJECT_TYPE(element) == type)
		eq = 0;
	GST_OBJECT_UNLOCK(element);

	return eq;
}

static GstElement *
gst_bin_get_by_gtype(GstBin *bin, GType type)
{
	GstIterator *children;
	GValue result = { 0, };
	GstElement *element;
	gboolean found;

	g_return_val_if_fail(GST_IS_BIN(bin), NULL);

	QTEC_DEBUG("[%s]: looking up child element of type %s",
		   GST_ELEMENT_NAME(bin), g_type_name(type));

	children = gst_bin_iterate_recurse(bin);
	found = gst_iterator_find_custom(children,
					 (GCompareFunc) compare_gtype,
					 &result, (gpointer) type);
	gst_iterator_free(children);

	if (found) {
		element = g_value_dup_object(&result);
		g_value_unset(&result);
	} else {
		element = NULL;
	}

	return element;
}

        GstElementFactory * proxysrc_factory =
gst_element_factory_find("proxysrc");

	if (!proxysrc_factory)
		return FALSE;

	GType proxysrc_type =
gst_element_factory_get_element_type(proxysrc_factory);

	GstElement *psrc = gst_bin_get_by_gtype(GST_BIN(bin), proxysrc_type);



--
Sent from: http://gstreamer-devel.966125.n4.nabble.com/
_______________________________________________
gstreamer-devel mailing list
[hidden email]
https://lists.freedesktop.org/mailman/listinfo/gstreamer-devel
_______________________________________________
gstreamer-devel mailing list
[hidden email]
https://lists.freedesktop.org/mailman/listinfo/gstreamer-devel

_______________________________________________
gstreamer-devel mailing list
[hidden email]
https://lists.freedesktop.org/mailman/listinfo/gstreamer-devel
Reply | Threaded
Open this post in threaded view
|

Re: Help with Gst.Iterator.find_custom() in python

GStreamer-devel mailing list
Hi, thanks for the help

I had tried using the iterator directly previously, but couldn't get it to
work either.
So I though that maybe it was me not knowing how to use it.

But with your code I'm getting similar errors:

API Exception: {'type': 'TypeError', 'args': ("'Iterator' object is not
iterable",), 'message': "'Iterator' object is not iterable"}
Traceback (most recent call last):
  File "/usr/lib/python3/dist-packages/jsonrpc/manager.py", line 113, in
_get_responses
    result = method(*request.args, **request.kwargs)
  File "/home/msb/QtecGit/python-tests/gst_ctrl.py", line 283, in play
    gst_handler.play(index)
  File "/home/msb/QtecGit/python-tests/gst_ctrl.py", line 79, in play
    elem = gst_bin_get_by_gtype(self.pipeline[index], "filesink")
  File "/home/msb/QtecGit/python-tests/gst_ctrl.py", line 61, in
gst_bin_get_by_gtype
    return None if factory is None else next(filter(lambda c: c.__gtype__ ==
factory.get_element_type(), bin.iterate_recurse()), None)
TypeError: 'Iterator' object is not iterable




--
Sent from: http://gstreamer-devel.966125.n4.nabble.com/
_______________________________________________
gstreamer-devel mailing list
[hidden email]
https://lists.freedesktop.org/mailman/listinfo/gstreamer-devel
Reply | Threaded
Open this post in threaded view
|

Re: Help with Gst.Iterator.find_custom() in python

GStreamer-devel mailing list
I did manage to make it work like this:

def gst_bin_get_by_gtype(bin, type_name):
    factory = Gst.ElementFactory.find(type_name)
    if factory is None:
        print("No factory found for " + type_name)
        return None
    type = factory.get_element_type()
    print("[" + bin.get_name() + "]: looking up child element of type " +
type.name)
   
    children = bin.iterate_recurse()        
    if children is None:
        print("Iterate Error")
        return None
       
    elem = children.next().elem
    while elem:
        #print(elem.name)
        #print(elem.__gtype__)
        if elem.__gtype__ == type:
            return elem
        elem = children.next().elem
       
    return None

And found out that since gstreamer 1.18 I can also use:

    #from gst 1.18
    children = bin.iterate_all_by_element_factory_name(type_name)
    if children is None:
        print("Iterate Error")
        return None
    res = []
    elem = children.next().elem
    while elem:
        print(elem.name)
        #print(elem.__gtype__)
        res.append(elem)
        elem = children.next().elem
    return res



--
Sent from: http://gstreamer-devel.966125.n4.nabble.com/
_______________________________________________
gstreamer-devel mailing list
[hidden email]
https://lists.freedesktop.org/mailman/listinfo/gstreamer-devel
Reply | Threaded
Open this post in threaded view
|

Re: Help with Gst.Iterator.find_custom() in python

GStreamer-devel mailing list
Hey, it looks like you're missing the gst-python overrides:

https://gitlab.freedesktop.org/gstreamer/gst-python/-/blob/master/gi/overrides/Gst.py#L233-246

On 5/25/21 2:09 PM, Marianna S. Buschle via gstreamer-devel wrote:

> I did manage to make it work like this:
>
> def gst_bin_get_by_gtype(bin, type_name):
>     factory = Gst.ElementFactory.find(type_name)
>     if factory is None:
>         print("No factory found for " + type_name)
>         return None
>     type = factory.get_element_type()
>     print("[" + bin.get_name() + "]: looking up child element of type " +
> type.name)
>    
>     children = bin.iterate_recurse()        
>     if children is None:
>         print("Iterate Error")
>         return None
>        
>     elem = children.next().elem
>     while elem:
>         #print(elem.name)
>         #print(elem.__gtype__)
>         if elem.__gtype__ == type:
>             return elem
>         elem = children.next().elem
>        
>     return None
>
> And found out that since gstreamer 1.18 I can also use:
>
>     #from gst 1.18
>     children = bin.iterate_all_by_element_factory_name(type_name)
>     if children is None:
>         print("Iterate Error")
>         return None
>     res = []
>     elem = children.next().elem
>     while elem:
>         print(elem.name)
>         #print(elem.__gtype__)
>         res.append(elem)
>         elem = children.next().elem
>     return res
>
>
>
> --
> Sent from: http://gstreamer-devel.966125.n4.nabble.com/
> _______________________________________________
> gstreamer-devel mailing list
> [hidden email]
> https://lists.freedesktop.org/mailman/listinfo/gstreamer-devel
_______________________________________________
gstreamer-devel mailing list
[hidden email]
https://lists.freedesktop.org/mailman/listinfo/gstreamer-devel
Reply | Threaded
Open this post in threaded view
|

Re: Help with Gst.Iterator.find_custom() in python

GStreamer-devel mailing list
Thanks,

Your code does work after installing: python3-gst-1.0



--
Sent from: http://gstreamer-devel.966125.n4.nabble.com/
_______________________________________________
gstreamer-devel mailing list
[hidden email]
https://lists.freedesktop.org/mailman/listinfo/gstreamer-devel
Reply | Threaded
Open this post in threaded view
|

Re: Help with Gst.Iterator.find_custom() in python

GStreamer-devel mailing list
Cool :)

On 5/26/21 9:21 AM, Marianna S. Buschle via gstreamer-devel wrote:

> Thanks,
>
> Your code does work after installing: python3-gst-1.0
>
>
>
> --
> Sent from: http://gstreamer-devel.966125.n4.nabble.com/
> _______________________________________________
> gstreamer-devel mailing list
> [hidden email]
> https://lists.freedesktop.org/mailman/listinfo/gstreamer-devel
_______________________________________________
gstreamer-devel mailing list
[hidden email]
https://lists.freedesktop.org/mailman/listinfo/gstreamer-devel