properly closing dynamically created rtspsrc ! rtph264depay link

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

properly closing dynamically created rtspsrc ! rtph264depay link

Joona Laine
Hi,

I'm having a problem with dynamically linked elements. My pipeline is

gst-launch-1.0 rtspsrc location=rtsp://root:root@10.128.1.88/axis-media/media.amp?videocodec=h264 latency=0 ! rtph264depay ! h264parse ! queue ! vaapidecode ! glimagesink

When closing the pipeline I get the following debug messages (GST_DEBUG=3):

Execution ended after 0:00:02.282472788
Setting pipeline to PAUSED ...
Setting pipeline to READY ...
Setting pipeline to NULL ...
0:00:02.913797906  6077      0x1c07320 WARN                 rtspsrc gstrtspsrc.c:5477:gst_rtspsrc_try_send:<rtspsrc0> receive interrupted
0:00:02.913841639  6077      0x1c07320 WARN                 rtspsrc gstrtspsrc.c:7500:gst_rtspsrc_pause:<rtspsrc0> PAUSE interrupted
0:00:02.922788913  6077      0x1c07320 WARN                 rtspsrc gstrtspsrc.c:5477:gst_rtspsrc_try_send:<rtspsrc0> receive interrupted
0:00:02.922838980  6077      0x1c07320 WARN                 rtspsrc gstrtspsrc.c:6971:gst_rtspsrc_close:<rtspsrc0> TEARDOWN interrupted
Freeing pipeline ...

Otherwise this wouldn't bother me, but I'm making an application that changes the camera source quite frequently. This behavior causes the application to crash (actually the whole machine crashes) after a while it has been changing the rtsp streams. The dynamic pad linking happens in the following way:

static void onPadAdded(GstElement *element, GstPad *pad, gpointer data)
{
    gchar *name;

    name = gst_pad_get_name(pad);
    g_print("A new pad %s was created\n", name);

    // here, you would setup a new pad link for the newly created pad
    // sooo, now find that rtph264depay is needed and link them?
    GstCaps * p_caps = gst_pad_get_pad_template_caps (pad);

    gchar * description = gst_caps_to_string(p_caps);

    g_print("Caps, %s .\n", description);
//    std::cout << p_caps << ", " << description << std::endl;
    g_free(description);

    GstElement *depay = GST_ELEMENT(data);

    // try to link the pads then ...
    if(gst_element_link_pads(element, name, depay, "sink") == 0)
    {
        g_print("cb_new_rtspsrc_pad : failed to link elements \n");
    }

    g_free(name);
}

Never mind the comments, it's copied and modified from some forum.

My question is that am I doing the linking correctly? The same debug messages can be seen using just the gst-launch pipeline.

Thanks,

Joona

PS.
I'll post a runnable example as a reply.
Reply | Threaded
Open this post in threaded view
|

Re: properly closing dynamically created rtspsrc ! rtph264depay link

Joona Laine
Okay, here's an example:

#include <gst/gst.h>

static void onPadAdded(GstElement *element, GstPad *pad, gpointer data)
{
    gchar *name;

    name = gst_pad_get_name(pad);
    g_print("A new pad %s was created\n", name);

    // here, you would setup a new pad link for the newly created pad
    // sooo, now find that rtph264depay is needed and link them?
    GstCaps * p_caps = gst_pad_get_pad_template_caps (pad);

    gchar * description = gst_caps_to_string(p_caps);
//    std::cout << p_caps << ", " << description << std::endl;
    g_free(description);

    GstElement *depay = GST_ELEMENT(data);

    // try to link the pads then ...
    if(gst_element_link_pads(element, name, depay, "sink") == 0)
    {
        g_print("cb_new_rtspsrc_pad : failed to link elements \n");
    }

    g_free(name);
}


static gboolean
bus_call (GstBus     *bus,
          GstMessage *msg,
          gpointer    data)
{
  GMainLoop *loop = data;

  switch (GST_MESSAGE_TYPE (msg)) {
    case GST_MESSAGE_EOS:
      g_print ("End-of-stream\n");
      g_main_loop_quit (loop);
      break;
    case GST_MESSAGE_ERROR: {
      gchar *debug = NULL;
      GError *err = NULL;

      gst_message_parse_error (msg, &err, &debug);

      g_print ("Error: %s\n", err->message);
      g_error_free (err);

      if (debug) {
        g_print ("Debug details: %s\n", debug);
        g_free (debug);
      }

      g_main_loop_quit (loop);
      break;
    }
    default:
      break;
  }

  return TRUE;
}

