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 2022/10/25 19:57:33 UTC

[incubator-nuttx] 01/08: drivers/video: Add get frame interval API

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/incubator-nuttx.git

commit 1332bdb9a7aa1b97b384caf79082cc8d2f540f4e
Author: SPRESENSE <41...@users.noreply.github.com>
AuthorDate: Mon Oct 24 21:00:40 2022 +0900

    drivers/video: Add get frame interval API
---
 drivers/video/isx012.c          |  1 +
 drivers/video/isx019.c          | 88 +++++++++++++++++++++++++++++++++++++++++
 drivers/video/video.c           | 45 +++++++++++++++++++++
 include/nuttx/video/imgsensor.h |  3 +-
 include/nuttx/video/video.h     |  6 +++
 5 files changed, 142 insertions(+), 1 deletion(-)

diff --git a/drivers/video/isx012.c b/drivers/video/isx012.c
index f05f28e1fd..8564df7703 100644
--- a/drivers/video/isx012.c
+++ b/drivers/video/isx012.c
@@ -628,6 +628,7 @@ static struct imgsensor_ops_s g_isx012_ops =
   isx012_validate_frame_setting,        /* validate_frame_setting */
   isx012_start_capture,                 /* start_capture */
   isx012_stop_capture,                  /* stop_capture */
+  NULL,                                 /* get_frame_interval */
   isx012_get_supported_value,           /* get_supported_value */
   isx012_get_value,                     /* get_value */
   isx012_set_value                      /* set_value */
diff --git a/drivers/video/isx019.c b/drivers/video/isx019.c
index f4d4c53bd2..7ef9e15393 100644
--- a/drivers/video/isx019.c
+++ b/drivers/video/isx019.c
@@ -148,6 +148,11 @@
 
 #define BW_COLORS_SATURATION (0x00)
 
+/* Definition for calculation of extended frame number */
+
+#define VTIME_PER_FRAME    (30518)
+#define INTERVAL_PER_FRAME (33333)
+
 /****************************************************************************
  * Private Types
  ****************************************************************************/
@@ -267,6 +272,8 @@ static int isx019_start_capture(imgsensor_stream_type_t type,
                                 FAR imgsensor_format_t *datafmts,
                                 FAR imgsensor_interval_t *interval);
 static int isx019_stop_capture(imgsensor_stream_type_t type);
+static int isx019_get_frame_interval(imgsensor_stream_type_t type,
+                                     FAR imgsensor_interval_t *interval);
 static int isx019_get_supported_value(uint32_t id,
                                      FAR imgsensor_supported_value_t *value);
 static int isx019_get_value(uint32_t id, uint32_t size,
@@ -294,6 +301,7 @@ static struct imgsensor_ops_s g_isx019_ops =
   isx019_validate_frame_setting,
   isx019_start_capture,
   isx019_stop_capture,
+  isx019_get_frame_interval,
   isx019_get_supported_value,
   isx019_get_value,
   isx019_set_value,
@@ -1607,6 +1615,86 @@ static int isx019_stop_capture(imgsensor_stream_type_t type)
   return OK;
 }
 
