cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

codec-v4l2-fwht.c (11095B)


      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
     13static const struct v4l2_fwht_pixfmt_info v4l2_fwht_pixfmts[] = {
     14	{ V4L2_PIX_FMT_YUV420,  1, 3, 2, 1, 1, 2, 2, 3, 3, V4L2_FWHT_FL_PIXENC_YUV},
     15	{ V4L2_PIX_FMT_YVU420,  1, 3, 2, 1, 1, 2, 2, 3, 3, V4L2_FWHT_FL_PIXENC_YUV},
     16	{ V4L2_PIX_FMT_YUV422P, 1, 2, 1, 1, 1, 2, 1, 3, 3, V4L2_FWHT_FL_PIXENC_YUV},
     17	{ V4L2_PIX_FMT_NV12,    1, 3, 2, 1, 2, 2, 2, 3, 2, V4L2_FWHT_FL_PIXENC_YUV},
     18	{ V4L2_PIX_FMT_NV21,    1, 3, 2, 1, 2, 2, 2, 3, 2, V4L2_FWHT_FL_PIXENC_YUV},
     19	{ V4L2_PIX_FMT_NV16,    1, 2, 1, 1, 2, 2, 1, 3, 2, V4L2_FWHT_FL_PIXENC_YUV},
     20	{ V4L2_PIX_FMT_NV61,    1, 2, 1, 1, 2, 2, 1, 3, 2, V4L2_FWHT_FL_PIXENC_YUV},
     21	{ V4L2_PIX_FMT_NV24,    1, 3, 1, 1, 2, 1, 1, 3, 2, V4L2_FWHT_FL_PIXENC_YUV},
     22	{ V4L2_PIX_FMT_NV42,    1, 3, 1, 1, 2, 1, 1, 3, 2, V4L2_FWHT_FL_PIXENC_YUV},
     23	{ V4L2_PIX_FMT_YUYV,    2, 2, 1, 2, 4, 2, 1, 3, 1, V4L2_FWHT_FL_PIXENC_YUV},
     24	{ V4L2_PIX_FMT_YVYU,    2, 2, 1, 2, 4, 2, 1, 3, 1, V4L2_FWHT_FL_PIXENC_YUV},
     25	{ V4L2_PIX_FMT_UYVY,    2, 2, 1, 2, 4, 2, 1, 3, 1, V4L2_FWHT_FL_PIXENC_YUV},
     26	{ V4L2_PIX_FMT_VYUY,    2, 2, 1, 2, 4, 2, 1, 3, 1, V4L2_FWHT_FL_PIXENC_YUV},
     27	{ V4L2_PIX_FMT_BGR24,   3, 3, 1, 3, 3, 1, 1, 3, 1, V4L2_FWHT_FL_PIXENC_RGB},
     28	{ V4L2_PIX_FMT_RGB24,   3, 3, 1, 3, 3, 1, 1, 3, 1, V4L2_FWHT_FL_PIXENC_RGB},
     29	{ V4L2_PIX_FMT_HSV24,   3, 3, 1, 3, 3, 1, 1, 3, 1, V4L2_FWHT_FL_PIXENC_HSV},
     30	{ V4L2_PIX_FMT_BGR32,   4, 4, 1, 4, 4, 1, 1, 4, 1, V4L2_FWHT_FL_PIXENC_RGB},
     31	{ V4L2_PIX_FMT_XBGR32,  4, 4, 1, 4, 4, 1, 1, 4, 1, V4L2_FWHT_FL_PIXENC_RGB},
     32	{ V4L2_PIX_FMT_ABGR32,  4, 4, 1, 4, 4, 1, 1, 4, 1, V4L2_FWHT_FL_PIXENC_RGB},
     33	{ V4L2_PIX_FMT_RGB32,   4, 4, 1, 4, 4, 1, 1, 4, 1, V4L2_FWHT_FL_PIXENC_RGB},
     34	{ V4L2_PIX_FMT_XRGB32,  4, 4, 1, 4, 4, 1, 1, 4, 1, V4L2_FWHT_FL_PIXENC_RGB},
     35	{ V4L2_PIX_FMT_ARGB32,  4, 4, 1, 4, 4, 1, 1, 4, 1, V4L2_FWHT_FL_PIXENC_RGB},
     36	{ V4L2_PIX_FMT_BGRX32,  4, 4, 1, 4, 4, 1, 1, 4, 1, V4L2_FWHT_FL_PIXENC_RGB},
     37	{ V4L2_PIX_FMT_BGRA32,  4, 4, 1, 4, 4, 1, 1, 4, 1, V4L2_FWHT_FL_PIXENC_RGB},
     38	{ V4L2_PIX_FMT_RGBX32,  4, 4, 1, 4, 4, 1, 1, 4, 1, V4L2_FWHT_FL_PIXENC_RGB},
     39	{ V4L2_PIX_FMT_RGBA32,  4, 4, 1, 4, 4, 1, 1, 4, 1, V4L2_FWHT_FL_PIXENC_RGB},
     40	{ V4L2_PIX_FMT_HSV32,   4, 4, 1, 4, 4, 1, 1, 4, 1, V4L2_FWHT_FL_PIXENC_HSV},
     41	{ V4L2_PIX_FMT_GREY,    1, 1, 1, 1, 0, 1, 1, 1, 1, V4L2_FWHT_FL_PIXENC_RGB},
     42};
     43
     44bool 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
     56const 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
     77const 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
     87const 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
     94static 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
    212int 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(V4L2_FWHT_VERSION);
    255	p_hdr->width = htonl(state->visible_width);
    256	p_hdr->height = htonl(state->visible_height);
    257	flags |= (info->components_num - 1) << V4L2_FWHT_FL_COMPONENTS_NUM_OFFSET;
    258	flags |= info->pixenc;
    259	if (encoding & FWHT_LUMA_UNENCODED)
    260		flags |= V4L2_FWHT_FL_LUMA_IS_UNCOMPRESSED;
    261	if (encoding & FWHT_CB_UNENCODED)
    262		flags |= V4L2_FWHT_FL_CB_IS_UNCOMPRESSED;
    263	if (encoding & FWHT_CR_UNENCODED)
    264		flags |= V4L2_FWHT_FL_CR_IS_UNCOMPRESSED;
    265	if (encoding & FWHT_ALPHA_UNENCODED)
    266		flags |= V4L2_FWHT_FL_ALPHA_IS_UNCOMPRESSED;
    267	if (!(encoding & FWHT_FRAME_PCODED))
    268		flags |= V4L2_FWHT_FL_I_FRAME;
    269	if (rf.height_div == 1)
    270		flags |= V4L2_FWHT_FL_CHROMA_FULL_HEIGHT;
    271	if (rf.width_div == 1)
    272		flags |= V4L2_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
    282int 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 > V4L2_FWHT_VERSION) {
    303		pr_err("version %d is not supported, current version is %d\n",
    304		       version, V4L2_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 & V4L2_FWHT_FL_PIXENC_MSK) != info->pixenc)
    321			return -EINVAL;
    322		components_num = 1 + ((flags & V4L2_FWHT_FL_COMPONENTS_NUM_MSK) >>
    323				V4L2_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 & V4L2_FWHT_FL_CHROMA_FULL_WIDTH) ? 1 : 2;
    337	hdr_height_div = (flags & V4L2_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}