Example #1
0
static GstElement *
gst_switch_select (GstSwitch * swit,
    GstPadTemplate * templ, const gchar * name, const GstCaps * caps)
{
  GList *item = GST_BIN_CHILDREN (GST_BIN (swit));
  GstElement *swcase = NULL;

  for (; item; item = g_list_next (item)) {
    GList *paditem = GST_ELEMENT_PADS (GST_ELEMENT (item->data));
    GstPad *basepad = NULL, *pad = NULL;
    for (; paditem; paditem = g_list_next (paditem)) {
      pad = GST_PAD (paditem->data);
      if (GST_PAD_IS_SINK (pad) && !gst_pad_is_linked (pad) &&
          !GST_OBJECT_FLAG_IS_SET (GST_OBJECT (pad),
              GST_SWITCH_PAD_FLAG_GHOSTED)) {
        basepad = pad;
        break;
      }
    }

    if (basepad) {
      swcase = GST_ELEMENT (item->data);
      break;
    }
  }

  if (!swcase) {
    swcase = gst_switch_request_new_case (swit, templ, caps);
  }

  return swcase;
}
static void
pad_removed (GstElement * element, GstPad * pad, KmsPlayerEndPoint * self)
{
  GST_DEBUG ("Pad removed");
  GstElement *appsink, *appsrc;

  if (GST_PAD_IS_SINK (pad))
    return;

  appsink = g_object_steal_data (G_OBJECT (pad), APPSINK_DATA);
  appsrc = g_object_steal_data (G_OBJECT (pad), APPSRC_DATA);

  if (appsrc != NULL) {
    GST_INFO ("Removing %" GST_PTR_FORMAT " from its parent", appsrc);
    if (GST_OBJECT_PARENT (appsrc) != NULL) {
      g_object_ref (appsrc);
      gst_bin_remove (GST_BIN (GST_OBJECT_PARENT (appsrc)), appsrc);
      gst_element_set_state (appsrc, GST_STATE_NULL);
      g_object_unref (appsrc);
    }
  }

  if (appsink == NULL) {
    GST_ERROR ("No appsink was found associated with %" GST_PTR_FORMAT, pad);
    return;
  }
  if (!gst_element_set_locked_state (appsink, TRUE))
    GST_ERROR ("Could not block element %s", GST_ELEMENT_NAME (appsink));

  GST_DEBUG ("Removing appsink %s from %s", GST_ELEMENT_NAME (appsink),
      GST_ELEMENT_NAME (self->priv->pipeline));

  gst_element_set_state (appsink, GST_STATE_NULL);
  gst_bin_remove (GST_BIN (self->priv->pipeline), appsink);
}
static gboolean
gst_vaapidecode_query (GstPad * pad, GstObject * parent, GstQuery * query)
{
  GstVaapiDecode *const decode =
      GST_VAAPIDECODE (gst_pad_get_parent_element (pad));
  GstVideoDecoder *const vdec = GST_VIDEO_DECODER (decode);
  gboolean res;

  GST_INFO_OBJECT (decode, "query type %s on %s pad",
      GST_QUERY_TYPE_NAME (query), GST_PAD_IS_SINK (pad) ? "sink" : "src");

  if (GST_PAD_IS_SINK (pad))
    res = gst_vaapidecode_sink_query (vdec, query);
  else
    res = gst_vaapidecode_src_query (vdec, query);

  gst_object_unref (vdec);
  return res;
}
Example #4
0
static int
gst_ffmpegdata_open (URLContext * h, const char *filename, int flags)
{
    GstProtocolInfo *info;
    GstPad *pad;

    GST_LOG ("Opening %s", filename);

    info = g_new0 (GstProtocolInfo, 1);

    info->set_streamheader = flags & GST_FFMPEG_URL_STREAMHEADER;
    flags &= ~GST_FFMPEG_URL_STREAMHEADER;
    h->flags &= ~GST_FFMPEG_URL_STREAMHEADER;

    /* we don't support R/W together */
    if (flags != URL_RDONLY && flags != URL_WRONLY) {
        GST_WARNING ("Only read-only or write-only are supported");
        return -EINVAL;
    }

    if (sscanf (&filename[12], "%p", &pad) != 1) {
        GST_WARNING ("could not decode pad from %s", filename);
        return -EIO;
    }

    /* make sure we're a pad and that we're of the right type */
    g_return_val_if_fail (GST_IS_PAD (pad), -EINVAL);

    switch (flags) {
    case URL_RDONLY:
        g_return_val_if_fail (GST_PAD_IS_SINK (pad), -EINVAL);
        break;
    case URL_WRONLY:
        g_return_val_if_fail (GST_PAD_IS_SRC (pad), -EINVAL);
        break;
    }

    info->eos = FALSE;
    info->pad = pad;
    info->offset = 0;

    h->priv_data = (void *) info;
    h->is_streamed = FALSE;
    h->max_packet_size = 0;

    return 0;
}
Example #5
0
/**
 * gst_collect_pads_add_pad_full:
 * @pads: the collectspads to use
 * @pad: the pad to add
 * @size: the size of the returned #GstCollectData structure
 * @destroy_notify: function to be called before the returned #GstCollectData
 * structure is freed
 *
 * Add a pad to the collection of collect pads. The pad has to be
 * a sinkpad. The refcount of the pad is incremented. Use
 * gst_collect_pads_remove_pad() to remove the pad from the collection
 * again.
 *
 * You specify a size for the returned #GstCollectData structure
 * so that you can use it to store additional information.
 *
 * You can also specify a #GstCollectDataDestroyNotify that will be called
 * just before the #GstCollectData structure is freed. It is passed the
 * pointer to the structure and should free any custom memory and resources
 * allocated for it.
 *
 * The pad will be automatically activated in push mode when @pads is
 * started.
 *
 * Since: 0.10.12
 *
 * Returns: a new #GstCollectData to identify the new pad. Or NULL
 *   if wrong parameters are supplied.
 *
 * MT safe.
 */
