Caps negotiation when there are multiple src pads

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

Caps negotiation when there are multiple src pads

jackBuffington
I have a gstreamer element that I am writing where I have multiple src pads.   All of them should have the same caps since they are all created from the same template.  I see the pads when I use gst-inspect.  If I run a pipeline where I connect to the original 'src' pad that is currently a leftover from the code that I am building from, everything works great.  My chain function is running and I push to the src pad.   

If I change things so that my chain function pushes to one of the other pads and then build a pipeline that connects to that pad, the pipeline gets built but fails in the chain function because the caps weren't negotiated.  

Similarly, if I make it so that it pushes to both the src pad and one of the other pads and then construct a pipeline that connects to src and the other pad, the buffer successfully comes out of the src pad and then it hangs when trying to push to the other pad.  When I look at a graph of that pipeline (created using dot) then I can see that indeed, the src pad has fully been negotiated but the other pad has not and I see all of the possible options that it could output.  

So...  

What should I do to make this element negotiate caps for all pads rather than just the original sink and src?  I have everything else in my element working but this part is stumping me.   

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

Re: Caps negotiation when there are multiple src pads

jackBuffington
I'll answer my own question and ask a new one since I have received no reply.
I have partially figured out what to do and hopefully this will help someone
in the future.

It appears that GstBaseTransform only will facilitate negotiating caps for
the src and sink pads.  You are on your own for anything else.  In my case,
I did the following:

In the set_caps function I faked my own negotiation by copying the final
caps of the src pad.  In my case, this will work because I have them
connected to the same things.  I did this by:

I called gst_query_caps using the src pad to get the caps on that pad.
I used gst_set_caps on my other source pad(s) using the caps from the last
step.
I call gst_pad_query_accept_caps for my other source pad(s) to see if the
connecting pad can accept those caps (I know they can but put this in
because I eventually want to do a full negotiation)
I then use gst_pad_push_event on my other source pad(s) with
gst_event_new_caps and the caps which I want the connecting pad to use.  
I'm not certain if this step is necessary but I then called
gst_pad_set_active for the pad for my other source pads.  

At each step I am doing checks to make sure that things go OK.  

This allows things to connect up and I can see when I graph out my pipeline
that the caps are indeed properly 'negotiated'.

OK.   So everything works now right?   Unfortunately not.  I'm stuck again.
If I connect to just one of the pads and code my chain function so that it
pushes to just that pad, I get video passing through just fine.  If I
connect to two pads and push to either pad, it will push one buffer and then
forever hang.   If I hit Control+C to kill the pipeline then it will
continue on to the next line of code which is my check to see what the
return value of the push was.  It is returning GST_FLOW_FLUSHING, which is
typically what I see when I kill the pipeline if I am running with only one
pad connected.    

So my new question is now that I am SO close to being done with this (I
think) how do I just get it to not hang on the push?





--
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: Caps negotiation when there are multiple src pads

David Ing
Are your src pads each connected to queues of some kind?

Elements with multiple src pads should always be connected directly to queues because queues create thread boundaries.  Without these thread boundaries you typically see deadlocking.  I have even seen deadlocking during caps negotiation.

Demuxers, tees, anything with multiple src pads ... Each src pads should always connect to some kind of queue.

On Thu, May 21, 2020, 8:34 AM jackBuffington <[hidden email]> wrote:
I'll answer my own question and ask a new one since I have received no reply.
I have partially figured out what to do and hopefully this will help someone
in the future.

It appears that GstBaseTransform only will facilitate negotiating caps for
the src and sink pads.  You are on your own for anything else.  In my case,
I did the following:

In the set_caps function I faked my own negotiation by copying the final
caps of the src pad.  In my case, this will work because I have them
connected to the same things.  I did this by:

I called gst_query_caps using the src pad to get the caps on that pad.
I used gst_set_caps on my other source pad(s) using the caps from the last
step.
I call gst_pad_query_accept_caps for my other source pad(s) to see if the
connecting pad can accept those caps (I know they can but put this in
because I eventually want to do a full negotiation)
I then use gst_pad_push_event on my other source pad(s) with
gst_event_new_caps and the caps which I want the connecting pad to use. 
I'm not certain if this step is necessary but I then called
gst_pad_set_active for the pad for my other source pads.   

