drivers/video: Support clip
Support clip by ioctl(VIDIOC_S_SELECTION) and ioctl(VIDIOC_G_SELECTION).
This commit is contained in:
parent
b45489753a
commit
9c57850466
@ -119,6 +119,7 @@ struct video_type_inf_s
|
||||
video_wait_capture_t wait_capture;
|
||||
uint8_t nr_fmt;
|
||||
video_format_t fmt[MAX_VIDEO_FMT];
|
||||
struct v4l2_rect clip;
|
||||
struct v4l2_fract frame_interval;
|
||||
video_framebuff_t bufinf;
|
||||
};
|
||||
@ -215,6 +216,10 @@ static int save_scene_param(enum v4l2_scene_mode mode,
|
||||
uint32_t id,
|
||||
struct v4l2_ext_control *control);
|
||||
static int video_complete_capture(uint8_t err_code, uint32_t datasize);
|
||||
static int validate_frame_setting(enum v4l2_buf_type type,
|
||||
uint8_t nr_fmt,
|
||||
FAR video_format_t *vfmt,
|
||||
FAR struct v4l2_fract *interval);
|
||||
|
||||
/* internal function for each cmds of ioctl */
|
||||
|
||||
@ -579,12 +584,69 @@ static void convert_to_imgsensorinterval(FAR struct v4l2_fract *video,
|
||||
sensor->denominator = video->denominator;
|
||||
}
|
||||
|
||||
static bool is_clipped(FAR struct v4l2_rect *clip)
|
||||
{
|
||||
bool ret = false;
|
||||
|
||||
if (clip)
|
||||
{
|
||||
if ((clip->left != 0) ||
|
||||
(clip->top != 0) ||
|
||||
(clip->width != 0) ||
|
||||
(clip->height != 0))
|
||||
{
|
||||
ret = true;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void get_clipped_format(uint8_t nr_fmt,
|
||||
FAR video_format_t *fmt,
|
||||
FAR struct v4l2_rect *clip,
|
||||
FAR video_format_t *c_fmt)
|
||||
{
|
||||
DEBUGASSERT(fmt && c_fmt);
|
||||
|
||||
if (is_clipped(clip))
|
||||
{
|
||||
c_fmt[VIDEO_FMT_MAIN].width = clip->width;
|
||||
c_fmt[VIDEO_FMT_MAIN].height = clip->height;
|
||||
c_fmt[VIDEO_FMT_MAIN].pixelformat
|
||||
= fmt[VIDEO_FMT_MAIN].pixelformat;
|
||||
|
||||
if (nr_fmt > 1)
|
||||
{
|
||||
/* clipped size of thumbnail is
|
||||
* small as ratio of main size and thumbnal size.
|
||||
*/
|
||||
|
||||
memcpy(&c_fmt[VIDEO_FMT_SUB],
|
||||
&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].height *= clip->height;
|
||||
c_fmt[VIDEO_FMT_SUB].height /= fmt[VIDEO_FMT_MAIN].height;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
memcpy(c_fmt, fmt, sizeof(video_format_t));
|
||||
}
|
||||
}
|
||||
|
||||
static int start_capture(enum v4l2_buf_type type,
|
||||
uint8_t nr_fmt,
|
||||
FAR video_format_t *fmt,
|
||||
FAR struct v4l2_rect *clip,
|
||||
FAR struct v4l2_fract *interval,
|
||||
uint32_t bufaddr, uint32_t bufsize)
|
||||
{
|
||||
video_format_t c_fmt[MAX_VIDEO_FMT];
|
||||
imgdata_format_t df[MAX_VIDEO_FMT];
|
||||
imgsensor_format_t sf[MAX_VIDEO_FMT];
|
||||
imgdata_interval_t di;
|
||||
@ -599,8 +661,10 @@ static int start_capture(enum v4l2_buf_type type,
|
||||
return -ENOTTY;
|
||||
}
|
||||
|
||||
convert_to_imgdatafmt(&fmt[VIDEO_FMT_MAIN], &df[IMGDATA_FMT_MAIN]);
|
||||
convert_to_imgdatafmt(&fmt[VIDEO_FMT_SUB], &df[IMGDATA_FMT_SUB]);
|
||||
get_clipped_format(nr_fmt, fmt, clip, c_fmt);
|
||||
|
||||
convert_to_imgdatafmt(&c_fmt[VIDEO_FMT_MAIN], &df[IMGDATA_FMT_MAIN]);
|
||||
convert_to_imgdatafmt(&c_fmt[VIDEO_FMT_SUB], &df[IMGDATA_FMT_SUB]);
|
||||
convert_to_imgdatainterval(interval, &di);
|
||||
convert_to_imgsensorfmt(&fmt[VIDEO_FMT_MAIN], &sf[IMGSENSOR_FMT_MAIN]);
|
||||
convert_to_imgsensorfmt(&fmt[VIDEO_FMT_SUB], &sf[IMGSENSOR_FMT_SUB]);
|
||||
@ -635,6 +699,7 @@ static void change_video_state(FAR video_mng_t *vmng,
|
||||
start_capture(V4L2_BUF_TYPE_VIDEO_CAPTURE,
|
||||
vmng->video_inf.nr_fmt,
|
||||
vmng->video_inf.fmt,
|
||||
&vmng->video_inf.clip,
|
||||
&vmng->video_inf.frame_interval,
|
||||
container->buf.m.userptr,
|
||||
container->buf.length);
|
||||
@ -1140,6 +1205,7 @@ static int video_qbuf(FAR struct video_mng_s *vmng,
|
||||
start_capture(buf->type,
|
||||
type_inf->nr_fmt,
|
||||
type_inf->fmt,
|
||||
&type_inf->clip,
|
||||
&type_inf->frame_interval,
|
||||
container->buf.m.userptr,
|
||||
container->buf.length);
|
||||
@ -1256,6 +1322,123 @@ static int video_cancel_dqbuf(FAR struct video_mng_s *vmng,
|
||||
return OK;
|
||||
}
|
||||
|
||||
static bool validate_clip_setting(FAR struct v4l2_rect *clip,
|
||||
FAR video_format_t *fmt)
|
||||
{
|
||||
int ret = true;
|
||||
|
||||
DEBUGASSERT(clip && fmt);
|
||||
|
||||
/* Not permit the setting which do not fit inside frame size. */
|
||||
|
||||
if ((clip->left < 0) ||
|
||||
(clip->top < 0) ||
|
||||
(clip->left + clip->width > fmt->width) ||
|
||||
(clip->top + clip->height > fmt->height))
|
||||
{
|
||||
ret = false;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int video_s_selection(FAR struct video_mng_s *vmng,
|
||||
FAR struct v4l2_selection *clip)
|
||||
{
|
||||
FAR video_type_inf_t *type_inf;
|
||||
int ret;
|
||||
int32_t id;
|
||||
uint32_t p_u32[IMGSENSOR_CLIP_NELEM];
|
||||
imgsensor_value_t val;
|
||||
video_format_t c_fmt[MAX_VIDEO_FMT];
|
||||
|
||||
ASSERT(g_video_sensor_ops && vmng);
|
||||
|
||||
if (g_video_sensor_ops->set_value == NULL)
|
||||
{
|
||||
return -ENOTTY;
|
||||
}
|
||||
|
||||
if (clip == NULL)
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
type_inf = get_video_type_inf(vmng, clip->type);
|
||||
if (type_inf == NULL)
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (type_inf->state != VIDEO_STATE_STREAMOFF)
|
||||
{
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
if (!validate_clip_setting(&clip->r, type_inf->fmt))
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* Query that clipped size is available. */
|
||||
|
||||
get_clipped_format(type_inf->nr_fmt,
|
||||
type_inf->fmt,
|
||||
&clip->r,
|
||||
c_fmt);
|
||||
|
||||
ret = validate_frame_setting(clip->type,
|
||||
type_inf->nr_fmt,
|
||||
c_fmt,
|
||||
&type_inf->frame_interval);
|
||||
if (ret != OK)
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
|
||||
id = (clip->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) ?
|
||||
IMGSENSOR_ID_CLIP_VIDEO : IMGSENSOR_ID_CLIP_STILL;
|
||||
|
||||
p_u32[IMGSENSOR_CLIP_INDEX_LEFT] = (uint32_t)clip->r.left;
|
||||
p_u32[IMGSENSOR_CLIP_INDEX_TOP] = (uint32_t)clip->r.top;
|
||||
p_u32[IMGSENSOR_CLIP_INDEX_WIDTH] = clip->r.width;
|
||||
p_u32[IMGSENSOR_CLIP_INDEX_HEIGHT] = clip->r.height;
|
||||
|
||||
val.p_u32 = p_u32;
|
||||
ret = g_video_sensor_ops->set_value
|
||||
(id, sizeof(p_u32), val);
|
||||
if (ret != OK)
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
|
||||
memcpy(&type_inf->clip, &clip->r, sizeof(struct v4l2_rect));
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int video_g_selection(FAR struct video_mng_s *vmng,
|
||||
FAR struct v4l2_selection *clip)
|
||||
{
|
||||
FAR video_type_inf_t *type_inf;
|
||||
|
||||
ASSERT(vmng);
|
||||
|
||||
if (clip == NULL)
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
type_inf = get_video_type_inf(vmng, clip->type);
|
||||
if (type_inf == NULL)
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
memcpy(&clip->r, &type_inf->clip, sizeof(struct v4l2_rect));
|
||||
return OK;
|
||||
}
|
||||
|
||||
static int validate_frame_setting(enum v4l2_buf_type type,
|
||||
uint8_t nr_fmt,
|
||||
FAR video_format_t *vfmt,
|
||||
@ -1623,6 +1806,7 @@ static int video_takepict_start(FAR struct video_mng_s *vmng,
|
||||
start_capture(V4L2_BUF_TYPE_STILL_CAPTURE,
|
||||
vmng->still_inf.nr_fmt,
|
||||
vmng->still_inf.fmt,
|
||||
&vmng->still_inf.clip,
|
||||
&vmng->still_inf.frame_interval,
|
||||
container->buf.m.userptr,
|
||||
container->buf.length);
|
||||
@ -2763,6 +2947,16 @@ static int video_ioctl(FAR struct file *filep, int cmd, unsigned long arg)
|
||||
|
||||
break;
|
||||
|
||||
case VIDIOC_S_SELECTION:
|
||||
ret = video_s_selection(priv, (FAR struct v4l2_selection *)arg);
|
||||
|
||||
break;
|
||||
|
||||
case VIDIOC_G_SELECTION:
|
||||
ret = video_g_selection(priv, (FAR struct v4l2_selection *)arg);
|
||||
|
||||
break;
|
||||
|
||||
case VIDIOC_TRY_FMT:
|
||||
ret = video_try_fmt(priv, (FAR struct v4l2_format *)arg);
|
||||
|
||||
|
@ -75,6 +75,23 @@
|
||||
#define IMGSENSOR_ID_3A_STATUS (0x00010015)
|
||||
#define IMGSENSOR_ID_FLASH_LED_MODE (0x00020000)
|
||||
#define IMGSENSOR_ID_JPEG_QUALITY (0x00030000)
|
||||
#define IMGSENSOR_ID_CLIP_VIDEO (0xFFFF0000)
|
||||
#define IMGSENSOR_ID_CLIP_STILL (0xFFFF0001)
|
||||
|
||||
/* Number of elements in clip data array
|
||||
* in IMGSENSOR_ID_CLIP_VIDEO and IMGSENSOR_ID_CLIP_STILL case
|
||||
*/
|
||||
|
||||
#define IMGSENSOR_CLIP_NELEM (4)
|
||||
|
||||
/* Index of clip information
|
||||
* in IMGSENSOR_ID_CLIP_VIDEO and IMGSENSOR_ID_CLIP_STILL case
|
||||
*/
|
||||
|
||||
#define IMGSENSOR_CLIP_INDEX_LEFT (0)
|
||||
#define IMGSENSOR_CLIP_INDEX_TOP (1)
|
||||
#define IMGSENSOR_CLIP_INDEX_WIDTH (2)
|
||||
#define IMGSENSOR_CLIP_INDEX_HEIGHT (3)
|
||||
|
||||
/* bit definition for IMGSENSOR_ID_3A_LOCK */
|
||||
|
||||
|
@ -178,6 +178,18 @@ extern "C"
|
||||
|
||||
#define VIDIOC_QUERYCAP _VIDIOC(0x001b)
|
||||
|
||||
/* Set clip
|
||||
* Address pointing to struct v4l2_selection
|
||||
*/
|
||||
|
||||
#define VIDIOC_S_SELECTION _VIDIOC(0x001c)
|
||||
|
||||
/* Get clip
|
||||
* Address pointing to struct v4l2_selection
|
||||
*/
|
||||
|
||||
#define VIDIOC_G_SELECTION _VIDIOC(0x001d)
|
||||
|
||||
#define VIDEO_HSIZE_QVGA (320) /* QVGA horizontal size */
|
||||
#define VIDEO_VSIZE_QVGA (240) /* QVGA vertical size */
|
||||
#define VIDEO_HSIZE_VGA (640) /* VGA horizontal size */
|
||||
@ -258,6 +270,39 @@ struct v4l2_capability
|
||||
uint32_t device_caps; /* Device capabilities of the opened device */
|
||||
};
|
||||
|
||||
/* Rectangle information */
|
||||
|
||||
struct v4l2_rect
|
||||
{
|
||||
/* Horizontal offset of the top, left corner of the rectangle, in pixels. */
|
||||
|
||||
int32_t left;
|
||||
|
||||
/* Vertical offset of the top, left corner of the rectangle, in pixels. */
|
||||
|
||||
int32_t top;
|
||||
|
||||
/* Width of the rectangle, in pixels. */
|
||||
|
||||
uint32_t width;
|
||||
|
||||
/* Height of the rectangle, in pixels. */
|
||||
|
||||
uint32_t height;
|
||||
};
|
||||
|
||||
/* V4L2 selection info for VIDIOC_S_SELECTION and VIDIOC_G_SELECTION.
|
||||
* Currently, only member type and r are supported.
|
||||
*/
|
||||
|
||||
struct v4l2_selection
|
||||
{
|
||||
uint32_t type; /* Buffer type */
|
||||
uint32_t target;
|
||||
uint32_t flags;
|
||||
struct v4l2_rect r; /* The selection rectangle. */
|
||||
};
|
||||
|
||||
/* Buffer type.
|
||||
* Currently, support only V4L2_BUF_TYPE_VIDEO_CAPTURE and
|
||||
* V4L2_BUF_TYPE_STILL_CAPTURE.
|
||||
|
Loading…
Reference in New Issue
Block a user