Jetson nano ,c++ ,Gstreamer,H265

Hi,
i use these plugins on ubuntu command line to save video on Jetson nano from MIPI camera and it generate test.mp4 successfully

gst-launch-1.0 nvarguscamerasrc ! 'video/x-raw(memory:NVMM), width=1024, height=720,format=NV12, framerate=30/1' ! omxh265enc ! qtmux ! filesink location=test.mp4 -e

but when i compile its equivalent code in c++ , test.mp4 generate and have acceptable file size but does not play by any player

#include <gst/gst.h>

int main(int argc, char *argv[]) {
    // Initialize GStreamer
    gst_init(&argc, &argv);

    // Create GStreamer pipeline elements
    GstElement *pipeline, *source, *encoder, *muxer, *sink;

    pipeline = gst_pipeline_new("my-pipeline");
    source = gst_element_factory_make("nvarguscamerasrc", "source");
    encoder = gst_element_factory_make("omxh265enc", "encoder");
    muxer = gst_element_factory_make("qtmux", "muxer");
    sink = gst_element_factory_make("filesink", "sink");

    // Check if all elements were created successfully
    if (!pipeline || !source || !encoder || !muxer || !sink) {
        g_error("Failed to create one or more pipeline elements");
        return -1;
    }

    // Set properties for the source element
    g_object_set(source, "! video/x-raw(memory:NVMM), width=1920, height=1080, format=NV12, framerate=30/1", NULL);

    // Set properties for the filesink element
    g_object_set(sink, "location", "test.mp4", NULL);

    // Add elements to the pipeline
    gst_bin_add_many(GST_BIN(pipeline), source, encoder, muxer, sink, NULL);

    // Link elements together
    if (!gst_element_link_many(source, encoder, muxer, sink, NULL)) {
        g_error("Failed to link one or more elements");
        gst_object_unref(pipeline);
        return -1;
    }

    // Set the pipeline to the playing state
    gst_element_set_state(pipeline, GST_STATE_PLAYING);

    // Wait until error or EOS (End of Stream)
    GstBus *bus = gst_element_get_bus(pipeline);
    GstMessage *msg = gst_bus_timed_pop_filtered(bus, GST_CLOCK_TIME_NONE, GST_MESSAGE_ERROR | GST_MESSAGE_EOS);

    // Parse and handle messages
    if (msg != NULL) {
        GError *err;
        gchar *debug_info;

        switch (GST_MESSAGE_TYPE(msg)) {
            case GST_MESSAGE_ERROR:
                gst_message_parse_error(msg, &err, &debug_info);
                g_error("Error received from element %s: %s", GST_OBJECT_NAME(msg->src), err->message);
                g_error("Debugging information: %s", debug_info ? debug_info : "none");
                g_clear_error(&err);
                g_free(debug_info);
                break;
            case GST_MESSAGE_EOS:
                g_print("End-Of-Stream reached.\n");
                
                // Manually send EOS event to the pipeline
                gst_element_send_event(pipeline, gst_event_new_eos());

                break;
            default:
                // Handle other messages
                break;
        }

        gst_message_unref(msg);
    }

    // Set the pipeline to the NULL state and release resources
    gst_element_set_state(pipeline, GST_STATE_NULL);
    gst_object_unref(pipeline);

    return 0;
}

i press Ctrl+C , to stop and it seems above program does not end properly and i have another question what can i do for suddenly ubuntu shut down to save video file properly ,
regards

With the MP4/QuickTime container you need to cleanly shutdown the pipeline, so that the muxer has a chance to write out a sample table with all the frames at the end. Without it, the file can’t be read, as you have discovered. Other formats such as Matroska or MPEG-TS are more robust towards this.

This section describes the mechanism: GstBaseSrc

Basically, you need to send an EOS event on the source element and/or top-level pipeline, and then it goes to the muxer and the muxer will write out the missing headers/tables, and then it goes to the filesink, and when everything has been written to disk the filesink will post an EOS message on the pipeline bus, and the application will get an EOS message.

In your code you send an EOS event after you have received an EOS message, but that doesn’t really make sense. You need to do it before you shut down (set state to NULL) the pipeline.

thank you for your fast reply
1.in qtmux, i dont really understand where should i use gst_element_send_event(pipeline, gst_event_new_eos()); would you please say me its place clearly?
2.in mpegtsmux, as you said its ok in suddenly close ubuntu terminal and test,mp4 is played by player ,but i have another problem when i use plugins in ubuntu command line i have test.mp4 file witout frame loss but in c++ code saved video seems to be slow motion and it seems i have frame loss how can i solved this problem?