Exemplo n.º 1
0
static GstCaps *
gst_play_sink_audio_convert_getcaps (GstPad * pad)
{
  GstPlaySinkAudioConvert *self =
      GST_PLAY_SINK_AUDIO_CONVERT (gst_pad_get_parent (pad));
  GstCaps *ret;
  GstPad *otherpad, *peer = NULL;

  GST_PLAY_SINK_AUDIO_CONVERT_LOCK (self);
  otherpad = gst_ghost_pad_get_target (GST_GHOST_PAD_CAST (pad));
  GST_PLAY_SINK_AUDIO_CONVERT_UNLOCK (self);

  if (otherpad) {
    peer = gst_pad_get_peer (otherpad);
    gst_object_unref (otherpad);
    otherpad = NULL;
  }

  if (peer) {
    ret = gst_pad_get_caps_reffed (peer);
    gst_object_unref (peer);
  } else {
    ret = gst_caps_new_any ();
  }

  gst_object_unref (self);

  return ret;
}
Exemplo n.º 2
0
static void
kms_element_release_pad (GstElement * element, GstPad * pad)
{
  GstElement *agnosticbin;
  GstPad *target;

  if (g_str_has_prefix (GST_OBJECT_NAME (pad), "audio_src")) {
    agnosticbin = KMS_ELEMENT (element)->priv->audio_agnosticbin;
  } else if (g_str_has_prefix (GST_OBJECT_NAME (pad), "video_src")) {
    agnosticbin = KMS_ELEMENT (element)->priv->video_agnosticbin;
  } else {
    return;
  }

  // TODO: Remove pad if is a sinkpad

  target = gst_ghost_pad_get_target (GST_GHOST_PAD (pad));

  if (target != NULL && agnosticbin != NULL)
    gst_element_release_request_pad (agnosticbin, target);

  if (GST_STATE (element) >= GST_STATE_PAUSED
      || GST_STATE_PENDING (element) >= GST_STATE_PAUSED)
    gst_pad_set_active (pad, FALSE);

  gst_element_remove_pad (element, pad);
}
static gboolean
gst_play_sink_convert_bin_sink_setcaps (GstPlaySinkConvertBin * self,
    GstCaps * caps)
{
  GstStructure *s;
  const gchar *name;
  gboolean reconfigure = FALSE;
  gboolean raw;

  GST_DEBUG_OBJECT (self, "setcaps");
  GST_PLAY_SINK_CONVERT_BIN_LOCK (self);
  s = gst_caps_get_structure (caps, 0);
  name = gst_structure_get_name (s);

  if (self->audio) {
    raw = g_str_equal (name, "audio/x-raw");
  } else {
    raw = g_str_equal (name, "video/x-raw");
  }

  GST_DEBUG_OBJECT (self, "raw %d, self->raw %d, blocked %d",
      raw, self->raw, gst_pad_is_blocked (self->sink_proxypad));

  if (raw) {
    if (!gst_pad_is_blocked (self->sink_proxypad)) {
      GstPad *target = gst_ghost_pad_get_target (GST_GHOST_PAD (self->sinkpad));

      if (!self->raw || (target && !gst_pad_query_accept_caps (target, caps))) {
        if (!self->raw)
          GST_DEBUG_OBJECT (self, "Changing caps from non-raw to raw");
        else
          GST_DEBUG_OBJECT (self, "Changing caps in an incompatible way");

        reconfigure = TRUE;
        block_proxypad (self);
      }

      if (target)
        gst_object_unref (target);
    }
  } else {
    if (self->raw && !gst_pad_is_blocked (self->sink_proxypad)) {
      GST_DEBUG_OBJECT (self, "Changing caps from raw to non-raw");
      reconfigure = TRUE;
      block_proxypad (self);
    }
  }

  /* Otherwise the setcaps below fails */
  if (reconfigure) {
    gst_ghost_pad_set_target (GST_GHOST_PAD_CAST (self->sinkpad), NULL);
    gst_ghost_pad_set_target (GST_GHOST_PAD_CAST (self->srcpad), NULL);
  }

  GST_PLAY_SINK_CONVERT_BIN_UNLOCK (self);

  GST_DEBUG_OBJECT (self, "Setting sink caps %" GST_PTR_FORMAT, caps);

  return TRUE;
}
Exemplo n.º 4
0
static gboolean
set_target (GstPad * gp, GstPad * target)
{
  GstPad *old_target;
  GstPad *peer;

  old_target = gst_ghost_pad_get_target (GST_GHOST_PAD (gp));
  if (old_target == NULL) {
    goto end;
  }
  peer = gst_pad_get_peer (old_target);

  if (peer != NULL) {
    if (peer->direction == GST_PAD_SINK) {
      gst_pad_unlink (old_target, peer);
    } else {
      gst_pad_unlink (peer, old_target);
    }
    g_object_unref (peer);
  }
  g_object_unref (old_target);

end:
  return gst_ghost_pad_set_target (GST_GHOST_PAD (gp), target);
}
Exemplo n.º 5
0
static GstPad *
_get_peer_pad (GstPad * pad)
{
  GstPad *peer = gst_pad_get_peer (pad);

  if (!peer)
    return NULL;

  while (GST_IS_PROXY_PAD (peer)) {
    GstPad *next_pad;

    if (GST_IS_GHOST_PAD (peer)) {
      next_pad = gst_pad_get_peer (peer);

      if (next_pad == pad)
        next_pad = gst_ghost_pad_get_target (GST_GHOST_PAD (peer));
    } else {
      next_pad = GST_PAD (gst_proxy_pad_get_internal (GST_PROXY_PAD (peer)));
    }

    if (!next_pad)
      return NULL;

    gst_object_unref (peer);
    peer = next_pad;
  }

  return peer;
}
static void
debug_dump_element_pad (GstPad * pad, GstElement * element,
    GstDebugGraphDetails details, FILE * out, const gint indent)
{
  GstElement *target_element;
  GstPad *target_pad, *tmp_pad;
  GstPadDirection dir;
  gchar *element_name;
  gchar *target_element_name;
  const gchar *color_name;

  dir = gst_pad_get_direction (pad);
  element_name = debug_dump_make_object_name (GST_OBJECT (element));
  if (GST_IS_GHOST_PAD (pad)) {
    color_name =
        (dir == GST_PAD_SRC) ? "#ffdddd" : ((dir ==
            GST_PAD_SINK) ? "#ddddff" : "#ffffff");
    /* output target-pad so that it belongs to this element */
    if ((tmp_pad = gst_ghost_pad_get_target (GST_GHOST_PAD (pad)))) {
      if ((target_pad = gst_pad_get_peer (tmp_pad))) {
        gchar *pad_name, *target_pad_name;
        const gchar *spc = &spaces[MAX (sizeof (spaces) - (1 + indent * 2), 0)];

        if ((target_element = gst_pad_get_parent_element (target_pad))) {
          target_element_name =
              debug_dump_make_object_name (GST_OBJECT (target_element));
        } else {
          target_element_name = g_strdup ("");
        }
        debug_dump_pad (target_pad, color_name, target_element_name, details,
            out, indent);
        /* src ghostpad relationship */
        pad_name = debug_dump_make_object_name (GST_OBJECT (pad));
        target_pad_name = debug_dump_make_object_name (GST_OBJECT (target_pad));
        if (dir == GST_PAD_SRC) {
          fprintf (out, "%s%s_%s -> %s_%s [style=dashed, minlen=0]\n", spc,
              target_element_name, target_pad_name, element_name, pad_name);
        } else {
          fprintf (out, "%s%s_%s -> %s_%s [style=dashed, minlen=0]\n", spc,
              element_name, pad_name, target_element_name, target_pad_name);
        }
        g_free (target_pad_name);
        g_free (target_element_name);
        if (target_element)
          gst_object_unref (target_element);
        gst_object_unref (target_pad);
        g_free (pad_name);
      }
      gst_object_unref (tmp_pad);
    }
  } else {
    color_name =
        (dir == GST_PAD_SRC) ? "#ffaaaa" : ((dir ==
            GST_PAD_SINK) ? "#aaaaff" : "#cccccc");
  }
  /* pads */
  debug_dump_pad (pad, color_name, element_name, details, out, indent);
  g_free (element_name);
}
Exemplo n.º 7
0
/**
 * Process a pad for connecting or disconnecting, it should be always called
 * whint the agnostic lock hold.
 *
 * @self: The #KmsAgnosticBin2 owner of the pad
 * @pad: The pad to be processed
 */
