From bb83c7135540d3391f4d0b46911c8aedbcd84313 Mon Sep 17 00:00:00 2001 From: Paul Elder Date: Tue, 22 Nov 2022 15:41:49 +0000 Subject: jpg-source: add jpg source class The jpg_source class is an implementation of the video_source class that streams a still jpg image as video. Reviewed-by: Kieran Bingham Signed-off-by: Paul Elder Signed-off-by: Daniel Scally Signed-off-by: Kieran Bingham --- include/uvcgadget/jpg-source.h | 20 ++++++ lib/jpg-source.c | 158 +++++++++++++++++++++++++++++++++++++++++ lib/meson.build | 1 + 3 files changed, 179 insertions(+) create mode 100644 include/uvcgadget/jpg-source.h create mode 100644 lib/jpg-source.c diff --git a/include/uvcgadget/jpg-source.h b/include/uvcgadget/jpg-source.h new file mode 100644 index 0000000..2c0b6ea --- /dev/null +++ b/include/uvcgadget/jpg-source.h @@ -0,0 +1,20 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * JPEG still image video source + * + * Copyright (C) 2018 Paul Elder + * + * Contact: Paul Elder + */ +#ifndef __JPG_VIDEO_SOURCE_H__ +#define __JPG_VIDEO_SOURCE_H__ + +#include "video-source.h" + +struct events; +struct video_source; + +struct video_source *jpg_video_source_create(const char *img_path); +void jpg_video_source_init(struct video_source *src, struct events *events); + +#endif /* __JPG_VIDEO_SOURCE_H__ */ diff --git a/lib/jpg-source.c b/lib/jpg-source.c new file mode 100644 index 0000000..0bbe26f --- /dev/null +++ b/lib/jpg-source.c @@ -0,0 +1,158 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * JPEG still image video source + * + * Copyright (C) 2018 Paul Elder + * + * Contact: Paul Elder + */ + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "events.h" +#include "tools.h" +#include "v4l2.h" +#include "jpg-source.h" +#include "video-buffers.h" + +struct jpg_source { + struct video_source src; + + unsigned int imgsize; + void *imgdata; +}; + +#define to_jpg_source(s) container_of(s, struct jpg_source, src) + +static void jpg_source_destroy(struct video_source *s) +{ + struct jpg_source *src = to_jpg_source(s); + + if (src->imgdata) + free(src->imgdata); + + free(src); +} + +static int jpg_source_set_format(struct video_source *s __attribute__((unused)), + struct v4l2_pix_format *fmt) +{ + if (fmt->pixelformat != v4l2_fourcc('M', 'J', 'P', 'G')) { + printf("jpg-source: unsupported fourcc\n"); + return -EINVAL; + } + + return 0; +} + +static int jpg_source_set_frame_rate(struct video_source *s __attribute__((unused)), + unsigned int fps __attribute__((unused))) +{ + return 0; +} + +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))) +{ + return 0; +} + +static int jpg_source_stream_off(struct video_source *s __attribute__((unused))) +{ + return 0; +} + +static void jpg_source_fill_buffer(struct video_source *s, + struct video_buffer *buf) +{ + struct jpg_source *src = to_jpg_source(s); + + memcpy(buf->mem, src->imgdata, src->imgsize); + buf->bytesused = src->imgsize; +} + +static const struct video_source_ops jpg_source_ops = { + .destroy = jpg_source_destroy, + .set_format = jpg_source_set_format, + .set_frame_rate = jpg_source_set_frame_rate, + .alloc_buffers = NULL, + .export_buffers = NULL, + .free_buffers = jpg_source_free_buffers, + .stream_on = jpg_source_stream_on, + .stream_off = jpg_source_stream_off, + .queue_buffer = NULL, + .fill_buffer = jpg_source_fill_buffer, +}; + +struct video_source *jpg_video_source_create(const char *img_path) +{ + struct jpg_source *src; + int fd = -1; + int ret; + + printf("using jpg video source\n"); + + if (img_path == NULL) + return NULL; + + src = malloc(sizeof *src); + if (!src) + return NULL; + + memset(src, 0, sizeof *src); + src->src.ops = &jpg_source_ops; + + fd = open(img_path, O_RDONLY); + if (fd == -1) { + printf("Unable to open MJPEG image '%s'\n", img_path); + goto err_free_src; + } + + src->imgsize = lseek(fd, 0, SEEK_END); + lseek(fd, 0, SEEK_SET); + src->imgdata = malloc(src->imgsize); + if (src->imgdata == NULL) { + printf("Unable to allocate memory for MJPEG image\n"); + goto err_close_fd; + } + + ret = read(fd, src->imgdata, src->imgsize); + if (ret < 0) { + fprintf(stderr, "error reading data from %s: %d\n", img_path, errno); + goto err_free_imgdata; + } + + close(fd); + + return &src->src; + +err_free_imgdata: + free(src->imgdata); +err_close_fd: + close(fd); +err_free_src: + free(src); + + return NULL; +} + +void jpg_video_source_init(struct video_source *s, struct events *events) +{ + struct jpg_source *src = to_jpg_source(s); + + src->src.events = events; +} diff --git a/lib/meson.build b/lib/meson.build index 2d9ad10..f6991d5 100644 --- a/lib/meson.build +++ b/lib/meson.build @@ -3,6 +3,7 @@ libuvcgadget_sources = files([ 'configfs.c', 'events.c', + 'jpg-source.c', 'stream.c', 'test-source.c', 'uvc.c', -- cgit v1.2.3