Shmsrc to jpegdec - cannot link elements with filter

Hello,

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 elements\n");
        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 elements\n");
        gst_object_unref(pipeline);
        return false;
    }

    status = link_elements_with_filter(shmSrc, jpegDec);
    if (!status) {
        g_printerr("Existing from createPipeline\n");
        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 elements\n");
  }
  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: %s\n", 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);
}

best regards,
Rz

Not sure, but maybe because you are trying to relink with filter already linked elements from your previous gst_element_link_many command.
I’d suggest to first link shmsrc and jpegdec with filter, then try link many without shmrsrc.

Note that you may also have to link jpegdec and videoconvert with filter, I’d suggest trying video/x-raw,format=I420,width=1280,height=720,framerate=30/1 so only use gst_element_link_many for videoconvert -> avimux -> filesink.

1 Like

This worked thank you !!