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; }
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; }
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); }
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); }
/** * 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; }
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); }
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); }
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); }
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); }
/* 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; }
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); }
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); }
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; }
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 }
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; }
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); }
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; }
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); }
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; }
/* * 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); }