Playing N sequential videos as a single video in GStreamer

57 views Asked by At

I have n sequential videos. I want to play them back to back as one video. For example, when the first video ends, it will continue with the second video without interruption. My code is as follows, I give the number of videos as a parameter. After creating the pipeline gst_element_set_state(pipeline, GST_STATE_NULL); I am getting an error in the part.

If there is an example that will work via cmd, I can check it out. I couldn't find an example the way I wanted.

#include <gst/gst.h>

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

    // Set the number of videos (n)
    const int num_videos = 3;

    GstElement* pipeline = gst_pipeline_new("video_pipeline");

    for (int i = 0; i < num_videos; ++i) {
        gchar* filename;
        gchar* pad_name;
        GstElement* multifilesrc;
        GstElement* qtdemux;
        GstElement* h264parse;
        GstElement* avdec_h264;
        GstElement* videoconvert;
        GstElement* autovideosink;
        GstPad* sink_pad;
        GstPad* src_pad;

        // Generate the filename based on the naming convention (e.g., video0000.mp4)
        filename = g_strdup_printf("video%04d.mp4", i);
        pad_name = g_strdup_printf("sink_%d", i);

        // Create multifilesrc element for each video
        multifilesrc = gst_element_factory_make("multifilesrc", NULL);
        g_object_set(multifilesrc, "location", filename, NULL);

        // Create qtdemux, h264parse, avdec_h264, videoconvert, and autovideosink elements
        qtdemux = gst_element_factory_make("qtdemux", NULL);
        h264parse = gst_element_factory_make("h264parse", NULL);
        avdec_h264 = gst_element_factory_make("avdec_h264", NULL);
        videoconvert = gst_element_factory_make("videoconvert", NULL);
        autovideosink = gst_element_factory_make("autovideosink", NULL);

        // Add all elements to the pipeline
        gst_bin_add_many(GST_BIN(pipeline), multifilesrc, qtdemux, h264parse, avdec_h264, videoconvert, autovideosink, NULL);

        // Link the elements
        gst_element_link_many(multifilesrc, qtdemux, h264parse, avdec_h264, videoconvert, autovideosink, NULL);

        // Set up a pad to dynamically link each multifilesrc to the next element
        sink_pad = gst_element_get_static_pad(multifilesrc, "src");
        src_pad = gst_element_get_static_pad(qtdemux, "sink");
        gst_pad_link(sink_pad, src_pad);

        // Set the name of the sink pad dynamically
        gst_element_class_add_pad_template(GST_ELEMENT_GET_CLASS(pipeline),
            gst_static_pad_template_get(pad_name));
        gst_element_set_name(multifilesrc, pad_name);

        // Clean up
        g_free(filename);
        g_free(pad_name);
    }

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

    // Set up the main loop
    GMainLoop* loop = g_main_loop_new(NULL, FALSE);
    g_main_loop_run(loop);

    // Clean up
    gst_element_set_state(pipeline, GST_STATE_NULL);
    gst_object_unref(GST_OBJECT(pipeline));
    g_main_loop_unref(loop);

    return 0;
}
1

There are 1 answers

2
Akkshay On

You don't have to use for loop to play each video, instead you provide the file name pattern and set the index properties on multifilesrc and gstreamer will handle the increment for you.

For example

multifilesrc = gst_element_factory_make("multifilesrc", NULL);
g_object_set(multifilesrc, "location", "video%04d.mp4", "index", 0, "stop-index", 3, NULL);

GStreamer will use the pattern "video%04d.mp4" and index from 0 to stop-index (3) to generate file names video0000.mp4, video0001.mp4, video0002.mp4 etc, and play them sequentially.