Upcoming maintenance
Dear Customers and Partners.
This website will be undergoing scheduled maintenance on June 14, 2023. Please be aware there may be disruption to the developer portal website and associated services during the scheduled maintenance period.
This upgrade is essential to ensure the continued performance, reliability, and security of Developer World.
We apologize for any inconvenience.
Solved How to use V4L2_PIX_FMT_JPEG_WITH_SUBIMG camera format
-
Hi, experts! I want to use subimage format -V4L2_PIX_FMT_JPEG_WITH_SUBIMG. How to get image data of a frame both with JPEG format and with YUV422 format? https://developer.sony.com/develop/spresense/docs/sdk_developer_guide_en.html#_isx012_proprietary_specifications
I don't have subimg_pixelformat = V4L2_PIX_FMT_UYVY field in my format structure.Regards,
Yury -
Hi @yuraspl
Please follow these steps:
Save the code below as
apps.patch
under `spresense/sdk/apps/:diff --git a/examples/camera/camera_main.c b/examples/camera/camera_main.c index 288f6170c..0d48596b3 100644 --- a/examples/camera/camera_main.c +++ b/examples/camera/camera_main.c @@ -83,7 +83,9 @@ static int camera_prepare(int fd, enum v4l2_buf_type type, uint32_t buf_mode, uint32_t pixformat, uint16_t hsize, uint16_t vsize, struct v_buffer **vbuf, - uint8_t buffernum, int buffersize); + uint8_t buffernum, int buffersize, + uint16_t sub_hsize, uint16_t sub_vsize, + uint32_t sub_pixformat); static void free_buffer(struct v_buffer *buffers, uint8_t bufnum); static int parse_arguments(int argc, char *argv[], int *capture_num, enum v4l2_buf_type *type); @@ -117,7 +119,9 @@ static int camera_prepare(int fd, enum v4l2_buf_type type, uint32_t buf_mode, uint32_t pixformat, uint16_t hsize, uint16_t vsize, struct v_buffer **vbuf, - uint8_t buffernum, int buffersize) + uint8_t buffernum, int buffersize, + uint16_t sub_hsize, uint16_t sub_vsize, + uint32_t sub_pixformat) { int ret; int cnt; @@ -158,6 +162,18 @@ static int camera_prepare(int fd, enum v4l2_buf_type type, fmt.fmt.pix.field = V4L2_FIELD_ANY; fmt.fmt.pix.pixelformat = pixformat; + ret = ioctl(fd, VIDIOC_S_FMT, (unsigned long)&fmt); + if (ret < 0) + { + printf("Failed to VIDIOC_S_FMT: errno = %d\n", errno); + return ret; + } + + fmt.type = type; + fmt.fmt.pix.width = sub_hsize; + fmt.fmt.pix.height = sub_vsize; + fmt.fmt.pix.pixelformat = sub_pixformat; + ret = ioctl(fd, VIDIOC_S_FMT, (unsigned long)&fmt); if (ret < 0) { @@ -518,9 +534,11 @@ int main(int argc, FAR char *argv[]) if (capture_num != 0) { ret = camera_prepare(v_fd, V4L2_BUF_TYPE_STILL_CAPTURE, - V4L2_BUF_MODE_FIFO, V4L2_PIX_FMT_JPEG, - VIDEO_HSIZE_FULLHD, VIDEO_VSIZE_FULLHD, - &buffers_still, STILL_BUFNUM, IMAGE_JPG_SIZE); + V4L2_BUF_MODE_FIFO, V4L2_PIX_FMT_JPEG_WITH_SUBIMG, + VIDEO_HSIZE_VGA, VIDEO_VSIZE_VGA, + &buffers_still, STILL_BUFNUM, IMAGE_JPG_SIZE + IMAGE_RGB_SIZE, + VIDEO_HSIZE_QVGA, VIDEO_VSIZE_QVGA, + V4L2_PIX_FMT_SUBIMG_UYVY); if (ret != OK) { goto exit_this_app; @@ -541,15 +559,6 @@ int main(int argc, FAR char *argv[]) * And all allocated memorys are VIDIOC_QBUFed. */ - ret = camera_prepare(v_fd, V4L2_BUF_TYPE_VIDEO_CAPTURE, - V4L2_BUF_MODE_RING, V4L2_PIX_FMT_RGB565, - VIDEO_HSIZE_QVGA, VIDEO_VSIZE_QVGA, - &buffers_video, VIDEO_BUFNUM, IMAGE_RGB_SIZE); - if (ret != OK) - { - goto exit_this_app; - } - /* This application has 3 states. * * APP_STATE_BEFORE_CAPTURE: @@ -615,23 +624,6 @@ int main(int argc, FAR char *argv[]) case APP_STATE_BEFORE_CAPTURE: case APP_STATE_AFTER_CAPTURE: - ret = get_camimage(v_fd, &v4l2_buf, V4L2_BUF_TYPE_VIDEO_CAPTURE); - if (ret != OK) - { - goto exit_this_app; - } - -#ifdef CONFIG_EXAMPLES_CAMERA_OUTPUT_LCD - nximage_draw((void *)v4l2_buf.m.userptr, - VIDEO_HSIZE_QVGA, VIDEO_VSIZE_QVGA); -#endif - - ret = release_camimage(v_fd, &v4l2_buf); - if (ret != OK) - { - goto exit_this_app; - } - if (!is_eternal) { gettimeofday(&now, NULL); @@ -676,9 +668,13 @@ int main(int argc, FAR char *argv[]) futil_writeimage( (uint8_t *)v4l2_buf.m.userptr, + (size_t)IMAGE_RGB_SIZE, + "UYVY"); + + futil_writeimage( + (uint8_t *)v4l2_buf.m.userptr + IMAGE_RGB_SIZE, (size_t)v4l2_buf.bytesused, - (capture_type == V4L2_BUF_TYPE_VIDEO_CAPTURE) ? - "RGB" : "JPG"); + "JPG"); ret = release_camimage(v_fd, &v4l2_buf); if (ret != OK) @@ -715,7 +711,6 @@ exit_this_app: close(v_fd); - free_buffer(buffers_video, VIDEO_BUFNUM); free_buffer(buffers_still, STILL_BUFNUM); exit_without_cleaning_buffer:
Run the commands:
$ cd spresense/sdk/apps $ git apply apps.patch $ cd .. $ ./tools/config.py examples/camera $ make $ ./tools/flash.sh nuttx.spk
In serial terminal, run
camera -jpg
:nsh> camera -jpg
The application is ready to run, but unfortunately there is a bug in SDK 2.4.0 (it will be fixed in the next release). You have two options. The first is to use a version other than 2.4.0, for example: 2.3.1. The second option is to apply a small patch. The instructions are below:
Save the code below as
nuttx.patch
under `spresense/nuttx/:diff --git a/drivers/video/video.c b/drivers/video/video.c index be0cb1656b..4b0ca38117 100644 --- a/drivers/video/video.c +++ b/drivers/video/video.c @@ -626,16 +626,18 @@ static void get_clipped_format(uint8_t nr_fmt, &fmt[VIDEO_FMT_SUB], sizeof(video_format_t)); - c_fmt[VIDEO_FMT_SUB].width *= clip->width; - c_fmt[VIDEO_FMT_SUB].width /= fmt[VIDEO_FMT_MAIN].width; + c_fmt[VIDEO_FMT_SUB].width + = (uint32_t)c_fmt[VIDEO_FMT_SUB].width + * clip->width / fmt[VIDEO_FMT_MAIN].width; - c_fmt[VIDEO_FMT_SUB].height *= clip->height; - c_fmt[VIDEO_FMT_SUB].height /= fmt[VIDEO_FMT_MAIN].height; + c_fmt[VIDEO_FMT_SUB].height + = (uint32_t)c_fmt[VIDEO_FMT_SUB].height + * clip->height / fmt[VIDEO_FMT_MAIN].height; } } else { - memcpy(c_fmt, fmt, sizeof(video_format_t)); + memcpy(c_fmt, fmt, nr_fmt * sizeof(video_format_t)); } }
Run the commands:
$ cd spresense/nuttx $ git apply nuttx.patch $ cd ../sdk $ ./tools/config.py examples/camera $ make $ ./tools/flash.sh nuttx.spk
Best Regards,
Kamil Tomaszewski -
Thank you so much @KamilTomaszewski, your example worked & it helped me a lot.
-
-