Skip to content

Commit 73e0f94

Browse files
committed
v4l2-m2m: support mplanes format
Add multi-plane format support for v4l2-m2m. Signed-off-by: niyinghao <niyinghao@xiaomi.com>
1 parent 684dcb9 commit 73e0f94

2 files changed

Lines changed: 139 additions & 29 deletions

File tree

drivers/video/v4l2_m2m.c

Lines changed: 136 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -351,8 +351,12 @@ static int codec_querybuf(FAR struct file *filep,
351351
FAR codec_mng_t *cmng = inode->i_private;
352352
FAR codec_file_t *cfile = filep->f_priv;
353353
FAR codec_type_inf_t *type_inf;
354+
struct v4l2_format format;
355+
uint32_t offset = 0;
356+
size_t bufsize;
357+
uint8_t i;
354358

355-
if (buf == NULL || buf->memory != V4L2_MEMORY_MMAP)
359+
if (buf == NULL)
356360
{
357361
return -EINVAL;
358362
}
@@ -368,22 +372,57 @@ static int codec_querybuf(FAR struct file *filep,
368372
return -EINVAL;
369373
}
370374

375+
memset(&format, 0, sizeof(format));
371376
if (V4L2_TYPE_IS_OUTPUT(buf->type))
372377
{
373-
buf->length = CODEC_OUTPUT_G_BUFSIZE(cmng->codec, cfile->priv);
374-
buf->m.offset = buf->length * buf->index;
378+
bufsize = CODEC_OUTPUT_G_BUFSIZE(cmng->codec, cfile->priv);
379+
CODEC_OUTPUT_G_FMT(cmng->codec, cfile->priv, &format);
375380
}
376381
else
377382
{
378-
buf->length = CODEC_CAPTURE_G_BUFSIZE(cmng->codec, cfile->priv);
379-
buf->m.offset = buf->length * buf->index + CAPTURE_BUF_OFFSET;
383+
offset = CAPTURE_BUF_OFFSET;
384+
bufsize = CODEC_CAPTURE_G_BUFSIZE(cmng->codec, cfile->priv);
385+
CODEC_CAPTURE_G_FMT(cmng->codec, cfile->priv, &format);
380386
}
381387

382-
if (buf->length == 0)
388+
if (bufsize == 0)
383389
{
384390
return -EINVAL;
385391
}
386392

393+
if (V4L2_TYPE_IS_MULTIPLANAR(buf->type))
394+
{
395+
for (i = 0; i < format.fmt.pix_mp.num_planes; i++)
396+
{
397+
switch (buf->memory)
398+
{
399+
case V4L2_MEMORY_MMAP:
400+
buf->m.planes[i].length =
401+
format.fmt.pix_mp.plane_fmt[i].sizeimage;
402+
buf->m.planes[i].m.mem_offset =
403+
offset + bufsize * buf->index;
404+
offset += buf->m.planes[i].length;
405+
break;
406+
407+
default:
408+
return -EINVAL;
409+
}
410+
}
411+
}
412+
else
413+
{
414+
switch (buf->memory)
415+
{
416+
case V4L2_MEMORY_MMAP:
417+
buf->length = bufsize;
418+
buf->m.offset = offset + bufsize * buf->index;
419+
break;
420+
421+
default:
422+
return -EINVAL;
423+
}
424+
}
425+
387426
return OK;
388427
}
389428

