From 9495e07dac5cb6230838763572f73b863cd72019 Mon Sep 17 00:00:00 2001 From: Chen-Yu Tsai Date: Thu, 18 Jul 2019 17:07:05 +0800 Subject: [PATCH] staging: bcm2835-codec: switch to multi-planar API There are two APIs for mem2mem devices, the older single-planar API and the newer multi-planar one. Without making things overly complex, the driver can only support one or the other. However the userspace libv4l2 library has a plugin that allows multi-planar API devices to service single-planar consumers. Chromium supports the multi-planar API exclusively, though this is currently limited to ChromiumOS. It would be possible to add support for generic Linux. Switching to the multi-planar API would allow usage of both APIs from userspace. Signed-off-by: Chen-Yu Tsai --- .../bcm2835-codec/bcm2835-v4l2-codec.c | 141 +++++++++--------- 1 file changed, 74 insertions(+), 67 deletions(-) --- a/drivers/staging/vc04_services/bcm2835-codec/bcm2835-v4l2-codec.c +++ b/drivers/staging/vc04_services/bcm2835-codec/bcm2835-v4l2-codec.c @@ -504,7 +504,7 @@ static struct bcm2835_codec_fmt *find_fo for (k = 0; k < fmts->num_entries; k++) { fmt = &fmts->list[k]; - if (fmt->fourcc == f->fmt.pix.pixelformat) + if (fmt->fourcc == f->fmt.pix_mp.pixelformat) break; } if (k == fmts->num_entries) @@ -522,9 +522,9 @@ static struct bcm2835_codec_q_data *get_ enum v4l2_buf_type type) { 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: v4l2_err(&ctx->dev->v4l2_dev, "%s: Invalid queue type %u\n", @@ -541,9 +541,9 @@ static struct vchiq_mmal_port *get_port_ return NULL; switch (type) { - case V4L2_BUF_TYPE_VIDEO_OUTPUT: + case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE: return &ctx->component->input[0]; - case V4L2_BUF_TYPE_VIDEO_CAPTURE: + case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE: return &ctx->component->output[0]; default: v4l2_err(&ctx->dev->v4l2_dev, "%s: Invalid queue type %u\n", @@ -752,7 +752,7 @@ static void handle_fmt_changed(struct bc format->es.video.crop.width, format->es.video.crop.height, format->es.video.color_space); - q_data = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE); + q_data = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE); q_data->crop_width = format->es.video.crop.width; q_data->crop_height = format->es.video.crop.height; q_data->bytesperline = format->es.video.crop.width; @@ -945,7 +945,7 @@ static int vidioc_querycap(struct file * strncpy(cap->card, MEM2MEM_NAME, sizeof(cap->card) - 1); snprintf(cap->bus_info, sizeof(cap->bus_info), "platform:%s", MEM2MEM_NAME); - cap->device_caps = V4L2_CAP_VIDEO_M2M | V4L2_CAP_STREAMING; + cap->device_caps = V4L2_CAP_VIDEO_M2M_MPLANE | V4L2_CAP_STREAMING; cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS; return 0; } @@ -996,16 +996,20 @@ static int vidioc_g_fmt(struct bcm2835_c q_data = get_q_data(ctx, f->type); - f->fmt.pix.width = q_data->crop_width; - f->fmt.pix.height = q_data->height; - f->fmt.pix.field = V4L2_FIELD_NONE; - f->fmt.pix.pixelformat = q_data->fmt->fourcc; - f->fmt.pix.bytesperline = q_data->bytesperline; - 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->quant; + f->fmt.pix_mp.width = q_data->crop_width; + f->fmt.pix_mp.height = q_data->height; + f->fmt.pix_mp.pixelformat = q_data->fmt->fourcc; + f->fmt.pix_mp.field = V4L2_FIELD_NONE; + f->fmt.pix_mp.colorspace = ctx->colorspace; + f->fmt.pix_mp.plane_fmt[0].sizeimage = q_data->sizeimage; + f->fmt.pix_mp.plane_fmt[0].bytesperline = q_data->bytesperline; + f->fmt.pix_mp.num_planes = 1; + f->fmt.pix_mp.ycbcr_enc = ctx->ycbcr_enc; + f->fmt.pix_mp.quantization = ctx->quant; + f->fmt.pix_mp.xfer_func = ctx->xfer_func; + + memset(f->fmt.pix_mp.plane_fmt[0].reserved, 0, + sizeof(f->fmt.pix_mp.plane_fmt[0].reserved)); return 0; } @@ -1029,17 +1033,17 @@ static int vidioc_try_fmt(struct bcm2835 * The V4L2 specification requires the driver to correct the format * struct if any of the dimensions is unsupported */ - if (f->fmt.pix.width > MAX_W) - f->fmt.pix.width = MAX_W; - if (f->fmt.pix.height > MAX_H) - f->fmt.pix.height = MAX_H; + if (f->fmt.pix_mp.width > MAX_W) + f->fmt.pix_mp.width = MAX_W; + if (f->fmt.pix_mp.height > MAX_H) + f->fmt.pix_mp.height = MAX_H; if (!fmt->flags & V4L2_FMT_FLAG_COMPRESSED) { /* Only clip min w/h on capture. Treat 0x0 as unknown. */ - if (f->fmt.pix.width < MIN_W) - f->fmt.pix.width = MIN_W; - if (f->fmt.pix.height < MIN_H) - f->fmt.pix.height = MIN_H; + if (f->fmt.pix_mp.width < MIN_W) + f->fmt.pix_mp.width = MIN_W; + if (f->fmt.pix_mp.height < MIN_H) + f->fmt.pix_mp.height = MIN_H; /* * For codecs the buffer must have a vertical alignment of 16 @@ -1048,16 +1052,18 @@ static int vidioc_try_fmt(struct bcm2835 * some of the pixels are active. */ if (ctx->dev->role != ISP) - f->fmt.pix.height = ALIGN(f->fmt.pix.height, 16); + f->fmt.pix_mp.height = ALIGN(f->fmt.pix_mp.height, 16); } - f->fmt.pix.bytesperline = get_bytesperline(f->fmt.pix.width, - fmt); - f->fmt.pix.sizeimage = get_sizeimage(f->fmt.pix.bytesperline, - f->fmt.pix.width, - f->fmt.pix.height, - fmt); + f->fmt.pix_mp.num_planes = 1; + f->fmt.pix_mp.plane_fmt[0].bytesperline = + get_bytesperline(f->fmt.pix_mp.width, fmt); + f->fmt.pix_mp.plane_fmt[0].sizeimage = + get_sizeimage(f->fmt.pix_mp.plane_fmt[0].bytesperline, + f->fmt.pix_mp.width, f->fmt.pix_mp.height, fmt); + memset(f->fmt.pix_mp.plane_fmt[0].reserved, 0, + sizeof(f->fmt.pix_mp.plane_fmt[0].reserved)); - f->fmt.pix.field = V4L2_FIELD_NONE; + f->fmt.pix_mp.field = V4L2_FIELD_NONE; return 0; } @@ -1070,8 +1076,8 @@ static int vidioc_try_fmt_vid_cap(struct fmt = find_format(f, ctx->dev, true); if (!fmt) { - f->fmt.pix.pixelformat = get_default_format(ctx->dev, - true)->fourcc; + f->fmt.pix_mp.pixelformat = get_default_format(ctx->dev, + true)->fourcc; fmt = find_format(f, ctx->dev, true); } @@ -1086,13 +1092,13 @@ static int vidioc_try_fmt_vid_out(struct fmt = find_format(f, ctx->dev, false); if (!fmt) { - f->fmt.pix.pixelformat = get_default_format(ctx->dev, - false)->fourcc; + f->fmt.pix_mp.pixelformat = get_default_format(ctx->dev, + false)->fourcc; fmt = find_format(f, ctx->dev, false); } - if (!f->fmt.pix.colorspace) - f->fmt.pix.colorspace = ctx->colorspace; + if (!f->fmt.pix_mp.colorspace) + f->fmt.pix_mp.colorspace = ctx->colorspace; return vidioc_try_fmt(ctx, f, fmt); } @@ -1106,9 +1112,10 @@ static int vidioc_s_fmt(struct bcm2835_c bool update_capture_port = false; int ret; - v4l2_dbg(1, debug, &ctx->dev->v4l2_dev, "Setting format for type %d, wxh: %dx%d, fmt: %08x, size %u\n", - f->type, f->fmt.pix.width, f->fmt.pix.height, - f->fmt.pix.pixelformat, f->fmt.pix.sizeimage); + v4l2_dbg(1, debug, &ctx->dev->v4l2_dev, "Setting format for type %d, wxh: %dx%d, fmt: %08x, size %u\n", + f->type, f->fmt.pix_mp.width, f->fmt.pix_mp.height, + f->fmt.pix_mp.pixelformat, f->fmt.pix_mp.plane_fmt[0].sizeimage); + vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx, f->type); if (!vq) @@ -1124,9 +1131,9 @@ static int vidioc_s_fmt(struct bcm2835_c } q_data->fmt = find_format(f, ctx->dev, - f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE); - q_data->crop_width = f->fmt.pix.width; - q_data->height = f->fmt.pix.height; + f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE); + q_data->crop_width = f->fmt.pix_mp.width; + q_data->height = f->fmt.pix_mp.height; if (!q_data->selection_set) q_data->crop_height = requested_height; @@ -1134,21 +1141,21 @@ static int vidioc_s_fmt(struct bcm2835_c * Copying the behaviour of vicodec which retains a single set of * colorspace parameters for both input and output. */ - ctx->colorspace = f->fmt.pix.colorspace; - ctx->xfer_func = f->fmt.pix.xfer_func; - ctx->ycbcr_enc = f->fmt.pix.ycbcr_enc; - ctx->quant = f->fmt.pix.quantization; + ctx->colorspace = f->fmt.pix_mp.colorspace; + ctx->xfer_func = f->fmt.pix_mp.xfer_func; + ctx->ycbcr_enc = f->fmt.pix_mp.ycbcr_enc; + ctx->quant = f->fmt.pix_mp.quantization; /* All parameters should have been set correctly by try_fmt */ - q_data->bytesperline = f->fmt.pix.bytesperline; - q_data->sizeimage = f->fmt.pix.sizeimage; + q_data->bytesperline = f->fmt.pix_mp.plane_fmt[0].bytesperline; + q_data->sizeimage = f->fmt.pix_mp.plane_fmt[0].sizeimage; v4l2_dbg(1, debug, &ctx->dev->v4l2_dev, "Calulated bpl as %u, size %u\n", q_data->bytesperline, q_data->sizeimage); if (ctx->dev->role == DECODE && q_data->fmt->flags & V4L2_FMT_FLAG_COMPRESSED && - f->fmt.pix.width && f->fmt.pix.height) { + q_data->crop_width && q_data->height) { /* * On the decoder, if provided with a resolution on the input * side, then replicate that to the output side. @@ -1165,7 +1172,7 @@ static int vidioc_s_fmt(struct bcm2835_c q_data_dst->height = ALIGN(q_data->crop_height, 16); q_data_dst->bytesperline = - get_bytesperline(f->fmt.pix.width, q_data_dst->fmt); + get_bytesperline(f->fmt.pix_mp.width, q_data_dst->fmt); q_data_dst->sizeimage = get_sizeimage(q_data_dst->bytesperline, q_data_dst->crop_width, q_data_dst->height, @@ -1215,7 +1222,7 @@ static int vidioc_s_fmt(struct bcm2835_c static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, struct v4l2_format *f) { - unsigned int height = f->fmt.pix.height; + unsigned int height = f->fmt.pix_mp.height; int ret; ret = vidioc_try_fmt_vid_cap(file, priv, f); @@ -1228,7 +1235,7 @@ static int vidioc_s_fmt_vid_cap(struct f static int vidioc_s_fmt_vid_out(struct file *file, void *priv, struct v4l2_format *f) { - unsigned int height = f->fmt.pix.height; + unsigned int height = f->fmt.pix_mp.height; int ret; ret = vidioc_try_fmt_vid_out(file, priv, f); @@ -1244,7 +1251,7 @@ static int vidioc_g_selection(struct fil { struct bcm2835_codec_ctx *ctx = file2ctx(file); struct bcm2835_codec_q_data *q_data; - bool capture_queue = s->type == V4L2_BUF_TYPE_VIDEO_CAPTURE ? + bool capture_queue = s->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE ? true : false; if ((ctx->dev->role == DECODE && !capture_queue) || @@ -1307,7 +1314,7 @@ static int vidioc_s_selection(struct fil { struct bcm2835_codec_ctx *ctx = file2ctx(file); struct bcm2835_codec_q_data *q_data = NULL; - bool capture_queue = s->type == V4L2_BUF_TYPE_VIDEO_CAPTURE ? + bool capture_queue = s->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE ? true : false; v4l2_dbg(1, debug, &ctx->dev->v4l2_dev, "%s: ctx %p, type %d, q_data %p, target %d, rect x/y %d/%d, w/h %ux%u\n", @@ -1368,7 +1375,7 @@ static int vidioc_s_parm(struct file *fi { struct bcm2835_codec_ctx *ctx = file2ctx(file); - if (parm->type != V4L2_BUF_TYPE_VIDEO_OUTPUT) + if (parm->type != V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) return -EINVAL; ctx->framerate_num = @@ -1739,14 +1746,14 @@ static const struct v4l2_ioctl_ops bcm28 .vidioc_querycap = vidioc_querycap, .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap, - .vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap, - .vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap, - .vidioc_s_fmt_vid_cap = vidioc_s_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_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, @@ -2089,7 +2096,7 @@ static int bcm2835_codec_start_streaming ctx->component_enabled = true; } - if (q->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) { + if (q->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) { /* * Create the EOS buffer. * We only need the MMAL part, and want to NOT attach a memory @@ -2216,7 +2223,7 @@ static int queue_init(void *priv, struct struct bcm2835_codec_ctx *ctx = priv; int ret; - src_vq->type = V4L2_BUF_TYPE_VIDEO_OUTPUT; + src_vq->type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; src_vq->io_modes = VB2_MMAP | VB2_DMABUF; src_vq->drv_priv = ctx; src_vq->buf_struct_size = sizeof(struct m2m_mmal_buffer); @@ -2230,7 +2237,7 @@ static int queue_init(void *priv, struct if (ret) return ret; - dst_vq->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + dst_vq->type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; dst_vq->io_modes = VB2_MMAP | VB2_DMABUF; dst_vq->drv_priv = ctx; dst_vq->buf_struct_size = sizeof(struct m2m_mmal_buffer);