Gstreamer Pipeline with CSI camera works fine with gst-launch-1.0, fails to link elements in C code

Hello,

I am trying to write a C application on my Jetson Orin Nano. The final application will utilize deepstream to perform inference on a CSI camera’s video feed, but for now I’m just trying to get the camera to work. I need my final video output to the model to have a resolution of 960x540, so I was hoping to use caps filters to size down and properly format my video. I have constructed the following gst-launch-1.0 command which works great.

gst-launch-1.0 nvarguscamerasrc sensor-id=0 ! "video/x-raw(memory:NVMM), width=(int)1920, height=(int)1080, format=(string)NV12, framerate=30/1" ! nvvidconv flip-method=2 ! "video/x-raw(memory:NVMM), width=(int)960, height=(int)540" ! nvvidconv ! queue ! autovideosink sync=false

However, when I tried to replicate this functionality in my C code, an error gets thrown when I try to link the camera source, caps, and first nvvidconv element. My C code is below.

#include <gst/gst.h>

int main(int argc, char *argv[]) {
    GstElement *pipeline, *source, *conv1, *conv2, *queue, *sink;
    GstCaps *caps1, *caps2;
    GstBus *bus;
    GstMessage *msg;
    GstStateChangeReturn ret;
    gchar *caps_str;

    /* Initialize GStreamer */
    gst_init(&argc, &argv);

    /* Create the elements */
    source = gst_element_factory_make("nvarguscamerasrc", "source");
    conv1 = gst_element_factory_make("nvvidconv", "conv1");
    conv2 = gst_element_factory_make("nvvidconv", "conv2");
    queue = gst_element_factory_make("queue", "queue");
    sink = gst_element_factory_make("autovideosink", "sink");

    /* Create the empty pipeline */
    pipeline = gst_pipeline_new("test-pipeline");

    if (!pipeline || !source || !conv1 || !conv2 || !queue || !sink) {
        g_printerr("Not all elements could be created.\n");
        return -1;
    }

    /* Configure nvarguscamerasrc */
    g_object_set(source, "sensor-id", 0, NULL);

    /* Configure caps for nvarguscamerasrc to nvvidconv */
    caps1 = gst_caps_new_simple("video/x-raw",
                                "memory", G_TYPE_STRING, "NVMM",
                                "width", G_TYPE_INT, 1920,
                                "height", G_TYPE_INT, 1080,
                                "format", G_TYPE_STRING, "NV12",
                                "framerate", GST_TYPE_FRACTION, 30, 1,
                                NULL);
    caps_str = gst_caps_to_string(caps1);
    g_print("Caps1: %s\n", caps_str);
    g_free(caps_str);

    /* Configure caps for nvvidconv to nvvidconv */
    caps2 = gst_caps_new_simple("video/x-raw",
                                "memory", G_TYPE_STRING, "NVMM",
                                "width", G_TYPE_INT, 960,
                                "height", G_TYPE_INT, 540,
                                NULL);
    caps_str = gst_caps_to_string(caps2);
    g_print("Caps2: %s\n", caps_str);
    g_free(caps_str);

    /* Set up the pipeline */
    gst_bin_add_many(GST_BIN(pipeline), source, conv1, conv2, queue, sink, NULL);
    g_object_set(conv1, "flip-method", 2, NULL);

    /* Link with caps filters */
    if (!gst_element_link_filtered(source, conv1, caps1)) {
        g_printerr("Failed to link source and conv1 with specified caps.\n");
        gst_caps_unref(caps1);
        gst_object_unref(pipeline);
        return -1;
    }
    gst_caps_unref(caps1);

    if (!gst_element_link_filtered(conv1, conv2, caps2)) {
        g_printerr("Failed to link conv1 and conv2 with specified caps.\n");
        gst_caps_unref(caps2);
        gst_object_unref(pipeline);
        return -1;
    }
    gst_caps_unref(caps2);

    /* Link the rest of the pipeline */
    if (!gst_element_link_many(conv2, queue, sink, NULL)) {
        g_printerr("Failed to link conv2, queue, and sink.\n");
        gst_object_unref(pipeline);
        return -1;
    }

    /* Start playing */
    ret = gst_element_set_state(pipeline, GST_STATE_PLAYING);
    if (ret == GST_STATE_CHANGE_FAILURE) {
        g_printerr("Unable to set the pipeline to the playing state.\n");
        gst_object_unref(pipeline);
        return -1;
    }

    /* Wait until error or EOS */
    bus = gst_element_get_bus(pipeline);
    msg = gst_bus_timed_pop_filtered(bus, GST_CLOCK_TIME_NONE, GST_MESSAGE_ERROR | GST_MESSAGE_EOS);

    /* Handle message */
    if (msg != NULL) {
        GError *err;
        gchar *debug_info;

        switch (GST_MESSAGE_TYPE(msg)) {
            case GST_MESSAGE_ERROR:
                gst_message_parse_error(msg, &err, &debug_info);
                g_printerr("Error received from element %s: %s\n", GST_OBJECT_NAME(msg->src), err->message);
                g_printerr("Debugging information: %s\n", debug_info ? debug_info : "none");
                g_clear_error(&err);
                g_free(debug_info);
                break;
            case GST_MESSAGE_EOS:
                g_print("End-Of-Stream reached.\n");
                break;
            default:
                g_printerr("Unexpected message received.\n");
                break;
        }
        gst_message_unref(msg);
    }

    /* Clean up */
    gst_object_unref(bus);
    gst_element_set_state(pipeline, GST_STATE_NULL);
    gst_object_unref(pipeline);
    return 0;
}

What am I doing wrong here? How can I get the caps to work correctly? For the record, if I completely remove the caps and just link the elements using gst_element_link() everything works fine.

You may reference to the nvgstcapture-1.0 for the problem.

Thanks

Shane,

What exactly am I supposed to be referencing regarding nvgstcapture-1.0? Is there documentation for the NVIDIA Gstreamer plugins? Does nvgstcapture-1.0 have an open source implementation somewhere that sets up an nvarguscamerasrc? If so, where in the codebase would it live?

This answer isn’t particularly helpful, I’m really not sure where to even start with that reply.

You can download the source code from the download center.
Below is the source for r32.7.5

https://developer.nvidia.com/downloads/embedded/l4t/r32_release_v7.5/sources/t210/public_sources.tbz2

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