How to prevent one branch of a tee from blocking the other branches?

My application tees a live video camera source to multiple sinks. If one of the sinks blocks, it prevents the other sinks from receiving new buffers.

To demonstrate:

gst-launch-1.0 videotestsrc is-live=true ! tee name=t t. ! queue ! glimagesink t. ! queue ! valve drop=true ! fakesink

When valve’s drop property is true, the glimagesink shows only a couple frames and then freezes. If drop=false then the glimagesink runs smoothly forever.

I’ve tried various combinations of sync=false, async=true, and making the queue leaky in an attempt to keep the glimagesink rolling when the valve is dropping. But nothing has worked so far.

Any suggestions?

There are two slightly different problems at play here.

Are you sure glimagesink shows a couple of frames and not just the first one?

This sounds like a preroll problem: all sinks in the pipeline need an initial buffer / video frame in order to preroll, and the pipeline needs to preroll in order to go to PAUSED state (and to PLAYING state after).

So if no buffers (or GAP events in lieu of buffers) make it to the fakesink, then the fakesink won’t preroll and the pipeline won’t preroll and won’t start up (go to PLAYING state).

Here buffers don’t make it to the fakesink because you’re dropping them using the valve.

Couple of ways around that:

  1. use valve drop=true drop-mode=transform-to-gap
  2. use fakesink async=false
  3. don’t use valve here in the first place (which doesn’t sound like it achieves what you want anyway)

To me it sounds like what you really want is a leaky queue, so that in case the (real) sink consumes data too slowly (e.g. network drops out or not enough bandwidth) the queue will run full, at which point it would drop data (new or old) rather than block the upstream data producer and thus the tee and the other branch.

Make sure the queue max-size-* limits are set correctly or unset (to 0), since the first limit to be hit takes effect.

1 Like

Thanks for the explanation Tim. You’re right: glimagesink only shows the first frame. With fakesink async=false, the pipeline runs smoothly. For any other readers, I didn’t test the drop-mode property because that prop is not available on my older Gst 1.14 machine, but it wasn’t needed in this particular case.

I see that valve was a bad choice for this question. I was looking for an element to simulate a real sink consuming data too slowly.

A more realistic pipeline is the producer/consumer shown below. Launch the producer, then the consumer, and the producer watchdog detects a lost frame as soon as the consumer appsink blocks. Changing the producer queue to leaky=2 prevents the consumer from blocking the producer.

Producer

gst-launch-1.0 videotestsrc is-live=true ! video/x-raw, format=NV12, width=2560, height=1440 ! watchdog timeout=40 ! tee name=t \
t. ! queue ! glimagesink \
t. ! queue leaky=0 ! shmsink socket-path=mysock wait-for-connection=false

Consumer

gst-launch-1.0 shmsrc socket-path=mysock is-live=true do-timestamp=true ! video/x-raw, width=2560, height=1440, format=NV12, framerate=30/1 ! appsink

Please let me know if the producer/consumer above have any downsides.