media: vivid: Improve timestamping
PATCH v2 1/1 media: vivid: Improve timestamping
Simulate a more precise timestamp by calculating it based on the current framerate.
---
Changes in v2:
- fix spelling
- end of exposure is offset by 90% of the frame period
- fix timestamp calculation for FIELD_ALTERNATE (untested)
- timestamp is now calculated and set from vivid_thread_cap_tick()
- capture vbi uses the same timestamp as non-vbi, but offset by 5%
- timestamp stays consistent even if the FPS changes
- tested with dropped frames
If 'Start of Exposure'/'End of Frame' changes mid-capture, it will be completely ignored. If that's an issue, I'll change how the frame period and cap_stream_start are calculated.
Also, should I modify the output's timestamp on this patch or on a separated one?
--- drivers/media/platform/vivid/vivid-core.h | 2 + drivers/media/platform/vivid/vivid-kthread-cap.c | 47 +++++++++++++++++------- drivers/media/platform/vivid/vivid-vbi-cap.c | 4 -- 3 files changed, 35 insertions(+), 18 deletions(-)
drivers/media/platform/vivid/vivid-core.h +2 -0
@@ -384,6 +384,8 @@ struct vivid_dev {/* thread for generating video capture stream */ struct task_struct *kthread_vid_cap;unsigned long jiffies_vid_cap; +u64 cap_stream_start; +u64 cap_frame_period;u32 cap_seq_offset;u32 cap_seq_count;bool cap_seq_resync;
drivers/media/platform/vivid/vivid-kthread-cap.c +33 -14
102 lines not on this page · raw message
drivers/media/platform/vivid/vivid-vbi-cap.c +0 -4
@@ -95,8 +95,6 @@ void vivid_raw_vbi_cap_process(struct vivid_dev *dev, struct vivid_buffer *buf)if (!VIVID_INVALID_SIGNAL (dev->std_signal_mode))vivid_vbi_gen_raw (&dev->vbi_gen, &vbi, vbuf); - - buf->vb.vb2_buf.timestamp =ktime_get_ns () + dev->time_wrap_offset; }
@@ -119,8 +117,6 @@ void vivid_sliced_vbi_cap_process(struct vivid_dev *dev,for (i =0 ; i <25 ; i++) vbuf[i] = dev->vbi_gen.data[i]; } - - buf->vb.vb2_buf.timestamp =ktime_get_ns () + dev->time_wrap_offset; } static int vbi_cap_queue_setup(struct vb2_queue *vq,
Signature · 1 line
1.9.1
Hi Gabriel,
This doesn't work. See my comment below.
I recommend testing with:
v4l2-ctl -P --stream-mmap --verbose
This shows the expected frame rate and --verbose shows the reported frame periods.
Quoted 14 lines · Gabriel Francisco Mandaji
Simulate a more precise timestamp by calculating it based on the current framerate.
Signed-off-by Gabriel Francisco Mandaji <[email protected]>---
Changes in v2:
- fix spelling
- end of exposure is offset by 90% of the frame period
- fix timestamp calculation forFIELD_ALTERNATE(untested)
- timestamp is now calculated and set fromvivid_thread_cap_tick()
- capture vbi uses the same timestamp as non-vbi, but offset by 5%
- timestamp stays consistent even if the FPS changes
- tested with dropped frames
Quoted 6 lines
If 'Start of Exposure'/'End of Frame' changes mid-capture, it will be completely ignored. If that's an issue, I'll change how the frame period and
cap_stream_startare calculated.Also, should I modify the output's timestamp on this patch or on
adrivers/media/platform/vivid/vivid-kthread-cap.cseparated one?
Separate one.
Quoted 57 lines
--- drivers/media/platform/vivid/vivid-core.h | 2 + drivers/media/platform/vivid/vivid-kthread-cap.c | 47 +++++++++++++++++------- drivers/media/platform/vivid/vivid-vbi-cap.c | 4 -- 3 files changed, 35 insertions(+), 18 deletions(-)drivers/media/platform/vivid/vivid-core.h +2
-0@@ -384,6 +384,8 @@ struct vivid_dev {/* thread for generating video capture stream */ struct task_struct *kthread_vid_cap;unsigned long jiffies_vid_cap; +u64 cap_stream_start; +u64 cap_frame_period;u32 cap_seq_offset;u32 cap_seq_count;bool cap_seq_resync;drivers/media/platform/vivid/vivid-kthread-cap.c +2
-14@@ -425,12 +425,6 @@ static void vivid_fillbuff(struct vivid_dev *dev, struct vivid_buffer *buf) is_loop = true; buf->vb.sequence = dev->vid_cap_seq_count; -/* -* Take the timestamp now if the timestamp source is set to -* "Start of Exposure". -*/ -if (dev->tstamp_src_is_soe) - buf->vb.vb2_buf.timestamp =ktime_get_ns ();if (dev->field_cap ==V4L2_FIELD_ALTERNATE ) {/* * 60 Hz standards start with the bottom field, 50 Hz standards @@ -554,14 +548,6 @@ static void vivid_fillbuff(struct vivid_dev *dev, struct vivid_buffer *buf) } } } - -/* -* If "End of Frame" is specified at the timestamp source, then take -* the timestamp now. -*/ -if (!dev->tstamp_src_is_soe) - buf->vb.vb2_buf.timestamp =ktime_get_ns (); - buf->vb.vb2_buf.timestamp += dev->time_wrap_offset; }/* @@ -667,10 +653,27 @@ static void vivid_overlay(struct vivid_dev *dev, struct vivid_buffer *buf) } } +static void vivid_cap_update_frame_period (struct vivid_dev *dev) +{
drivers/media/platform/vivid/vivid-kthread-cap.c static void vivid_overlay(struct vivid_dev *dev, struct vivid_buffer *buf) · line 667
Quoted 10 lines
drivers/media/platform/vivid/vivid-kthread-cap.c +10
-0+u64 f_period = dev->timeperframe_vid_cap.numerator *1000000000 / + dev->timeperframe_vid_cap.denominator; +if (dev->field_cap ==V4L2_FIELD_ALTERNATE ) + f_period /=2 ; +/* +* If "End of Frame", then calculate the exposure time as 0.9 +* of the frame period. +*/ +if (!dev->tstamp_src_is_soe) + f_period += f_period /10 *9 ;
This is very wrong: if the timestamp is for the "End of Frame" (the default), then that does not change the frame period value, it just adds an offset.
Easiest is probably to add a dev->cap_frame_offset field:
if (dev->tstamp_src_is_soe) dev->cap_frame_offset = 0; else dev->cap_frame_offset = f_period * 9 / 10;
This bug gave really weird frame periods.
Regards,
Hans
Quoted 89 lines
drivers/media/platform/vivid/vivid-kthread-cap.c +21
-0+ + dev->cap_frame_period = f_period; +} +static void vivid_thread_vid_cap_tick (struct vivid_dev *dev,int dropped_bufs) {struct vivid_buffer *vid_cap_buf =NULL ;struct vivid_buffer *vbi_cap_buf =NULL ; +u64 f_time =0 ;dprintk (dev,1 ,"Video Capture Thread Tick\n" );@@ -702,6 +705,9 @@ static void vivid_thread_vid_cap_tick(struct vivid_dev *dev, int dropped_bufs)if (!vid_cap_buf && !vbi_cap_buf) goto update_mv; + f_time = dev->cap_frame_period * dev->vid_cap_seq_count + + dev->cap_stream_start + dev->time_wrap_offset; +if (vid_cap_buf) {/* Fill buffer */ vivid_fillbuff (dev, vid_cap_buf);@@ -717,9 +723,13 @@ static void vivid_thread_vid_cap_tick(struct vivid_dev *dev, int dropped_bufs) VB2_BUF_STATE_ERROR : VB2_BUF_STATE_DONE);dprintk (dev,2 ,"vid_cap buffer %d done\n" , vid_cap_buf->vb.vb2_buf.index); + + vid_cap_buf->vb.vb2_buf.timestamp = f_time; }if (vbi_cap_buf) { +u64 vbi_period; +if (dev->stream_sliced_vbi_cap)vivid_sliced_vbi_cap_process (dev, vbi_cap_buf);else @@ -728,6 +738,10 @@ static void vivid_thread_vid_cap_tick(struct vivid_dev *dev, int dropped_bufs) VB2_BUF_STATE_ERROR : VB2_BUF_STATE_DONE);dprintk (dev,2 ,"vbi_cap %d done\n" , vbi_cap_buf->vb.vb2_buf.index); + +/* If capturing a VBI, offset by 0.05 */ + vbi_period = dev->cap_frame_period /100 *5 ; + vbi_cap_buf->vb.vb2_buf.timestamp = f_time + vbi_period; } dev->dqbuf_error = false;@@ -759,6 +773,8 @@ static int vivid_thread_vid_cap(void *data) dev->cap_seq_count =0 ; dev->cap_seq_resync = false; dev->jiffies_vid_cap = jiffies; + dev->cap_stream_start =ktime_get_ns (); +vivid_cap_update_frame_period (dev);for (;;) {try_to_freeze ();@@ -771,6 +787,9 @@ static int vivid_thread_vid_cap(void *data) dev->jiffies_vid_cap = cur_jiffies; dev->cap_seq_offset = dev->cap_seq_count +1 ; dev->cap_seq_count =0 ; + dev->cap_stream_start += dev->cap_frame_period * + dev->cap_seq_offset; +vivid_cap_update_frame_period (dev); dev->cap_seq_resync = false; } numerator = dev->timeperframe_vid_cap.numerator;drivers/media/platform/vivid/vivid-vbi-cap.c +0
-4@@ -95,8 +95,6 @@ void vivid_raw_vbi_cap_process(struct vivid_dev *dev, struct vivid_buffer *buf)if (!VIVID_INVALID_SIGNAL (dev->std_signal_mode))vivid_vbi_gen_raw (&dev->vbi_gen, &vbi, vbuf); - - buf->vb.vb2_buf.timestamp =ktime_get_ns () + dev->time_wrap_offset; }@@ -119,8 +117,6 @@ void vivid_sliced_vbi_cap_process(struct vivid_dev *dev,for (i =0 ; i <25 ; i++) vbuf[i] = dev->vbi_gen.data[i]; } - - buf->vb.vb2_buf.timestamp =ktime_get_ns () + dev->time_wrap_offset; } static int vbi_cap_queue_setup(struct vb2_queue *vq,