Frame read from appsink and push it to appsrc doesn't work

Hi,
I’m trying to build an application that reads frames from a gstreamer pipeline with appsink and pushes them to another pipeline with appsrc. It looks straightforward but I couldn’t make it work and couldn’t find any reason. The thing that I’m trying to do here is I want to save videos from the camera with a certain amount of frames. Eventually, I will update the output pipeline with a different name a couple of times so that I have sequential videos with the same frame number such as video_0.mp4, video_1.mp4, video_2.mp4. The splitmuxsink plugin doesn’t work on our use case since its videos always have different frame numbers and if I change the iframeinterval, the duration of the videos is not desired.
Here is my example main.cpp file if we make it work I can do further modifications:
Thank you all in advance!

#include <stdint.h>
#include <gst/gst.h>
#include <gst/app/gstappsrc.h>
#include <gst/app/gstappsink.h>


static GMainLoop *main_loop;

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

    GError *error = nullptr;

    GstElement *pipeline1 = gst_parse_launch("nvarguscamerasrc ! video/x-raw(memory:NVMM), width=3840, height=2160, framerate=30/1, format=NV12 ! nvvidconv ! videoconvert ! video/x-raw, format=RGBA ! queue ! appsink name=appsink", &error);
    GstElement *appsink = gst_bin_get_by_name(GST_BIN(pipeline1), "appsink");

    if (pipeline1 == nullptr)
    {
        g_print("Failed to parse launch: %s\n", error->message);
        return -1;
    }
    if (error)
        g_error_free(error);

    // Create the second pipeline to encode frames from appsrc and save them to a file
    GstElement *pipeline2 = gst_parse_launch("appsrc name=appsrc ! videoconvert ! video/x-raw, format=I420 ! nvvidconv ! video/x-raw(memory:NVMM), format=NV12 ! nvv4l2h264enc maxperf-enable=1 ! h264parse ! qtmux ! filesink location=output.mp4", &error);
    GstElement *appsrc = gst_bin_get_by_name(GST_BIN(pipeline2), "appsrc");

    if (pipeline2 == nullptr)
    {
        g_print("Failed to parse launch: %s\n", error->message);
        return -1;
    }
    if (error)
        g_error_free(error);

    main_loop = g_main_loop_new(NULL, FALSE);

    gst_element_set_state(pipeline1, GST_STATE_PLAYING);
    gst_element_set_state(pipeline2, GST_STATE_PLAYING);

    uint32_t frame_id = 0;
    GstFlowReturn ret;

    while (true)
    {
        GstSample *sample = gst_app_sink_pull_sample(GST_APP_SINK(appsink));
        if (sample)
        {
            GstBuffer *buffer = gst_sample_get_buffer(sample);

            ret = gst_app_src_push_buffer(GST_APP_SRC(appsrc), gst_buffer_ref(buffer));
            g_print("ret: %d, frame_id: %d, buffer_size: %lu\n", ret, frame_id, gst_buffer_get_size(buffer));
            gst_sample_unref(sample);
        }
        frame_id++;
        if (frame_id >= 100)
            break;
    }

    // Cleanup
    gst_element_set_state(pipeline1, GST_STATE_NULL);
    gst_element_set_state(pipeline2, GST_STATE_NULL);

    return 0;
}

PS: If I run this code, memory usage increases very fast, and it crashes at some point. If I comment the line of gst_app_src_push_buffer out, it doesn’t happen so it looks like the error is in the second pipeline.
PS2: NVENC is off during the program so the second pipeline cannot carry the buffers until nvv4l2h264enc element.

Hi,
Please refer to this sample:
Starvation (?) of gstreamer threads - #12 by DaneLLL

If you see memory increase, it is very likely the functions are are called:

gst_buffer_unref(buffer);

or

gst_sample_unref (sample);

I changed this part and it worked:

    while (true)
    {
        GstSample *sample = gst_app_sink_pull_sample(GST_APP_SINK(appsink));
        if (sample)
        {
            ret = gst_app_src_push_sample(GST_APP_SRC(appsrc),  sample);
            gst_sample_unref(sample);
        }
        frame_id++;
        if (frame_id >= 100)
            break;
    }
1 Like

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