Trying translate working gst-launch command to the API

Gary Metalle Gary.Metalle at rvl.co.uk
Tue Aug 25 08:07:01 UTC 2020


Hi

Sorry I think it's ok as it is with the tee because gst_element_link_many can request the src pads for you.

I had been reading the following article recently and remembered that they manually linked up the src pads for the tee so that they could be free'd up nicely at the end:

https://gstreamer.freedesktop.org/documentation/tutorials/basic/multithreading-and-pad-availability.html?gi-language=c

Maybe that example will have some other hints that are useful to you as the beginning of the pipeline is very similar to yours.

Also be prepared to trawl through a debug log after you've set "export GST_DEBUG=4" or "export GST_DEBUG=6" because it always has clues, just that it's difficult to find what you need. Lately I've found it easier to start at the end of the log and go backwards.
________________________________________
From: gstreamer-devel <gstreamer-devel-bounces at lists.freedesktop.org> on behalf of Kelly Wiles <rkwiles at twc.com>
Sent: 24 August 2020 20:31
To: gstreamer-devel at lists.freedesktop.org
Subject: Re: Trying translate working gst-launch command to the API

Hi

The code

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;
          }


Gives no errors and I think that the code above was linking the tee to
src and other elements.

I may not be understanding what you are talking about, sorry.

Thanks

On 8/24/2020 11:46 AM, Gary Metalle wrote:
> Hi
>
> 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 lists.freedesktop.org> on behalf of Kelly Wiles <rkwiles at twc.com>
> 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
> extra-controls="controls,h264_profile=4,h264_level=10,video_bitrate=500000;"
> ! h264parse !
> // filesink location=foo1.h264 t. ! queue !
> // v4l2h264enc
> extra-controls="controls,h264_profile=4,h264_level=10,video_bitrate=2000000;"
> ! 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
> elements\npip=%p\nsrc=%p\ntee=%p\nenc1=%p\nenc2=%p\nf1=%p\nf2=%p\nh1=%p\nh2=%p\nq1=%p\nq2=%p",
>                                   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,
>                           NULL);
>           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,
>                           NULL);
>           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,
>                  NULL);
>           g_object_set (G_OBJECT (src), "extra-controls", srcOpts, NULL);
>
>           // GST_DEBUG_BIN_TO_DOT_FILE(GST_BIN(app.pipeline),
> GST_DEBUG_GRAPH_SHOW_ALL, "pipeline");
>
>           gst_element_set_state (app.pipeline, GST_STATE_PLAYING);
>
> #if(0)
>           if (gst_element_get_state (app.pipeline, NULL, NULL, -1) ==
> GST_STATE_CHANGE_FAILURE) {
>                   g_error ("Failed to go into PLAYING state");
>           }
>
>           g_print ("Running ...\n");
>           g_main_loop_run (app.loop);
> #endif
>
>           bus = gst_element_get_bus (app.pipeline);
>           msg = gst_bus_timed_pop_filtered (bus, GST_CLOCK_TIME_NONE,
> GST_MESSAGE_ERROR | GST_MESSAGE_EOS);
>
>           /* 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);
>                           break;
>                   case GST_MESSAGE_EOS:
>                           g_print ("End-Of-Stream reached.\n");
>                           break;
>                   default:
>                           /* We should not reach here because we only
> asked for ERRORs and EOS */
>                           g_printerr ("Unexpected message received.\n");
>                           break;
>                   }
>                   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.
>
> Thanks
>
>
>
>
> --
> This email has been checked for viruses by AVG.
> https://www.avg.com
> _______________________________________________
> gstreamer-devel mailing list
> gstreamer-devel at lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/gstreamer-devel

--
This email has been checked for viruses by AVG.
https://www.avg.com

_______________________________________________
gstreamer-devel mailing list
gstreamer-devel at lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/gstreamer-devel


More information about the gstreamer-devel mailing list