C - Cannot initialize pipeline with tee and queue for video and image encode

simo zz simon.zz at yahoo.com
Thu Aug 31 15:30:04 UTC 2017


Hello,
I need to implement the following pipeline (successfully tested with gst-launch-1.0 -e) using C API:

v4l2src device=/dev/webcam ! videoconvert ! video/x-raw,width=544,height=288,framerate=10/1 ! tee name=t ! queue ! v4l2h264enc ! h264parse ! mp4mux ! filesink location=video.mp4 t. ! queue ! decodebin ! videoconvert ! pngenc ! multifilesink location=file%6d.png
The C code used for GstElements declaration and pipeline initialization is the following:
typedef struct _CustomData
{
    GstElement *pipeline;
    GstElement *v4l2src;
        
    GstElement *tee;
    // connect this pad to v4lserc
    GstPadTemplate *teepadtmplate;
    
    // tee src pads
    GstPad *teeSrcVPad;
    GstPad *teeSrcIPad;

    // queues sink pads
    GstPad *vQueueSinkPad;
    GstPad *iQueueSinkPad;

    GstElement *vQueue;
    GstElement *iQueue;

    GstElement *decodebin;
    GstElement *pngenc;

    GstElement *vVideoconvert;
    GstElement *iVideoconvert;

    GstElement *capsfilter;
    GstCaps *caps;
    GstElement *v4l2h264enc;
    GstElement *h264parse;
    GstElement *mp4mux;
    GstElement *filesink;
    GstElement *multifilesink;
    GstBuffer *buffer;

} GstData;


