Correct approach for retrying a network sink

Hi, I’m working on an application where I have video pipeline that’s starts with rtspsrc and includes a tee and then several independent downstream branches.

On one of the branches I want to push to a media server with RTMP, so that branch looks like:

tee ! queue leaky=downstream ! h264parse ! h264timestamper ! flvmux ! rtmpsink location="..."

I want:

  1. The pipeline not to fail if the media server is not available (or disappears while playing); and
  2. to retry connections every N seconds.

So far I’m only working on (1) only. What I have is

  1. listen on the message bus for errors from rtmpsink, and if/when those happen add a blocking probe to the queue src pad
  2. In the probe callback unlink the the queue and h264parse, and creat a fakesink and link queue to the fakesink.
  3. Put a message on the message bus to indicate that is done.
  4. In the message call back set h264parse and everything downstream of that to NULL and remove from the bin, and also set the pipeline to PLAYING.

This seems to work most of the time, but fails intermittently: if I start the application and then a little while later kill the media server that rtmpsink is connecting to then sometimes this switching out for fakesink seems to work and every thing else carries on fine. However sometimes instead I immediately get an error from the rtspsrc element.

Here’s the tail end of the debug output. Prior to the error there is nothing that jumps out at me, the messages all related to unlinking and removing the elements I’ve requested.

Am I taking the right approach to swapping out the rtmpsink for the fakesink and any pointers on the cause of that failure?

I’m not sure if it makes a difference but the queue and everything onwards is contained within a bin.

... clipped ....
0:00:14.450365705     7      0x253c450 INFO              GST_STATES gstelement.c:2724:_priv_gst_element_state_changed:<sink-streamtarget-x2g4q> notifying about state-changed PAUSED to READY (NULL pending)
0:00:14.450374027     7      0x253c450 INFO              GST_STATES gstelement.c:2804:gst_element_continue_state:<sink-streamtarget-x2g4q> continue state change READY to NULL, final NULL
0:00:14.450385078     7      0x253c450 INFO              GST_STATES gstelement.c:2824:gst_element_continue_state:<sink-streamtarget-x2g4q> completed state change to NULL
0:00:14.450394206     7      0x253c450 INFO              GST_STATES gstelement.c:2724:_priv_gst_element_state_changed:<sink-streamtarget-x2g4q> notifying about state-changed READY to NULL (VOID_PENDING pending)
0:00:14.450436504     7      0x253c450 INFO        GST_ELEMENT_PADS gstpad.c:2145:gst_pad_unlink: unlinking h264parse-streamtarget-x2g4q:src(0x2d3b100) and h264timestamper-streamtarget-x2g4q:sink(0x2d3db40)
0:00:14.450452162     7      0x253c450 INFO        GST_ELEMENT_PADS gstpad.c:2200:gst_pad_unlink: unlinked h264parse-streamtarget-x2g4q:src and h264timestamper-streamtarget-x2g4q:sink
0:00:14.450462664     7      0x253c450 INFO           GST_PARENTAGE gstbin.c:1805:gst_bin_remove_func:<streamtarget-bin-x2g4q> removed child "h264parse-streamtarget-x2g4q"
0:00:14.450486142     7      0x253c450 INFO        GST_ELEMENT_PADS gstpad.c:2145:gst_pad_unlink: unlinking h264timestamper-streamtarget-x2g4q:src(0x2d3df00) and flvmux-streamtarget-x2g4q:video(0x2d65b20)
0:00:14.450498841     7      0x253c450 INFO        GST_ELEMENT_PADS gstpad.c:2200:gst_pad_unlink: unlinked h264timestamper-streamtarget-x2g4q:src and flvmux-streamtarget-x2g4q:video
0:00:14.450510637     7      0x253c450 INFO           GST_PARENTAGE gstbin.c:1805:gst_bin_remove_func:<streamtarget-bin-x2g4q> removed child "h264timestamper-streamtarget-x2g4q"
0:00:14.450529402     7      0x253c450 INFO        GST_ELEMENT_PADS gstpad.c:2145:gst_pad_unlink: unlinking flvmux-streamtarget-x2g4q:src(0x2d42250) and sink-streamtarget-x2g4q:sink(0x2d643a0)
0:00:14.450540944     7      0x253c450 INFO        GST_ELEMENT_PADS gstpad.c:2200:gst_pad_unlink: unlinked flvmux-streamtarget-x2g4q:src and sink-streamtarget-x2g4q:sink
0:00:14.450550571     7      0x253c450 INFO           GST_PARENTAGE gstbin.c:1805:gst_bin_remove_func:<streamtarget-bin-x2g4q> removed child "flvmux-streamtarget-x2g4q"
0:00:14.450566899     7      0x253c450 INFO           GST_PARENTAGE gstbin.c:1805:gst_bin_remove_func:<streamtarget-bin-x2g4q> removed child "sink-streamtarget-x2g4q"
0:00:14.655103411     7 0x710fa40017d0 WARN                 rtspsrc gstrtspsrc.c:6511:gst_rtspsrc_loop:<source> error: Internal data stream error.
0:00:14.655138787     7 0x710fa40017d0 WARN                 rtspsrc gstrtspsrc.c:6511:gst_rtspsrc_loop:<source> error: streaming stopped, reason error (-5)
0:00:14.655174692     7 0x710fa40017d0 INFO        GST_ERROR_SYSTEM gstelement.c:2281:gst_element_message_full_with_details:<source> posting message: Internal data stream error.
0:00:14.655220428     7 0x710fa40017d0 INFO        GST_ERROR_SYSTEM gstelement.c:2308:gst_element_message_full_with_details:<source> posted error message: Internal data stream error.
0:00:14.655291407     7 0x710fa40017d0 INFO                    task gsttask.c:383:gst_task_func:<task0> Task going to paused

Follow up in case anyone else is having this issue: I think it’s maybe a bug with rtmpsink (see chat on replacement here, and link to a bug: Alternative RTMP implementation (#562) · Issues · GStreamer / gst-plugins-bad · GitLab)

I’ve not fully tested it yet, but moving to rtmp2sink instead.

I think your approach was the correct one indeed. And you’re probably correct that you hit an issue in rtmpsink.

1 Like