gint
main (gint   argc, gchar *argv[])
{
  GstStateChangeReturn ret;
  GstElement *pipeline, *rtspsrc, *depayer, *parser, *queue, *decoder, *filter, *sink;
  GMainLoop *loop;
  GstBus *bus;
  guint watch_id;

  char *uri1 = "rtsp://root:root@10.128.1.88/axis-media/media.amp";
//  char *uri2 = "rtsp://root:root@10.128.1.82/axis-media/media.amp";

  /* initialization */
  gst_init (&argc, &argv);
  loop = g_main_loop_new (NULL, FALSE);

  /* create elements */
  pipeline = gst_pipeline_new ("my_pipeline");

  /* watch for messages on the pipeline's bus (note that this will only
   * work like this when a GLib main loop is running) */
  bus = gst_pipeline_get_bus (GST_PIPELINE (pipeline));
  watch_id = gst_bus_add_watch (bus, bus_call, loop);
  gst_object_unref (bus);

  rtspsrc = gst_element_factory_make ("rtspsrc", "my_source");
  depayer = gst_element_factory_make ("rtph264depay", "my_depayer");
  parser = gst_element_factory_make ("h264parse", "my_parser");
  queue =  gst_element_factory_make ("queue", "my_queue");
  decoder = gst_element_factory_make ("vaapidecode", "my_decoder");
  filter = gst_element_factory_make ("videoconvert", "my_filter");
  sink = gst_element_factory_make ("glimagesink", "my_sink");


  if (!sink || !decoder) {
    g_print ("Decoder or output could not be found - check your install\n");
    return -1;
  } else if (!depayer || !parser || !queue) {
    g_print ("Could not create audioconvert or audioresample element, "
             "check your installation\n");
    return -1;
  } else if (!filter) {
    g_print ("Your self-written filter could not be found. Make sure it "
             "is installed correctly in $(libdir)/gstreamer-1.0/ or "
             "~/.gstreamer-1.0/plugins/ and that gst-inspect-1.0 lists it. "
             "If it doesn't, check with 'GST_DEBUG=*:2 gst-inspect-1.0' for "
             "the reason why it is not being loaded.");
    return -1;
  }

  g_object_set (G_OBJECT (rtspsrc), "location", uri1, NULL);
  g_object_set (G_OBJECT (rtspsrc), "latency", 0, NULL);

  g_signal_connect(G_OBJECT(rtspsrc), "pad-added", G_CALLBACK(onPadAdded), depayer);
 
  gst_bin_add_many (GST_BIN (pipeline), rtspsrc, depayer, parser, queue, decoder, filter, sink, NULL);

  /* link everything together */
  if (!gst_element_link_many (depayer, parser, queue, decoder, filter, sink, NULL)) {
    g_print ("Failed to link one or more elements!\n");
    return -1;
  }

  /* run */
  ret = gst_element_set_state (pipeline, GST_STATE_PLAYING);
  if (ret == GST_STATE_CHANGE_FAILURE) {
    GstMessage *msg;

    g_print ("Failed to start up pipeline!\n");

    /* check if there is an error message with details on the bus */
    msg = gst_bus_poll (bus, GST_MESSAGE_ERROR, 0);
    if (msg) {
      GError *err = NULL;

      gst_message_parse_error (msg, &err, NULL);
      g_print ("ERROR: %s\n", err->message);
      g_error_free (err);
      gst_message_unref (msg);
    }
    return -1;
  }

  g_main_loop_run (loop);

  /* clean up */
  gst_element_set_state (pipeline, GST_STATE_NULL);
  gst_object_unref (pipeline);
  g_source_remove (watch_id);
  g_main_loop_unref (loop);

  return 0;
}
Reply | Threaded
Open this post in threaded view
|

Re: properly closing dynamically created rtspsrc ! rtph264depay link

Joona Laine
In reply to this post by Joona Laine
0:00:02.913797906  6077      0x1c07320 WARN                 rtspsrc gstrtspsrc.c:5477:gst_rtspsrc_try_send:<rtspsrc0> receive interrupted
0:00:02.913841639  6077      0x1c07320 WARN                 rtspsrc gstrtspsrc.c:7500:gst_rtspsrc_pause:<rtspsrc0> PAUSE interrupted
0:00:02.922788913  6077      0x1c07320 WARN                 rtspsrc gstrtspsrc.c:5477:gst_rtspsrc_try_send:<rtspsrc0> receive interrupted
0:00:02.922838980  6077      0x1c07320 WARN                 rtspsrc gstrtspsrc.c:6971:gst_rtspsrc_close:<rtspsrc0> TEARDOWN interrupted

Okay, so one thing seems to be certain. The above warnings come when I set the pipeline to GST_STATE_NULL. If I only set them to PAUSED then I don't get any warnings but no resources can be freed until the pipeline is in the NULL state.

Any help would be highly appreciated.