Message ID | 20180720065901.56269-1-keiichiw@chromium.org (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
On 07/20/2018 08:59 AM, Keiichi Watanabe wrote: > Support multi-planar APIs in the virtual codec driver. > Multi-planar APIs are enabled by the module parameter 'multiplanar'. > > Signed-off-by: Keiichi Watanabe <keiichiw@chromium.org> Thank you for contributing this code! I've folded it into patch series (I just posted v2) and added a Co-Developed-by tag. BTW, for future reference: always run v4l2-compliance after making driver changes. It caught a bunch of missing checks in this code. I've fixed those, but you should always check V4L2 driver changes with v4l2-compliance. Regards, Hans > --- > drivers/media/platform/vicodec/vicodec-core.c | 219 ++++++++++++++---- > 1 file changed, 171 insertions(+), 48 deletions(-) > > diff --git a/drivers/media/platform/vicodec/vicodec-core.c b/drivers/media/platform/vicodec/vicodec-core.c > index 12c12cb0c1c0..1717f44e1743 100644 > --- a/drivers/media/platform/vicodec/vicodec-core.c > +++ b/drivers/media/platform/vicodec/vicodec-core.c > @@ -29,6 +29,11 @@ MODULE_DESCRIPTION("Virtual codec device"); > MODULE_AUTHOR("Hans Verkuil <hans.verkuil@cisco.com>"); > MODULE_LICENSE("GPL v2"); > > +static bool multiplanar; > +module_param(multiplanar, bool, 0444); > +MODULE_PARM_DESC(multiplanar, > + " use multi-planar API instead of single-planar API"); > + > static unsigned int debug; > module_param(debug, uint, 0644); > MODULE_PARM_DESC(debug, "activates debug info"); > @@ -135,8 +140,10 @@ static struct vicodec_q_data *get_q_data(struct vicodec_ctx *ctx, > { > switch (type) { > case V4L2_BUF_TYPE_VIDEO_OUTPUT: > + case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE: > return &ctx->q_data[V4L2_M2M_SRC]; > case V4L2_BUF_TYPE_VIDEO_CAPTURE: > + case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE: > return &ctx->q_data[V4L2_M2M_DST]; > default: > WARN_ON(1); > @@ -530,7 +537,10 @@ static int vidioc_querycap(struct file *file, void *priv, > strncpy(cap->card, VICODEC_NAME, sizeof(cap->card) - 1); > snprintf(cap->bus_info, sizeof(cap->bus_info), > "platform:%s", VICODEC_NAME); > - cap->device_caps = V4L2_CAP_VIDEO_M2M | V4L2_CAP_STREAMING; > + cap->device_caps = V4L2_CAP_STREAMING | > + (multiplanar ? > + V4L2_CAP_VIDEO_M2M_MPLANE : > + V4L2_CAP_VIDEO_M2M); > cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS; > return 0; > } > @@ -576,20 +586,44 @@ static int vidioc_g_fmt(struct vicodec_ctx *ctx, struct v4l2_format *f) > > q_data = get_q_data(ctx, f->type); > > - f->fmt.pix.width = q_data->width; > - f->fmt.pix.height = q_data->height; > - f->fmt.pix.field = V4L2_FIELD_NONE; > - f->fmt.pix.pixelformat = q_data->fourcc; > - if (q_data->fourcc == V4L2_PIX_FMT_FWHT) > - f->fmt.pix.bytesperline = 0; > - else > - f->fmt.pix.bytesperline = q_data->width; > - f->fmt.pix.sizeimage = q_data->sizeimage; > - f->fmt.pix.colorspace = ctx->colorspace; > - f->fmt.pix.xfer_func = ctx->xfer_func; > - f->fmt.pix.ycbcr_enc = ctx->ycbcr_enc; > - f->fmt.pix.quantization = ctx->quantization; > + switch (f->type) { > + case V4L2_BUF_TYPE_VIDEO_CAPTURE: > + case V4L2_BUF_TYPE_VIDEO_OUTPUT: > + f->fmt.pix.width = q_data->width; > + f->fmt.pix.height = q_data->height; > + f->fmt.pix.field = V4L2_FIELD_NONE; > + f->fmt.pix.pixelformat = q_data->fourcc; > + if (q_data->fourcc == V4L2_PIX_FMT_FWHT) > + f->fmt.pix.bytesperline = 0; > + else > + f->fmt.pix.bytesperline = q_data->width; > + f->fmt.pix.sizeimage = q_data->sizeimage; > + f->fmt.pix.colorspace = ctx->colorspace; > + f->fmt.pix.xfer_func = ctx->xfer_func; > + f->fmt.pix.ycbcr_enc = ctx->ycbcr_enc; > + f->fmt.pix.quantization = ctx->quantization; > + break; > > + case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE: > + case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE: > + f->fmt.pix_mp.width = q_data->width; > + f->fmt.pix_mp.height = q_data->height; > + f->fmt.pix_mp.field = V4L2_FIELD_NONE; > + f->fmt.pix_mp.pixelformat = q_data->fourcc; > + f->fmt.pix_mp.num_planes = 1; > + if (q_data->fourcc == V4L2_PIX_FMT_FWHT) > + f->fmt.pix_mp.plane_fmt[0].bytesperline = 0; > + else > + f->fmt.pix_mp.plane_fmt[0].bytesperline = q_data->width; > + f->fmt.pix_mp.plane_fmt[0].sizeimage = q_data->sizeimage; > + f->fmt.pix_mp.colorspace = ctx->colorspace; > + f->fmt.pix_mp.xfer_func = ctx->xfer_func; > + f->fmt.pix_mp.ycbcr_enc = ctx->ycbcr_enc; > + f->fmt.pix_mp.quantization = ctx->quantization; > + break; > + default: > + return -EINVAL; > + } > return 0; > } > > @@ -607,16 +641,41 @@ static int vidioc_g_fmt_vid_cap(struct file *file, void *priv, > > static int vidioc_try_fmt(struct vicodec_ctx *ctx, struct v4l2_format *f) > { > - struct v4l2_pix_format *pix = &f->fmt.pix; > - > - pix->width = clamp(pix->width, MIN_WIDTH, MAX_WIDTH) & ~7; > - pix->height = clamp(pix->height, MIN_HEIGHT, MAX_HEIGHT) & ~7; > - pix->bytesperline = pix->width; > - pix->sizeimage = pix->width * pix->height * 3 / 2; > - pix->field = V4L2_FIELD_NONE; > - if (pix->pixelformat == V4L2_PIX_FMT_FWHT) { > - pix->bytesperline = 0; > - pix->sizeimage += sizeof(struct cframe_hdr); > + struct v4l2_pix_format *pix; > + struct v4l2_pix_format_mplane *pix_mp; > + > + switch (f->type) { > + case V4L2_BUF_TYPE_VIDEO_CAPTURE: > + case V4L2_BUF_TYPE_VIDEO_OUTPUT: > + pix = &f->fmt.pix; > + pix->width = clamp(pix->width, MIN_WIDTH, MAX_WIDTH) & ~7; > + pix->height = clamp(pix->height, MIN_HEIGHT, MAX_HEIGHT) & ~7; > + pix->bytesperline = pix->width; > + pix->sizeimage = pix->width * pix->height * 3 / 2; > + pix->field = V4L2_FIELD_NONE; > + if (pix->pixelformat == V4L2_PIX_FMT_FWHT) { > + pix->bytesperline = 0; > + pix->sizeimage += sizeof(struct cframe_hdr); > + } > + break; > + case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE: > + case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE: > + pix_mp = &f->fmt.pix_mp; > + pix_mp->width = clamp(pix_mp->width, MIN_WIDTH, MAX_WIDTH) & ~7; > + pix_mp->height = > + clamp(pix_mp->height, MIN_HEIGHT, MAX_HEIGHT) & ~7; > + pix_mp->plane_fmt[0].bytesperline = pix_mp->width; > + pix_mp->plane_fmt[0].sizeimage = > + pix_mp->width * pix_mp->height * 3 / 2; > + pix_mp->field = V4L2_FIELD_NONE; > + if (pix_mp->pixelformat == V4L2_PIX_FMT_FWHT) { > + pix_mp->plane_fmt[0].bytesperline = 0; > + pix_mp->plane_fmt[0].sizeimage += > + sizeof(struct cframe_hdr); > + } > + break; > + default: > + return -EINVAL; > } > > return 0; > @@ -627,12 +686,26 @@ static int vidioc_try_fmt_vid_cap(struct file *file, void *priv, > { > struct vicodec_ctx *ctx = file2ctx(file); > > - f->fmt.pix.pixelformat = ctx->is_enc ? V4L2_PIX_FMT_FWHT : > - find_fmt(f->fmt.pix.pixelformat); > - f->fmt.pix.colorspace = ctx->colorspace; > - f->fmt.pix.xfer_func = ctx->xfer_func; > - f->fmt.pix.ycbcr_enc = ctx->ycbcr_enc; > - f->fmt.pix.quantization = ctx->quantization; > + switch (f->type) { > + case V4L2_BUF_TYPE_VIDEO_CAPTURE: > + f->fmt.pix.pixelformat = ctx->is_enc ? V4L2_PIX_FMT_FWHT : > + find_fmt(f->fmt.pix.pixelformat); > + f->fmt.pix.colorspace = ctx->colorspace; > + f->fmt.pix.xfer_func = ctx->xfer_func; > + f->fmt.pix.ycbcr_enc = ctx->ycbcr_enc; > + f->fmt.pix.quantization = ctx->quantization; > + break; > + case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE: > + f->fmt.pix_mp.pixelformat = ctx->is_enc ? V4L2_PIX_FMT_FWHT : > + find_fmt(f->fmt.pix_mp.pixelformat); > + f->fmt.pix_mp.colorspace = ctx->colorspace; > + f->fmt.pix_mp.xfer_func = ctx->xfer_func; > + f->fmt.pix_mp.ycbcr_enc = ctx->ycbcr_enc; > + f->fmt.pix_mp.quantization = ctx->quantization; > + break; > + default: > + return -EINVAL; > + } > > return vidioc_try_fmt(ctx, f); > } > @@ -642,10 +715,22 @@ static int vidioc_try_fmt_vid_out(struct file *file, void *priv, > { > struct vicodec_ctx *ctx = file2ctx(file); > > - f->fmt.pix.pixelformat = !ctx->is_enc ? V4L2_PIX_FMT_FWHT : > - find_fmt(f->fmt.pix.pixelformat); > - if (!f->fmt.pix.colorspace) > - f->fmt.pix.colorspace = V4L2_COLORSPACE_REC709; > + switch (f->type) { > + case V4L2_BUF_TYPE_VIDEO_OUTPUT: > + f->fmt.pix.pixelformat = !ctx->is_enc ? V4L2_PIX_FMT_FWHT : > + find_fmt(f->fmt.pix.pixelformat); > + if (!f->fmt.pix.colorspace) > + f->fmt.pix.colorspace = V4L2_COLORSPACE_REC709; > + break; > + case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE: > + f->fmt.pix_mp.pixelformat = !ctx->is_enc ? V4L2_PIX_FMT_FWHT : > + find_fmt(f->fmt.pix_mp.pixelformat); > + if (!f->fmt.pix_mp.colorspace) > + f->fmt.pix_mp.colorspace = V4L2_COLORSPACE_REC709; > + break; > + default: > + return -EINVAL; > + } > > return vidioc_try_fmt(ctx, f); > } > @@ -664,18 +749,42 @@ static int vidioc_s_fmt(struct vicodec_ctx *ctx, struct v4l2_format *f) > if (!q_data) > return -EINVAL; > > - if (ctx->is_enc && V4L2_TYPE_IS_OUTPUT(f->type)) > - fmt_changed = q_data->fourcc != f->fmt.pix.pixelformat || > - q_data->width != f->fmt.pix.width || > - q_data->height != f->fmt.pix.height; > - > - if (vb2_is_busy(vq) && fmt_changed) > - return -EBUSY; > - > - q_data->fourcc = f->fmt.pix.pixelformat; > - q_data->width = f->fmt.pix.width; > - q_data->height = f->fmt.pix.height; > - q_data->sizeimage = f->fmt.pix.sizeimage; > + switch (f->type) { > + case V4L2_BUF_TYPE_VIDEO_CAPTURE: > + case V4L2_BUF_TYPE_VIDEO_OUTPUT: > + if (ctx->is_enc && V4L2_TYPE_IS_OUTPUT(f->type)) > + fmt_changed = > + q_data->fourcc != f->fmt.pix.pixelformat || > + q_data->width != f->fmt.pix.width || > + q_data->height != f->fmt.pix.height; > + > + if (vb2_is_busy(vq) && fmt_changed) > + return -EBUSY; > + > + q_data->fourcc = f->fmt.pix.pixelformat; > + q_data->width = f->fmt.pix.width; > + q_data->height = f->fmt.pix.height; > + q_data->sizeimage = f->fmt.pix.sizeimage; > + break; > + case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE: > + case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE: > + if (ctx->is_enc && V4L2_TYPE_IS_OUTPUT(f->type)) > + fmt_changed = > + q_data->fourcc != f->fmt.pix_mp.pixelformat || > + q_data->width != f->fmt.pix_mp.width || > + q_data->height != f->fmt.pix_mp.height; > + > + if (vb2_is_busy(vq) && fmt_changed) > + return -EBUSY; > + > + q_data->fourcc = f->fmt.pix_mp.pixelformat; > + q_data->width = f->fmt.pix_mp.width; > + q_data->height = f->fmt.pix_mp.height; > + q_data->sizeimage = f->fmt.pix_mp.plane_fmt[0].sizeimage; > + break; > + default: > + return -EINVAL; > + } > > dprintk(ctx->dev, > "Setting format for type %d, wxh: %dx%d, fourcc: %08x\n", > @@ -832,11 +941,21 @@ static const struct v4l2_ioctl_ops vicodec_ioctl_ops = { > .vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap, > .vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap, > > + .vidioc_enum_fmt_vid_cap_mplane = vidioc_enum_fmt_vid_cap, > + .vidioc_g_fmt_vid_cap_mplane = vidioc_g_fmt_vid_cap, > + .vidioc_try_fmt_vid_cap_mplane = vidioc_try_fmt_vid_cap, > + .vidioc_s_fmt_vid_cap_mplane = vidioc_s_fmt_vid_cap, > + > .vidioc_enum_fmt_vid_out = vidioc_enum_fmt_vid_out, > .vidioc_g_fmt_vid_out = vidioc_g_fmt_vid_out, > .vidioc_try_fmt_vid_out = vidioc_try_fmt_vid_out, > .vidioc_s_fmt_vid_out = vidioc_s_fmt_vid_out, > > + .vidioc_enum_fmt_vid_out_mplane = vidioc_enum_fmt_vid_out, > + .vidioc_g_fmt_vid_out_mplane = vidioc_g_fmt_vid_out, > + .vidioc_try_fmt_vid_out_mplane = vidioc_try_fmt_vid_out, > + .vidioc_s_fmt_vid_out_mplane = vidioc_s_fmt_vid_out, > + > .vidioc_reqbufs = v4l2_m2m_ioctl_reqbufs, > .vidioc_querybuf = v4l2_m2m_ioctl_querybuf, > .vidioc_qbuf = v4l2_m2m_ioctl_qbuf, > @@ -1002,7 +1121,9 @@ static int queue_init(void *priv, struct vb2_queue *src_vq, > struct vicodec_ctx *ctx = priv; > int ret; > > - src_vq->type = V4L2_BUF_TYPE_VIDEO_OUTPUT; > + src_vq->type = (multiplanar ? > + V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE : > + V4L2_BUF_TYPE_VIDEO_OUTPUT); > src_vq->io_modes = VB2_MMAP | VB2_USERPTR | VB2_DMABUF; > src_vq->drv_priv = ctx; > src_vq->buf_struct_size = sizeof(struct v4l2_m2m_buffer); > @@ -1016,7 +1137,9 @@ static int queue_init(void *priv, struct vb2_queue *src_vq, > if (ret) > return ret; > > - dst_vq->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; > + dst_vq->type = (multiplanar ? > + V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE : > + V4L2_BUF_TYPE_VIDEO_CAPTURE); > dst_vq->io_modes = VB2_MMAP | VB2_USERPTR | VB2_DMABUF; > dst_vq->drv_priv = ctx; > dst_vq->buf_struct_size = sizeof(struct v4l2_m2m_buffer); > -- > 2.18.0.233.g985f88cf7e-goog > > This is an additional patch to Hans's patch series of the new vicodec driver. > This patch adds multi-planar API support. I confirmed that v4l2-ctl uses > multi-planar APIs to decode a FWHT format video when vicodec module is loaded > with module parameter 'multiplanar'. >
On Fri, Jul 20, 2018 at 5:30 PM, Hans Verkuil <hverkuil@xs4all.nl> wrote: > On 07/20/2018 08:59 AM, Keiichi Watanabe wrote: >> Support multi-planar APIs in the virtual codec driver. >> Multi-planar APIs are enabled by the module parameter 'multiplanar'. >> >> Signed-off-by: Keiichi Watanabe <keiichiw@chromium.org> > > Thank you for contributing this code! I've folded it into patch series > (I just posted v2) and added a Co-Developed-by tag. > Thanks, Hans! That sounds good. > BTW, for future reference: always run v4l2-compliance after making driver > changes. It caught a bunch of missing checks in this code. I've fixed those, > but you should always check V4L2 driver changes with v4l2-compliance. > Sorry for the inconvenience. I'll use v4l2-compliance next time. Best regards, Keiichi > Regards, > > Hans > >> --- >> drivers/media/platform/vicodec/vicodec-core.c | 219 ++++++++++++++---- >> 1 file changed, 171 insertions(+), 48 deletions(-) >> >> diff --git a/drivers/media/platform/vicodec/vicodec-core.c b/drivers/media/platform/vicodec/vicodec-core.c >> index 12c12cb0c1c0..1717f44e1743 100644 >> --- a/drivers/media/platform/vicodec/vicodec-core.c >> +++ b/drivers/media/platform/vicodec/vicodec-core.c >> @@ -29,6 +29,11 @@ MODULE_DESCRIPTION("Virtual codec device"); >> MODULE_AUTHOR("Hans Verkuil <hans.verkuil@cisco.com>"); >> MODULE_LICENSE("GPL v2"); >> >> +static bool multiplanar; >> +module_param(multiplanar, bool, 0444); >> +MODULE_PARM_DESC(multiplanar, >> + " use multi-planar API instead of single-planar API"); >> + >> static unsigned int debug; >> module_param(debug, uint, 0644); >> MODULE_PARM_DESC(debug, "activates debug info"); >> @@ -135,8 +140,10 @@ static struct vicodec_q_data *get_q_data(struct vicodec_ctx *ctx, >> { >> switch (type) { >> case V4L2_BUF_TYPE_VIDEO_OUTPUT: >> + case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE: >> return &ctx->q_data[V4L2_M2M_SRC]; >> case V4L2_BUF_TYPE_VIDEO_CAPTURE: >> + case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE: >> return &ctx->q_data[V4L2_M2M_DST]; >> default: >> WARN_ON(1); >> @@ -530,7 +537,10 @@ static int vidioc_querycap(struct file *file, void *priv, >> strncpy(cap->card, VICODEC_NAME, sizeof(cap->card) - 1); >> snprintf(cap->bus_info, sizeof(cap->bus_info), >> "platform:%s", VICODEC_NAME); >> - cap->device_caps = V4L2_CAP_VIDEO_M2M | V4L2_CAP_STREAMING; >> + cap->device_caps = V4L2_CAP_STREAMING | >> + (multiplanar ? >> + V4L2_CAP_VIDEO_M2M_MPLANE : >> + V4L2_CAP_VIDEO_M2M); >> cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS; >> return 0; >> } >> @@ -576,20 +586,44 @@ static int vidioc_g_fmt(struct vicodec_ctx *ctx, struct v4l2_format *f) >> >> q_data = get_q_data(ctx, f->type); >> >> - f->fmt.pix.width = q_data->width; >> - f->fmt.pix.height = q_data->height; >> - f->fmt.pix.field = V4L2_FIELD_NONE; >> - f->fmt.pix.pixelformat = q_data->fourcc; >> - if (q_data->fourcc == V4L2_PIX_FMT_FWHT) >> - f->fmt.pix.bytesperline = 0; >> - else >> - f->fmt.pix.bytesperline = q_data->width; >> - f->fmt.pix.sizeimage = q_data->sizeimage; >> - f->fmt.pix.colorspace = ctx->colorspace; >> - f->fmt.pix.xfer_func = ctx->xfer_func; >> - f->fmt.pix.ycbcr_enc = ctx->ycbcr_enc; >> - f->fmt.pix.quantization = ctx->quantization; >> + switch (f->type) { >> + case V4L2_BUF_TYPE_VIDEO_CAPTURE: >> + case V4L2_BUF_TYPE_VIDEO_OUTPUT: >> + f->fmt.pix.width = q_data->width; >> + f->fmt.pix.height = q_data->height; >> + f->fmt.pix.field = V4L2_FIELD_NONE; >> + f->fmt.pix.pixelformat = q_data->fourcc; >> + if (q_data->fourcc == V4L2_PIX_FMT_FWHT) >> + f->fmt.pix.bytesperline = 0; >> + else >> + f->fmt.pix.bytesperline = q_data->width; >> + f->fmt.pix.sizeimage = q_data->sizeimage; >> + f->fmt.pix.colorspace = ctx->colorspace; >> + f->fmt.pix.xfer_func = ctx->xfer_func; >> + f->fmt.pix.ycbcr_enc = ctx->ycbcr_enc; >> + f->fmt.pix.quantization = ctx->quantization; >> + break; >> >> + case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE: >> + case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE: >> + f->fmt.pix_mp.width = q_data->width; >> + f->fmt.pix_mp.height = q_data->height; >> + f->fmt.pix_mp.field = V4L2_FIELD_NONE; >> + f->fmt.pix_mp.pixelformat = q_data->fourcc; >> + f->fmt.pix_mp.num_planes = 1; >> + if (q_data->fourcc == V4L2_PIX_FMT_FWHT) >> + f->fmt.pix_mp.plane_fmt[0].bytesperline = 0; >> + else >> + f->fmt.pix_mp.plane_fmt[0].bytesperline = q_data->width; >> + f->fmt.pix_mp.plane_fmt[0].sizeimage = q_data->sizeimage; >> + f->fmt.pix_mp.colorspace = ctx->colorspace; >> + f->fmt.pix_mp.xfer_func = ctx->xfer_func; >> + f->fmt.pix_mp.ycbcr_enc = ctx->ycbcr_enc; >> + f->fmt.pix_mp.quantization = ctx->quantization; >> + break; >> + default: >> + return -EINVAL; >> + } >> return 0; >> } >> >> @@ -607,16 +641,41 @@ static int vidioc_g_fmt_vid_cap(struct file *file, void *priv, >> >> static int vidioc_try_fmt(struct vicodec_ctx *ctx, struct v4l2_format *f) >> { >> - struct v4l2_pix_format *pix = &f->fmt.pix; >> - >> - pix->width = clamp(pix->width, MIN_WIDTH, MAX_WIDTH) & ~7; >> - pix->height = clamp(pix->height, MIN_HEIGHT, MAX_HEIGHT) & ~7; >> - pix->bytesperline = pix->width; >> - pix->sizeimage = pix->width * pix->height * 3 / 2; >> - pix->field = V4L2_FIELD_NONE; >> - if (pix->pixelformat == V4L2_PIX_FMT_FWHT) { >> - pix->bytesperline = 0; >> - pix->sizeimage += sizeof(struct cframe_hdr); >> + struct v4l2_pix_format *pix; >> + struct v4l2_pix_format_mplane *pix_mp; >> + >> + switch (f->type) { >> + case V4L2_BUF_TYPE_VIDEO_CAPTURE: >> + case V4L2_BUF_TYPE_VIDEO_OUTPUT: >> + pix = &f->fmt.pix; >> + pix->width = clamp(pix->width, MIN_WIDTH, MAX_WIDTH) & ~7; >> + pix->height = clamp(pix->height, MIN_HEIGHT, MAX_HEIGHT) & ~7; >> + pix->bytesperline = pix->width; >> + pix->sizeimage = pix->width * pix->height * 3 / 2; >> + pix->field = V4L2_FIELD_NONE; >> + if (pix->pixelformat == V4L2_PIX_FMT_FWHT) { >> + pix->bytesperline = 0; >> + pix->sizeimage += sizeof(struct cframe_hdr); >> + } >> + break; >> + case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE: >> + case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE: >> + pix_mp = &f->fmt.pix_mp; >> + pix_mp->width = clamp(pix_mp->width, MIN_WIDTH, MAX_WIDTH) & ~7; >> + pix_mp->height = >> + clamp(pix_mp->height, MIN_HEIGHT, MAX_HEIGHT) & ~7; >> + pix_mp->plane_fmt[0].bytesperline = pix_mp->width; >> + pix_mp->plane_fmt[0].sizeimage = >> + pix_mp->width * pix_mp->height * 3 / 2; >> + pix_mp->field = V4L2_FIELD_NONE; >> + if (pix_mp->pixelformat == V4L2_PIX_FMT_FWHT) { >> + pix_mp->plane_fmt[0].bytesperline = 0; >> + pix_mp->plane_fmt[0].sizeimage += >> + sizeof(struct cframe_hdr); >> + } >> + break; >> + default: >> + return -EINVAL; >> } >> >> return 0; >> @@ -627,12 +686,26 @@ static int vidioc_try_fmt_vid_cap(struct file *file, void *priv, >> { >> struct vicodec_ctx *ctx = file2ctx(file); >> >> - f->fmt.pix.pixelformat = ctx->is_enc ? V4L2_PIX_FMT_FWHT : >> - find_fmt(f->fmt.pix.pixelformat); >> - f->fmt.pix.colorspace = ctx->colorspace; >> - f->fmt.pix.xfer_func = ctx->xfer_func; >> - f->fmt.pix.ycbcr_enc = ctx->ycbcr_enc; >> - f->fmt.pix.quantization = ctx->quantization; >> + switch (f->type) { >> + case V4L2_BUF_TYPE_VIDEO_CAPTURE: >> + f->fmt.pix.pixelformat = ctx->is_enc ? V4L2_PIX_FMT_FWHT : >> + find_fmt(f->fmt.pix.pixelformat); >> + f->fmt.pix.colorspace = ctx->colorspace; >> + f->fmt.pix.xfer_func = ctx->xfer_func; >> + f->fmt.pix.ycbcr_enc = ctx->ycbcr_enc; >> + f->fmt.pix.quantization = ctx->quantization; >> + break; >> + case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE: >> + f->fmt.pix_mp.pixelformat = ctx->is_enc ? V4L2_PIX_FMT_FWHT : >> + find_fmt(f->fmt.pix_mp.pixelformat); >> + f->fmt.pix_mp.colorspace = ctx->colorspace; >> + f->fmt.pix_mp.xfer_func = ctx->xfer_func; >> + f->fmt.pix_mp.ycbcr_enc = ctx->ycbcr_enc; >> + f->fmt.pix_mp.quantization = ctx->quantization; >> + break; >> + default: >> + return -EINVAL; >> + } >> >> return vidioc_try_fmt(ctx, f); >> } >> @@ -642,10 +715,22 @@ static int vidioc_try_fmt_vid_out(struct file *file, void *priv, >> { >> struct vicodec_ctx *ctx = file2ctx(file); >> >> - f->fmt.pix.pixelformat = !ctx->is_enc ? V4L2_PIX_FMT_FWHT : >> - find_fmt(f->fmt.pix.pixelformat); >> - if (!f->fmt.pix.colorspace) >> - f->fmt.pix.colorspace = V4L2_COLORSPACE_REC709; >> + switch (f->type) { >> + case V4L2_BUF_TYPE_VIDEO_OUTPUT: >> + f->fmt.pix.pixelformat = !ctx->is_enc ? V4L2_PIX_FMT_FWHT : >> + find_fmt(f->fmt.pix.pixelformat); >> + if (!f->fmt.pix.colorspace) >> + f->fmt.pix.colorspace = V4L2_COLORSPACE_REC709; >> + break; >> + case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE: >> + f->fmt.pix_mp.pixelformat = !ctx->is_enc ? V4L2_PIX_FMT_FWHT : >> + find_fmt(f->fmt.pix_mp.pixelformat); >> + if (!f->fmt.pix_mp.colorspace) >> + f->fmt.pix_mp.colorspace = V4L2_COLORSPACE_REC709; >> + break; >> + default: >> + return -EINVAL; >> + } >> >> return vidioc_try_fmt(ctx, f); >> } >> @@ -664,18 +749,42 @@ static int vidioc_s_fmt(struct vicodec_ctx *ctx, struct v4l2_format *f) >> if (!q_data) >> return -EINVAL; >> >> - if (ctx->is_enc && V4L2_TYPE_IS_OUTPUT(f->type)) >> - fmt_changed = q_data->fourcc != f->fmt.pix.pixelformat || >> - q_data->width != f->fmt.pix.width || >> - q_data->height != f->fmt.pix.height; >> - >> - if (vb2_is_busy(vq) && fmt_changed) >> - return -EBUSY; >> - >> - q_data->fourcc = f->fmt.pix.pixelformat; >> - q_data->width = f->fmt.pix.width; >> - q_data->height = f->fmt.pix.height; >> - q_data->sizeimage = f->fmt.pix.sizeimage; >> + switch (f->type) { >> + case V4L2_BUF_TYPE_VIDEO_CAPTURE: >> + case V4L2_BUF_TYPE_VIDEO_OUTPUT: >> + if (ctx->is_enc && V4L2_TYPE_IS_OUTPUT(f->type)) >> + fmt_changed = >> + q_data->fourcc != f->fmt.pix.pixelformat || >> + q_data->width != f->fmt.pix.width || >> + q_data->height != f->fmt.pix.height; >> + >> + if (vb2_is_busy(vq) && fmt_changed) >> + return -EBUSY; >> + >> + q_data->fourcc = f->fmt.pix.pixelformat; >> + q_data->width = f->fmt.pix.width; >> + q_data->height = f->fmt.pix.height; >> + q_data->sizeimage = f->fmt.pix.sizeimage; >> + break; >> + case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE: >> + case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE: >> + if (ctx->is_enc && V4L2_TYPE_IS_OUTPUT(f->type)) >> + fmt_changed = >> + q_data->fourcc != f->fmt.pix_mp.pixelformat || >> + q_data->width != f->fmt.pix_mp.width || >> + q_data->height != f->fmt.pix_mp.height; >> + >> + if (vb2_is_busy(vq) && fmt_changed) >> + return -EBUSY; >> + >> + q_data->fourcc = f->fmt.pix_mp.pixelformat; >> + q_data->width = f->fmt.pix_mp.width; >> + q_data->height = f->fmt.pix_mp.height; >> + q_data->sizeimage = f->fmt.pix_mp.plane_fmt[0].sizeimage; >> + break; >> + default: >> + return -EINVAL; >> + } >> >> dprintk(ctx->dev, >> "Setting format for type %d, wxh: %dx%d, fourcc: %08x\n", >> @@ -832,11 +941,21 @@ static const struct v4l2_ioctl_ops vicodec_ioctl_ops = { >> .vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap, >> .vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap, >> >> + .vidioc_enum_fmt_vid_cap_mplane = vidioc_enum_fmt_vid_cap, >> + .vidioc_g_fmt_vid_cap_mplane = vidioc_g_fmt_vid_cap, >> + .vidioc_try_fmt_vid_cap_mplane = vidioc_try_fmt_vid_cap, >> + .vidioc_s_fmt_vid_cap_mplane = vidioc_s_fmt_vid_cap, >> + >> .vidioc_enum_fmt_vid_out = vidioc_enum_fmt_vid_out, >> .vidioc_g_fmt_vid_out = vidioc_g_fmt_vid_out, >> .vidioc_try_fmt_vid_out = vidioc_try_fmt_vid_out, >> .vidioc_s_fmt_vid_out = vidioc_s_fmt_vid_out, >> >> + .vidioc_enum_fmt_vid_out_mplane = vidioc_enum_fmt_vid_out, >> + .vidioc_g_fmt_vid_out_mplane = vidioc_g_fmt_vid_out, >> + .vidioc_try_fmt_vid_out_mplane = vidioc_try_fmt_vid_out, >> + .vidioc_s_fmt_vid_out_mplane = vidioc_s_fmt_vid_out, >> + >> .vidioc_reqbufs = v4l2_m2m_ioctl_reqbufs, >> .vidioc_querybuf = v4l2_m2m_ioctl_querybuf, >> .vidioc_qbuf = v4l2_m2m_ioctl_qbuf, >> @@ -1002,7 +1121,9 @@ static int queue_init(void *priv, struct vb2_queue *src_vq, >> struct vicodec_ctx *ctx = priv; >> int ret; >> >> - src_vq->type = V4L2_BUF_TYPE_VIDEO_OUTPUT; >> + src_vq->type = (multiplanar ? >> + V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE : >> + V4L2_BUF_TYPE_VIDEO_OUTPUT); >> src_vq->io_modes = VB2_MMAP | VB2_USERPTR | VB2_DMABUF; >> src_vq->drv_priv = ctx; >> src_vq->buf_struct_size = sizeof(struct v4l2_m2m_buffer); >> @@ -1016,7 +1137,9 @@ static int queue_init(void *priv, struct vb2_queue *src_vq, >> if (ret) >> return ret; >> >> - dst_vq->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; >> + dst_vq->type = (multiplanar ? >> + V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE : >> + V4L2_BUF_TYPE_VIDEO_CAPTURE); >> dst_vq->io_modes = VB2_MMAP | VB2_USERPTR | VB2_DMABUF; >> dst_vq->drv_priv = ctx; >> dst_vq->buf_struct_size = sizeof(struct v4l2_m2m_buffer); >> -- >> 2.18.0.233.g985f88cf7e-goog >> >> This is an additional patch to Hans's patch series of the new vicodec driver. >> This patch adds multi-planar API support. I confirmed that v4l2-ctl uses >> multi-planar APIs to decode a FWHT format video when vicodec module is loaded >> with module parameter 'multiplanar'. >> >
diff --git a/drivers/media/platform/vicodec/vicodec-core.c b/drivers/media/platform/vicodec/vicodec-core.c index 12c12cb0c1c0..1717f44e1743 100644 --- a/drivers/media/platform/vicodec/vicodec-core.c +++ b/drivers/media/platform/vicodec/vicodec-core.c @@ -29,6 +29,11 @@ MODULE_DESCRIPTION("Virtual codec device"); MODULE_AUTHOR("Hans Verkuil <hans.verkuil@cisco.com>"); MODULE_LICENSE("GPL v2"); +static bool multiplanar; +module_param(multiplanar, bool, 0444); +MODULE_PARM_DESC(multiplanar, + " use multi-planar API instead of single-planar API"); + static unsigned int debug; module_param(debug, uint, 0644); MODULE_PARM_DESC(debug, "activates debug info"); @@ -135,8 +140,10 @@ static struct vicodec_q_data *get_q_data(struct vicodec_ctx *ctx, { switch (type) { case V4L2_BUF_TYPE_VIDEO_OUTPUT: + case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE: return &ctx->q_data[V4L2_M2M_SRC]; case V4L2_BUF_TYPE_VIDEO_CAPTURE: + case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE: return &ctx->q_data[V4L2_M2M_DST]; default: WARN_ON(1); @@ -530,7 +537,10 @@ static int vidioc_querycap(struct file *file, void *priv, strncpy(cap->card, VICODEC_NAME, sizeof(cap->card) - 1); snprintf(cap->bus_info, sizeof(cap->bus_info), "platform:%s", VICODEC_NAME); - cap->device_caps = V4L2_CAP_VIDEO_M2M | V4L2_CAP_STREAMING; + cap->device_caps = V4L2_CAP_STREAMING | + (multiplanar ? + V4L2_CAP_VIDEO_M2M_MPLANE : + V4L2_CAP_VIDEO_M2M); cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS; return 0; } @@ -576,20 +586,44 @@ static int vidioc_g_fmt(struct vicodec_ctx *ctx, struct v4l2_format *f) q_data = get_q_data(ctx, f->type); - f->fmt.pix.width = q_data->width; - f->fmt.pix.height = q_data->height; - f->fmt.pix.field = V4L2_FIELD_NONE; - f->fmt.pix.pixelformat = q_data->fourcc; - if (q_data->fourcc == V4L2_PIX_FMT_FWHT) - f->fmt.pix.bytesperline = 0; - else - f->fmt.pix.bytesperline = q_data->width; - f->fmt.pix.sizeimage = q_data->sizeimage; - f->fmt.pix.colorspace = ctx->colorspace; - f->fmt.pix.xfer_func = ctx->xfer_func; - f->fmt.pix.ycbcr_enc = ctx->ycbcr_enc; - f->fmt.pix.quantization = ctx->quantization; + switch (f->type) { + case V4L2_BUF_TYPE_VIDEO_CAPTURE: + case V4L2_BUF_TYPE_VIDEO_OUTPUT: + f->fmt.pix.width = q_data->width; + f->fmt.pix.height = q_data->height; + f->fmt.pix.field = V4L2_FIELD_NONE; + f->fmt.pix.pixelformat = q_data->fourcc; + if (q_data->fourcc == V4L2_PIX_FMT_FWHT) + f->fmt.pix.bytesperline = 0; + else + f->fmt.pix.bytesperline = q_data->width; + f->fmt.pix.sizeimage = q_data->sizeimage; + f->fmt.pix.colorspace = ctx->colorspace; + f->fmt.pix.xfer_func = ctx->xfer_func; + f->fmt.pix.ycbcr_enc = ctx->ycbcr_enc; + f->fmt.pix.quantization = ctx->quantization; + break; + case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE: + case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE: + f->fmt.pix_mp.width = q_data->width; + f->fmt.pix_mp.height = q_data->height; + f->fmt.pix_mp.field = V4L2_FIELD_NONE; + f->fmt.pix_mp.pixelformat = q_data->fourcc; + f->fmt.pix_mp.num_planes = 1; + if (q_data->fourcc == V4L2_PIX_FMT_FWHT) + f->fmt.pix_mp.plane_fmt[0].bytesperline = 0; + else + f->fmt.pix_mp.plane_fmt[0].bytesperline = q_data->width; + f->fmt.pix_mp.plane_fmt[0].sizeimage = q_data->sizeimage; + f->fmt.pix_mp.colorspace = ctx->colorspace; + f->fmt.pix_mp.xfer_func = ctx->xfer_func; + f->fmt.pix_mp.ycbcr_enc = ctx->ycbcr_enc; + f->fmt.pix_mp.quantization = ctx->quantization; + break; + default: + return -EINVAL; + } return 0; } @@ -607,16 +641,41 @@ static int vidioc_g_fmt_vid_cap(struct file *file, void *priv, static int vidioc_try_fmt(struct vicodec_ctx *ctx, struct v4l2_format *f) { - struct v4l2_pix_format *pix = &f->fmt.pix; - - pix->width = clamp(pix->width, MIN_WIDTH, MAX_WIDTH) & ~7; - pix->height = clamp(pix->height, MIN_HEIGHT, MAX_HEIGHT) & ~7; - pix->bytesperline = pix->width; - pix->sizeimage = pix->width * pix->height * 3 / 2; - pix->field = V4L2_FIELD_NONE; - if (pix->pixelformat == V4L2_PIX_FMT_FWHT) { - pix->bytesperline = 0; - pix->sizeimage += sizeof(struct cframe_hdr); + struct v4l2_pix_format *pix; + struct v4l2_pix_format_mplane *pix_mp; + + switch (f->type) { + case V4L2_BUF_TYPE_VIDEO_CAPTURE: + case V4L2_BUF_TYPE_VIDEO_OUTPUT: + pix = &f->fmt.pix; + pix->width = clamp(pix->width, MIN_WIDTH, MAX_WIDTH) & ~7; + pix->height = clamp(pix->height, MIN_HEIGHT, MAX_HEIGHT) & ~7; + pix->bytesperline = pix->width; + pix->sizeimage = pix->width * pix->height * 3 / 2; + pix->field = V4L2_FIELD_NONE; + if (pix->pixelformat == V4L2_PIX_FMT_FWHT) { + pix->bytesperline = 0; + pix->sizeimage += sizeof(struct cframe_hdr); + } + break; + case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE: + case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE: + pix_mp = &f->fmt.pix_mp; + pix_mp->width = clamp(pix_mp->width, MIN_WIDTH, MAX_WIDTH) & ~7; + pix_mp->height = + clamp(pix_mp->height, MIN_HEIGHT, MAX_HEIGHT) & ~7; + pix_mp->plane_fmt[0].bytesperline = pix_mp->width; + pix_mp->plane_fmt[0].sizeimage = + pix_mp->width * pix_mp->height * 3 / 2; + pix_mp->field = V4L2_FIELD_NONE; + if (pix_mp->pixelformat == V4L2_PIX_FMT_FWHT) { + pix_mp->plane_fmt[0].bytesperline = 0; + pix_mp->plane_fmt[0].sizeimage += + sizeof(struct cframe_hdr); + } + break; + default: + return -EINVAL; } return 0; @@ -627,12 +686,26 @@ static int vidioc_try_fmt_vid_cap(struct file *file, void *priv, { struct vicodec_ctx *ctx = file2ctx(file); - f->fmt.pix.pixelformat = ctx->is_enc ? V4L2_PIX_FMT_FWHT : - find_fmt(f->fmt.pix.pixelformat); - f->fmt.pix.colorspace = ctx->colorspace; - f->fmt.pix.xfer_func = ctx->xfer_func; - f->fmt.pix.ycbcr_enc = ctx->ycbcr_enc; - f->fmt.pix.quantization = ctx->quantization; + switch (f->type) { + case V4L2_BUF_TYPE_VIDEO_CAPTURE: + f->fmt.pix.pixelformat = ctx->is_enc ? V4L2_PIX_FMT_FWHT : + find_fmt(f->fmt.pix.pixelformat); + f->fmt.pix.colorspace = ctx->colorspace; + f->fmt.pix.xfer_func = ctx->xfer_func; + f->fmt.pix.ycbcr_enc = ctx->ycbcr_enc; + f->fmt.pix.quantization = ctx->quantization; + break; + case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE: + f->fmt.pix_mp.pixelformat = ctx->is_enc ? V4L2_PIX_FMT_FWHT : + find_fmt(f->fmt.pix_mp.pixelformat); + f->fmt.pix_mp.colorspace = ctx->colorspace; + f->fmt.pix_mp.xfer_func = ctx->xfer_func; + f->fmt.pix_mp.ycbcr_enc = ctx->ycbcr_enc; + f->fmt.pix_mp.quantization = ctx->quantization; + break; + default: + return -EINVAL; + } return vidioc_try_fmt(ctx, f); } @@ -642,10 +715,22 @@ static int vidioc_try_fmt_vid_out(struct file *file, void *priv, { struct vicodec_ctx *ctx = file2ctx(file); - f->fmt.pix.pixelformat = !ctx->is_enc ? V4L2_PIX_FMT_FWHT : - find_fmt(f->fmt.pix.pixelformat); - if (!f->fmt.pix.colorspace) - f->fmt.pix.colorspace = V4L2_COLORSPACE_REC709; + switch (f->type) { + case V4L2_BUF_TYPE_VIDEO_OUTPUT: + f->fmt.pix.pixelformat = !ctx->is_enc ? V4L2_PIX_FMT_FWHT : + find_fmt(f->fmt.pix.pixelformat); + if (!f->fmt.pix.colorspace) + f->fmt.pix.colorspace = V4L2_COLORSPACE_REC709; + break; + case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE: + f->fmt.pix_mp.pixelformat = !ctx->is_enc ? V4L2_PIX_FMT_FWHT : + find_fmt(f->fmt.pix_mp.pixelformat); + if (!f->fmt.pix_mp.colorspace) + f->fmt.pix_mp.colorspace = V4L2_COLORSPACE_REC709; + break; + default: + return -EINVAL; + } return vidioc_try_fmt(ctx, f); } @@ -664,18 +749,42 @@ static int vidioc_s_fmt(struct vicodec_ctx *ctx, struct v4l2_format *f) if (!q_data) return -EINVAL; - if (ctx->is_enc && V4L2_TYPE_IS_OUTPUT(f->type)) - fmt_changed = q_data->fourcc != f->fmt.pix.pixelformat || - q_data->width != f->fmt.pix.width || - q_data->height != f->fmt.pix.height; - - if (vb2_is_busy(vq) && fmt_changed) - return -EBUSY; - - q_data->fourcc = f->fmt.pix.pixelformat; - q_data->width = f->fmt.pix.width; - q_data->height = f->fmt.pix.height; - q_data->sizeimage = f->fmt.pix.sizeimage; + switch (f->type) { + case V4L2_BUF_TYPE_VIDEO_CAPTURE: + case V4L2_BUF_TYPE_VIDEO_OUTPUT: + if (ctx->is_enc && V4L2_TYPE_IS_OUTPUT(f->type)) + fmt_changed = + q_data->fourcc != f->fmt.pix.pixelformat || + q_data->width != f->fmt.pix.width || + q_data->height != f->fmt.pix.height; + + if (vb2_is_busy(vq) && fmt_changed) + return -EBUSY; + + q_data->fourcc = f->fmt.pix.pixelformat; + q_data->width = f->fmt.pix.width; + q_data->height = f->fmt.pix.height; + q_data->sizeimage = f->fmt.pix.sizeimage; + break; + case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE: + case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE: + if (ctx->is_enc && V4L2_TYPE_IS_OUTPUT(f->type)) + fmt_changed = + q_data->fourcc != f->fmt.pix_mp.pixelformat || + q_data->width != f->fmt.pix_mp.width || + q_data->height != f->fmt.pix_mp.height; + + if (vb2_is_busy(vq) && fmt_changed) + return -EBUSY; + + q_data->fourcc = f->fmt.pix_mp.pixelformat; + q_data->width = f->fmt.pix_mp.width; + q_data->height = f->fmt.pix_mp.height; + q_data->sizeimage = f->fmt.pix_mp.plane_fmt[0].sizeimage; + break; + default: + return -EINVAL; + } dprintk(ctx->dev, "Setting format for type %d, wxh: %dx%d, fourcc: %08x\n", @@ -832,11 +941,21 @@ static const struct v4l2_ioctl_ops vicodec_ioctl_ops = { .vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap, .vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap, + .vidioc_enum_fmt_vid_cap_mplane = vidioc_enum_fmt_vid_cap, + .vidioc_g_fmt_vid_cap_mplane = vidioc_g_fmt_vid_cap, + .vidioc_try_fmt_vid_cap_mplane = vidioc_try_fmt_vid_cap, + .vidioc_s_fmt_vid_cap_mplane = vidioc_s_fmt_vid_cap, + .vidioc_enum_fmt_vid_out = vidioc_enum_fmt_vid_out, .vidioc_g_fmt_vid_out = vidioc_g_fmt_vid_out, .vidioc_try_fmt_vid_out = vidioc_try_fmt_vid_out, .vidioc_s_fmt_vid_out = vidioc_s_fmt_vid_out, + .vidioc_enum_fmt_vid_out_mplane = vidioc_enum_fmt_vid_out, + .vidioc_g_fmt_vid_out_mplane = vidioc_g_fmt_vid_out, + .vidioc_try_fmt_vid_out_mplane = vidioc_try_fmt_vid_out, + .vidioc_s_fmt_vid_out_mplane = vidioc_s_fmt_vid_out, + .vidioc_reqbufs = v4l2_m2m_ioctl_reqbufs, .vidioc_querybuf = v4l2_m2m_ioctl_querybuf, .vidioc_qbuf = v4l2_m2m_ioctl_qbuf, @@ -1002,7 +1121,9 @@ static int queue_init(void *priv, struct vb2_queue *src_vq, struct vicodec_ctx *ctx = priv; int ret; - src_vq->type = V4L2_BUF_TYPE_VIDEO_OUTPUT; + src_vq->type = (multiplanar ? + V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE : + V4L2_BUF_TYPE_VIDEO_OUTPUT); src_vq->io_modes = VB2_MMAP | VB2_USERPTR | VB2_DMABUF; src_vq->drv_priv = ctx; src_vq->buf_struct_size = sizeof(struct v4l2_m2m_buffer); @@ -1016,7 +1137,9 @@ static int queue_init(void *priv, struct vb2_queue *src_vq, if (ret) return ret; - dst_vq->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + dst_vq->type = (multiplanar ? + V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE : + V4L2_BUF_TYPE_VIDEO_CAPTURE); dst_vq->io_modes = VB2_MMAP | VB2_USERPTR | VB2_DMABUF; dst_vq->drv_priv = ctx; dst_vq->buf_struct_size = sizeof(struct v4l2_m2m_buffer);
Support multi-planar APIs in the virtual codec driver. Multi-planar APIs are enabled by the module parameter 'multiplanar'. Signed-off-by: Keiichi Watanabe <keiichiw@chromium.org> --- drivers/media/platform/vicodec/vicodec-core.c | 219 ++++++++++++++---- 1 file changed, 171 insertions(+), 48 deletions(-) -- 2.18.0.233.g985f88cf7e-goog This is an additional patch to Hans's patch series of the new vicodec driver. This patch adds multi-planar API support. I confirmed that v4l2-ctl uses multi-planar APIs to decode a FWHT format video when vicodec module is loaded with module parameter 'multiplanar'.