media: vicodec: Add support of greyscale format
authorDafna Hirschfeld <dafna3@gmail.com>
Thu, 15 Nov 2018 11:23:31 +0000 (06:23 -0500)
committerMauro Carvalho Chehab <mchehab+samsung@kernel.org>
Fri, 23 Nov 2018 09:34:29 +0000 (04:34 -0500)
Add support for single plane greyscale format V4L2_PIX_FMT_GREY.
Also change the header of the encoded file to include the number
of components.

Signed-off-by: Dafna Hirschfeld <dafna3@gmail.com>
Signed-off-by: Hans Verkuil <hverkuil@xs4all.nl>
[hans.verkuil@cisco.com: fix line-too-long warnings]
Signed-off-by: Mauro Carvalho Chehab <mchehab+samsung@kernel.org>
drivers/media/platform/vicodec/codec-fwht.c
drivers/media/platform/vicodec/codec-fwht.h
drivers/media/platform/vicodec/codec-v4l2-fwht.c
drivers/media/platform/vicodec/vicodec-core.c

index 4ee6d7e0fbe2e3068e7fa8f8c5f86bd219707350..e5cc3434299fd4dec93e9948147e5b4d98a99274 100644 (file)
@@ -753,9 +753,6 @@ u32 fwht_encode_frame(struct fwht_raw_frame *frm,
        __be16 *rlco = cf->rlc_data;
        __be16 *rlco_max;
        u32 encoding;
-       u32 chroma_h = frm->height / frm->height_div;
-       u32 chroma_w = frm->width / frm->width_div;
-       unsigned int chroma_size = chroma_h * chroma_w;
 
        rlco_max = rlco + size / 2 - 256;
        encoding = encode_plane(frm->luma, ref_frm->luma, &rlco, rlco_max, cf,
@@ -764,20 +761,29 @@ u32 fwht_encode_frame(struct fwht_raw_frame *frm,
        if (encoding & FWHT_FRAME_UNENCODED)
                encoding |= FWHT_LUMA_UNENCODED;
        encoding &= ~FWHT_FRAME_UNENCODED;
-       rlco_max = rlco + chroma_size / 2 - 256;
-       encoding |= encode_plane(frm->cb, ref_frm->cb, &rlco, rlco_max, cf,
-                                chroma_h, chroma_w,
-                                frm->chroma_step, is_intra, next_is_intra);
-       if (encoding & FWHT_FRAME_UNENCODED)
-               encoding |= FWHT_CB_UNENCODED;
-       encoding &= ~FWHT_FRAME_UNENCODED;
-       rlco_max = rlco + chroma_size / 2 - 256;
-       encoding |= encode_plane(frm->cr, ref_frm->cr, &rlco, rlco_max, cf,
-                                chroma_h, chroma_w,
-                                frm->chroma_step, is_intra, next_is_intra);
-       if (encoding & FWHT_FRAME_UNENCODED)
-               encoding |= FWHT_CR_UNENCODED;
-       encoding &= ~FWHT_FRAME_UNENCODED;
+
+       if (frm->components_num >= 3) {
+               u32 chroma_h = frm->height / frm->height_div;
+               u32 chroma_w = frm->width / frm->width_div;
+               unsigned int chroma_size = chroma_h * chroma_w;
+
+               rlco_max = rlco + chroma_size / 2 - 256;
+               encoding |= encode_plane(frm->cb, ref_frm->cb, &rlco, rlco_max,
+                                        cf, chroma_h, chroma_w,
+                                        frm->chroma_step,
+                                        is_intra, next_is_intra);
+               if (encoding & FWHT_FRAME_UNENCODED)
+                       encoding |= FWHT_CB_UNENCODED;
+               encoding &= ~FWHT_FRAME_UNENCODED;
+               rlco_max = rlco + chroma_size / 2 - 256;
+               encoding |= encode_plane(frm->cr, ref_frm->cr, &rlco, rlco_max,
+                                        cf, chroma_h, chroma_w,
+                                        frm->chroma_step,
+                                        is_intra, next_is_intra);
+               if (encoding & FWHT_FRAME_UNENCODED)
+                       encoding |= FWHT_CR_UNENCODED;
+               encoding &= ~FWHT_FRAME_UNENCODED;
+       }
        cf->size = (rlco - cf->rlc_data) * sizeof(*rlco);
        return encoding;
 }
@@ -836,20 +842,24 @@ static void decode_plane(struct fwht_cframe *cf, const __be16 **rlco, u8 *ref,
 }
 
 void fwht_decode_frame(struct fwht_cframe *cf, struct fwht_raw_frame *ref,
-                      u32 hdr_flags)
+                      u32 hdr_flags, unsigned int components_num)
 {
        const __be16 *rlco = cf->rlc_data;
-       u32 h = cf->height / 2;
-       u32 w = cf->width / 2;
 
-       if (hdr_flags & FWHT_FL_CHROMA_FULL_HEIGHT)
-               h *= 2;
-       if (hdr_flags & FWHT_FL_CHROMA_FULL_WIDTH)
-               w *= 2;
        decode_plane(cf, &rlco, ref->luma, cf->height, cf->width,
                     hdr_flags & FWHT_FL_LUMA_IS_UNCOMPRESSED);
-       decode_plane(cf, &rlco, ref->cb, h, w,
-                    hdr_flags & FWHT_FL_CB_IS_UNCOMPRESSED);
-       decode_plane(cf, &rlco, ref->cr, h, w,
-                    hdr_flags & FWHT_FL_CR_IS_UNCOMPRESSED);
+
+       if (components_num >= 3) {
+               u32 h = cf->height;
+               u32 w = cf->width;
+
+               if (!(hdr_flags & FWHT_FL_CHROMA_FULL_HEIGHT))
+                       h /= 2;
+               if (!(hdr_flags & FWHT_FL_CHROMA_FULL_WIDTH))
+                       w /= 2;
+               decode_plane(cf, &rlco, ref->cb, h, w,
+                            hdr_flags & FWHT_FL_CB_IS_UNCOMPRESSED);
+               decode_plane(cf, &rlco, ref->cr, h, w,
+                            hdr_flags & FWHT_FL_CR_IS_UNCOMPRESSED);
+       }
 }
index 743d78e112f886e007e7d06d4d835eb83a4edbb1..bde11fb93f269e5f9d711861b8b1c0a1324bad26 100644 (file)
@@ -56,7 +56,7 @@
 #define FWHT_MAGIC1 0x4f4f4f4f
 #define FWHT_MAGIC2 0xffffffff
 
-#define FWHT_VERSION 1
+#define FWHT_VERSION 2
 
 /* Set if this is an interlaced format */
 #define FWHT_FL_IS_INTERLACED          BIT(0)
 #define FWHT_FL_CHROMA_FULL_HEIGHT     BIT(7)
 #define FWHT_FL_CHROMA_FULL_WIDTH      BIT(8)
 
+/* A 4-values flag - the number of components - 1 */
+#define FWHT_FL_COMPONENTS_NUM_MSK     GENMASK(17, 16)
+#define FWHT_FL_COMPONENTS_NUM_OFFSET  16
+
 struct fwht_cframe_hdr {
        u32 magic1;
        u32 magic2;
@@ -121,6 +125,6 @@ u32 fwht_encode_frame(struct fwht_raw_frame *frm,
                      struct fwht_cframe *cf,
                      bool is_intra, bool next_is_intra);
 void fwht_decode_frame(struct fwht_cframe *cf, struct fwht_raw_frame *ref,
-                      u32 hdr_flags);
+                      u32 hdr_flags, unsigned int components_num);
 
 #endif
index b842636e71a919fd7f2c7307bb14e701ef46c2b4..f8f86204d9aa2f4773480e8a3a5a063a6fcc3a24 100644 (file)
@@ -11,6 +11,7 @@
 #include "codec-v4l2-fwht.h"
 
 static const struct v4l2_fwht_pixfmt_info v4l2_fwht_pixfmts[] = {
+       { V4L2_PIX_FMT_GREY,    1, 1, 1, 1, 0, 1, 1, 1},
        { V4L2_PIX_FMT_YUV420,  1, 3, 2, 1, 1, 2, 2, 3},
        { V4L2_PIX_FMT_YVU420,  1, 3, 2, 1, 1, 2, 2, 3},
        { V4L2_PIX_FMT_YUV422P, 1, 2, 1, 1, 1, 2, 1, 3},
@@ -75,6 +76,10 @@ int v4l2_fwht_encode(struct v4l2_fwht_state *state, u8 *p_in, u8 *p_out)
        rf.components_num = info->components_num;
 
        switch (info->id) {
+       case V4L2_PIX_FMT_GREY:
+               rf.cb = NULL;
+               rf.cr = NULL;
+               break;
        case V4L2_PIX_FMT_YUV420:
                rf.cb = rf.luma + size;
                rf.cr = rf.cb + size / 4;
@@ -165,6 +170,7 @@ int v4l2_fwht_encode(struct v4l2_fwht_state *state, u8 *p_in, u8 *p_out)
        p_hdr->version = htonl(FWHT_VERSION);
        p_hdr->width = htonl(cf.width);
        p_hdr->height = htonl(cf.height);
+       flags |= (info->components_num - 1) << FWHT_FL_COMPONENTS_NUM_OFFSET;
        if (encoding & FWHT_LUMA_UNENCODED)
                flags |= FWHT_FL_LUMA_IS_UNCOMPRESSED;
        if (encoding & FWHT_CB_UNENCODED)
@@ -195,6 +201,8 @@ int v4l2_fwht_decode(struct v4l2_fwht_state *state, u8 *p_in, u8 *p_out)
        struct fwht_cframe_hdr *p_hdr;
        struct fwht_cframe cf;
        u8 *p;
+       unsigned int components_num = 3;
+       unsigned int version;
 
        if (!state->info)
                return -EINVAL;
@@ -202,16 +210,16 @@ int v4l2_fwht_decode(struct v4l2_fwht_state *state, u8 *p_in, u8 *p_out)
        p_hdr = (struct fwht_cframe_hdr *)p_in;
        cf.width = ntohl(p_hdr->width);
        cf.height = ntohl(p_hdr->height);
-       flags = ntohl(p_hdr->flags);
-       state->colorspace = ntohl(p_hdr->colorspace);
-       state->xfer_func = ntohl(p_hdr->xfer_func);
-       state->ycbcr_enc = ntohl(p_hdr->ycbcr_enc);
-       state->quantization = ntohl(p_hdr->quantization);
-       cf.rlc_data = (__be16 *)(p_in + sizeof(*p_hdr));
+
+       version = ntohl(p_hdr->version);
+       if (!version || version > FWHT_VERSION) {
+               pr_err("version %d is not supported, current version is %d\n",
+                      version, FWHT_VERSION);
+               return -EINVAL;
+       }
 
        if (p_hdr->magic1 != FWHT_MAGIC1 ||
            p_hdr->magic2 != FWHT_MAGIC2 ||
-           ntohl(p_hdr->version) != FWHT_VERSION ||
            (cf.width & 7) || (cf.height & 7))
                return -EINVAL;
 
@@ -219,14 +227,34 @@ int v4l2_fwht_decode(struct v4l2_fwht_state *state, u8 *p_in, u8 *p_out)
        if (cf.width != state->width || cf.height != state->height)
                return -EINVAL;
 
+       flags = ntohl(p_hdr->flags);
+
+       if (version == FWHT_VERSION) {
+               components_num = 1 + ((flags & FWHT_FL_COMPONENTS_NUM_MSK) >>
+                       FWHT_FL_COMPONENTS_NUM_OFFSET);
+       }
+
+       state->colorspace = ntohl(p_hdr->colorspace);
+       state->xfer_func = ntohl(p_hdr->xfer_func);
+       state->ycbcr_enc = ntohl(p_hdr->ycbcr_enc);
+       state->quantization = ntohl(p_hdr->quantization);
+       cf.rlc_data = (__be16 *)(p_in + sizeof(*p_hdr));
+
        if (!(flags & FWHT_FL_CHROMA_FULL_WIDTH))
                chroma_size /= 2;
        if (!(flags & FWHT_FL_CHROMA_FULL_HEIGHT))
                chroma_size /= 2;
 
-       fwht_decode_frame(&cf, &state->ref_frame, flags);
+       fwht_decode_frame(&cf, &state->ref_frame, flags, components_num);
 
+       /*
+        * TODO - handle the case where the compressed stream encodes a
+        * different format than the requested decoded format.
+        */
        switch (state->info->id) {
+       case V4L2_PIX_FMT_GREY:
+               memcpy(p_out, state->ref_frame.luma, size);
+               break;
        case V4L2_PIX_FMT_YUV420:
        case V4L2_PIX_FMT_YUV422P:
                memcpy(p_out, state->ref_frame.luma, size);
index b26ca043e8c31cb6becf0638b79971468e59d7cf..b67fb5d7a620ad56b44a92aaba89f417cc2ba6e9 100644 (file)
@@ -988,6 +988,16 @@ static int vicodec_start_streaming(struct vb2_queue *q,
        unsigned int size = q_data->width * q_data->height;
        const struct v4l2_fwht_pixfmt_info *info = q_data->info;
        unsigned int chroma_div = info->width_div * info->height_div;
+       unsigned int total_planes_size;
+
+       /*
+        * we don't know ahead how many components are in the encoding type
+        * V4L2_PIX_FMT_FWHT, so we will allocate space for 3 planes.
+        */
+       if (info->id == V4L2_PIX_FMT_FWHT || info->components_num >= 3)
+               total_planes_size = size + 2 * (size / chroma_div);
+       else
+               total_planes_size = size;
 
        q_data->sequence = 0;
 
@@ -997,10 +1007,8 @@ static int vicodec_start_streaming(struct vb2_queue *q,
        state->width = q_data->width;
        state->height = q_data->height;
        state->ref_frame.width = state->ref_frame.height = 0;
-       state->ref_frame.luma = kvmalloc(size + 2 * size / chroma_div,
-                                        GFP_KERNEL);
-       ctx->comp_max_size = size + 2 * size / chroma_div +
-                            sizeof(struct fwht_cframe_hdr);
+       state->ref_frame.luma = kvmalloc(total_planes_size, GFP_KERNEL);
+       ctx->comp_max_size = total_planes_size + sizeof(struct fwht_cframe_hdr);
        state->compressed_frame = kvmalloc(ctx->comp_max_size, GFP_KERNEL);
        if (!state->ref_frame.luma || !state->compressed_frame) {
                kvfree(state->ref_frame.luma);
@@ -1008,8 +1016,13 @@ static int vicodec_start_streaming(struct vb2_queue *q,
                vicodec_return_bufs(q, VB2_BUF_STATE_QUEUED);
                return -ENOMEM;
        }
-       state->ref_frame.cb = state->ref_frame.luma + size;
-       state->ref_frame.cr = state->ref_frame.cb + size / chroma_div;
+       if (info->id == V4L2_PIX_FMT_FWHT || info->components_num >= 3) {
+               state->ref_frame.cb = state->ref_frame.luma + size;
+               state->ref_frame.cr = state->ref_frame.cb + size / chroma_div;
+       } else {
+               state->ref_frame.cb = NULL;
+               state->ref_frame.cr = NULL;
+       }
        ctx->last_src_buf = NULL;
        ctx->last_dst_buf = NULL;
        state->gop_cnt = 0;