gboolean buildPipeline(GstData *gstData, const char *filename)
{
    gstData->pipeline = gst_pipeline_new ("pipeline");
    if (! gstData->pipeline)
    {
        printf("Error creating pipeline.\n");
        return false;
    }
    
    gstData->v4l2src = gst_element_factory_make("v4l2src", NULL);
    if (! gstData->v4l2src)
    {
        printf("Error creating v4l2src.\n");
        return false;
    }

    gstData->tee = gst_element_factory_make("tee", "tee");
    if (! gstData->tee)
    {
        printf("Error creating tee.\n");
        return false;
    }

    gstData->vQueue = gst_element_factory_make("queue", NULL);
    if (! gstData->vQueue)
    {
        printf("Error creating video queue.\n");
        return false;
    }

    gstData->iQueue = gst_element_factory_make("queue", NULL);
    if (! gstData->iQueue)
    {
        printf("Error creating image queue.\n");
        return false;
    }

    gstData->decodebin = gst_element_factory_make("decodebin", NULL);
    if (! gstData->decodebin)
    {
        printf("Error creating decodebin.\n");
        return false;
    }

    gstData->pngenc = gst_element_factory_make("pngenc", NULL);
    if (! gstData->pngenc)
    {
        printf("Error creating pngenc.\n");
        return false;
    }

    gstData->iVideoconvert = gst_element_factory_make("videoconvert", NULL);
    if (! gstData->iVideoconvert)
    {
        printf("Error creating iVideoconvert.\n");
        return false;
    }

    gstData->vVideoconvert = gst_element_factory_make("videoconvert", NULL);
    if (! gstData->vVideoconvert)
    {
        printf("Error creating vVideoconvert.\n");
        return false;
    }

    gstData->capsfilter = gst_element_factory_make("capsfilter", NULL);
    if (! gstData->capsfilter)
    {
        printf("Error creating capsfilter.\n");
        return false;
    }

    gstData->v4l2h264enc = gst_element_factory_make("v4l2h264enc", NULL);
    if (! gstData->v4l2h264enc)
    {
        printf("Error creating v4l2h264enc.\n");
        return false;
    }

    gstData->h264parse = gst_element_factory_make("h264parse", NULL);
    if (! gstData->h264parse)
    {
        printf("Error creating h264parse.\n");
        return false;
    }

    gstData->mp4mux = gst_element_factory_make("mp4mux", NULL);
    if (! gstData->mp4mux)
    {
        printf("Error creating mp4mux.\n");
        return false;
    }

    gstData->filesink = gst_element_factory_make("filesink", NULL);
    if (! gstData->filesink)
    {
        printf("Error creating filesink.\n");
        return false;
    }

    gstData->multifilesink = gst_element_factory_make("multifilesink", NULL);
    if (! gstData->multifilesink)
    {
        printf("Error creating multifilesink.\n");
        return false;
    }

    g_object_set(G_OBJECT(gstData->v4l2src), "device", filename, NULL);
    g_object_set(G_OBJECT(gstData->filesink), "location", "video.mp4", NULL);
    g_object_set(G_OBJECT(gstData->multifilesink), "location", "file%6u.png", NULL);

    gstData->caps = gst_caps_from_string(CAPS_STR);
    g_object_set(G_OBJECT(gstData->capsfilter), "caps", gstData->caps, NULL);

    gst_bin_add_many(GST_BIN(gstData->pipeline), gstData->v4l2src, gstData->tee, gstData->vQueue, gstData->iQueue, gstData->iVideoconvert, gstData->vVideoconvert, gstData->decodebin, gstData->pngenc, gstData->capsfilter, gstData->v4l2h264enc, gstData->h264parse, gstData->mp4mux, gstData->filesink, gstData->multifilesink, NULL);

    if(gst_element_link_many(gstData->v4l2src, gstData->vVideoconvert, gstData->capsfilter, gstData->tee, NULL) != true)
    {
        g_print("Error linking pipeline: v4l2src ! videoconvert ! capsfilter ! tee ...\n");
        return false;
    }

    if(gst_element_link_many(gstData->vQueue, gstData->v4l2h264enc, gstData->h264parse, gstData->mp4mux, gstData->filesink, NULL) != true)
    {
        g_print("Error linking pipeline: queue ! v4l2h264enc ! h264parse ! mp4mux ! filesink ...\n");
        return false;
    }

    // Program fails here
    if(gst_element_link_many(gstData->iQueue, gstData->decodebin, gstData->iVideoconvert, gstData->pngenc, gstData->multifilesink, NULL) != true)
    {
        g_print("Error linking pipeline: queue ! decodebin ! videoconvert ! pngenc ! multifilesink ...\n");
        return false;
    }

    // manually link pads
    gstData->teepadtmplate = gst_element_class_get_pad_template(GST_ELEMENT_GET_CLASS (gstData->tee), "src_%u");
    if (! gstData->teepadtmplate)
    {
        g_print("Error setting tee pad template...\n");
        return false;
    }
    
    gstData->teeSrcVPad = gst_element_request_pad(gstData->tee, gstData->teepadtmplate, NULL, NULL);
    if(! gstData->teeSrcVPad)
    {
        g_print("Error setting tee video src pad...\n");
        return false;
    }

    gstData->vQueueSinkPad = gst_element_get_static_pad(gstData->vQueue, "sink");
    if(! gstData->vQueueSinkPad)
    {
        g_print("Error setting tee video sink pad...\n");
        return false;
    }

    gstData->teeSrcIPad = gst_element_request_pad(gstData->tee, gstData->teepadtmplate, NULL, NULL);
    if(! gstData->teeSrcIPad)
    {
        g_print("Error setting tee image src pad...\n");
        return false;
    }
    gstData->iQueueSinkPad = gst_element_get_static_pad (gstData->iQueue, "sink");
    if(! gstData->iQueueSinkPad)
    {
        g_print("Error setting queue image sink pad...\n");
        return false;
    }

    if (gst_pad_link(gstData->teeSrcVPad, gstData->vQueueSinkPad) != GST_PAD_LINK_OK)
    {
        g_print("Error: cannot connect tee to video queue...\n");
        return false;
    }

    if (gst_pad_link(gstData->teeSrcIPad, gstData->iQueueSinkPad) != GST_PAD_LINK_OK)
    {
        g_print("Error: cannot connect tee to appsink queue...\n");
        return false;
    }
    
    return 0;
}
This code is inspired from the tutorial
 https://gstreamer.freedesktop.org/documentation/tutorials/basic/short-cutting-the-pipeline.html

But I cannot understand why it fails. What's wrong with it ?
Thank you in advance for your help.Simon
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.freedesktop.org/archives/gstreamer-devel/attachments/20170831/a65cae7b/attachment-0001.html>


More information about the gstreamer-devel mailing list