static gboolean
kms_agnostic_bin2_process_pad (KmsAgnosticBin2 * self, GstPad * pad)
{
  GstPad *peer = NULL;

  if (!GST_OBJECT_FLAG_IS_SET (pad, KMS_AGNOSTIC_PAD_STARTED)) {
    return FALSE;
  }

  if (!self->priv->started) {
    return FALSE;
  }

  GST_DEBUG_OBJECT (self, "Processing pad: %" GST_PTR_FORMAT, pad);

  if (pad == NULL) {
    return FALSE;
  }

  peer = gst_pad_get_peer (pad);

  if (peer != NULL) {
    GstPad *target = gst_ghost_pad_get_target (GST_GHOST_PAD (pad));

    if (target) {
      GstCaps *caps = gst_pad_get_current_caps (pad);

      if (caps != NULL) {
        gboolean accepted;

        accepted = gst_pad_query_accept_caps (peer, caps);
        gst_caps_unref (caps);

        if (accepted) {
          GST_DEBUG_OBJECT (self, "No need to reconfigure pad %" GST_PTR_FORMAT,
              pad);
          g_object_unref (target);
          g_object_unref (peer);
          return FALSE;
        }

        remove_target_pad (pad);
      }

      g_object_unref (target);
    }

    kms_agnostic_bin2_link_pad (self, pad, peer);
  }

  return TRUE;
}
Exemplo n.º 8
0
static GstPad *
gst_switch_request_new_pad (GstElement * element,
    GstPadTemplate * templ, const gchar * name, const GstCaps * caps)
{
  GstSwitch *swit = GST_SWITCH (element);
  GstGhostPad *pad;

  INFO ("requesting: %s.%s (%d=%d+%d)", GST_ELEMENT_NAME (swit),
      name ? name : GST_PAD_TEMPLATE_NAME_TEMPLATE (templ),
      element->numpads, element->numsrcpads, element->numsinkpads);

  GST_SWITCH_LOCK (swit);

  switch (GST_PAD_TEMPLATE_DIRECTION (templ)) {
    case GST_PAD_SRC:
      pad = gst_switch_request_new_src_pad (swit, templ, name, caps);
      break;
    case GST_PAD_SINK:
      pad = gst_switch_request_new_sink_pad (swit, templ, name, caps);
      break;
    default:
      pad = NULL;
      break;
  }

  if (pad) {
    gst_pad_set_active (GST_PAD (pad), TRUE);

    if (gst_element_add_pad (GST_ELEMENT (swit), GST_PAD (pad))) {
      GstPad *basepad = gst_ghost_pad_get_target (pad);
      GstElement *swcase = GST_ELEMENT (GST_PAD_PARENT (basepad));

      GST_OBJECT_FLAG_SET (basepad, GST_SWITCH_PAD_FLAG_GHOSTED);

      GST_DEBUG_OBJECT (swit, "New %s:%s on %s:%s",
          GST_ELEMENT_NAME (swit), GST_PAD_NAME (pad),
          GST_ELEMENT_NAME (swcase), GST_PAD_NAME (basepad));

      INFO ("requested %s.%s on %s.%s",
          GST_ELEMENT_NAME (swit), GST_PAD_NAME (pad),
          GST_ELEMENT_NAME (swcase), GST_PAD_NAME (basepad));
    }
  }

  GST_SWITCH_UNLOCK (swit);

  return GST_PAD (pad);
}
Exemplo n.º 9
0
static void
dvb_base_bin_release_pad (GstElement * element, GstPad * pad)
{
  GstGhostPad *ghost;
  GstPad *target;

  g_return_if_fail (GST_IS_DVB_BASE_BIN (element));

  ghost = GST_GHOST_PAD (pad);
  target = gst_ghost_pad_get_target (ghost);
  gst_element_release_request_pad (GST_ELEMENT (GST_DVB_BASE_BIN (element)->
          mpegtsparse), target);
  gst_object_unref (target);

  gst_element_remove_pad (element, pad);
}
static void
gst_splitmux_sink_release_pad (GstElement * element, GstPad * pad)
{
  GstSplitMuxSink *splitmux = (GstSplitMuxSink *) element;
  GstPad *mqsink, *mqsrc, *muxpad;
  MqStreamCtx *ctx =
      (MqStreamCtx *) (g_object_get_qdata ((GObject *) (pad), PAD_CONTEXT));

  GST_SPLITMUX_LOCK (splitmux);

  if (splitmux->muxer == NULL || splitmux->mq == NULL)
    goto fail;                  /* Elements don't exist yet - nothing to release */

  GST_INFO_OBJECT (pad, "releasing request pad");

  mqsink = gst_ghost_pad_get_target (GST_GHOST_PAD (pad));
  mqsrc = mq_sink_to_src (splitmux->mq, mqsink);
  muxpad = gst_pad_get_peer (mqsrc);

  /* Remove the context from our consideration */
  splitmux->contexts = g_list_remove (splitmux->contexts, ctx);

  if (ctx->sink_pad_block_id)
    gst_pad_remove_probe (ctx->sinkpad, ctx->sink_pad_block_id);

  if (ctx->src_pad_block_id)
    gst_pad_remove_probe (ctx->srcpad, ctx->src_pad_block_id);

  /* Can release the context now */
  mq_stream_ctx_unref (ctx);

  /* Release and free the mq input */
  gst_element_release_request_pad (splitmux->mq, mqsink);

  /* Release and free the muxer input */
  gst_element_release_request_pad (splitmux->muxer, muxpad);

  gst_object_unref (mqsink);
  gst_object_unref (mqsrc);
  gst_object_unref (muxpad);

  gst_element_remove_pad (element, pad);

fail:
  GST_SPLITMUX_UNLOCK (splitmux);
}
Exemplo n.º 11
0
static void
kms_element_release_pad (GstElement * element, GstPad * pad)
{
  GstElement *agnosticbin;
  GstPad *target;
  GstPad *peer;

  if (g_str_has_prefix (GST_OBJECT_NAME (pad), "audio_src")) {
    agnosticbin = KMS_ELEMENT (element)->priv->audio_agnosticbin;
  } else if (g_str_has_prefix (GST_OBJECT_NAME (pad), "video_src")) {
    agnosticbin = KMS_ELEMENT (element)->priv->video_agnosticbin;
  } else {
    return;
  }

  // TODO: Remove pad if is a sinkpad

  target = gst_ghost_pad_get_target (GST_GHOST_PAD (pad));

  if (target != NULL) {
    if (agnosticbin != NULL) {
      gst_element_release_request_pad (agnosticbin, target);
    }
    g_object_unref (target);
  }

  peer = gst_pad_get_peer (pad);

  gst_pad_push_event (pad, gst_event_new_flush_start ());

  if (GST_STATE (element) >= GST_STATE_PAUSED
      || GST_STATE_PENDING (element) >= GST_STATE_PAUSED) {
    gst_pad_set_active (pad, FALSE);
  }

  if (peer) {
    gst_pad_send_event (peer, gst_event_new_flush_stop (FALSE));
    g_object_unref (peer);
  }

  gst_element_remove_pad (element, pad);
}
Exemplo n.º 12
0
static void
remove_target_pad (GstPad * pad)
{
  // TODO: Remove target pad is just like a disconnection it should be done
  // with care, possibly blocking the pad, or at least disconnecting directly
  // from the tee
  GstPad *target = gst_ghost_pad_get_target (GST_GHOST_PAD (pad));

  GST_DEBUG_OBJECT (pad, "Removing target pad");

  if (target == NULL) {
    return;
  }

  gst_pad_add_probe (target, GST_PAD_PROBE_TYPE_DATA_DOWNSTREAM,
      remove_target_pad_block, NULL, NULL);
  gst_ghost_pad_set_target (GST_GHOST_PAD (pad), NULL);

  g_object_unref (target);
}
Exemplo n.º 13
0
/* Event function for the ghost sink pad. */
static gboolean
gst_rg_volume_sink_event (GstPad * pad, GstObject * parent, GstEvent * event)
{
  GstRgVolume *self;
  GstPad *volume_sink_pad;
  GstEvent *send_event = event;
  gboolean res;

  self = GST_RG_VOLUME (parent);
  volume_sink_pad = gst_ghost_pad_get_target (GST_GHOST_PAD (pad));

  switch (GST_EVENT_TYPE (event)) {
    case GST_EVENT_TAG:

      GST_LOG_OBJECT (self, "received tag event");

      send_event = gst_rg_volume_tag_event (self, event);

      if (send_event == NULL)
        GST_LOG_OBJECT (self, "all tags handled, dropping event");

      break;

    case GST_EVENT_EOS:

      gst_rg_volume_reset (self);
      break;

    default:
      break;
  }

  if (G_LIKELY (send_event != NULL))
    res = gst_pad_send_event (volume_sink_pad, send_event);
  else
    res = TRUE;

  gst_object_unref (volume_sink_pad);

  return res;
}
Exemplo n.º 14
0
static void
kms_element_remove_target_pad (KmsElement * self, GstPad * pad)
{
  GstElement *agnosticbin;
  GstPad *target;

  target = gst_ghost_pad_get_target (GST_GHOST_PAD (pad));
  if (target == NULL) {
    return;
  }

  agnosticbin = gst_pad_get_parent_element (target);
  if (agnosticbin == NULL) {
    GST_WARNING_OBJECT (self, "No agnosticbin owns %" GST_PTR_FORMAT, pad);
  } else {
    gst_element_release_request_pad (agnosticbin, target);
    g_object_unref (agnosticbin);
  }

  gst_ghost_pad_set_target (GST_GHOST_PAD (pad), NULL);
  g_object_unref (target);
}
Exemplo n.º 15
0
static void
kms_element_remove_target_on_unlinked (GstPad * pad, GstPad * peer,
    GstElement * element)
{
  GstPad *target;

  target = gst_ghost_pad_get_target (GST_GHOST_PAD (pad));

  if (target == NULL) {
    GST_DEBUG_OBJECT (pad, "No target pad");
    return;
  }

  if (!gst_ghost_pad_set_target (GST_GHOST_PAD (pad), NULL)) {
    GST_ERROR_OBJECT (pad, "Can not remove target pad");
  }

  GST_DEBUG_OBJECT (element, "Removing requested pad %" GST_PTR_FORMAT, target);
  gst_element_release_request_pad (element, target);

  g_object_unref (target);
}
Exemplo n.º 16
0
static void
pad_added_cb (GstElement * element, GstPad * pad, gint * n_added)
{
  App *app = &s_app;
  GstPad *sinkpad = NULL;
  GstPad *target = NULL;

  if (app->fakesink[*n_added] != NULL) {
    sinkpad = gst_element_get_static_pad (app->fakesink[*n_added], "sink");
    fail_unless (GST_PAD_LINK_SUCCESSFUL (gst_pad_link (pad, sinkpad)));
    gst_object_unref (sinkpad);

    target = gst_ghost_pad_get_target (GST_GHOST_PAD (pad));
    fail_unless (target != NULL);

    gst_pad_add_probe (target, GST_PAD_PROBE_TYPE_EVENT_UPSTREAM,
        _appsrc_event_probe, GST_PAD_PARENT (target), NULL);
    gst_object_unref (target);
  }

  *n_added = *n_added + 1;
}
static GstStructure *
find_stream_for_node (GstDiscoverer * dc, const GstStructure * topology)
{
  GstPad *pad;
  GstPad *target_pad = NULL;
  GstStructure *st = NULL;
  PrivateStream *ps;
  guint i;
  GList *tmp;

  if (!gst_structure_id_has_field (topology, _TOPOLOGY_PAD_QUARK)) {
    GST_DEBUG ("Could not find pad for node %" GST_PTR_FORMAT "\n", topology);
    return NULL;
  }

  gst_structure_id_get (topology, _TOPOLOGY_PAD_QUARK,
      GST_TYPE_PAD, &pad, NULL);

  if (!dc->priv->streams)
    return NULL;

  for (i = 0, tmp = dc->priv->streams; tmp; tmp = tmp->next, i++) {
    ps = (PrivateStream *) tmp->data;

    target_pad = gst_ghost_pad_get_target (GST_GHOST_PAD (ps->pad));
    gst_object_unref (target_pad);

    if (target_pad == pad)
      break;
  }

  if (tmp)
    st = collect_stream_information (dc, ps, i);

  gst_object_unref (pad);

  return st;
}
Exemplo n.º 18
0
static void
do_element_stats (GstStatsTracer * self, GstPad * pad, GstClockTime elapsed1,
    GstClockTime elapsed2)
{
  GstClockTimeDiff elapsed = GST_CLOCK_DIFF (elapsed1, elapsed2);
  GstObject *parent = GST_OBJECT_PARENT (pad);
  GstElement *this =
      GST_ELEMENT_CAST (GST_IS_PAD (parent) ? GST_OBJECT_PARENT (parent) :
      parent);
  GstElementStats *this_stats = get_element_stats (self, this);
  GstPad *peer_pad = GST_PAD_PEER (pad);
  GstElementStats *peer_stats;

  if (!peer_pad)
    return;

  /* walk the ghost pad chain downstream to get the real pad */
  /* if parent of peer_pad is a ghost-pad, then peer_pad is a proxy_pad */
  parent = GST_OBJECT_PARENT (peer_pad);
  if (parent && GST_IS_GHOST_PAD (parent)) {
    peer_pad = GST_PAD_CAST (parent);
    /* if this is now the ghost pad, get the peer of this */
    get_pad_stats (self, peer_pad);
    if ((parent = GST_OBJECT_PARENT (peer_pad))) {
      get_element_stats (self, GST_ELEMENT_CAST (parent));
    }
    peer_pad = GST_PAD_PEER (GST_GHOST_PAD_CAST (peer_pad));
    parent = peer_pad ? GST_OBJECT_PARENT (peer_pad) : NULL;
  }
  /* walk the ghost pad chain upstream to get the real pad */
  /* if peer_pad is a ghost-pad, then parent is a bin and it is the parent of
   * a proxy_pad */
  while (peer_pad && GST_IS_GHOST_PAD (peer_pad)) {
    get_pad_stats (self, peer_pad);
    get_element_stats (self, GST_ELEMENT_CAST (parent));
    peer_pad = gst_ghost_pad_get_target (GST_GHOST_PAD_CAST (peer_pad));
    parent = peer_pad ? GST_OBJECT_PARENT (peer_pad) : NULL;
  }

  if (!parent) {
    printf ("%" GST_TIME_FORMAT
        " transmission on unparented target pad %s_%s -> %s_%s\n",
        GST_TIME_ARGS (elapsed), GST_DEBUG_PAD_NAME (pad),
        GST_DEBUG_PAD_NAME (peer_pad));
    return;
  }
  peer_stats = get_element_stats (self, GST_ELEMENT_CAST (parent));

  /* we'd like to gather time spend in each element, but this does not make too
   * much sense yet
   * pure push/pull-based:
   *   - the time spend in the push/pull_range is accounted for the peer and
   *     removed from the current element
   *   - this works for chains
   *   - drawback is sink elements that block to sync have a high time usage
   *     - we could rerun the ests with sync=false
   * both:
   *   - a.g. demuxers both push and pull. thus we subtract time for the pull
   *     and the push operations, but never add anything.
   *   - can we start a counter after push/pull in such elements and add then
   *     time to the element upon next pad activity?
   */
#if 1
  /* this does not make sense for demuxers */
  this_stats->treal -= elapsed;
  peer_stats->treal += elapsed;
#else
  /* this creates several >100% figures */
  this_stats->treal += GST_CLOCK_DIFF (this_stats->last_ts, elapsed2) - elapsed;
  peer_stats->treal += elapsed;
  this_stats->last_ts = elapsed2;
  peer_stats->last_ts = elapsed2;
#endif
}
Exemplo n.º 19
0
static gboolean gst_a2dp_sink_init_dynamic_elements(GstA2dpSink *self,
						GstCaps *caps)
{
	GstStructure *structure;
	GstEvent *event;
	GstPad *capsfilterpad;
	gboolean crc;
	gchar *mode = NULL;

	structure = gst_caps_get_structure(caps, 0);

	/* before everything we need to remove fakesink */
	gst_a2dp_sink_remove_fakesink(self);

	/* first, we need to create our rtp payloader */
	if (gst_structure_has_name(structure, "audio/x-sbc")) {
		GST_LOG_OBJECT(self, "sbc media received");
		if (!gst_a2dp_sink_init_rtp_sbc_element(self))
			return FALSE;
	} else if (gst_structure_has_name(structure, "audio/mpeg")) {
		GST_LOG_OBJECT(self, "mp3 media received");
		if (!gst_a2dp_sink_init_rtp_mpeg_element(self))
			return FALSE;
	} else {
		GST_ERROR_OBJECT(self, "Unexpected media type");
		return FALSE;
	}

	if (!gst_a2dp_sink_init_avdtp_sink(self))
		return FALSE;

	/* check if we should push the taglist FIXME should we push this?
	 * we can send the tags directly if needed */
	if (self->taglist != NULL &&
			gst_structure_has_name(structure, "audio/mpeg")) {

		event = gst_event_new_tag(self->taglist);

		/* send directly the crc */
		if (gst_tag_list_get_boolean(self->taglist, "has-crc", &crc))
			gst_avdtp_sink_set_crc(self->sink, crc);

		if (gst_tag_list_get_string(self->taglist, "channel-mode",
				&mode))
			gst_avdtp_sink_set_channel_mode(self->sink, mode);

		capsfilterpad = gst_ghost_pad_get_target(self->ghostpad);
		gst_pad_send_event(capsfilterpad, event);
		self->taglist = NULL;
		g_free(mode);
	}

	if (!gst_avdtp_sink_set_device_caps(self->sink, caps))
		return FALSE;

	g_object_set(G_OBJECT(self->rtp), "mtu",
		gst_avdtp_sink_get_link_mtu(self->sink), NULL);

	/* we forward our new segment here if we have one */
	if (self->newseg_event) {
		gst_pad_send_event(GST_BASE_RTP_PAYLOAD_SINKPAD(self->rtp),
					self->newseg_event);
		self->newseg_event = NULL;
	}

	return TRUE;
}
Exemplo n.º 20
0
void test_parse_bin_from_description()
{
  struct
  {
    const gchar *bin_desc;
    const gchar *pad_names;
  } bin_tests[] = {
    {
    "identity", "identity0/sink,identity0/src"}, {
    "identity ! identity ! identity", "identity1/sink,identity3/src"}, {
    "identity ! fakesink", "identity4/sink"}, {
    "fakesrc ! identity", "identity5/src"}, {
    "fakesrc ! fakesink", ""}
  };
  gint i;
  
  xmlfile = "gstutils_test_parse_bin_from_description";
  std_log(LOG_FILENAME_LINE, "Test Started gstutils_test_parse_bin_from_description");

  for (i = 0; i < G_N_ELEMENTS (bin_tests); ++i) {
    GstElement *bin, *parent;
    GString *s;
    GstPad *ghost_pad, *target_pad;
    GError *err = NULL;

    bin = gst_parse_bin_from_description (bin_tests[i].bin_desc, TRUE, &err);
    if (err) {
      g_error ("ERROR in gst_parse_bin_from_description (%s): %s",
          bin_tests[i].bin_desc, err->message);
    }
    g_assert (bin != NULL);

    s = g_string_new ("");
    if ((ghost_pad = gst_element_get_pad (bin, "sink"))) {
      g_assert (GST_IS_GHOST_PAD (ghost_pad));

      target_pad = gst_ghost_pad_get_target (GST_GHOST_PAD (ghost_pad));
      g_assert (target_pad != NULL);
      g_assert (GST_IS_PAD (target_pad));

      parent = gst_pad_get_parent_element (target_pad);
      g_assert (parent != NULL);

      g_string_append_printf (s, "%s/sink", GST_ELEMENT_NAME (parent));

      gst_object_unref (parent);
      gst_object_unref (target_pad);
      gst_object_unref (ghost_pad);
    }

    if ((ghost_pad = gst_element_get_pad (bin, "src"))) {
      g_assert (GST_IS_GHOST_PAD (ghost_pad));

      target_pad = gst_ghost_pad_get_target (GST_GHOST_PAD (ghost_pad));
      g_assert (target_pad != NULL);
      g_assert (GST_IS_PAD (target_pad));

      parent = gst_pad_get_parent_element (target_pad);
      g_assert (parent != NULL);

      if (s->len > 0) {
        g_string_append (s, ",");
      }

      g_string_append_printf (s, "%s/src", GST_ELEMENT_NAME (parent));

      gst_object_unref (parent);
      gst_object_unref (target_pad);
      gst_object_unref (ghost_pad);
    }

    if (strcmp (s->str, bin_tests[i].pad_names) != 0) {
      g_error ("FAILED: expted '%s', got '%s' for bin '%s'",
          bin_tests[i].pad_names, s->str, bin_tests[i].bin_desc);
    }
    g_string_free (s, TRUE);

    gst_object_unref (bin);
  }
  std_log(LOG_FILENAME_LINE, "Test Successful");
  create_xml(0);
}
Exemplo n.º 21
0
static GstPad *
kms_element_request_new_pad (GstElement * element,
    GstPadTemplate * templ, const gchar * name, const GstCaps * caps)
{
  GstPad *ret_pad = NULL;
  gchar *pad_name;
  gboolean added;

  KMS_ELEMENT_LOCK (element);
  if (templ ==
      gst_element_class_get_pad_template (GST_ELEMENT_CLASS (G_OBJECT_GET_CLASS
              (element)), "audio_src_%u")) {
    pad_name = g_strdup_printf ("audio_src_%d",
        KMS_ELEMENT (element)->priv->audio_pad_count++);

    ret_pad = kms_element_generate_src_pad (KMS_ELEMENT (element), pad_name,
        KMS_ELEMENT (element)->priv->audio_agnosticbin, templ);
    if (ret_pad == NULL)
      KMS_ELEMENT (element)->priv->audio_pad_count--;

    g_free (pad_name);

  } else if (templ ==
      gst_element_class_get_pad_template (GST_ELEMENT_CLASS (G_OBJECT_GET_CLASS
              (element)), "video_src_%u")) {
    pad_name = g_strdup_printf ("video_src_%d",
        KMS_ELEMENT (element)->priv->video_pad_count++);

    ret_pad = kms_element_generate_src_pad (KMS_ELEMENT (element), pad_name,
        KMS_ELEMENT (element)->priv->video_agnosticbin, templ);
    if (ret_pad == NULL)
      KMS_ELEMENT (element)->priv->video_pad_count--;

    g_free (pad_name);

  } else if (templ ==
      gst_element_class_get_pad_template (GST_ELEMENT_CLASS (G_OBJECT_GET_CLASS
              (element)), AUDIO_SINK_PAD)) {
    ret_pad =
        kms_element_generate_sink_pad (KMS_ELEMENT (element), AUDIO_SINK_PAD,
        &KMS_ELEMENT (element)->priv->audio_valve, templ);

    gst_pad_add_probe (ret_pad, GST_PAD_PROBE_TYPE_EVENT_DOWNSTREAM,
        accept_eos_probe, element, NULL);

    g_signal_connect (G_OBJECT (ret_pad), "unlinked",
        G_CALLBACK (send_flush_on_unlink), NULL);
  } else if (templ ==
      gst_element_class_get_pad_template (GST_ELEMENT_CLASS (G_OBJECT_GET_CLASS
              (element)), VIDEO_SINK_PAD)) {
    ret_pad =
        kms_element_generate_sink_pad (KMS_ELEMENT (element), VIDEO_SINK_PAD,
        &KMS_ELEMENT (element)->priv->video_valve, templ);

    gst_pad_add_probe (ret_pad, GST_PAD_PROBE_TYPE_EVENT_DOWNSTREAM,
        accept_eos_probe, element, NULL);

    g_signal_connect (G_OBJECT (ret_pad), "unlinked",
        G_CALLBACK (send_flush_on_unlink), NULL);
  }

  if (ret_pad == NULL) {
    KMS_ELEMENT_UNLOCK (element);
    GST_WARNING ("No pad created");
    return NULL;
  }

  if (GST_STATE (element) >= GST_STATE_PAUSED
      || GST_STATE_PENDING (element) >= GST_STATE_PAUSED
      || GST_STATE_TARGET (element) >= GST_STATE_PAUSED)
    gst_pad_set_active (ret_pad, TRUE);

  added = gst_element_add_pad (element, ret_pad);
  KMS_ELEMENT_UNLOCK (element);

  if (added)
    return ret_pad;

  if (gst_pad_get_direction (ret_pad) == GST_PAD_SRC) {
    GstPad *target = gst_ghost_pad_get_target (GST_GHOST_PAD (ret_pad));

    if (target != NULL) {
      GstElement *agnostic = gst_pad_get_parent_element (target);

      gst_element_release_request_pad (agnostic, target);
      g_object_unref (target);
      g_object_unref (agnostic);
    }
  }

  g_object_unref (ret_pad);
  return NULL;
}
Exemplo n.º 22
0
static void
link_sinkpad_cb (GstPad * pad, GstPad * peer, gpointer user_data)
{
  KmsRecorderEndpoint *self = KMS_RECORDER_ENDPOINT (user_data);
  KmsSinkPadData *sinkdata;
  GstAppSinkCallbacks callbacks;
  GstElement *appsink, *appsrc;
  KmsRecordingProfile profile;
  DataEvtProbe *data;
  KmsMediaType type;
  GstPad *target;
  gchar *id, *key;

  target = gst_ghost_pad_get_target (GST_GHOST_PAD (pad));
  if (target == NULL) {
    GST_ERROR_OBJECT (pad, "No target pad set");
    return;
  }

  key = g_object_get_data (G_OBJECT (target), KMS_PAD_IDENTIFIER_KEY);

  if (key == NULL) {
    GST_ERROR_OBJECT (pad, "No identifier assigned");
    g_object_unref (&target);
    return;
  }

  KMS_ELEMENT_LOCK (KMS_ELEMENT (self));

  sinkdata = g_hash_table_lookup (self->priv->sink_pad_data, key);
  if (sinkdata == NULL) {
    GST_ERROR_OBJECT (self, "Invalid pad %" GST_PTR_FORMAT " connected %"
        GST_PTR_FORMAT, pad, peer);
    goto end;
  }

  switch (sinkdata->type) {
    case KMS_ELEMENT_PAD_TYPE_AUDIO:
      type = KMS_MEDIA_TYPE_AUDIO;
      break;
    case KMS_ELEMENT_PAD_TYPE_VIDEO:
      type = KMS_MEDIA_TYPE_VIDEO;
      break;
    default:
      GST_ERROR_OBJECT (self, "Invalid pad %" GST_PTR_FORMAT " connected %"
          GST_PTR_FORMAT, pad, peer);
      goto end;
  }

  profile = self->priv->profile;

  GST_DEBUG_OBJECT (pad, "linked to %" GST_PTR_FORMAT, peer);

  id = gst_pad_get_name (pad);

  appsrc = kms_base_media_muxer_add_src (self->priv->mux, type, id);

  if (appsrc == NULL) {
    GST_ERROR_OBJECT (self, "Can not get appsrc for pad %" GST_PTR_FORMAT, pad);
    KMS_ELEMENT_UNLOCK (KMS_ELEMENT (self));
    g_object_unref (target);
    g_free (id);

    return;
  }

  g_hash_table_insert (self->priv->srcs, id, g_object_ref (appsrc));

  if (sinkdata->sink_probe != 0UL) {
    gst_pad_remove_probe (target, sinkdata->sink_probe);
  }

  callbacks.eos = recv_eos;
  callbacks.new_preroll = NULL;
  callbacks.new_sample = recv_sample;

  appsink = gst_pad_get_parent_element (target);
  gst_app_sink_set_callbacks (GST_APP_SINK (appsink), &callbacks, appsrc, NULL);
  g_object_unref (appsink);

  data = data_evt_probe_new (appsrc, profile);
  sinkdata->sink_probe =
      gst_pad_add_probe (target, GST_PAD_PROBE_TYPE_EVENT_DOWNSTREAM,
      configure_pipeline_capabilities, data,
      (GDestroyNotify) data_evt_probe_destroy);

end:
  KMS_ELEMENT_UNLOCK (KMS_ELEMENT (self));

  g_clear_object (&target);
}
Exemplo n.º 23
0
static gboolean
kms_recorder_endpoint_query_caps (KmsElement * element, GstPad * pad,
    GstQuery * query)
{
  KmsRecorderEndpoint *self = KMS_RECORDER_ENDPOINT (element);
  GstCaps *allowed = NULL, *caps = NULL;
  GstCaps *filter, *result, *tcaps;
  GstPad *target;

  target = gst_ghost_pad_get_target (GST_GHOST_PAD (pad));
  if (target == NULL) {
    GST_ERROR_OBJECT (pad, "No target pad set");
    return FALSE;
  }

  gst_query_parse_caps (query, &filter);

  switch (kms_element_get_pad_type (element, pad)) {
    case KMS_ELEMENT_PAD_TYPE_VIDEO:
      caps =
          kms_recorder_endpoint_get_caps_from_profile (self,
          KMS_ELEMENT_PAD_TYPE_VIDEO);
      result = gst_caps_from_string (KMS_AGNOSTIC_VIDEO_CAPS);
      break;
    case KMS_ELEMENT_PAD_TYPE_AUDIO:
      caps =
          kms_recorder_endpoint_get_caps_from_profile (self,
          KMS_ELEMENT_PAD_TYPE_AUDIO);
      result = gst_caps_from_string (KMS_AGNOSTIC_AUDIO_CAPS);
      break;
    default:
      GST_ERROR_OBJECT (pad, "unknown pad");
      g_object_unref (target);
      return FALSE;
  }

  allowed = gst_pad_get_allowed_caps (target);

  /* make sure we only return results that intersect our padtemplate */
  tcaps = gst_pad_get_pad_template_caps (pad);
  if (tcaps != NULL) {
    /* Update result caps */
    gst_caps_unref (result);

    if (allowed == NULL) {
      result = gst_caps_ref (tcaps);
    } else {
      result = gst_caps_intersect (allowed, tcaps);
    }
    gst_caps_unref (tcaps);
  } else {
    GST_WARNING_OBJECT (pad,
        "Can not get capabilities from pad's template. Using agnostic's' caps");
  }

  if (caps == NULL) {
    GST_ERROR_OBJECT (self, "No caps from profile");
  } else {
    GstElement *appsrc;
    GstPad *srcpad;
    gchar *id;

    id = gst_pad_get_name (pad);

    KMS_ELEMENT_LOCK (KMS_ELEMENT (self));

    appsrc = g_hash_table_lookup (self->priv->srcs, id);
    g_free (id);

    if (appsrc == NULL) {
      GstCaps *aux;

      KMS_ELEMENT_UNLOCK (KMS_ELEMENT (self));
      GST_ERROR_OBJECT (self, "No appsrc attached to pad %" GST_PTR_FORMAT,
          pad);

      /* Filter against profile */
      GST_WARNING_OBJECT (appsrc, "Using generic profile's caps");
      aux = gst_caps_intersect (caps, result);
      gst_caps_unref (result);
      result = aux;
      goto filter_caps;
    }
    srcpad = gst_element_get_static_pad (appsrc, "src");

    KMS_ELEMENT_UNLOCK (KMS_ELEMENT (self));

    /* Get encodebin's caps filtering by profile */
    tcaps = gst_pad_peer_query_caps (srcpad, caps);
    if (tcaps != NULL) {
      /* Filter against filtered encodebin's caps */
      GstCaps *aux;

      aux = gst_caps_intersect (tcaps, result);
      gst_caps_unref (result);
      gst_caps_unref (tcaps);
      result = aux;
    } else if (caps != NULL) {
      /* Filter against profile */
      GstCaps *aux;

      GST_WARNING_OBJECT (appsrc, "Using generic profile's caps");
      aux = gst_caps_intersect (caps, result);
      gst_caps_unref (result);
      result = aux;
    }

    g_object_unref (srcpad);
  }

filter_caps:

  /* filter against the query filter when needed */
  if (filter != NULL) {
    GstCaps *aux;

    aux = gst_caps_intersect (result, filter);
    gst_caps_unref (result);
    result = aux;
  }

  gst_query_set_caps_result (query, result);
  gst_caps_unref (result);

  if (allowed != NULL)
    gst_caps_unref (allowed);

  if (caps != NULL)
    gst_caps_unref (caps);

  g_object_unref (target);

  return TRUE;
}
Exemplo n.º 24
0
/*
 * debug_dump_element:
 * @bin: the bin that should be analyzed
 * @out: file to write to
 * @indent: level of graph indentation
 *
 * Helper for _gst_debug_bin_to_dot_file() to recursively dump a pipeline.
 */
