static void
gst_insert_bin_block_pad_unlock (GstInsertBin * self)
{
  struct ChangeData *data;
  GstPad *pad;
  GstPadProbeType probetype;

again:

  data = g_queue_peek_head (&self->priv->change_queue);
  if (!data) {
    GST_OBJECT_UNLOCK (self);
    return;
  }

  if (data->action == GST_INSERT_BIN_ACTION_ADD &&
      !validate_element (self, data->element))
    goto error;

  if (data->action == GST_INSERT_BIN_ACTION_ADD) {
    if (data->sibling) {
      if (data->direction == DIRECTION_BEFORE)
        pad = get_single_pad (data->sibling, GST_PAD_SINK);
      else
        pad = get_single_pad (data->sibling, GST_PAD_SRC);
    } else {
      if (data->direction == DIRECTION_BEFORE)
        pad = (GstPad *)
            gst_proxy_pad_get_internal (GST_PROXY_PAD (self->priv->srcpad));
      else
        pad = (GstPad *)
            gst_proxy_pad_get_internal (GST_PROXY_PAD (self->priv->sinkpad));
    }

    if (!pad) {
      GST_WARNING_OBJECT (self, "Can not obtain a sibling pad to block"
          " before adding");
      goto error;
    }

    if (!is_right_direction_for_block (pad)) {
      GstPad *peer = gst_pad_get_peer (pad);

      if (peer) {
        gst_object_unref (pad);
        pad = peer;
      }
    }
  } else {
    GstPad *element_pad;

    element_pad = get_single_pad (data->element, GST_PAD_SINK);
    if (!element_pad) {
      GST_WARNING_OBJECT (self, "Can not obtain the element's sink pad");
      goto error;
    }

    if (!is_right_direction_for_block (element_pad)) {
      pad = gst_pad_get_peer (element_pad);
    } else {
      gst_object_unref (element_pad);

      element_pad = get_single_pad (data->element, GST_PAD_SRC);
      if (!element_pad) {
        GST_WARNING_OBJECT (self, "Can not obtain the element's src pad");
        goto error;
      }

      pad = gst_pad_get_peer (element_pad);
    }
    gst_object_unref (element_pad);

    if (!pad) {
      GST_WARNING_OBJECT (self, "Can not obtain a sibling pad for removing");
      goto error;
    }
  }

  if (GST_PAD_IS_SRC (pad))
    probetype = GST_PAD_PROBE_TYPE_BLOCK_DOWNSTREAM;
  else
    probetype = GST_PAD_PROBE_TYPE_BLOCK_UPSTREAM;

  GST_OBJECT_UNLOCK (self);
  gst_pad_add_probe (pad, GST_PAD_PROBE_TYPE_IDLE | probetype, pad_blocked_cb,
      self, NULL);
  gst_object_unref (pad);
  return;

error:
  g_queue_pop_head (&self->priv->change_queue);
  gst_insert_bin_change_data_complete (self, data, FALSE);
  goto again;
}
Beispiel #2
0
static void
kms_agnostic_bin2_link_to_tee (KmsAgnosticBin2 * self, GstPad * pad,
    GstElement * tee, GstCaps * caps)
{
  GstElement *queue = gst_element_factory_make ("queue", NULL);
  GstPad *target;
  GstProxyPad *proxy;

  gst_bin_add (GST_BIN (self), queue);
  gst_element_sync_state_with_parent (queue);

  if (!(gst_caps_is_any (caps) || gst_caps_is_empty (caps))
      && kms_utils_caps_are_raw (caps)) {
    GstElement *convert = kms_utils_create_convert_for_caps (caps);
    GstElement *rate = kms_utils_create_rate_for_caps (caps);
    GstElement *mediator = kms_utils_create_mediator_element (caps);

    if (kms_utils_caps_are_video (caps)) {
      g_object_set (queue, "leaky", 2, "max-size-time", LEAKY_TIME, NULL);
    }

    remove_element_on_unlinked (convert, "src", "sink");
    if (rate) {
      remove_element_on_unlinked (rate, "src", "sink");
    }
    remove_element_on_unlinked (mediator, "src", "sink");

    if (rate) {
      gst_bin_add (GST_BIN (self), rate);
    }

    gst_bin_add_many (GST_BIN (self), convert, mediator, NULL);

    gst_element_sync_state_with_parent (mediator);
    gst_element_sync_state_with_parent (convert);
    if (rate) {
      gst_element_sync_state_with_parent (rate);
    }

    if (rate) {
      gst_element_link_many (queue, rate, mediator, NULL);
    } else {
      gst_element_link (queue, mediator);
    }

    gst_element_link_many (mediator, convert, NULL);
    target = gst_element_get_static_pad (convert, "src");
  } else {
    target = gst_element_get_static_pad (queue, "src");
  }

  gst_ghost_pad_set_target (GST_GHOST_PAD (pad), target);

  proxy = gst_proxy_pad_get_internal (GST_PROXY_PAD (pad));
  gst_pad_set_query_function (GST_PAD_CAST (proxy),
      proxy_src_pad_query_function);
  g_object_unref (proxy);

  g_object_unref (target);
  link_element_to_tee (tee, queue);
}