Skip to content

Commit 52b36de

Browse files
JianyuWang0623acassis
authored andcommitted
examples/camera: use MMAP with USERPTR fallback and fix NX stride
Use MMAP buffer allocation by default so the driver can manage DMA-capable memory with proper alignment and cache attributes. Fall back to USERPTR if the driver does not support MMAP. Also fix NX framebuffer stride calculation to use the actual display width instead of hardcoded values. Signed-off-by: wangjianyu3 <wangjianyu3@xiaomi.com>
1 parent a6286ee commit 52b36de

2 files changed

Lines changed: 91 additions & 36 deletions

File tree

examples/camera/camera_bkgd.c

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -307,21 +307,28 @@ void nximage_draw(FAR void *image, int w, int h)
307307
FAR struct nxgl_rect_s dest;
308308
FAR const void *src[CONFIG_NX_NPLANES];
309309
int ret;
310+
int dest_w;
311+
int dest_h;
310312

311313
origin.x = 0;
312314
origin.y = 0;
313315

314-
/* Set up the destination to whole LCD screen */
316+
/* Clip destination to the smaller of image size and screen size */
317+
318+
dest_w = w < g_nximage.xres ? w : g_nximage.xres;
319+
dest_h = h < g_nximage.yres ? h : g_nximage.yres;
315320

316321
dest.pt1.x = 0;
317322
dest.pt1.y = 0;
318-
dest.pt2.x = g_nximage.xres - 1;
319-
dest.pt2.y = g_nximage.yres - 1;
323+
dest.pt2.x = dest_w - 1;
324+
dest.pt2.y = dest_h - 1;
320325

321326
src[0] = image;
322327