@@ -395,7 +434,9 @@ static int codec_qbuf(FAR struct file *filep,
395434
FAR codec_file_t *cfile = filep->f_priv;
396435
FAR codec_type_inf_t *type_inf;
397436
FAR vbuf_container_t *container;
398-
size_t buf_size;
437+
struct v4l2_format format;
438+
uint32_t offset = 0;
439+
uint8_t i;
399440

400441
if (buf == NULL)
401442
{
@@ -415,28 +456,51 @@ static int codec_qbuf(FAR struct file *filep,
415456
return -EAGAIN;
416457
}
417458

418-
memcpy(&container->buf, buf, sizeof(struct v4l2_buffer));
419-
if (buf->memory == V4L2_MEMORY_MMAP)
459+
memset(&format, 0, sizeof(format));
460+
if (V4L2_TYPE_IS_OUTPUT(buf->type))
420461
{
421-
/* only use userptr inside the container */
462+
CODEC_OUTPUT_G_FMT(cmng->codec, cfile->priv, &format);
463+
}
464+
else
465+
{
466+
offset = CAPTURE_BUF_OFFSET;
467+
CODEC_CAPTURE_G_FMT(cmng->codec, cfile->priv, &format);
468+
}
422469

423-
if (V4L2_TYPE_IS_OUTPUT(buf->type))
470+
memcpy(&container->buf, buf, sizeof(struct v4l2_buffer));
471+
472+
if (V4L2_TYPE_IS_MULTIPLANAR(buf->type))
473+
{
474+
memcpy(container->planes, buf->m.planes,
475+
sizeof(struct v4l2_plane) * format.fmt.pix_mp.num_planes);
476+
container->buf.m.planes = container->planes;
477+
for (i = 0; i < format.fmt.pix_mp.num_planes; i++)
424478
{
425-
buf_size = CODEC_OUTPUT_G_BUFSIZE(cmng->codec, cfile->priv);
479+
switch (container->buf.memory)
480+
{
481+
case V4L2_MEMORY_MMAP:
482+
container->buf.m.planes[i].m.vaddr =
483+
(FAR void *)(buf->m.planes[i].m.mem_offset -
484+
offset + type_inf->bufheap);
485+
break;
486+
487+
default:
488+
return -EINVAL;
489+
}
426490
}
427-
else
491+
}
492+
else
493+
{
494+
switch (buf->memory)
428495
{
429-
buf_size = CODEC_CAPTURE_G_BUFSIZE(cmng->codec, cfile->priv);
430-
}
496+
case V4L2_MEMORY_MMAP:
497+
container->buf.m.vaddr =
498+
(FAR void *)(type_inf->bufheap + buf->m.offset - offset);
499+
break;
431500

432-
if (buf_size == 0)
433-
{
434-
return -EINVAL;
501+
default:
502+
return -EINVAL;
435503
}
436-
437-
container->buf.length = buf_size;
438-
container->buf.m.vaddr = type_inf->bufheap +
439-
container->buf.length * buf->index;
440504
}
441505

442506
video_framebuff_queue_container(&type_inf->bufinf, container);
@@ -454,9 +518,15 @@ static int codec_qbuf(FAR struct file *filep,
454518
static int codec_dqbuf(FAR struct file *filep,
455519
FAR struct v4l2_buffer *buf)
456520
{
521+
FAR struct v4l2_plane *plans = buf->m.planes;
522+
FAR struct inode *inode = filep->f_inode;
523+
FAR codec_mng_t *cmng = inode->i_private;
457524
FAR codec_file_t *cfile = filep->f_priv;
458525
FAR codec_type_inf_t *type_inf;
459526
FAR vbuf_container_t *container;
527+
struct v4l2_format format;
528+
uint32_t offset = 0;
529+
uint8_t i;
460530

461531
if (buf == NULL)
462532
{
@@ -480,15 +550,54 @@ static int codec_dqbuf(FAR struct file *filep,
480550
return -EAGAIN;
481551
}
482552

483-
memcpy(buf, &container->buf, sizeof(struct v4l2_buffer));
484-
video_framebuff_free_container(&type_inf->bufinf, container);
553+
memset(&format, 0, sizeof(format));
554+
if (V4L2_TYPE_IS_OUTPUT(buf->type))
555+
{
556+
CODEC_OUTPUT_G_FMT(cmng->codec, cfile->priv, &format);
557+
}
558+
else
559+
{
560+
offset = CAPTURE_BUF_OFFSET;
561+
CODEC_CAPTURE_G_FMT(cmng->codec, cfile->priv, &format);
562+
}
485563

486-
if (buf->memory == V4L2_MEMORY_MMAP)
564+
memcpy(buf, &container->buf, sizeof(struct v4l2_buffer));
565+
if (V4L2_TYPE_IS_MULTIPLANAR(buf->type))
566+
{
567+
buf->m.planes = plans;
568+
memcpy(plans, container->planes,
569+
sizeof(struct v4l2_plane) * format.fmt.pix_mp.num_planes);
570+
for (i = 0; i < format.fmt.pix_mp.num_planes; i++)
571+
{
572+
switch (container->buf.memory)
573+
{
574+
case V4L2_MEMORY_MMAP:
575+
buf->m.planes[i].m.mem_offset = (uint32_t)
576+
((uint8_t *)buf->m.planes[i].m.vaddr -
577+
type_inf->bufheap + offset);
578+
break;
579+
580+
default:
581+
return -EINVAL;
582+
}
583+
}
584+
}
585+
else
487586
{
488-
buf->m.offset = buf->length * buf->index +
489-
V4L2_TYPE_IS_OUTPUT(buf->type) ? 0 : CAPTURE_BUF_OFFSET;
587+
switch (container->buf.memory)
588+
{
589+
case V4L2_MEMORY_MMAP:
590+
buf->m.offset = (uint32_t)((uint8_t *)buf->m.vaddr -
591+
type_inf->bufheap + offset);
592+
break;
593+
594+
default:
595+
return -EINVAL;
596+
}
490597
}
491598

599+
video_framebuff_free_container(&type_inf->bufinf, container);
600+
492601
vinfo("%s dequeue done\n", V4L2_TYPE_IS_OUTPUT(buf->type) ?
493602
"output" : "capture");
494603

drivers/video/video_framebuff.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,8 +38,9 @@
3838

3939
struct vbuf_container_s
4040
{
41-
struct v4l2_buffer buf; /* Buffer information */
42-
struct vbuf_container_s *next; /* Pointer to next buffer */
41+
struct v4l2_buffer buf; /* Buffer information */
42+
struct v4l2_plane planes[VIDEO_MAX_PLANES]; /* Buffer planes */
43+
struct vbuf_container_s *next; /* Pointer to next buffer */
4344
};
4445

4546
typedef struct vbuf_container_s vbuf_container_t;

0 commit comments

Comments
 (0)