GstCollectData *
gst_collect_pads_add_pad_full (GstCollectPads * pads, GstPad * pad, guint size,
    GstCollectDataDestroyNotify destroy_notify)
{
  GstCollectData *data;

  g_return_val_if_fail (pads != NULL, NULL);
  g_return_val_if_fail (GST_IS_COLLECT_PADS (pads), NULL);
  g_return_val_if_fail (pad != NULL, NULL);
  g_return_val_if_fail (GST_PAD_IS_SINK (pad), NULL);
  g_return_val_if_fail (size >= sizeof (GstCollectData), NULL);

  GST_DEBUG ("adding pad %s:%s", GST_DEBUG_PAD_NAME (pad));

  data = g_malloc0 (size);
  data->collect = pads;
  data->pad = gst_object_ref (pad);
  data->buffer = NULL;
  data->pos = 0;
  gst_segment_init (&data->segment, GST_FORMAT_UNDEFINED);
  data->abidata.ABI.flushing = FALSE;
  data->abidata.ABI.new_segment = FALSE;
  data->abidata.ABI.eos = FALSE;
  data->abidata.ABI.refcount = 1;

  /* FIXME: Ugly hack as we can't add more fields to GstCollectData */
  g_object_set_data (G_OBJECT (pad), "gst-collect-data-destroy-notify",
      (void *) destroy_notify);

  GST_COLLECT_PADS_PAD_LOCK (pads);
  GST_OBJECT_LOCK (pad);
  gst_pad_set_element_private (pad, data);
  GST_OBJECT_UNLOCK (pad);
  pads->abidata.ABI.pad_list =
      g_slist_append (pads->abidata.ABI.pad_list, data);
  gst_pad_set_chain_function (pad, GST_DEBUG_FUNCPTR (gst_collect_pads_chain));
  gst_pad_set_event_function (pad, GST_DEBUG_FUNCPTR (gst_collect_pads_event));
  /* activate the pad when needed */
  if (pads->started)
    gst_pad_set_active (pad, TRUE);
  pads->abidata.ABI.pad_cookie++;
  GST_COLLECT_PADS_PAD_UNLOCK (pads);

  return data;
}
static void
post_decodebin_pad_removed_handler (GstElement * decodebin, GstPad * pad,
    KmsHttpEndpoint * self)
{
  GstElement *appsink, *appsrc;
  GstPad *sinkpad;

  if (GST_PAD_IS_SINK (pad))
    return;

  GST_DEBUG ("pad %" GST_PTR_FORMAT " removed", pad);

  appsink = g_object_steal_qdata (G_OBJECT (pad), appsink_data_quark ());

  if (appsink == NULL) {
    GST_ERROR ("No appsink was found associated with %" GST_PTR_FORMAT, pad);
    return;
  }

  sinkpad = gst_element_get_static_pad (appsink, "sink");
  appsrc = g_object_get_qdata (G_OBJECT (sinkpad), appsrc_data_quark ());
  g_object_unref (sinkpad);

  if (!gst_element_set_locked_state (appsink, TRUE))
    GST_ERROR ("Could not block element %s", GST_ELEMENT_NAME (appsink));

  GST_DEBUG ("Removing appsink %s from %s", GST_ELEMENT_NAME (appsink),
      GST_ELEMENT_NAME (self->pipeline));

  gst_element_set_state (appsink, GST_STATE_NULL);
  gst_bin_remove (GST_BIN (self->pipeline), appsink);

  if (appsrc == NULL) {
    GST_ERROR ("No appsink was found associated with %" GST_PTR_FORMAT, pad);
    return;
  }

  if (GST_OBJECT_PARENT (appsrc) != NULL) {
    g_object_ref (appsrc);
    gst_bin_remove (GST_BIN (GST_OBJECT_PARENT (appsrc)), appsrc);
    gst_element_set_state (appsrc, GST_STATE_NULL);
    g_object_unref (appsrc);
  }
}
static void
gst_rtp_mux_dispose (GObject * object)
{
  GstRTPMux *rtp_mux = GST_RTP_MUX (object);
  GList *item;

  g_clear_object (&rtp_mux->last_pad);

restart:
  for (item = GST_ELEMENT_PADS (object); item; item = g_list_next (item)) {
    GstPad *pad = GST_PAD (item->data);
    if (GST_PAD_IS_SINK (pad)) {
      gst_element_release_request_pad (GST_ELEMENT (object), pad);
      goto restart;
    }
  }

  G_OBJECT_CLASS (gst_rtp_mux_parent_class)->dispose (object);
}
Example #8
0
static void
fs_funnel_dispose (GObject * object)
{
  GList *item;

 restart:
  for (item = GST_ELEMENT_PADS (object); item; item = g_list_next (item))
  {
    GstPad *pad = GST_PAD (item->data);

    if (GST_PAD_IS_SINK (pad))
    {
      gst_element_release_request_pad (GST_ELEMENT (object), pad);
      goto restart;
    }
  }

  G_OBJECT_CLASS (parent_class)->dispose (object);
}
static gboolean
gst_vaapiencode_query (GstPad * pad, GstObject * parent, GstQuery * query)
{
  GstVaapiPluginBase *const plugin =
      GST_VAAPI_PLUGIN_BASE (gst_pad_get_parent_element (pad));
  gboolean success;

  GST_INFO_OBJECT (plugin, "query type %s", GST_QUERY_TYPE_NAME (query));

  if (gst_vaapi_reply_to_query (query, plugin->display))
    success = TRUE;
  else if (GST_PAD_IS_SINK (pad))
    success = plugin->sinkpad_query (plugin->sinkpad, parent, query);
  else
    success = plugin->srcpad_query (plugin->srcpad, parent, query);

  gst_object_unref (plugin);
  return success;
}
Example #10
0
/**
 * gst_proxy_pad_save_thyself:
 * @pad: a ghost #GstPad to save.
 * @parent: the parent #xmlNodePtr to save the description in.
 *
 * Saves the ghost pad into an xml representation.
 *
 * Returns: the #xmlNodePtr representation of the pad.
 */
