Saving Raw H265 Files with splitmuxsink without MP4 Encapsulation

• Hardware Platform (Jetson / GPU) : NVIDIA Jetson AGX Orin
• DeepStream Version : 7.1
• JetPack Version (valid for Jetson only) : 6.1
• TensorRT Version : 8.6.2.3
• Issue Type( questions, new requirements, bugs) : question
Hello,

I have a pipeline that saves H.265 files every 60 frames:

...

# Create H265 queue element
h265_queue = create_pipeline_element(
    "queue", "h265-queue", "H265 Queue"
)

# Create H265 encoder element
h265_encoder = create_pipeline_element(
    "nvv4l2h265enc", "h265-encoder", "H265 Encoder"
)

# Create H265 parser element
h265_parser = create_pipeline_element(
   "h265parse", "h265-parser", "H265 Parser"
)

# Create H265 splitmuxsink element
h265_splitmuxsink = create_pipeline_element(
    "splitmuxsink", "h265-muxer", "H265 SplitMuxSink"
)
h265_splitmuxsink.set_property("location", temp%06d.hevc)

h265_splitmuxsink_sink_pad = h265_splitmuxsink.get_request_pad("video")
h265_splitmuxsink_sink_pad.add_probe(
    Gst.PadProbeType.BUFFER,
    h265_splitmuxsink_pad_probe_function,
    h265_pad_probe_data,
    h265_splitmuxsink,
)

def h265_splitmuxsink_pad_probe_function(
    pad: Gst.Pad, info: Gst.PadProbeInfo, data: dict, splitmuxsink: Gst.Element
) -> Gst.PadProbeReturn:
    """
    Pad probe function to count frames and trigger file save every 60 frames.
    """
    data["count"] += 1
    if data["count"] >= 60:
        # Reset frame counter
        data["count"] = 0

        # Trigger splitmuxsink to save file
        splitmuxsink.emit("split-now")
    return Gst.PadProbeReturn.OK

Recently, I discovered that splitmuxsink uses mp4mux internally, which encapsulates raw H265 files into an MP4 container. As a result, the files saved every 60 frames are not raw H265, which affects my later processing.

Question

How can I configure splitmuxsink to save raw H265 files without wrapping them in an MP4 container? I noticed the muxer-factory property defaults to mp4mux, but I’m unsure if it supports a raw H265 output as I could not find it in Splitmuxsink source code

If splitmuxsink doesn’t provide this option, is there an alternative approach to achieve the same result while ensuring files are saved every 60 frames?

It cannot directly save a raw H265 stream with the splitmuxsink . If you want to save the h265 stream, you will need to implement your own code logic in your sample code similar to the splitmuxsink plugin.

@yuweiw Thank you for your response! I’m looking for a plugin that can split the incoming video into 60-frame chunks while keeping the output in raw H265 format. I currently have h265parse before the muxer - would filesink or multifilesink be suitable for this, or is there another plugin that might work better? I do not want to stick with splitmuxsink if it does not support my logic, if there’s another plugin that fits my needs, I’d be happy to switch to it.

Yes. You can use filesink to save the h265 stream. The pipeline is like ......->h265parse->filesink location=test.h265. But you need to implement the logic of the split part code yourself. This step can be a bit complicated and you need to research the implementation.

@yuweiw Thank you for your reply!

Would it be possible to use filesink with a probe function to emit a signal or apply some splitting criteria? I was considering an approach like the one below, where a probe function on the H.265 pad counts frames and switches the output file every 60 frames.

Could this be a viable solution? Or is there a better approach?

def h265_pad_probe_function(pad: Gst.Pad, info: Gst.PadProbeInfo, data: dict) -> Gst.PadProbeReturn:
    """
    Pad probe function to count frames and trigger file change every 60 frames.
    """
    data["count"] += 1

    if data["count"] >= 60:  # Every 60 frames, change the file
        data["count"] = 0  # Reset counter

        # Generate a new filename based on timestamp
        new_filename = f"/path/to/output/h265_{int(time.time())}.h265"
        print(f"Switching to new file: {new_filename}")

        # Close current file and set new location
        filesink = data["filesink"]
        filesink.set_state(Gst.State.NULL)  # Stop writing to the old file
        filesink.set_property("location", new_filename)  # Update filename
        filesink.set_state(Gst.State.PLAYING)  # Start writing to the new file

    return Gst.PadProbeReturn.OK

Would appreciate any insights on whether this approach is feasible or if another method would be more suitable.

This might not work. You can refer to the Splitmuxsink source code. There are many Gstreamer messages, like eos, to be processed correctly.

I think you can consider the simple way by the multifilesink. Please tune the parameters of the plugin according to your requirements and see if it works. We don’t have much experience with your particular scenario either.

I have managed to use multifilesink. Here is the pipeline I wrote using GStreamer. Recreating it in DeepStream is just using those elements and setting properties.

gst-launch-1.0 -e nvarguscamerasrc sensor_id=0 sensor_mode=0 ! capsfilter caps="video/x-raw(memory:NVMM), width=3840, height=2160, framerate=60/1, format=NV12" ! queue ! nvv4l2h265enc iframeinterval=60 idrinterval=1 insert-sps-pps=true ! h265parse ! multifilesink location="frame%03d.h265" next-file="max-duration" max-file-duration=1000000000

It saves raw hevc/h265 files every 1 second.

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.