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

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

commit 6cc53f2f37ff949d7994f19ec51bb47c0b354dde
Author: niyinghao <[email protected]>
AuthorDate: Thu Sep 25 20:27:26 2025 +0800

    v4l2-m2m: support userptr mode
    
    Add userptr buffer mode support for v4l2-m2m.
    
    Signed-off-by: niyinghao <[email protected]>
---
 drivers/video/v4l2_m2m.c        | 33 ++++++++++++++++++++++++++++
 drivers/video/video_framebuff.c | 48 +++++++++++++++++++++++++++++++++++++++++
 drivers/video/video_framebuff.h |  2 ++
 3 files changed, 83 insertions(+)

diff --git a/drivers/video/v4l2_m2m.c b/drivers/video/v4l2_m2m.c
index 29fc0412a46..42359a98cde 100644
--- a/drivers/video/v4l2_m2m.c
+++ b/drivers/video/v4l2_m2m.c
@@ -352,6 +352,7 @@ static int codec_querybuf(FAR struct file *filep,
   FAR codec_mng_t *cmng = inode->i_private;
   FAR codec_file_t *cfile = filep->f_priv;
   FAR codec_type_inf_t *type_inf;
+  FAR vbuf_container_t *container;
   struct v4l2_format format;
   uint32_t offset = 0;
   size_t bufsize;
@@ -391,6 +392,8 @@ static int codec_querybuf(FAR struct file *filep,
       return -EINVAL;
     }
 
+  container = video_framebuff_find_container(&type_inf->bufinf, buf->index);
+
   if (V4L2_TYPE_IS_MULTIPLANAR(buf->type))
     {
       for (i = 0; i < format.fmt.pix_mp.num_planes; i++)
@@ -405,6 +408,11 @@ static int codec_querybuf(FAR struct file *filep,
                 offset += buf->m.planes[i].length;
                 break;
 
+              case V4L2_MEMORY_USERPTR:
+                buf->m.planes[i].m.userptr = container ?
+                    container->buf.m.planes[i].m.userptr : 0;
+                break;
+
               default:
                 return -EINVAL;
             }
@@ -419,6 +427,10 @@ static int codec_querybuf(FAR struct file *filep,
             buf->m.offset = offset + bufsize * buf->index;
             break;
 
+          case V4L2_MEMORY_USERPTR:
+            buf->m.userptr = container ? container->buf.m.userptr : 0;
+            break;
+
           default:
             return -EINVAL;
         }
@@ -459,6 +471,9 @@ static int codec_qbuf(FAR struct file *filep,
           }
         break;
 
+      case V4L2_MEMORY_USERPTR:
+        break;
+
       default:
         return -EINVAL;
     }
@@ -509,6 +524,11 @@ static int codec_qbuf(FAR struct file *filep,
                      bufsize * buf->index + plane_offset);
                 plane_offset += format.fmt.pix_mp.plane_fmt[i].sizeimage;
                 break;
+
+              case V4L2_MEMORY_USERPTR:
+                container->buf.m.planes[i].m.vaddr =
+                    (FAR void *)buf->m.planes[i].m.userptr;
+                break;
             }
         }
     }
@@ -527,6 +547,10 @@ static int codec_qbuf(FAR struct file *filep,
                   (FAR void *)(type_inf->bufheap + bufsize * buf->index);
             }
             break;
+
+          case V4L2_MEMORY_USERPTR:
+            container->buf.m.vaddr = (FAR void *)buf->m.userptr;
+            break;
         }
     }
 
@@ -610,6 +634,11 @@ static int codec_dqbuf(FAR struct file *filep,
                      type_inf->bufheap + offset);
                 break;
 
+              case V4L2_MEMORY_USERPTR:
+                buf->m.planes[i].m.userptr = (unsigned long)
+                    buf->m.planes[i].m.vaddr;
+                break;
+
               default:
                 return -EINVAL;
             }
@@ -624,6 +653,10 @@ static int codec_dqbuf(FAR struct file *filep,
                             type_inf->bufheap + offset);
             break;
 
+          case V4L2_MEMORY_USERPTR:
+            buf->m.userptr = (unsigned long)buf->m.vaddr;
+            break;
+
           default:
             return -EINVAL;
         }
diff --git a/drivers/video/video_framebuff.c b/drivers/video/video_framebuff.c
index f74f550e6be..152f8a736a6 100644
--- a/drivers/video/video_framebuff.c
+++ b/drivers/video/video_framebuff.c
@@ -289,3 +289,51 @@ vbuf_container_t 
*video_framebuff_pop_curr_container(video_framebuff_t *fbuf)
   spin_unlock_irqrestore(&fbuf->lock_queue, flags);
   return ret;
 }
+
+vbuf_container_t *video_framebuff_find_container(video_framebuff_t *fbuf,
+                                                 uint32_t index)
+{
+  vbuf_container_t *ret = NULL;
+  vbuf_container_t *curr;
+  vbuf_container_t *start;
+  irqstate_t flags;
+
+  flags = spin_lock_irqsave(&fbuf->lock_queue);
+  if (fbuf->vbuf_top != NULL)
+    {
+      curr = start = fbuf->vbuf_top;
+      do
+        {
+          if (curr->buf.index == index)
+            {
+              ret = curr;
+              break;
+            }
+
+          curr = curr->next;
+        }
+      while (curr != NULL && curr != start);
+    }
+
+  spin_unlock_irqrestore(&fbuf->lock_queue, flags);
+
+  if (ret == NULL)
+    {
+      nxmutex_lock(&fbuf->lock_empty);
+      curr = fbuf->vbuf_empty;
+      while (curr != NULL)
+        {
+          if (curr->buf.index == index)
+            {
+              ret = curr;
+              break;
+            }
+
+          curr = curr->next;
+        }
+
+      nxmutex_unlock(&fbuf->lock_empty);
+    }
+
+  return ret;
+}
diff --git a/drivers/video/video_framebuff.h b/drivers/video/video_framebuff.h
index 1fd252b99a9..9dc470a161b 100644
--- a/drivers/video/video_framebuff.h
+++ b/drivers/video/video_framebuff.h
@@ -90,5 +90,7 @@ void              video_framebuff_capture_done
                        (video_framebuff_t *fbuf);
 void              video_framebuff_change_mode
                        (video_framebuff_t *fbuf, enum v4l2_buf_mode mode);
+vbuf_container_t *video_framebuff_find_container
+                       (video_framebuff_t *fbuf, uint32_t index);
 
 #endif  /* __DRIVERS_VIDEO_VIDEO_FRAMEBUFF_H */

Reply via email to