mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-12-23 16:50:47 +00:00
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:
parent
f093e3f5fb
commit
ed893592ea
3 changed files with 32 additions and 9 deletions
|
@ -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, ¶m.hdr);
|
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: */
|
/* 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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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,6 +1431,9 @@ 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));
|
||||||
|
/* 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;
|
GST_BUFFER_DURATION (*buf) = src->duration;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue