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.
This commit is contained in:
Jan Schmidt 2017-07-01 00:51:13 +10:00 committed by Tim-Philipp Müller
parent f093e3f5fb
commit ed893592ea
3 changed files with 32 additions and 9 deletions

View file

@ -929,6 +929,7 @@ GstFlowReturn
raspi_capture_fill_buffer(RASPIVID_STATE *state, GstBuffer **bufp, raspi_capture_fill_buffer(RASPIVID_STATE *state, GstBuffer **bufp,
GstClock *clock, GstClockTime base_time) GstClock *clock, GstClockTime base_time)
{ {
RASPIVID_CONFIG *config = &state->config;
GstBuffer *buf; GstBuffer *buf;
MMAL_BUFFER_HEADER_T *buffer; MMAL_BUFFER_HEADER_T *buffer;
GstFlowReturn ret = GST_FLOW_ERROR; 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); buffer = mmal_queue_wait(state->encoded_buffer_q);
if (G_LIKELY (clock)) { if (G_LIKELY (config->useSTC && clock)) {
MMAL_PARAMETER_INT64_T param; MMAL_PARAMETER_INT64_T param;
GstClockTime runtime; GstClockTime runtime;
@ -951,7 +952,7 @@ raspi_capture_fill_buffer(RASPIVID_STATE *state, GstBuffer **bufp,
mmal_port_parameter_get(state->encoder_output_port, &param.hdr); mmal_port_parameter_get(state->encoder_output_port, &param.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: */ /* Convert microsecond RPi TS to GStreamer clock: */
GstClockTime offset = (param.value - buffer->pts) * 1000; GstClockTime offset = (param.value - buffer->pts) * 1000;
if (runtime >= offset) 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, buffer->pts, buffer->dts, param.value, param.value - buffer->pts,
GST_TIME_ARGS (gst_pts)); GST_TIME_ARGS (gst_pts));
} }
else {
GST_LOG ("use-stc=false. Not applying STC to buffer");
}
mmal_buffer_header_mem_lock(buffer); mmal_buffer_header_mem_lock(buffer);
buf = gst_buffer_new_allocate(NULL, buffer->length, NULL); buf = gst_buffer_new_allocate(NULL, buffer->length, NULL);
if (buf) { 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? */ /* 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); gst_buffer_fill(buf, 0, buffer->data, buffer->length);
ret = GST_FLOW_OK; ret = GST_FLOW_OK;
} }

View file

@ -116,6 +116,8 @@ typedef struct
int jpegQuality; int jpegQuality;
int jpegRestartInterval; int jpegRestartInterval;
int useSTC;
} RASPIVID_CONFIG; } RASPIVID_CONFIG;
typedef struct RASPIVID_STATE_T RASPIVID_STATE; typedef struct RASPIVID_STATE_T RASPIVID_STATE;

View file

@ -138,7 +138,8 @@ enum
#ifdef GST_RPI_CAM_SRC_ENABLE_VIDEO_DIRECTION #ifdef GST_RPI_CAM_SRC_ENABLE_VIDEO_DIRECTION
PROP_VIDEO_DIRECTION, PROP_VIDEO_DIRECTION,
#endif #endif
PROP_JPEG_QUALITY PROP_JPEG_QUALITY,
PROP_USE_STC
}; };
#define CAMERA_DEFAULT 0 #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, g_object_class_override_property (gobject_class, PROP_VIDEO_DIRECTION,
"video-direction"); "video-direction");
#endif #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, gst_element_class_set_static_metadata (gstelement_class,
"Raspberry Pi Camera Source", "Source/Video", "Raspberry Pi Camera Source", "Source/Video",
@ -517,12 +522,12 @@ gst_rpi_cam_src_init (GstRpiCamSrc * src)
raspicapture_default_config (&src->capture_config); raspicapture_default_config (&src->capture_config);
src->capture_config.intraperiod = KEYFRAME_INTERVAL_DEFAULT; src->capture_config.intraperiod = KEYFRAME_INTERVAL_DEFAULT;
src->capture_config.verbose = 1; src->capture_config.verbose = 1;
src->capture_config.useSTC = TRUE;
g_mutex_init (&src->config_lock); g_mutex_init (&src->config_lock);
/* Don't let basesrc set timestamps, we'll do it using /* basesrc will generate timestamps if use-stc = false */
* buffer PTS and system times */ gst_base_src_set_do_timestamp (GST_BASE_SRC (src), TRUE);
gst_base_src_set_do_timestamp (GST_BASE_SRC (src), FALSE);
/* Generate the channels list */ /* Generate the channels list */
channel = g_object_new (GST_TYPE_COLOR_BALANCE_CHANNEL, NULL); 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)); gst_rpi_cam_src_set_orientation (src, g_value_get_enum (value));
break; break;
#endif #endif
case PROP_USE_STC:
src->capture_config.useSTC = g_value_get_boolean (value);
break;
default: default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break; break;
@ -1170,6 +1178,9 @@ gst_rpi_cam_src_get_property (GObject * object, guint prop_id,
g_value_set_enum (value, src->orientation); g_value_set_enum (value, src->orientation);
break; break;
#endif #endif
case PROP_USE_STC:
g_value_set_boolean (value, src->capture_config.useSTC);
break;
default: default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break; break;
@ -1182,6 +1193,9 @@ gst_rpi_cam_src_start (GstBaseSrc * parent)
{ {
GstRpiCamSrc *src = GST_RPICAMSRC (parent); GstRpiCamSrc *src = GST_RPICAMSRC (parent);
GST_LOG_OBJECT (src, "In src_start()"); 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); g_mutex_lock (&src->config_lock);
src->capture_state = raspi_capture_setup (&src->capture_config); src->capture_state = raspi_capture_setup (&src->capture_config);
/* Clear all capture flags */ /* Clear all capture flags */
@ -1417,7 +1431,10 @@ gst_rpi_cam_src_create (GstPushSrc * parent, GstBuffer ** buf)
if (*buf) { if (*buf) {
GST_LOG_OBJECT (src, "Made buffer of size %" G_GSIZE_FORMAT, GST_LOG_OBJECT (src, "Made buffer of size %" G_GSIZE_FORMAT,
gst_buffer_get_size (*buf)); 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) if (clock)