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