mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-27 20:21:24 +00:00
v4l2: use driver timestamps
Use the drive timestamps for timestamping outgoing buffers.
This commit is contained in:
parent
eecb9a96a6
commit
46045316ce
2 changed files with 53 additions and 5 deletions
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
|
|
Loading…
Reference in a new issue