drivers/video: add support for V4L2 mmap-ed buffer
Support V4L2_MEMORY_MMAP memory mode Signed-off-by: Peter Bee <bijunda1@xiaomi.com>
This commit is contained in:
parent
4320eed4a1
commit
31347da187
|
@ -58,6 +58,10 @@ config VIDEO_STREAM
|
|||
|
||||
if VIDEO_STREAM
|
||||
|
||||
config VIDEO_REQBUFS_COUNT_MAX
|
||||
int "Maximum Video reqbuf buffers count"
|
||||
default 3
|
||||
|
||||
config VIDEO_SCENE_BACKLIGHT
|
||||
bool "Enable backlight scene"
|
||||
default y
|
||||
|
|
|
@ -123,6 +123,7 @@ struct video_type_inf_s
|
|||
struct v4l2_rect clip;
|
||||
struct v4l2_fract frame_interval;
|
||||
video_framebuff_t bufinf;
|
||||
FAR uint8_t *bufheap; /* for V4L2_MEMORY_MMAP buffers */
|
||||
};
|
||||
|
||||
typedef struct video_type_inf_s video_type_inf_t;
|
||||
|
@ -219,6 +220,7 @@ static int validate_frame_setting(enum v4l2_buf_type type,
|
|||
uint8_t nr_fmt,
|
||||
FAR video_format_t *vfmt,
|
||||
FAR struct v4l2_fract *interval);
|
||||
static size_t get_bufsize(FAR video_format_t *vf);
|
||||
|
||||
/* internal function for each cmds of ioctl */
|
||||
|
||||
|
@ -653,7 +655,7 @@ static int start_capture(enum v4l2_buf_type type,
|
|||
FAR video_format_t *fmt,
|
||||
FAR struct v4l2_rect *clip,
|
||||
FAR struct v4l2_fract *interval,
|
||||
uint32_t bufaddr, uint32_t bufsize)
|
||||
uintptr_t bufaddr, uint32_t bufsize)
|
||||
{
|
||||
video_format_t c_fmt[MAX_VIDEO_FMT];
|
||||
imgdata_format_t df[MAX_VIDEO_FMT];
|
||||
|
@ -940,6 +942,11 @@ static void cleanup_streamresources(FAR video_type_inf_t *type_inf)
|
|||
video_framebuff_uninit(&type_inf->bufinf);
|
||||
nxsem_destroy(&type_inf->wait_capture.dqbuf_wait_flg);
|
||||
nxmutex_destroy(&type_inf->lock_state);
|
||||
if (type_inf->bufheap != NULL)
|
||||
{
|
||||
kumm_free(type_inf->bufheap);
|
||||
type_inf->bufheap = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static void cleanup_scene_parameter(video_scene_params_t *sp)
|
||||
|
@ -1172,10 +1179,29 @@ static int video_reqbufs(FAR struct video_mng_s *vmng,
|
|||
}
|
||||
else
|
||||
{
|
||||
if (reqbufs->count > V4L2_REQBUFS_COUNT_MAX)
|
||||
{
|
||||
reqbufs->count = V4L2_REQBUFS_COUNT_MAX;
|
||||
}
|
||||
|
||||
video_framebuff_change_mode(&type_inf->bufinf, reqbufs->mode);
|
||||
|
||||
ret = video_framebuff_realloc_container(&type_inf->bufinf,
|
||||
reqbufs->count);
|
||||
if (ret == OK && reqbufs->memory == V4L2_MEMORY_MMAP)
|
||||
{
|
||||
if (type_inf->bufheap != NULL)
|
||||
{
|
||||
kumm_free(type_inf->bufheap);
|
||||
}
|
||||
|
||||
type_inf->bufheap = kumm_memalign(32, reqbufs->count *
|
||||
get_bufsize(&type_inf->fmt[VIDEO_FMT_MAIN]));
|
||||
if (type_inf->bufheap == NULL)
|
||||
{
|
||||
ret = -ENOMEM;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
leave_critical_section(flags);
|
||||
|
@ -1183,6 +1209,33 @@ static int video_reqbufs(FAR struct video_mng_s *vmng,
|
|||
return ret;
|
||||
}
|
||||
|
||||
static int video_querybuf(FAR struct video_mng_s *vmng,
|
||||
FAR struct v4l2_buffer *buf)
|
||||
{
|
||||
FAR video_type_inf_t *type_inf;
|
||||
|
||||
if ((vmng == NULL) || (buf == NULL) || buf->memory != V4L2_MEMORY_MMAP)
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
type_inf = get_video_type_inf(vmng, buf->type);
|
||||
if (type_inf == NULL)
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (buf->index >= type_inf->bufinf.container_size)
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
buf->length = get_bufsize(&type_inf->fmt[VIDEO_FMT_MAIN]);
|
||||
buf->m.offset = buf->length * buf->index;
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
static int video_qbuf(FAR struct video_mng_s *vmng,
|
||||
FAR struct v4l2_buffer *buf)
|
||||
{
|
||||
|
@ -1214,6 +1267,15 @@ static int video_qbuf(FAR struct video_mng_s *vmng,
|
|||
}
|
||||
|
||||
memcpy(&container->buf, buf, sizeof(struct v4l2_buffer));
|
||||
if (buf->memory == V4L2_MEMORY_MMAP)
|
||||
{
|
||||
/* only use userptr inside the container */
|
||||
|
||||
container->buf.length = get_bufsize(&type_inf->fmt[VIDEO_FMT_MAIN]);
|
||||
container->buf.m.userptr = (unsigned long)(type_inf->bufheap +
|
||||
buf->length * buf->index);
|
||||
}
|
||||
|
||||
video_framebuff_queue_container(&type_inf->bufinf, container);
|
||||
|
||||
nxmutex_lock(&type_inf->lock_state);
|
||||
|
@ -1522,6 +1584,22 @@ static int validate_frame_setting(enum v4l2_buf_type type,
|
|||
return g_video_data_ops->validate_frame_setting(nr_fmt, df, &di);
|
||||
}
|
||||
|
||||
static size_t get_bufsize(video_format_t *vf)
|
||||
{
|
||||
size_t ret = vf->width * vf->height;
|
||||
switch (vf->pixelformat)
|
||||
{
|
||||
case V4L2_PIX_FMT_YUV420:
|
||||
return ret * 3 / 2;
|
||||
case V4L2_PIX_FMT_YUYV:
|
||||
case V4L2_PIX_FMT_UYVY:
|
||||
case V4L2_PIX_FMT_RGB565:
|
||||
case V4L2_PIX_FMT_JPEG:
|
||||
default:
|
||||
return ret * 2;
|
||||
}
|
||||
}
|
||||
|
||||
static int video_try_fmt(FAR struct video_mng_s *priv,
|
||||
FAR struct v4l2_format *v4l2)
|
||||
{
|
||||
|
@ -3019,6 +3097,11 @@ static int video_ioctl(FAR struct file *filep, int cmd, unsigned long arg)
|
|||
|
||||
break;
|
||||
|
||||
case VIDIOC_QUERYBUF:
|
||||
ret = video_querybuf(priv, (FAR struct v4l2_buffer *)arg);
|
||||
|
||||
break;
|
||||
|
||||
case VIDIOC_QBUF:
|
||||
ret = video_qbuf(priv, (FAR struct v4l2_buffer *)arg);
|
||||
|
||||
|
@ -3162,6 +3245,13 @@ static int video_ioctl(FAR struct file *filep, int cmd, unsigned long arg)
|
|||
|
||||
break;
|
||||
|
||||
case FIOC_MMAP:
|
||||
DEBUGASSERT((FAR void **)(uintptr_t)arg != NULL);
|
||||
*(FAR void **)((uintptr_t)arg) = priv->video_inf.bufheap;
|
||||
ret = OK;
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
verr("Unrecognized cmd: %d\n", cmd);
|
||||
ret = - ENOTTY;
|
||||
|
|
|
@ -114,11 +114,6 @@ void video_framebuff_uninit(video_framebuff_t *fbuf)
|
|||
|
||||
int video_framebuff_realloc_container(video_framebuff_t *fbuf, int sz)
|
||||
{
|
||||
if (sz > V4L2_REQBUFS_COUNT_MAX)
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (fbuf->vbuf_alloced == NULL || fbuf->container_size != sz)
|
||||
{
|
||||
if (fbuf->container_size != sz)
|
||||
|
|
|
@ -459,7 +459,7 @@ extern "C"
|
|||
|
||||
/* MAX value of VIDIOC_REQBUFS count parameter */
|
||||
|
||||
#define V4L2_REQBUFS_COUNT_MAX (256)
|
||||
#define V4L2_REQBUFS_COUNT_MAX CONFIG_VIDEO_REQBUFS_COUNT_MAX
|
||||
|
||||
/* Buffer error flag */
|
||||
|
||||
|
@ -751,7 +751,7 @@ struct v4l2_requestbuffers
|
|||
{
|
||||
uint32_t count; /* The number of buffers requested.
|
||||
* Supported maximum is
|
||||
* is V4L2_REQBUFS_COUNT_MAX(=256)
|
||||
* is V4L2_REQBUFS_COUNT_MAX
|
||||
*/
|
||||
uint32_t type; /* enum #v4l2_buf_type */
|
||||
uint32_t memory; /* enum #v4l2_memory */
|
||||
|
|
Loading…
Reference in New Issue