Trying translate working gst-launch command to the API
Kelly Wiles
rkwiles at twc.com
Tue Aug 25 11:08:54 UTC 2020
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 <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
> _______________________________________________
> 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
More information about the gstreamer-devel
mailing list