You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@nuttx.apache.org by xi...@apache.org on 2023/02/13 15:17:54 UTC

[nuttx] 02/02: drivers/video/video: add poll support to capture

This is an automated email from the ASF dual-hosted git repository.

xiaoxiang pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/nuttx.git

commit a1e04617f81a8b5c8b3103b509117bb672a3603b
Author: jihandong <ji...@xiaomi.com>
AuthorDate: Tue Jan 31 17:23:28 2023 +0800

    drivers/video/video: add poll support to capture
    
    support part of Linux std:
    https://www.kernel.org/doc/html/v4.9/media/uapi/v4l/func-poll.html
    
    Capture devices set the POLLIN and POLLRDNORM flags in the revents field
    
    Signed-off-by: jihandong <ji...@xiaomi.com>
---
 drivers/video/video.c           | 54 +++++++++++++++++++++++++++++++++++++++++
 drivers/video/video_framebuff.c |  5 ++++
 drivers/video/video_framebuff.h |  2 ++
 3 files changed, 61 insertions(+)

diff --git a/drivers/video/video.c b/drivers/video/video.c
index ad7d20cc6f..4c8ee4c6a3 100644
--- a/drivers/video/video.c
+++ b/drivers/video/video.c
@@ -119,6 +119,7 @@ struct video_type_inf_s
   struct v4l2_fract    frame_interval;
   video_framebuff_t    bufinf;
   FAR uint8_t          *bufheap;   /* for V4L2_MEMORY_MMAP buffers */
+  FAR struct pollfd    *fds;
   uint32_t             seqnum;
 };
 
@@ -200,6 +201,8 @@ static ssize_t video_write(FAR struct file *filep,
 static int video_ioctl(FAR struct file *filep, int cmd, unsigned long arg);
 static int video_mmap(FAR struct file *filep,
                       FAR struct mm_map_entry_s *map);
+static int video_poll(FAR struct file *filep, FAR struct pollfd *fds,
+                      bool setup);
 
 /* Common function */
 
@@ -290,6 +293,8 @@ static const struct file_operations g_video_fops =
   NULL,                     /* seek */
   video_ioctl,              /* ioctl */
   video_mmap,               /* mmap */
+  NULL,                     /* truncate */
+  video_poll,               /* poll */
 };
 
 static bool g_video_initialized = false;
@@ -3154,6 +3159,53 @@ static int video_mmap(FAR struct file *filep, FAR struct mm_map_entry_s *map)
   return ret;
 }
 
+static int video_poll(FAR struct file *filep, struct pollfd *fds, bool setup)
+{
+  FAR struct inode     *inode = filep->f_inode;
+  FAR video_mng_t      *priv  = (FAR video_mng_t *)inode->i_private;
+  FAR video_type_inf_t *type_inf;
+  enum v4l2_buf_type   buf_type;
+  irqstate_t           flags;
+
+  buf_type = priv->still_inf.state == VIDEO_STATE_CAPTURE ?
+                V4L2_BUF_TYPE_STILL_CAPTURE : V4L2_BUF_TYPE_VIDEO_CAPTURE;
+
+  type_inf = get_video_type_inf(priv, buf_type);
+  if (type_inf == NULL)
+    {
+      return -EINVAL;
+    }
+
+  flags = enter_critical_section();
+
+  if (setup)
+    {
+      if (type_inf->fds == NULL)
+        {
+          type_inf->fds = fds;
+          fds->priv     = &type_inf->fds;
+          if (!video_framebuff_is_empty(&type_inf->bufinf))
+            {
+              poll_notify(&type_inf->fds, 1, POLLIN);
+            }
+        }
+      else
+        {
+          leave_critical_section(flags);
+          return -EBUSY;
+        }
+    }
+  else if (fds->priv)
+    {
+      type_inf->fds = NULL;
+      fds->priv     = NULL;
+    }
+
+  leave_critical_section(flags);
+
+  return OK;
+}
+
 static FAR void *video_register(FAR const char *devpath)
 {
   FAR video_mng_t *priv;
@@ -3259,6 +3311,8 @@ static int video_complete_capture(uint8_t err_code, uint32_t datasize,
       return -EINVAL;
     }
 
+  poll_notify(&type_inf->fds, 1, POLLIN);
+
   if (err_code == 0)
     {
       type_inf->bufinf.vbuf_curr->buf.flags = 0;
diff --git a/drivers/video/video_framebuff.c b/drivers/video/video_framebuff.c
index bb4a2ecf9f..fc66745e9f 100644
--- a/drivers/video/video_framebuff.c
+++ b/drivers/video/video_framebuff.c
@@ -120,6 +120,11 @@ int video_framebuff_realloc_container(video_framebuff_t *fbuf, int sz)
   return OK;
 }
 
+int video_framebuff_is_empty(video_framebuff_t *fbuf)
+{
+  return fbuf->vbuf_top == NULL || fbuf->vbuf_top == fbuf->vbuf_next;
+}
+
 vbuf_container_t *video_framebuff_get_container(video_framebuff_t *fbuf)
 {
   vbuf_container_t *ret;
diff --git a/drivers/video/video_framebuff.h b/drivers/video/video_framebuff.h
index cf2bbbb4bb..a4183a5f9c 100644
--- a/drivers/video/video_framebuff.h
+++ b/drivers/video/video_framebuff.h
@@ -71,6 +71,8 @@ vbuf_container_t *video_framebuff_get_container
                        (video_framebuff_t *fbuf);
 void              video_framebuff_free_container
                        (video_framebuff_t *fbuf, vbuf_container_t *cnt);
+int               video_framebuff_is_empty
+                       (video_framebuff_t *fbuf);
 void              video_framebuff_queue_container
                        (video_framebuff_t *fbuf, vbuf_container_t *tgt);
 vbuf_container_t *video_framebuff_dq_valid_container