GstElement * kms_element_get_data_tee (KmsElement * self) { GstElement *sink, *tee; GST_DEBUG_OBJECT (self, "Data tee requested"); KMS_ELEMENT_LOCK (self); if (self->priv->data_tee != NULL) { KMS_ELEMENT_UNLOCK (self); return self->priv->data_tee; } tee = gst_element_factory_make ("tee", NULL); sink = gst_element_factory_make ("fakesink", NULL); g_object_set (sink, "sync", FALSE, "async", FALSE, NULL); gst_bin_add_many (GST_BIN (self), tee, sink, NULL); gst_element_link (tee, sink); self->priv->data_tee = tee; KMS_ELEMENT_UNLOCK (self); gst_element_sync_state_with_parent (sink); gst_element_sync_state_with_parent (tee); kms_element_create_pending_pads (self, KMS_ELEMENT_PAD_TYPE_DATA); return tee; }
static void kms_element_get_property (GObject * object, guint property_id, GValue * value, GParamSpec * pspec) { KmsElement *self = KMS_ELEMENT (object); switch (property_id) { case PROP_ACCEPT_EOS: KMS_ELEMENT_LOCK (self); g_value_set_boolean (value, self->priv->accept_eos); KMS_ELEMENT_UNLOCK (self); break; case PROP_AUDIO_CAPS: g_value_take_boxed (value, kms_element_endpoint_get_caps (self, self->priv->audio_caps)); break; case PROP_VIDEO_CAPS: g_value_take_boxed (value, kms_element_endpoint_get_caps (self, self->priv->video_caps)); break; case PROP_TARGET_BITRATE: KMS_ELEMENT_LOCK (self); g_value_set_int (value, self->priv->target_bitrate); KMS_ELEMENT_UNLOCK (self); break; case PROP_MEDIA_STATS: KMS_ELEMENT_LOCK (self); g_value_set_boolean (value, self->priv->stats_enabled); KMS_ELEMENT_UNLOCK (self); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); break; } }
static void kms_recorder_endpoint_get_property (GObject * object, guint property_id, GValue * value, GParamSpec * pspec) { KmsRecorderEndpoint *self = KMS_RECORDER_ENDPOINT (object); KMS_ELEMENT_LOCK (KMS_ELEMENT (self)); switch (property_id) { case PROP_DVR: g_value_set_boolean (value, self->priv->use_dvr); break; case PROP_PROFILE:{ KmsRecordingProfile profile; g_object_get (G_OBJECT (self->priv->controller), "profile", &profile, NULL); g_value_set_enum (value, profile); break; } default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); break; } KMS_ELEMENT_UNLOCK (KMS_ELEMENT (self)); }
static void kms_recorder_endpoint_paused (KmsUriEndpoint * obj) { KmsRecorderEndpoint *self = KMS_RECORDER_ENDPOINT (obj); GstClock *clk; kms_recorder_endpoint_change_state (self, KMS_URI_ENDPOINT_STATE_PAUSE); kms_recorder_endpoint_remove_pads (self); KMS_ELEMENT_UNLOCK (self); /* Set internal pipeline to GST_STATE_PAUSED */ kms_base_media_muxer_set_state (self->priv->mux, GST_STATE_PAUSED); KMS_ELEMENT_LOCK (self); clk = kms_base_media_muxer_get_clock (self->priv->mux); if (clk) { self->priv->paused_start = gst_clock_get_time (clk); } kms_recorder_endpoint_state_changed (self, KMS_URI_ENDPOINT_STATE_PAUSE); }
static void kms_recorder_endpoint_started (KmsUriEndpoint * obj) { KmsRecorderEndpoint *self = KMS_RECORDER_ENDPOINT (obj); kms_recorder_endpoint_create_parent_directories (self); kms_recorder_endpoint_change_state (self, KMS_URI_ENDPOINT_STATE_START); KMS_ELEMENT_UNLOCK (self); /* Set internal pipeline to playing */ kms_base_media_muxer_set_state (self->priv->mux, GST_STATE_PLAYING); KMS_ELEMENT_LOCK (self); BASE_TIME_LOCK (self); if (GST_CLOCK_TIME_IS_VALID (self->priv->paused_start)) { self->priv->paused_time += gst_clock_get_time (kms_base_media_muxer_get_clock (self->priv->mux)) - self->priv->paused_start; self->priv->paused_start = GST_CLOCK_TIME_NONE; } BASE_TIME_UNLOCK (self); kms_recorder_generate_pads (self); }
static void kms_recorder_endpoint_stopped (KmsUriEndpoint * obj) { KmsRecorderEndpoint *self = KMS_RECORDER_ENDPOINT (obj); if (self->priv->stopping) { return; } kms_recorder_endpoint_change_state (self, KMS_URI_ENDPOINT_STATE_STOP); if (kms_base_media_muxer_get_state (self->priv->mux) >= GST_STATE_PAUSED) { self->priv->stopping = TRUE; kms_recorder_endpoint_send_eos_to_appsrcs (self); } kms_recorder_endpoint_remove_pads (self); // Reset base time data BASE_TIME_LOCK (self); g_object_set_qdata_full (G_OBJECT (self), base_time_key_quark (), NULL, NULL); self->priv->paused_time = G_GUINT64_CONSTANT (0); self->priv->paused_start = GST_CLOCK_TIME_NONE; BASE_TIME_UNLOCK (self); if (kms_base_media_muxer_get_state (self->priv->mux) < GST_STATE_PAUSED && !self->priv->stopping) { KMS_ELEMENT_UNLOCK (self); kms_base_media_muxer_set_state (self->priv->mux, GST_STATE_NULL); KMS_ELEMENT_LOCK (self); } }
static void kms_recorder_end_point_started (KmsUriEndPoint * obj) { KmsRecorderEndPoint *self = KMS_RECORDER_END_POINT (obj); kms_recorder_end_point_change_state (self); /* Set internal pipeline to playing */ gst_element_set_state (self->priv->pipeline, GST_STATE_PLAYING); KMS_ELEMENT_LOCK (self); if (GST_CLOCK_TIME_IS_VALID (self->priv->paused_start)) { self->priv->paused_time += gst_clock_get_time (GST_ELEMENT (self->priv->pipeline)->clock) - self->priv->paused_start; self->priv->paused_start = GST_CLOCK_TIME_NONE; } KMS_ELEMENT_UNLOCK (self); /* Open valves */ kms_recorder_end_point_open_valves (self); kms_recorder_end_point_state_changed (self, KMS_URI_END_POINT_STATE_START); }
static void kms_recorder_endpoint_dispose (GObject * object) { KmsRecorderEndpoint *self = KMS_RECORDER_ENDPOINT (object); GST_DEBUG_OBJECT (self, "dispose"); KMS_ELEMENT_LOCK (KMS_ELEMENT (self)); if (self->priv->mux != NULL) { if (kms_base_media_muxer_get_state (self->priv->mux) != GST_STATE_NULL) { GST_ELEMENT_WARNING (self, RESOURCE, BUSY, ("Recorder may have buffers to save"), ("Disposing recorder when it isn't stopped.")); } kms_base_media_muxer_set_state (self->priv->mux, GST_STATE_NULL); if (self->priv->stopping) { GST_WARNING_OBJECT (self, "Forcing pending stop operation to finish"); kms_recorder_endpoint_state_changed (self, KMS_URI_ENDPOINT_STATE_STOP); self->priv->stopping = FALSE; } } KMS_ELEMENT_UNLOCK (KMS_ELEMENT (self)); g_mutex_clear (&self->priv->base_time_lock); /* clean up as possible. may be called multiple times */ G_OBJECT_CLASS (kms_recorder_endpoint_parent_class)->dispose (object); }
void kms_element_remove_sink (KmsElement * self, GstPad * pad) { GSList *l; g_return_if_fail (self); g_return_if_fail (pad); KMS_ELEMENT_LOCK (self); l = g_slist_find_custom (self->priv->stats.probes, pad, (GCompareFunc) find_stat_probe); if (l != NULL) { KmsStatsProbe *probe = l->data; self->priv->stats.probes = g_slist_remove (self->priv->stats.probes, l->data); kms_stats_probe_destroy (probe); } KMS_ELEMENT_UNLOCK (self); // TODO: Unlink correctly pad before removing it gst_ghost_pad_set_target (GST_GHOST_PAD (pad), NULL); gst_element_remove_pad (GST_ELEMENT (self), pad); }
static void kms_recorder_endpoint_send_eos_to_appsrcs (KmsRecorderEndpoint * self) { if (g_hash_table_size (self->priv->srcs) == 0) { KMS_ELEMENT_UNLOCK (KMS_ELEMENT (self)); kms_base_media_muxer_set_state (self->priv->mux, GST_STATE_NULL); KMS_ELEMENT_LOCK (KMS_ELEMENT (self)); return; } KMS_ELEMENT_UNLOCK (KMS_ELEMENT (self)); kms_base_media_muxer_set_state (self->priv->mux, GST_STATE_PLAYING); KMS_ELEMENT_LOCK (KMS_ELEMENT (self)); g_hash_table_foreach (self->priv->srcs, (GHFunc) send_eos_cb, NULL); }
static gboolean kms_dummy_sink_release_requested_sink_pad (KmsElement * obj, GstPad * pad) { KmsDummySink *self = KMS_DUMMY_SINK (obj); KmsDummySinkElement *dummy; gchar *padname; padname = gst_pad_get_name (pad); KMS_ELEMENT_LOCK (KMS_ELEMENT (self)); dummy = g_hash_table_lookup (self->priv->sinks, padname); if (dummy == NULL) { KMS_ELEMENT_UNLOCK (KMS_ELEMENT (self)); return FALSE; } kms_element_remove_sink_by_type_full (obj, dummy->type, dummy->description); g_hash_table_remove (self->priv->sinks, padname); g_free (padname); return TRUE; }
static void kms_recorder_endpoint_set_property (GObject * object, guint property_id, const GValue * value, GParamSpec * pspec) { KmsRecorderEndpoint *self = KMS_RECORDER_ENDPOINT (object); KMS_ELEMENT_LOCK (KMS_ELEMENT (self)); switch (property_id) { case PROP_DVR: self->priv->use_dvr = g_value_get_boolean (value); break; case PROP_PROFILE:{ if (self->priv->profile == KMS_RECORDING_PROFILE_NONE) { self->priv->profile = g_value_get_enum (value); if (self->priv->profile != KMS_RECORDING_PROFILE_NONE) { kms_recorder_endpoint_new_media_muxer (self); } } else { GST_ERROR_OBJECT (self, "Profile can only be configured once"); } break; } default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); break; } KMS_ELEMENT_UNLOCK (KMS_ELEMENT (self)); }
static void kms_element_set_sink_input_stats (KmsElement * self, GstPad * pad, KmsElementPadType type) { KmsStatsProbe *s_probe; KmsMediaType media_type; switch (type) { case KMS_ELEMENT_PAD_TYPE_AUDIO: media_type = KMS_MEDIA_TYPE_AUDIO; case KMS_ELEMENT_PAD_TYPE_VIDEO: media_type = KMS_MEDIA_TYPE_VIDEO; break; default: GST_DEBUG ("No stats collected for pad type %d", type); return; } s_probe = kms_stats_probe_new (pad, media_type); KMS_ELEMENT_LOCK (self); self->priv->stats.probes = g_slist_prepend (self->priv->stats.probes, s_probe); if (self->priv->stats_enabled) { kms_stats_probe_add_latency (s_probe, kms_element_calculate_stats, self, NULL); } KMS_ELEMENT_UNLOCK (self); }
static GstPadProbeReturn accept_eos_probe (GstPad * pad, GstPadProbeInfo * info, gpointer data) { GstEvent *event = gst_pad_probe_info_get_event (info); GstEventType type = GST_EVENT_TYPE (event); if (type == GST_EVENT_EOS || type == GST_EVENT_FLUSH_START || type == GST_EVENT_FLUSH_STOP) { KmsElement *self; gboolean accept; self = KMS_ELEMENT (data); KMS_ELEMENT_LOCK (self); accept = self->priv->accept_eos; KMS_ELEMENT_UNLOCK (self); if (!accept) { GST_DEBUG_OBJECT (pad, "Event %s dropped", gst_event_type_get_name (type)); } return (accept) ? GST_PAD_PROBE_OK : GST_PAD_PROBE_DROP; } return GST_PAD_PROBE_OK; }
static void unlink_sinkpad_cb (GstPad * pad, GstPad * peer, gpointer user_data) { KmsRecorderEndpoint *self = KMS_RECORDER_ENDPOINT (user_data); gchar *id = NULL; KMS_ELEMENT_LOCK (KMS_ELEMENT (self)); id = gst_pad_get_name (pad); if (self->priv->stopping) { GST_DEBUG_OBJECT (self, "Stop operation is pending"); self->priv->pending_pads = g_slist_prepend (self->priv->pending_pads, g_strdup (id)); goto end; } if (kms_base_media_muxer_remove_src (self->priv->mux, id)) { g_hash_table_remove (self->priv->srcs, id); } end: KMS_ELEMENT_UNLOCK (KMS_ELEMENT (self)); g_free (id); }
static gchar * kms_element_request_new_srcpad_action (KmsElement * self, KmsElementPadType type, const gchar * desc) { const gchar *templ_name; gchar *pad_name; GstElement *element; KMS_ELEMENT_LOCK (self); if (!kms_element_get_data_by_type (self, type, &templ_name, &element)) { KMS_ELEMENT_UNLOCK (self); return NULL; } switch (type) { case KMS_ELEMENT_PAD_TYPE_DATA: pad_name = g_strdup_printf (templ_name, self->priv->data_pad_count++); break; case KMS_ELEMENT_PAD_TYPE_AUDIO: pad_name = g_strdup_printf (templ_name, self->priv->audio_pad_count++); break; case KMS_ELEMENT_PAD_TYPE_VIDEO: pad_name = g_strdup_printf (templ_name, self->priv->video_pad_count++); break; default: GST_WARNING_OBJECT (self, "Unsupported pad type %u", type); KMS_ELEMENT_UNLOCK (self); return NULL; } if (element == NULL) { PendingSrcPad *data; data = create_pendingpad (type, desc); g_hash_table_insert (self->priv->pendingpads, g_strdup (pad_name), data); KMS_ELEMENT_UNLOCK (self); return pad_name; } KMS_ELEMENT_UNLOCK (self); kms_element_add_src_pad (self, element, pad_name, templ_name); return pad_name; }
static void kms_element_set_property (GObject * object, guint property_id, const GValue * value, GParamSpec * pspec) { KmsElement *self = KMS_ELEMENT (object); switch (property_id) { case PROP_ACCEPT_EOS: KMS_ELEMENT_LOCK (self); self->priv->accept_eos = g_value_get_boolean (value); KMS_ELEMENT_UNLOCK (self); break; case PROP_AUDIO_CAPS: kms_element_endpoint_set_caps (self, gst_value_get_caps (value), &self->priv->audio_caps); break; case PROP_VIDEO_CAPS: kms_element_endpoint_set_caps (self, gst_value_get_caps (value), &self->priv->video_caps); break; case PROP_TARGET_BITRATE: KMS_ELEMENT_LOCK (self); self->priv->target_bitrate = g_value_get_int (value); g_object_set (G_OBJECT (kms_element_get_video_agnosticbin (self)), DEFAULT_BITRATE_, self->priv->target_bitrate, NULL); KMS_ELEMENT_UNLOCK (self); break; case PROP_MEDIA_STATS:{ gboolean enable = g_value_get_boolean (value); KMS_ELEMENT_LOCK (self); if (enable != self->priv->stats_enabled) { self->priv->stats_enabled = enable; KMS_ELEMENT_GET_CLASS (self)->collect_media_stats (self, enable); } KMS_ELEMENT_UNLOCK (self); break; } default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); break; } }
static void kms_dummy_sink_set_property (GObject * object, guint property_id, const GValue * value, GParamSpec * pspec) { KmsDummySink *self = KMS_DUMMY_SINK (object); gboolean val; KMS_ELEMENT_LOCK (KMS_ELEMENT (self)); switch (property_id) { case PROP_DATA: val = g_value_get_boolean (value); if (val && !self->priv->data) { kms_dummy_sink_add_sinkpad (self, KMS_ELEMENT_PAD_TYPE_DATA); } else if (!val && self->priv->data) { kms_element_remove_sink_by_type (KMS_ELEMENT (self), KMS_ELEMENT_PAD_TYPE_DATA); } else { GST_DEBUG_OBJECT (self, "Operation without effect"); } self->priv->data = val; break; case PROP_AUDIO: val = g_value_get_boolean (value); if (val && !self->priv->audio) { kms_dummy_sink_add_sinkpad (self, KMS_ELEMENT_PAD_TYPE_AUDIO); } else if (!val && self->priv->audio) { kms_element_remove_sink_by_type (KMS_ELEMENT (self), KMS_ELEMENT_PAD_TYPE_AUDIO); } else { GST_DEBUG_OBJECT (self, "Operation without effect"); } self->priv->audio = val; break; case PROP_VIDEO: val = g_value_get_boolean (value); if (val && !self->priv->video) { kms_dummy_sink_add_sinkpad (self, KMS_ELEMENT_PAD_TYPE_VIDEO); } else if (!val && self->priv->video) { kms_element_remove_sink_by_type (KMS_ELEMENT (self), KMS_ELEMENT_PAD_TYPE_VIDEO); } else { GST_DEBUG_OBJECT (self, "Operation without effect"); } self->priv->video = val; break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); break; } KMS_ELEMENT_UNLOCK (KMS_ELEMENT (self)); }
static GstFlowReturn kms_http_post_endpoint_end_of_stream_action (KmsHttpPostEndpoint * self) { GstFlowReturn ret; KMS_ELEMENT_LOCK (self); if (KMS_HTTP_ENDPOINT (self)->pipeline == NULL) { KMS_ELEMENT_UNLOCK (self); GST_ELEMENT_ERROR (self, RESOURCE, FAILED, ("Pipeline is not initialized"), GST_ERROR_SYSTEM); return GST_FLOW_ERROR; } KMS_ELEMENT_UNLOCK (self); g_signal_emit_by_name (self->priv->appsrc, "end-of-stream", &ret); return ret; }
static void kms_recorder_endpoint_state_changed (KmsRecorderEndpoint * self, KmsUriEndpointState state) { KMS_ELEMENT_LOCK (KMS_ELEMENT (self)); if (!self->priv->stopping || state == KMS_URI_ENDPOINT_STATE_STOP) { KMS_URI_ENDPOINT_GET_CLASS (self)->change_state (KMS_URI_ENDPOINT (self), state); } KMS_ELEMENT_UNLOCK (KMS_ELEMENT (self)); }
static gboolean kms_dummy_sink_request_new_sink_pad (KmsElement * obj, KmsElementPadType type, const gchar * description, const gchar * name) { KmsDummySink *self = KMS_DUMMY_SINK (obj); KmsDummySinkElement *dummy; GstElement *sink; GstPad *sinkpad; KMS_ELEMENT_LOCK (KMS_ELEMENT (self)); if (g_hash_table_contains (self->priv->sinks, name)) { KMS_ELEMENT_UNLOCK (KMS_ELEMENT (self)); return TRUE; } sink = gst_element_factory_make ("fakesink", NULL); g_object_set (sink, "async", FALSE, "sync", FALSE, NULL); dummy = create_dummy_sink_element (type, description, sink); if (!gst_bin_add (GST_BIN (self), sink)) { KMS_ELEMENT_UNLOCK (KMS_ELEMENT (self)); destroy_dummy_sink_element (dummy); return FALSE; } g_hash_table_insert (self->priv->sinks, g_strdup (name), dummy); KMS_ELEMENT_UNLOCK (KMS_ELEMENT (self)); gst_element_sync_state_with_parent (sink); sinkpad = gst_element_get_static_pad (sink, "sink"); kms_element_connect_sink_target_full (KMS_ELEMENT (self), sinkpad, type, description, NULL, NULL); g_object_unref (sinkpad); return TRUE; }
GstElement * kms_element_get_video_agnosticbin (KmsElement * self) { GST_DEBUG_OBJECT (self, "Video agnostic requested"); KMS_ELEMENT_LOCK (self); if (self->priv->video_agnosticbin != NULL) { KMS_ELEMENT_UNLOCK (self); return self->priv->video_agnosticbin; } self->priv->video_agnosticbin = gst_element_factory_make ("agnosticbin", NULL); gst_bin_add (GST_BIN (self), self->priv->video_agnosticbin); gst_element_sync_state_with_parent (self->priv->video_agnosticbin); KMS_ELEMENT_UNLOCK (self); kms_element_create_pending_pads (self, KMS_ELEMENT_PAD_TYPE_VIDEO); return self->priv->video_agnosticbin; }
static void kms_recorder_endpoint_set_property (GObject * object, guint property_id, const GValue * value, GParamSpec * pspec) { KmsRecorderEndpoint *self = KMS_RECORDER_ENDPOINT (object); KMS_ELEMENT_LOCK (KMS_ELEMENT (self)); switch (property_id) { case PROP_DVR: self->priv->use_dvr = g_value_get_boolean (value); break; case PROP_PROFILE:{ if (self->priv->profile == KMS_RECORDING_PROFILE_NONE) { self->priv->profile = g_value_get_enum (value); if (self->priv->profile != KMS_RECORDING_PROFILE_NONE) { GstElement *sink; GstBus *bus; sink = kms_recorder_endpoint_create_sink (self); self->priv->mux = kms_muxing_pipeline_new (KMS_MUXING_PIPELINE_PROFILE, self->priv->profile, KMS_MUXING_PIPELINE_SINK, sink, NULL); g_object_unref (sink); bus = kms_muxing_pipeline_get_bus (self->priv->mux); gst_bus_set_sync_handler (bus, bus_sync_signal_handler, self, NULL); g_object_unref (bus); if (kms_recording_profile_supports_type (self->priv->profile, KMS_ELEMENT_PAD_TYPE_AUDIO)) { kms_recorder_endpoint_add_appsink (self, KMS_ELEMENT_PAD_TYPE_AUDIO); } if (kms_recording_profile_supports_type (self->priv->profile, KMS_ELEMENT_PAD_TYPE_VIDEO)) { kms_recorder_endpoint_add_appsink (self, KMS_ELEMENT_PAD_TYPE_VIDEO); } } } else { GST_ERROR_OBJECT (self, "Profile can only be configured once"); } break; } default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); break; } KMS_ELEMENT_UNLOCK (KMS_ELEMENT (self)); }
static gboolean kms_element_release_requested_srcpad_action (KmsElement * self, const gchar * pad_name) { GValue item = G_VALUE_INIT; gboolean done = FALSE; gboolean released; GstIterator *it; GstPad *pad; KMS_ELEMENT_LOCK (self); released = g_hash_table_remove (self->priv->pendingpads, pad_name); KMS_ELEMENT_UNLOCK (self); if (released) { /* Pad was not created yet */ return TRUE; } /* Pad is not in the pending list so it may have been already created */ it = gst_element_iterate_src_pads (GST_ELEMENT (self)); while (!done) { switch (gst_iterator_next (it, &item)) { case GST_ITERATOR_OK:{ gchar *name; pad = g_value_get_object (&item); name = gst_pad_get_name (pad); if ((released = g_strcmp0 (name, pad_name) == 0)) { kms_element_remove_target_pad (self, pad); kms_element_release_pad (GST_ELEMENT (self), pad); done = TRUE; } g_value_reset (&item); g_free (name); break; } case GST_ITERATOR_RESYNC: gst_iterator_resync (it); break; case GST_ITERATOR_ERROR: case GST_ITERATOR_DONE: done = TRUE; break; } } gst_iterator_free (it); return released; }
static void kms_element_create_pending_pads (KmsElement * self, KmsElementPadType type) { GHashTableIter iter; gpointer key, value; GstElement *element; const gchar *templ_name; GSList *keys = NULL, *l; KMS_ELEMENT_LOCK (self); if (!kms_element_get_data_by_type (self, type, &templ_name, &element)) { KMS_ELEMENT_UNLOCK (self); return; } g_hash_table_iter_init (&iter, self->priv->pendingpads); while (g_hash_table_iter_next (&iter, &key, &value)) { PendingSrcPad *pendingpad = value; /* TODO: Discriminate pads using their description */ if (pendingpad->type != type) { continue; } keys = g_slist_prepend (keys, g_strdup (key)); g_hash_table_iter_remove (&iter); } KMS_ELEMENT_UNLOCK (self); /* Create all pending pads */ for (l = keys; l != NULL; l = l->next) { kms_element_add_src_pad (self, element, l->data, templ_name); } g_slist_free_full (keys, g_free); }
static void kms_player_end_point_stopped (KmsUriEndPoint * obj) { KmsPlayerEndPoint *self = KMS_PLAYER_END_POINT (obj); /* Set internal pipeline to NULL */ gst_element_set_state (self->priv->pipeline, GST_STATE_NULL); KMS_ELEMENT_LOCK (self); g_object_set_data (G_OBJECT (self), BASE_TIME_DATA, NULL); KMS_ELEMENT_UNLOCK (self); KMS_URI_END_POINT_GET_CLASS (self)->change_state (KMS_URI_END_POINT (self), KMS_URI_END_POINT_STATE_STOP); }
static GstStructure * kms_element_get_e2e_latency_stats (KmsRecorderEndpoint * self, gchar * selector) { gpointer key, value; GHashTableIter iter; GstStructure *stats; stats = gst_structure_new_empty ("e2e-latencies"); KMS_ELEMENT_LOCK (self); g_hash_table_iter_init (&iter, self->priv->stats.avg_e2e); while (g_hash_table_iter_next (&iter, &key, &value)) { StreamE2EAvgStat *avg = value; GstStructure *pad_latency; gchar *padname, *id = key; if (selector != NULL && ((g_strcmp0 (selector, AUDIO_STREAM_NAME) == 0 && avg->type != KMS_MEDIA_TYPE_AUDIO) || (g_strcmp0 (selector, VIDEO_STREAM_NAME) == 0 && avg->type != KMS_MEDIA_TYPE_VIDEO))) { continue; } padname = kms_element_get_padname_from_id (self, id); if (padname == NULL) { GST_WARNING_OBJECT (self, "No pad identified by %s", id); continue; } /* Video and audio latencies are measured in nano seconds. They */ /* are such an small values so there is no harm in casting them */ /* to uint64 even we might lose a bit of preccision. */ pad_latency = gst_structure_new (padname, "type", G_TYPE_STRING, (avg->type == KMS_MEDIA_TYPE_AUDIO) ? AUDIO_STREAM_NAME : VIDEO_STREAM_NAME, "avg", G_TYPE_UINT64, (guint64) avg->avg, NULL); gst_structure_set (stats, padname, GST_TYPE_STRUCTURE, pad_latency, NULL); gst_structure_free (pad_latency); g_free (padname); } KMS_ELEMENT_UNLOCK (self); return stats; }
static void kms_recorder_endpoint_collect_media_stats (KmsElement * obj, gboolean enable) { KmsRecorderEndpoint *self = KMS_RECORDER_ENDPOINT (obj); KMS_ELEMENT_LOCK (self); self->priv->stats.enabled = enable; kms_recorder_endpoint_update_media_stats (self); KMS_ELEMENT_UNLOCK (self); KMS_ELEMENT_CLASS (kms_recorder_endpoint_parent_class)->collect_media_stats (obj, enable); }
static void kms_recorder_endpoint_state_changed (KmsRecorderEndpoint * self, KmsUriEndpointState state) { KMS_URI_ENDPOINT_GET_CLASS (self)->change_state (KMS_URI_ENDPOINT (self), state); KMS_ELEMENT_UNLOCK (KMS_ELEMENT (self)); g_mutex_lock (&self->priv->state_manager.mutex); self->priv->state_manager.changing = FALSE; if (self->priv->state_manager.locked > 0) g_cond_broadcast (&self->priv->state_manager.cond); g_mutex_unlock (&self->priv->state_manager.mutex); KMS_ELEMENT_LOCK (KMS_ELEMENT (self)); }
static gboolean set_to_null_state_on_EOS (gpointer data) { KmsRecorderEndpoint *recorder = KMS_RECORDER_ENDPOINT (data); GST_DEBUG ("Received EOS in pipeline, setting NULL state"); KMS_ELEMENT_LOCK (KMS_ELEMENT (recorder)); kms_muxing_pipeline_set_state (recorder->priv->mux, GST_STATE_NULL); kms_recorder_endpoint_state_changed (recorder, KMS_URI_ENDPOINT_STATE_STOP); KMS_ELEMENT_UNLOCK (KMS_ELEMENT (recorder)); return G_SOURCE_REMOVE; }