static xmlNodePtr
gst_proxy_pad_save_thyself (GstObject * object, xmlNodePtr parent)
{
  xmlNodePtr self;
  GstProxyPad *proxypad;
  GstPad *pad;
  GstPad *peer;

  g_return_val_if_fail (GST_IS_PROXY_PAD (object), NULL);

  self = xmlNewChild (parent, NULL, (xmlChar *) "ghostpad", NULL);
  xmlNewChild (self, NULL, (xmlChar *) "name",
      (xmlChar *) GST_OBJECT_NAME (object));
  xmlNewChild (self, NULL, (xmlChar *) "parent",
      (xmlChar *) GST_OBJECT_NAME (GST_OBJECT_PARENT (object)));

  proxypad = GST_PROXY_PAD_CAST (object);
  pad = GST_PAD_CAST (proxypad);
  peer = GST_PAD_CAST (pad->peer);

  if (GST_IS_PAD (pad)) {
    if (GST_PAD_IS_SRC (pad))
      xmlNewChild (self, NULL, (xmlChar *) "direction", (xmlChar *) "source");
    else if (GST_PAD_IS_SINK (pad))
      xmlNewChild (self, NULL, (xmlChar *) "direction", (xmlChar *) "sink");
    else
      xmlNewChild (self, NULL, (xmlChar *) "direction", (xmlChar *) "unknown");
  } else {
    xmlNewChild (self, NULL, (xmlChar *) "direction", (xmlChar *) "unknown");
  }
  if (GST_IS_PAD (peer)) {
    gchar *content = g_strdup_printf ("%s.%s",
        GST_OBJECT_NAME (GST_PAD_PARENT (peer)), GST_PAD_NAME (peer));

    xmlNewChild (self, NULL, (xmlChar *) "peer", (xmlChar *) content);
    g_free (content);
  } else {
    xmlNewChild (self, NULL, (xmlChar *) "peer", NULL);
  }

  return self;
}
Example #11
0
static void
gst_funnel_dispose (GObject * object)
{
  GstFunnel *funnel = GST_FUNNEL (object);
  GList *item;

  gst_object_replace ((GstObject **) & funnel->last_sinkpad, NULL);

restart:
  for (item = GST_ELEMENT_PADS (object); item; item = g_list_next (item)) {
    GstPad *pad = GST_PAD (item->data);

    if (GST_PAD_IS_SINK (pad)) {
      gst_element_release_request_pad (GST_ELEMENT (object), pad);
      goto restart;
    }
  }

  G_OBJECT_CLASS (parent_class)->dispose (object);
}
Example #12
0
/*
 * This function sends a dummy event to force blocked probe to be called
 */
