diff --git a/examples/camera/Kconfig b/examples/camera/Kconfig new file mode 100644 index 000000000..229643153 --- /dev/null +++ b/examples/camera/Kconfig @@ -0,0 +1,29 @@ +# +# For a description of the syntax of this configuration file, +# see the file kconfig-language.txt in the NuttX tools repository. +# + +config EXAMPLES_CAMERA + tristate "Camera example" + default n + ---help--- + Enable the camera example + +if EXAMPLES_CAMERA + +config EXAMPLES_CAMERA_PROGNAME + string "Program name" + default "camera" + ---help--- + This is the name of the program that will be use when the NSH ELF + program is installed. + +config EXAMPLES_CAMERA_PRIORITY + int "Camera task priority" + default 100 + +config EXAMPLES_CAMERA_STACKSIZE + int "Camera stack size" + default 2048 + +endif diff --git a/examples/camera/Make.defs b/examples/camera/Make.defs new file mode 100644 index 000000000..94ad598d2 --- /dev/null +++ b/examples/camera/Make.defs @@ -0,0 +1,38 @@ +############################################################################ +# examples/camera/Make.defs +# +# Copyright 2018 Sony Semiconductor Solutions Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# 3. Neither the name of Sony Semiconductor Solutions Corporation nor +# the names of its contributors may be used to endorse or promote +# products derived from this software without specific prior written +# permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED +# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# +############################################################################ + +ifneq ($(CONFIG_EXAMPLES_CAMERA),) +CONFIGURED_APPS += $(APPDIR)/examples/camera +endif diff --git a/examples/camera/Makefile b/examples/camera/Makefile new file mode 100644 index 000000000..a0edeebe9 --- /dev/null +++ b/examples/camera/Makefile @@ -0,0 +1,50 @@ +############################################################################ +# examples/camera/Makefile +# +# Copyright 2018, 2020 Sony Semiconductor Solutions Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# 3. Neither the name of Sony Semiconductor Solutions Corporation nor +# the names of its contributors may be used to endorse or promote +# products derived from this software without specific prior written +# permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED +# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# +############################################################################ + +include $(TOPDIR)/Make.defs + +# camera built-in application info + +PROGNAME = $(CONFIG_EXAMPLES_CAMERA_PROGNAME) +PRIORITY = $(CONFIG_EXAMPLES_CAMERA_PRIORITY) +STACKSIZE = $(CONFIG_EXAMPLES_CAMERA_STACKSIZE) +MODULE = $(CONFIG_EXAMPLES_CAMERA) + +# camera Example + +CSRCS += camera_fileutil.c +MAINSRC = camera_main.c + +include $(APPDIR)/Application.mk diff --git a/examples/camera/README.txt b/examples/camera/README.txt new file mode 100644 index 000000000..a2d123522 --- /dev/null +++ b/examples/camera/README.txt @@ -0,0 +1,39 @@ +examples/camera +^^^^^^^^^^^^^^^ + + This sample is implemented as 'camera' command on NuttX Shell. + The synopsys of the command is as below. + + nsh> camera ([-jpg]) ([capture num]) + + -jpg : this option is set for storing JPEG file into a strage. + : If this option isn't set capturing raw YUV422 data in a file. + : raw YUV422 is default. + + capture num : this option instructs number of taking pictures. + : 10 is default. + Storage will be selected automatically based on the available storage option. + + Execution example: + + nsh> camera + nximage_listener: Connected + nximage_initialize: Screen resolution (320,240) + Take 10 pictures as YUV file in /mnt/sd0 after 5000 mili-seconds. + After finishing taking pictures, this app will be finished after 10000 mili-seconds. + Expier time is pasted. + Start captureing... + FILENAME:/mnt/sd0/VIDEO001.YUV + FILENAME:/mnt/sd0/VIDEO002.YUV + FILENAME:/mnt/sd0/VIDEO003.YUV + FILENAME:/mnt/sd0/VIDEO004.YUV + FILENAME:/mnt/sd0/VIDEO005.YUV + FILENAME:/mnt/sd0/VIDEO006.YUV + FILENAME:/mnt/sd0/VIDEO007.YUV + FILENAME:/mnt/sd0/VIDEO008.YUV + FILENAME:/mnt/sd0/VIDEO009.YUV + FILENAME:/mnt/sd0/VIDEO010.YUV + Finished captureing... + Expier time is pasted. + nximage_listener: Lost server connection: 117 + diff --git a/examples/camera/camera_fileutil.c b/examples/camera/camera_fileutil.c new file mode 100644 index 000000000..0698e2dbf --- /dev/null +++ b/examples/camera/camera_fileutil.c @@ -0,0 +1,137 @@ +/**************************************************************************** + * camera/camera_fileutil.c + * + * Copyright 2020 Sony Semiconductor Solutions Corporation + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name of Sony Semiconductor Solutions Corporation nor + * the names of its contributors may be used to endorse or promote + * products derived from this software without specific prior written + * permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include +#include +#include +#include + +#include "camera_fileutil.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#define IMAGE_FILENAME_LEN (32) + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +static const char *save_dir; + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: futil_initialize() + * + * Description: + * Choose strage to write a file. + ****************************************************************************/ + +const char *futil_initialize(void) +{ + int ret; + struct stat stat_buf; + + /* In SD card is available, use SD card. + * Otherwise, use SPI flash. + */ + + ret = stat("/mnt/sd0", &stat_buf); + if (ret < 0) + { + save_dir = "/mnt/spif"; + } + else + { + save_dir = "/mnt/sd0"; + } + + return save_dir; +} + +/**************************************************************************** + * Name: futil_writeimage() + * + * Description: + * Write a image file to selected storage. + ****************************************************************************/ + +int futil_writeimage(uint8_t *data, size_t len, const char *fsuffix) +{ + static char s_fname[IMAGE_FILENAME_LEN]; + static int s_framecount = 0; + + FILE *fp; + + s_framecount++; + if (s_framecount >= 1000) + { + s_framecount = 1; + } + + memset(s_fname, 0, sizeof(s_fname)); + + snprintf(s_fname, + IMAGE_FILENAME_LEN, + "%s/VIDEO%03d.%s", + save_dir, s_framecount, fsuffix); + + printf("FILENAME:%s\n", s_fname); + + fp = fopen(s_fname, "wb"); + if (NULL == fp) + { + printf("fopen error : %d\n", errno); + return -1; + } + + if (len != fwrite(data, 1, len, fp)) + { + printf("fwrite error : %d\n", errno); + } + + fclose(fp); + return 0; +} + diff --git a/examples/camera/camera_fileutil.h b/examples/camera/camera_fileutil.h new file mode 100644 index 000000000..8dd029323 --- /dev/null +++ b/examples/camera/camera_fileutil.h @@ -0,0 +1,59 @@ +/**************************************************************************** + * camera/camera_fileutil.h + * + * Copyright 2020 Sony Semiconductor Solutions Corporation + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name of Sony Semiconductor Solutions Corporation nor + * the names of its contributors may be used to endorse or promote + * products derived from this software without specific prior written + * permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +#ifndef __EXAMPLES_CAMERA_CAMERA_FILEUTIL_H__ +#define __EXAMPLES_CAMERA_CAMERA_FILEUTIL_H__ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +/* Initialize file util of camera example */ + +const char *futil_initialize(void); + +/* Write an image file */ + +int futil_writeimage(uint8_t *data, size_t len, const char *fsuffix); + +#endif /* __EXAMPLES_CAMERA_CAMERA_FILEUTIL_H__ */ + diff --git a/examples/camera/camera_main.c b/examples/camera/camera_main.c new file mode 100644 index 000000000..caa6622f9 --- /dev/null +++ b/examples/camera/camera_main.c @@ -0,0 +1,607 @@ +/**************************************************************************** + * camera/camera_main.c + * + * Copyright 2018, 2020 Sony Semiconductor Solutions Corporation + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name of Sony Semiconductor Solutions Corporation nor + * the names of its contributors may be used to endorse or promote + * products derived from this software without specific prior written + * permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "camera_fileutil.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#define IMAGE_JPG_SIZE (512*1024) /* 512kB for FullHD Jpeg file. */ +#define IMAGE_YUV_SIZE (320*240*2) /* QVGA YUV422 */ + +#define VIDEO_BUFNUM (3) +#define STILL_BUFNUM (1) + +#define MAX_CAPTURE_NUM (100) +#define DEFAULT_CAPTURE_NUM (10) + +#define START_CAPTURE_TIME (5000) /* mili-seconds */ +#define KEEP_VIDEO_TIME (10000) /* mili-seconds */ + +#define RESET_INITIAL_TIME(t) gettimeofday(&(t), NULL) +#define UPDATE_DIFF_TIME(d, then, now) \ + { \ + gettimeofday(&(now), NULL); \ + (d) = ((((now).tv_sec - (then).tv_sec) * 1000) \ + + (((now).tv_usec - (then).tv_usec) / 1000)); \ + } + +#define APP_STATE_BEFORE_CAPTURE (0) +#define APP_STATE_UNDER_CAPTURE (1) +#define APP_STATE_AFTER_CAPTURE (2) + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +struct v_buffer +{ + uint32_t *start; + uint32_t length; +}; + +typedef struct v_buffer v_buffer_t; + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +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); +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); +static int get_camimage(int fd, struct v4l2_buffer *v4l2_buf, + enum v4l2_buf_type buf_type); +static int release_camimage(int fd, struct v4l2_buffer *v4l2_buf); +static int start_stillcapture(int v_fd, enum v4l2_buf_type capture_type); +static int stop_stillcapture(int v_fd, enum v4l2_buf_type capture_type); + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: camera_prepare() + * + * Description: + * Allocate frame buffer for camera and Queue the allocated buffer + * into video driver. + ****************************************************************************/ + +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) +{ + int ret; + int cnt; + struct v4l2_format fmt = + { + 0 + }; + + struct v4l2_requestbuffers req = + { + 0 + }; + + struct v4l2_buffer buf = + { + 0 + }; + + /* VIDIOC_REQBUFS initiate user pointer I/O */ + + req.type = type; + req.memory = V4L2_MEMORY_USERPTR; + req.count = buffernum; + req.mode = buf_mode; + + ret = ioctl(fd, VIDIOC_REQBUFS, (unsigned long)&req); + if (ret < 0) + { + printf("Failed to VIDIOC_REQBUFS: errno = %d\n", errno); + return ret; + } + + /* VIDIOC_S_FMT set format */ + + fmt.type = type; + fmt.fmt.pix.width = hsize; + fmt.fmt.pix.height = vsize; + 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; + } + + /* Prepare video memory to store images */ + + *vbuf = malloc(sizeof(v_buffer_t) * buffernum); + + if (!(*vbuf)) + { + printf("Out of memory for array of v_buffer_t[%d]\n", buffernum); + return ERROR; + } + + for (cnt = 0; cnt < buffernum; cnt++) + { + (*vbuf)[cnt].length = buffersize; + + /* Note: + * VIDIOC_QBUF set buffer pointer. + * Buffer pointer must be 32bytes aligned. + */ + + (*vbuf)[cnt].start = memalign(32, buffersize); + if (!(*vbuf)[cnt].start) + { + printf("Out of memory for image buffer of %d/%d\n", + cnt, buffernum); + + /* Release allocated memory. */ + + while (cnt) + { + cnt--; + free((*vbuf)[cnt].start); + } + + free(*vbuf); + *vbuf = NULL; + return ERROR; + } + } + + /* VIDIOC_QBUF enqueue buffer */ + + for (cnt = 0; cnt < buffernum; cnt++) + { + memset(&buf, 0, sizeof(v4l2_buffer_t)); + buf.type = type; + buf.memory = V4L2_MEMORY_USERPTR; + buf.index = cnt; + buf.m.userptr = (unsigned long)(*vbuf)[cnt].start; + buf.length = (*vbuf)[cnt].length; + + ret = ioctl(fd, VIDIOC_QBUF, (unsigned long)&buf); + if (ret) + { + printf("Fail QBUF %d\n", errno); + free_buffer(*vbuf, buffernum); + *vbuf = NULL; + return ERROR; + } + } + + /* VIDIOC_STREAMON start stream */ + + ret = ioctl(fd, VIDIOC_STREAMON, (unsigned long)&type); + if (ret < 0) + { + printf("Failed to VIDIOC_STREAMON: errno = %d\n", errno); + free_buffer(*vbuf, buffernum); + *vbuf = NULL; + return ret; + } + + return OK; +} + +/**************************************************************************** + * Name: free_buffer() + * + * Description: + * All free allocated memory of v_buffer. + ****************************************************************************/ + +static void free_buffer(struct v_buffer *buffers, uint8_t bufnum) +{ + uint8_t cnt; + if (buffers) + { + for (cnt = 0; cnt < bufnum; cnt++) + { + if (buffers[cnt].start) + { + free(buffers[cnt].start); + } + } + + free(buffers); + } +} + +/**************************************************************************** + * Name: parse_argument() + * + * Description: + * Parse and decode commandline arguments. + ****************************************************************************/ + +static int parse_arguments(int argc, char *argv[], + int *capture_num, enum v4l2_buf_type *type) +{ + if (argc == 1) + { + *capture_num = DEFAULT_CAPTURE_NUM; + *type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + } + else if (argc == 2) + { + if (strncmp(argv[1], "-jpg", 5) == 0) + { + *capture_num = DEFAULT_CAPTURE_NUM; + *type = V4L2_BUF_TYPE_STILL_CAPTURE; + } + else + { + *capture_num = atoi(argv[1]); + if ((*capture_num < 0) || (*capture_num > MAX_CAPTURE_NUM)) + { + printf("Invalid capture num(%d). must be >=0 and <=%d\n", + *capture_num, MAX_CAPTURE_NUM); + return ERROR; + } + + *type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + } + } + else if (argc == 3) + { + if (strncmp(argv[1], "-jpg", 5) == 0) + { + *capture_num = atoi(argv[2]); + if ((*capture_num < 0) || (*capture_num > MAX_CAPTURE_NUM)) + { + printf("Invalid capture num(%d). must be >=0 and <=%d\n", + *capture_num, MAX_CAPTURE_NUM); + return ERROR; + } + + *type = V4L2_BUF_TYPE_STILL_CAPTURE; + } + else + { + printf("Invalid argument 1 : %s\n", argv[1]); + return ERROR; + } + } + else + { + printf("Too many arguments\n"); + return ERROR; + } + + return OK; +} + +/**************************************************************************** + * Name: get_camimage() + * + * Description: + * DQBUF camera frame buffer from video driver with taken picture data. + ****************************************************************************/ + +static int get_camimage(int fd, struct v4l2_buffer *v4l2_buf, + enum v4l2_buf_type buf_type) +{ + int ret; + + /* VIDIOC_DQBUF acquires captured data. */ + + memset(v4l2_buf, 0, sizeof(v4l2_buffer_t)); + v4l2_buf->type = buf_type; + v4l2_buf->memory = V4L2_MEMORY_USERPTR; + + ret = ioctl(fd, VIDIOC_DQBUF, (unsigned long)v4l2_buf); + if (ret) + { + printf("Fail DQBUF %d\n", errno); + return ERROR; + } + + return OK; +} + +/**************************************************************************** + * Name: release_camimage() + * + * Description: + * Re-QBUF to set used frame buffer into video driver. + ****************************************************************************/ + +static int release_camimage(int fd, struct v4l2_buffer *v4l2_buf) +{ + int ret; + + /* VIDIOC_QBUF sets buffer pointer into video driver again. */ + + ret = ioctl(fd, VIDIOC_QBUF, (unsigned long)v4l2_buf); + if (ret) + { + printf("Fail QBUF %d\n", errno); + return ERROR; + } + + return OK; +} + +/**************************************************************************** + * Name: start_stillcapture() + * + * Description: + * Start STILL capture stream by TAKEPICT_START if buf_type is + * STILL_CAPTURE. + ****************************************************************************/ + +static int start_stillcapture(int v_fd, enum v4l2_buf_type capture_type) +{ + int ret; + + if (capture_type == V4L2_BUF_TYPE_STILL_CAPTURE) + { + ret = ioctl(v_fd, VIDIOC_TAKEPICT_START, 0); + if (ret < 0) + { + printf("Failed to start taking picture\n"); + return ERROR; + } + } + + return OK; +} + +/**************************************************************************** + * Name: stop_stillcapture() + * + * Description: + * Stop STILL capture stream by TAKEPICT_STOP if buf_type is STILL_CAPTURE. + ****************************************************************************/ + +static int stop_stillcapture(int v_fd, enum v4l2_buf_type capture_type) +{ + int ret; + + if (capture_type == V4L2_BUF_TYPE_STILL_CAPTURE) + { + ret = ioctl(v_fd, VIDIOC_TAKEPICT_STOP, false); + if (ret < 0) + { + printf("Failed to stop taking picture\n"); + return ERROR; + } + } + + return OK; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: main() + * + * Description: + * main routine of this example. + ****************************************************************************/ + +int main(int argc, FAR char *argv[]) +{ + int ret; + int v_fd; + int capture_num = DEFAULT_CAPTURE_NUM; + enum v4l2_buf_type capture_type = V4L2_BUF_TYPE_STILL_CAPTURE; + struct v4l2_buffer v4l2_buf; + const char *save_dir; + + struct timeval then; + + struct v_buffer *buffers_video = NULL; + struct v_buffer *buffers_still = NULL; + + /* ===== Parse and Check arguments ===== */ + + ret = parse_arguments(argc, argv, &capture_num, &capture_type); + if (ret != OK) + { + printf("usage: %s ([-jpg]) ([capture num])\n", argv[0]); + return ERROR; + } + + /* ===== Initialization Code ===== */ + + /* Select storage to save image files */ + + save_dir = futil_initialize(); + + /* Open the device file. */ + + v_fd = open("/dev/video", 0); + if (v_fd < 0) + { + printf("ERROR: Failed to open video.errno = %d\n", errno); + ret = ERROR; + goto exit_without_cleaning_buffer; + } + + /* Prepare for STILL_CAPTURE stream. + * + * The video buffer mode is V4L2_BUF_MODE_FIFO mode. + * In this FIFO mode, if all VIDIOC_QBUFed frame buffers are captured image + * and no additional frame buffers are VIDIOC_QBUFed, the capture stops and + * waits for new VIDIOC_QBUFed frame buffer. + * And when new VIDIOC_QBUF is executed, the capturing is resumed. + * + * Allocate freame buffers for FullHD JPEG size (512KB). + * Number of frame buffers is defined as STILL_BUFNUM(1). + * And all allocated memorys are VIDIOC_QBUFed. + */ + + 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); + if (ret != OK) + { + goto exit_this_app; + } + + /* Prepare for VIDEO_CAPTURE stream. + * + * The video buffer mode is V4L2_BUF_MODE_RING mode. + * In this RING mode, if all VIDIOC_QBUFed frame buffers are captured image + * and no additional frame buffers are VIDIOC_QBUFed, the capture continues + * as the oldest image in the V4L2_BUF_QBUFed frame buffer is reused in + * order from the captured frame buffer and a new camera image is + * recaptured. + * + * Allocate freame buffers for QVGA YUV422 size (320x240x2=150KB). + * Number of frame buffers is defined as VIDEO_BUFNUM(3). + * And all allocated memorys are VIDIOC_QBUFed. + */ + + ret = camera_prepare(v_fd, V4L2_BUF_TYPE_VIDEO_CAPTURE, + V4L2_BUF_MODE_RING, V4L2_PIX_FMT_UYVY, + VIDEO_HSIZE_QVGA, VIDEO_VSIZE_QVGA, + &buffers_video, VIDEO_BUFNUM, IMAGE_YUV_SIZE); + if (ret != OK) + { + goto exit_this_app; + } + + printf("Take %d pictures as %s file in %s after %d mili-seconds.\n", + capture_num, + (capture_type == V4L2_BUF_TYPE_STILL_CAPTURE) ? "JPEG" : "YUV", + save_dir, START_CAPTURE_TIME); + printf(" After taking pictures, the app will be exit after %d ms.\n", + KEEP_VIDEO_TIME); + + RESET_INITIAL_TIME(then); + + /* ===== Main Loop ===== */ + + while (1) + { + printf("Start captureing...\n"); + ret = start_stillcapture(v_fd, capture_type); + if (ret != OK) + { + goto exit_this_app; + } + + while (capture_num) + { + ret = get_camimage(v_fd, &v4l2_buf, capture_type); + if (ret != OK) + { + goto exit_this_app; + } + + futil_writeimage((uint8_t *)v4l2_buf.m.userptr, + (size_t)v4l2_buf.bytesused, + (capture_type == V4L2_BUF_TYPE_VIDEO_CAPTURE) ? "YUV" : "JPG"); + + ret = release_camimage(v_fd, &v4l2_buf); + if (ret != OK) + { + goto exit_this_app; + } + + capture_num--; + } + + ret = stop_stillcapture(v_fd, capture_type); + if (ret != OK) + { + goto exit_this_app; + } + + RESET_INITIAL_TIME(then); + printf("Finished captureing...\n"); + } + +exit_this_app: + + /* Close video device file makes dequqe all buffers */ + + close(v_fd); + + free_buffer(buffers_video, VIDEO_BUFNUM); + free_buffer(buffers_still, STILL_BUFNUM); + +exit_without_cleaning_buffer: + + video_uninitialize(); + + return ret; +}