root/drivers/media/platform/vicodec/codec-v4l2-fwht.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. v4l2_fwht_validate_fmt
  2. v4l2_fwht_find_nth_fmt
  3. v4l2_fwht_find_pixfmt
  4. v4l2_fwht_get_pixfmt
  5. prepare_raw_frame
  6. v4l2_fwht_encode
  7. v4l2_fwht_decode

   1 // SPDX-License-Identifier: LGPL-2.1
   2 /*
   3  * A V4L2 frontend for the FWHT codec
   4  *
   5  * Copyright 2018 Cisco Systems, Inc. and/or its affiliates. All rights reserved.
   6  */
   7 
   8 #include <linux/errno.h>
   9 #include <linux/string.h>
  10 #include <linux/videodev2.h>
  11 #include "codec-v4l2-fwht.h"
  12 
  13 static const struct v4l2_fwht_pixfmt_info v4l2_fwht_pixfmts[] = {
  14         { V4L2_PIX_FMT_YUV420,  1, 3, 2, 1, 1, 2, 2, 3, 3, FWHT_FL_PIXENC_YUV},
  15         { V4L2_PIX_FMT_YVU420,  1, 3, 2, 1, 1, 2, 2, 3, 3, FWHT_FL_PIXENC_YUV},
  16         { V4L2_PIX_FMT_YUV422P, 1, 2, 1, 1, 1, 2, 1, 3, 3, FWHT_FL_PIXENC_YUV},
  17         { V4L2_PIX_FMT_NV12,    1, 3, 2, 1, 2, 2, 2, 3, 2, FWHT_FL_PIXENC_YUV},
  18         { V4L2_PIX_FMT_NV21,    1, 3, 2, 1, 2, 2, 2, 3, 2, FWHT_FL_PIXENC_YUV},
  19         { V4L2_PIX_FMT_NV16,    1, 2, 1, 1, 2, 2, 1, 3, 2, FWHT_FL_PIXENC_YUV},
  20         { V4L2_PIX_FMT_NV61,    1, 2, 1, 1, 2, 2, 1, 3, 2, FWHT_FL_PIXENC_YUV},
  21         { V4L2_PIX_FMT_NV24,    1, 3, 1, 1, 2, 1, 1, 3, 2, FWHT_FL_PIXENC_YUV},
  22         { V4L2_PIX_FMT_NV42,    1, 3, 1, 1, 2, 1, 1, 3, 2, FWHT_FL_PIXENC_YUV},
  23         { V4L2_PIX_FMT_YUYV,    2, 2, 1, 2, 4, 2, 1, 3, 1, FWHT_FL_PIXENC_YUV},
  24         { V4L2_PIX_FMT_YVYU,    2, 2, 1, 2, 4, 2, 1, 3, 1, FWHT_FL_PIXENC_YUV},
  25         { V4L2_PIX_FMT_UYVY,    2, 2, 1, 2, 4, 2, 1, 3, 1, FWHT_FL_PIXENC_YUV},
  26         { V4L2_PIX_FMT_VYUY,    2, 2, 1, 2, 4, 2, 1, 3, 1, FWHT_FL_PIXENC_YUV},
  27         { V4L2_PIX_FMT_BGR24,   3, 3, 1, 3, 3, 1, 1, 3, 1, FWHT_FL_PIXENC_RGB},
  28         { V4L2_PIX_FMT_RGB24,   3, 3, 1, 3, 3, 1, 1, 3, 1, FWHT_FL_PIXENC_RGB},
  29         { V4L2_PIX_FMT_HSV24,   3, 3, 1, 3, 3, 1, 1, 3, 1, FWHT_FL_PIXENC_HSV},
  30         { V4L2_PIX_FMT_BGR32,   4, 4, 1, 4, 4, 1, 1, 4, 1, FWHT_FL_PIXENC_RGB},
  31         { V4L2_PIX_FMT_XBGR32,  4, 4, 1, 4, 4, 1, 1, 4, 1, FWHT_FL_PIXENC_RGB},
  32         { V4L2_PIX_FMT_ABGR32,  4, 4, 1, 4, 4, 1, 1, 4, 1, FWHT_FL_PIXENC_RGB},
  33         { V4L2_PIX_FMT_RGB32,   4, 4, 1, 4, 4, 1, 1, 4, 1, FWHT_FL_PIXENC_RGB},
  34         { V4L2_PIX_FMT_XRGB32,  4, 4, 1, 4, 4, 1, 1, 4, 1, FWHT_FL_PIXENC_RGB},
  35         { V4L2_PIX_FMT_ARGB32,  4, 4, 1, 4, 4, 1, 1, 4, 1, FWHT_FL_PIXENC_RGB},
  36         { V4L2_PIX_FMT_BGRX32,  4, 4, 1, 4, 4, 1, 1, 4, 1, FWHT_FL_PIXENC_RGB},
  37         { V4L2_PIX_FMT_BGRA32,  4, 4, 1, 4, 4, 1, 1, 4, 1, FWHT_FL_PIXENC_RGB},
  38         { V4L2_PIX_FMT_RGBX32,  4, 4, 1, 4, 4, 1, 1, 4, 1, FWHT_FL_PIXENC_RGB},
  39         { V4L2_PIX_FMT_RGBA32,  4, 4, 1, 4, 4, 1, 1, 4, 1, FWHT_FL_PIXENC_RGB},
  40         { V4L2_PIX_FMT_HSV32,   4, 4, 1, 4, 4, 1, 1, 4, 1, FWHT_FL_PIXENC_HSV},
  41         { V4L2_PIX_FMT_GREY,    1, 1, 1, 1, 0, 1, 1, 1, 1, FWHT_FL_PIXENC_RGB},
  42 };
  43 
  44 bool v4l2_fwht_validate_fmt(const struct v4l2_fwht_pixfmt_info *info,
  45                             u32 width_div, u32 height_div, u32 components_num,
  46                             u32 pixenc)
  47 {
  48         if (info->width_div == width_div &&
  49             info->height_div == height_div &&
  50             (!pixenc || info->pixenc == pixenc) &&
  51             info->components_num == components_num)
  52                 return true;
  53         return false;
  54 }
  55 
  56 const struct v4l2_fwht_pixfmt_info *v4l2_fwht_find_nth_fmt(u32 width_div,
  57                                                           u32 height_div,
  58                                                           u32 components_num,
  59                                                           u32 pixenc,
  60                                                           unsigned int start_idx)
  61 {
  62         unsigned int i;
  63 
  64         for (i = 0; i < ARRAY_SIZE(v4l2_fwht_pixfmts); i++) {
  65                 bool is_valid = v4l2_fwht_validate_fmt(&v4l2_fwht_pixfmts[i],
  66                                                        width_div, height_div,
  67                                                        components_num, pixenc);
  68                 if (is_valid) {
  69                         if (start_idx == 0)
  70                                 return v4l2_fwht_pixfmts + i;
  71                         start_idx--;
  72                 }
  73         }
  74         return NULL;
  75 }
  76 
  77 const struct v4l2_fwht_pixfmt_info *v4l2_fwht_find_pixfmt(u32 pixelformat)
  78 {
  79         unsigned int i;
  80 
  81         for (i = 0; i < ARRAY_SIZE(v4l2_fwht_pixfmts); i++)
  82                 if (v4l2_fwht_pixfmts[i].id == pixelformat)
  83                         return v4l2_fwht_pixfmts + i;
  84         return NULL;
  85 }
  86 
  87 const struct v4l2_fwht_pixfmt_info *v4l2_fwht_get_pixfmt(u32 idx)
  88 {
  89         if (idx >= ARRAY_SIZE(v4l2_fwht_pixfmts))
  90                 return NULL;
  91         return v4l2_fwht_pixfmts + idx;
  92 }
  93 
  94 static int prepare_raw_frame(struct fwht_raw_frame *rf,
  95                          const struct v4l2_fwht_pixfmt_info *info, u8 *buf,
  96                          unsigned int size)
  97 {
  98         rf->luma = buf;
  99         rf->width_div = info->width_div;
 100         rf->height_div = info->height_div;
 101         rf->luma_alpha_step = info->luma_alpha_step;
 102         rf->chroma_step = info->chroma_step;
 103         rf->alpha = NULL;
 104         rf->components_num = info->components_num;
 105 
 106         /*
 107          * The buffer is NULL if it is the reference
 108          * frame of an I-frame in the stateless decoder
 109          */
 110         if (!buf) {
 111                 rf->luma = NULL;
 112                 rf->cb = NULL;
 113                 rf->cr = NULL;
 114                 rf->alpha = NULL;
 115                 return 0;
 116         }
 117         switch (info->id) {
 118         case V4L2_PIX_FMT_GREY:
 119                 rf->cb = NULL;
 120                 rf->cr = NULL;
 121                 break;
 122         case V4L2_PIX_FMT_YUV420:
 123                 rf->cb = rf->luma + size;
 124                 rf->cr = rf->cb + size / 4;
 125                 break;
 126         case V4L2_PIX_FMT_YVU420:
 127                 rf->cr = rf->luma + size;
 128                 rf->cb = rf->cr + size / 4;
 129                 break;
 130         case V4L2_PIX_FMT_YUV422P:
 131                 rf->cb = rf->luma + size;
 132                 rf->cr = rf->cb + size / 2;
 133                 break;
 134         case V4L2_PIX_FMT_NV12:
 135         case V4L2_PIX_FMT_NV16:
 136         case V4L2_PIX_FMT_NV24:
 137                 rf->cb = rf->luma + size;
 138                 rf->cr = rf->cb + 1;
 139                 break;
 140         case V4L2_PIX_FMT_NV21:
 141         case V4L2_PIX_FMT_NV61:
 142         case V4L2_PIX_FMT_NV42:
 143                 rf->cr = rf->luma + size;
 144                 rf->cb = rf->cr + 1;
 145                 break;
 146         case V4L2_PIX_FMT_YUYV:
 147                 rf->cb = rf->luma + 1;
 148                 rf->cr = rf->cb + 2;
 149                 break;
 150         case V4L2_PIX_FMT_YVYU:
 151                 rf->cr = rf->luma + 1;
 152                 rf->cb = rf->cr + 2;
 153                 break;
 154         case V4L2_PIX_FMT_UYVY:
 155                 rf->cb = rf->luma;
 156                 rf->cr = rf->cb + 2;
 157                 rf->luma++;
 158                 break;
 159         case V4L2_PIX_FMT_VYUY:
 160                 rf->cr = rf->luma;
 161                 rf->cb = rf->cr + 2;
 162                 rf->luma++;
 163                 break;
 164         case V4L2_PIX_FMT_RGB24:
 165         case V4L2_PIX_FMT_HSV24:
 166                 rf->cr = rf->luma;
 167                 rf->cb = rf->cr + 2;
 168                 rf->luma++;
 169                 break;
 170         case V4L2_PIX_FMT_BGR24:
 171                 rf->cb = rf->luma;
 172                 rf->cr = rf->cb + 2;
 173                 rf->luma++;
 174                 break;
 175         case V4L2_PIX_FMT_RGB32:
 176         case V4L2_PIX_FMT_XRGB32:
 177         case V4L2_PIX_FMT_HSV32:
 178         case V4L2_PIX_FMT_ARGB32:
 179                 rf->alpha = rf->luma;
 180                 rf->cr = rf->luma + 1;
 181                 rf->cb = rf->cr + 2;
 182                 rf->luma += 2;
 183                 break;
 184         case V4L2_PIX_FMT_BGR32:
 185         case V4L2_PIX_FMT_XBGR32:
 186         case V4L2_PIX_FMT_ABGR32:
 187                 rf->cb = rf->luma;
 188                 rf->cr = rf->cb + 2;
 189                 rf->luma++;
 190                 rf->alpha = rf->cr + 1;
 191                 break;
 192         case V4L2_PIX_FMT_BGRX32:
 193         case V4L2_PIX_FMT_BGRA32:
 194                 rf->alpha = rf->luma;
 195                 rf->cb = rf->luma + 1;
 196                 rf->cr = rf->cb + 2;
 197                 rf->luma += 2;
 198                 break;
 199         case V4L2_PIX_FMT_RGBX32:
 200         case V4L2_PIX_FMT_RGBA32:
 201                 rf->alpha = rf->luma + 3;
 202                 rf->cr = rf->luma;
 203                 rf->cb = rf->cr + 2;
 204                 rf->luma++;
 205                 break;
 206         default:
 207                 return -EINVAL;
 208         }
 209         return 0;
 210 }
 211 
 212 int v4l2_fwht_encode(struct v4l2_fwht_state *state, u8 *p_in, u8 *p_out)
 213 {
 214         unsigned int size = state->stride * state->coded_height;
 215         unsigned int chroma_stride = state->stride;
 216         const struct v4l2_fwht_pixfmt_info *info = state->info;
 217         struct fwht_cframe_hdr *p_hdr;
 218         struct fwht_cframe cf;
 219         struct fwht_raw_frame rf;
 220         u32 encoding;
 221         u32 flags = 0;
 222 
 223         if (!info)
 224                 return -EINVAL;
 225 
 226         if (prepare_raw_frame(&rf, info, p_in, size))
 227                 return -EINVAL;
 228 
 229         if (info->planes_num == 3)
 230                 chroma_stride /= 2;
 231 
 232         if (info->id == V4L2_PIX_FMT_NV24 ||
 233             info->id == V4L2_PIX_FMT_NV42)
 234                 chroma_stride *= 2;
 235 
 236         cf.i_frame_qp = state->i_frame_qp;
 237         cf.p_frame_qp = state->p_frame_qp;
 238         cf.rlc_data = (__be16 *)(p_out + sizeof(*p_hdr));
 239 
 240         encoding = fwht_encode_frame(&rf, &state->ref_frame, &cf,
 241                                      !state->gop_cnt,
 242                                      state->gop_cnt == state->gop_size - 1,
 243                                      state->visible_width,
 244                                      state->visible_height,
 245                                      state->stride, chroma_stride);
 246         if (!(encoding & FWHT_FRAME_PCODED))
 247                 state->gop_cnt = 0;
 248         if (++state->gop_cnt >= state->gop_size)
 249                 state->gop_cnt = 0;
 250 
 251         p_hdr = (struct fwht_cframe_hdr *)p_out;
 252         p_hdr->magic1 = FWHT_MAGIC1;
 253         p_hdr->magic2 = FWHT_MAGIC2;
 254         p_hdr->version = htonl(FWHT_VERSION);
 255         p_hdr->width = htonl(state->visible_width);
 256         p_hdr->height = htonl(state->visible_height);
 257         flags |= (info->components_num - 1) << FWHT_FL_COMPONENTS_NUM_OFFSET;
 258         flags |= info->pixenc;
 259         if (encoding & FWHT_LUMA_UNENCODED)
 260                 flags |= FWHT_FL_LUMA_IS_UNCOMPRESSED;
 261         if (encoding & FWHT_CB_UNENCODED)
 262                 flags |= FWHT_FL_CB_IS_UNCOMPRESSED;
 263         if (encoding & FWHT_CR_UNENCODED)
 264                 flags |= FWHT_FL_CR_IS_UNCOMPRESSED;
 265         if (encoding & FWHT_ALPHA_UNENCODED)
 266                 flags |= FWHT_FL_ALPHA_IS_UNCOMPRESSED;
 267         if (!(encoding & FWHT_FRAME_PCODED))
 268                 flags |= FWHT_FL_I_FRAME;
 269         if (rf.height_div == 1)
 270                 flags |= FWHT_FL_CHROMA_FULL_HEIGHT;
 271         if (rf.width_div == 1)
 272                 flags |= FWHT_FL_CHROMA_FULL_WIDTH;
 273         p_hdr->flags = htonl(flags);
 274         p_hdr->colorspace = htonl(state->colorspace);
 275         p_hdr->xfer_func = htonl(state->xfer_func);
 276         p_hdr->ycbcr_enc = htonl(state->ycbcr_enc);
 277         p_hdr->quantization = htonl(state->quantization);
 278         p_hdr->size = htonl(cf.size);
 279         return cf.size + sizeof(*p_hdr);
 280 }
 281 
 282 int v4l2_fwht_decode(struct v4l2_fwht_state *state, u8 *p_in, u8 *p_out)
 283 {
 284         u32 flags;
 285         struct fwht_cframe cf;
 286         unsigned int components_num = 3;
 287         unsigned int version;
 288         const struct v4l2_fwht_pixfmt_info *info;
 289         unsigned int hdr_width_div, hdr_height_div;
 290         struct fwht_raw_frame dst_rf;
 291         unsigned int dst_chroma_stride = state->stride;
 292         unsigned int ref_chroma_stride = state->ref_stride;
 293         unsigned int dst_size = state->stride * state->coded_height;
 294         unsigned int ref_size;
 295 
 296         if (!state->info)
 297                 return -EINVAL;
 298 
 299         info = state->info;
 300 
 301         version = ntohl(state->header.version);
 302         if (!version || version > FWHT_VERSION) {
 303                 pr_err("version %d is not supported, current version is %d\n",
 304                        version, FWHT_VERSION);
 305                 return -EINVAL;
 306         }
 307 
 308         if (state->header.magic1 != FWHT_MAGIC1 ||
 309             state->header.magic2 != FWHT_MAGIC2)
 310                 return -EINVAL;
 311 
 312         /* TODO: support resolution changes */
 313         if (ntohl(state->header.width)  != state->visible_width ||
 314             ntohl(state->header.height) != state->visible_height)
 315                 return -EINVAL;
 316 
 317         flags = ntohl(state->header.flags);
 318 
 319         if (version >= 2) {
 320                 if ((flags & FWHT_FL_PIXENC_MSK) != info->pixenc)
 321                         return -EINVAL;
 322                 components_num = 1 + ((flags & FWHT_FL_COMPONENTS_NUM_MSK) >>
 323                                 FWHT_FL_COMPONENTS_NUM_OFFSET);
 324         }
 325 
 326         if (components_num != info->components_num)
 327                 return -EINVAL;
 328 
 329         state->colorspace = ntohl(state->header.colorspace);
 330         state->xfer_func = ntohl(state->header.xfer_func);
 331         state->ycbcr_enc = ntohl(state->header.ycbcr_enc);
 332         state->quantization = ntohl(state->header.quantization);
 333         cf.rlc_data = (__be16 *)p_in;
 334         cf.size = ntohl(state->header.size);
 335 
 336         hdr_width_div = (flags & FWHT_FL_CHROMA_FULL_WIDTH) ? 1 : 2;
 337         hdr_height_div = (flags & FWHT_FL_CHROMA_FULL_HEIGHT) ? 1 : 2;
 338         if (hdr_width_div != info->width_div ||
 339             hdr_height_div != info->height_div)
 340                 return -EINVAL;
 341 
 342         if (prepare_raw_frame(&dst_rf, info, p_out, dst_size))
 343                 return -EINVAL;
 344         if (info->planes_num == 3) {
 345                 dst_chroma_stride /= 2;
 346                 ref_chroma_stride /= 2;
 347         }
 348         if (info->id == V4L2_PIX_FMT_NV24 ||
 349             info->id == V4L2_PIX_FMT_NV42) {
 350                 dst_chroma_stride *= 2;
 351                 ref_chroma_stride *= 2;
 352         }
 353 
 354 
 355         ref_size = state->ref_stride * state->coded_height;
 356 
 357         if (prepare_raw_frame(&state->ref_frame, info, state->ref_frame.buf,
 358                               ref_size))
 359                 return -EINVAL;
 360 
 361         if (!fwht_decode_frame(&cf, flags, components_num,
 362                         state->visible_width, state->visible_height,
 363                         &state->ref_frame, state->ref_stride, ref_chroma_stride,
 364                         &dst_rf, state->stride, dst_chroma_stride))
 365                 return -EINVAL;
 366         return 0;
 367 }

/* [<][>][^][v][top][bottom][index][help] */