Skip to content

Commit 5c36887

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 a13b43c commit 5c36887

2 files changed

Lines changed: 136 additions & 29 deletions

File tree

drivers/video/v4l2_m2m.c

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

356-
if (buf == NULL || buf->memory != V4L2_MEMORY_MMAP)
360+
if (buf == NULL)
357361
{
358362
return -EINVAL;
359363
}
@@ -371,20 +375,54 @@ static int codec_querybuf(FAR struct file *filep,
371375

372376
if (V4L2_TYPE_IS_OUTPUT(buf->type))
373377
{
374-
buf->length = CODEC_OUTPUT_G_BUFSIZE(cmng->codec, cfile->priv);
375-
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);
376380
}
377381
else
378382
{
379-
buf->length = CODEC_CAPTURE_G_BUFSIZE(cmng->codec, cfile->priv);
380-
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);
381386
}
382387

383-
if (buf->length == 0)
388+
if (bufsize == 0)
384389
{
385390
return -EINVAL;
386391
}
387392

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+
388426
return OK;
389427
}
390428

@@ -396,7 +434,9 @@ static int codec_qbuf(FAR struct file *filep,
396434
FAR codec_file_t *cfile = filep->f_priv;
397435
FAR codec_type_inf_t *type_inf;
398436
FAR vbuf_container_t *container;
399-
size_t buf_size;
437+
struct v4l2_format format;
438+
uint32_t offset = 0;
439+
uint8_t i;
400440

401441
if (buf == NULL)
402442
{
@@ -416,28 +456,50 @@ static int codec_qbuf(FAR struct file *filep,
416456
return -EAGAIN;
417457
}
418458

419-
memcpy(&container->buf, buf, sizeof(struct v4l2_buffer));
420-
if (buf->memory == V4L2_MEMORY_MMAP)
459+
if (V4L2_TYPE_IS_OUTPUT(buf->type))
421460
{
422-
/* only use userptr inside the container */
461+
CODEC_OUTPUT_G_FMT(cmng->codec, cfile->priv, &format);
462+
}
463+
else
464+
{
465+
offset = CAPTURE_BUF_OFFSET;
466+
CODEC_CAPTURE_G_FMT(cmng->codec, cfile->priv, &format);
467+
}
423468

424-
if (V4L2_TYPE_IS_OUTPUT(buf->type))
469+
memcpy(&container->buf, buf, sizeof(struct v4l2_buffer));
470+
471+
if (V4L2_TYPE_IS_MULTIPLANAR(buf->type))
472+
{
473+
memcpy(container->planes, buf->m.planes,
474+
sizeof(struct v4l2_plane) * format.fmt.pix_mp.num_planes);
475+
container->buf.m.planes = container->planes;
476+
for (i = 0; i < format.fmt.pix_mp.num_planes; i++)
425477
{
426-
buf_size = CODEC_OUTPUT_G_BUFSIZE(cmng->codec, cfile->priv);
478+
switch (container->buf.memory)
479+
{
480+
case V4L2_MEMORY_MMAP:
481+
container->buf.m.planes[i].m.vaddr =
482+
(FAR void *)(buf->m.planes[i].m.mem_offset -
483+
offset + type_inf->bufheap);
484+
break;
485+
486+
default:
487+
return -EINVAL;
488+
}
427489
}
428-
else
490+
}
491+
else
492+
{
493+
switch (buf->memory)
429494
{
430-
buf_size = CODEC_CAPTURE_G_BUFSIZE(cmng->codec, cfile->priv);
431-
}
495+
case V4L2_MEMORY_MMAP:
496+
container->buf.m.vaddr =
497+
(FAR void *)(type_inf->bufheap + buf->m.offset - offset);
498+
break;
432499

433-
if (buf_size == 0)
434-
{
435-
return -EINVAL;
500+
default:
501+
return -EINVAL;
436502
}
437-
438-
container->buf.length = buf_size;
439-
container->buf.m.vaddr = type_inf->bufheap +
440-
container->buf.length * buf->index;
441503
}
442504

443505
video_framebuff_queue_container(&type_inf->bufinf, container);
@@ -455,10 +517,16 @@ static int codec_qbuf(FAR struct file *filep,
455517
static int codec_dqbuf(FAR struct file *filep,
456518
FAR struct v4l2_buffer *buf)
457519
{
520+
FAR struct v4l2_plane *plans = buf->m.planes;
521+
FAR struct inode *inode = filep->f_inode;
522+
FAR codec_mng_t *cmng = inode->i_private;
458523
FAR codec_file_t *cfile = filep->f_priv;
459524
FAR codec_type_inf_t *type_inf;
460525
FAR vbuf_container_t *container;
461526
irqstate_t flags;
527+
struct v4l2_format format;
528+
uint32_t offset = 0;
529+
uint8_t i;
462530

463531
if (buf == NULL)
464532
{
@@ -486,15 +554,53 @@ static int codec_dqbuf(FAR struct file *filep,
486554
return -EAGAIN;
487555
}
488556

489-
memcpy(buf, &container->buf, sizeof(struct v4l2_buffer));
490-
video_framebuff_free_container(&type_inf->bufinf, container);
557+
if (V4L2_TYPE_IS_OUTPUT(buf->type))
558+
{
559+
CODEC_OUTPUT_G_FMT(cmng->codec, cfile->priv, &format);
560+
}
561+
else
562+
{
563+
offset = CAPTURE_BUF_OFFSET;
564+
CODEC_CAPTURE_G_FMT(cmng->codec, cfile->priv, &format);
565+
}
491566

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

602+
video_framebuff_free_container(&type_inf->bufinf, container);
603+
498604
vinfo("%s dequeue done\n", V4L2_TYPE_IS_OUTPUT(buf->type) ?
499605
"output" : "capture");
500606

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)