C - Cannot initialize pipeline with tee and queue for video and image encode
simo zz
simon.zz at yahoo.com
Thu Aug 31 16:53:47 UTC 2017
Solved !
This is the correct pipeline:
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 ! videoconvert ! pngenc ! multifilesink location=file%6d.png
Simon
El Jueves 31 de agosto de 2017 18:23, simo zz <simon.zz at yahoo.com> escribió:
There is an error in the return of the function buildPipeline. Should return true and of course not 0.
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 true;
}
Simon
El Jueves 31 de agosto de 2017 17:30, simo zz <simon.zz at yahoo.com> escribió:
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/b2619784/attachment-0001.html>
More information about the gstreamer-devel
mailing list