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 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 pragha_backend_set_target_state (PraghaBackend *backend, GstState target_state) { GstStateChangeReturn ret; PraghaBackendPrivate *priv = backend->priv; GstState old_state = priv->target_state; priv->target_state = target_state; ret = gst_element_set_state(priv->pipeline, target_state); switch (ret) { case GST_STATE_CHANGE_SUCCESS: if (target_state == GST_STATE_READY) pragha_backend_evaluate_state(old_state, GST_STATE (priv->pipeline), GST_STATE_PENDING (priv->pipeline), backend); break; case GST_STATE_CHANGE_NO_PREROLL: if (target_state == GST_STATE_PLAYING) priv->is_live = TRUE; break; default: break; } g_object_notify_by_pspec (G_OBJECT (backend), properties[PROP_TARGET_STATE]); }
static void kms_audio_mixer_remove_sometimes_src_pad (KmsAudioMixer * self, GstElement * adder) { GstProxyPad *internal; GstPad *srcpad, *peer; srcpad = gst_element_get_static_pad (adder, "src"); peer = gst_pad_get_peer (srcpad); if (peer == NULL) goto end_phase_1; internal = gst_proxy_pad_get_internal ((GstProxyPad *) peer); if (internal == NULL) goto end_phase_2; gst_ghost_pad_set_target (GST_GHOST_PAD (internal), 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 (GST_PAD (internal), FALSE); } GST_DEBUG ("Removing source pad %" GST_PTR_FORMAT, internal); gst_element_remove_pad (GST_ELEMENT (self), GST_PAD (internal)); gst_object_unref (internal); end_phase_2: gst_object_unref (peer); end_phase_1: gst_object_unref (srcpad); }
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 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 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; }
static gboolean do_toggle_element (GstGConfVideoSrc * src) { GstPad *targetpad; gchar *new_gconf_str; GstState cur, next; new_gconf_str = gst_gconf_get_string (GST_GCONF_AUDIOSRC_KEY); if (new_gconf_str != NULL && src->gconf_str != NULL && (strlen (new_gconf_str) == 0 || strcmp (src->gconf_str, new_gconf_str) == 0)) { g_free (new_gconf_str); GST_DEBUG_OBJECT (src, "GConf key was updated, but it didn't change"); return TRUE; } GST_OBJECT_LOCK (src); cur = GST_STATE (src); next = GST_STATE_PENDING (src); GST_OBJECT_UNLOCK (src); if (cur >= GST_STATE_READY || next == GST_STATE_PAUSED) { GST_DEBUG_OBJECT (src, "already running, ignoring GConf change"); g_free (new_gconf_str); return TRUE; } g_free (src->gconf_str); src->gconf_str = new_gconf_str; /* kill old element */ if (src->kid) { GST_DEBUG_OBJECT (src, "Removing old kid"); gst_element_set_state (src->kid, GST_STATE_NULL); gst_bin_remove (GST_BIN (src), src->kid); src->kid = NULL; } GST_DEBUG_OBJECT (src, "Creating new kid"); if (!(src->kid = gst_gconf_get_default_video_src ())) { GST_ELEMENT_ERROR (src, LIBRARY, SETTINGS, (NULL), ("Failed to render video source from GConf")); g_free (src->gconf_str); src->gconf_str = NULL; return FALSE; } gst_element_set_state (src->kid, GST_STATE (src)); gst_bin_add (GST_BIN (src), src->kid); /* re-attach ghostpad */ GST_DEBUG_OBJECT (src, "Creating new ghostpad"); targetpad = gst_element_get_static_pad (src->kid, "src"); gst_ghost_pad_set_target (GST_GHOST_PAD (src->pad), targetpad); gst_object_unref (targetpad); GST_DEBUG_OBJECT (src, "done changing gconf video source"); return TRUE; }
static void gst_sctp_base_sink_release_pad (GstElement * element, GstPad * pad) { 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 GstStateChangeReturn gst_mikmod_change_state (GstElement * element, GstStateChange transition) { GstMikMod *mikmod; g_return_val_if_fail (GST_IS_MIKMOD (element), GST_STATE_CHANGE_FAILURE); mikmod = GST_MIKMOD (element); GST_DEBUG ("state pending %d", GST_STATE_PENDING (element)); if (GST_STATE_PENDING (element) == GST_STATE_READY) { gst_mikmod_setup (mikmod); if (Player_Active ()) { Player_TogglePause (); Player_SetPosition (0); } mikmod->initialized = FALSE; } if (GST_STATE_PENDING (element) == GST_STATE_PLAYING) { if (Player_Active () && Player_Paused ()) Player_TogglePause (); else if (!Player_Active ()) Player_Start (module); } if (GST_STATE_PENDING (element) == GST_STATE_PAUSED) if (Player_Active () && !Player_Paused ()) Player_TogglePause (); if (GST_STATE_PENDING (element) == GST_STATE_NULL) MikMod_Exit (); if (GST_ELEMENT_CLASS (parent_class)->change_state) return GST_ELEMENT_CLASS (parent_class)->change_state (element, transition); return GST_STATE_CHANGE_SUCCESS; }
static void gst_decklink_video_src_start_streams (GstElement * element) { GstDecklinkVideoSrc *self = GST_DECKLINK_VIDEO_SRC_CAST (element); HRESULT res; if (self->input->video_enabled && (!self->input->audiosrc || self->input->audio_enabled) && (GST_STATE (self) == GST_STATE_PLAYING || GST_STATE_PENDING (self) == GST_STATE_PLAYING)) { GstClock *clock; clock = gst_element_get_clock (element); if (!clock) { GST_ELEMENT_ERROR (self, STREAM, FAILED, (NULL), ("Streams supposed to start but we have no clock")); return; } GST_DEBUG_OBJECT (self, "Starting streams"); res = self->input->input->StartStreams (); if (res != S_OK) { GST_ELEMENT_ERROR (self, STREAM, FAILED, (NULL), ("Failed to start streams: 0x%08x", res)); gst_object_unref (clock); return; } self->input->started = TRUE; self->input->clock_restart = TRUE; // Need to unlock to get the clock time g_mutex_unlock (&self->input->lock); // Current times of internal and external clock when we go to // playing. We need this to convert the pipeline running time // to the running time of the hardware // // We can't use the normal base time for the external clock // because we might go to PLAYING later than the pipeline self->internal_base_time = gst_clock_get_internal_time (self->input->clock); self->external_base_time = gst_clock_get_internal_time (clock); gst_object_unref (clock); g_mutex_lock (&self->input->lock); } else { GST_DEBUG_OBJECT (self, "Not starting streams yet"); } }
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 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 GstStateChangeReturn gst_artsdsink_change_state (GstElement * element, GstStateChange transition) { g_return_val_if_fail (GST_IS_ARTSDSINK (element), FALSE); /* if going down into NULL state, close the stream if it's open */ if (GST_STATE_PENDING (element) == GST_STATE_NULL) { if (GST_OBJECT_FLAG_IS_SET (element, GST_ARTSDSINK_OPEN)) gst_artsdsink_close_audio (GST_ARTSDSINK (element)); /* otherwise (READY or higher) we need to open the stream */ } else { if (!GST_OBJECT_FLAG_IS_SET (element, GST_ARTSDSINK_OPEN)) { if (!gst_artsdsink_open_audio (GST_ARTSDSINK (element))) return GST_STATE_CHANGE_FAILURE; } } if (GST_ELEMENT_CLASS (parent_class)->change_state) return GST_ELEMENT_CLASS (parent_class)->change_state (element, transition); return GST_STATE_CHANGE_SUCCESS; }
static GstStateChangeReturn gst_festival_change_state (GstElement * element, GstStateChange transition) { g_return_val_if_fail (GST_IS_FESTIVAL (element), GST_STATE_CHANGE_FAILURE); if (GST_STATE_PENDING (element) == GST_STATE_NULL) { if (GST_OBJECT_FLAG_IS_SET (element, GST_FESTIVAL_OPEN)) { GST_DEBUG ("Closing connection "); gst_festival_close (GST_FESTIVAL (element)); } } else { if (!GST_OBJECT_FLAG_IS_SET (element, GST_FESTIVAL_OPEN)) { GST_DEBUG ("Opening connection "); if (!gst_festival_open (GST_FESTIVAL (element))) return GST_STATE_CHANGE_FAILURE; } } if (GST_ELEMENT_CLASS (parent_class)->change_state) return GST_ELEMENT_CLASS (parent_class)->change_state (element, transition); return GST_STATE_CHANGE_SUCCESS; }
static GstStateChangeReturn dxr3audiosink_change_state (GstElement * element, GstStateChange transition) { g_return_val_if_fail (GST_IS_DXR3AUDIOSINK (element), GST_STATE_CHANGE_FAILURE); if (GST_STATE_PENDING (element) == GST_STATE_NULL) { if (GST_OBJECT_FLAG_IS_SET (element, DXR3AUDIOSINK_OPEN)) { dxr3audiosink_close (DXR3AUDIOSINK (element)); } } else { if (!GST_OBJECT_FLAG_IS_SET (element, DXR3AUDIOSINK_OPEN)) { if (!dxr3audiosink_open (DXR3AUDIOSINK (element))) { return GST_STATE_CHANGE_FAILURE; } } } if (GST_ELEMENT_CLASS (parent_class)->change_state) { return GST_ELEMENT_CLASS (parent_class)->change_state (element, transition); } return GST_STATE_CHANGE_SUCCESS; }
static void kms_element_add_src_pad (KmsElement * self, GstElement * element, const gchar * pad_name, const gchar * templ_name) { GstPad *srcpad; srcpad = gst_ghost_pad_new_no_target_from_template (pad_name, gst_element_class_get_pad_template (GST_ELEMENT_CLASS (G_OBJECT_GET_CLASS (self)), templ_name)); 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 (srcpad, TRUE); g_signal_connect (srcpad, "linked", G_CALLBACK (kms_element_set_target_on_linked), element); g_signal_connect (srcpad, "unlinked", G_CALLBACK (kms_element_remove_target_on_unlinked), element); gst_element_add_pad (GST_ELEMENT (self), srcpad); }
static GstStateChangeReturn cdplayer_change_state (GstElement * element, GstStateChange transition) { CDPlayer *cdp; GstState state = GST_STATE (element); GstState pending = GST_STATE_PENDING (element); g_return_val_if_fail (GST_IS_CDPLAYER (element), GST_STATE_CHANGE_FAILURE); cdp = CDPLAYER (element); switch (pending) { case GST_STATE_READY: if (state != GST_STATE_PAUSED) { if (cd_init (CDPLAYER_CD (cdp), cdp->device) == FALSE) { return GST_STATE_CHANGE_FAILURE; } cdp->num_tracks = cdp->cd.num_tracks; cdp->cddb_discid = cd_cddb_discid (CDPLAYER_CD (cdp)); } break; case GST_STATE_PAUSED: /* ready->paused is not useful */ if (state != GST_STATE_READY) { if (cd_pause (CDPLAYER_CD (cdp)) == FALSE) { return GST_STATE_CHANGE_FAILURE; } cdp->paused = TRUE; } break; case GST_STATE_PLAYING: if (cdp->paused == TRUE) { if (cd_resume (CDPLAYER_CD (cdp)) == FALSE) { return GST_STATE_CHANGE_FAILURE; } cdp->paused = FALSE; } else { if (cd_start (CDPLAYER_CD (cdp), cdp->start_track, cdp->end_track) == FALSE) { return GST_STATE_CHANGE_FAILURE; } } break; case GST_STATE_NULL: /* stop & close fd */ if (cd_stop (CDPLAYER_CD (cdp)) == FALSE || cd_close (CDPLAYER_CD (cdp)) == FALSE) { return GST_STATE_CHANGE_FAILURE; } break; default: break; } if (GST_ELEMENT_CLASS (parent_class)->change_state) { GST_ELEMENT_CLASS (parent_class)->change_state (element, transition); } return GST_STATE_CHANGE_SUCCESS; }
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 do_toggle_element (GstGConfVideoSink * sink) { GstPad *targetpad; gchar *new_gconf_str; GstState cur, next; new_gconf_str = gst_gconf_get_string (GST_GCONF_VIDEOSINK_KEY); if (new_gconf_str != NULL && sink->gconf_str != NULL && (strlen (new_gconf_str) == 0 || strcmp (sink->gconf_str, new_gconf_str) == 0)) { g_free (new_gconf_str); GST_DEBUG_OBJECT (sink, "GConf key was updated, but it didn't change"); return TRUE; } /* Sometime, it would be lovely to allow sink changes even when * already running, but this involves sending an appropriate new-segment * and possibly prerolling etc */ GST_OBJECT_LOCK (sink); cur = GST_STATE (sink); next = GST_STATE_PENDING (sink); GST_OBJECT_UNLOCK (sink); if (cur > GST_STATE_READY || next == GST_STATE_PAUSED) { GST_DEBUG_OBJECT (sink, "Auto-sink is already running. Ignoring GConf change"); g_free (new_gconf_str); return TRUE; } GST_DEBUG_OBJECT (sink, "GConf key changed: '%s' to '%s'", GST_STR_NULL (sink->gconf_str), GST_STR_NULL (new_gconf_str)); g_free (sink->gconf_str); sink->gconf_str = new_gconf_str; /* kill old element */ if (sink->kid) { GST_DEBUG_OBJECT (sink, "Removing old kid"); gst_element_set_state (sink->kid, GST_STATE_NULL); gst_bin_remove (GST_BIN (sink), sink->kid); sink->kid = NULL; } GST_DEBUG_OBJECT (sink, "Creating new kid"); if (!(sink->kid = gst_gconf_get_default_video_sink ())) { GST_ELEMENT_ERROR (sink, LIBRARY, SETTINGS, (NULL), ("Failed to render video sink from GConf")); return FALSE; } gst_element_set_state (sink->kid, GST_STATE (sink)); gst_bin_add (GST_BIN (sink), sink->kid); /* re-attach ghostpad */ GST_DEBUG_OBJECT (sink, "Creating new ghostpad"); targetpad = gst_element_get_static_pad (sink->kid, "sink"); gst_ghost_pad_set_target (GST_GHOST_PAD (sink->pad), targetpad); gst_object_unref (targetpad); GST_DEBUG_OBJECT (sink, "done changing gconf video sink"); return TRUE; }
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 gst_decklink_video_sink_start_scheduled_playback (GstElement * element) { GstDecklinkVideoSink *self = GST_DECKLINK_VIDEO_SINK_CAST (element); GstClockTime start_time; HRESULT res; bool active; if (self->output->video_enabled && (!self->output->audiosink || self->output->audio_enabled) && (GST_STATE (self) == GST_STATE_PLAYING || GST_STATE_PENDING (self) == GST_STATE_PLAYING)) { GstClock *clock = NULL; clock = gst_element_get_clock (element); if (!clock) { GST_ELEMENT_ERROR (self, STREAM, FAILED, (NULL), ("Scheduled playback supposed to start but we have no clock")); return; } // Need to unlock to get the clock time g_mutex_unlock (&self->output->lock); // FIXME: start time is the same for the complete pipeline, // but what we need here is the start time of this element! start_time = gst_element_get_base_time (element); if (start_time != GST_CLOCK_TIME_NONE) start_time = gst_clock_get_time (clock) - start_time; // FIXME: This will probably not work if (start_time == GST_CLOCK_TIME_NONE) start_time = 0; // Current times of internal and external clock when we go to // playing. We need this to convert the pipeline running time // to the running time of the hardware // // We can't use the normal base time for the external clock // because we might go to PLAYING later than the pipeline self->internal_base_time = gst_clock_get_internal_time (self->output->clock); self->external_base_time = gst_clock_get_internal_time (clock); convert_to_internal_clock (self, &start_time, NULL); g_mutex_lock (&self->output->lock); // Check if someone else started in the meantime if (self->output->started) { gst_object_unref (clock); return; } active = false; self->output->output->IsScheduledPlaybackRunning (&active); if (active) { GST_DEBUG_OBJECT (self, "Stopping scheduled playback"); self->output->started = FALSE; res = self->output->output->StopScheduledPlayback (0, 0, 0); if (res != S_OK) { GST_ELEMENT_ERROR (self, STREAM, FAILED, (NULL), ("Failed to stop scheduled playback: 0x%08x", res)); gst_object_unref (clock); return; } } GST_DEBUG_OBJECT (self, "Starting scheduled playback at %" GST_TIME_FORMAT, GST_TIME_ARGS (start_time)); res = self->output->output->StartScheduledPlayback (start_time, GST_SECOND, 1.0); if (res != S_OK) { GST_ELEMENT_ERROR (self, STREAM, FAILED, (NULL), ("Failed to start scheduled playback: 0x%08x", res)); gst_object_unref (clock); return; } self->output->started = TRUE; self->output->clock_restart = TRUE; // Need to unlock to get the clock time g_mutex_unlock (&self->output->lock); // Sample the clocks again to get the most accurate values // after we started scheduled playback self->internal_base_time = gst_clock_get_internal_time (self->output->clock); self->external_base_time = gst_clock_get_internal_time (clock); g_mutex_lock (&self->output->lock); gst_object_unref (clock); } else { GST_DEBUG_OBJECT (self, "Not starting scheduled playback yet"); } }