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,
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, &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: */
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;
}

View file

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

View file

@ -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)