a29d9ea9da
to get the prototypes or macros are defined in it Signed-off-by: Xiang Xiao <xiaoxiang@xiaomi.com>
769 lines
22 KiB
C
769 lines
22 KiB
C
/****************************************************************************
|
|
* apps/examples/camera/camera_main.c
|
|
*
|
|
* Licensed to the Apache Software Foundation (ASF) under one or more
|
|
* contributor license agreements. See the NOTICE file distributed with
|
|
* this work for additional information regarding copyright ownership. The
|
|
* ASF licenses this file to you under the Apache License, Version 2.0 (the
|
|
* "License"); you may not use this file except in compliance with the
|
|
* License. You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
|
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
|
* License for the specific language governing permissions and limitations
|
|
* under the License.
|
|
*
|
|
****************************************************************************/
|
|
|
|
/****************************************************************************
|
|
* Included Files
|
|
****************************************************************************/
|
|
|
|
#include <nuttx/config.h>
|
|
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
#include <stdlib.h>
|
|
#include <errno.h>
|
|
#include <fcntl.h>
|
|
#include <sys/time.h>
|
|
#include <sys/ioctl.h>
|
|
#include <time.h>
|
|
#include <unistd.h>
|
|
|
|
#include <nuttx/video/video.h>
|
|
|
|
#include "camera_fileutil.h"
|
|
#include "camera_bkgd.h"
|
|
|
|
/****************************************************************************
|
|
* Pre-processor Definitions
|
|
****************************************************************************/
|
|
|
|
#define IMAGE_JPG_SIZE (512*1024) /* 512kB for FullHD Jpeg file. */
|
|
#define IMAGE_RGB_SIZE (320*240*2) /* QVGA RGB565 */
|
|
|
|
#define VIDEO_BUFNUM (3)
|
|
#define STILL_BUFNUM (1)
|
|
|
|
#define MAX_CAPTURE_NUM (100)
|
|
#define DEFAULT_CAPTURE_NUM (10)
|
|
|
|
#define START_CAPTURE_TIME (5) /* seconds */
|
|
#define KEEP_VIDEO_TIME (10) /* seconds */
|
|
|
|
#define APP_STATE_BEFORE_CAPTURE (0)
|
|
#define APP_STATE_UNDER_CAPTURE (1)
|
|
#define APP_STATE_AFTER_CAPTURE (2)
|
|
|
|
/****************************************************************************
|
|
* Private Types
|
|
****************************************************************************/
|
|
|
|
struct v_buffer
|
|
{
|
|
FAR 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,
|
|
FAR struct v_buffer **vbuf,
|
|
uint8_t buffernum, int buffersize);
|
|
static void free_buffer(FAR struct v_buffer *buffers, uint8_t bufnum);
|
|
static int parse_arguments(int argc, FAR char *argv[],
|
|
FAR int *capture_num,
|
|
FAR enum v4l2_buf_type *type);
|
|
static int get_camimage(int fd, FAR struct v4l2_buffer *v4l2_buf,
|
|
enum v4l2_buf_type buf_type);
|
|
static int release_camimage(int fd, FAR 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,
|
|
FAR 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_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, (uintptr_t)&fmt);
|
|
if (ret < 0)
|
|
{
|
|
printf("Failed to VIDIOC_S_FMT: errno = %d\n", errno);
|
|
return ret;
|
|
}
|
|
|
|
/* 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, (uintptr_t)&req);
|
|
if (ret < 0)
|
|
{
|
|
printf("Failed to VIDIOC_REQBUFS: 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--)
|
|
{
|
|
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 = (uintptr_t)(*vbuf)[cnt].start;
|
|
buf.length = (*vbuf)[cnt].length;
|
|
|
|
ret = ioctl(fd, VIDIOC_QBUF, (uintptr_t)&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, (uintptr_t)&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(FAR 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, FAR char *argv[],
|
|
FAR int *capture_num,
|
|
FAR 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, FAR 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, (uintptr_t)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, FAR struct v4l2_buffer *v4l2_buf)
|
|
{
|
|
int ret;
|
|
|
|
/* VIDIOC_QBUF sets buffer pointer into video driver again. */
|
|
|
|
ret = ioctl(fd, VIDIOC_QBUF, (uintptr_t)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;
|
|
}
|
|
|
|
/****************************************************************************
|
|
* Name: get_imgsensor_name()
|
|
*
|
|
* Description:
|
|
* Get image sensor driver name by querying device capabilities.
|
|
****************************************************************************/
|
|
|
|
static FAR const char *get_imgsensor_name(int fd)
|
|
{
|
|
static struct v4l2_capability cap;
|
|
|
|
ioctl(fd, VIDIOC_QUERYCAP, (uintptr_t)&cap);
|
|
|
|
return (FAR const char *)cap.driver;
|
|
}
|
|
|
|
/****************************************************************************
|
|
* 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;
|
|
FAR const char *save_dir;
|
|
FAR const char *sensor;
|
|
uint16_t w;
|
|
uint16_t h;
|
|
int is_eternal;
|
|
int app_state;
|
|
|
|
struct timeval start;
|
|
struct timeval now;
|
|
struct timeval delta;
|
|
struct timeval wait;
|
|
|
|
FAR struct v_buffer *buffers_video = NULL;
|
|
FAR 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 ===== */
|
|
|
|
/* Initialize NX graphics subsystem to use LCD */
|
|
|
|
#ifdef CONFIG_EXAMPLES_CAMERA_OUTPUT_LCD
|
|
ret = nximage_initialize();
|
|
if (ret < 0)
|
|
{
|
|
printf("camera_main: Failed to get NX handle: %d\n", errno);
|
|
return ERROR;
|
|
}
|
|
#endif
|
|
|
|
/* Select storage to save image files */
|
|
|
|
save_dir = futil_initialize();
|
|
|
|
/* Initialize video driver to create a device file */
|
|
|
|
ret = video_initialize("/dev/video");
|
|
if (ret != 0)
|
|
{
|
|
printf("ERROR: Failed to initialize video: errno = %d\n", errno);
|
|
goto exit_without_cleaning_videodriver;
|
|
}
|
|
|
|
/* 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 frame buffers for JPEG size (512KB).
|
|
* Set FULLHD size in ISX012 case, QUADVGA size in ISX019 case or other
|
|
* image sensors,
|
|
* Number of frame buffers is defined as STILL_BUFNUM(1).
|
|
* And all allocated memorys are VIDIOC_QBUFed.
|
|
*/
|
|
|
|
if (capture_num != 0)
|
|
{
|
|
/* Determine image size from connected image sensor name,
|
|
* because video driver does not support VIDIOC_ENUM_FRAMESIZES
|
|
* for now.
|
|
*/
|
|
|
|
sensor = get_imgsensor_name(v_fd);
|
|
if (strncmp(sensor, "ISX012", strlen("ISX012")) == 0)
|
|
{
|
|
w = VIDEO_HSIZE_FULLHD;
|
|
h = VIDEO_VSIZE_FULLHD;
|
|
}
|
|
else if (strncmp(sensor, "ISX019", strlen("ISX019")) == 0)
|
|
{
|
|
w = VIDEO_HSIZE_QUADVGA;
|
|
h = VIDEO_VSIZE_QUADVGA;
|
|
}
|
|
else
|
|
{
|
|
w = VIDEO_HSIZE_QUADVGA;
|
|
h = VIDEO_VSIZE_QUADVGA;
|
|
}
|
|
|
|
ret = camera_prepare(v_fd, V4L2_BUF_TYPE_STILL_CAPTURE,
|
|
V4L2_BUF_MODE_FIFO, V4L2_PIX_FMT_JPEG,
|
|
w, h,
|
|
&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 RGB565 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_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:
|
|
* This state waits 5 seconds (defined as START_CAPTURE_TIME)
|
|
* with displaying preview (VIDEO_CAPTURE stream image) on LCD.
|
|
* After 5 seconds, state will be changed to APP_STATE_UNDER_CAPTURE.
|
|
*
|
|
* APP_STATE_UNDER_CAPTURE:
|
|
* This state will start taking picture and store the image into files.
|
|
* Number of taking pictures is set capture_num valiable.
|
|
* It can be changed by command line argument.
|
|
* After finishing taking pictures, the state will be changed to
|
|
* APP_STATE_AFTER_CAPTURE.
|
|
*
|
|
* APP_STATE_AFTER_CAPTURE:
|
|
* This state waits 10 seconds (defined as KEEP_VIDEO_TIME)
|
|
* with displaying preview (VIDEO_CAPTURE stream image) on LCD.
|
|
* After 10 seconds, this application will be finished.
|
|
*
|
|
* Notice:
|
|
* If capture_num is set '0', state will stay APP_STATE_BEFORE_CAPTURE.
|
|
*/
|
|
|
|
app_state = APP_STATE_BEFORE_CAPTURE;
|
|
|
|
/* Show this application behavior. */
|
|
|
|
if (capture_num == 0)
|
|
{
|
|
is_eternal = 1;
|
|
printf("Start video this mode is eternal."
|
|
" (Non stop, non save files.)\n");
|
|
#ifndef CONFIG_EXAMPLES_CAMERA_OUTPUT_LCD
|
|
printf("This mode should be run with LCD display\n");
|
|
#endif
|
|
}
|
|
else
|
|
{
|
|
is_eternal = 0;
|
|
wait.tv_sec = START_CAPTURE_TIME;
|
|
wait.tv_usec = 0;
|
|
printf("Take %d pictures as %s file in %s after %d seconds.\n",
|
|
capture_num,
|
|
capture_type == V4L2_BUF_TYPE_STILL_CAPTURE ? "JPEG" : "RGB",
|
|
save_dir, START_CAPTURE_TIME);
|
|
printf(" After finishing taking pictures,"
|
|
" this app will be finished after %d seconds.\n",
|
|
KEEP_VIDEO_TIME);
|
|
}
|
|
|
|
gettimeofday(&start, NULL);
|
|
|
|
/* ===== Main Loop ===== */
|
|
|
|
while (1)
|
|
{
|
|
switch (app_state)
|
|
{
|
|
/* BEFORE_CAPTURE and AFTER_CAPTURE is waiting for expiring the
|
|
* time.
|
|
* In the meantime, Capturing VIDEO image to show pre-view on LCD.
|
|
*/
|
|
|
|
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((FAR 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);
|
|
timersub(&now, &start, &delta);
|
|
if (timercmp(&delta, &wait, >))
|
|
{
|
|
printf("Expire time is pasted. GoTo next state.\n");
|
|
if (app_state == APP_STATE_BEFORE_CAPTURE)
|
|
{
|
|
app_state = APP_STATE_UNDER_CAPTURE;
|
|
}
|
|
else
|
|
{
|
|
ret = OK;
|
|
goto exit_this_app;
|
|
}
|
|
}
|
|
}
|
|
|
|
break; /* Finish APP_STATE_BEFORE_CAPTURE or APP_STATE_AFTER_CAPTURE */
|
|
|
|
/* UNDER_CAPTURE is taking pictures until number of capture_num
|
|
* value.
|
|
* This state stays until finishing all pictures.
|
|
*/
|
|
|
|
case APP_STATE_UNDER_CAPTURE:
|
|
printf("Start capturing...\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(
|
|
(FAR uint8_t *)v4l2_buf.m.userptr,
|
|
(size_t)v4l2_buf.bytesused,
|
|
capture_type == V4L2_BUF_TYPE_VIDEO_CAPTURE ?
|
|
"RGB" : "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;
|
|
}
|
|
|
|
app_state = APP_STATE_AFTER_CAPTURE;
|
|
wait.tv_sec = KEEP_VIDEO_TIME;
|
|
wait.tv_usec = 0;
|
|
gettimeofday(&start, NULL);
|
|
printf("Finished capturing...\n");
|
|
break; /* Finish APP_STATE_UNDER_CAPTURE */
|
|
|
|
default:
|
|
printf("Unknown error is occurred.. state=%d\n", app_state);
|
|
goto exit_this_app;
|
|
break;
|
|
}
|
|
}
|
|
|
|
exit_this_app:
|
|
|
|
/* Close video device file makes dequeue all buffers */
|
|
|
|
close(v_fd);
|
|
|
|
free_buffer(buffers_video, VIDEO_BUFNUM);
|
|
free_buffer(buffers_still, STILL_BUFNUM);
|
|
|
|
exit_without_cleaning_buffer:
|
|
video_uninitialize();
|
|
|
|
exit_without_cleaning_videodriver:
|
|
#ifdef CONFIG_EXAMPLES_CAMERA_OUTPUT_LCD
|
|
nximage_finalize();
|
|
#endif
|
|
return ret;
|
|
}
|