At each step I am doing checks to make sure that things go OK. 

This allows things to connect up and I can see when I graph out my pipeline
that the caps are indeed properly 'negotiated'.

OK.   So everything works now right?   Unfortunately not.  I'm stuck again.
If I connect to just one of the pads and code my chain function so that it
pushes to just that pad, I get video passing through just fine.  If I
connect to two pads and push to either pad, it will push one buffer and then
forever hang.   If I hit Control+C to kill the pipeline then it will
continue on to the next line of code which is my check to see what the
return value of the push was.  It is returning GST_FLOW_FLUSHING, which is
typically what I see when I kill the pipeline if I am running with only one
pad connected.     

So my new question is now that I am SO close to being done with this (I
think) how do I just get it to not hang on the push?





--
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: Caps negotiation when there are multiple src pads

jackBuffington
Thank you so much David!  I was really frustrated with this.  Between that
and setting sync=false on my display element, I am now getting video out of
both pads!  



--
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: Caps negotiation when there are multiple src pads

Mathieu Duponchelle
In reply to this post by jackBuffington
It sounds like what you want to do is closer to a demuxer than your
typical BaseTransform subclass. While we do have a base class
for N-to-1 elements (GstAggregator), you are indeed on your own
when it comes to 1-to-N elements for now.

As David pointed out, the hang is at least easily solvable as it is a
standard trap when plugging in a demuxer-like element: your first
push hangs forever, blocked by the prerolling sink, and prerolling
will never occur because you would need to push on your second
src pad for all sinks to be prerolled :)

Depending on your use case, you can either make your sinks
async=false, or add queues (that's the most commonly correct
solution).

Depending on what you're trying to do, you might want to subclass
GstElement directly, and take some inspiration from standard
demuxers. Note that you probably want to use a GstFlowCombiner
by the way.

Good luck,

--
Mathieu Duponchelle · https://www.centricular.com


On 5/21/20 5:34 PM, jackBuffington wrote:

> I'll answer my own question and ask a new one since I have received no reply.
> I have partially figured out what to do and hopefully this will help someone
> in the future.
>
> It appears that GstBaseTransform only will facilitate negotiating caps for
> the src and sink pads.  You are on your own for anything else.  In my case,
> I did the following:
>
> In the set_caps function I faked my own negotiation by copying the final
> caps of the src pad.  In my case, this will work because I have them
> connected to the same things.  I did this by:
>
> I called gst_query_caps using the src pad to get the caps on that pad.
> I used gst_set_caps on my other source pad(s) using the caps from the last
> step.
> I call gst_pad_query_accept_caps for my other source pad(s) to see if the
> connecting pad can accept those caps (I know they can but put this in
> because I eventually want to do a full negotiation)
> I then use gst_pad_push_event on my other source pad(s) with
> gst_event_new_caps and the caps which I want the connecting pad to use.  
> I'm not certain if this step is necessary but I then called
> gst_pad_set_active for the pad for my other source pads.  
>
> At each step I am doing checks to make sure that things go OK.  
>
> This allows things to connect up and I can see when I graph out my pipeline
> that the caps are indeed properly 'negotiated'.
>
> OK.   So everything works now right?   Unfortunately not.  I'm stuck again.
> If I connect to just one of the pads and code my chain function so that it
> pushes to just that pad, I get video passing through just fine.  If I
> connect to two pads and push to either pad, it will push one buffer and then
> forever hang.   If I hit Control+C to kill the pipeline then it will
> continue on to the next line of code which is my check to see what the
> return value of the push was.  It is returning GST_FLOW_FLUSHING, which is
> typically what I see when I kill the pipeline if I am running with only one
> pad connected.    
>
> So my new question is now that I am SO close to being done with this (I
> think) how do I just get it to not hang on the push?
>
>
>
>
>
> --
> 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