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.