}
GstFlowReturn
-raspi_capture_fill_buffer(RASPIVID_STATE *state, GstBuffer **bufp)
+raspi_capture_fill_buffer(RASPIVID_STATE *state, GstBuffer **bufp,
+ GstClock *clock, GstClockTime base_time)
{
GstBuffer *buf;
MMAL_BUFFER_HEADER_T *buffer;
GstFlowReturn ret = GST_FLOW_ERROR;
+ /* No timestamps if no clockm or invalid PTS */
+ GstClockTime gst_pts = GST_CLOCK_TIME_NONE;
/* FIXME: Use our own interruptible cond wait: */
buffer = mmal_queue_wait(state->encoded_buffer_q);
+
+ if (G_LIKELY (clock)) {
+ MMAL_PARAMETER_INT64_T param;
+ GstClockTime runtime;
+
+ runtime = gst_clock_get_time (clock) - base_time;
+
+ param.hdr.id = MMAL_PARAMETER_SYSTEM_TIME;
+ param.hdr.size = sizeof(param);
+ param.value = -1;
+
+ mmal_port_parameter_get(state->encoder_output_port, ¶m.hdr);
+
+ if (param.value != -1 && param.value >= buffer->pts) {
+ GstClockTime offset = param.value - buffer->pts;
+ if (runtime >= offset)
+ gst_pts = runtime - offset;
+ }
+ GST_LOG ("Buf PTS %" G_GINT64_FORMAT " DTS %" G_GINT64_FORMAT
+ " STC %" G_GINT64_FORMAT " TS %" GST_TIME_FORMAT,
+ buffer->pts, buffer->dts, param.value,
+ GST_TIME_ARGS (gst_pts));
+ }
+
+
mmal_buffer_header_mem_lock(buffer);
buf = gst_buffer_new_allocate(NULL, buffer->length, NULL);
if (buf) {
+ /* 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;
}
.num_preview_video_frames = 3,
.stills_capture_circular_buffer_height = 0,
.fast_preview_resume = 0,
- .use_stc_timestamp = MMAL_PARAM_TIMESTAMP_MODE_RESET_STC
+ .use_stc_timestamp = MMAL_PARAM_TIMESTAMP_MODE_RAW_STC
};
camera = state->camera_component;
void raspicapture_default_config(RASPIVID_CONFIG *config);
RASPIVID_STATE *raspi_capture_setup(RASPIVID_CONFIG *config);
gboolean raspi_capture_start(RASPIVID_STATE *state);
-GstFlowReturn raspi_capture_fill_buffer(RASPIVID_STATE *state, GstBuffer **buf);
+GstFlowReturn raspi_capture_fill_buffer(RASPIVID_STATE *state, GstBuffer **buf,
+ GstClock *clock, GstClockTime base_time);
void raspi_capture_stop(RASPIVID_STATE *state);
void raspi_capture_free(RASPIVID_STATE *state);
gboolean raspi_capture_request_i_frame(RASPIVID_STATE *state);
raspicapture_default_config (&src->capture_config);
src->capture_config.intraperiod = KEYFRAME_INTERVAL_DEFAULT;
src->capture_config.verbose = 1;
- /* do-timestamping by default for now. FIXME: Implement proper timestamping */
- gst_base_src_set_do_timestamp (GST_BASE_SRC (src), TRUE);
+ /* 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);
}
static void
{
GstRpiCamSrc *src = GST_RPICAMSRC (parent);
GstFlowReturn ret;
+ GstClock *clock = NULL;
+ GstClockTime base_time;
+
if (!src->started) {
if (!raspi_capture_start (src->capture_state))
return GST_FLOW_ERROR;
src->started = TRUE;
}
+ GST_OBJECT_LOCK (src);
+ if ((clock = GST_ELEMENT_CLOCK (src)) != NULL)
+ gst_object_ref (clock);
+ base_time = GST_ELEMENT_CAST (src)->base_time;
+ GST_OBJECT_UNLOCK (src);
+
/* FIXME: Use custom allocator */
- ret = raspi_capture_fill_buffer (src->capture_state, buf);
+ ret = raspi_capture_fill_buffer (src->capture_state, buf, clock, base_time);
if (*buf)
GST_LOG_OBJECT (src, "Made buffer of size %" G_GSIZE_FORMAT,
gst_buffer_get_size (*buf));
+
+ if (clock)
+ gst_object_unref (clock);
return ret;
}