static void configure_test_element (GstBin * bin, const gchar * capsfilter) { GstElement *filter; GstElement *identity; GstPad *pad, *ghostpad; GstPadTemplate *test_static_templ; filter = gst_element_factory_make ("capsfilter", NULL); fail_unless (filter != NULL); gst_util_set_object_arg (G_OBJECT (filter), "caps", capsfilter); identity = gst_element_factory_make ("identity", NULL); fail_unless (identity != NULL); gst_bin_add_many (bin, filter, identity, NULL); fail_unless (gst_element_link_many (filter, identity, NULL) == TRUE); test_static_templ = gst_static_pad_template_get (&sink_factory); pad = gst_element_get_static_pad (filter, "sink"); ghostpad = gst_ghost_pad_new_from_template ("sink", pad, test_static_templ); gst_element_add_pad (GST_ELEMENT_CAST (bin), ghostpad); gst_object_unref (pad); gst_object_unref (test_static_templ); test_static_templ = gst_static_pad_template_get (&src_factory); pad = gst_element_get_static_pad (identity, "src"); ghostpad = gst_ghost_pad_new_from_template ("src", pad, test_static_templ); gst_element_add_pad (GST_ELEMENT_CAST (bin), ghostpad); gst_object_unref (pad); gst_object_unref (test_static_templ); }
static void gst_video_parse_init (GstVideoParse * vp) { GstPad *inner_pad; GstPad *ghostpad; vp->rawvideoparse = gst_element_factory_make ("rawvideoparse", "inner_rawvideoparse"); g_assert (vp->rawvideoparse != NULL); gst_bin_add (GST_BIN (vp), vp->rawvideoparse); inner_pad = gst_element_get_static_pad (vp->rawvideoparse, "sink"); ghostpad = gst_ghost_pad_new_from_template ("sink", inner_pad, gst_element_class_get_pad_template (GST_ELEMENT_GET_CLASS (vp), "sink")); gst_element_add_pad (GST_ELEMENT (vp), ghostpad); gst_object_unref (GST_OBJECT (inner_pad)); inner_pad = gst_element_get_static_pad (vp->rawvideoparse, "src"); ghostpad = gst_ghost_pad_new_from_template ("src", inner_pad, gst_element_class_get_pad_template (GST_ELEMENT_GET_CLASS (vp), "src")); gst_element_add_pad (GST_ELEMENT (vp), ghostpad); gst_object_unref (GST_OBJECT (inner_pad)); }
static void gst_vt_h264_enc_bin_init (GstVTH264EncBin * self, GstVTH264EncBinClass * gclass) { GstVTH264EncBinPrivate *priv; GstPad *encoder_sinkpad, *parser_srcpad, *ghost_pad; self->priv = priv = TAA_VT_H264_ENC_BIN_GET_PRIVATE (self); priv->encoder = gst_element_factory_make ("vtenc_h264", "encoder"); priv->parser = gst_element_factory_make ("h264parse", "parser"); gst_bin_add_many (GST_BIN_CAST (self), priv->encoder, priv->parser, NULL); gst_element_link (priv->encoder, priv->parser); encoder_sinkpad = gst_element_get_static_pad (priv->encoder, "sink"); ghost_pad = gst_ghost_pad_new_from_template ("sink", encoder_sinkpad, gst_static_pad_template_get (&vth264encbin_sink_template)); gst_object_unref (encoder_sinkpad); gst_element_add_pad (GST_ELEMENT_CAST (self), ghost_pad); parser_srcpad = gst_element_get_static_pad (priv->parser, "src"); ghost_pad = gst_ghost_pad_new_from_template ("src", parser_srcpad, gst_static_pad_template_get (&vth264encbin_src_template)); gst_object_unref (parser_srcpad); gst_element_add_pad (GST_ELEMENT_CAST (self), ghost_pad); g_object_set (priv->encoder, "usage", 6, NULL); g_object_set (priv->parser, "output-format", H264PARSE_OUTPUT_FORMAT_BYTE_STREAM, "split-packetized", TRUE, NULL); }
static void gst_unaligned_audio_parse_init (GstUnalignedAudioParse * unaligned_audio_parse) { GstPad *inner_pad; GstPad *ghostpad; unaligned_audio_parse->inner_parser = gst_element_factory_make ("rawaudioparse", "inner_parser"); g_assert (unaligned_audio_parse->inner_parser != NULL); g_object_set (G_OBJECT (unaligned_audio_parse->inner_parser), "use-sink-caps", TRUE, NULL); gst_bin_add (GST_BIN (unaligned_audio_parse), unaligned_audio_parse->inner_parser); inner_pad = gst_element_get_static_pad (unaligned_audio_parse->inner_parser, "sink"); ghostpad = gst_ghost_pad_new_from_template ("sink", inner_pad, gst_element_class_get_pad_template (GST_ELEMENT_GET_CLASS (unaligned_audio_parse), "sink")); gst_element_add_pad (GST_ELEMENT (unaligned_audio_parse), ghostpad); gst_object_unref (GST_OBJECT (inner_pad)); inner_pad = gst_element_get_static_pad (unaligned_audio_parse->inner_parser, "src"); ghostpad = gst_ghost_pad_new_from_template ("src", inner_pad, gst_element_class_get_pad_template (GST_ELEMENT_GET_CLASS (unaligned_audio_parse), "src")); gst_element_add_pad (GST_ELEMENT (unaligned_audio_parse), ghostpad); gst_object_unref (GST_OBJECT (inner_pad)); }
static GstPad * kms_hub_port_generate_sink_pad (GstElement * element, GstPadTemplate * templ, const gchar * name, const GstCaps * caps, GstElement * output) { GstPad *output_pad, *pad; output_pad = gst_element_get_static_pad (output, "sink"); pad = gst_ghost_pad_new_from_template (name, output_pad, templ); g_object_unref (output_pad); 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 (pad, TRUE); } if (gst_element_add_pad (element, pad)) return pad; GST_ERROR_OBJECT (element, "Cannot add pad %" GST_PTR_FORMAT, pad); g_object_unref (pad); return NULL; }
static void owr_inter_src_init(OwrInterSrc *self) { GstPad *srcpad, *sinkpad; GST_OBJECT_FLAG_SET(self, GST_ELEMENT_FLAG_SOURCE); self->queue = gst_element_factory_make("queue", NULL); gst_bin_add(GST_BIN(self), self->queue); srcpad = gst_element_get_static_pad(self->queue, "src"); self->srcpad = gst_ghost_pad_new_from_template("src", srcpad, gst_static_pad_template_get(&src_template)); gst_object_unref(srcpad); gst_element_add_pad(GST_ELEMENT(self), self->srcpad); /* Just to allow linking... */ self->dummy_sinkpad = gst_pad_new("dummy_sinkpad", GST_PAD_SINK); gst_object_set_parent(GST_OBJECT(self->dummy_sinkpad), GST_OBJECT(self)); self->internal_srcpad = gst_pad_new("internal_src", GST_PAD_SRC); gst_object_set_parent(GST_OBJECT(self->internal_srcpad), GST_OBJECT(self->dummy_sinkpad)); gst_pad_set_event_function(self->internal_srcpad, owr_inter_src_internal_src_event); gst_pad_set_query_function(self->internal_srcpad, owr_inter_src_internal_src_query); sinkpad = gst_element_get_static_pad(self->queue, "sink"); gst_pad_link(self->internal_srcpad, sinkpad); gst_object_unref(sinkpad); }
static GstPad * kms_element_generate_sink_pad (KmsElement * element, const gchar * name, GstElement ** target, GstPadTemplate * templ) { GstElement *valve = *target; GstPad *sink, *ret_pad; if (valve != NULL) return NULL; valve = gst_element_factory_make ("valve", NULL); *target = valve; g_object_set (valve, "drop", TRUE, NULL); gst_bin_add (GST_BIN (element), valve); gst_element_sync_state_with_parent (valve); if (target == &element->priv->audio_valve) { KMS_ELEMENT_GET_CLASS (element)->audio_valve_added (element, valve); } else { KMS_ELEMENT_GET_CLASS (element)->video_valve_added (element, valve); } sink = gst_element_get_static_pad (valve, "sink"); ret_pad = gst_ghost_pad_new_from_template (name, sink, templ); g_object_unref (sink); return ret_pad; }
static gboolean kms_base_hub_create_and_link_ghost_pad (KmsBaseHub * mixer, GstPad * src_pad, const gchar * gp_name, const gchar * gp_template_name, GstPad * target) { GstPadTemplate *templ; GstPad *gp; gboolean ret; templ = gst_element_class_get_pad_template (GST_ELEMENT_CLASS (G_OBJECT_GET_CLASS (mixer)), gp_template_name); gp = gst_ghost_pad_new_from_template (gp_name, target, templ); if (GST_STATE (mixer) >= GST_STATE_PAUSED || GST_STATE_PENDING (mixer) >= GST_STATE_PAUSED || GST_STATE_TARGET (mixer) >= GST_STATE_PAUSED) { gst_pad_set_active (gp, TRUE); } ret = gst_element_add_pad (GST_ELEMENT (mixer), gp); if (ret) { gst_pad_link (src_pad, gp); } else { g_object_unref (gp); } return ret; }
static void kms_hub_port_start_media_type (KmsElement * self, KmsElementPadType type, GstPadTemplate * templ, const gchar * pad_name) { GstElement *capsfilter = gst_element_factory_make ("capsfilter", NULL); GstPad *src = gst_element_get_static_pad (capsfilter, "src"); GstPad *internal_src; gst_bin_add (GST_BIN (self), capsfilter); gst_element_sync_state_with_parent (capsfilter); internal_src = gst_ghost_pad_new_from_template (pad_name, src, templ); g_object_set_qdata_full (G_OBJECT (internal_src), key_elem_data_quark (), g_object_ref (capsfilter), g_object_unref); g_object_set_qdata (G_OBJECT (internal_src), key_type_data_quark (), GINT_TO_POINTER (type)); g_signal_connect (internal_src, "linked", G_CALLBACK (kms_hub_port_internal_src_pad_linked), NULL); if (GST_STATE (self) >= GST_STATE_PAUSED || GST_STATE_PENDING (self) >= GST_STATE_PAUSED || GST_STATE_TARGET (self) >= GST_STATE_PAUSED) { gst_pad_set_active (internal_src, TRUE); } gst_element_add_pad (GST_ELEMENT (self), internal_src); g_object_unref (src); }
static GstPad * gst_hls_sink2_request_new_pad (GstElement * element, GstPadTemplate * templ, const gchar * name, const GstCaps * caps) { GstHlsSink2 *sink = GST_HLS_SINK2_CAST (element); GstPad *pad, *peer; gboolean is_audio; g_return_val_if_fail (strcmp (templ->name_template, "audio") == 0 || strcmp (templ->name_template, "video") == 0, NULL); g_return_val_if_fail (strcmp (templ->name_template, "audio") != 0 || !sink->audio_sink, NULL); g_return_val_if_fail (strcmp (templ->name_template, "video") != 0 || !sink->video_sink, NULL); is_audio = strcmp (templ->name_template, "audio") == 0; peer = gst_element_get_request_pad (sink->splitmuxsink, is_audio ? "audio_0" : "video"); if (!peer) return NULL; pad = gst_ghost_pad_new_from_template (templ->name_template, peer, templ); gst_pad_set_active (pad, TRUE); gst_element_add_pad (element, pad); gst_object_unref (peer); if (is_audio) sink->audio_sink = pad; else sink->video_sink = pad; return pad; }
static void gst_rg_volume_init (GstRgVolume * self) { GObjectClass *volume_class; GstPad *volume_pad, *ghost_pad; self->album_mode = DEFAULT_ALBUM_MODE; self->headroom = DEFAULT_HEADROOM; self->pre_amp = DEFAULT_PRE_AMP; self->fallback_gain = DEFAULT_FALLBACK_GAIN; self->target_gain = 0.0; self->result_gain = 0.0; self->volume_element = gst_element_factory_make ("volume", "rgvolume-volume"); if (G_UNLIKELY (self->volume_element == NULL)) { GstMessage *msg; GST_WARNING_OBJECT (self, "could not create volume element"); msg = gst_missing_element_message_new (GST_ELEMENT_CAST (self), "volume"); gst_element_post_message (GST_ELEMENT_CAST (self), msg); /* Nothing else to do, we will refuse the state change from NULL to READY to * indicate that something went very wrong. It is doubtful that someone * attempts changing our state though, since we end up having no pads! */ return; } volume_class = G_OBJECT_GET_CLASS (G_OBJECT (self->volume_element)); self->max_volume = G_PARAM_SPEC_DOUBLE (g_object_class_find_property (volume_class, "volume"))->maximum; GST_BIN_CLASS (parent_class)->add_element (GST_BIN_CAST (self), self->volume_element); volume_pad = gst_element_get_static_pad (self->volume_element, "sink"); ghost_pad = gst_ghost_pad_new_from_template ("sink", volume_pad, gst_pad_get_pad_template (volume_pad)); gst_object_unref (volume_pad); gst_pad_set_event_function (ghost_pad, gst_rg_volume_sink_event); gst_element_add_pad (GST_ELEMENT_CAST (self), ghost_pad); volume_pad = gst_element_get_static_pad (self->volume_element, "src"); ghost_pad = gst_ghost_pad_new_from_template ("src", volume_pad, gst_pad_get_pad_template (volume_pad)); gst_object_unref (volume_pad); gst_element_add_pad (GST_ELEMENT_CAST (self), ghost_pad); }
static void gst_vaapi_decode_bin_init (GstVaapiDecodeBin * vaapidecbin) { GstPad *pad, *ghostpad; vaapidecbin->deinterlace_method = DEFAULT_DEINTERLACE_METHOD; vaapidecbin->disable_vpp = (g_getenv ("GST_VAAPI_DISABLE_VPP") != NULL); /* create the decoder */ vaapidecbin->decoder = g_object_new (g_type_from_name ("GstVaapiDecode"), NULL); g_assert (vaapidecbin->decoder); /* create the queue */ vaapidecbin->queue = gst_element_factory_make ("queue", "vaapi-queue"); if (!vaapidecbin->queue) { g_clear_object (&vaapidecbin->decoder); post_missing_element_message (vaapidecbin, "queue"); return; } gst_bin_add_many (GST_BIN (vaapidecbin), vaapidecbin->decoder, vaapidecbin->queue, NULL); if (!gst_element_link (vaapidecbin->decoder, vaapidecbin->queue)) { g_clear_object (&vaapidecbin->decoder); g_clear_object (&vaapidecbin->queue); g_critical ("failed to link decoder and queue"); return; } /* create ghost pad sink */ pad = gst_element_get_static_pad (vaapidecbin->decoder, "sink"); ghostpad = gst_ghost_pad_new_from_template ("sink", pad, GST_PAD_PAD_TEMPLATE (pad)); gst_object_unref (pad); if (!gst_element_add_pad (GST_ELEMENT (vaapidecbin), ghostpad)) g_critical ("failed to add decoder sink pad to bin"); /* create ghost pad src */ pad = gst_element_get_static_pad (GST_ELEMENT (vaapidecbin->queue), "src"); ghostpad = gst_ghost_pad_new_from_template ("src", pad, GST_PAD_PAD_TEMPLATE (pad)); gst_object_unref (pad); if (!gst_element_add_pad (GST_ELEMENT (vaapidecbin), ghostpad)) g_critical ("failed to add queue source pad to bin"); }
static gboolean kms_base_hub_link_src_pad (KmsBaseHub * mixer, const gchar * gp_name, const gchar * template_name, GstElement * internal_element, const gchar * pad_name, gboolean remove_on_unlink) { GstPad *gp, *target; gboolean ret; if (GST_OBJECT_PARENT (internal_element) != GST_OBJECT (mixer)) { GST_ERROR_OBJECT (mixer, "Cannot link %" GST_PTR_FORMAT " wrong hierarchy", internal_element); return FALSE; } target = gst_element_get_static_pad (internal_element, pad_name); if (target == NULL) { target = gst_element_get_request_pad (internal_element, pad_name); if (target != NULL && remove_on_unlink) { g_signal_connect (G_OBJECT (target), "unlinked", G_CALLBACK (remove_unlinked_pad), NULL); } } if (target == NULL) { GST_ERROR_OBJECT (mixer, "Cannot get target pad"); return FALSE; } gp = gst_element_get_static_pad (GST_ELEMENT (mixer), gp_name); if (gp == NULL) { GstPadTemplate *templ; templ = gst_element_class_get_pad_template (GST_ELEMENT_CLASS (G_OBJECT_GET_CLASS (mixer)), template_name); gp = gst_ghost_pad_new_from_template (gp_name, target, templ); if (GST_STATE (mixer) >= GST_STATE_PAUSED || GST_STATE_PENDING (mixer) >= GST_STATE_PAUSED || GST_STATE_TARGET (mixer) >= GST_STATE_PAUSED) { gst_pad_set_active (gp, TRUE); } ret = gst_element_add_pad (GST_ELEMENT (mixer), gp); if (!ret) { g_object_unref (gp); } } else { ret = set_target (gp, target); g_object_unref (gp); } g_object_unref (target); return ret; }
GstPad* webkitGstGhostPadFromStaticTemplate(GstStaticPadTemplate* staticPadTemplate, const gchar* name, GstPad* target) { GstPad* pad; GstPadTemplate* padTemplate = gst_static_pad_template_get(staticPadTemplate); if (target) pad = gst_ghost_pad_new_from_template(name, target, padTemplate); else pad = gst_ghost_pad_new_no_target_from_template(name, padTemplate); gst_object_unref(padTemplate); return pad; }
static GstPad * kms_element_generate_src_pad (KmsElement * element, const gchar * name, GstElement * agnosticbin, GstPadTemplate * templ) { GstPad *agnostic_pad; GstPad *ret_pad; if (agnosticbin == NULL) return NULL; agnostic_pad = gst_element_get_request_pad (agnosticbin, "src_%u"); ret_pad = gst_ghost_pad_new_from_template (name, agnostic_pad, templ); g_object_unref (agnostic_pad); return ret_pad; }
static void kms_agnostic_bin2_init (KmsAgnosticBin2 * self) { GstPadTemplate *templ; GstElement *tee, *fakesink; GstPad *target, *sink; self->priv = KMS_AGNOSTIC_BIN2_GET_PRIVATE (self); tee = gst_element_factory_make ("tee", NULL); self->priv->input_tee = tee; fakesink = gst_element_factory_make ("fakesink", NULL); g_object_set (fakesink, "async", FALSE, "sync", FALSE, NULL); gst_bin_add_many (GST_BIN (self), tee, fakesink, NULL); gst_element_link_many (tee, fakesink, NULL); target = gst_element_get_static_pad (tee, "sink"); templ = gst_static_pad_template_get (&sink_factory); self->priv->sink = gst_ghost_pad_new_from_template ("sink", target, templ); gst_pad_set_query_function (self->priv->sink, kms_agnostic_bin2_sink_query); gst_pad_set_chain_function (self->priv->sink, kms_agnostic_bin2_sink_chain); gst_pad_set_chain_list_function (self->priv->sink, kms_agnostic_bin2_sink_chain_list); kms_utils_manage_gaps (self->priv->sink); g_object_unref (templ); g_object_unref (target); sink = gst_element_get_static_pad (fakesink, "sink"); gst_pad_add_probe (sink, GST_PAD_PROBE_TYPE_EVENT_DOWNSTREAM, kms_agnostic_bin2_sink_caps_probe, self, NULL); g_object_unref (sink); gst_element_add_pad (GST_ELEMENT (self), self->priv->sink); self->priv->started = FALSE; self->priv->remove_pool = g_thread_pool_new (remove_on_unlinked_async, NULL, -1, FALSE, NULL); self->priv->bins = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, g_object_unref); g_rec_mutex_init (&self->priv->thread_mutex); self->priv->min_bitrate = MIN_BITRATE_DEFAULT; self->priv->max_bitrate = MAX_BITRATE_DEFAULT; self->priv->bitrate_unlimited = FALSE; }
static gboolean kms_base_mixer_link_src_pad (KmsBaseMixer * mixer, const gchar * gp_name, const gchar * template_name, GstElement * internal_element, const gchar * pad_name) { GstPad *gp, *target; gboolean ret; if (GST_OBJECT_PARENT (internal_element) != GST_OBJECT (mixer)) { GST_ERROR_OBJECT (mixer, "Cannot link %" GST_PTR_FORMAT " wrong hierarchy", internal_element); return FALSE; } target = gst_element_get_static_pad (internal_element, pad_name); if (target == NULL) { target = gst_element_get_request_pad (internal_element, pad_name); } if (target == NULL) { GST_ERROR_OBJECT (mixer, "Cannot get target pad"); return FALSE; } gp = gst_element_get_static_pad (GST_ELEMENT (mixer), gp_name); if (gp == NULL) { GstPadTemplate *templ; templ = gst_element_class_get_pad_template (GST_ELEMENT_CLASS (G_OBJECT_GET_CLASS (mixer)), template_name); gp = gst_ghost_pad_new_from_template (gp_name, target, templ); ret = gst_element_add_pad (GST_ELEMENT (mixer), gp); if (!ret) { g_object_unref (gp); } } else { ret = gst_ghost_pad_set_target (GST_GHOST_PAD (gp), target); g_object_unref (gp); } g_object_unref (target); return ret; }
static void kms_mixer_endpoint_valve_added (KmsElement * self, GstElement * valve, GstPadTemplate * templ, const gchar * pad_name) { GstPad *src = gst_element_get_static_pad (valve, "src"); GstPad *internal_src = gst_ghost_pad_new_from_template (pad_name, src, templ); g_object_set_data_full (G_OBJECT (internal_src), KEY_VALVE_DATA, g_object_ref (valve), g_object_unref); g_signal_connect (internal_src, "linked", G_CALLBACK (kms_mixer_end_point_internal_src_pad_linked), NULL); internal_src->unlinkfunc = GST_DEBUG_FUNCPTR (kms_mixer_end_point_internal_src_pad_unlinked); gst_element_add_pad (GST_ELEMENT (self), internal_src); g_object_unref (src); }
static GstPad * kms_mixer_endpoint_generate_sink_pad (GstElement * element, GstPadTemplate * templ, const gchar * name, const GstCaps * caps, GstElement * agnosticbin) { GstPad *agnostic_pad, *pad; agnostic_pad = gst_element_get_static_pad (agnosticbin, "sink"); pad = gst_ghost_pad_new_from_template (name, agnostic_pad, templ); g_object_unref (agnostic_pad); if (gst_element_add_pad (element, pad)) return pad; GST_ERROR_OBJECT (element, "Cannot add pad %" GST_PTR_FORMAT, pad); g_object_unref (pad); return NULL; }
GstPad * kms_element_connect_sink_target_full (KmsElement * self, GstPad * target, KmsElementPadType type, const gchar * description) { GstPad *pad; gchar *pad_name; GstPadTemplate *templ; templ = gst_static_pad_template_get (&sink_factory); pad_name = get_pad_name (type, description); pad = gst_ghost_pad_new_from_template (pad_name, target, templ); g_free (pad_name); g_object_unref (templ); if (type == KMS_ELEMENT_PAD_TYPE_VIDEO) { kms_utils_drop_until_keyframe (pad, TRUE); kms_utils_manage_gaps (pad); } gst_pad_set_query_function (pad, kms_element_pad_query); gst_pad_add_probe (pad, GST_PAD_PROBE_TYPE_EVENT_DOWNSTREAM | GST_PAD_PROBE_TYPE_EVENT_FLUSH, accept_eos_probe, self, NULL); g_signal_connect (G_OBJECT (pad), "unlinked", G_CALLBACK (send_flush_on_unlink), NULL); if (GST_STATE (self) >= GST_STATE_PAUSED || GST_STATE_PENDING (self) >= GST_STATE_PAUSED || GST_STATE_TARGET (self) >= GST_STATE_PAUSED) { gst_pad_set_active (pad, TRUE); } if (gst_element_add_pad (GST_ELEMENT (self), pad)) { kms_element_set_sink_input_stats (self, pad, type); return pad; } g_object_unref (pad); return NULL; }
static void gst_vaapi_decode_bin_init (GstVaapiDecodeBin * vaapidecbin) { GstPad *element_pad, *ghost_pad; /* let's assume we have VPP until we prove the opposite */ vaapidecbin->has_vpp = TRUE; if (!gst_vaapi_decode_bin_configure (vaapidecbin)) return; /* create ghost pad sink */ element_pad = gst_element_get_static_pad (GST_ELEMENT (vaapidecbin->decoder), "sink"); ghost_pad = gst_ghost_pad_new_from_template ("sink", element_pad, GST_PAD_PAD_TEMPLATE (element_pad)); gst_object_unref (element_pad); gst_element_add_pad (GST_ELEMENT (vaapidecbin), ghost_pad); }
static void gst_insert_bin_init (GstInsertBin * self) { GstProxyPad *internal; self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, GST_TYPE_INSERT_BIN, GstInsertBinPrivate); g_queue_init (&self->priv->change_queue); self->priv->sinkpad = gst_ghost_pad_new_no_target_from_template ("sink", gst_element_class_get_pad_template (GST_ELEMENT_GET_CLASS (self), "sink")); gst_element_add_pad (GST_ELEMENT (self), self->priv->sinkpad); internal = gst_proxy_pad_get_internal (GST_PROXY_PAD (self->priv->sinkpad)); self->priv->srcpad = gst_ghost_pad_new_from_template ("src", GST_PAD (internal), gst_element_class_get_pad_template (GST_ELEMENT_GET_CLASS (self), "src")); gst_object_unref (internal); gst_element_add_pad (GST_ELEMENT (self), self->priv->srcpad); }
static gboolean kms_base_mixer_create_and_link_ghost_pad (KmsBaseMixer * mixer, GstPad * src_pad, const gchar * gp_name, const gchar * gp_template_name, GstPad * target) { GstPadTemplate *templ; GstPad *gp; gboolean ret; templ = gst_element_class_get_pad_template (GST_ELEMENT_CLASS (G_OBJECT_GET_CLASS (mixer)), gp_template_name); gp = gst_ghost_pad_new_from_template (gp_name, target, templ); ret = gst_element_add_pad (GST_ELEMENT (mixer), gp); if (ret) { gst_pad_link (src_pad, gp); } else { g_object_unref (gp); } return ret; }
gboolean fs_rtp_sub_stream_add_output_ghostpad_unlock (FsRtpSubStream *substream, GError **error) { GstPad *valve_srcpad; gchar *padname = NULL; GstPad *ghostpad = NULL; FsCodec *codec = NULL; if (fs_rtp_sub_stream_has_stopped_enter (substream)) { FS_RTP_SESSION_UNLOCK (substream->priv->session); return TRUE; } if (substream->priv->adding_output_ghostpad) { FS_RTP_SESSION_UNLOCK (substream->priv->session); goto out; } g_assert (substream->priv->output_ghostpad == NULL); substream->priv->adding_output_ghostpad = TRUE; padname = g_strdup_printf ("src_%u_%u_%d", substream->priv->session->id, substream->ssrc, substream->pt); FS_RTP_SESSION_UNLOCK (substream->priv->session); valve_srcpad = gst_element_get_static_pad (substream->priv->output_valve, "src"); g_assert (valve_srcpad); ghostpad = gst_ghost_pad_new_from_template (padname, valve_srcpad, gst_element_class_get_pad_template ( GST_ELEMENT_GET_CLASS (substream->priv->conference), "src_%d_%d_%d")); gst_object_unref (valve_srcpad); g_free (padname); if (!ghostpad) { g_set_error (error, FS_ERROR, FS_ERROR_CONSTRUCTION, "Could not build ghostpad src_%u_%u_%d", substream->priv->session->id, substream->ssrc, substream->pt); goto error; } if (!gst_pad_set_active (ghostpad, TRUE)) { g_set_error (error, FS_ERROR, FS_ERROR_CONSTRUCTION, "Could not activate the src_%u_%u_%d", substream->priv->session->id, substream->ssrc, substream->pt); gst_object_unref (ghostpad); goto error; } if (!gst_element_add_pad (GST_ELEMENT (substream->priv->conference), ghostpad)) { g_set_error (error, FS_ERROR, FS_ERROR_CONSTRUCTION, "Could add build ghostpad src_%u_%u_%d to the conference", substream->priv->session->id, substream->ssrc, substream->pt); gst_object_unref (ghostpad); goto error; } FS_RTP_SESSION_LOCK (substream->priv->session); substream->priv->output_ghostpad = ghostpad; GST_DEBUG ("Src pad added on substream for ssrc:%X pt:%u " FS_CODEC_FORMAT, substream->ssrc, substream->pt, FS_CODEC_ARGS (substream->codec)); codec = fs_codec_copy (substream->codec); FS_RTP_SESSION_UNLOCK (substream->priv->session); g_signal_emit (substream, signals[SRC_PAD_ADDED], 0, ghostpad, codec); g_signal_emit (substream, signals[CODEC_CHANGED], 0); fs_codec_destroy (codec); g_object_set (substream->priv->output_valve, "drop", FALSE, NULL); out: fs_rtp_sub_stream_has_stopped_exit (substream); return TRUE; error: substream->priv->adding_output_ghostpad = FALSE; fs_rtp_sub_stream_has_stopped_exit (substream); return FALSE; }
static void kms_webrtc_data_session_bin_init (KmsWebRtcDataSessionBin * self) { GstPadTemplate *pad_template; GstPad *pad, *target; gchar *name; self->priv = KMS_WEBRTC_DATA_SESSION_BIN_GET_PRIVATE (self); g_rec_mutex_init (&self->priv->mutex); self->priv->data_channels = g_hash_table_new (g_direct_hash, g_direct_equal); self->priv->channels = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, g_object_unref); self->priv->assoc_id = get_sctp_association_id (); self->priv->session_established = FALSE; self->priv->even_id = 0; self->priv->odd_id = 1; self->priv->pool = g_thread_pool_new (reset_stream_async, self, -1, FALSE, NULL); name = get_decoder_name (self->priv->assoc_id); self->priv->sctpdec = gst_element_factory_make ("sctpdec", name); g_free (name); name = get_encoder_name (self->priv->assoc_id); self->priv->sctpenc = gst_element_factory_make ("sctpenc", name); g_free (name); g_object_set (self->priv->sctpdec, "sctp-association-id", self->priv->assoc_id, NULL); g_object_set (self->priv->sctpenc, "sctp-association-id", self->priv->assoc_id, "use-sock-stream", TRUE, NULL); g_object_bind_property (self, "sctp-local-port", self->priv->sctpdec, "local-sctp-port", G_BINDING_SYNC_CREATE); g_object_bind_property (self, "sctp-remote-port", self->priv->sctpenc, "remote-sctp-port", G_BINDING_SYNC_CREATE); g_signal_connect (self->priv->sctpdec, "pad-added", G_CALLBACK (kms_webrtc_data_session_bin_pad_added), self); g_signal_connect (self->priv->sctpdec, "pad-removed", G_CALLBACK (kms_webrtc_data_session_bin_pad_removed), self); g_signal_connect (self->priv->sctpenc, "sctp-association-established", G_CALLBACK (kms_webrtc_data_session_bin_association_established), self); gst_bin_add_many (GST_BIN (self), self->priv->sctpdec, self->priv->sctpenc, NULL); target = gst_element_get_static_pad (self->priv->sctpdec, "sink"); pad_template = gst_static_pad_template_get (&sink_template); pad = gst_ghost_pad_new_from_template ("sink", target, pad_template); g_object_unref (pad_template); g_object_unref (target); gst_element_add_pad (GST_ELEMENT (self), pad); target = gst_element_get_static_pad (self->priv->sctpenc, "src"); pad_template = gst_static_pad_template_get (&src_template); pad = gst_ghost_pad_new_from_template ("src", target, pad_template); g_object_unref (pad_template); g_object_unref (target); gst_element_add_pad (GST_ELEMENT (self), pad); gst_element_sync_state_with_parent (self->priv->sctpdec); gst_element_sync_state_with_parent (self->priv->sctpenc); }
static gboolean create_elements (RsnDvdBin * dvdbin) { GstPadTemplate *src_templ = NULL; GstPad *src = NULL; GstPad *sink = NULL; RsnDvdBinPadBlockCtx *bctx = NULL; if (!try_create_piece (dvdbin, DVD_ELEM_SOURCE, NULL, RESIN_TYPE_DVDSRC, "dvdsrc", "DVD source")) { return FALSE; } /* FIXME: Locking */ if (dvdbin->device) { g_object_set (G_OBJECT (dvdbin->pieces[DVD_ELEM_SOURCE]), "device", dvdbin->device, NULL); } if (!try_create_piece (dvdbin, DVD_ELEM_DEMUX, NULL, GST_TYPE_FLUPS_DEMUX, "dvddemux", "DVD demuxer")) return FALSE; if (gst_element_link (dvdbin->pieces[DVD_ELEM_SOURCE], dvdbin->pieces[DVD_ELEM_DEMUX]) == FALSE) goto failed_connect; /* Listen for new pads from the demuxer */ g_signal_connect (G_OBJECT (dvdbin->pieces[DVD_ELEM_DEMUX]), "pad-added", G_CALLBACK (demux_pad_added), dvdbin); g_signal_connect (G_OBJECT (dvdbin->pieces[DVD_ELEM_DEMUX]), "no-more-pads", G_CALLBACK (demux_no_more_pads), dvdbin); if (!try_create_piece (dvdbin, DVD_ELEM_MQUEUE, "multiqueue", 0, "mq", "multiqueue")) return FALSE; g_object_set (dvdbin->pieces[DVD_ELEM_MQUEUE], "max-size-time", (7 * GST_SECOND / 10), "max-size-bytes", 0, "max-size-buffers", 0, NULL); /* Decodebin will throw a missing element message to find an MPEG decoder */ if (!try_create_piece (dvdbin, DVD_ELEM_VIDDEC, NULL, RSN_TYPE_VIDEODEC, "viddec", "video decoder")) return FALSE; if (!try_create_piece (dvdbin, DVD_ELEM_PARSET, NULL, RSN_TYPE_RSNPARSETTER, "rsnparsetter", "Aspect ratio adjustment")) return FALSE; src = gst_element_get_static_pad (dvdbin->pieces[DVD_ELEM_VIDDEC], "src"); sink = gst_element_get_static_pad (dvdbin->pieces[DVD_ELEM_PARSET], "sink"); if (src == NULL || sink == NULL) goto failed_viddec_connect; if (GST_PAD_LINK_FAILED (gst_pad_link (src, sink))) goto failed_viddec_connect; gst_object_unref (src); gst_object_unref (sink); src = sink = NULL; src = gst_element_get_static_pad (dvdbin->pieces[DVD_ELEM_PARSET], "src"); if (src == NULL) goto failed_video_ghost; src_templ = gst_static_pad_template_get (&video_src_template); dvdbin->video_pad = gst_ghost_pad_new_from_template ("video", src, src_templ); gst_object_unref (src_templ); if (dvdbin->video_pad == NULL) goto failed_video_ghost; gst_pad_set_active (dvdbin->video_pad, TRUE); bctx = g_slice_new (RsnDvdBinPadBlockCtx); bctx->dvdbin = gst_object_ref (dvdbin); bctx->pad = gst_object_ref (dvdbin->video_pad); gst_pad_set_blocked_async_full (src, TRUE, (GstPadBlockCallback) dvdbin_pad_blocked_cb, bctx, (GDestroyNotify) _pad_block_destroy_notify); gst_object_unref (src); src = NULL; if (!try_create_piece (dvdbin, DVD_ELEM_SPU_SELECT, NULL, RSN_TYPE_STREAM_SELECTOR, "subpselect", "Subpicture stream selector")) return FALSE; /* Add a single standalone queue to hold a single buffer of SPU data */ if (!try_create_piece (dvdbin, DVD_ELEM_SPUQ, "queue", 0, "spu_q", "subpicture decoder buffer")) return FALSE; g_object_set (dvdbin->pieces[DVD_ELEM_SPUQ], "max-size-time", G_GUINT64_CONSTANT (0), "max-size-bytes", 0, "max-size-buffers", 1, NULL); src = gst_element_get_static_pad (dvdbin->pieces[DVD_ELEM_SPU_SELECT], "src"); sink = gst_element_get_static_pad (dvdbin->pieces[DVD_ELEM_SPUQ], "sink"); if (src == NULL || sink == NULL) goto failed_spuq_connect; if (GST_PAD_LINK_FAILED (gst_pad_link (src, sink))) goto failed_spuq_connect; gst_object_unref (src); gst_object_unref (sink); src = sink = NULL; src = gst_element_get_static_pad (dvdbin->pieces[DVD_ELEM_SPUQ], "src"); if (src == NULL) goto failed_spu_ghost; src_templ = gst_static_pad_template_get (&subpicture_src_template); dvdbin->subpicture_pad = gst_ghost_pad_new_from_template ("subpicture", src, src_templ); gst_object_unref (src_templ); if (dvdbin->subpicture_pad == NULL) goto failed_spu_ghost; gst_pad_set_active (dvdbin->subpicture_pad, TRUE); bctx = g_slice_new (RsnDvdBinPadBlockCtx); bctx->dvdbin = gst_object_ref (dvdbin); bctx->pad = gst_object_ref (dvdbin->subpicture_pad); gst_pad_set_blocked_async_full (src, TRUE, (GstPadBlockCallback) dvdbin_pad_blocked_cb, bctx, (GDestroyNotify) _pad_block_destroy_notify); gst_object_unref (src); src = NULL; if (!try_create_piece (dvdbin, DVD_ELEM_AUD_SELECT, NULL, RSN_TYPE_STREAM_SELECTOR, "audioselect", "Audio stream selector")) return FALSE; if (!try_create_piece (dvdbin, DVD_ELEM_AUDDEC, NULL, RSN_TYPE_AUDIODEC, "auddec", "audio decoder")) return FALSE; /* rsnaudiomunge goes after the audio decoding to regulate the stream */ if (!try_create_piece (dvdbin, DVD_ELEM_AUD_MUNGE, NULL, RSN_TYPE_AUDIOMUNGE, "audiomunge", "Audio output filter")) return FALSE; src = gst_element_get_static_pad (dvdbin->pieces[DVD_ELEM_AUDDEC], "src"); sink = gst_element_get_static_pad (dvdbin->pieces[DVD_ELEM_AUD_MUNGE], "sink"); if (src == NULL || sink == NULL) goto failed_aud_connect; if (GST_PAD_LINK_FAILED (gst_pad_link (src, sink))) goto failed_aud_connect; gst_object_unref (sink); gst_object_unref (src); src = sink = NULL; src = gst_element_get_static_pad (dvdbin->pieces[DVD_ELEM_AUD_SELECT], "src"); sink = gst_element_get_static_pad (dvdbin->pieces[DVD_ELEM_AUDDEC], "sink"); if (src == NULL || sink == NULL) goto failed_aud_connect; if (GST_PAD_LINK_FAILED (gst_pad_link (src, sink))) goto failed_aud_connect; gst_object_unref (sink); gst_object_unref (src); src = sink = NULL; /* ghost audio munge output pad onto bin */ src = gst_element_get_static_pad (dvdbin->pieces[DVD_ELEM_AUD_MUNGE], "src"); if (src == NULL) goto failed_aud_ghost; src_templ = gst_static_pad_template_get (&audio_src_template); dvdbin->audio_pad = gst_ghost_pad_new_from_template ("audio", src, src_templ); gst_object_unref (src_templ); if (dvdbin->audio_pad == NULL) goto failed_aud_ghost; gst_pad_set_active (dvdbin->audio_pad, TRUE); bctx = g_slice_new (RsnDvdBinPadBlockCtx); bctx->dvdbin = gst_object_ref (dvdbin); bctx->pad = gst_object_ref (dvdbin->audio_pad); gst_pad_set_blocked_async_full (src, TRUE, (GstPadBlockCallback) dvdbin_pad_blocked_cb, bctx, (GDestroyNotify) _pad_block_destroy_notify); gst_object_unref (src); src = NULL; if (dvdbin->video_added && (dvdbin->audio_added || dvdbin->audio_broken) && dvdbin->subpicture_added) { GST_DEBUG_OBJECT (dvdbin, "Firing no more pads"); gst_element_no_more_pads (GST_ELEMENT (dvdbin)); } return TRUE; failed_connect: GST_ELEMENT_ERROR (dvdbin, CORE, FAILED, (NULL), ("Could not connect DVD source and demuxer elements")); goto error_out; failed_viddec_connect: GST_ELEMENT_ERROR (dvdbin, CORE, FAILED, (NULL), ("Could not connect DVD video decoder and aspect ratio adjuster")); goto error_out; failed_video_ghost: GST_ELEMENT_ERROR (dvdbin, CORE, FAILED, (NULL), ("Could not ghost video output pad")); goto error_out; failed_spuq_connect: GST_ELEMENT_ERROR (dvdbin, CORE, FAILED, (NULL), ("Could not connect DVD subpicture selector and buffer elements")); goto error_out; failed_spu_ghost: GST_ELEMENT_ERROR (dvdbin, CORE, FAILED, (NULL), ("Could not ghost SPU output pad")); goto error_out; failed_aud_connect: GST_ELEMENT_ERROR (dvdbin, CORE, FAILED, (NULL), ("Could not connect DVD audio decoder")); goto error_out; failed_aud_ghost: GST_ELEMENT_ERROR (dvdbin, CORE, FAILED, (NULL), ("Could not ghost audio output pad")); goto error_out; error_out: if (src != NULL) gst_object_unref (src); if (sink != NULL) gst_object_unref (sink); return FALSE; }
static gboolean gst_vaapi_decode_bin_configure (GstVaapiDecodeBin * vaapidecbin) { gchar *missing_factory = NULL; GstPad *pad, *ghostpad; GstPadTemplate *tmpl; /* create the decoder */ vaapidecbin->decoder = gst_element_factory_make ("vaapidecode", "vaapidecode"); if (!vaapidecbin->decoder) { missing_factory = "vaapidecode"; goto error_element_missing; } /* create the queue */ vaapidecbin->queue = gst_element_factory_make ("queue", "queue"); if (!vaapidecbin->queue) { missing_factory = "queue"; goto error_element_missing; } g_object_set (G_OBJECT (vaapidecbin->queue), "max-size-bytes", vaapidecbin->max_size_bytes, "max-size-buffers", vaapidecbin->max_size_buffers, "max-size-time", vaapidecbin->max_size_time, NULL); gst_bin_add_many (GST_BIN (vaapidecbin), vaapidecbin->decoder, vaapidecbin->queue, NULL); if (!gst_element_link_many (vaapidecbin->decoder, vaapidecbin->queue, NULL)) goto error_link_pad; /* create ghost pad sink */ pad = gst_element_get_static_pad (GST_ELEMENT (vaapidecbin->decoder), "sink"); ghostpad = gst_ghost_pad_new_from_template ("sink", pad, GST_PAD_PAD_TEMPLATE (pad)); gst_object_unref (pad); if (!gst_element_add_pad (GST_ELEMENT (vaapidecbin), ghostpad)) goto error_adding_pad; /* create ghost pad src */ pad = gst_element_get_static_pad (GST_ELEMENT (vaapidecbin->queue), "src"); tmpl = gst_static_pad_template_get (&gst_vaapi_decode_bin_src_factory); ghostpad = gst_ghost_pad_new_from_template ("src", pad, tmpl); gst_object_unref (pad); gst_object_unref (tmpl); if (!gst_element_add_pad (GST_ELEMENT (vaapidecbin), ghostpad)) goto error_adding_pad; return TRUE; error_element_missing: { post_missing_element_message (vaapidecbin, missing_factory); return FALSE; } error_link_pad: { GST_ELEMENT_ERROR (vaapidecbin, CORE, PAD, (NULL), ("Failed to configure the vaapidecodebin.")); return FALSE; } error_adding_pad: { GST_ELEMENT_ERROR (vaapidecbin, CORE, PAD, (NULL), ("Failed to adding pads.")); return FALSE; } }
static GstPad * gst_sctp_base_sink_request_new_pad (GstElement * element, GstPadTemplate * templ, const gchar * name, const GstCaps * caps) { GstSCTPBaseSink *self = GST_SCTP_BASE_SINK (element); GstPad *sinkpad, *ghostpad; GstElement *sctpclientsink; gchar *padname; gchar *pad_id; gint64 val; guint16 id; GST_SCTP_BASE_SINK_LOCK (self); if (self->priv->num_ostreams < self->priv->streams) { GST_SCTP_BASE_SINK_UNLOCK (self); GST_WARNING ("No more available streams"); return NULL; } pad_id = get_stream_id_from_padname (name); if (pad_id == NULL) { GST_SCTP_BASE_SINK_UNLOCK (self); GST_WARNING ("Link of elements without using pad names is not yet supported"); return NULL; } val = g_ascii_strtoll (pad_id, NULL, 10); g_free (pad_id); if (val > G_MAXUINT32) { GST_SCTP_BASE_SINK_UNLOCK (self); GST_ERROR ("SCTP stream id %" G_GINT64_FORMAT " is not valid", val); return NULL; } id = val; sctpclientsink = gst_element_factory_make ("sctpclientsink", NULL); sinkpad = gst_element_get_static_pad (sctpclientsink, "sink"); if (sinkpad == NULL) { GST_SCTP_BASE_SINK_UNLOCK (self); GST_ERROR_OBJECT (sctpclientsink, "Can not get sink pad"); gst_object_unref (sctpclientsink); return NULL; } g_object_set (sctpclientsink, "stream-id", id, "socket", self->priv->socket, NULL); gst_bin_add (GST_BIN (element), sctpclientsink); gst_element_sync_state_with_parent (sctpclientsink); padname = g_strdup_printf ("sink_%u", id); ghostpad = gst_ghost_pad_new_from_template (padname, sinkpad, templ); g_object_unref (sinkpad); g_free (padname); 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 (ghostpad, TRUE); gst_element_add_pad (element, ghostpad); self->priv->streams++; GST_SCTP_BASE_SINK_UNLOCK (self); return ghostpad; }
static gboolean create_elements (RsnDvdBin * dvdbin) { GstPadTemplate *src_templ = NULL; GstPad *src = NULL; GstPad *sink = NULL; RsnDvdBinPadBlockCtx *bctx = NULL; if (!try_create_piece (dvdbin, DVD_ELEM_SOURCE, NULL, RESIN_TYPE_DVDSRC, "dvdsrc", "DVD source")) { return FALSE; } /* FIXME: Locking */ if (dvdbin->device) { g_object_set (G_OBJECT (dvdbin->pieces[DVD_ELEM_SOURCE]), "device", dvdbin->device, NULL); } /* FIXME: Import and use local copy of mpeg PS demuxer */ if (!try_create_piece (dvdbin, DVD_ELEM_DEMUX, NULL, GST_TYPE_FLUPS_DEMUX, "dvddemux", "DVD demuxer")) return FALSE; if (gst_element_link (dvdbin->pieces[DVD_ELEM_SOURCE], dvdbin->pieces[DVD_ELEM_DEMUX]) == FALSE) goto failed_connect; /* Listen for new pads from the demuxer */ g_signal_connect (G_OBJECT (dvdbin->pieces[DVD_ELEM_DEMUX]), "pad-added", G_CALLBACK (demux_pad_added), dvdbin); g_signal_connect (G_OBJECT (dvdbin->pieces[DVD_ELEM_DEMUX]), "no-more-pads", G_CALLBACK (demux_no_more_pads), dvdbin); if (!try_create_piece (dvdbin, DVD_ELEM_MQUEUE, "multiqueue", 0, "rsnmq", "multiqueue")) return FALSE; g_object_set (dvdbin->pieces[DVD_ELEM_MQUEUE], "max-size-time", (7 * GST_SECOND / 10), "max-size-bytes", 0, "max-size-buffers", 0, NULL); if (!try_create_piece (dvdbin, DVD_ELEM_VIDPARSE, "mpegvideoparse", 0, "rsnvidparse", "video parser")) return FALSE; /* Decodebin will throw a missing element message to find an MPEG decoder */ if (!try_create_piece (dvdbin, DVD_ELEM_VIDDEC, NULL, RSN_TYPE_VIDEODEC, "rsnviddec", "video decoder")) return FALSE; /* FIXME: Replace identity */ if (!try_create_piece (dvdbin, DVD_ELEM_PARSET, NULL, RSN_TYPE_RSNPARSETTER, "rsnparsetter", "Aspect ratio adjustment")) return FALSE; if (!try_link_pieces (dvdbin->pieces[DVD_ELEM_VIDPARSE], "src", dvdbin->pieces[DVD_ELEM_VIDDEC], "sink")) goto failed_vidparse_connect; src = gst_element_get_static_pad (dvdbin->pieces[DVD_ELEM_VIDDEC], "src"); sink = gst_element_get_static_pad (dvdbin->pieces[DVD_ELEM_PARSET], "sink"); if (src == NULL || sink == NULL) goto failed_viddec_connect; if (GST_PAD_LINK_FAILED (gst_pad_link (src, sink))) goto failed_viddec_connect; gst_object_unref (src); gst_object_unref (sink); src = sink = NULL; src = gst_element_get_static_pad (dvdbin->pieces[DVD_ELEM_PARSET], "src"); if (src == NULL) goto failed_video_ghost; src_templ = gst_static_pad_template_get (&video_src_template); dvdbin->video_pad = gst_ghost_pad_new_from_template ("video", src, src_templ); gst_object_unref (src_templ); if (dvdbin->video_pad == NULL) goto failed_video_ghost; gst_pad_set_active (dvdbin->video_pad, TRUE); bctx = g_slice_new (RsnDvdBinPadBlockCtx); bctx->dvdbin = gst_object_ref (dvdbin); bctx->pad = gst_object_ref (dvdbin->video_pad); bctx->pad_block_id = gst_pad_add_probe (src, GST_PAD_PROBE_TYPE_BLOCK_DOWNSTREAM, (GstPadProbeCallback) dvdbin_pad_blocked_cb, bctx, (GDestroyNotify) _pad_block_destroy_notify); gst_object_unref (src); src = NULL; #if DEBUG_TIMING gst_pad_add_probe (dvdbin->video_pad, GST_PAD_PROBE_TYPE_EVENT_DOWNSTREAM | GST_PAD_PROBE_TYPE_BUFFER | GST_PAD_PROBE_TYPE_EVENT_FLUSH, (GstPadProbeCallback) dvdbin_dump_timing_info, NULL, NULL); #endif /* FIXME: Merge stream-selection logic to core and switch back */ if (!try_create_piece (dvdbin, DVD_ELEM_SPU_SELECT, NULL, RSN_TYPE_INPUT_SELECTOR, "subpselect", "Subpicture stream selector")) return FALSE; g_object_set (G_OBJECT (dvdbin->pieces[DVD_ELEM_SPU_SELECT]), "sync-streams", FALSE, NULL); /* Add a single standalone queue to hold a single buffer of SPU data */ if (!try_create_piece (dvdbin, DVD_ELEM_SPUQ, "queue", 0, "spu_q", "subpicture decoder buffer")) return FALSE; /* Allow a lot more while pre-rolling */ g_object_set (dvdbin->pieces[DVD_ELEM_SPUQ], "max-size-time", G_GUINT64_CONSTANT (0), "max-size-bytes", 0, "max-size-buffers", 100, NULL); src = gst_element_get_static_pad (dvdbin->pieces[DVD_ELEM_SPU_SELECT], "src"); sink = gst_element_get_static_pad (dvdbin->pieces[DVD_ELEM_SPUQ], "sink"); if (src == NULL || sink == NULL) goto failed_spuq_connect; if (GST_PAD_LINK_FAILED (gst_pad_link (src, sink))) goto failed_spuq_connect; gst_object_unref (src); gst_object_unref (sink); src = sink = NULL; src = gst_element_get_static_pad (dvdbin->pieces[DVD_ELEM_SPUQ], "src"); if (src == NULL) goto failed_spu_ghost; src_templ = gst_static_pad_template_get (&subpicture_src_template); dvdbin->subpicture_pad = gst_ghost_pad_new_from_template ("subpicture", src, src_templ); gst_object_unref (src_templ); if (dvdbin->subpicture_pad == NULL) goto failed_spu_ghost; gst_pad_set_active (dvdbin->subpicture_pad, TRUE); bctx = g_slice_new (RsnDvdBinPadBlockCtx); bctx->dvdbin = gst_object_ref (dvdbin); bctx->pad = gst_object_ref (dvdbin->subpicture_pad); bctx->pad_block_id = gst_pad_add_probe (src, GST_PAD_PROBE_TYPE_BLOCK_DOWNSTREAM, (GstPadProbeCallback) dvdbin_pad_blocked_cb, bctx, (GDestroyNotify) _pad_block_destroy_notify); gst_object_unref (src); src = NULL; if (!try_create_piece (dvdbin, DVD_ELEM_AUD_SELECT, NULL, RSN_TYPE_INPUT_SELECTOR, "audioselect", "Audio stream selector")) return FALSE; g_object_set (G_OBJECT (dvdbin->pieces[DVD_ELEM_AUD_SELECT]), "sync-streams", FALSE, NULL); if (!try_create_piece (dvdbin, DVD_ELEM_AUDDEC, NULL, RSN_TYPE_AUDIODEC, "auddec", "audio decoder")) return FALSE; src = gst_element_get_static_pad (dvdbin->pieces[DVD_ELEM_AUD_SELECT], "src"); sink = gst_element_get_static_pad (dvdbin->pieces[DVD_ELEM_AUDDEC], "sink"); if (src == NULL || sink == NULL) goto failed_aud_connect; if (GST_PAD_LINK_FAILED (gst_pad_link (src, sink))) goto failed_aud_connect; gst_object_unref (sink); gst_object_unref (src); src = sink = NULL; /* ghost audio munge output pad onto bin */ src = gst_element_get_static_pad (dvdbin->pieces[DVD_ELEM_AUDDEC], "src"); if (src == NULL) goto failed_aud_ghost; src_templ = gst_static_pad_template_get (&audio_src_template); dvdbin->audio_pad = gst_ghost_pad_new_from_template ("audio", src, src_templ); gst_object_unref (src_templ); if (dvdbin->audio_pad == NULL) goto failed_aud_ghost; gst_pad_set_active (dvdbin->audio_pad, TRUE); bctx = g_slice_new (RsnDvdBinPadBlockCtx); bctx->dvdbin = gst_object_ref (dvdbin); bctx->pad = gst_object_ref (dvdbin->audio_pad); bctx->pad_block_id = gst_pad_add_probe (src, GST_PAD_PROBE_TYPE_BLOCK_DOWNSTREAM, (GstPadProbeCallback) dvdbin_pad_blocked_cb, bctx, (GDestroyNotify) _pad_block_destroy_notify); gst_object_unref (src); src = NULL; if (dvdbin->video_added && (dvdbin->audio_added || dvdbin->audio_broken) && dvdbin->subpicture_added) { rsn_dvdbin_no_more_pads (dvdbin); } return TRUE; failed_connect: GST_ELEMENT_ERROR (dvdbin, CORE, FAILED, (NULL), ("Could not connect DVD source and demuxer elements")); goto error_out; failed_vidparse_connect: GST_ELEMENT_ERROR (dvdbin, CORE, FAILED, (NULL), ("Could not connect DVD video parser and video decoder")); goto error_out; failed_viddec_connect: GST_ELEMENT_ERROR (dvdbin, CORE, FAILED, (NULL), ("Could not connect DVD video decoder and aspect ratio adjuster")); goto error_out; failed_video_ghost: GST_ELEMENT_ERROR (dvdbin, CORE, FAILED, (NULL), ("Could not ghost video output pad")); goto error_out; failed_spuq_connect: GST_ELEMENT_ERROR (dvdbin, CORE, FAILED, (NULL), ("Could not connect DVD subpicture selector and buffer elements")); goto error_out; failed_spu_ghost: GST_ELEMENT_ERROR (dvdbin, CORE, FAILED, (NULL), ("Could not ghost SPU output pad")); goto error_out; failed_aud_connect: GST_ELEMENT_ERROR (dvdbin, CORE, FAILED, (NULL), ("Could not connect DVD audio decoder")); goto error_out; failed_aud_ghost: GST_ELEMENT_ERROR (dvdbin, CORE, FAILED, (NULL), ("Could not ghost audio output pad")); goto error_out; error_out: if (src != NULL) gst_object_unref (src); if (sink != NULL) gst_object_unref (sink); return FALSE; }