Please provide complete information as applicable to your setup.
• Hardware Platform (Jetson / GPU): both dGPU & Jetson
• DeepStream Version: Deepstream6.4 (dGPU) and Deepstream6.2 (Jetson)
• JetPack Version (valid for Jetson only): Jetpack 5.1.2
• TensorRT Version
• NVIDIA GPU Driver Version (valid for GPU only)
• Issue Type( questions, new requirements, bugs)
• How to reproduce the issue ? (This is for bugs. Including which sample app is using, the configuration files content, the command line used and other details for reproducing)
• Requirement details( This is for new requirement. Including the module name-for which plugin or for which sample application, the function description): Gstreamer version 1.20.3
Hi.
I’m developing a python-based deepstream pipeline to generate H265 encoded video with HLS container.
When I use the following code, it works well and the video is well generated.
original_width, original_height = py_.at(self.video_meta.resolution, 'width', 'height')
self.video_appsrc = Gst.ElementFactory.make("appsrc", "video_src")
self.video_appsrc.set_property("format", Gst.Format.TIME)
self.video_appsrc.set_property("is-live", True)
self.video_appsrc.set_property("max-bytes", 0)
video_src_caps = Gst.caps_from_string(f"video/x-raw(memory:NVMM),format=NV12,width={original_width},height={original_height},framerate={self.fps}/1")
self.video_appsrc.set_property("caps", video_src_caps)
self.pipeline.add(self.video_appsrc)
pre_encoder_queue = Gst.ElementFactory.make("queue")
pre_encoder_queue.set_property('max-size-buffers', 0)
pre_encoder_queue.set_property('max-size-bytes', 0)
pre_encoder_queue.set_property('max-size-time', 0)
self.pipeline.add(pre_encoder_queue)
encoder = Gst.ElementFactory.make("nvv4l2h265enc")
encoder.set_property("control-rate", 1) # constant bitrate
encoder.set_property('force-idr', True)
encoder.set_property("idrinterval", self.fps * self.segment_length)
encoder.set_property('force-intra', True)
encoder.set_property("iframeinterval", self.fps * self.segment_length)
encoder.set_property("bitrate", self.bit_rate)
encoder.set_property('vbvbufsize', self.bit_rate) # https://forums.developer.nvidia.com/t/random-blockiness-in-the-picture-rtsp-server-client-jetson-tx2/174896/5?u=kang12
encoder.set_property("preset-id", 2) # FastPreset
encoder.set_property("maxbitrate", int(self.bit_rate * self.max_bitrate_factor))
encoder.set_property("tuning-info-id", 1)
self.pipeline.add(encoder)
capsfilter = Gst.ElementFactory.make("capsfilter", "encoder_caps")
encoder_caps_string = Gst.Caps.from_string(f"video/x-h265, stream-format=(string)byte-stream,framerate={self.fps}/1")
capsfilter.set_property("caps", encoder_caps_string)
self.pipeline.add(capsfilter)
encoder_parse = Gst.ElementFactory.make("h265parse") # necessary to create hls ts files properly
encoder_parse.set_property('config-interval', -1) # Send SPS and PPS with every IDR frame
self.pipeline.add(encoder_parse)
self.mux = Gst.ElementFactory.make("hlssink", 'hlssink')
self.mux.set_property("location", f"{self.local_dir}/{self.segment_prefix}%05d.ts")
self.mux.set_property("playlist-location", f"{self.local_dir}/{self.segment_prefix}-temp.m3u8")
self.mux.set_property("target-duration", self.segment_length)
self.mux.set_property("max-files", 0)
self.mux.set_property("playlist-length", 0)
self.pipeline.add(self.mux)
self.video_appsrc.link(pre_encoder_queue)
pre_encoder_queue.link(encoder)
encoder.link(capsfilter)
capsfilter.link(encoder_parse)
encoder_parse.link(self.mux)
# I also have an audio stream and link it properly to the hlssink2's audio pad
However, the issue is that when I produce .ts segment based H265 HLS stream, then it’s not playable in Chrome or Safari browsers. I should use fragmented MP4 to make it playable in those browsers.
So I added this in between the h265parse
and hlssink2
element in the following way
self.mp4mux = Gst.ElementFactory.make("mp4mux")
self.mp4mux.set_property("fragment-duration", self.segment_length * 1000) # ms
self.pipeline.add(self.mp4mux)
#[...]
encoder_parse.link(self.mp4mux)
self.mp4mux.link(self.mux)
and changed a property of the hlssink
element in this way to generate .m4s file instead of .ts file
self.mux.set_property("location", f"{self.local_dir}/{self.segment_prefix}%05d.m4s")
So this is the full code including mp4mux
.
original_width, original_height = py_.at(self.video_meta.resolution, 'width', 'height')
self.video_appsrc = Gst.ElementFactory.make("appsrc", "video_src")
self.video_appsrc.set_property("format", Gst.Format.TIME)
self.video_appsrc.set_property("is-live", True)
self.video_appsrc.set_property("max-bytes", 0)
video_src_caps = Gst.caps_from_string(f"video/x-raw(memory:NVMM),format=NV12,width={original_width},height={original_height},framerate={self.fps}/1")
self.video_appsrc.set_property("caps", video_src_caps)
self.pipeline.add(self.video_appsrc)
pre_encoder_queue = Gst.ElementFactory.make("queue")
pre_encoder_queue.set_property('max-size-buffers', 0)
pre_encoder_queue.set_property('max-size-bytes', 0)
pre_encoder_queue.set_property('max-size-time', 0)
self.pipeline.add(pre_encoder_queue)
encoder = Gst.ElementFactory.make("nvv4l2h265enc")
encoder.set_property("control-rate", 1) # constant bitrate
encoder.set_property("profile", 2) # Main
encoder.set_property("idrinterval", self.fps * self.segment_length)
encoder.set_property("iframeinterval", self.fps * self.segment_length)
encoder.set_property("bitrate", self.bit_rate)
encoder.set_property('vbvbufsize', self.bit_rate) # https://forums.developer.nvidia.com/t/random-blockiness-in-the-picture-rtsp-server-client-jetson-tx2/174896/5?u=kang12
encoder.set_property("preset-id", 2) # FastPreset
encoder.set_property("maxbitrate", int(self.bit_rate * self.max_bitrate_factor))
encoder.set_property("tuning-info-id", 1)
self.pipeline.add(encoder)
capsfilter = Gst.ElementFactory.make("capsfilter", "encoder_caps")
encoder_caps_string = Gst.Caps.from_string(f"video/x-h265, stream-format=(string)byte-stream,framerate={self.fps}/1")
capsfilter.set_property("caps", encoder_caps_string)
self.pipeline.add(capsfilter)
encoder_parse = Gst.ElementFactory.make("h265parse") # necessary to create hls ts files properly
self.pipeline.add(encoder_parse)
self.mp4mux = Gst.ElementFactory.make("mp4mux")
self.mp4mux.set_property("fragment-duration", self.segment_length * 1000) # ms
self.pipeline.add(self.mp4mux)
self.mux = Gst.ElementFactory.make("hlssink", 'hlssink')
self.mux.set_property("send-keyframe-requests", False)
self.mux.set_property("location", f"{self.local_dir}/{self.segment_prefix}%05d.m4s")
self.mux.set_property("playlist-location", f"{self.local_dir}/{self.segment_prefix}-temp.m3u8")
self.mux.set_property("target-duration", self.segment_length)
self.mux.set_property("max-files", 0)
self.mux.set_property("playlist-length", 0)
self.pipeline.add(self.mux)
self.video_appsrc.link(pre_encoder_queue)
pre_encoder_queue.link(encoder)
encoder.link(capsfilter)
capsfilter.link(encoder_parse)
encoder_parse.link(self.mp4mux)
self.mp4mux.link(self.mux)
But when I add this mp4mux
element, the pipeline running, but the following errors are displayed and the video files are corrupted.
(python3:1065): GStreamer-CRITICAL **: 22:20:25.713: gst_segment_to_running_time: assertion 'segment->format == format' failed
0:00:34.316468895 1065 0x5cfd5451b640 INFO GST_ELEMENT_PADS gstelement.c:1016:gst_element_get_static_pad: found pad hlssink:sink
0:00:34.316521984 1065 0x5cfd5451b640 INFO hlssink gsthlssink.c:510:schedule_next_key_unit:<hlssink> sending upstream force-key-unit, index 1 now 99:99:99.999999999 target 0:00:14.999999999
0:00:34.316576682 1065 0x5cfd5451b640 INFO h265parse gsth265parse.c:3365:gst_h265_parse_src_event:<h265parse0> received upstream force-key-unit event, seqnum 2336 running_time 0:00:14.999999999 all_headers 1 count 1
0:00:34.316636099 1065 0x5cfd5451b640 ERROR hlssink gsthlssink.c:518:schedule_next_key_unit:<hlssink> Failed to push upstream force key unit event
Is there anything else I should amend the element options or configurations?
I’ve spent a lot of time debugging it but couldn’t make it done and become very desperate.
Really appreciate any helps in advance.