]> asedeno.scripts.mit.edu Git - linux.git/blob - drivers/media/platform/vicodec/codec-v4l2-fwht.c
Merge tag 'armsoc-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/soc/soc
[linux.git] / drivers / media / platform / vicodec / codec-v4l2-fwht.c
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, 3, 1, FWHT_FL_PIXENC_RGB},
31         { V4L2_PIX_FMT_XBGR32,  4, 4, 1, 4, 4, 1, 1, 3, 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, 3, 1, FWHT_FL_PIXENC_RGB},
34         { V4L2_PIX_FMT_XRGB32,  4, 4, 1, 4, 4, 1, 1, 3, 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, 3, 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, 3, 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, 3, 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                 rf->cr = rf->luma + 1;
179                 rf->cb = rf->cr + 2;
180                 rf->luma += 2;
181                 break;
182         case V4L2_PIX_FMT_BGR32:
183         case V4L2_PIX_FMT_XBGR32:
184                 rf->cb = rf->luma;
185                 rf->cr = rf->cb + 2;
186                 rf->luma++;
187                 break;
188         case V4L2_PIX_FMT_ARGB32:
189                 rf->alpha = rf->luma;
190                 rf->cr = rf->luma + 1;
191                 rf->cb = rf->cr + 2;
192                 rf->luma += 2;
193                 break;
194         case V4L2_PIX_FMT_ABGR32:
195                 rf->cb = rf->luma;
196                 rf->cr = rf->cb + 2;
197                 rf->luma++;
198                 rf->alpha = rf->cr + 1;
199                 break;
200         case V4L2_PIX_FMT_BGRX32:
201                 rf->cb = rf->luma + 1;
202                 rf->cr = rf->cb + 2;
203                 rf->luma += 2;
204                 break;
205         case V4L2_PIX_FMT_BGRA32:
206                 rf->alpha = rf->luma;
207                 rf->cb = rf->luma + 1;
208                 rf->cr = rf->cb + 2;
209                 rf->luma += 2;
210                 break;
211         case V4L2_PIX_FMT_RGBX32:
212                 rf->cr = rf->luma;
213                 rf->cb = rf->cr + 2;
214                 rf->luma++;
215                 break;
216         case V4L2_PIX_FMT_RGBA32:
217                 rf->alpha = rf->luma + 3;
218                 rf->cr = rf->luma;
219                 rf->cb = rf->cr + 2;
220                 rf->luma++;
221                 break;
222         default:
223                 return -EINVAL;
224         }
225         return 0;
226 }
227
228 int v4l2_fwht_encode(struct v4l2_fwht_state *state, u8 *p_in, u8 *p_out)
229 {
230         unsigned int size = state->stride * state->coded_height;
231         unsigned int chroma_stride = state->stride;
232         const struct v4l2_fwht_pixfmt_info *info = state->info;
233         struct fwht_cframe_hdr *p_hdr;
234         struct fwht_cframe cf;
235         struct fwht_raw_frame rf;
236         u32 encoding;
237         u32 flags = 0;
238
239         if (!info)
240                 return -EINVAL;
241
242         if (prepare_raw_frame(&rf, info, p_in, size))
243                 return -EINVAL;
244
245         if (info->planes_num == 3)
246                 chroma_stride /= 2;
247
248         if (info->id == V4L2_PIX_FMT_NV24 ||
249             info->id == V4L2_PIX_FMT_NV42)
250                 chroma_stride *= 2;
251
252         cf.i_frame_qp = state->i_frame_qp;
253         cf.p_frame_qp = state->p_frame_qp;
254         cf.rlc_data = (__be16 *)(p_out + sizeof(*p_hdr));
255
256         encoding = fwht_encode_frame(&rf, &state->ref_frame, &cf,
257                                      !state->gop_cnt,
258                                      state->gop_cnt == state->gop_size - 1,
259                                      state->visible_width,
260                                      state->visible_height,
261                                      state->stride, chroma_stride);
262         if (!(encoding & FWHT_FRAME_PCODED))
263                 state->gop_cnt = 0;
264         if (++state->gop_cnt >= state->gop_size)
265                 state->gop_cnt = 0;
266
267         p_hdr = (struct fwht_cframe_hdr *)p_out;
268         p_hdr->magic1 = FWHT_MAGIC1;
269         p_hdr->magic2 = FWHT_MAGIC2;
270         p_hdr->version = htonl(FWHT_VERSION);
271         p_hdr->width = htonl(state->visible_width);
272         p_hdr->height = htonl(state->visible_height);
273         flags |= (info->components_num - 1) << FWHT_FL_COMPONENTS_NUM_OFFSET;
274         flags |= info->pixenc;
275         if (encoding & FWHT_LUMA_UNENCODED)
276                 flags |= FWHT_FL_LUMA_IS_UNCOMPRESSED;
277         if (encoding & FWHT_CB_UNENCODED)
278                 flags |= FWHT_FL_CB_IS_UNCOMPRESSED;
279         if (encoding & FWHT_CR_UNENCODED)
280                 flags |= FWHT_FL_CR_IS_UNCOMPRESSED;
281         if (encoding & FWHT_ALPHA_UNENCODED)
282                 flags |= FWHT_FL_ALPHA_IS_UNCOMPRESSED;
283         if (!(encoding & FWHT_FRAME_PCODED))
284                 flags |= FWHT_FL_I_FRAME;
285         if (rf.height_div == 1)
286                 flags |= FWHT_FL_CHROMA_FULL_HEIGHT;
287         if (rf.width_div == 1)
288                 flags |= FWHT_FL_CHROMA_FULL_WIDTH;
289         p_hdr->flags = htonl(flags);
290         p_hdr->colorspace = htonl(state->colorspace);
291         p_hdr->xfer_func = htonl(state->xfer_func);
292         p_hdr->ycbcr_enc = htonl(state->ycbcr_enc);
293         p_hdr->quantization = htonl(state->quantization);
294         p_hdr->size = htonl(cf.size);
295         return cf.size + sizeof(*p_hdr);
296 }
297
298 int v4l2_fwht_decode(struct v4l2_fwht_state *state, u8 *p_in, u8 *p_out)
299 {
300         u32 flags;
301         struct fwht_cframe cf;
302         unsigned int components_num = 3;
303         unsigned int version;
304         const struct v4l2_fwht_pixfmt_info *info;
305         unsigned int hdr_width_div, hdr_height_div;
306         struct fwht_raw_frame dst_rf;
307         unsigned int dst_chroma_stride = state->stride;
308         unsigned int ref_chroma_stride = state->ref_stride;
309         unsigned int dst_size = state->stride * state->coded_height;
310         unsigned int ref_size;
311
312         if (!state->info)
313                 return -EINVAL;
314
315         info = state->info;
316
317         version = ntohl(state->header.version);
318         if (!version || version > FWHT_VERSION) {
319                 pr_err("version %d is not supported, current version is %d\n",
320                        version, FWHT_VERSION);
321                 return -EINVAL;
322         }
323
324         if (state->header.magic1 != FWHT_MAGIC1 ||
325             state->header.magic2 != FWHT_MAGIC2)
326                 return -EINVAL;
327
328         /* TODO: support resolution changes */
329         if (ntohl(state->header.width)  != state->visible_width ||
330             ntohl(state->header.height) != state->visible_height)
331                 return -EINVAL;
332
333         flags = ntohl(state->header.flags);
334
335         if (version >= 2) {
336                 if ((flags & FWHT_FL_PIXENC_MSK) != info->pixenc)
337                         return -EINVAL;
338                 components_num = 1 + ((flags & FWHT_FL_COMPONENTS_NUM_MSK) >>
339                                 FWHT_FL_COMPONENTS_NUM_OFFSET);
340         }
341
342         if (components_num != info->components_num)
343                 return -EINVAL;
344
345         state->colorspace = ntohl(state->header.colorspace);
346         state->xfer_func = ntohl(state->header.xfer_func);
347         state->ycbcr_enc = ntohl(state->header.ycbcr_enc);
348         state->quantization = ntohl(state->header.quantization);
349         cf.rlc_data = (__be16 *)p_in;
350         cf.size = ntohl(state->header.size);
351
352         hdr_width_div = (flags & FWHT_FL_CHROMA_FULL_WIDTH) ? 1 : 2;
353         hdr_height_div = (flags & FWHT_FL_CHROMA_FULL_HEIGHT) ? 1 : 2;
354         if (hdr_width_div != info->width_div ||
355             hdr_height_div != info->height_div)
356                 return -EINVAL;
357
358         if (prepare_raw_frame(&dst_rf, info, p_out, dst_size))
359                 return -EINVAL;
360         if (info->planes_num == 3) {
361                 dst_chroma_stride /= 2;
362                 ref_chroma_stride /= 2;
363         }
364         if (info->id == V4L2_PIX_FMT_NV24 ||
365             info->id == V4L2_PIX_FMT_NV42) {
366                 dst_chroma_stride *= 2;
367                 ref_chroma_stride *= 2;
368         }
369
370
371         ref_size = state->ref_stride * state->coded_height;
372
373         if (prepare_raw_frame(&state->ref_frame, info, state->ref_frame.buf,
374                               ref_size))
375                 return -EINVAL;
376
377         if (!fwht_decode_frame(&cf, flags, components_num,
378                         state->visible_width, state->visible_height,
379                         &state->ref_frame, state->ref_stride, ref_chroma_stride,
380                         &dst_rf, state->stride, dst_chroma_stride))
381                 return -EINVAL;
382         return 0;
383 }