static GstBusSyncReply bus_sync_signal_handler (GstBus * bus, GstMessage * msg, gpointer data) { KmsRecorderEndpoint *self = KMS_RECORDER_ENDPOINT (data); if (GST_MESSAGE_TYPE (msg) == GST_MESSAGE_ERROR) { ErrorData *data; GST_DEBUG_BIN_TO_DOT_FILE_WITH_TS (GST_BIN (self), GST_DEBUG_GRAPH_SHOW_ALL, GST_ELEMENT_NAME (self)); kms_base_media_muxer_dot_file (self->priv->mux); GST_ERROR_OBJECT (self, "Message %" GST_PTR_FORMAT, msg); data = create_error_data (self, msg); GST_ERROR_OBJECT (self, "Error: %" GST_PTR_FORMAT, msg); gst_task_pool_push (self->priv->pool, kms_recorder_endpoint_post_error, data, NULL); } else if (GST_MESSAGE_TYPE (msg) == GST_MESSAGE_EOS) { gst_task_pool_push (self->priv->pool, kms_recorder_endpoint_on_eos_message, self, NULL); } else if ((GST_MESSAGE_TYPE (msg) == GST_MESSAGE_STATE_CHANGED) && (GST_OBJECT_CAST (KMS_BASE_MEDIA_MUXER_GET_PIPELINE (self-> priv->mux)) == GST_MESSAGE_SRC (msg))) { GstState new_state, pending; gst_message_parse_state_changed (msg, NULL, &new_state, &pending); if (pending == GST_STATE_VOID_PENDING || (pending == GST_STATE_NULL && new_state == GST_STATE_READY)) { GST_DEBUG_OBJECT (self, "Pipeline changed state to %d", new_state); switch (new_state) { case GST_STATE_PLAYING: kms_recorder_endpoint_state_changed (self, KMS_URI_ENDPOINT_STATE_START); break; case GST_STATE_READY: kms_recorder_endpoint_state_changed (self, KMS_URI_ENDPOINT_STATE_STOP); break; default: GST_DEBUG_OBJECT (self, "Not raising event"); break; } } } return GST_BUS_PASS; }
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); /* Set internal pipeline to playing */ kms_base_media_muxer_set_state (self->priv->mux, GST_STATE_PLAYING); 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); kms_recorder_endpoint_state_changed (self, KMS_URI_ENDPOINT_STATE_START); }
static void kms_recorder_endpoint_stopped (KmsUriEndpoint * obj) { KmsRecorderEndpoint *self = KMS_RECORDER_ENDPOINT (obj); kms_recorder_endpoint_change_state (self); if (kms_base_media_muxer_get_state (self->priv->mux) >= GST_STATE_PAUSED) { kms_recorder_endpoint_send_eos_to_appsrcs (self); self->priv->stopping = TRUE; } kms_recorder_endpoint_remove_pads (self); // Reset base time data BASE_TIME_LOCK (self); g_object_set_data_full (G_OBJECT (self), BASE_TIME_DATA, 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_base_media_muxer_set_state (self->priv->mux, GST_STATE_NULL); kms_recorder_endpoint_state_changed (self, KMS_URI_ENDPOINT_STATE_STOP); } }
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); }
static void kms_recorder_endpoint_send_eos_to_appsrcs (KmsRecorderEndpoint * self) { GstElement *audiosrc, *videosrc; g_object_get (self->priv->mux, KMS_MUXING_PIPELINE_AUDIO_APPSRC, &audiosrc, NULL); g_object_get (self->priv->mux, KMS_MUXING_PIPELINE_VIDEO_APPSRC, &videosrc, NULL); if (audiosrc == NULL && videosrc == NULL) { kms_muxing_pipeline_set_state (self->priv->mux, GST_STATE_NULL); kms_recorder_endpoint_state_changed (self, KMS_URI_ENDPOINT_STATE_STOP); return; } kms_muxing_pipeline_set_state (self->priv->mux, GST_STATE_PLAYING); if (audiosrc != NULL) { send_eos (audiosrc); g_object_unref (audiosrc); } if (videosrc != NULL) { send_eos (videosrc); g_object_unref (videosrc); } }
static void kms_recorder_endpoint_started (KmsUriEndpoint * obj) { KmsRecorderEndpoint *self = KMS_RECORDER_ENDPOINT (obj); kms_recorder_endpoint_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_endpoint_open_valves (self); kms_recorder_endpoint_state_changed (self, KMS_URI_ENDPOINT_STATE_START); }
static void kms_recorder_endpoint_send_eos_to_appsrcs (KmsRecorderEndpoint * self) { GstElement *audiosrc = gst_bin_get_by_name (GST_BIN (self->priv->pipeline), AUDIO_APPSRC); GstElement *videosrc = gst_bin_get_by_name (GST_BIN (self->priv->pipeline), VIDEO_APPSRC); if (audiosrc == NULL && videosrc == NULL) { gst_element_set_state (self->priv->pipeline, GST_STATE_NULL); kms_recorder_endpoint_state_changed (self, KMS_URI_ENDPOINT_STATE_STOP); return; } gst_element_set_state (self->priv->pipeline, GST_STATE_PLAYING); if (audiosrc != NULL) { send_eos (audiosrc); g_object_unref (audiosrc); } if (videosrc != NULL) { send_eos (videosrc); g_object_unref (videosrc); } }
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 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; }
static void kms_recorder_endpoint_send_eos_to_appsrcs (KmsRecorderEndpoint * self) { KMS_ELEMENT_LOCK (KMS_ELEMENT (self)); if (g_hash_table_size (self->priv->srcs) == 0) { kms_base_media_muxer_set_state (self->priv->mux, GST_STATE_NULL); kms_recorder_endpoint_state_changed (self, KMS_URI_ENDPOINT_STATE_STOP); goto end; } kms_base_media_muxer_set_state (self->priv->mux, GST_STATE_PLAYING); g_hash_table_foreach (self->priv->srcs, (GHFunc) send_eos_cb, NULL); end: KMS_ELEMENT_UNLOCK (KMS_ELEMENT (self)); }
static void kms_recorder_endpoint_stopped (KmsUriEndpoint * obj) { KmsRecorderEndpoint *self = KMS_RECORDER_ENDPOINT (obj); GstElement *audio_src, *video_src; kms_recorder_endpoint_change_state (self); /* Close valves */ kms_recorder_endpoint_close_valves (self); // Reset base time data audio_src = gst_bin_get_by_name (GST_BIN (self->priv->pipeline), AUDIO_APPSRC); video_src = gst_bin_get_by_name (GST_BIN (self->priv->pipeline), VIDEO_APPSRC); KMS_ELEMENT_LOCK (self); if (audio_src != NULL) { g_object_set_data_full (G_OBJECT (audio_src), BASE_TIME_DATA, NULL, NULL); g_object_unref (audio_src); } if (video_src != NULL) { g_object_set_data_full (G_OBJECT (video_src), BASE_TIME_DATA, NULL, NULL); g_object_unref (video_src); } self->priv->paused_time = G_GUINT64_CONSTANT (0); self->priv->paused_start = GST_CLOCK_TIME_NONE; KMS_ELEMENT_UNLOCK (self); if (GST_STATE (self->priv->pipeline) >= GST_STATE_PAUSED) { kms_recorder_endpoint_send_eos_to_appsrcs (self); } else { gst_element_set_state (self->priv->pipeline, GST_STATE_NULL); kms_recorder_endpoint_state_changed (self, KMS_URI_ENDPOINT_STATE_STOP); } }
static void kms_recorder_endpoint_paused (KmsUriEndpoint * obj) { KmsRecorderEndpoint *self = KMS_RECORDER_ENDPOINT (obj); kms_recorder_endpoint_change_state (self); /* Close valves */ kms_recorder_endpoint_remove_pads (self); /* Set internal pipeline to GST_STATE_PAUSED */ kms_muxing_pipeline_set_state (self->priv->mux, GST_STATE_PAUSED); KMS_ELEMENT_LOCK (self); self->priv->paused_start = gst_clock_get_time (kms_muxing_pipeline_get_clock (self->priv->mux)); KMS_ELEMENT_UNLOCK (self); kms_recorder_endpoint_state_changed (self, KMS_URI_ENDPOINT_STATE_PAUSE); }
static void kms_recorder_endpoint_on_eos (KmsBaseMediaMuxer * obj, gpointer user_data) { KmsRecorderEndpoint *recorder = KMS_RECORDER_ENDPOINT (user_data); GST_DEBUG_OBJECT (recorder, "Received EOS in muxing pipeline, setting NULL state"); KMS_ELEMENT_LOCK (KMS_ELEMENT (recorder)); kms_base_media_muxer_set_state (recorder->priv->mux, GST_STATE_NULL); kms_recorder_endpoint_state_changed (recorder, KMS_URI_ENDPOINT_STATE_STOP); if (recorder->priv->stopping) { GST_WARNING_OBJECT (recorder, "Releasing pending pads"); g_slist_foreach (recorder->priv->pending_pads, (GFunc) kms_recorder_release_pending_pad, recorder); g_slist_free_full (recorder->priv->pending_pads, g_free); recorder->priv->pending_pads = NULL; recorder->priv->stopping = FALSE; } KMS_ELEMENT_UNLOCK (KMS_ELEMENT (recorder)); }