v4l2: use driver timestamps

Use the drive timestamps for timestamping outgoing buffers.
This commit is contained in:
Wim Taymans 2012-04-24 12:37:33 +02:00
parent eecb9a96a6
commit 46045316ce
2 changed files with 53 additions and 5 deletions

View file

@ -587,6 +587,7 @@ gst_v4l2_buffer_pool_dqbuf (GstV4l2BufferPool * pool, GstBuffer ** buffer)
GstBuffer *outbuf; GstBuffer *outbuf;
struct v4l2_buffer vbuffer; struct v4l2_buffer vbuffer;
GstV4l2Object *obj = pool->obj; GstV4l2Object *obj = pool->obj;
GstClockTime timestamp;
if (obj->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) { if (obj->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) {
/* select works for input devices when data is available. According to the /* select works for input devices when data is available. According to the
@ -615,10 +616,13 @@ gst_v4l2_buffer_pool_dqbuf (GstV4l2BufferPool * pool, GstBuffer ** buffer)
pool->buffers[vbuffer.index] = NULL; pool->buffers[vbuffer.index] = NULL;
pool->num_queued--; pool->num_queued--;
timestamp = GST_TIMEVAL_TO_TIME (vbuffer.timestamp);
GST_LOG_OBJECT (pool, GST_LOG_OBJECT (pool,
"dequeued buffer %p seq:%d (ix=%d), used %d, flags %08x, pool-queued=%d, buffer=%p", "dequeued buffer %p seq:%d (ix=%d), used %d, flags %08x, ts %"
outbuf, vbuffer.sequence, vbuffer.index, vbuffer.bytesused, vbuffer.flags, GST_TIME_FORMAT ", pool-queued=%d, buffer=%p", outbuf, vbuffer.sequence,
pool->num_queued, outbuf); vbuffer.index, vbuffer.bytesused, vbuffer.flags,
GST_TIME_ARGS (timestamp), pool->num_queued, outbuf);
/* set top/bottom field first if v4l2_buffer has the information */ /* set top/bottom field first if v4l2_buffer has the information */
if (vbuffer.field == V4L2_FIELD_INTERLACED_TB) { if (vbuffer.field == V4L2_FIELD_INTERLACED_TB) {
@ -634,6 +638,8 @@ gst_v4l2_buffer_pool_dqbuf (GstV4l2BufferPool * pool, GstBuffer ** buffer)
else else
gst_buffer_resize (outbuf, 0, vbuffer.length); gst_buffer_resize (outbuf, 0, vbuffer.length);
GST_BUFFER_TIMESTAMP (outbuf) = timestamp;
*buffer = outbuf; *buffer = outbuf;
return GST_FLOW_OK; return GST_FLOW_OK;

View file

@ -779,6 +779,7 @@ gst_v4l2src_fill (GstPushSrc * src, GstBuffer * buf)
GstFlowReturn ret; GstFlowReturn ret;
GstClock *clock; GstClock *clock;
GstClockTime timestamp, duration; GstClockTime timestamp, duration;
GstClockTime delay;
#if 0 #if 0
int i; int i;
@ -798,6 +799,40 @@ gst_v4l2src_fill (GstPushSrc * src, GstBuffer * buf)
if (G_UNLIKELY (ret != GST_FLOW_OK)) if (G_UNLIKELY (ret != GST_FLOW_OK))
goto error; goto error;
timestamp = GST_BUFFER_TIMESTAMP (buf);
if (timestamp != GST_CLOCK_TIME_NONE) {
struct timespec now;
GstClockTime gstnow;
/* v4l2 specs say to use the system time although many drivers switched to
* the more desirable monotonic time. We first try to use the monotonic time
* and see how that goes */
clock_gettime (CLOCK_MONOTONIC, &now);
gstnow = GST_TIMESPEC_TO_TIME (now);
if (gstnow < timestamp && (timestamp - gstnow) > (10 * GST_SECOND)) {
GTimeVal now;
/* very large diff, fall back to system time */
g_get_current_time (&now);
gstnow = GST_TIMEVAL_TO_TIME (now);
}
if (gstnow > timestamp) {
delay = gstnow - timestamp;
} else {
delay = 0;
}
GST_DEBUG_OBJECT (v4l2src, "ts: %" GST_TIME_FORMAT " now %" GST_TIME_FORMAT
" delay %" GST_TIME_FORMAT, GST_TIME_ARGS (timestamp),
GST_TIME_ARGS (gstnow), GST_TIME_ARGS (delay));
} else {
delay = 0;
}
/* set buffer metadata */ /* set buffer metadata */
GST_BUFFER_OFFSET (buf) = v4l2src->offset++; GST_BUFFER_OFFSET (buf) = v4l2src->offset++;
GST_BUFFER_OFFSET_END (buf) = v4l2src->offset; GST_BUFFER_OFFSET_END (buf) = v4l2src->offset;
@ -822,6 +857,12 @@ gst_v4l2src_fill (GstPushSrc * src, GstBuffer * buf)
timestamp = gst_clock_get_time (clock) - timestamp; timestamp = gst_clock_get_time (clock) - timestamp;
gst_object_unref (clock); gst_object_unref (clock);
/* adjust for delay in the device */
if (timestamp > delay)
timestamp -= delay;
else
timestamp = 0;
/* if we have a framerate adjust timestamp for frame latency */ /* if we have a framerate adjust timestamp for frame latency */
if (GST_CLOCK_TIME_IS_VALID (duration)) { if (GST_CLOCK_TIME_IS_VALID (duration)) {
if (timestamp > duration) if (timestamp > duration)
@ -841,8 +882,9 @@ gst_v4l2src_fill (GstPushSrc * src, GstBuffer * buf)
v4l2src->ctrl_time = timestamp; v4l2src->ctrl_time = timestamp;
} }
gst_object_sync_values (GST_OBJECT (src), v4l2src->ctrl_time); gst_object_sync_values (GST_OBJECT (src), v4l2src->ctrl_time);
GST_INFO_OBJECT (src, "sync to %" GST_TIME_FORMAT,
GST_TIME_ARGS (v4l2src->ctrl_time)); GST_INFO_OBJECT (src, "sync to %" GST_TIME_FORMAT " out ts %" GST_TIME_FORMAT,
GST_TIME_ARGS (v4l2src->ctrl_time), GST_TIME_ARGS (timestamp));
/* FIXME: use the timestamp from the buffer itself! */ /* FIXME: use the timestamp from the buffer itself! */
GST_BUFFER_TIMESTAMP (buf) = timestamp; GST_BUFFER_TIMESTAMP (buf) = timestamp;