Esempio n. 1
0
/* Stolen from gst-plugins-good/ext/gconf/gconf.c */
static GstPad *
my_gst_bin_find_unconnected_pad (GstBin * bin, GstPadDirection direction)
{
  GstPad *pad = NULL;
  GList *elements = NULL;
  const GList *pads = NULL;
  GstElement *element = NULL;

  GST_OBJECT_LOCK (bin);
  elements = bin->children;
  /* traverse all elements looking for unconnected pads */
  while (elements && pad == NULL) {
    element = GST_ELEMENT (elements->data);
    GST_OBJECT_LOCK (element);
    pads = element->pads;
    while (pads) {
      GstPad *testpad = GST_PAD (pads->data);

      /* check if the direction matches */
      if (GST_PAD_DIRECTION (testpad) == direction) {
        GST_OBJECT_LOCK (testpad);
        if (GST_PAD_PEER (testpad) == NULL) {
          GST_OBJECT_UNLOCK (testpad);
          /* found it ! */
          pad = testpad;
          break;
        }
        GST_OBJECT_UNLOCK (testpad);
      }
      pads = g_list_next (pads);
    }
    GST_OBJECT_UNLOCK (element);
    elements = g_list_next (elements);
  }
  GST_OBJECT_UNLOCK (bin);

  return pad;
}
Esempio n. 2
0
static gboolean
gst_ghost_pad_internal_activate_pull_default (GstPad * pad, GstObject * parent,
    gboolean active)
{
  gboolean ret;
  GstPad *other;

  GST_LOG_OBJECT (pad, "%sactivate pull on %s:%s", (active ? "" : "de"),
      GST_DEBUG_PAD_NAME (pad));

  if (GST_PAD_DIRECTION (pad) == GST_PAD_SRC) {
    /* we are activated in pull mode by our peer element, which is a sinkpad
     * that wants to operate in pull mode. This activation has to propagate
     * upstream through the pipeline. We call the internal activation function,
     * which will trigger gst_ghost_pad_activate_pull_default, which propagates even
     * further upstream */
    GST_LOG_OBJECT (pad, "pad is src, activate internal");
    GST_PROXY_PAD_ACQUIRE_INTERNAL (pad, other, FALSE);
    ret = gst_pad_activate_mode (other, GST_PAD_MODE_PULL, active);
    GST_PROXY_PAD_RELEASE_INTERNAL (other);
  } else if (G_LIKELY ((other = gst_pad_get_peer (pad)))) {
    /* We are SINK, the ghostpad is SRC, we propagate the activation upstream
     * since we hold a pointer to the upstream peer. */
    GST_LOG_OBJECT (pad, "activating peer");
    ret = gst_pad_activate_mode (other, GST_PAD_MODE_PULL, active);
    gst_object_unref (other);
  } else if (active) {
    /* this is failure, we can't activate pull if there is no peer */
    GST_LOG_OBJECT (pad, "not src and no peer, failing");
    ret = FALSE;
  } else {
    GST_LOG_OBJECT (pad, "deactivating pull, with no peer - allowing");
    ret = TRUE;
  }

  return ret;
}
Esempio n. 3
0
/* Clean up output/input pad and respective selector request pad */
void
cleanup_pad (GstPad * pad, GstElement * element)
{
    GstPad *selpad = NULL;
    guint probe_id = 0;

    fail_if (pad == NULL, "pad doesn't exist");

    /* remove probe if necessary */
    probe_id = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (pad), "probe_id"));
    if (probe_id)
        gst_pad_remove_data_probe (pad, probe_id);

    /* unlink */
    selpad = gst_pad_get_peer (pad);
    if (GST_PAD_DIRECTION (selpad) == GST_PAD_SRC) {
        gst_pad_unlink (selpad, pad);
    } else {
        gst_pad_unlink (pad, selpad);
    }

    /* caps could have been set, make sure they get unset */
    gst_pad_set_caps (pad, NULL);

    GST_DEBUG_OBJECT (pad, "clean up %" GST_PTR_FORMAT " and  %" GST_PTR_FORMAT,
                      selpad, pad);

    /* cleanup the pad */
    gst_pad_set_active (pad, FALSE);
    ASSERT_OBJECT_REFCOUNT (pad, "pad", 1);
    gst_object_unref (pad);

    /* cleanup selector pad, reffed by this function (_get_peer) and creator */
    gst_element_release_request_pad (element, selpad);
    gst_object_unref (selpad);
}
Esempio n. 4
0
static GstCaps *
gst_deinterleave_sink_getcaps (GstPad * pad)
{
  GstDeinterleave *self = GST_DEINTERLEAVE (gst_pad_get_parent (pad));

  GstCaps *ret;

  GList *l;

  GST_OBJECT_LOCK (self);
  /* Intersect all of our pad template caps with the peer caps of the pad
   * to get all formats that are possible up- and downstream.
   *
   * For the pad for which the caps are requested we don't remove the channel
   * informations as they must be in the returned caps and incompatibilities
   * will be detected here already
   */
  ret = gst_caps_new_any ();
  for (l = GST_ELEMENT (self)->pads; l != NULL; l = l->next) {
    GstPad *ourpad = GST_PAD (l->data);

    GstCaps *peercaps = NULL, *ourcaps;

    ourcaps = gst_caps_copy (gst_pad_get_pad_template_caps (ourpad));

    if (pad == ourpad) {
      if (GST_PAD_DIRECTION (pad) == GST_PAD_SINK)
        __set_channels (ourcaps, self->channels);
      else
        __set_channels (ourcaps, 1);
    } else {
      __remove_channels (ourcaps);
      /* Only ask for peer caps for other pads than pad
       * as otherwise gst_pad_peer_get_caps() might call
       * back into this function and deadlock
       */
      peercaps = gst_pad_peer_get_caps (ourpad);
    }

    /* If the peer exists and has caps add them to the intersection,
     * otherwise assume that the peer accepts everything */
    if (peercaps) {
      GstCaps *intersection;

      GstCaps *oldret = ret;

      __remove_channels (peercaps);

      intersection = gst_caps_intersect (peercaps, ourcaps);

      ret = gst_caps_intersect (ret, intersection);
      gst_caps_unref (intersection);
      gst_caps_unref (peercaps);
      gst_caps_unref (oldret);
    } else {
      GstCaps *oldret = ret;

      ret = gst_caps_intersect (ret, ourcaps);
      gst_caps_unref (oldret);
    }
    gst_caps_unref (ourcaps);
  }
  GST_OBJECT_UNLOCK (self);

  gst_object_unref (self);

  GST_DEBUG_OBJECT (pad, "Intersected caps to %" GST_PTR_FORMAT, ret);

  return ret;
}
/* Fetches a compatible pad on the target element which isn't already
 * linked */
