Trying translate working gst-launch command to the API

classic Classic list List threaded Threaded
9 messages Options
Reply | Threaded
Open this post in threaded view
|

Trying translate working gst-launch command to the API

Kelly Wiles
I am getting a segment fault when I try and convert the following, which
works into the C API.

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

I run the v4l2-ctl commands before executing the gst command.

v4l2-ctl --set-edid=file=edid5.txt --fix-edid-checksums
v4l2-ctl -v pixelformat=UYVY
v4l2-ctl --set-dv-bt-timings query

The edid5.txt is.

00,FF,FF,FF,FF,FF,FF,00,52,62,88,88,00,88,88,88,1C,15,01,03,80,00,00,78,0A,EE,91,A3,54,4C,99,26,0F,50,54,00,00,00,01,01,01,01,01,0
1,01,01,01,01,01,01,01,01,01,01,01,1D,00,72,51,D0,1E,20,6E,28,55,00,C4,8E,21,00,00,1E,8C,0A,D0,8A,20,E0,2D,10,10,3E,96,00,13,8E,21
,00,00,1E,00,00,00,FC,00,54,6F,73,68,69,62,61,2D,48,32,43,0A,20,00,00,00,FD,00,3B,3D,0F,2E,0F,00,0A,20,20,20,20,20,20,01,6D,02,03,
21,41,4D,84,13,03,02,12,11,01,20,21,22,3C,3D,3E,23,09,07,07,66,03,0C,00,30,00,80,E3,00,7F,8C,8C,0A,D0,8A,20,E0,2D,10,10,3E,96,00,C
4,8E,21,00,00,18,8C,0A,D0,8A,20,E0,2D,10,10,3E,96,00,13,8E,21,00,00,18,8C,0A,A0,14,51,F0,16,00,26,7C,43,00,13,8E,21,00,00,98,00,00
,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,BE

When I run this code it crashes with a segment fault on the g_object_set
function.

#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[]) {

         GstElement *src, *split, *enc1, *enc2, *f1, *f2, *h1, *h2, *q1,
*q2;
         GstCaps *filtercaps;
         GstCaps *enccaps;

         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");
         split = gst_element_factory_make("tee", "split");
         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 || !split || !enc1 || !enc2 || !f1 ||
!f2 || !h1 || !h2 || !q1 || !q2) {
                 g_error ("Could not create
elements\npip=%p\nsrc=%p\nsplit=%p\nenc1=%p\nenc2=%p\nf1=%p\nf2=%p\nh1=%p\nh2=%p\nq1=%p\nq2=%p",
                                 app.pipeline, src, split, 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);

         fprintf(stderr, "Here 1\n");
         // g_object_set(enc1, "extra-controls",
"controls,h264_profile=4,h264_level=10,video_bitrate=500000;", NULL);
         enccaps = gst_caps_new_simple ("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", enccaps, NULL);
         fprintf(stderr, "Here 2\n");
         g_object_set(enc2, "extra-controls",
"controls,h264_profile=4,h264_level=10,video_bitrate=2000000;", NULL);
         fprintf(stderr, "Here 3\n");

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

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

         filtercaps = gst_caps_new_simple ("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), "caps", filtercaps, NULL);
         gst_caps_unref (filtercaps);

         gst_element_set_state (app.pipeline, GST_STATE_PLAYING);

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

         /* exit */
         gst_element_set_state (app.pipeline, GST_STATE_NULL);
         gst_object_unref (app.pipeline);

         return 0;
}

The 'Here 1' prints then it dies, can any one help me to understand why?

Either method of calling g_object_set fails the same way.

Thanks



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

_______________________________________________
gstreamer-devel mailing list
[hidden email]
https://lists.freedesktop.org/mailman/listinfo/gstreamer-devel
Reply | Threaded
Open this post in threaded view
|

Re: Trying translate working gst-launch command to the API

Matthew Waters
On 24/8/20 5:12 am, Kelly Wiles wrote:

> I am getting a segment fault when I try and convert the following,
> which works into the C API.
>
> 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
>
> I run the v4l2-ctl commands before executing the gst command.
>
> v4l2-ctl --set-edid=file=edid5.txt --fix-edid-checksums
> v4l2-ctl -v pixelformat=UYVY
> v4l2-ctl --set-dv-bt-timings query
>
> The edid5.txt is.
>
> 00,FF,FF,FF,FF,FF,FF,00,52,62,88,88,00,88,88,88,1C,15,01,03,80,00,00,78,0A,EE,91,A3,54,4C,99,26,0F,50,54,00,00,00,01,01,01,01,01,0
>
> 1,01,01,01,01,01,01,01,01,01,01,01,1D,00,72,51,D0,1E,20,6E,28,55,00,C4,8E,21,00,00,1E,8C,0A,D0,8A,20,E0,2D,10,10,3E,96,00,13,8E,21
>
> ,00,00,1E,00,00,00,FC,00,54,6F,73,68,69,62,61,2D,48,32,43,0A,20,00,00,00,FD,00,3B,3D,0F,2E,0F,00,0A,20,20,20,20,20,20,01,6D,02,03,
>
> 21,41,4D,84,13,03,02,12,11,01,20,21,22,3C,3D,3E,23,09,07,07,66,03,0C,00,30,00,80,E3,00,7F,8C,8C,0A,D0,8A,20,E0,2D,10,10,3E,96,00,C
>
> 4,8E,21,00,00,18,8C,0A,D0,8A,20,E0,2D,10,10,3E,96,00,13,8E,21,00,00,18,8C,0A,A0,14,51,F0,16,00,26,7C,43,00,13,8E,21,00,00,98,00,00
>
> ,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,BE
>
>
> When I run this code it crashes with a segment fault on the
> g_object_set function.
>
> #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[]) {
>
>         GstElement *src, *split, *enc1, *enc2, *f1, *f2, *h1, *h2,
> *q1, *q2;
>         GstCaps *filtercaps;
>         GstCaps *enccaps;
>
>         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");
>         split = gst_element_factory_make("tee", "split");
>         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 || !split || !enc1 || !enc2 || !f1
> || !f2 || !h1 || !h2 || !q1 || !q2) {
>                 g_error ("Could not create
> elements\npip=%p\nsrc=%p\nsplit=%p\nenc1=%p\nenc2=%p\nf1=%p\nf2=%p\nh1=%p\nh2=%p\nq1=%p\nq2=%p",
>                                 app.pipeline, src, split, 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);
>
>         fprintf(stderr, "Here 1\n");
>         // g_object_set(enc1, "extra-controls",
> "controls,h264_profile=4,h264_level=10,video_bitrate=500000;", NULL);
>         enccaps = gst_caps_new_simple ("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", enccaps, NULL);
I assume here is the crash?

extra-controls requires a GstStructure, not a GstCaps.

Replace gst_caps_new_simple() with gst_structure_new() (and types).

>         fprintf(stderr, "Here 2\n");
>         g_object_set(enc2, "extra-controls",
> "controls,h264_profile=4,h264_level=10,video_bitrate=2000000;", NULL);
>         fprintf(stderr, "Here 3\n");
>
>         gst_bin_add_many(GST_BIN(app.pipeline), src, split, q1, enc1,
> h1, f1, q2, enc2, h2, f2, NULL);
>
>         if (!gst_element_link_many(src, split, NULL)
>                 || !gst_element_link_many(split, q1, enc1, h1, f1, NULL)
>                 || !gst_element_link_many(split, q2, enc2, h2, f2,
> NULL)) {
>                 g_error("Failed to link elements ...");
>                 return -2;
>         }
>
>         filtercaps = gst_caps_new_simple ("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), "caps", filtercaps, NULL);
>         gst_caps_unref (filtercaps);
>
>         gst_element_set_state (app.pipeline, GST_STATE_PLAYING);
>
>         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);
>
>         /* exit */
>         gst_element_set_state (app.pipeline, GST_STATE_NULL);
>         gst_object_unref (app.pipeline);
>
>         return 0;
> }
>
> The 'Here 1' prints then it dies, can any one help me to understand why?
>
> Either method of calling g_object_set fails the same way.
>
> Thanks
>
>
>

_______________________________________________
gstreamer-devel mailing list
[hidden email]
https://lists.freedesktop.org/mailman/listinfo/gstreamer-devel

signature.asc (499 bytes) Download Attachment
Reply | Threaded
Open this post in threaded view
|

Re: Trying translate working gst-launch command to the API

Kelly Wiles
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
[hidden email]
https://lists.freedesktop.org/mailman/listinfo/gstreamer-devel

out.pdf (47K) Download Attachment
Reply | Threaded
Open this post in threaded view
|

Re: Trying translate working gst-launch command to the API

Gary Metalle
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 <[hidden email]> on behalf of Kelly Wiles <[hidden email]>
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
[hidden email]
https://lists.freedesktop.org/mailman/listinfo/gstreamer-devel
Reply | Threaded
Open this post in threaded view
|

Re: Trying translate working gst-launch command to the API