static void
debug_dump_element (GstBin * bin, GstDebugGraphDetails details, FILE * out,
    const gint indent)
{
  GstIterator *element_iter, *pad_iter;
  gboolean elements_done, pads_done;
  GstElement *element, *peer_element, *target_element;
  GstPad *pad, *peer_pad, *target_pad;
  GstPadDirection dir;
  GstCaps *caps;
  GstStructure *structure;
  gboolean free_caps, free_media;
  guint src_pads, sink_pads;
  gchar *media = NULL;
  gchar *pad_name, *element_name;
  gchar *peer_pad_name, *peer_element_name;
  gchar *target_pad_name, *target_element_name;
  gchar *color_name;
  gchar *state_name = NULL;
  gchar *param_name = NULL;
  gchar *spc = NULL;

  spc = g_malloc (1 + indent * 2);
  memset (spc, 32, indent * 2);
  spc[indent * 2] = '\0';

  element_iter = gst_bin_iterate_elements (bin);
  elements_done = FALSE;
  while (!elements_done) {
    switch (gst_iterator_next (element_iter, (gpointer) & element)) {
      case GST_ITERATOR_OK:
        element_name = debug_dump_make_object_name (GST_OBJECT (element));

        if (details & GST_DEBUG_GRAPH_SHOW_STATES) {
          state_name = debug_dump_get_element_state (GST_ELEMENT (element));
        }
        if (details & GST_DEBUG_GRAPH_SHOW_NON_DEFAULT_PARAMS) {
          param_name = debug_dump_get_element_params (GST_ELEMENT (element));
        }
        /* elements */
        fprintf (out, "%ssubgraph cluster_%s {\n", spc, element_name);
        fprintf (out, "%s  fontname=\"Bitstream Vera Sans\";\n", spc);
        fprintf (out, "%s  fontsize=\"8\";\n", spc);
        fprintf (out, "%s  style=filled;\n", spc);
        fprintf (out, "%s  color=black;\n\n", spc);
        fprintf (out, "%s  label=\"<%s>\\n%s%s%s\";\n", spc,
            G_OBJECT_TYPE_NAME (element), GST_OBJECT_NAME (element),
            (state_name ? state_name : ""), (param_name ? param_name : "")
            );
        if (state_name) {
          g_free (state_name);
          state_name = NULL;
        }
        if (param_name) {
          g_free (param_name);
          param_name = NULL;
        }
        g_free (element_name);

        src_pads = sink_pads = 0;
        if ((pad_iter = gst_element_iterate_pads (element))) {
          pads_done = FALSE;
          while (!pads_done) {
            switch (gst_iterator_next (pad_iter, (gpointer) & pad)) {
              case GST_ITERATOR_OK:
                dir = gst_pad_get_direction (pad);
                pad_name = debug_dump_make_object_name (GST_OBJECT (pad));
                element_name =
                    debug_dump_make_object_name (GST_OBJECT (element));
                if (GST_IS_GHOST_PAD (pad)) {
                  color_name =
                      (dir == GST_PAD_SRC) ? "#ffdddd" : ((dir ==
                          GST_PAD_SINK) ? "#ddddff" : "#ffffff");
                } else {
                  color_name =
                      (dir == GST_PAD_SRC) ? "#ffaaaa" : ((dir ==
                          GST_PAD_SINK) ? "#aaaaff" : "#cccccc");
                }
                /* pads */
                fprintf (out,
                    "%s  %s_%s [color=black, fillcolor=\"%s\", label=\"%s\"];\n",
                    spc, element_name, pad_name, color_name,
                    GST_OBJECT_NAME (pad));

                if (dir == GST_PAD_SRC)
                  src_pads++;
                else if (dir == GST_PAD_SINK)
                  sink_pads++;
                g_free (pad_name);
                g_free (element_name);
                gst_object_unref (pad);
                break;
              case GST_ITERATOR_RESYNC:
                gst_iterator_resync (pad_iter);
                break;
              case GST_ITERATOR_ERROR:
              case GST_ITERATOR_DONE:
                pads_done = TRUE;
                break;
            }
          }
          gst_iterator_free (pad_iter);
        }
        if (GST_IS_BIN (element)) {
          fprintf (out, "%s  fillcolor=\"#ffffff\";\n", spc);
          /* recurse */
          debug_dump_element (GST_BIN (element), details, out, indent + 1);
        } else {
          if (src_pads && !sink_pads)
            fprintf (out, "%s  fillcolor=\"#ffaaaa\";\n", spc);
          else if (!src_pads && sink_pads)
            fprintf (out, "%s  fillcolor=\"#aaaaff\";\n", spc);
          else if (src_pads && sink_pads)
            fprintf (out, "%s  fillcolor=\"#aaffaa\";\n", spc);
          else
            fprintf (out, "%s  fillcolor=\"#ffffff\";\n", spc);
        }
        fprintf (out, "%s}\n\n", spc);
        if ((pad_iter = gst_element_iterate_pads (element))) {
          pads_done = FALSE;
          while (!pads_done) {
            switch (gst_iterator_next (pad_iter, (gpointer) & pad)) {
              case GST_ITERATOR_OK:
                if (gst_pad_is_linked (pad)
                    && gst_pad_get_direction (pad) == GST_PAD_SRC) {
                  if ((peer_pad = gst_pad_get_peer (pad))) {
                    free_media = FALSE;
                    if ((details & GST_DEBUG_GRAPH_SHOW_MEDIA_TYPE) ||
                        (details & GST_DEBUG_GRAPH_SHOW_CAPS_DETAILS)
                        ) {
                      if ((caps = gst_pad_get_negotiated_caps (pad))) {
                        free_caps = TRUE;
                      } else {
                        free_caps = FALSE;
                        if (!(caps = (GstCaps *)
                                gst_pad_get_pad_template_caps (pad))) {
                          /* this should not happen */
                          media = "?";
                        }
                      }
                      if (caps) {
                        if (details & GST_DEBUG_GRAPH_SHOW_CAPS_DETAILS) {
                          gchar *tmp =
                              g_strdelimit (gst_caps_to_string (caps), ",",
                              '\n');

                          media = g_strescape (tmp, NULL);
                          free_media = TRUE;
                          g_free (tmp);
                        } else {
                          if (GST_CAPS_IS_SIMPLE (caps)) {
                            structure = gst_caps_get_structure (caps, 0);
                            media =
                                (gchar *) gst_structure_get_name (structure);
                          } else
                            media = "*";
                        }
                        if (free_caps) {
                          gst_caps_unref (caps);
                        }
                      }
                    }

                    pad_name = debug_dump_make_object_name (GST_OBJECT (pad));
                    element_name =
                        debug_dump_make_object_name (GST_OBJECT (element));
                    peer_pad_name =
                        debug_dump_make_object_name (GST_OBJECT (peer_pad));
                    if ((peer_element = gst_pad_get_parent_element (peer_pad))) {
                      peer_element_name =
                          debug_dump_make_object_name (GST_OBJECT
                          (peer_element));
                    } else {
                      peer_element_name = "";
                    }
                    /* pad link */
                    if (media) {
                      fprintf (out, "%s%s_%s -> %s_%s [label=\"%s\"]\n", spc,
                          element_name, pad_name, peer_element_name,
                          peer_pad_name, media);
                      if (free_media) {
                        g_free (media);
                      }
                    } else {
                      fprintf (out, "%s%s_%s -> %s_%s\n", spc,
                          element_name, pad_name, peer_element_name,
                          peer_pad_name);
                    }

                    if (GST_IS_GHOST_PAD (pad)) {
                      if ((target_pad =
                              gst_ghost_pad_get_target (GST_GHOST_PAD (pad)))) {
                        target_pad_name =
                            debug_dump_make_object_name (GST_OBJECT
                            (target_pad));
                        if ((target_element =
                                gst_pad_get_parent_element (target_pad))) {
                          target_element_name =
                              debug_dump_make_object_name (GST_OBJECT
                              (target_element));
                        } else {
                          target_element_name = "";
                        }
                        /* src ghostpad relationship */
                        fprintf (out, "%s%s_%s -> %s_%s [style=dashed]\n", spc,
                            target_element_name, target_pad_name, element_name,
                            pad_name);

                        g_free (target_pad_name);
                        if (target_element) {
                          g_free (target_element_name);
                          gst_object_unref (target_element);
                        }
                        gst_object_unref (target_pad);
                      }
                    }
                    if (GST_IS_GHOST_PAD (peer_pad)) {
                      if ((target_pad =
                              gst_ghost_pad_get_target (GST_GHOST_PAD
                                  (peer_pad)))) {
                        target_pad_name =
                            debug_dump_make_object_name (GST_OBJECT
                            (target_pad));
                        if ((target_element =
                                gst_pad_get_parent_element (target_pad))) {
                          target_element_name =
                              debug_dump_make_object_name (GST_OBJECT
                              (target_element));
                        } else {
                          target_element_name = "";
                        }
                        /* sink ghostpad relationship */
                        fprintf (out, "%s%s_%s -> %s_%s [style=dashed]\n", spc,
                            peer_element_name, peer_pad_name,
                            target_element_name, target_pad_name);

                        g_free (target_pad_name);
                        if (target_element) {
                          g_free (target_element_name);
                          gst_object_unref (target_element);
                        }
                        gst_object_unref (target_pad);
                      }
                    }

                    g_free (pad_name);
                    g_free (element_name);
                    g_free (peer_pad_name);
                    if (peer_element) {
                      g_free (peer_element_name);
                      gst_object_unref (peer_element);
                    }
                    gst_object_unref (peer_pad);
                  }
                }
                gst_object_unref (pad);
                break;
              case GST_ITERATOR_RESYNC:
                gst_iterator_resync (pad_iter);
                break;
              case GST_ITERATOR_ERROR:
              case GST_ITERATOR_DONE:
                pads_done = TRUE;
                break;
            }
          }
          gst_iterator_free (pad_iter);
        }
        gst_object_unref (element);
        break;
      case GST_ITERATOR_RESYNC:
        gst_iterator_resync (element_iter);
        break;
      case GST_ITERATOR_ERROR:
      case GST_ITERATOR_DONE:
        elements_done = TRUE;
        break;
    }
  }
  gst_iterator_free (element_iter);
  g_free (spc);
}