+static int calc_gcm(int a, int b)
+{
+  int r;
+
+  DEBUGASSERT((a != 0) && (b != 0));
+
+  while ((r = a % b) != 0)
+    {
+      a = b;
+      b = r;
+    }
+
+  return b;
+}
+
+static int isx019_get_frame_interval(imgsensor_stream_type_t type,
+                                     FAR imgsensor_interval_t *interval)
+{
+  uint32_t vtime = VTIME_PER_FRAME;
+  uint32_t frame = 1;
+  uint8_t  fps   = FPGA_FPS_1_1;
+  int decimation = 1;
+  int gcm;
+
+  if (interval == NULL)
+    {
+      return -EINVAL;
+    }
+
+  /* ISX019's base frame interval = 1/30. */
+
+  interval->denominator = 30;
+  interval->numerator = 1;
+
+  /* ISX019 has the frame extension feature, which automatically
+   * exposes longer than one frame in dark environment.
+   * The number of extended frame is calculated from V_TIME register,
+   * which has the value
+   *   VTIME_PER_FRAME + INTERVAL_PER_FRAME * (frame number - 1)
+   */
+
+  isx019_i2c_read(CAT_AESOUT, V_TIME, (FAR uint8_t *)&vtime, 4);
+  frame = 1 + (vtime - VTIME_PER_FRAME) / INTERVAL_PER_FRAME;
+  interval->numerator *= frame;
+
+  /* Also, consider frame decimation by FPGA.
+   * decimation amount is gotten from FPGA register.
+   */
+
+  fpga_i2c_read(FPGA_FPS_AND_THUMBNAIL, &fps, 1);
+  switch (fps & FPGA_FPS_BITS)
+    {
+      case FPGA_FPS_1_1:
+        decimation = 1;
+        break;
+
+      case FPGA_FPS_1_2:
+        decimation = 2;
+        break;
+
+      case FPGA_FPS_1_3:
+        decimation = 3;
+        break;
+
+      default: /* FPGA_FPS_1_4 */
+        decimation = 4;
+        break;
+    }
+
+  interval->numerator *= decimation;
+
+  /* Reduce the fraction. */
+
+  gcm = calc_gcm(30, frame * decimation);
+  interval->denominator /= gcm;
+  interval->numerator   /= gcm;
+
+  return OK;
+}
+
 static int isx019_get_supported_value(uint32_t id,
                                       FAR imgsensor_supported_value_t *val)
 {
diff --git a/drivers/video/video.c b/drivers/video/video.c
index f82992c6e4..b7c5d03793 100644
--- a/drivers/video/video.c
+++ b/drivers/video/video.c
@@ -1630,6 +1630,46 @@ static int video_s_parm(FAR struct video_mng_s *priv,
   return ret;
 }
 
+static int video_g_parm(FAR struct video_mng_s *vmng,
+                        FAR struct v4l2_streamparm *parm)
+{
+  int ret = -EINVAL;
+  FAR video_type_inf_t *type_inf;
+
+  DEBUGASSERT(vmng && g_video_sensor_ops);
+
+  type_inf = get_video_type_inf(vmng, parm->type);
+  if (type_inf == NULL)
+    {
+      return -EINVAL;
+    }
+
+  if ((type_inf->state == VIDEO_STATE_CAPTURE) &&
+      (g_video_sensor_ops->get_frame_interval != NULL))
+    {
+      /* If capture is started and lower driver has the get_frame_interval(),
+       * query lower driver.
+       */
+
+      memset(&parm->parm, 0, sizeof(parm->parm));
+
+      ret = g_video_sensor_ops->get_frame_interval
+              (parm->type,
+               (imgsensor_interval_t *)&parm->parm.capture.timeperframe);
+    }
+
+  if (ret != OK)
+    {
+      /* In no capture state or error case, return stored value. */
+
+      memcpy(&parm->parm.capture.timeperframe,
+             &type_inf->frame_interval,
+             sizeof(struct v4l2_fract));
+    }
+
+  return OK;
+}
+
 static int video_streamon(FAR struct video_mng_s *vmng,
                           FAR enum v4l2_buf_type *type)
 {
@@ -2955,6 +2995,11 @@ static int video_ioctl(FAR struct file *filep, int cmd, unsigned long arg)
 
         break;
 
+      case VIDIOC_G_PARM:
+        ret = video_g_parm(priv, (FAR struct v4l2_streamparm *)arg);
+
+        break;
+
       case VIDIOC_QUERYCTRL:
         ret = video_queryctrl((FAR struct v4l2_queryctrl *)arg);
 
diff --git a/include/nuttx/video/imgsensor.h b/include/nuttx/video/imgsensor.h
index d40aa080f5..f31eb3b55f 100644
--- a/include/nuttx/video/imgsensor.h
+++ b/include/nuttx/video/imgsensor.h
@@ -333,7 +333,8 @@ struct imgsensor_ops_s
                              FAR imgsensor_format_t *datafmts,
                              FAR imgsensor_interval_t *interval);
   CODE int  (*stop_capture)(imgsensor_stream_type_t type);
-
+  CODE int  (*get_frame_interval)(imgsensor_stream_type_t type,
+                                  FAR imgsensor_interval_t *interval);
   CODE int  (*get_supported_value)(uint32_t id,
                                    FAR imgsensor_supported_value_t *value);
   CODE int  (*get_value)(uint32_t id,
diff --git a/include/nuttx/video/video.h b/include/nuttx/video/video.h
index bf35e88d9e..b7703e7749 100644
--- a/include/nuttx/video/video.h
+++ b/include/nuttx/video/video.h
@@ -190,6 +190,12 @@ extern "C"
 
 #define VIDIOC_G_SELECTION            _VIDIOC(0x001d)
 
+/* Get the frame interval.
+ * Address pointing to struct v4l2_streamparm
+ */
+
+#define VIDIOC_G_PARM                 _VIDIOC(0x001e)
+
 #define VIDEO_HSIZE_QVGA        (320)   /* QVGA    horizontal size */
 #define VIDEO_VSIZE_QVGA        (240)   /* QVGA    vertical   size */
 #define VIDEO_HSIZE_VGA         (640)   /* VGA     horizontal size */