Trying translate working gst-launch command to the API

Gary Metalle Gary.Metalle at
Mon Aug 24 16:46:01 UTC 2020


I don't think you can just use the 'tee' and expect it to work without a bit more work. It has src pads created as when you need them so you'd have to hook into pad_created and link up your src and encoder from there.

Are you not getting errors from the calls to gst_element_link_many?
From: gstreamer-devel <gstreamer-devel-bounces at> on behalf of Kelly Wiles <rkwiles at>
Sent: 24 August 2020 15:03
To: Matthew Waters; Discussion of the development of and with GStreamer
Subject: Re: Trying translate working gst-launch command to the API

Ok, so i fixed the crash and now getting error

     Maybe be due to not enough memory or failing driver

The code:

#include <gst/gst.h>
#include <stdio.h>

// gst-launch-1.0 -e -v v4l2src !
'video/x-raw,width=1280,height=720,framerate=30/1,format=UYVY' ! tee
name=t !
// queue ! v4l2h264enc
! h264parse !
// filesink location=foo1.h264 t. ! queue !
// v4l2h264enc
! h264parse !
// filesink location=foo2.h264

typedef struct _App {
         GstElement *pipeline;
         GstElement *appsrc;

         GMainLoop *loop;
         guint sourceid;

         GTimer *timer;
} App;

App app;

gint main(gint argc, gchar *argv[]) {

         GstBus *bus;
         GstMessage *msg;
         GstElement *src, *tee, *enc1, *enc2, *f1, *f2, *h1, *h2, *q1, *q2;
         GstStructure *srcOpts;
         GstStructure *encOpts;

         gst_init(&argc, &argv);

         app.loop = g_main_loop_new(NULL, FALSE);

         app.pipeline = gst_pipeline_new("my-pipeline");

         src = gst_element_factory_make("v4l2src", "src");
         tee = gst_element_factory_make("tee", "tee");
         h1 = gst_element_factory_make("h264parse", "h1");
         h2 = gst_element_factory_make("h264parse", "h2");
         q1 = gst_element_factory_make("queue", "q1");
         q2 = gst_element_factory_make("queue", "q2");
         enc1 = gst_element_factory_make("v4l2h264enc", "enc1");
         enc2 = gst_element_factory_make("v4l2h264enc", "enc2");
         f1 = gst_element_factory_make("filesink", "f1");
         f2 = gst_element_factory_make("filesink", "f2");

         if (!app.pipeline || !src || !tee || !enc1 || !enc2 || !f1 ||
!f2 || !h1 || !h2 || !q1 || !q2) {
                 g_error ("Could not create
                                 app.pipeline, src, tee, enc1, enc2, f1,
f2, h1, h2, q1, q2);
                 return -1;

         g_object_set(f1, "location", "foo1.h264", NULL);
         g_object_set(f2, "location", "foo2.h264", NULL);

         encOpts = gst_structure_new ("controls",
                         "h264_profile", G_TYPE_INT, 4,
                         "h264_level", G_TYPE_INT, 10,
                         "video_bitrate", G_TYPE_INT, 500000,
         g_object_set (G_OBJECT (enc1), "extra-controls", encOpts, NULL);

         encOpts = gst_structure_new ("controls",
                         "h264_profile", G_TYPE_INT, 4,
                         "h264_level", G_TYPE_INT, 10,
                         "video_bitrate", G_TYPE_INT, 200000,
         g_object_set (G_OBJECT (enc2), "extra-controls", encOpts, NULL);

         gst_bin_add_many(GST_BIN(app.pipeline), src, tee, q1, enc1, h1,
f1, q2, enc2, h2, f2, NULL);

         if (!gst_element_link_many(src, tee, NULL)
                 || !gst_element_link_many(tee, q1, enc1, h1, f1, NULL)
                 || !gst_element_link_many(tee, q2, enc2, h2, f2, NULL)) {
                 g_error("Failed to link elements ...");
                 return -2;

         srcOpts = gst_structure_new ("video/x-raw",
                "format", G_TYPE_STRING, "UYVY",
                "width", G_TYPE_INT, 1280,
                "height", G_TYPE_INT, 720,
                "framerate", GST_TYPE_FRACTION, 30, 1,
         g_object_set (G_OBJECT (src), "extra-controls", srcOpts, NULL);

         // GST_DEBUG_BIN_TO_DOT_FILE(GST_BIN(app.pipeline),

         gst_element_set_state (app.pipeline, GST_STATE_PLAYING);

         if (gst_element_get_state (app.pipeline, NULL, NULL, -1) ==
                 g_error ("Failed to go into PLAYING state");

         g_print ("Running ...\n");
         g_main_loop_run (app.loop);

         bus = gst_element_get_bus (app.pipeline);
         msg = gst_bus_timed_pop_filtered (bus, GST_CLOCK_TIME_NONE,

         /* exit */
         /* Free resources */
         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);
                 case GST_MESSAGE_EOS:
                         g_print ("End-Of-Stream reached.\n");
                         /* We should not reach here because we only
asked for ERRORs and EOS */
                         g_printerr ("Unexpected message received.\n");
                 gst_message_unref (msg);
         gst_object_unref (bus);
         gst_element_set_state (app.pipeline, GST_STATE_NULL);
         gst_object_unref (app.pipeline);

         return 0;

This works through the command line so I guess i am missing something
else in the code.  Just do not understand why it works as a command line
but not as an API.

I enabled the pipeline graph dot files for both the gst-launch-1.0 and
my program and they appear to be alike, see attached of my program graph.

The graph was created by un-commenting the GST_DEBUG_BIN_TO_DOT_FILE line.

I have read most of the tutorials but feel lost if i try anything new
that the docs did not cover.


This email has been checked for viruses by AVG.

More information about the gstreamer-devel mailing list