static GstPad *
get_compatible_unlinked_pad (GstElement * element, GstPad * pad)
{
  GstPad *res = NULL;
  GstIterator *pads;
  gboolean done = FALSE;
  GstCaps *srccaps;

  if (G_UNLIKELY (pad == NULL))
    goto no_pad;

  GST_DEBUG ("element : %s, pad %s:%s",
      GST_ELEMENT_NAME (element), GST_DEBUG_PAD_NAME (pad));

  if (GST_PAD_DIRECTION (pad) == GST_PAD_SRC)
    pads = gst_element_iterate_sink_pads (element);
  else
    pads = gst_element_iterate_src_pads (element);
  srccaps = gst_pad_get_caps_reffed (pad);

  GST_DEBUG ("srccaps %" GST_PTR_FORMAT, srccaps);

  while (!done) {
    gpointer padptr;

    switch (gst_iterator_next (pads, &padptr)) {
      case GST_ITERATOR_OK:
      {
        GstPad *testpad = (GstPad *) padptr;

        if (gst_pad_is_linked (testpad)) {
          gst_object_unref (testpad);
        } else {
          GstCaps *sinkcaps = gst_pad_get_caps_reffed (testpad);

          GST_DEBUG ("sinkccaps %" GST_PTR_FORMAT, sinkcaps);

          if (gst_caps_can_intersect (srccaps, sinkcaps)) {
            res = testpad;
            done = TRUE;
          } else
            gst_object_unref (testpad);
          gst_caps_unref (sinkcaps);
        }
      }
        break;
      case GST_ITERATOR_DONE:
      case GST_ITERATOR_ERROR:
        done = TRUE;
        break;
      case GST_ITERATOR_RESYNC:
        gst_iterator_resync (pads);
        break;
    }
  }
  gst_iterator_free (pads);
  gst_caps_unref (srccaps);

  return res;

no_pad:
  {
    GST_ERROR ("No pad to check against");
    return NULL;
  }
}