<div dir="ltr"><div dir="ltr"><div dir="ltr"><div dir="ltr"><div>Hello,</div><div><br></div><div>Tutorial 3 is great and explains how to dynamically add pads:<br></div><div><a href="https://gstreamer.freedesktop.org/documentation/tutorials/basic/dynamic-pipelines.html">https://gstreamer.freedesktop.org/documentation/tutorials/basic/dynamic-pipelines.html</a></div><div><br></div><div>When I try to do the exercise to add a video converter and video sink, I get a ton of messages and the audio and video do not work. Any pointers on what am I doing incorrect?<br></div><div><br></div><div><b>Here is my code:</b></div><div>#include <gst/gst.h><br><br>/* Structure to contain all our information, so we can pass it to callbacks */<br>typedef struct _CustomData {<br>  GstElement *pipeline;<br>  GstElement *source;<br>  GstElement *audio_convert;<br>  GstElement *video_convert;<br>  GstElement *audio_sink;<br>  GstElement *video_sink;<br>} CustomData;<br><br>/* Handler for the pad-added signal */<br>static void pad_added_handler (GstElement *src, GstPad *pad, CustomData *data);<br><br>int main(int argc, char *argv[]) {<br>  CustomData data;<br>  GstBus *bus;<br>  GstMessage *msg;<br>  GstStateChangeReturn ret;<br>  gboolean terminate = FALSE;<br><br>  /* Initialize GStreamer */<br>  gst_init (&argc, &argv);<br><br>  /* Create the elements */<br>  data.source = gst_element_factory_make ("uridecodebin", "source");<br>  data.audio_convert = gst_element_factory_make ("audioconvert", "audio_convert");<br>  data.video_convert = gst_element_factory_make ("videoconvert", "video_convert");<br>  data.audio_sink = gst_element_factory_make ("autoaudiosink", "audio_sink");<br>  data.video_sink = gst_element_factory_make ("autovideosink", "video_sink");<br><br>  /* Create the empty pipeline */<br>  data.pipeline = gst_pipeline_new ("test-pipeline");<br><br>  if (!data.pipeline || !data.source || <br>      !data.audio_convert || !data.audio_sink ||<br>      !data.video_convert || !data.video_sink) {<br>    g_printerr ("Not all elements could be created.\n");<br>    return -1;<br>  }<br><br>  /* Build the pipeline. Note that we are NOT linking the source at this<br>   * point. We will do it later. */<br>  gst_bin_add_many (GST_BIN (data.pipeline), data.source,<br>                    data.audio_convert , data.video_convert, data.audio_sink,<br>                    data.video_sink, NULL);<br>  if (!gst_element_link (data.audio_convert, data.audio_sink)) {<br>    g_printerr ("audio_convert -> audio_sink elements could not be linked.\n");<br>    gst_object_unref (data.pipeline);<br>    return -1;<br>  }<br>  if (!gst_element_link (data.video_convert, data.video_sink)) {<br>    g_printerr ("video_convert -> video_sink elements could not be linked.\n");<br>    gst_object_unref (data.pipeline);<br>    return -1;<br>  }<br><br>  /* Set the URI to play */<br>  g_object_set (data.source, "uri", "<a href="https://www.freedesktop.org/software/gstreamer-sdk/data/media/sintel_trailer-480p.webm">https://www.freedesktop.org/software/gstreamer-sdk/data/media/sintel_trailer-480p.webm</a>", NULL);<br><br>  /* Connect to the pad-added signal */<br>  g_signal_connect (data.source, "pad-added", G_CALLBACK (pad_added_handler), &data);<br><br>  /* Start playing */<br>  ret = gst_element_set_state (data.pipeline, GST_STATE_PLAYING);<br>  if (ret == GST_STATE_CHANGE_FAILURE) {<br>    g_printerr ("Unable to set the pipeline to the playing state.\n");<br>    gst_object_unref (data.pipeline);<br>    return -1;<br>  }<br><br>  /* Listen to the bus */<br>  bus = gst_element_get_bus (data.pipeline);<br>  do {<br>    msg = gst_bus_timed_pop_filtered (bus, GST_CLOCK_TIME_NONE,<br>        GST_MESSAGE_STATE_CHANGED | GST_MESSAGE_ERROR | GST_MESSAGE_EOS);<br><br>    /* Parse message */<br>    if (msg != NULL) {<br>      GError *err;<br>      gchar *debug_info;<br><br>      switch (GST_MESSAGE_TYPE (msg)) {<br>        case GST_MESSAGE_ERROR:<br>          gst_message_parse_error (msg, &err, &debug_info);<br>          g_printerr ("Error received from element %s: %s\n", GST_OBJECT_NAME (msg->src), err->message);<br>          g_printerr ("Debugging information: %s\n", debug_info ? debug_info : "none");<br>          g_clear_error (&err);<br>          g_free (debug_info);<br>          terminate = TRUE;<br>          break;<br>        case GST_MESSAGE_EOS:<br>          g_print ("End-Of-Stream reached.\n");<br>          terminate = TRUE;<br>          break;<br>        case GST_MESSAGE_STATE_CHANGED:<br>          /* We are only interested in state-changed messages from the pipeline */<br>          if (GST_MESSAGE_SRC (msg) == GST_OBJECT (data.pipeline)) {<br>            GstState old_state, new_state, pending_state;<br>            gst_message_parse_state_changed (msg, &old_state, &new_state, &pending_state);<br>            g_print ("Pipeline state changed from %s to %s:\n",<br>                gst_element_state_get_name (old_state), gst_element_state_get_name (new_state));<br>          }<br>          break;<br>        default:<br>          /* We should not reach here */<br>          g_printerr ("Unexpected message received.\n");<br>          break;<br>      }<br>      gst_message_unref (msg);<br>    }<br>  } while (!terminate);<br><br>  /* Free resources */<br>  gst_object_unref (bus);<br>  gst_element_set_state (data.pipeline, GST_STATE_NULL);<br>  gst_object_unref (data.pipeline);<br>  return 0;<br>}<br><br>/* This function will be called by the pad-added signal */<br>static void pad_added_handler (GstElement *src, GstPad *new_pad, CustomData *data) {<br>  GstPad *audio_sink_pad = gst_element_get_static_pad (data->audio_convert, "audio_sink");<br>  GstPad *video_sink_pad = gst_element_get_static_pad (data->video_convert, "video_sink");<br>  GstPadLinkReturn ret;<br>  GstCaps *new_pad_caps = NULL;<br>  GstStructure *new_pad_struct = NULL;<br>  const gchar *new_pad_type = NULL;<br><br>  g_print ("Received new pad '%s' from '%s':\n", GST_PAD_NAME (new_pad), GST_ELEMENT_NAME (src));<br><br>  /* If our converter is already linked, we have nothing to do here<br>  if (gst_pad_is_linked (sink_pad)) {<br>    g_print ("We are already linked. Ignoring.\n");<br>    goto exit;<br>  }<br>  */<br><br>  /* Check the new pad's type */<br>  new_pad_caps = gst_pad_get_current_caps (new_pad);<br>  new_pad_struct = gst_caps_get_structure (new_pad_caps, 0);<br>  new_pad_type = gst_structure_get_name (new_pad_struct);<br><br>  // Check for audio<br>  if (g_str_has_prefix (new_pad_type, "audio/x-raw")) {<br>      /* Attempt the link */<br>      ret = gst_pad_link (new_pad, audio_sink_pad);<br>      if (GST_PAD_LINK_FAILED (ret)) {<br>        g_print ("Type is '%s' but link failed.\n", new_pad_type);<br>      } else {<br>        g_print ("Link succeeded (type '%s').\n", new_pad_type);<br>      }<br>      goto exit;<br>  }<br>  else if (g_str_has_prefix (new_pad_type, "video/x-raw")) {<br>      /* Attempt the link */<br>      ret = gst_pad_link (new_pad, video_sink_pad);<br>      if (GST_PAD_LINK_FAILED (ret)) {<br>        g_print ("Type is '%s' but link failed.\n", new_pad_type);<br>      } else {<br>        g_print ("Link succeeded (type '%s').\n", new_pad_type);<br>      }<br>      goto exit;<br>  }<br>  else {<br>    g_print ("It has type '%s' which is not raw audio or video. Ignoring.\n", new_pad_type);<br>    goto exit;<br>  }<br><br><br>exit:<br>  /* Unreference the new pad's caps, if we got them */<br>  if (new_pad_caps != NULL)<br>    gst_caps_unref (new_pad_caps);<br><br>  /* Unreference the sink pad */<br>  gst_object_unref (audio_sink_pad);<br>  gst_object_unref (video_sink_pad);<br>}<br><br></div><div><br></div><div><b>Here is the output:</b></div><div>Pipeline state changed from NULL to READY:<br>Received new pad 'src_0' from 'source':<br><br>(basic-tutorial-3c:30218): GStreamer-CRITICAL **: gst_pad_link_full: assertion 'GST_IS_PAD (sinkpad)' failed<br>Type is 'video/x-raw' but link failed.<br><br>(basic-tutorial-3c:30218): GStreamer-CRITICAL **: gst_object_unref: assertion 'object != NULL' failed<br><br>(basic-tutorial-3c:30218): GStreamer-CRITICAL **: gst_object_unref: assertion 'object != NULL' failed<br>Received new pad 'src_1' from 'source':<br><br>(basic-tutorial-3c:30218): GStreamer-CRITICAL **: gst_pad_link_full: assertion 'GST_IS_PAD (sinkpad)' failed<br>Type is 'audio/x-raw' but link failed.<br><br>(basic-tutorial-3c:30218): GStreamer-CRITICAL **: gst_object_unref: assertion 'object != NULL' failed<br><br>(basic-tutorial-3c:30218): GStreamer-CRITICAL **: gst_object_unref: assertion 'object != NULL' failed<br>Error received from element matroskademux0: GStreamer encountered a general stream error.<br>Debugging information: matroska-demux.c(4761): gst_matroska_demux_loop (): /GstPipeline:test-pipeline/GstURIDecodeBin:source/GstDecodeBin:decodebin0/GstMatroskaDemux:matroskademux0:<br>stream stopped, reason not-linked<br><br></div><div>Can someone please comment what am I doing incorrect?</div><div><br></div><div><br></div></div></div></div></div>