static void
send_dummy_event (GstPad * pad, const gchar * name)
{
  GstElement *parent = gst_pad_get_parent_element (pad);

  if (parent == NULL) {
    return;
  }

  if (GST_PAD_IS_SINK (pad)) {
    gst_pad_send_event (pad,
        gst_event_new_custom (GST_EVENT_TYPE_DOWNSTREAM |
            GST_EVENT_TYPE_SERIALIZED, gst_structure_new_empty (name)));
  } else {
    gst_pad_send_event (pad,
        gst_event_new_custom (GST_EVENT_TYPE_UPSTREAM |
            GST_EVENT_TYPE_SERIALIZED, gst_structure_new_empty (name)));
  }

  g_object_unref (parent);
}
Example #13
0
static GstElement *
setup_multiqueue (GstElement * pipe, GstElement * inputs[],
    GstElement * outputs[], guint num)
{
  GstElement *mq;
  guint i;

  mq = gst_element_factory_make ("multiqueue", NULL);
  fail_unless (mq != NULL, "failed to create 'multiqueue' element");

  gst_bin_add (GST_BIN (pipe), mq);

  for (i = 0; i < num; ++i) {
    GstPad *sinkpad = NULL;
    GstPad *srcpad = NULL;

    /* create multiqueue sink (and source) pad */
    sinkpad = gst_element_get_request_pad (mq, "sink%d");
    fail_unless (sinkpad != NULL,
        "failed to create multiqueue request pad #%u", i);

    /* link input element N to the N-th multiqueue sink pad we just created */
    if (inputs != NULL && inputs[i] != NULL) {
      gst_bin_add (GST_BIN (pipe), inputs[i]);

      srcpad = gst_element_get_static_pad (inputs[i], "src");
      fail_unless (srcpad != NULL, "failed to find src pad for input #%u", i);

      fail_unless_equals_int (GST_PAD_LINK_OK, gst_pad_link (srcpad, sinkpad));

      gst_object_unref (srcpad);
      srcpad = NULL;
    }
    gst_object_unref (sinkpad);
    sinkpad = NULL;

    /* link output element N to the N-th multiqueue src pad */
    if (outputs != NULL && outputs[i] != NULL) {
      gchar padname[10];

      /* only the sink pads are by request, the source pads are sometimes pads,
       * so this should return NULL */
      srcpad = gst_element_get_request_pad (mq, "src%d");
      fail_unless (srcpad == NULL);

      g_snprintf (padname, sizeof (padname), "src%d", i);
      srcpad = gst_element_get_static_pad (mq, padname);
      fail_unless (srcpad != NULL, "failed to get multiqueue src pad #%u", i);
      fail_unless (GST_PAD_IS_SRC (srcpad),
          "%s:%s is not a source pad?!", GST_DEBUG_PAD_NAME (srcpad));

      gst_bin_add (GST_BIN (pipe), outputs[i]);

      sinkpad = gst_element_get_static_pad (outputs[i], "sink");
      fail_unless (sinkpad != NULL, "failed to find sink pad of output #%u", i);
      fail_unless (GST_PAD_IS_SINK (sinkpad));

      fail_unless_equals_int (GST_PAD_LINK_OK, gst_pad_link (srcpad, sinkpad));

      gst_object_unref (srcpad);
      gst_object_unref (sinkpad);
    }
  }

  return mq;
}
static gboolean
check_and_remove_input_selector_counters (GstElement * element,
    gchar ** error_message)
{
  GstIterator *iterator;
  gboolean done = FALSE;
  GstPad *pad;
  GValue value = { 0, };
  guint id, ncounters = 0, total_sink_count = 0;
  BufferCountData *bcd, **bcds =
      g_malloc0 (sizeof (BufferCountData *) * element->numpads);
  gboolean ret = TRUE;

  /* First gather all counts, and free memory, etc */
  iterator = gst_element_iterate_pads (element);
  while (!done) {
    switch (gst_iterator_next (iterator, &value)) {
      case GST_ITERATOR_OK:
        pad = g_value_get_object (&value);
        bcd = g_object_get_data (G_OBJECT (pad), "buffer-count-data");
        if (GST_PAD_IS_SINK (pad)) {
          bcds[++ncounters] = bcd;
          total_sink_count += bcd->counter;
        } else {
          bcds[0] = bcd;
        }
        gst_pad_remove_probe (pad, bcd->probe_id);
        g_value_reset (&value);
        break;
      case GST_ITERATOR_RESYNC:
        gst_iterator_resync (iterator);
        break;
      case GST_ITERATOR_ERROR:
        done = TRUE;
        *error_message = g_strdup ("Failed to iterate through pads");
        ret = FALSE;
        break;
      case GST_ITERATOR_DONE:
        done = TRUE;
        break;
    }
  }
  gst_iterator_free (iterator);

  if (!ret) {
    g_free (bcds);
    return FALSE;
  }

  /* Now bcd[0] contains the total number of buffers received,
     and subsequent bcd slots contain the total number of buffers sent
     by each source pad. Check that the totals match, and that every
     source pad got at least one buffer.
     Or that's the theory. It doesn't work in practice, the number of
     raw buffers flowing is non deterministic. */
#if 0
  if (bcds[0]->counter != total_sink_count) {
    *error_message = g_strdup_printf ("%u buffers received, %u buffers sent",
        total_sink_count, bcds[0]->counter);
    ret = FALSE;
  }
  for (id = 1; id < element->numpads; ++id) {
    if (bcds[id]->counter == 0) {
      *error_message =
          g_strdup_printf ("Sink pad %s got no buffers",
          GST_PAD_NAME (bcds[id]->pad));
      ret = FALSE;
    }
  }
#endif
  /* We at least check that at least one buffer was sent while the
     selected sink was a given sink, for all sinks */
  for (id = 1; id < element->numpads; ++id) {
    if (bcds[id]->back_counter == 0) {
      *error_message =
          g_strdup_printf ("No buffer was sent while sink pad %s was active",
          GST_PAD_NAME (bcds[id]->pad));
      ret = FALSE;
    }
  }

  for (id = 0; id < element->numpads; ++id) {
    gst_object_unref (bcds[id]->pad);
    g_slice_free (BufferCountData, bcds[id]);
  }
  g_free (bcds);
  return ret;
}