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 GstFlowReturn recv_sample (GstAppSink * appsink, gpointer user_data) { KmsRecorderEndpoint *self = KMS_RECORDER_ENDPOINT (GST_OBJECT_PARENT (appsink)); GstAppSrc *appsrc = GST_APP_SRC (user_data); KmsUriEndpointState state; GstFlowReturn ret; GstSample *sample; GstSegment *segment; GstBuffer *buffer; BaseTimeType *base_time; GstClockTime offset; g_signal_emit_by_name (appsink, "pull-sample", &sample); if (sample == NULL) return GST_FLOW_OK; buffer = gst_sample_get_buffer (sample); if (buffer == NULL) { ret = GST_FLOW_OK; goto end; } segment = gst_sample_get_segment (sample); g_object_get (G_OBJECT (self), "state", &state, NULL); if (state != KMS_URI_ENDPOINT_STATE_START) { GST_WARNING ("Dropping buffer received in invalid state %" GST_PTR_FORMAT, buffer); // TODO: Add a flag to discard buffers until keyframe ret = GST_FLOW_OK; goto end; } gst_buffer_ref (buffer); buffer = gst_buffer_make_writable (buffer); if (GST_BUFFER_PTS_IS_VALID (buffer)) buffer->pts = gst_segment_to_running_time (segment, GST_FORMAT_TIME, buffer->pts); if (GST_BUFFER_DTS_IS_VALID (buffer)) buffer->dts = gst_segment_to_running_time (segment, GST_FORMAT_TIME, buffer->dts); BASE_TIME_LOCK (self); base_time = g_object_get_data (G_OBJECT (self), BASE_TIME_DATA); if (base_time == NULL) { base_time = g_slice_new0 (BaseTimeType); base_time->pts = buffer->pts; base_time->dts = buffer->dts; GST_DEBUG_OBJECT (appsrc, "Setting pts base time to: %" G_GUINT64_FORMAT, base_time->pts); g_object_set_data_full (G_OBJECT (self), BASE_TIME_DATA, base_time, release_base_time_type); } if (!GST_CLOCK_TIME_IS_VALID (base_time->pts) && GST_BUFFER_PTS_IS_VALID (buffer)) { base_time->pts = buffer->pts; GST_DEBUG_OBJECT (appsrc, "Setting pts base time to: %" G_GUINT64_FORMAT, base_time->pts); base_time->dts = buffer->dts; } if (GST_CLOCK_TIME_IS_VALID (base_time->pts)) { if (GST_BUFFER_PTS_IS_VALID (buffer)) { offset = base_time->pts + self->priv->paused_time; if (buffer->pts > offset) { buffer->pts -= offset; } else { buffer->pts = 0; } } } if (GST_CLOCK_TIME_IS_VALID (base_time->dts)) { if (GST_BUFFER_DTS_IS_VALID (buffer)) { offset = base_time->dts + self->priv->paused_time; if (buffer->dts > offset) { buffer->dts -= offset; } else { buffer->dts = 0; } } } BASE_TIME_UNLOCK (GST_OBJECT_PARENT (appsink)); GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_LIVE); if (GST_BUFFER_FLAG_IS_SET (buffer, GST_BUFFER_FLAG_HEADER)) GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_DISCONT); ret = gst_app_src_push_buffer (appsrc, buffer); if (ret != GST_FLOW_OK) { /* something wrong */ GST_ERROR ("Could not send buffer to appsrc %s. Cause: %s", GST_ELEMENT_NAME (appsrc), gst_flow_get_name (ret)); } end: if (sample != NULL) { gst_sample_unref (sample); } return ret; }
static GstFlowReturn new_sample_post_handler (GstElement * appsink, gpointer user_data) { GstElement *appsrc = GST_ELEMENT (user_data); GstSample *sample = NULL; GstBuffer *buffer; GstFlowReturn ret; GstClockTime *base_time; g_signal_emit_by_name (appsink, "pull-sample", &sample); if (sample == NULL) return GST_FLOW_OK; buffer = gst_sample_get_buffer (sample); if (buffer == NULL) { ret = GST_FLOW_OK; goto end; } gst_buffer_ref (buffer); buffer = gst_buffer_make_writable (buffer); BASE_TIME_LOCK (GST_OBJECT_PARENT (appsrc)); base_time = g_object_get_qdata (G_OBJECT (GST_OBJECT_PARENT (appsrc)), base_time_data_quark ()); if (base_time == NULL) { GstClock *clock; clock = gst_element_get_clock (appsrc); base_time = g_slice_new0 (GstClockTime); g_object_set_qdata_full (G_OBJECT (GST_OBJECT_PARENT (appsrc)), base_time_data_quark (), base_time, release_gst_clock); *base_time = gst_clock_get_time (clock) - gst_element_get_base_time (appsrc); g_object_unref (clock); GST_DEBUG ("Setting base time to: %" G_GUINT64_FORMAT, *base_time); } if (GST_BUFFER_PTS_IS_VALID (buffer)) buffer->pts += *base_time; if (GST_BUFFER_DTS_IS_VALID (buffer)) buffer->dts += *base_time; BASE_TIME_UNLOCK (GST_OBJECT_PARENT (appsrc)); /* Pass the buffer through appsrc element which is */ /* placed in a different pipeline */ g_signal_emit_by_name (appsrc, "push-buffer", buffer, &ret); gst_buffer_unref (buffer); if (ret != GST_FLOW_OK) { /* something went wrong */ GST_ERROR ("Could not send buffer to appsrc %s. Cause %s", GST_ELEMENT_NAME (appsrc), gst_flow_get_name (ret)); } end: if (sample != NULL) gst_sample_unref (sample); return ret; }