Problem: splitmuxsink functions correctly with a local pipeline, but not in a similar two-pipeline setup split by udpsink & udpsrc.
Hello all, I’m prototyping a video archiving pipeline using this as my starting point.
GStreamer 1.28.2 and gst-plugin-rs tag gstreamer-1.29.2.
The fully local (no network) pipeline works exactly like how I want it to: it produces 10 second fragmented MP4 video files with 2 seconds per fragments.
$ gst-launch-1.0 videotestsrc pattern=0 is-live=true ! video/x-raw,width=3840,height=2160,framerate=25/1 \
! timeoverlay \
! x265enc tune=zerolatency key-int-max=25 \
! video/x-h265,profile=main \
! h265parse \
! splitmuxsink location=test4-%02d.mp4 max-size-time=10000000000 send-keyframe-requests=true async-finalize=true muxer-factory=isofmp4mux muxer-properties="properties,fragment-duration=2000000000,offset-to-zero=true,header-update-mode=1,write-mehd=true,write-mfra=true"
$ gst-discoverer-1.0 test4-02.mp4
Analyzing file:///home/adrian/test-gstreamer/test4-02.mp4
Done discovering file:///home/adrian/test-gstreamer/test4-02.mp4
Properties:
Duration: 0:00:10.000000000
Seekable: yes
Live: no
container #0: Quicktime
video #1: H.265 (Main Profile)
Stream ID: f73f66652eef94e6053e0dcb163cae67a3194cc98210fcd8a66dc6fd458136cd/001
Width: 3840
Height: 2160
Depth: 24
Frame rate: 25/1
Pixel aspect ratio: 1/1
Interlaced: false
Bitrate: 2095233
Max bitrate: 2097152
So my natural next step is to split the above into two pipelines, and add a network in between:
Sender
$ gst-launch-1.0 videotestsrc pattern=0 is-live=true ! video/x-raw,width=3840,height=2160 \
! timeoverlay \
! x265enc tune=zerolatency key-int-max=25 \
! video/x-h265,profile=main \
! rtph265pay pt=96 config-interval=-1 \
! udpsink host=224.0.2.1 port=5050
And the receiver, which is giving me EOS:
$ gst-launch-1.0 udpsrc -v address=224.0.2.1 port=5050 \
! application/x-rtp,media=video,clock-rate=90000,encoding-name=H265 \
! rtpjitterbuffer \
! rtph265depay \
! h265parse \
! splitmuxsink location=testrx-%02d.mp4 max-size-time=10000000000 send-keyframe-requests=true async-finalize=true muxer-factory=isofmp4mux muxer-properties="properties,fragment-duration=2000000000,offset-to-zero=true,header-update-mode=1,write-mehd=true,write-mfra=true"
Setting pipeline to PAUSED ...
Pipeline is live and does not need PREROLL ...
/GstPipeline:pipeline0/GstSplitMuxSink:splitmuxsink0/GstFileSink:sink: async = false
Pipeline is PREROLLED ...
Setting pipeline to PLAYING ...
New clock: GstSystemClock
/GstPipeline:pipeline0/GstCapsFilter:capsfilter0.GstPad:src: caps = application/x-rtp, media=(string)video, clock-rate=(int)90000, encoding-name=(string)H265
/GstPipeline:pipeline0/GstRtpJitterBuffer:rtpjitterbuffer0.GstPad:sink: caps = application/x-rtp, media=(string)video, clock-rate=(int)90000, encoding-name=(string)H265
/GstPipeline:pipeline0/GstRtpJitterBuffer:rtpjitterbuffer0.GstPad:src: caps = application/x-rtp, media=(string)video, clock-rate=(int)90000, encoding-name=(string)H265
/GstPipeline:pipeline0/GstRtpH265Depay:rtph265depay0: extensions = < >
/GstPipeline:pipeline0/GstRtpH265Depay:rtph265depay0.GstPad:sink: caps = application/x-rtp, media=(string)video, clock-rate=(int)90000, encoding-name=(string)H265
/GstPipeline:pipeline0/GstRtpH265Depay:rtph265depay0.GstPad:src: caps = video/x-h265, stream-format=(string)hvc1, alignment=(string)au, codec_data=(buffer)01016000000090000000000096f000fcfdf8f800000f03200001001840010c01ffff0160000003009000000300000300969280902100010031420101016000000300900000030000030096a001e020021c5964a924cafff000100016a020202080000003008000000f0422000100074401c172b46240, profile=(string)main, tier=(string)main, level=(string)5
/GstPipeline:pipeline0/GstH265Parse:h265parse0.GstPad:sink: caps = video/x-h265, stream-format=(string)hvc1, alignment=(string)au, codec_data=(buffer)01016000000090000000000096f000fcfdf8f800000f03200001001840010c01ffff0160000003009000000300000300969280902100010031420101016000000300900000030000030096a001e020021c5964a924cafff000100016a020202080000003008000000f0422000100074401c172b46240, profile=(string)main, tier=(string)main, level=(string)5
Redistribute latency...
/GstPipeline:pipeline0/GstH265Parse:h265parse0.GstPad:src: caps = video/x-h265, stream-format=(string)hvc1, alignment=(string)au, codec_data=(buffer)01016000000090000000000096f000fcfdf8f800000f03200001001840010c01ffff0160000003009000000300000300969280902100010031420101016000000300900000030000030096a001e020021c5964a924cafff000100016a020202080000003008000000f0422000100074401c172b46240, profile=(string)main, tier=(string)main, level=(string)5, width=(int)3840, height=(int)2160, framerate=(fraction)30/1, chroma-format=(string)4:2:0, bit-depth-luma=(uint)8, bit-depth-chroma=(uint)8, colorimetry=(string)bt709, parsed=(boolean)true, pixel-aspect-ratio=(fraction)1/1, lcevc=(boolean)false
/GstPipeline:pipeline0/GstSplitMuxSink:splitmuxsink0.GstGhostPad:video.GstProxyPad:proxypad0: caps = video/x-h265, stream-format=(string)hvc1, alignment=(string)au, codec_data=(buffer)01016000000090000000000096f000fcfdf8f800000f03200001001840010c01ffff0160000003009000000300000300969280902100010031420101016000000300900000030000030096a001e020021c5964a924cafff000100016a020202080000003008000000f0422000100074401c172b46240, profile=(string)main, tier=(string)main, level=(string)5, width=(int)3840, height=(int)2160, framerate=(fraction)30/1, chroma-format=(string)4:2:0, bit-depth-luma=(uint)8, bit-depth-chroma=(uint)8, colorimetry=(string)bt709, parsed=(boolean)true, pixel-aspect-ratio=(fraction)1/1, lcevc=(boolean)false
/GstPipeline:pipeline0/GstSplitMuxSink:splitmuxsink0/GstQueue:queue_video.GstPad:sink: caps = video/x-h265, stream-format=(string)hvc1, alignment=(string)au, codec_data=(buffer)01016000000090000000000096f000fcfdf8f800000f03200001001840010c01ffff0160000003009000000300000300969280902100010031420101016000000300900000030000030096a001e020021c5964a924cafff000100016a020202080000003008000000f0422000100074401c172b46240, profile=(string)main, tier=(string)main, level=(string)5, width=(int)3840, height=(int)2160, framerate=(fraction)30/1, chroma-format=(string)4:2:0, bit-depth-luma=(uint)8, bit-depth-chroma=(uint)8, colorimetry=(string)bt709, parsed=(boolean)true, pixel-aspect-ratio=(fraction)1/1, lcevc=(boolean)false
/GstPipeline:pipeline0/GstSplitMuxSink:splitmuxsink0.GstGhostPad:video: caps = video/x-h265, stream-format=(string)hvc1, alignment=(string)au, codec_data=(buffer)01016000000090000000000096f000fcfdf8f800000f03200001001840010c01ffff0160000003009000000300000300969280902100010031420101016000000300900000030000030096a001e020021c5964a924cafff000100016a020202080000003008000000f0422000100074401c172b46240, profile=(string)main, tier=(string)main, level=(string)5, width=(int)3840, height=(int)2160, framerate=(fraction)30/1, chroma-format=(string)4:2:0, bit-depth-luma=(uint)8, bit-depth-chroma=(uint)8, colorimetry=(string)bt709, parsed=(boolean)true, pixel-aspect-ratio=(fraction)1/1, lcevc=(boolean)false
/GstPipeline:pipeline0/GstSplitMuxSink:splitmuxsink0/GstQueue:queue_video.GstPad:src: caps = video/x-h265, stream-format=(string)hvc1, alignment=(string)au, codec_data=(buffer)01016000000090000000000096f000fcfdf8f800000f03200001001840010c01ffff0160000003009000000300000300969280902100010031420101016000000300900000030000030096a001e020021c5964a924cafff000100016a020202080000003008000000f0422000100074401c172b46240, profile=(string)main, tier=(string)main, level=(string)5, width=(int)3840, height=(int)2160, framerate=(fraction)30/1, chroma-format=(string)4:2:0, bit-depth-luma=(uint)8, bit-depth-chroma=(uint)8, colorimetry=(string)bt709, parsed=(boolean)true, pixel-aspect-ratio=(fraction)1/1, lcevc=(boolean)false
/GstPipeline:pipeline0/GstSplitMuxSink:splitmuxsink0/GstISOFMP4Mux:muxer.GstFMP4MuxPad:sink_0: caps = video/x-h265, stream-format=(string)hvc1, alignment=(string)au, codec_data=(buffer)01016000000090000000000096f000fcfdf8f800000f03200001001840010c01ffff0160000003009000000300000300969280902100010031420101016000000300900000030000030096a001e020021c5964a924cafff000100016a020202080000003008000000f0422000100074401c172b46240, profile=(string)main, tier=(string)main, level=(string)5, width=(int)3840, height=(int)2160, framerate=(fraction)30/1, chroma-format=(string)4:2:0, bit-depth-luma=(uint)8, bit-depth-chroma=(uint)8, colorimetry=(string)bt709, parsed=(boolean)true, pixel-aspect-ratio=(fraction)1/1, lcevc=(boolean)false
/GstPipeline:pipeline0/GstSplitMuxSink:splitmuxsink0/GstFileSink:sink: location = testrx-00.mp4
Redistribute latency...
/GstPipeline:pipeline0/GstSplitMuxSink:splitmuxsink0/GstQueue:queue_video: max-size-buffers = 6
/GstPipeline:pipeline0/GstSplitMuxSink:splitmuxsink0/GstQueue:queue_video: max-size-buffers = 7
/GstPipeline:pipeline0/GstSplitMuxSink:splitmuxsink0/GstQueue:queue_video: max-size-buffers = 8
/GstPipeline:pipeline0/GstSplitMuxSink:splitmuxsink0/GstQueue:queue_video: max-size-buffers = 9
/GstPipeline:pipeline0/GstSplitMuxSink:splitmuxsink0/GstQueue:queue_video: max-size-buffers = 10
/GstPipeline:pipeline0/GstSplitMuxSink:splitmuxsink0/GstQueue:queue_video: max-size-buffers = 11
/GstPipeline:pipeline0/GstSplitMuxSink:splitmuxsink0/GstQueue:queue_video: max-size-buffers = 12
/GstPipeline:pipeline0/GstSplitMuxSink:splitmuxsink0/GstQueue:queue_video: max-size-buffers = 13
/GstPipeline:pipeline0/GstSplitMuxSink:splitmuxsink0/GstQueue:queue_video: max-size-buffers = 14
/GstPipeline:pipeline0/GstSplitMuxSink:splitmuxsink0/GstQueue:queue_video: max-size-buffers = 15
/GstPipeline:pipeline0/GstSplitMuxSink:splitmuxsink0/GstQueue:queue_video: max-size-buffers = 16
/GstPipeline:pipeline0/GstSplitMuxSink:splitmuxsink0/GstQueue:queue_video: max-size-buffers = 17
/GstPipeline:pipeline0/GstSplitMuxSink:splitmuxsink0/GstQueue:queue_video: max-size-buffers = 18
/GstPipeline:pipeline0/GstSplitMuxSink:splitmuxsink0/GstQueue:queue_video: max-size-buffers = 19
/GstPipeline:pipeline0/GstSplitMuxSink:splitmuxsink0/GstQueue:queue_video: max-size-buffers = 20
/GstPipeline:pipeline0/GstSplitMuxSink:splitmuxsink0/GstQueue:queue_video: max-size-buffers = 21
/GstPipeline:pipeline0/GstSplitMuxSink:splitmuxsink0/GstQueue:queue_video: max-size-buffers = 22
/GstPipeline:pipeline0/GstSplitMuxSink:splitmuxsink0/GstQueue:queue_video: max-size-buffers = 23
/GstPipeline:pipeline0/GstSplitMuxSink:splitmuxsink0/GstQueue:queue_video: max-size-buffers = 24
/GstPipeline:pipeline0/GstSplitMuxSink:splitmuxsink0/GstQueue:queue_video: max-size-buffers = 25
/GstPipeline:pipeline0/GstSplitMuxSink:splitmuxsink0/GstQueue:queue_video: max-size-buffers = 26
Redistribute latency...
Got EOS from element "pipeline0".
Execution ended after 0:00:02.180310029
Setting pipeline to NULL ...
Freeing pipeline ...
My suspicion is that the pipeline is overwhelming splitmuxsink’s internal buffer queues. I would gladly learn about anything I’ve missed or done wrong.
Is this something that can be addressed with a proper C/C++ implementation?