static GstPad * mpegtsmux_request_new_pad (GstElement * element, GstPadTemplate * templ, const gchar * name) { MpegTsMux *mux = GST_MPEG_TSMUX (element); gint pid = -1; gchar *pad_name = NULL; GstPad *pad = NULL; MpegTsPadData *pad_data = NULL; if (name != NULL && sscanf (name, "sink_%d", &pid) == 1) { if (tsmux_find_stream (mux->tsmux, pid)) goto stream_exists; } else { pid = tsmux_get_new_pid (mux->tsmux); } pad_name = g_strdup_printf ("sink_%d", pid); pad = gst_pad_new_from_template (templ, pad_name); g_free (pad_name); pad_data = (MpegTsPadData *) gst_collect_pads_add_pad (mux->collect, pad, sizeof (MpegTsPadData)); if (pad_data == NULL) goto pad_failure; pad_data->pid = pid; pad_data->last_ts = GST_CLOCK_TIME_NONE; pad_data->codec_data = NULL; pad_data->prepare_func = NULL; if (G_UNLIKELY (!gst_element_add_pad (element, pad))) goto could_not_add; return pad; stream_exists: GST_ELEMENT_ERROR (element, STREAM, MUX, ("Duplicate PID requested"), (NULL)); return NULL; could_not_add: GST_ELEMENT_ERROR (element, STREAM, FAILED, ("Internal data stream error."), ("Could not add pad to element")); gst_collect_pads_remove_pad (mux->collect, pad); gst_object_unref (pad); return NULL; pad_failure: GST_ELEMENT_ERROR (element, STREAM, FAILED, ("Internal data stream error."), ("Could not add pad to collectpads")); gst_object_unref (pad); return NULL; }
static GstPad * gst_mxf_mux_request_new_pad (GstElement * element, GstPadTemplate * templ, const gchar * pad_name) { GstMXFMux *mux = GST_MXF_MUX (element); GstMXFMuxPad *cpad; GstPad *pad = NULL; guint pad_number; gchar *name = NULL; const MXFEssenceElementWriter *writer; if (mux->state != GST_MXF_MUX_STATE_HEADER) { GST_WARNING_OBJECT (mux, "Can't request pads after writing header"); return NULL; } writer = mxf_essence_element_writer_find (templ); if (!writer) { GST_ERROR_OBJECT (mux, "Not our template"); return NULL; } pad_number = g_atomic_int_exchange_and_add ((gint *) & mux->n_pads, 1); name = gst_mxf_mux_create_pad_name (templ, pad_number); GST_DEBUG_OBJECT (mux, "Creating pad '%s'", name); pad = gst_pad_new_from_template (templ, name); g_free (name); cpad = (GstMXFMuxPad *) gst_collect_pads_add_pad (mux->collect, pad, sizeof (GstMXFMuxPad)); cpad->last_timestamp = 0; cpad->adapter = gst_adapter_new (); cpad->writer = writer; /* FIXME: hacked way to override/extend the event function of * GstCollectPads; because it sets its own event function giving the * element no access to events. */ mux->collect_event = (GstPadEventFunction) GST_PAD_EVENTFUNC (pad); gst_pad_set_event_function (pad, GST_DEBUG_FUNCPTR (gst_mxf_mux_handle_sink_event)); gst_pad_set_setcaps_function (pad, gst_mxf_mux_setcaps); gst_pad_use_fixed_caps (pad); gst_pad_set_active (pad, TRUE); gst_element_add_pad (element, pad); return pad; }
static void gst_smpte_init (GstSMPTE * smpte) { smpte->sinkpad1 = gst_pad_new_from_static_template (&gst_smpte_sink1_template, "sink1"); GST_PAD_SET_PROXY_CAPS (smpte->sinkpad1); gst_element_add_pad (GST_ELEMENT (smpte), smpte->sinkpad1); smpte->sinkpad2 = gst_pad_new_from_static_template (&gst_smpte_sink2_template, "sink2"); GST_PAD_SET_PROXY_CAPS (smpte->sinkpad2); gst_element_add_pad (GST_ELEMENT (smpte), smpte->sinkpad2); smpte->srcpad = gst_pad_new_from_static_template (&gst_smpte_src_template, "src"); gst_element_add_pad (GST_ELEMENT (smpte), smpte->srcpad); smpte->collect = gst_collect_pads_new (); gst_collect_pads_set_function (smpte->collect, (GstCollectPadsFunction) GST_DEBUG_FUNCPTR (gst_smpte_collected), smpte); gst_collect_pads_set_event_function (smpte->collect, GST_DEBUG_FUNCPTR (gst_smpte_sink_event), smpte); gst_collect_pads_add_pad (smpte->collect, smpte->sinkpad1, sizeof (GstCollectData), NULL, TRUE); gst_collect_pads_add_pad (smpte->collect, smpte->sinkpad2, sizeof (GstCollectData), NULL, TRUE); smpte->type = DEFAULT_PROP_TYPE; smpte->border = DEFAULT_PROP_BORDER; smpte->depth = DEFAULT_PROP_DEPTH; smpte->duration = DEFAULT_PROP_DURATION; smpte->invert = DEFAULT_PROP_INVERT; smpte->fps_num = 0; smpte->fps_denom = 1; }
static GstPad * gst_multipart_mux_request_new_pad (GstElement * element, GstPadTemplate * templ, const gchar * req_name) { GstMultipartMux *multipart_mux; GstPad *newpad; GstElementClass *klass = GST_ELEMENT_GET_CLASS (element); gchar *name; if (templ != gst_element_class_get_pad_template (klass, "sink_%d")) goto wrong_template; multipart_mux = GST_MULTIPART_MUX (element); /* create new pad with the name */ name = g_strdup_printf ("sink_%02d", multipart_mux->numpads); newpad = gst_pad_new_from_template (templ, name); g_free (name); /* construct our own wrapper data structure for the pad to * keep track of its status */ { GstMultipartPadData *multipartpad; multipartpad = (GstMultipartPadData *) gst_collect_pads_add_pad (multipart_mux->collect, newpad, sizeof (GstMultipartPadData)); /* save a pointer to our data in the pad */ gst_pad_set_element_private (newpad, multipartpad); multipart_mux->numpads++; } /* add the pad to the element */ gst_element_add_pad (element, newpad); return newpad; /* ERRORS */ wrong_template: { g_warning ("multipart_mux: this is not our template!"); return NULL; } }
static GstPad * gst_mxf_mux_request_new_pad (GstElement * element, GstPadTemplate * templ, const gchar * pad_name, const GstCaps * caps) { GstMXFMux *mux = GST_MXF_MUX (element); GstMXFMuxPad *cpad; GstPad *pad = NULL; guint pad_number; gchar *name = NULL; const MXFEssenceElementWriter *writer; if (mux->state != GST_MXF_MUX_STATE_HEADER) { GST_WARNING_OBJECT (mux, "Can't request pads after writing header"); return NULL; } writer = mxf_essence_element_writer_find (templ); if (!writer) { GST_ERROR_OBJECT (mux, "Not our template"); return NULL; } pad_number = g_atomic_int_add ((gint *) & mux->n_pads, 1); name = gst_mxf_mux_create_pad_name (templ, pad_number); GST_DEBUG_OBJECT (mux, "Creating pad '%s'", name); pad = gst_pad_new_from_template (templ, name); g_free (name); cpad = (GstMXFMuxPad *) gst_collect_pads_add_pad (mux->collect, pad, sizeof (GstMXFMuxPad), NULL, TRUE); cpad->last_timestamp = 0; cpad->adapter = gst_adapter_new (); cpad->writer = writer; gst_pad_use_fixed_caps (pad); gst_pad_set_active (pad, TRUE); gst_element_add_pad (element, pad); return pad; }
static GstPad * mpegpsmux_request_new_pad (GstElement * element, GstPadTemplate * templ, const gchar * name) { MpegPsMux *mux = GST_MPEG_PSMUX (element); GstPad *pad = NULL; MpegPsPadData *pad_data = NULL; pad = gst_pad_new_from_template (templ, name); pad_data = (MpegPsPadData *) gst_collect_pads_add_pad (mux->collect, pad, sizeof (MpegPsPadData)); if (pad_data == NULL) goto pad_failure; pad_data->last_ts = GST_CLOCK_TIME_NONE; pad_data->codec_data = NULL; pad_data->prepare_func = NULL; if (G_UNLIKELY (!gst_element_add_pad (element, pad))) goto could_not_add; return pad; could_not_add: GST_ELEMENT_ERROR (element, STREAM, FAILED, ("Internal data stream error."), ("Could not add pad to element")); gst_collect_pads_remove_pad (mux->collect, pad); gst_object_unref (pad); return NULL; pad_failure: GST_ELEMENT_ERROR (element, STREAM, FAILED, ("Internal data stream error."), ("Could not add pad to collectpads")); gst_object_unref (pad); return NULL; }
static GstPad * gst_aggregator_request_new_pad (GstElement * element, GstPadTemplate * templ, const gchar * unused, const GstCaps * caps) { GstAggregator *aggregator = GST_AGGREGATOR (element); gchar *name; GstPad *newpad; gint padcount; if (templ->direction != GST_PAD_SINK) return NULL; /* create new pad */ padcount = g_atomic_int_add (&aggregator->padcount, 1); name = g_strdup_printf ("sink_%u", padcount); newpad = gst_pad_new_from_template (templ, name); g_free (name); gst_collect_pads_add_pad (aggregator->collect, newpad, sizeof (GstCollectData), NULL, TRUE); /* takes ownership of the pad */ if (!gst_element_add_pad (GST_ELEMENT (aggregator), newpad)) goto could_not_add; GST_DEBUG_OBJECT (aggregator, "added new pad %s", GST_OBJECT_NAME (newpad)); return newpad; /* errors */ could_not_add: { GST_DEBUG_OBJECT (aggregator, "could not add pad"); gst_collect_pads_remove_pad (aggregator->collect, newpad); gst_object_unref (newpad); return NULL; } }
static GstPad * gst_interleave_request_new_pad (GstElement * element, GstPadTemplate * templ, const gchar * req_name, const GstCaps * caps) { GstInterleave *self = GST_INTERLEAVE (element); GstPad *new_pad; gchar *pad_name; gint channels, padnumber; GValue val = { 0, }; if (templ->direction != GST_PAD_SINK) goto not_sink_pad; padnumber = g_atomic_int_add (&self->padcounter, 1); if (self->channel_positions_from_input) channels = g_atomic_int_add (&self->channels, 1); else channels = padnumber; pad_name = g_strdup_printf ("sink_%u", padnumber); new_pad = GST_PAD_CAST (g_object_new (GST_TYPE_INTERLEAVE_PAD, "name", pad_name, "direction", templ->direction, "template", templ, NULL)); GST_INTERLEAVE_PAD_CAST (new_pad)->channel = channels; GST_DEBUG_OBJECT (self, "requested new pad %s", pad_name); g_free (pad_name); gst_pad_use_fixed_caps (new_pad); gst_collect_pads_add_pad (self->collect, new_pad, sizeof (GstCollectData), NULL, TRUE); gst_collect_pads_set_event_function (self->collect, (GstCollectPadsEventFunction) GST_DEBUG_FUNCPTR (gst_interleave_sink_event), self); if (!gst_element_add_pad (element, new_pad)) goto could_not_add; g_value_init (&val, GST_TYPE_AUDIO_CHANNEL_POSITION); g_value_set_enum (&val, GST_AUDIO_CHANNEL_POSITION_NONE); self->input_channel_positions = g_value_array_append (self->input_channel_positions, &val); g_value_unset (&val); /* Update the src caps if we already have them */ if (self->sinkcaps) { GstCaps *srccaps; GstStructure *s; /* Take lock to make sure processing finishes first */ GST_OBJECT_LOCK (self->collect); srccaps = gst_caps_copy (self->sinkcaps); s = gst_caps_get_structure (srccaps, 0); gst_structure_set (s, "channels", G_TYPE_INT, self->channels, NULL); gst_interleave_set_channel_positions (self, s); /* FIXME: send caps event after stream-start event */ gst_pad_set_active (self->src, TRUE); gst_pad_set_caps (self->src, srccaps); gst_caps_unref (srccaps); GST_OBJECT_UNLOCK (self->collect); } return new_pad; /* errors */ not_sink_pad: { g_warning ("interleave: requested new pad that is not a SINK pad\n"); return NULL; } could_not_add: { GST_DEBUG_OBJECT (self, "could not add pad %s", GST_PAD_NAME (new_pad)); gst_collect_pads_remove_pad (self->collect, new_pad); gst_object_unref (new_pad); return NULL; } }
static GstPad * gst_ffmpegmux_request_new_pad (GstElement * element, GstPadTemplate * templ, const gchar * name) { GstFFMpegMux *ffmpegmux = (GstFFMpegMux *) element; GstElementClass *klass = GST_ELEMENT_GET_CLASS (element); GstFFMpegMuxPad *collect_pad; gchar *padname; GstPad *pad; AVStream *st; enum CodecType type; gint bitrate = 0, framesize = 0; g_return_val_if_fail (templ != NULL, NULL); g_return_val_if_fail (templ->direction == GST_PAD_SINK, NULL); g_return_val_if_fail (ffmpegmux->opened == FALSE, NULL); /* figure out a name that *we* like */ if (templ == gst_element_class_get_pad_template (klass, "video_%d")) { padname = g_strdup_printf ("video_%d", ffmpegmux->videopads++); type = CODEC_TYPE_VIDEO; bitrate = 64 * 1024; framesize = 1152; } else if (templ == gst_element_class_get_pad_template (klass, "audio_%d")) { padname = g_strdup_printf ("audio_%d", ffmpegmux->audiopads++); type = CODEC_TYPE_AUDIO; bitrate = 285 * 1024; } else { g_warning ("ffmux: unknown pad template!"); return NULL; } /* create pad */ pad = gst_pad_new_from_template (templ, padname); collect_pad = (GstFFMpegMuxPad *) gst_collect_pads_add_pad (ffmpegmux->collect, pad, sizeof (GstFFMpegMuxPad)); collect_pad->padnum = ffmpegmux->context->nb_streams; /* small hack to put our own event pad function and chain up to collect pad */ ffmpegmux->event_function = GST_PAD_EVENTFUNC (pad); gst_pad_set_event_function (pad, GST_DEBUG_FUNCPTR (gst_ffmpegmux_sink_event)); gst_pad_set_setcaps_function (pad, GST_DEBUG_FUNCPTR (gst_ffmpegmux_setcaps)); gst_element_add_pad (element, pad); /* AVStream needs to be created */ st = av_new_stream (ffmpegmux->context, collect_pad->padnum); st->codec->codec_type = type; st->codec->codec_id = CODEC_ID_NONE; /* this is a check afterwards */ st->stream_copy = 1; /* we're not the actual encoder */ st->codec->bit_rate = bitrate; st->codec->frame_size = framesize; /* we fill in codec during capsnego */ /* we love debug output (c) (tm) (r) */ GST_DEBUG ("Created %s pad for ffmux_%s element", padname, ((GstFFMpegMuxClass *) klass)->in_plugin->name); g_free (padname); return pad; }
static void gst_frei0r_mixer_init (GstFrei0rMixer * self, GstFrei0rMixerClass * klass) { self->property_cache = gst_frei0r_property_cache_init (klass->properties, klass->n_properties); self->collect = gst_collect_pads_new (); gst_collect_pads_set_function (self->collect, (GstCollectPadsFunction) gst_frei0r_mixer_collected, self); self->src = gst_pad_new_from_template (gst_element_class_get_pad_template (GST_ELEMENT_CLASS (klass), "src"), "src"); gst_pad_set_getcaps_function (self->src, GST_DEBUG_FUNCPTR (gst_frei0r_mixer_get_caps)); gst_pad_set_setcaps_function (self->src, GST_DEBUG_FUNCPTR (gst_frei0r_mixer_set_caps)); gst_pad_set_query_function (self->src, GST_DEBUG_FUNCPTR (gst_frei0r_mixer_src_query)); gst_pad_set_event_function (self->src, GST_DEBUG_FUNCPTR (gst_frei0r_mixer_src_event)); gst_element_add_pad (GST_ELEMENT_CAST (self), self->src); self->sink0 = gst_pad_new_from_template (gst_element_class_get_pad_template (GST_ELEMENT_CLASS (klass), "sink_0"), "sink_0"); gst_pad_set_getcaps_function (self->sink0, GST_DEBUG_FUNCPTR (gst_frei0r_mixer_get_caps)); gst_pad_set_setcaps_function (self->sink0, GST_DEBUG_FUNCPTR (gst_frei0r_mixer_set_caps)); gst_pad_set_query_function (self->sink0, GST_DEBUG_FUNCPTR (gst_frei0r_mixer_sink_query)); gst_collect_pads_add_pad (self->collect, self->sink0, sizeof (GstCollectData)); self->collect_event = (GstPadEventFunction) GST_PAD_EVENTFUNC (self->sink0); gst_pad_set_event_function (self->sink0, GST_DEBUG_FUNCPTR (gst_frei0r_mixer_sink0_event)); gst_element_add_pad (GST_ELEMENT_CAST (self), self->sink0); self->sink1 = gst_pad_new_from_template (gst_element_class_get_pad_template (GST_ELEMENT_CLASS (klass), "sink_1"), "sink_1"); gst_pad_set_getcaps_function (self->sink1, GST_DEBUG_FUNCPTR (gst_frei0r_mixer_get_caps)); gst_pad_set_setcaps_function (self->sink1, GST_DEBUG_FUNCPTR (gst_frei0r_mixer_set_caps)); gst_pad_set_query_function (self->sink0, GST_DEBUG_FUNCPTR (gst_frei0r_mixer_sink_query)); gst_collect_pads_add_pad (self->collect, self->sink1, sizeof (GstCollectData)); gst_element_add_pad (GST_ELEMENT_CAST (self), self->sink1); if (klass->info->plugin_type == F0R_PLUGIN_TYPE_MIXER3) { self->sink2 = gst_pad_new_from_template (gst_element_class_get_pad_template (GST_ELEMENT_CLASS (klass), "sink_2"), "sink_2"); gst_pad_set_getcaps_function (self->sink2, GST_DEBUG_FUNCPTR (gst_frei0r_mixer_get_caps)); gst_pad_set_setcaps_function (self->sink2, GST_DEBUG_FUNCPTR (gst_frei0r_mixer_set_caps)); gst_pad_set_query_function (self->sink0, GST_DEBUG_FUNCPTR (gst_frei0r_mixer_sink_query)); gst_collect_pads_add_pad (self->collect, self->sink2, sizeof (GstCollectData)); gst_element_add_pad (GST_ELEMENT_CAST (self), self->sink2); } }