Kelly Wiles
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 <[hidden email]> on behalf of Kelly Wiles <[hidden email]>
> 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
> [hidden email]
> 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
[hidden email]
https://lists.freedesktop.org/mailman/listinfo/gstreamer-devel
Reply | Threaded
Open this post in threaded view
|

Re: Trying translate working gst-launch command to the API

RK29
Hey Guys,
I am trying to do the same with the incoming stream received from webrtc
bin.
But adding the caps filter is messing my stream. I cannot even run it on
command line to debug. Kelly, can you please answer the question as to why
call back does not work when caps is introduced?
here is the link :
http://gstreamer-devel.966125.n4.nabble.com/Waiting-for-the-reply-Unable-to-get-the-sample-from-Appsink-using-C-td4695139.html



--
Sent from: http://gstreamer-devel.966125.n4.nabble.com/
_______________________________________________
gstreamer-devel mailing list
[hidden email]
https://lists.freedesktop.org/mailman/listinfo/gstreamer-devel
Reply | Threaded
Open this post in threaded view
|

Re: Trying translate working gst-launch command to the API

Kelly Wiles
Sadly I just started playing with this GStreamer stuff a few days ago,
do not think I  am qualified to answer your question.


On 8/24/2020 3:18 PM, RK29 wrote:

> Hey Guys,
> I am trying to do the same with the incoming stream received from webrtc
> bin.
> But adding the caps filter is messing my stream. I cannot even run it on
> command line to debug. Kelly, can you please answer the question as to why
> call back does not work when caps is introduced?
> here is the link :
> http://gstreamer-devel.966125.n4.nabble.com/Waiting-for-the-reply-Unable-to-get-the-sample-from-Appsink-using-C-td4695139.html
>
>
>
> --
> Sent from: http://gstreamer-devel.966125.n4.nabble.com/
> _______________________________________________
> gstreamer-devel mailing list
> [hidden email]
> 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
[hidden email]
https://lists.freedesktop.org/mailman/listinfo/gstreamer-devel
Reply | Threaded
Open this post in threaded view
|

Re: Trying translate working gst-launch command to the API

Gary Metalle
In reply to this post by Kelly Wiles
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 <[hidden email]> on behalf of Kelly Wiles <[hidden email]>
Sent: 24 August 2020 20:31
To: [hidden email]
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 <[hidden email]> on behalf of Kelly Wiles <[hidden email]>
> 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
> [hidden email]
> 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
[hidden email]
https://lists.freedesktop.org/mailman/listinfo/gstreamer-devel
_______________________________________________
gstreamer-devel mailing list
[hidden email]
https://lists.freedesktop.org/mailman/listinfo/gstreamer-devel
Reply | Threaded
Open this post in threaded view
|

Re: Trying translate working gst-launch command to the API

Kelly Wiles
Ok, so I changed the code. The code below mades it work, thanks Gary
Metalle.

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

     tee_1_pad = gst_element_get_request_pad (tee, "src_%u");
     g_print ("Obtained request pad %s for 500K branch.\n",
gst_pad_get_name (tee_1_pad));
     queue_1_pad = gst_element_get_static_pad (q1, "sink");
     tee_2_pad = gst_element_get_request_pad (tee, "src_%u");
     g_print ("Obtained request pad %s for 2M branch.\n",
gst_pad_get_name (tee_2_pad));
     queue_2_pad = gst_element_get_static_pad (q2, "sink");
     if (gst_pad_link (tee_1_pad, queue_1_pad) != GST_PAD_LINK_OK ||
         gst_pad_link (tee_2_pad, queue_2_pad) != GST_PAD_LINK_OK) {
         g_printerr ("Tee could not be linked.\n");
         gst_object_unref (app.pipeline);
         return -1;
     }
     gst_object_unref (queue_1_pad);
     gst_object_unref (queue_2_pad);

It now captures video in 500k and 2M BPS but the resolution is still
640x480 which is should be 1280x720.

Thanks

On 8/25/2020 3:07 AM, Gary Metalle wrote:

> 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 <[hidden email]> on behalf of Kelly Wiles <[hidden email]>
> Sent: 24 August 2020 20:31
> To: [hidden email]
> 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 <[hidden email]> on behalf of Kelly Wiles <[hidden email]>
>> 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
>> [hidden email]
>> 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
> [hidden email]
> https://lists.freedesktop.org/mailman/listinfo/gstreamer-devel
> _______________________________________________
> gstreamer-devel mailing list
> [hidden email]
> 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
[hidden email]
https://lists.freedesktop.org/mailman/listinfo/gstreamer-devel