From d2427718c9e91870ceddc032bcfce51def667596 Mon Sep 17 00:00:00 2001 From: Daniel Scally Date: Wed, 30 Nov 2022 13:31:09 +0000 Subject: lib/jpg-source: Constrain fps As written the fps output by the jpg-source is unconstrained; it will simply fill buffers as quickly as the USB subsysem can handle them. This is not particularly realistic and also means that the frame rates configured (and thus expected) by the host are not being adhered to. Use the new timer infrastructure to slow down the buffer fill operation such that the frame rates seen match those configured by the host. Reviewed-by: Kieran Bingham Signed-off-by: Daniel Scally --- lib/jpg-source.c | 48 +++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 43 insertions(+), 5 deletions(-) (limited to 'lib') diff --git a/lib/jpg-source.c b/lib/jpg-source.c index 0bbe26f..c95d76c 100644 --- a/lib/jpg-source.c +++ b/lib/jpg-source.c @@ -20,6 +20,7 @@ #include #include "events.h" +#include "timer.h" #include "tools.h" #include "v4l2.h" #include "jpg-source.h" @@ -30,6 +31,9 @@ struct jpg_source { unsigned int imgsize; void *imgdata; + + struct timer *timer; + bool streaming; }; #define to_jpg_source(s) container_of(s, struct jpg_source, src) @@ -41,6 +45,8 @@ static void jpg_source_destroy(struct video_source *s) if (src->imgdata) free(src->imgdata); + timer_destroy(src->timer); + free(src); } @@ -55,9 +61,12 @@ static int jpg_source_set_format(struct video_source *s __attribute__((unused)), return 0; } -static int jpg_source_set_frame_rate(struct video_source *s __attribute__((unused)), - unsigned int fps __attribute__((unused))) +static int jpg_source_set_frame_rate(struct video_source *s, unsigned int fps) { + struct jpg_source *src = to_jpg_source(s); + + timer_set_fps(src->timer, fps); + return 0; } @@ -66,14 +75,32 @@ static int jpg_source_free_buffers(struct video_source *s __attribute__((unused) return 0; } -static int jpg_source_stream_on(struct video_source *s __attribute__((unused))) +static int jpg_source_stream_on(struct video_source *s) { + struct jpg_source *src = to_jpg_source(s); + int ret; + + ret = timer_arm(src->timer); + if (ret) + return ret; + + src->streaming = true; return 0; } -static int jpg_source_stream_off(struct video_source *s __attribute__((unused))) +static int jpg_source_stream_off(struct video_source *s) { - return 0; + struct jpg_source *src = to_jpg_source(s); + int ret; + + /* + * No error check here, because we want to flag that streaming is over + * even if the timer is still running due to the failure. + */ + ret = timer_disarm(src->timer); + src->streaming = false; + + return ret; } static void jpg_source_fill_buffer(struct video_source *s, @@ -83,6 +110,13 @@ static void jpg_source_fill_buffer(struct video_source *s, memcpy(buf->mem, src->imgdata, src->imgsize); buf->bytesused = src->imgsize; + + /* + * Wait for the timer to elapse to ensure that our configured frame rate + * is adhered to. + */ + if (src->streaming) + timer_wait(src->timer); } static const struct video_source_ops jpg_source_ops = { @@ -136,6 +170,10 @@ struct video_source *jpg_video_source_create(const char *img_path) goto err_free_imgdata; } + src->timer = timer_new(); + if (!src->timer) + goto err_free_imgdata; + close(fd); return &src->src; -- cgit v1.2.3