I am building an app that can stream my webcam to a shared memory using shmsink plugin, and elsewhere get it using shmsrc and registering it to a file.
The following works perfectly :
Creating the shm source: gst-launch-1.0 v4l2src device=“/dev/video0” ! image/jpeg,width=1280,height=720,framerate=30/1 ! queue ! shmsink socket-path=/dev/shm/shm_test1
Getting the shared memory and registering it to a file:
gst-launch-1.0 -e shmsrc socket-path=/dev/shm/shm_test1 ! “image/jpeg,width=1280,height=720,framerate=30/1” ! jpegdec ! videoconvert ! “video/x-raw,format=I420” ! avimux ! filesink location=./test.avi
Now I wanted to turn that into actual code. I managed to create a class to stream the shared memory. But I am not able to do the second part, using it and recording it. This is the code that keeps failing :
bool Recorder::createPipeline() {
gboolean status;
shmSrc = gst_element_factory_make("shmsrc", "shm_source");
jpegDec = gst_element_factory_make("jpegdec", "jpeg_decoder");
videoConvert = gst_element_factory_make("videoconvert", "video_converter");
aviMux = gst_element_factory_make("avimux", "avi_muxer");
filesink = gst_element_factory_make("filesink", "file_sink");
if (!shmSrc || !jpegDec || !videoConvert || !aviMux || !filesink) {
g_printerr("Failed to create elementsn");
return false;
}
g_object_set(shmSrc, "socket-path", shm_name.c_str(), NULL);
g_object_set(filesink, "location", output_file.c_str(), NULL);
GstCaps *caps = gst_caps_from_string("image/jpeg,width=1280,height=720,framerate=30/1");
pipeline = gst_pipeline_new("recorder_pipeline");
gst_bin_add_many(GST_BIN(pipeline), shmSrc, jpegDec, videoConvert, aviMux, filesink, NULL);
if (!gst_element_link_many(shmSrc, jpegDec, videoConvert, aviMux, filesink, NULL)) {
g_printerr("Failed to link elementsn");
gst_object_unref(pipeline);
return false;
}
status = link_elements_with_filter(shmSrc, jpegDec);
if (!status) {
g_printerr("Existing from createPipelinen");
gst_caps_unref(caps);
gst_object_unref(pipeline);
return false;
}
gst_caps_unref(caps);
return true;
}
gboolean Recorder::link_elements_with_filter(GstElement* element1, GstElement* element2) {
gboolean link_ok;
GstCaps* caps;
caps = gst_caps_from_string("image/jpeg,width=1280,height=720,framerate=30/1");
link_ok = gst_element_link_filtered(element1, element2, caps);
gst_caps_unref(caps);
if (!link_ok) {
g_printerr("Failed to link elementsn");
}
return link_ok;
}
Specifically, it is the link elements with filter that keeps failing and I dont understand why. Any help would be appreciated !
EDIT1: Fixed code formatting.
EDIT2: I managed to make it work using gst_parse_launch() but I don’t understand why I can’t link a capsfilter…
bool Recorder::createPipeline() {
std::string pipeline_description = "shmsrc socket-path=" + shm_name +
" ! image/jpeg,width=1280,height=720,framerate=30/1 ! jpegdec ! videoconvert ! avimux ! filesink location=" + output_file;
GError *error = nullptr;
pipeline = gst_parse_launch(pipeline_description.c_str(), &error);
if (!pipeline) {
g_printerr("Failed to create pipeline: %sn", error->message);
g_error_free(error);
return false;
}
bus = gst_element_get_bus(pipeline);
return true;
}
void Recorder::start() {
running = true;
gst_element_set_state(pipeline, GST_STATE_PLAYING);
bus_watch_thread = std::thread(&Recorder::bus_watch_thread_func, this);
}
Why does the capsfilter linking fails using dynamic pipelining but not when using gst_parse_launch() static pipeline ?
1