328+
/* stride must match the source image width, not the screen width */
329+
323330
ret = nx_bitmap(g_nximage.hbkgd, &dest, src, &origin,
324-
g_nximage.xres * sizeof(nxgl_mxpixel_t));
331+
w * sizeof(nxgl_mxpixel_t));
325332
if (ret < 0)
326333
{
327334
printf("nximage_image: nx_bitmap failed: %d\n", errno);

examples/camera/camera_main.c

Lines changed: 80 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -84,13 +84,14 @@ static int camera_prepare(int fd, enum v4l2_buf_type type,
8484
uint32_t buf_mode, uint32_t pixformat,
8585
uint16_t hsize, uint16_t vsize,
8686
FAR struct v_buffer **vbuf,
87-
uint8_t buffernum, int buffersize);
87+
uint8_t buffernum, int buffersize,
88+
FAR uint32_t *memory);
8889
static void free_buffer(FAR struct v_buffer *buffers, uint8_t bufnum);
8990
static int parse_arguments(int argc, FAR char *argv[],
9091
FAR int *capture_num,
9192
FAR enum v4l2_buf_type *type);
9293
static int get_camimage(int fd, FAR struct v4l2_buffer *v4l2_buf,
93-
enum v4l2_buf_type buf_type);
94+
enum v4l2_buf_type buf_type, uint32_t memory);
9495
static int release_camimage(int fd, FAR struct v4l2_buffer *v4l2_buf);
9596
static int start_stillcapture(int v_fd, enum v4l2_buf_type capture_type);
9697
static int stop_stillcapture(int v_fd, enum v4l2_buf_type capture_type);
@@ -119,7 +120,8 @@ static int camera_prepare(int fd, enum v4l2_buf_type type,
119120
uint32_t buf_mode, uint32_t pixformat,
120121
uint16_t hsize, uint16_t vsize,
121122
FAR struct v_buffer **vbuf,
122-
uint8_t buffernum, int buffersize)
123+
uint8_t buffernum, int buffersize,
124+
FAR uint32_t *memory)
123125
{
124126
int ret;
125127
int cnt;
@@ -153,21 +155,30 @@ static int camera_prepare(int fd, enum v4l2_buf_type type,
153155
return ret;
154156
}
155157

156-
/* VIDIOC_REQBUFS initiate user pointer I/O */
158+
/* VIDIOC_REQBUFS: try MMAP first (driver-managed DMA buffers).
159+
* Fall back to USERPTR if the driver does not support MMAP.
160+
*/
157161

158162
req.type = type;
159-
req.memory = V4L2_MEMORY_USERPTR;
163+
req.memory = V4L2_MEMORY_MMAP;
160164
req.count = buffernum;
161165
req.mode = buf_mode;
162166

163167
ret = ioctl(fd, VIDIOC_REQBUFS, (uintptr_t)&req);
164168
if (ret < 0)
165169
{
166-
printf("Failed to VIDIOC_REQBUFS: errno = %d\n", errno);
167-
return ret;
170+
req.memory = V4L2_MEMORY_USERPTR;
171+
ret = ioctl(fd, VIDIOC_REQBUFS, (uintptr_t)&req);
172+
if (ret < 0)
173+
{
174+
printf("Failed to VIDIOC_REQBUFS: errno = %d\n", errno);
175+
return ret;
176+
}
168177
}
169178

170-
/* Prepare video memory to store images */
179+
*memory = req.memory;
180+
181+
/* Prepare v_buffer array to track buffer metadata */
171182

172183
*vbuf = malloc(sizeof(v_buffer_t) * buffernum);
173184
if (!(*vbuf))
@@ -178,29 +189,54 @@ static int camera_prepare(int fd, enum v4l2_buf_type type,
178189

179190
for (cnt = 0; cnt < buffernum; cnt++)
180191
{
181-
(*vbuf)[cnt].length = buffersize;
192+
if (req.memory == V4L2_MEMORY_MMAP)
193+
{
194+
/* VIDIOC_QUERYBUF: get driver-allocated buffer metadata */
182195

183-
/* Note:
184-
* VIDIOC_QBUF set buffer pointer.
185-
* Buffer pointer must be 32bytes aligned.
186-
*/
196+
memset(&buf, 0, sizeof(v4l2_buffer_t));
197+
buf.type = type;
198+
buf.memory = V4L2_MEMORY_MMAP;
199+
buf.index = cnt;
200+
201+
ret = ioctl(fd, VIDIOC_QUERYBUF, (uintptr_t)&buf);
202+
if (ret < 0)
203+
{
204+
printf("Failed to VIDIOC_QUERYBUF %d: errno = %d\n",
205+
cnt, errno);
206+
free(*vbuf);
207+
*vbuf = NULL;
208+
return ret;
209+
}
187210

188-
(*vbuf)[cnt].start = memalign(32, buffersize);
189-
if (!(*vbuf)[cnt].start)
211+
(*vbuf)[cnt].start = NULL;
212+
(*vbuf)[cnt].length = buf.length;
213+
}
214+
else
190215
{
191-
printf("Out of memory for image buffer of %d/%d\n",
192-
cnt, buffernum);
216+
(*vbuf)[cnt].length = buffersize;
193217

194-
/* Release allocated memory. */
218+
/* Note:
219+
* VIDIOC_QBUF set buffer pointer.
220+
* Buffer pointer must be 32bytes aligned.
221+
*/
195222

196-
while (cnt--)
223+
(*vbuf)[cnt].start = memalign(32, buffersize);
224+
if (!(*vbuf)[cnt].start)
197225
{
198-
free((*vbuf)[cnt].start);
199-
}
226+
printf("Out of memory for image buffer of %d/%d\n",
227+
cnt, buffernum);
200228

201-
free(*vbuf);
202-
*vbuf = NULL;
203-
return ERROR;
229+
/* Release allocated memory. */
230+
231+
while (cnt--)
232+
{
233+
free((*vbuf)[cnt].start);
234+
}
235+
236+
free(*vbuf);
237+
*vbuf = NULL;
238+
return ERROR;
239+
}
204240
}
205241
}
206242

@@ -210,11 +246,15 @@ static int camera_prepare(int fd, enum v4l2_buf_type type,
210246
{
211247
memset(&buf, 0, sizeof(v4l2_buffer_t));
212248
buf.type = type;
213-
buf.memory = V4L2_MEMORY_USERPTR;
249+
buf.memory = req.memory;
214250
buf.index = cnt;
215-
buf.m.userptr = (uintptr_t)(*vbuf)[cnt].start;
216251
buf.length = (*vbuf)[cnt].length;
217252

253+
if (req.memory == V4L2_MEMORY_USERPTR)
254+
{
255+
buf.m.userptr = (uintptr_t)(*vbuf)[cnt].start;
256+
}
257+
218258
ret = ioctl(fd, VIDIOC_QBUF, (uintptr_t)&buf);
219259
if (ret)
220260
{
@@ -336,15 +376,15 @@ static int parse_arguments(int argc, FAR char *argv[],
336376
****************************************************************************/
337377

338378
static int get_camimage(int fd, FAR struct v4l2_buffer *v4l2_buf,
339-
enum v4l2_buf_type buf_type)
379+
enum v4l2_buf_type buf_type, uint32_t memory)
340380
{
341381
int ret;
342382

343383
/* VIDIOC_DQBUF acquires captured data. */
344384

345385
memset(v4l2_buf, 0, sizeof(v4l2_buffer_t));
346386
v4l2_buf->type = buf_type;
347-
v4l2_buf->memory = V4L2_MEMORY_USERPTR;
387+
v4l2_buf->memory = memory;
348388

349389
ret = ioctl(fd, VIDIOC_DQBUF, (uintptr_t)v4l2_buf);
350390
if (ret)
@@ -476,6 +516,8 @@ int main(int argc, FAR char *argv[])
476516

477517
FAR struct v_buffer *buffers_video = NULL;
478518
FAR struct v_buffer *buffers_still = NULL;
519+
uint32_t video_memory = V4L2_MEMORY_USERPTR;
520+
uint32_t still_memory = V4L2_MEMORY_USERPTR;
479521

480522
/* ===== Parse and Check arguments ===== */
481523

@@ -564,7 +606,8 @@ int main(int argc, FAR char *argv[])
564606
ret = camera_prepare(v_fd, V4L2_BUF_TYPE_STILL_CAPTURE,
565607
V4L2_BUF_MODE_FIFO, V4L2_PIX_FMT_JPEG,
566608
w, h,
567-
&buffers_still, STILL_BUFNUM, IMAGE_JPG_SIZE);
609+
&buffers_still, STILL_BUFNUM, IMAGE_JPG_SIZE,
610+
&still_memory);
568611
if (ret != OK)
569612
{
570613
goto exit_this_app;
@@ -588,7 +631,8 @@ int main(int argc, FAR char *argv[])
588631
ret = camera_prepare(v_fd, V4L2_BUF_TYPE_VIDEO_CAPTURE,
589632
V4L2_BUF_MODE_RING, V4L2_PIX_FMT_RGB565,
590633
VIDEO_HSIZE_QVGA, VIDEO_VSIZE_QVGA,
591-
&buffers_video, VIDEO_BUFNUM, IMAGE_RGB_SIZE);
634+
&buffers_video, VIDEO_BUFNUM, IMAGE_RGB_SIZE,
635+
&video_memory);
592636
if (ret != OK)
593637
{
594638
goto exit_this_app;
@@ -659,7 +703,8 @@ int main(int argc, FAR char *argv[])
659703

660704
case APP_STATE_BEFORE_CAPTURE:
661705
case APP_STATE_AFTER_CAPTURE:
662-
ret = get_camimage(v_fd, &v4l2_buf, V4L2_BUF_TYPE_VIDEO_CAPTURE);
706+
ret = get_camimage(v_fd, &v4l2_buf,
707+
V4L2_BUF_TYPE_VIDEO_CAPTURE, video_memory);
663708
if (ret != OK)
664709
{
665710
goto exit_this_app;
@@ -712,7 +757,10 @@ int main(int argc, FAR char *argv[])
712757

713758
while (capture_num)
714759
{
715-
ret = get_camimage(v_fd, &v4l2_buf, capture_type);
760+
ret = get_camimage(v_fd, &v4l2_buf, capture_type,
761+
capture_type ==
762+
V4L2_BUF_TYPE_STILL_CAPTURE ?
763+
still_memory : video_memory);
716764
if (ret != OK)
717765
{
718766
goto exit_this_app;

0 commit comments

Comments
 (0)