From ed893592eaa5493fa3b3b92e7255b209da1672ab Mon Sep 17 00:00:00 2001 From: Jan Schmidt Date: Sat, 1 Jul 2017 00:51:13 +1000 Subject: [PATCH] rpicamsrc: Implement use-stc property to disable STC timestamps If use-stc=false, then rpicamsrc won't apply the camera timestamping to outgoing buffers, instead relying on real-time timestamping by the GStreamer clock. It means slightly less accuracy and more jitter in timestamps, but might help on some CSI inputs with broken timestamping. --- sys/rpicamsrc/RaspiCapture.c | 12 ++++++++---- sys/rpicamsrc/RaspiCapture.h | 2 ++ sys/rpicamsrc/gstrpicamsrc.c | 27 ++++++++++++++++++++++----- 3 files changed, 32 insertions(+), 9 deletions(-) diff --git a/sys/rpicamsrc/RaspiCapture.c b/sys/rpicamsrc/RaspiCapture.c index c50ef99..d0616c5 100644 --- a/sys/rpicamsrc/RaspiCapture.c +++ b/sys/rpicamsrc/RaspiCapture.c @@ -929,6 +929,7 @@ GstFlowReturn raspi_capture_fill_buffer(RASPIVID_STATE *state, GstBuffer **bufp, GstClock *clock, GstClockTime base_time) { + RASPIVID_CONFIG *config = &state->config; GstBuffer *buf; MMAL_BUFFER_HEADER_T *buffer; GstFlowReturn ret = GST_FLOW_ERROR; @@ -939,7 +940,7 @@ raspi_capture_fill_buffer(RASPIVID_STATE *state, GstBuffer **bufp, buffer = mmal_queue_wait(state->encoded_buffer_q); - if (G_LIKELY (clock)) { + if (G_LIKELY (config->useSTC && clock)) { MMAL_PARAMETER_INT64_T param; GstClockTime runtime; @@ -951,7 +952,7 @@ raspi_capture_fill_buffer(RASPIVID_STATE *state, GstBuffer **bufp, mmal_port_parameter_get(state->encoder_output_port, ¶m.hdr); - if (param.value != -1 && param.value >= buffer->pts) { + if (buffer->pts != -1 && param.value != -1 && param.value >= buffer->pts) { /* Convert microsecond RPi TS to GStreamer clock: */ GstClockTime offset = (param.value - buffer->pts) * 1000; if (runtime >= offset) @@ -963,13 +964,16 @@ raspi_capture_fill_buffer(RASPIVID_STATE *state, GstBuffer **bufp, buffer->pts, buffer->dts, param.value, param.value - buffer->pts, GST_TIME_ARGS (gst_pts)); } - + else { + GST_LOG ("use-stc=false. Not applying STC to buffer"); + } mmal_buffer_header_mem_lock(buffer); buf = gst_buffer_new_allocate(NULL, buffer->length, NULL); if (buf) { + if (config->useSTC) + GST_BUFFER_DTS(buf) = GST_BUFFER_PTS(buf) = gst_pts; /* FIXME: Can we avoid copies and give MMAL our own buffers to fill? */ - GST_BUFFER_PTS(buf) = gst_pts; gst_buffer_fill(buf, 0, buffer->data, buffer->length); ret = GST_FLOW_OK; } diff --git a/sys/rpicamsrc/RaspiCapture.h b/sys/rpicamsrc/RaspiCapture.h index 6a79ac5..053ae1c 100644 --- a/sys/rpicamsrc/RaspiCapture.h +++ b/sys/rpicamsrc/RaspiCapture.h @@ -116,6 +116,8 @@ typedef struct int jpegQuality; int jpegRestartInterval; + + int useSTC; } RASPIVID_CONFIG; typedef struct RASPIVID_STATE_T RASPIVID_STATE; diff --git a/sys/rpicamsrc/gstrpicamsrc.c b/sys/rpicamsrc/gstrpicamsrc.c index f2a993c..7cd369e 100644 --- a/sys/rpicamsrc/gstrpicamsrc.c +++ b/sys/rpicamsrc/gstrpicamsrc.c @@ -138,7 +138,8 @@ enum #ifdef GST_RPI_CAM_SRC_ENABLE_VIDEO_DIRECTION PROP_VIDEO_DIRECTION, #endif - PROP_JPEG_QUALITY + PROP_JPEG_QUALITY, + PROP_USE_STC }; #define CAMERA_DEFAULT 0 @@ -488,6 +489,10 @@ gst_rpi_cam_src_class_init (GstRpiCamSrcClass * klass) g_object_class_override_property (gobject_class, PROP_VIDEO_DIRECTION, "video-direction"); #endif + g_object_class_install_property (gobject_class, PROP_USE_STC, + g_param_spec_boolean ("use-stc", "Use System Time Clock", + "Use the camera STC for timestamping buffers", TRUE, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); gst_element_class_set_static_metadata (gstelement_class, "Raspberry Pi Camera Source", "Source/Video", @@ -517,12 +522,12 @@ gst_rpi_cam_src_init (GstRpiCamSrc * src) raspicapture_default_config (&src->capture_config); src->capture_config.intraperiod = KEYFRAME_INTERVAL_DEFAULT; src->capture_config.verbose = 1; + src->capture_config.useSTC = TRUE; g_mutex_init (&src->config_lock); - /* Don't let basesrc set timestamps, we'll do it using - * buffer PTS and system times */ - gst_base_src_set_do_timestamp (GST_BASE_SRC (src), FALSE); + /* basesrc will generate timestamps if use-stc = false */ + gst_base_src_set_do_timestamp (GST_BASE_SRC (src), TRUE); /* Generate the channels list */ channel = g_object_new (GST_TYPE_COLOR_BALANCE_CHANNEL, NULL); @@ -1006,6 +1011,9 @@ gst_rpi_cam_src_set_property (GObject * object, guint prop_id, gst_rpi_cam_src_set_orientation (src, g_value_get_enum (value)); break; #endif + case PROP_USE_STC: + src->capture_config.useSTC = g_value_get_boolean (value); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -1170,6 +1178,9 @@ gst_rpi_cam_src_get_property (GObject * object, guint prop_id, g_value_set_enum (value, src->orientation); break; #endif + case PROP_USE_STC: + g_value_set_boolean (value, src->capture_config.useSTC); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -1182,6 +1193,9 @@ gst_rpi_cam_src_start (GstBaseSrc * parent) { GstRpiCamSrc *src = GST_RPICAMSRC (parent); GST_LOG_OBJECT (src, "In src_start()"); + /* Ensure basesrc timestamping is off is use-stc is on */ + if (src->capture_config.useSTC) + gst_base_src_set_do_timestamp (GST_BASE_SRC (src), FALSE); g_mutex_lock (&src->config_lock); src->capture_state = raspi_capture_setup (&src->capture_config); /* Clear all capture flags */ @@ -1417,7 +1431,10 @@ gst_rpi_cam_src_create (GstPushSrc * parent, GstBuffer ** buf) if (*buf) { GST_LOG_OBJECT (src, "Made buffer of size %" G_GSIZE_FORMAT, gst_buffer_get_size (*buf)); - GST_BUFFER_DURATION (*buf) = src->duration; + /* Only set the duration when we have a PTS update from the rpi encoder. + * not every buffer is a frame */ + if (GST_BUFFER_PTS_IS_VALID (*buf)) + GST_BUFFER_DURATION (*buf) = src->duration; } if (clock) -- 2.7.4