|
@@ -48,6 +48,46 @@ MODULE_PARM_DESC(debug, " activates debug info");
|
|
|
v4l2_dbg(1, debug, &dev->v4l2_dev, "%s: " fmt, __func__, ## arg)
|
|
|
|
|
|
|
|
|
+struct pixfmt_info {
|
|
|
+ u32 id;
|
|
|
+ unsigned int bytesperline_mult;
|
|
|
+ unsigned int sizeimage_mult;
|
|
|
+ unsigned int sizeimage_div;
|
|
|
+ unsigned int luma_step;
|
|
|
+ unsigned int chroma_step;
|
|
|
+ /* Chroma plane subsampling */
|
|
|
+ unsigned int width_div;
|
|
|
+ unsigned int height_div;
|
|
|
+};
|
|
|
+
|
|
|
+static const struct pixfmt_info pixfmts[] = {
|
|
|
+ { V4L2_PIX_FMT_YUV420, 1, 3, 2, 1, 1, 2, 2 },
|
|
|
+ { V4L2_PIX_FMT_YVU420, 1, 3, 2, 1, 1, 2, 2 },
|
|
|
+ { V4L2_PIX_FMT_YUV422P, 1, 2, 1, 1, 1, 2, 1 },
|
|
|
+ { V4L2_PIX_FMT_NV12, 1, 3, 2, 1, 2, 2, 2 },
|
|
|
+ { V4L2_PIX_FMT_NV21, 1, 3, 2, 1, 2, 2, 2 },
|
|
|
+ { V4L2_PIX_FMT_NV16, 1, 2, 1, 1, 2, 2, 1 },
|
|
|
+ { V4L2_PIX_FMT_NV61, 1, 2, 1, 1, 2, 2, 1 },
|
|
|
+ { V4L2_PIX_FMT_NV24, 1, 3, 1, 1, 2, 1, 1 },
|
|
|
+ { V4L2_PIX_FMT_NV42, 1, 3, 1, 1, 2, 1, 1 },
|
|
|
+ { V4L2_PIX_FMT_YUYV, 2, 2, 1, 2, 4, 2, 1 },
|
|
|
+ { V4L2_PIX_FMT_YVYU, 2, 2, 1, 2, 4, 2, 1 },
|
|
|
+ { V4L2_PIX_FMT_UYVY, 2, 2, 1, 2, 4, 2, 1 },
|
|
|
+ { V4L2_PIX_FMT_VYUY, 2, 2, 1, 2, 4, 2, 1 },
|
|
|
+ { V4L2_PIX_FMT_BGR24, 3, 3, 1, 3, 3, 1, 1 },
|
|
|
+ { V4L2_PIX_FMT_RGB24, 3, 3, 1, 3, 3, 1, 1 },
|
|
|
+ { V4L2_PIX_FMT_HSV24, 3, 3, 1, 3, 3, 1, 1 },
|
|
|
+ { V4L2_PIX_FMT_BGR32, 4, 4, 1, 4, 4, 1, 1 },
|
|
|
+ { V4L2_PIX_FMT_XBGR32, 4, 4, 1, 4, 4, 1, 1 },
|
|
|
+ { V4L2_PIX_FMT_RGB32, 4, 4, 1, 4, 4, 1, 1 },
|
|
|
+ { V4L2_PIX_FMT_XRGB32, 4, 4, 1, 4, 4, 1, 1 },
|
|
|
+ { V4L2_PIX_FMT_HSV32, 4, 4, 1, 4, 4, 1, 1 },
|
|
|
+};
|
|
|
+
|
|
|
+static const struct pixfmt_info pixfmt_fwht = {
|
|
|
+ V4L2_PIX_FMT_FWHT, 0, 3, 1, 1, 1, 1, 1
|
|
|
+};
|
|
|
+
|
|
|
static void vicodec_dev_release(struct device *dev)
|
|
|
{
|
|
|
}
|
|
@@ -64,7 +104,7 @@ struct vicodec_q_data {
|
|
|
unsigned int flags;
|
|
|
unsigned int sizeimage;
|
|
|
unsigned int sequence;
|
|
|
- u32 fourcc;
|
|
|
+ const struct pixfmt_info *info;
|
|
|
};
|
|
|
|
|
|
enum {
|
|
@@ -124,13 +164,6 @@ struct vicodec_ctx {
|
|
|
bool comp_has_next_frame;
|
|
|
};
|
|
|
|
|
|
-static const u32 pixfmts_yuv[] = {
|
|
|
- V4L2_PIX_FMT_YUV420,
|
|
|
- V4L2_PIX_FMT_YVU420,
|
|
|
- V4L2_PIX_FMT_NV12,
|
|
|
- V4L2_PIX_FMT_NV21,
|
|
|
-};
|
|
|
-
|
|
|
static inline struct vicodec_ctx *file2ctx(struct file *file)
|
|
|
{
|
|
|
return container_of(file->private_data, struct vicodec_ctx, fh);
|
|
@@ -158,6 +191,7 @@ static void encode(struct vicodec_ctx *ctx,
|
|
|
u8 *p_in, u8 *p_out)
|
|
|
{
|
|
|
unsigned int size = q_data->width * q_data->height;
|
|
|
+ const struct pixfmt_info *info = q_data->info;
|
|
|
struct cframe_hdr *p_hdr;
|
|
|
struct cframe cf;
|
|
|
struct raw_frame rf;
|
|
@@ -166,27 +200,77 @@ static void encode(struct vicodec_ctx *ctx,
|
|
|
rf.width = q_data->width;
|
|
|
rf.height = q_data->height;
|
|
|
rf.luma = p_in;
|
|
|
+ rf.width_div = info->width_div;
|
|
|
+ rf.height_div = info->height_div;
|
|
|
+ rf.luma_step = info->luma_step;
|
|
|
+ rf.chroma_step = info->chroma_step;
|
|
|
|
|
|
- switch (q_data->fourcc) {
|
|
|
+ switch (info->id) {
|
|
|
case V4L2_PIX_FMT_YUV420:
|
|
|
rf.cb = rf.luma + size;
|
|
|
rf.cr = rf.cb + size / 4;
|
|
|
- rf.chroma_step = 1;
|
|
|
break;
|
|
|
case V4L2_PIX_FMT_YVU420:
|
|
|
rf.cr = rf.luma + size;
|
|
|
rf.cb = rf.cr + size / 4;
|
|
|
- rf.chroma_step = 1;
|
|
|
+ break;
|
|
|
+ case V4L2_PIX_FMT_YUV422P:
|
|
|
+ rf.cb = rf.luma + size;
|
|
|
+ rf.cr = rf.cb + size / 2;
|
|
|
break;
|
|
|
case V4L2_PIX_FMT_NV12:
|
|
|
+ case V4L2_PIX_FMT_NV16:
|
|
|
+ case V4L2_PIX_FMT_NV24:
|
|
|
rf.cb = rf.luma + size;
|
|
|
rf.cr = rf.cb + 1;
|
|
|
- rf.chroma_step = 2;
|
|
|
break;
|
|
|
case V4L2_PIX_FMT_NV21:
|
|
|
+ case V4L2_PIX_FMT_NV61:
|
|
|
+ case V4L2_PIX_FMT_NV42:
|
|
|
rf.cr = rf.luma + size;
|
|
|
rf.cb = rf.cr + 1;
|
|
|
- rf.chroma_step = 2;
|
|
|
+ break;
|
|
|
+ case V4L2_PIX_FMT_YUYV:
|
|
|
+ rf.cb = rf.luma + 1;
|
|
|
+ rf.cr = rf.cb + 2;
|
|
|
+ break;
|
|
|
+ case V4L2_PIX_FMT_YVYU:
|
|
|
+ rf.cr = rf.luma + 1;
|
|
|
+ rf.cb = rf.cr + 2;
|
|
|
+ break;
|
|
|
+ case V4L2_PIX_FMT_UYVY:
|
|
|
+ rf.cb = rf.luma;
|
|
|
+ rf.cr = rf.cb + 2;
|
|
|
+ rf.luma++;
|
|
|
+ break;
|
|
|
+ case V4L2_PIX_FMT_VYUY:
|
|
|
+ rf.cr = rf.luma;
|
|
|
+ rf.cb = rf.cr + 2;
|
|
|
+ rf.luma++;
|
|
|
+ break;
|
|
|
+ case V4L2_PIX_FMT_RGB24:
|
|
|
+ case V4L2_PIX_FMT_HSV24:
|
|
|
+ rf.cr = rf.luma;
|
|
|
+ rf.cb = rf.cr + 2;
|
|
|
+ rf.luma++;
|
|
|
+ break;
|
|
|
+ case V4L2_PIX_FMT_BGR24:
|
|
|
+ rf.cb = rf.luma;
|
|
|
+ rf.cr = rf.cb + 2;
|
|
|
+ rf.luma++;
|
|
|
+ break;
|
|
|
+ case V4L2_PIX_FMT_RGB32:
|
|
|
+ case V4L2_PIX_FMT_XRGB32:
|
|
|
+ case V4L2_PIX_FMT_HSV32:
|
|
|
+ rf.cr = rf.luma + 1;
|
|
|
+ rf.cb = rf.cr + 2;
|
|
|
+ rf.luma += 2;
|
|
|
+ break;
|
|
|
+ case V4L2_PIX_FMT_BGR32:
|
|
|
+ case V4L2_PIX_FMT_XBGR32:
|
|
|
+ rf.cb = rf.luma;
|
|
|
+ rf.cr = rf.cb + 2;
|
|
|
+ rf.luma++;
|
|
|
break;
|
|
|
}
|
|
|
|
|
@@ -216,6 +300,10 @@ static void encode(struct vicodec_ctx *ctx,
|
|
|
p_hdr->flags |= htonl(VICODEC_FL_CB_IS_UNCOMPRESSED);
|
|
|
if (encoding & CR_UNENCODED)
|
|
|
p_hdr->flags |= htonl(VICODEC_FL_CR_IS_UNCOMPRESSED);
|
|
|
+ if (rf.height_div == 1)
|
|
|
+ p_hdr->flags |= htonl(VICODEC_FL_CHROMA_FULL_HEIGHT);
|
|
|
+ if (rf.width_div == 1)
|
|
|
+ p_hdr->flags |= htonl(VICODEC_FL_CHROMA_FULL_WIDTH);
|
|
|
p_hdr->colorspace = htonl(ctx->colorspace);
|
|
|
p_hdr->xfer_func = htonl(ctx->xfer_func);
|
|
|
p_hdr->ycbcr_enc = htonl(ctx->ycbcr_enc);
|
|
@@ -230,6 +318,7 @@ static int decode(struct vicodec_ctx *ctx,
|
|
|
u8 *p_in, u8 *p_out)
|
|
|
{
|
|
|
unsigned int size = q_data->width * q_data->height;
|
|
|
+ unsigned int chroma_size = size;
|
|
|
unsigned int i;
|
|
|
struct cframe_hdr *p_hdr;
|
|
|
struct cframe cf;
|
|
@@ -259,32 +348,114 @@ static int decode(struct vicodec_ctx *ctx,
|
|
|
if (cf.width != q_data->width || cf.height != q_data->height)
|
|
|
return -EINVAL;
|
|
|
|
|
|
+ if (!(q_data->flags & VICODEC_FL_CHROMA_FULL_WIDTH))
|
|
|
+ chroma_size /= 2;
|
|
|
+ if (!(q_data->flags & VICODEC_FL_CHROMA_FULL_HEIGHT))
|
|
|
+ chroma_size /= 2;
|
|
|
+
|
|
|
decode_frame(&cf, &ctx->ref_frame, q_data->flags);
|
|
|
- memcpy(p_out, ctx->ref_frame.luma, size);
|
|
|
- p_out += size;
|
|
|
|
|
|
- switch (q_data->fourcc) {
|
|
|
+ switch (q_data->info->id) {
|
|
|
case V4L2_PIX_FMT_YUV420:
|
|
|
- memcpy(p_out, ctx->ref_frame.cb, size / 4);
|
|
|
- p_out += size / 4;
|
|
|
- memcpy(p_out, ctx->ref_frame.cr, size / 4);
|
|
|
+ case V4L2_PIX_FMT_YUV422P:
|
|
|
+ memcpy(p_out, ctx->ref_frame.luma, size);
|
|
|
+ p_out += size;
|
|
|
+ memcpy(p_out, ctx->ref_frame.cb, chroma_size);
|
|
|
+ p_out += chroma_size;
|
|
|
+ memcpy(p_out, ctx->ref_frame.cr, chroma_size);
|
|
|
break;
|
|
|
case V4L2_PIX_FMT_YVU420:
|
|
|
- memcpy(p_out, ctx->ref_frame.cr, size / 4);
|
|
|
- p_out += size / 4;
|
|
|
- memcpy(p_out, ctx->ref_frame.cb, size / 4);
|
|
|
+ memcpy(p_out, ctx->ref_frame.luma, size);
|
|
|
+ p_out += size;
|
|
|
+ memcpy(p_out, ctx->ref_frame.cr, chroma_size);
|
|
|
+ p_out += chroma_size;
|
|
|
+ memcpy(p_out, ctx->ref_frame.cb, chroma_size);
|
|
|
break;
|
|
|
case V4L2_PIX_FMT_NV12:
|
|
|
- for (i = 0, p = p_out; i < size / 4; i++, p += 2)
|
|
|
- *p = ctx->ref_frame.cb[i];
|
|
|
- for (i = 0, p = p_out + 1; i < size / 4; i++, p += 2)
|
|
|
- *p = ctx->ref_frame.cr[i];
|
|
|
+ case V4L2_PIX_FMT_NV16:
|
|
|
+ case V4L2_PIX_FMT_NV24:
|
|
|
+ memcpy(p_out, ctx->ref_frame.luma, size);
|
|
|
+ p_out += size;
|
|
|
+ for (i = 0, p = p_out; i < chroma_size; i++) {
|
|
|
+ *p++ = ctx->ref_frame.cb[i];
|
|
|
+ *p++ = ctx->ref_frame.cr[i];
|
|
|
+ }
|
|
|
break;
|
|
|
case V4L2_PIX_FMT_NV21:
|
|
|
- for (i = 0, p = p_out; i < size / 4; i++, p += 2)
|
|
|
- *p = ctx->ref_frame.cr[i];
|
|
|
- for (i = 0, p = p_out + 1; i < size / 4; i++, p += 2)
|
|
|
- *p = ctx->ref_frame.cb[i];
|
|
|
+ case V4L2_PIX_FMT_NV61:
|
|
|
+ case V4L2_PIX_FMT_NV42:
|
|
|
+ memcpy(p_out, ctx->ref_frame.luma, size);
|
|
|
+ p_out += size;
|
|
|
+ for (i = 0, p = p_out; i < chroma_size; i++) {
|
|
|
+ *p++ = ctx->ref_frame.cr[i];
|
|
|
+ *p++ = ctx->ref_frame.cb[i];
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ case V4L2_PIX_FMT_YUYV:
|
|
|
+ for (i = 0, p = p_out; i < size; i += 2) {
|
|
|
+ *p++ = ctx->ref_frame.luma[i];
|
|
|
+ *p++ = ctx->ref_frame.cb[i / 2];
|
|
|
+ *p++ = ctx->ref_frame.luma[i + 1];
|
|
|
+ *p++ = ctx->ref_frame.cr[i / 2];
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ case V4L2_PIX_FMT_YVYU:
|
|
|
+ for (i = 0, p = p_out; i < size; i += 2) {
|
|
|
+ *p++ = ctx->ref_frame.luma[i];
|
|
|
+ *p++ = ctx->ref_frame.cr[i / 2];
|
|
|
+ *p++ = ctx->ref_frame.luma[i + 1];
|
|
|
+ *p++ = ctx->ref_frame.cb[i / 2];
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ case V4L2_PIX_FMT_UYVY:
|
|
|
+ for (i = 0, p = p_out; i < size; i += 2) {
|
|
|
+ *p++ = ctx->ref_frame.cb[i / 2];
|
|
|
+ *p++ = ctx->ref_frame.luma[i];
|
|
|
+ *p++ = ctx->ref_frame.cr[i / 2];
|
|
|
+ *p++ = ctx->ref_frame.luma[i + 1];
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ case V4L2_PIX_FMT_VYUY:
|
|
|
+ for (i = 0, p = p_out; i < size; i += 2) {
|
|
|
+ *p++ = ctx->ref_frame.cr[i / 2];
|
|
|
+ *p++ = ctx->ref_frame.luma[i];
|
|
|
+ *p++ = ctx->ref_frame.cb[i / 2];
|
|
|
+ *p++ = ctx->ref_frame.luma[i + 1];
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ case V4L2_PIX_FMT_RGB24:
|
|
|
+ case V4L2_PIX_FMT_HSV24:
|
|
|
+ for (i = 0, p = p_out; i < size; i++) {
|
|
|
+ *p++ = ctx->ref_frame.cr[i];
|
|
|
+ *p++ = ctx->ref_frame.luma[i];
|
|
|
+ *p++ = ctx->ref_frame.cb[i];
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ case V4L2_PIX_FMT_BGR24:
|
|
|
+ for (i = 0, p = p_out; i < size; i++) {
|
|
|
+ *p++ = ctx->ref_frame.cb[i];
|
|
|
+ *p++ = ctx->ref_frame.luma[i];
|
|
|
+ *p++ = ctx->ref_frame.cr[i];
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ case V4L2_PIX_FMT_RGB32:
|
|
|
+ case V4L2_PIX_FMT_XRGB32:
|
|
|
+ case V4L2_PIX_FMT_HSV32:
|
|
|
+ for (i = 0, p = p_out; i < size; i++) {
|
|
|
+ *p++ = 0;
|
|
|
+ *p++ = ctx->ref_frame.cr[i];
|
|
|
+ *p++ = ctx->ref_frame.luma[i];
|
|
|
+ *p++ = ctx->ref_frame.cb[i];
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ case V4L2_PIX_FMT_BGR32:
|
|
|
+ case V4L2_PIX_FMT_XBGR32:
|
|
|
+ for (i = 0, p = p_out; i < size; i++) {
|
|
|
+ *p++ = ctx->ref_frame.cb[i];
|
|
|
+ *p++ = ctx->ref_frame.luma[i];
|
|
|
+ *p++ = ctx->ref_frame.cr[i];
|
|
|
+ *p++ = 0;
|
|
|
+ }
|
|
|
break;
|
|
|
}
|
|
|
return 0;
|
|
@@ -322,8 +493,7 @@ static int device_process(struct vicodec_ctx *ctx,
|
|
|
ret = decode(ctx, q_cap, p_in, p_out);
|
|
|
if (ret)
|
|
|
return ret;
|
|
|
- vb2_set_plane_payload(&out_vb->vb2_buf, 0,
|
|
|
- q_cap->width * q_cap->height * 3 / 2);
|
|
|
+ vb2_set_plane_payload(&out_vb->vb2_buf, 0, q_cap->sizeimage);
|
|
|
}
|
|
|
|
|
|
out_vb->sequence = q_cap->sequence++;
|
|
@@ -523,14 +693,14 @@ static void job_abort(void *priv)
|
|
|
* video ioctls
|
|
|
*/
|
|
|
|
|
|
-static u32 find_fmt(u32 fmt)
|
|
|
+static const struct pixfmt_info *find_fmt(u32 fmt)
|
|
|
{
|
|
|
unsigned int i;
|
|
|
|
|
|
- for (i = 0; i < ARRAY_SIZE(pixfmts_yuv); i++)
|
|
|
- if (pixfmts_yuv[i] == fmt)
|
|
|
- return fmt;
|
|
|
- return pixfmts_yuv[0];
|
|
|
+ for (i = 0; i < ARRAY_SIZE(pixfmts); i++)
|
|
|
+ if (pixfmts[i].id == fmt)
|
|
|
+ return &pixfmts[i];
|
|
|
+ return &pixfmts[0];
|
|
|
}
|
|
|
|
|
|
static int vidioc_querycap(struct file *file, void *priv,
|
|
@@ -550,17 +720,17 @@ static int vidioc_querycap(struct file *file, void *priv,
|
|
|
|
|
|
static int enum_fmt(struct v4l2_fmtdesc *f, bool is_enc, bool is_out)
|
|
|
{
|
|
|
- bool is_yuv = (is_enc && is_out) || (!is_enc && !is_out);
|
|
|
+ bool is_uncomp = (is_enc && is_out) || (!is_enc && !is_out);
|
|
|
|
|
|
if (V4L2_TYPE_IS_MULTIPLANAR(f->type) && !multiplanar)
|
|
|
return -EINVAL;
|
|
|
if (!V4L2_TYPE_IS_MULTIPLANAR(f->type) && multiplanar)
|
|
|
return -EINVAL;
|
|
|
- if (f->index >= (is_yuv ? ARRAY_SIZE(pixfmts_yuv) : 1))
|
|
|
+ if (f->index >= (is_uncomp ? ARRAY_SIZE(pixfmts) : 1))
|
|
|
return -EINVAL;
|
|
|
|
|
|
- if (is_yuv)
|
|
|
- f->pixelformat = pixfmts_yuv[f->index];
|
|
|
+ if (is_uncomp)
|
|
|
+ f->pixelformat = pixfmts[f->index].id;
|
|
|
else
|
|
|
f->pixelformat = V4L2_PIX_FMT_FWHT;
|
|
|
return 0;
|
|
@@ -588,12 +758,14 @@ static int vidioc_g_fmt(struct vicodec_ctx *ctx, struct v4l2_format *f)
|
|
|
struct vicodec_q_data *q_data;
|
|
|
struct v4l2_pix_format_mplane *pix_mp;
|
|
|
struct v4l2_pix_format *pix;
|
|
|
+ const struct pixfmt_info *info;
|
|
|
|
|
|
vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx, f->type);
|
|
|
if (!vq)
|
|
|
return -EINVAL;
|
|
|
|
|
|
q_data = get_q_data(ctx, f->type);
|
|
|
+ info = q_data->info;
|
|
|
|
|
|
switch (f->type) {
|
|
|
case V4L2_BUF_TYPE_VIDEO_CAPTURE:
|
|
@@ -604,11 +776,8 @@ static int vidioc_g_fmt(struct vicodec_ctx *ctx, struct v4l2_format *f)
|
|
|
pix->width = q_data->width;
|
|
|
pix->height = q_data->height;
|
|
|
pix->field = V4L2_FIELD_NONE;
|
|
|
- pix->pixelformat = q_data->fourcc;
|
|
|
- if (q_data->fourcc == V4L2_PIX_FMT_FWHT)
|
|
|
- pix->bytesperline = 0;
|
|
|
- else
|
|
|
- pix->bytesperline = q_data->width;
|
|
|
+ pix->pixelformat = info->id;
|
|
|
+ pix->bytesperline = q_data->width * info->bytesperline_mult;
|
|
|
pix->sizeimage = q_data->sizeimage;
|
|
|
pix->colorspace = ctx->colorspace;
|
|
|
pix->xfer_func = ctx->xfer_func;
|
|
@@ -624,12 +793,10 @@ static int vidioc_g_fmt(struct vicodec_ctx *ctx, struct v4l2_format *f)
|
|
|
pix_mp->width = q_data->width;
|
|
|
pix_mp->height = q_data->height;
|
|
|
pix_mp->field = V4L2_FIELD_NONE;
|
|
|
- pix_mp->pixelformat = q_data->fourcc;
|
|
|
+ pix_mp->pixelformat = info->id;
|
|
|
pix_mp->num_planes = 1;
|
|
|
- if (q_data->fourcc == V4L2_PIX_FMT_FWHT)
|
|
|
- pix_mp->plane_fmt[0].bytesperline = 0;
|
|
|
- else
|
|
|
- pix_mp->plane_fmt[0].bytesperline = q_data->width;
|
|
|
+ pix_mp->plane_fmt[0].bytesperline =
|
|
|
+ q_data->width * info->bytesperline_mult;
|
|
|
pix_mp->plane_fmt[0].sizeimage = q_data->sizeimage;
|
|
|
pix_mp->colorspace = ctx->colorspace;
|
|
|
pix_mp->xfer_func = ctx->xfer_func;
|
|
@@ -661,40 +828,44 @@ static int vidioc_try_fmt(struct vicodec_ctx *ctx, struct v4l2_format *f)
|
|
|
{
|
|
|
struct v4l2_pix_format_mplane *pix_mp;
|
|
|
struct v4l2_pix_format *pix;
|
|
|
+ struct v4l2_plane_pix_format *plane;
|
|
|
+ const struct pixfmt_info *info = &pixfmt_fwht;
|
|
|
|
|
|
switch (f->type) {
|
|
|
case V4L2_BUF_TYPE_VIDEO_CAPTURE:
|
|
|
case V4L2_BUF_TYPE_VIDEO_OUTPUT:
|
|
|
pix = &f->fmt.pix;
|
|
|
+ if (pix->pixelformat != V4L2_PIX_FMT_FWHT)
|
|
|
+ info = find_fmt(pix->pixelformat);
|
|
|
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->bytesperline =
|
|
|
+ pix->width * info->bytesperline_mult;
|
|
|
+ pix->sizeimage = pix->width * pix->height *
|
|
|
+ info->sizeimage_mult / info->sizeimage_div;
|
|
|
+ if (pix->pixelformat == V4L2_PIX_FMT_FWHT)
|
|
|
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;
|
|
|
+ plane = pix_mp->plane_fmt;
|
|
|
+ if (pix_mp->pixelformat != V4L2_PIX_FMT_FWHT)
|
|
|
+ info = find_fmt(pix_mp->pixelformat);
|
|
|
+ pix_mp->num_planes = 1;
|
|
|
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;
|
|
|
- pix_mp->num_planes = 1;
|
|
|
- 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);
|
|
|
- }
|
|
|
+ plane->bytesperline =
|
|
|
+ pix_mp->width * info->bytesperline_mult;
|
|
|
+ plane->sizeimage = pix_mp->width * pix_mp->height *
|
|
|
+ info->sizeimage_mult / info->sizeimage_div;
|
|
|
+ if (pix_mp->pixelformat == V4L2_PIX_FMT_FWHT)
|
|
|
+ plane->sizeimage += sizeof(struct cframe_hdr);
|
|
|
memset(pix_mp->reserved, 0, sizeof(pix_mp->reserved));
|
|
|
- memset(pix_mp->plane_fmt[0].reserved, 0,
|
|
|
- sizeof(pix_mp->plane_fmt[0].reserved));
|
|
|
+ memset(plane->reserved, 0, sizeof(plane->reserved));
|
|
|
break;
|
|
|
default:
|
|
|
return -EINVAL;
|
|
@@ -716,7 +887,7 @@ static int vidioc_try_fmt_vid_cap(struct file *file, void *priv,
|
|
|
return -EINVAL;
|
|
|
pix = &f->fmt.pix;
|
|
|
pix->pixelformat = ctx->is_enc ? V4L2_PIX_FMT_FWHT :
|
|
|
- find_fmt(f->fmt.pix.pixelformat);
|
|
|
+ find_fmt(f->fmt.pix.pixelformat)->id;
|
|
|
pix->colorspace = ctx->colorspace;
|
|
|
pix->xfer_func = ctx->xfer_func;
|
|
|
pix->ycbcr_enc = ctx->ycbcr_enc;
|
|
@@ -727,14 +898,11 @@ static int vidioc_try_fmt_vid_cap(struct file *file, void *priv,
|
|
|
return -EINVAL;
|
|
|
pix_mp = &f->fmt.pix_mp;
|
|
|
pix_mp->pixelformat = ctx->is_enc ? V4L2_PIX_FMT_FWHT :
|
|
|
- find_fmt(pix_mp->pixelformat);
|
|
|
+ find_fmt(pix_mp->pixelformat)->id;
|
|
|
pix_mp->colorspace = ctx->colorspace;
|
|
|
pix_mp->xfer_func = ctx->xfer_func;
|
|
|
pix_mp->ycbcr_enc = ctx->ycbcr_enc;
|
|
|
pix_mp->quantization = ctx->quantization;
|
|
|
- memset(pix_mp->reserved, 0, sizeof(pix_mp->reserved));
|
|
|
- memset(pix_mp->plane_fmt[0].reserved, 0,
|
|
|
- sizeof(pix_mp->plane_fmt[0].reserved));
|
|
|
break;
|
|
|
default:
|
|
|
return -EINVAL;
|
|
@@ -756,7 +924,7 @@ static int vidioc_try_fmt_vid_out(struct file *file, void *priv,
|
|
|
return -EINVAL;
|
|
|
pix = &f->fmt.pix;
|
|
|
pix->pixelformat = !ctx->is_enc ? V4L2_PIX_FMT_FWHT :
|
|
|
- find_fmt(pix->pixelformat);
|
|
|
+ find_fmt(pix->pixelformat)->id;
|
|
|
if (!pix->colorspace)
|
|
|
pix->colorspace = V4L2_COLORSPACE_REC709;
|
|
|
break;
|
|
@@ -765,7 +933,7 @@ static int vidioc_try_fmt_vid_out(struct file *file, void *priv,
|
|
|
return -EINVAL;
|
|
|
pix_mp = &f->fmt.pix_mp;
|
|
|
pix_mp->pixelformat = !ctx->is_enc ? V4L2_PIX_FMT_FWHT :
|
|
|
- find_fmt(pix_mp->pixelformat);
|
|
|
+ find_fmt(pix_mp->pixelformat)->id;
|
|
|
if (!pix_mp->colorspace)
|
|
|
pix_mp->colorspace = V4L2_COLORSPACE_REC709;
|
|
|
break;
|
|
@@ -798,14 +966,17 @@ static int vidioc_s_fmt(struct vicodec_ctx *ctx, struct v4l2_format *f)
|
|
|
pix = &f->fmt.pix;
|
|
|
if (ctx->is_enc && V4L2_TYPE_IS_OUTPUT(f->type))
|
|
|
fmt_changed =
|
|
|
- q_data->fourcc != pix->pixelformat ||
|
|
|
+ q_data->info->id != pix->pixelformat ||
|
|
|
q_data->width != pix->width ||
|
|
|
q_data->height != pix->height;
|
|
|
|
|
|
if (vb2_is_busy(vq) && fmt_changed)
|
|
|
return -EBUSY;
|
|
|
|
|
|
- q_data->fourcc = pix->pixelformat;
|
|
|
+ if (pix->pixelformat == V4L2_PIX_FMT_FWHT)
|
|
|
+ q_data->info = &pixfmt_fwht;
|
|
|
+ else
|
|
|
+ q_data->info = find_fmt(pix->pixelformat);
|
|
|
q_data->width = pix->width;
|
|
|
q_data->height = pix->height;
|
|
|
q_data->sizeimage = pix->sizeimage;
|
|
@@ -815,14 +986,17 @@ static int vidioc_s_fmt(struct vicodec_ctx *ctx, struct v4l2_format *f)
|
|
|
pix_mp = &f->fmt.pix_mp;
|
|
|
if (ctx->is_enc && V4L2_TYPE_IS_OUTPUT(f->type))
|
|
|
fmt_changed =
|
|
|
- q_data->fourcc != pix_mp->pixelformat ||
|
|
|
+ q_data->info->id != pix_mp->pixelformat ||
|
|
|
q_data->width != pix_mp->width ||
|
|
|
q_data->height != pix_mp->height;
|
|
|
|
|
|
if (vb2_is_busy(vq) && fmt_changed)
|
|
|
return -EBUSY;
|
|
|
|
|
|
- q_data->fourcc = pix_mp->pixelformat;
|
|
|
+ if (pix_mp->pixelformat == V4L2_PIX_FMT_FWHT)
|
|
|
+ q_data->info = &pixfmt_fwht;
|
|
|
+ else
|
|
|
+ q_data->info = find_fmt(pix_mp->pixelformat);
|
|
|
q_data->width = pix_mp->width;
|
|
|
q_data->height = pix_mp->height;
|
|
|
q_data->sizeimage = pix_mp->plane_fmt[0].sizeimage;
|
|
@@ -833,7 +1007,7 @@ static int vidioc_s_fmt(struct vicodec_ctx *ctx, struct v4l2_format *f)
|
|
|
|
|
|
dprintk(ctx->dev,
|
|
|
"Setting format for type %d, wxh: %dx%d, fourcc: %08x\n",
|
|
|
- f->type, q_data->width, q_data->height, q_data->fourcc);
|
|
|
+ f->type, q_data->width, q_data->height, q_data->info->id);
|
|
|
|
|
|
return 0;
|
|
|
}
|
|
@@ -965,7 +1139,7 @@ static int vicodec_enum_framesizes(struct file *file, void *fh,
|
|
|
case V4L2_PIX_FMT_FWHT:
|
|
|
break;
|
|
|
default:
|
|
|
- if (find_fmt(fsize->pixel_format) == fsize->pixel_format)
|
|
|
+ if (find_fmt(fsize->pixel_format)->id == fsize->pixel_format)
|
|
|
break;
|
|
|
return -EINVAL;
|
|
|
}
|
|
@@ -1123,6 +1297,8 @@ static int vicodec_start_streaming(struct vb2_queue *q,
|
|
|
struct vicodec_ctx *ctx = vb2_get_drv_priv(q);
|
|
|
struct vicodec_q_data *q_data = get_q_data(ctx, q->type);
|
|
|
unsigned int size = q_data->width * q_data->height;
|
|
|
+ const struct pixfmt_info *info = q_data->info;
|
|
|
+ unsigned int chroma_div = info->width_div * info->height_div;
|
|
|
|
|
|
q_data->sequence = 0;
|
|
|
|
|
@@ -1130,8 +1306,9 @@ static int vicodec_start_streaming(struct vb2_queue *q,
|
|
|
return 0;
|
|
|
|
|
|
ctx->ref_frame.width = ctx->ref_frame.height = 0;
|
|
|
- ctx->ref_frame.luma = kvmalloc(size * 3 / 2, GFP_KERNEL);
|
|
|
- ctx->comp_max_size = size * 3 / 2 + sizeof(struct cframe_hdr);
|
|
|
+ ctx->ref_frame.luma = kvmalloc(size + 2 * size / chroma_div, GFP_KERNEL);
|
|
|
+ ctx->comp_max_size = size + 2 * size / chroma_div +
|
|
|
+ sizeof(struct cframe_hdr);
|
|
|
ctx->compressed_frame = kvmalloc(ctx->comp_max_size, GFP_KERNEL);
|
|
|
if (!ctx->ref_frame.luma || !ctx->compressed_frame) {
|
|
|
kvfree(ctx->ref_frame.luma);
|
|
@@ -1140,7 +1317,7 @@ static int vicodec_start_streaming(struct vb2_queue *q,
|
|
|
return -ENOMEM;
|
|
|
}
|
|
|
ctx->ref_frame.cb = ctx->ref_frame.luma + size;
|
|
|
- ctx->ref_frame.cr = ctx->ref_frame.cb + size / 4;
|
|
|
+ ctx->ref_frame.cr = ctx->ref_frame.cb + size / chroma_div;
|
|
|
ctx->last_src_buf = NULL;
|
|
|
ctx->last_dst_buf = NULL;
|
|
|
ctx->gop_cnt = 0;
|
|
@@ -1301,15 +1478,19 @@ static int vicodec_open(struct file *file)
|
|
|
ctx->fh.ctrl_handler = hdl;
|
|
|
v4l2_ctrl_handler_setup(hdl);
|
|
|
|
|
|
- ctx->q_data[V4L2_M2M_SRC].fourcc =
|
|
|
- ctx->is_enc ? V4L2_PIX_FMT_YUV420 : V4L2_PIX_FMT_FWHT;
|
|
|
+ ctx->q_data[V4L2_M2M_SRC].info =
|
|
|
+ ctx->is_enc ? pixfmts : &pixfmt_fwht;
|
|
|
ctx->q_data[V4L2_M2M_SRC].width = 1280;
|
|
|
ctx->q_data[V4L2_M2M_SRC].height = 720;
|
|
|
- size = 1280 * 720 * 3 / 2;
|
|
|
+ size = 1280 * 720 * ctx->q_data[V4L2_M2M_SRC].info->sizeimage_mult /
|
|
|
+ ctx->q_data[V4L2_M2M_SRC].info->sizeimage_div;
|
|
|
ctx->q_data[V4L2_M2M_SRC].sizeimage = size;
|
|
|
ctx->q_data[V4L2_M2M_DST] = ctx->q_data[V4L2_M2M_SRC];
|
|
|
- ctx->q_data[V4L2_M2M_DST].fourcc =
|
|
|
- ctx->is_enc ? V4L2_PIX_FMT_FWHT : V4L2_PIX_FMT_YUV420;
|
|
|
+ ctx->q_data[V4L2_M2M_DST].info =
|
|
|
+ ctx->is_enc ? &pixfmt_fwht : pixfmts;
|
|
|
+ size = 1280 * 720 * ctx->q_data[V4L2_M2M_DST].info->sizeimage_mult /
|
|
|
+ ctx->q_data[V4L2_M2M_DST].info->sizeimage_div;
|
|
|
+ ctx->q_data[V4L2_M2M_DST].sizeimage = size;
|
|
|
ctx->colorspace = V4L2_COLORSPACE_REC709;
|
|
|
|
|
|
size += sizeof(struct cframe_hdr);
|