gstrtpbin race condition

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

gstrtpbin race condition

Wes Miller
Administrator
I have created a gstrtpbin based sender/receiver program where the same gstrtpbin services both the incoming and outgoing streams.  When the program starts I can watch (via print statements) as pads are added and connections are made.  The connection from recv_rtp_src_%d_%d_%d to the receive pipe, i.e. the depayloader, waits until a packet is received from the remote host.  This works great so long as the remote host sends a packet, but if it doesn't, I am deadlocked.

In particular, when I use my programs for both ends of the connection, I see both get down to waiting for recv_rtp_src_%d_%d_%d to connect.  Neither ever gets to running because it is waiting on the other.  a classic race condition. (or is that a Mexican Standoff?)

So, I'd like a suggestion on how to get things rolling.  Do I somehow need to start a local pipe that send data to myself to get me kicked off?  Is there a way to force gstrtpbin to create recv_rtp_src_%d_%d_%d without seeing an inbound packet?  Or should I mux the udpsrc with an audiotestsrc (with num-buffers = 1 or 5 or ???) to fool the gstrtpbin into thinking it is seeing (bad) traffic?

Warmly,

Wes


Reply | Threaded
Open this post in threaded view
|

Re: [SOLVED] gstrtpbin race condition

Wes Miller
Administrator
The solution proved to be quite picky but simple.

I added a simple, separate, loop and pipeline that hooked an audiotestsrc to an encoder, payloader and udpsink. I call this the priming pump.

In the main thread, I set the main pipeline to PLAYING, got rc = async wiat. Then I started  the priming pump and pointed its udpsink at the main pipelines udpsrc (i.e. myself).  The data from the priming pump flows into the main pipe and gets it started.

 --> mainthread --> pipeline to PLAYING, rc = async wait --> launch priming pump --> main pipeline completes async wait

Since I am using the same programs in two computers, call them host and client, the freshly started main pipeline on the first machine connects sound in through the gstrtpbin and out through the udpsink onto the net, into the other program/PC's udpsrc and that data starts the second instance.

Works great except for the gotchas....

First, data leaving the second machine and flowing into the first uses the same port as the priming pump.  So I added a num-buffers to the audiotestsrc in the primer.  Unfortunately, the EOS that produced could cause the second instance to terminate.So instead, I added a timer to the second thread and had it abruptly terminate the priming pump so it couldn't send an EOS.

Then there is the matter of unhocking the priming pump's SSRC connection through gstrtpbin with the actual data streams SSRC.  That required a padprobe on the priming pump to get its SSRC.  Using that info, on_pad_added() can tell if incoming data is primer data or real data and change the connection when real data shows up.

Adding another padprobe on the main udpsrc to see what the current incoming SSRC is can be used to prevent the launch of the priming thread.  If you are already working with data you don't need to be primed.

So, hope this helps someone else get started.  The solution is not perfect as I still have sound quality issues which I've asked about in later posting to this discussion group.  If/when those questions get answers I may be able to get a good working solution.

Warmly,

Wes

--- encouraging everyone to post your final solutions.  Unanswered and incomplete questions help no one. ---