EXPORT_C #endif GstPad * gst_ghost_pad_new (const gchar * name, GstPad * target) { GstPad *ret; g_return_val_if_fail (GST_IS_PAD (target), NULL); g_return_val_if_fail (!gst_pad_is_linked (target), NULL); GST_LOG ("name:%s, target:%s:%s", GST_STR_NULL (name), GST_DEBUG_PAD_NAME (target)); if ((ret = gst_ghost_pad_new_no_target (name, GST_PAD_DIRECTION (target)))) if (!gst_ghost_pad_set_target (GST_GHOST_PAD_CAST (ret), target)) goto set_target_failed; return ret; /* ERRORS */ set_target_failed: { GST_WARNING_OBJECT (ret, "failed to set target %s:%s", GST_DEBUG_PAD_NAME (target)); gst_object_unref (ret); return NULL; } }
GstPad * gst_ghost_pad_new_from_template (const gchar * name, GstPad * target, GstPadTemplate * templ) { GstPad *ret; g_return_val_if_fail (GST_IS_PAD (target), NULL); g_return_val_if_fail (!gst_pad_is_linked (target), NULL); g_return_val_if_fail (templ != NULL, NULL); g_return_val_if_fail (GST_PAD_TEMPLATE_DIRECTION (templ) == GST_PAD_DIRECTION (target), NULL); GST_LOG ("name:%s, target:%s:%s, templ:%p", GST_STR_NULL (name), GST_DEBUG_PAD_NAME (target), templ); if ((ret = gst_ghost_pad_new_full (name, GST_PAD_DIRECTION (target), templ))) if (!gst_ghost_pad_set_target (GST_GHOST_PAD_CAST (ret), target)) goto set_target_failed; return ret; /* ERRORS */ set_target_failed: { GST_WARNING_OBJECT (ret, "failed to set target %s:%s", GST_DEBUG_PAD_NAME (target)); gst_object_unref (ret); return NULL; } }
static void new_decoded_pad_cb(GstElement *demuxer, GstPad *new_pad, gpointer user_data) { GstElement *decoder; GstPad *pad; GstCaps *caps; gchar *str; caps = gst_pad_get_caps(new_pad); str = gst_caps_to_string(caps); if (g_str_has_prefix(str, "video/")) { decoder = GST_ELEMENT(user_data); pad = gst_element_get_pad(decoder, "sink"); if (GST_PAD_LINK_FAILED(gst_pad_link(new_pad, pad))) { g_warning("Failed to link %s:%s to %s:%s", GST_DEBUG_PAD_NAME(new_pad), GST_DEBUG_PAD_NAME(pad)); } } g_free(str); gst_caps_unref(caps); }
/** * gst_video_get_size: * @pad: pointer to a #GstPad * @width: pointer to integer to hold pixel width of the video frames (output) * @height: pointer to integer to hold pixel height of the video frames (output) * * Inspect the caps of the provided pad and retrieve the width and height of * the video frames it is configured for. * * The pad needs to have negotiated caps containing width and height properties. * * Returns: TRUE if the width and height could be retrieved. * */ gboolean gst_video_get_size (GstPad * pad, gint * width, gint * height) { const GstCaps *caps = NULL; GstStructure *structure; gboolean ret; g_return_val_if_fail (pad != NULL, FALSE); g_return_val_if_fail (width != NULL, FALSE); g_return_val_if_fail (height != NULL, FALSE); caps = GST_PAD_CAPS (pad); if (caps == NULL) { g_warning ("gstvideo: failed to get caps of pad %s:%s", GST_DEBUG_PAD_NAME (pad)); return FALSE; } structure = gst_caps_get_structure (caps, 0); ret = gst_structure_get_int (structure, "width", width); ret &= gst_structure_get_int (structure, "height", height); if (!ret) { g_warning ("gstvideo: failed to get size properties on pad %s:%s", GST_DEBUG_PAD_NAME (pad)); return FALSE; } GST_DEBUG ("size request on pad %s:%s: %dx%d", GST_DEBUG_PAD_NAME (pad), width ? *width : -1, height ? *height : -1); return TRUE; }
static GstCaps * rsn_stream_selector_getcaps (GstPad * pad) { GstPad *otherpad; GstObject *parent; GstCaps *caps; otherpad = rsn_stream_selector_get_linked_pad (pad, FALSE); parent = gst_object_get_parent (GST_OBJECT (pad)); if (!otherpad) { GST_DEBUG_OBJECT (parent, "Pad %s:%s not linked, returning ANY", GST_DEBUG_PAD_NAME (pad)); caps = gst_caps_new_any (); } else { GST_DEBUG_OBJECT (parent, "Pad %s:%s is linked (to %s:%s), returning peer caps", GST_DEBUG_PAD_NAME (pad), GST_DEBUG_PAD_NAME (otherpad)); /* if the peer has caps, use those. If the pad is not linked, this function * returns NULL and we return ANY */ if (!(caps = gst_pad_peer_get_caps (otherpad))) caps = gst_caps_new_any (); gst_object_unref (otherpad); } gst_object_unref (parent); return caps; }
static GstFlowReturn gst_selector_pad_chain (GstPad * pad, GstBuffer * buf) { RsnStreamSelector *sel; GstFlowReturn res; GstPad *active_sinkpad; RsnSelectorPad *selpad; GstClockTime timestamp; GstSegment *seg; sel = RSN_STREAM_SELECTOR (gst_pad_get_parent (pad)); selpad = GST_SELECTOR_PAD_CAST (pad); seg = &selpad->segment; active_sinkpad = rsn_stream_selector_get_active (sel, pad); timestamp = GST_BUFFER_TIMESTAMP (buf); if (GST_CLOCK_TIME_IS_VALID (timestamp)) { GST_DEBUG_OBJECT (sel, "received timestamp %" GST_TIME_FORMAT, GST_TIME_ARGS (timestamp)); gst_segment_set_last_stop (seg, seg->format, timestamp); } /* Ignore buffers from pads except the selected one */ if (pad != active_sinkpad) goto ignore; /* if we have a pending segment, push it out now */ if (selpad->segment_pending) { gst_pad_push_event (sel->srcpad, gst_event_new_new_segment_full (FALSE, seg->rate, seg->applied_rate, seg->format, seg->start, seg->stop, seg->time)); selpad->segment_pending = FALSE; } /* forward */ GST_DEBUG_OBJECT (sel, "Forwarding buffer %p from pad %s:%s", buf, GST_DEBUG_PAD_NAME (pad)); res = gst_pad_push (sel->srcpad, buf); done: gst_object_unref (sel); return res; /* dropped buffers */ ignore: { GST_DEBUG_OBJECT (sel, "Ignoring buffer %p from pad %s:%s", buf, GST_DEBUG_PAD_NAME (pad)); gst_buffer_unref (buf); res = GST_FLOW_NOT_LINKED; goto done; } }
static gint _demux_get_writer_id (GstIndex * index, GstPad * pad) { gint id; if (!gst_index_get_writer_id (index, GST_OBJECT (pad), &id)) { GST_WARNING_OBJECT (index, "can't get index id for %s:%s", GST_DEBUG_PAD_NAME (pad)); return -1; } else { GST_LOG_OBJECT (index, "got index id %d for %s:%s", id, GST_DEBUG_PAD_NAME (pad)); return id; } }
/* FIXME, we can do this in the _chain functions */ guint gst_collect_pads_available (GstCollectPads * pads) { GSList *collected; guint result = G_MAXUINT; g_return_val_if_fail (pads != NULL, 0); g_return_val_if_fail (GST_IS_COLLECT_PADS (pads), 0); for (collected = pads->data; collected; collected = g_slist_next (collected)) { GstCollectData *pdata; GstBuffer *buffer; gint size; pdata = (GstCollectData *) collected->data; /* ignore pad with EOS */ if (G_UNLIKELY (pdata->abidata.ABI.eos)) { GST_DEBUG ("pad %s:%s is EOS", GST_DEBUG_PAD_NAME (pdata->pad)); continue; } /* an empty buffer without EOS is weird when we get here.. */ if (G_UNLIKELY ((buffer = pdata->buffer) == NULL)) { GST_WARNING ("pad %s:%s has no buffer", GST_DEBUG_PAD_NAME (pdata->pad)); goto not_filled; } /* this is the size left of the buffer */ size = GST_BUFFER_SIZE (buffer) - pdata->pos; GST_DEBUG ("pad %s:%s has %d bytes left", GST_DEBUG_PAD_NAME (pdata->pad), size); /* need to return the min of all available data */ if (size < result) result = size; } /* nothing changed, all must be EOS then, return 0 */ if (G_UNLIKELY (result == G_MAXUINT)) result = 0; return result; not_filled: { return 0; } }
static void pad_added_cb (GstElement * uridecodebin, GstPad * pad, GstElement * encodebin) { GstPad *sinkpad; sinkpad = gst_element_get_compatible_pad (encodebin, pad, NULL); if (sinkpad == NULL) { GstCaps *caps; /* Ask encodebin for a compatible pad */ caps = gst_pad_query_caps (pad, NULL); g_signal_emit_by_name (encodebin, "request-pad", caps, &sinkpad); if (caps) gst_caps_unref (caps); } if (sinkpad == NULL) { g_print ("Couldn't get an encoding channel for pad %s:%s\n", GST_DEBUG_PAD_NAME (pad)); return; } if (G_UNLIKELY (gst_pad_link (pad, sinkpad) != GST_PAD_LINK_OK)) { g_print ("Couldn't link pads\n"); } return; }
static void _rtpbin_pad_added (GstElement *rtpbin, GstPad *new_pad, gpointer user_data) { FsRtpConference *self = FS_RTP_CONFERENCE (user_data); gchar *name; GST_DEBUG_OBJECT (self, "pad %s:%s added", GST_DEBUG_PAD_NAME (new_pad)); name = gst_pad_get_name (new_pad); if (g_str_has_prefix (name, "recv_rtp_src_")) { guint session_id, ssrc, pt; if (sscanf (name, "recv_rtp_src_%u_%u_%u", &session_id, &ssrc, &pt) == 3 && ssrc <= G_MAXUINT32) { FsRtpSession *session = fs_rtp_conference_get_session_by_id (self, session_id); if (session) { fs_rtp_session_new_recv_pad (session, new_pad, ssrc, pt); g_object_unref (session); } } } g_free (name); }
static GstPad * gst_funnel_request_new_pad (GstElement * element, GstPadTemplate * templ, const gchar * name, const GstCaps * caps) { GstPad *sinkpad; GST_DEBUG_OBJECT (element, "requesting pad"); sinkpad = GST_PAD_CAST (g_object_new (GST_TYPE_FUNNEL_PAD, "name", name, "direction", templ->direction, "template", templ, NULL)); gst_pad_set_chain_function (sinkpad, GST_DEBUG_FUNCPTR (gst_funnel_sink_chain)); gst_pad_set_chain_list_function (sinkpad, GST_DEBUG_FUNCPTR (gst_funnel_sink_chain_list)); gst_pad_set_event_function (sinkpad, GST_DEBUG_FUNCPTR (gst_funnel_sink_event)); GST_OBJECT_FLAG_SET (sinkpad, GST_PAD_FLAG_PROXY_CAPS); GST_OBJECT_FLAG_SET (sinkpad, GST_PAD_FLAG_PROXY_ALLOCATION); gst_pad_set_active (sinkpad, TRUE); gst_element_add_pad (element, sinkpad); GST_DEBUG_OBJECT (element, "requested pad %s:%s", GST_DEBUG_PAD_NAME (sinkpad)); return sinkpad; }
static gboolean gst_interleave_sink_event (GstPad * pad, GstEvent * event) { GstInterleave *self = GST_INTERLEAVE (gst_pad_get_parent (pad)); gboolean ret; GST_DEBUG ("Got %s event on pad %s:%s", GST_EVENT_TYPE_NAME (event), GST_DEBUG_PAD_NAME (pad)); switch (GST_EVENT_TYPE (event)) { case GST_EVENT_FLUSH_STOP: /* mark a pending new segment. This event is synchronized * with the streaming thread so we can safely update the * variable without races. It's somewhat weird because we * assume the collectpads forwarded the FLUSH_STOP past us * and downstream (using our source pad, the bastard!). */ self->segment_pending = TRUE; break; default: break; } /* now GstCollectPads can take care of the rest, e.g. EOS */ ret = self->collect_event (pad, event); gst_object_unref (self); return ret; }
static void gst_funnel_release_pad (GstElement * element, GstPad * pad) { GstFunnel *funnel = GST_FUNNEL (element); GstFunnelPad *fpad = GST_FUNNEL_PAD_CAST (pad); gboolean got_eos; gboolean send_eos = FALSE; GST_DEBUG_OBJECT (funnel, "releasing pad %s:%s", GST_DEBUG_PAD_NAME (pad)); gst_pad_set_active (pad, FALSE); got_eos = fpad->got_eos; gst_element_remove_pad (GST_ELEMENT_CAST (funnel), pad); GST_OBJECT_LOCK (funnel); if (!got_eos && gst_funnel_all_sinkpads_eos_unlocked (funnel, NULL)) { GST_DEBUG_OBJECT (funnel, "Pad removed. All others are EOS. Sending EOS"); send_eos = TRUE; } GST_OBJECT_UNLOCK (funnel); if (send_eos) if (!gst_pad_push_event (funnel->srcpad, gst_event_new_eos ())) GST_WARNING_OBJECT (funnel, "Failure pushing EOS"); }
static GstStructure * collect_stream_information (GstDiscoverer * dc, PrivateStream * ps, guint idx) { GstCaps *caps; GstStructure *st; gchar *stname; stname = g_strdup_printf ("stream-%02d", idx); st = gst_structure_empty_new (stname); g_free (stname); /* Get caps */ caps = gst_pad_get_negotiated_caps (ps->pad); if (!caps) { GST_WARNING ("Couldn't get negotiated caps from %s:%s", GST_DEBUG_PAD_NAME (ps->pad)); caps = gst_pad_get_caps (ps->pad); } if (caps) { GST_DEBUG ("Got caps %" GST_PTR_FORMAT, caps); gst_structure_id_set (st, _CAPS_QUARK, GST_TYPE_CAPS, caps, NULL); gst_caps_unref (caps); } if (ps->tags) gst_structure_id_set (st, _TAGS_QUARK, GST_TYPE_STRUCTURE, ps->tags, NULL); return st; }
/** * gst_camerabin_try_add_element: * @bin: tries adding an element to this bin * @srcpad: src pad name, or NULL for any * @new_elem: new element to be added * @dstpad: dst pad name, or NULL for any * * Adds given element to given @bin. Looks for an unconnected src pad * (with name @srcpad, if specified) from the @bin and links the element to * it. * * Returns: %TRUE if adding and linking succeeded, %FALSE otherwise. */ gboolean gst_camerabin_try_add_element (GstBin * bin, const gchar * srcpad, GstElement * new_elem, const gchar * dstpad) { GstPad *bin_pad; GstElement *bin_elem; gboolean ret = TRUE; g_return_val_if_fail (bin, FALSE); g_return_val_if_fail (new_elem, FALSE); /* Get pads for linking */ bin_pad = gst_bin_find_unlinked_pad (bin, GST_PAD_SRC); /* Add to bin */ gst_bin_add (GST_BIN (bin), new_elem); /* Link, if unconnected pad was found, otherwise just add it to bin */ if (bin_pad) { GST_DEBUG_OBJECT (bin, "linking %s to %s:%s", GST_OBJECT_NAME (new_elem), GST_DEBUG_PAD_NAME (bin_pad)); bin_elem = gst_pad_get_parent_element (bin_pad); gst_object_unref (bin_pad); if (!gst_element_link_pads_full (bin_elem, srcpad, new_elem, dstpad, GST_PAD_LINK_CHECK_CAPS)) { gst_object_ref (new_elem); gst_bin_remove (bin, new_elem); ret = FALSE; } gst_object_unref (bin_elem); } else { GST_INFO_OBJECT (bin, "no unlinked source pad in bin"); } return ret; }
static gboolean gst_proxy_pad_set_target_unlocked (GstPad * pad, GstPad * target) { GstPad *oldtarget; if (target) { GST_LOG_OBJECT (pad, "setting target %s:%s", GST_DEBUG_PAD_NAME (target)); if (G_UNLIKELY (GST_PAD_DIRECTION (pad) != GST_PAD_DIRECTION (target))) goto wrong_direction; } else GST_LOG_OBJECT (pad, "clearing target"); /* clear old target */ if ((oldtarget = GST_PROXY_PAD_TARGET (pad))) { gst_object_unref (oldtarget); } /* set and ref new target if any */ if (target) GST_PROXY_PAD_TARGET (pad) = gst_object_ref (target); else GST_PROXY_PAD_TARGET (pad) = NULL; return TRUE; /* ERRORS */ wrong_direction: { GST_ERROR_OBJECT (pad, "target pad doesn't have the same direction as ourself"); return FALSE; } }
/** * gst_ghost_pad_set_target: * @gpad: the #GstGhostPad * @newtarget: (transfer none) (allow-none): the new pad target * * Set the new target of the ghostpad @gpad. Any existing target * is unlinked and links to the new target are established. if @newtarget is * %NULL the target will be cleared. * * Returns: (transfer full): %TRUE if the new target could be set. This function * can return %FALSE when the internal pads could not be linked. */ gboolean gst_ghost_pad_set_target (GstGhostPad * gpad, GstPad * newtarget) { GstPad *internal; GstPad *oldtarget; GstPadLinkReturn lret; g_return_val_if_fail (GST_IS_GHOST_PAD (gpad), FALSE); g_return_val_if_fail (GST_PAD_CAST (gpad) != newtarget, FALSE); g_return_val_if_fail (newtarget != GST_PROXY_PAD_INTERNAL (gpad), FALSE); GST_OBJECT_LOCK (gpad); internal = GST_PROXY_PAD_INTERNAL (gpad); if (newtarget) GST_DEBUG_OBJECT (gpad, "set target %s:%s", GST_DEBUG_PAD_NAME (newtarget)); else GST_DEBUG_OBJECT (gpad, "clearing target"); /* clear old target */ if ((oldtarget = gst_pad_get_peer (internal))) { GST_OBJECT_UNLOCK (gpad); /* unlink internal pad */ if (GST_PAD_IS_SRC (internal)) gst_pad_unlink (internal, oldtarget); else gst_pad_unlink (oldtarget, internal); gst_object_unref (oldtarget); } else { GST_OBJECT_UNLOCK (gpad); } if (newtarget) { /* and link to internal pad without any checks */ GST_DEBUG_OBJECT (gpad, "connecting internal pad to target %" GST_PTR_FORMAT, newtarget); if (GST_PAD_IS_SRC (internal)) lret = gst_pad_link_full (internal, newtarget, GST_PAD_LINK_CHECK_NOTHING); else lret = gst_pad_link_full (newtarget, internal, GST_PAD_LINK_CHECK_NOTHING); if (lret != GST_PAD_LINK_OK) goto link_failed; } return TRUE; /* ERRORS */ link_failed: { GST_WARNING_OBJECT (gpad, "could not link internal and target, reason:%s", gst_pad_link_get_name (lret)); return FALSE; } }
static gboolean gst_frei0r_mixer_sink0_event (GstPad * pad, GstEvent * event) { GstFrei0rMixer *self = GST_FREI0R_MIXER (gst_pad_get_parent (pad)); gboolean ret = FALSE; GstEvent **p_ev; GST_DEBUG ("Got %s event on pad %s:%s", GST_EVENT_TYPE_NAME (event), GST_DEBUG_PAD_NAME (pad)); switch (GST_EVENT_TYPE (event)) { case GST_EVENT_NEWSEGMENT: p_ev = &self->newseg_event; gst_event_replace (p_ev, event); break; default: break; } /* now GstCollectPads can take care of the rest, e.g. EOS */ ret = self->collect_event (pad, event); gst_object_unref (self); return ret; }
static gboolean gst_fake_src_event_handler (GstBaseSrc * basesrc, GstEvent * event) { GstFakeSrc *src; src = GST_FAKE_SRC (basesrc); if (!src->silent) { const GstStructure *s; const gchar *tstr; gchar *sstr; GST_OBJECT_LOCK (src); g_free (src->last_message); tstr = gst_event_type_get_name (GST_EVENT_TYPE (event)); if ((s = gst_event_get_structure (event))) sstr = gst_structure_to_string (s); else sstr = g_strdup (""); src->last_message = g_strdup_printf ("event ******* (%s:%s) E (type: %s (%d), %s) %p", GST_DEBUG_PAD_NAME (GST_BASE_SRC_CAST (src)->srcpad), tstr, GST_EVENT_TYPE (event), sstr, event); g_free (sstr); GST_OBJECT_UNLOCK (src); g_object_notify_by_pspec ((GObject *) src, pspec_last_message); } return GST_BASE_SRC_CLASS (parent_class)->event (basesrc, event); }
EXPORT_C #endif int gst_audio_frame_byte_size (GstPad * pad) { /* FIXME: this should be moved closer to the gstreamer core * and be implemented for every mime type IMO */ int width = 0; int channels = 0; const GstCaps *caps = NULL; GstStructure *structure; /* get caps of pad */ caps = GST_PAD_CAPS (pad); if (caps == NULL) { /* ERROR: could not get caps of pad */ g_warning ("gstaudio: could not get caps of pad %s:%s\n", GST_DEBUG_PAD_NAME (pad)); return 0; } structure = gst_caps_get_structure (caps, 0); gst_structure_get_int (structure, "width", &width); gst_structure_get_int (structure, "channels", &channels); return (width / 8) * channels; }
static void gst_log_android_handler(GstDebugCategory *category, GstDebugLevel level, const gchar *file, const gchar *function, gint line, GObject *object, GstDebugMessage *message, gpointer data) { gchar *obj = NULL; OWR_UNUSED(data); if (level > gst_debug_category_get_threshold(category)) return; if (GST_IS_PAD(object) && GST_OBJECT_NAME(object)) { obj = g_strdup_printf("<%s:%s>", GST_DEBUG_PAD_NAME(object)); } else if (GST_IS_OBJECT(object)) { obj = g_strdup_printf("<%s>", GST_OBJECT_NAME(object)); } __android_log_print(ANDROID_LOG_INFO, "gst_log", "%p %s %s %s:%d:%s:%s %s\n", (void *)g_thread_self(), gst_debug_level_get_name(level), gst_debug_category_get_name(category), file, line, function, obj ? obj : "", gst_debug_message_get(message)); g_free(obj); }
static void gst_identity_update_last_message_for_buffer (GstIdentity * identity, const gchar * action, GstBuffer * buf, gsize size) { gchar dts_str[64], pts_str[64], dur_str[64]; gchar *flag_str; GST_OBJECT_LOCK (identity); flag_str = gst_buffer_get_flags_string (buf); g_free (identity->last_message); identity->last_message = g_strdup_printf ("%s ******* (%s:%s) " "(%" G_GSIZE_FORMAT " bytes, dts: %s, pts:%s, duration: %s, offset: %" G_GINT64_FORMAT ", " "offset_end: % " G_GINT64_FORMAT ", flags: %08x %s) %p", action, GST_DEBUG_PAD_NAME (GST_BASE_TRANSFORM_CAST (identity)->sinkpad), size, print_pretty_time (dts_str, sizeof (dts_str), GST_BUFFER_DTS (buf)), print_pretty_time (pts_str, sizeof (pts_str), GST_BUFFER_PTS (buf)), print_pretty_time (dur_str, sizeof (dur_str), GST_BUFFER_DURATION (buf)), GST_BUFFER_OFFSET (buf), GST_BUFFER_OFFSET_END (buf), GST_BUFFER_FLAGS (buf), flag_str, buf); g_free (flag_str); GST_OBJECT_UNLOCK (identity); gst_identity_notify_last_message (identity); }
static GstPad * gst_dtls_dec_request_new_pad (GstElement * element, GstPadTemplate * tmpl, const gchar * name, const GstCaps * caps) { GstDtlsDec *self = GST_DTLS_DEC (element); GstPad *pad; GST_DEBUG_OBJECT (element, "requesting pad"); g_return_val_if_fail (!self->src, NULL); g_return_val_if_fail (tmpl->direction == GST_PAD_SRC, NULL); g_mutex_lock (&self->src_mutex); if (self->src) { GST_ERROR_OBJECT (self, "Pad %s:%s exists already", GST_DEBUG_PAD_NAME (self->src)); g_mutex_unlock (&self->src_mutex); return NULL; } self->src = pad = gst_pad_new_from_template (tmpl, name); gst_object_ref (pad); g_mutex_unlock (&self->src_mutex); gst_pad_set_active (pad, TRUE); if (caps) gst_pad_set_caps (pad, (GstCaps *) caps); gst_element_add_pad (element, pad); gst_object_unref (pad); return pad; }
/** * gst_camerabin_try_add_element: * @bin: tries adding an element to this bin * @new_elem: new element to be added * * Adds given element to given @bin. Looks for an unconnected src pad * from the @bin and links the element to it. * * Returns: %TRUE if adding and linking succeeded, %FALSE otherwise. */ gboolean gst_camerabin_try_add_element (GstBin * bin, GstElement * new_elem) { GstPad *bin_pad; GstElement *bin_elem; gboolean ret = TRUE; if (!bin || !new_elem) { return FALSE; } /* Get pads for linking */ bin_pad = gst_bin_find_unlinked_pad (bin, GST_PAD_SRC); /* Add to bin */ gst_bin_add (GST_BIN (bin), new_elem); /* Link, if unconnected pad was found, otherwise just add it to bin */ if (bin_pad) { GST_DEBUG_OBJECT (bin, "linking %s to %s:%s", GST_OBJECT_NAME (new_elem), GST_DEBUG_PAD_NAME (bin_pad)); bin_elem = gst_pad_get_parent_element (bin_pad); gst_object_unref (bin_pad); if (!gst_element_link (bin_elem, new_elem)) { gst_bin_remove (bin, new_elem); ret = FALSE; } gst_object_unref (bin_elem); } else { GST_INFO_OBJECT (bin, "no unlinked source pad in bin"); } return ret; }
static gboolean gst_ghost_pad_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) { /* the ghostpad is SRC and activated in pull mode by its peer, call the * activation function of the internal pad to propagate the activation * 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 and activated by the internal pad, propagate activation * upstream because we hold a ref 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 { /* no peer, we fail */ GST_LOG_OBJECT (pad, "pad not src and no peer, failing"); ret = FALSE; } return ret; }
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 { /* 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; } return ret; }
static gboolean gst_interleave_sink_query (GstCollectPads * pads, GstCollectData * data, GstQuery * query, gpointer user_data) { GstInterleave *self = GST_INTERLEAVE (user_data); gboolean ret = TRUE; GST_DEBUG ("Got %s query on pad %s:%s", GST_QUERY_TYPE_NAME (query), GST_DEBUG_PAD_NAME (data->pad)); switch (GST_QUERY_TYPE (query)) { case GST_QUERY_CAPS: { GstCaps *filter, *caps; gst_query_parse_caps (query, &filter); caps = gst_interleave_sink_getcaps (data->pad, self, filter); gst_query_set_caps_result (query, caps); gst_caps_unref (caps); ret = TRUE; break; } default: ret = gst_collect_pads_query_default (pads, data, query, FALSE); break; } return ret; }
static gboolean gst_fake_sink_event (GstBaseSink * bsink, GstEvent * event) { GstFakeSink *sink = GST_FAKE_SINK (bsink); if (!sink->silent) { const GstStructure *s; const gchar *tstr; gchar *sstr; GST_OBJECT_LOCK (sink); g_free (sink->last_message); if (GST_EVENT_TYPE (event) == GST_EVENT_SINK_MESSAGE) { GstMessage *msg; const GstStructure *structure; gst_event_parse_sink_message (event, &msg); structure = gst_message_get_structure (msg); sstr = gst_structure_to_string (structure); sink->last_message = g_strdup_printf ("message ******* (%s:%s) M (type: %d, %s) %p", GST_DEBUG_PAD_NAME (GST_BASE_SINK_CAST (sink)->sinkpad), GST_MESSAGE_TYPE (msg), sstr, msg); gst_message_unref (msg); } else { tstr = gst_event_type_get_name (GST_EVENT_TYPE (event)); if ((s = gst_event_get_structure (event))) { sstr = gst_structure_to_string (s); } else { sstr = g_strdup (""); } sink->last_message = g_strdup_printf ("event ******* (%s:%s) E (type: %s (%d), %s) %p", GST_DEBUG_PAD_NAME (GST_BASE_SINK_CAST (sink)->sinkpad), tstr, GST_EVENT_TYPE (event), sstr, event); } g_free (sstr); GST_OBJECT_UNLOCK (sink); gst_fake_sink_notify_last_message (sink); } return GST_BASE_SINK_CLASS (parent_class)->event (bsink, event); }
static void pad_added_cb (GstElement * decodebin, GstPad * pad, PlayState * state) { GstPadLinkReturn ret; GstElement *fakesink; GstPad *fakesink_pad; StreamInfo *si; fakesink = gst_element_factory_make ("fakesink", NULL); #if 0 if (state->n_sinks == 1) g_object_set (fakesink, "silent", FALSE, NULL); #endif si = g_new0 (StreamInfo, 1); si->pad = g_object_ref (pad); si->state = state; si->fwd_times = g_array_new (FALSE, TRUE, sizeof (StreamTSRange)); si->bkwd_times = g_array_new (FALSE, TRUE, sizeof (StreamTSRange)); gst_pad_add_probe (pad, GST_PAD_PROBE_TYPE_DATA_DOWNSTREAM, (GstPadProbeCallback) handle_output, si, (GDestroyNotify) _destroy_stream_info); state->n_sinks++; gst_bin_add (GST_BIN (state->pipe), fakesink); gst_element_sync_state_with_parent (fakesink); fakesink_pad = gst_element_get_static_pad (fakesink, "sink"); ret = gst_pad_link (pad, fakesink_pad); if (!GST_PAD_LINK_SUCCESSFUL (ret)) { g_printerr ("Failed to link %s:%s to %s:%s (ret = %d)\n", GST_DEBUG_PAD_NAME (pad), GST_DEBUG_PAD_NAME (fakesink_pad), ret); } else { GstCaps *caps = gst_pad_get_current_caps (pad); gchar *s = gst_caps_to_string (caps); g_print ("Linked %s:%s to %s:%s caps %s\n", GST_DEBUG_PAD_NAME (pad), GST_DEBUG_PAD_NAME (fakesink_pad), s); gst_caps_unref (caps); g_free (s); } gst_object_unref (fakesink_pad); }
EXPORT_C #endif gboolean gst_ghost_pad_set_target (GstGhostPad * gpad, GstPad * newtarget) { GstPad *internal; GstPad *oldtarget; gboolean result; GstPadLinkReturn lret; g_return_val_if_fail (GST_IS_GHOST_PAD (gpad), FALSE); GST_PROXY_LOCK (gpad); internal = GST_PROXY_PAD_INTERNAL (gpad); GST_DEBUG_OBJECT (gpad, "set target %s:%s", GST_DEBUG_PAD_NAME (newtarget)); /* clear old target */ if ((oldtarget = GST_PROXY_PAD_TARGET (gpad))) { /* if we have an internal pad, unlink */ if (internal) { if (GST_PAD_IS_SRC (internal)) gst_pad_unlink (internal, oldtarget); else gst_pad_unlink (oldtarget, internal); } } result = gst_proxy_pad_set_target_unlocked (GST_PAD_CAST (gpad), newtarget); if (result && newtarget) { /* and link to internal pad */ GST_DEBUG_OBJECT (gpad, "connecting internal pad to target"); if (GST_PAD_IS_SRC (internal)) lret = gst_pad_link (internal, newtarget); else lret = gst_pad_link (newtarget, internal); if (lret != GST_PAD_LINK_OK) goto link_failed; } GST_PROXY_UNLOCK (gpad); return result; /* ERRORS */ link_failed: { GST_WARNING_OBJECT (gpad, "could not link internal and target, reason:%d", lret); /* and unset target again */ gst_proxy_pad_set_target_unlocked (GST_PAD_CAST (gpad), NULL); GST_PROXY_UNLOCK (gpad); return FALSE; } }