1 // SPDX-License-Identifier: GPL-2.0+
3 * Copyright 2016 Tom aan de Wiel
4 * Copyright 2018 Cisco Systems, Inc. and/or its affiliates. All rights reserved.
6 * 8x8 Fast Walsh Hadamard Transform in sequency order based on the paper:
8 * A Recursive Algorithm for Sequency-Ordered Fast Walsh Transforms,
12 #include <linux/string.h>
13 #include "vicodec-codec.h"
17 static const uint8_t zigzag[64] = {
23 5, 12, 19, 26, 33, 40,
24 6, 13, 20, 27, 34, 41, 48,
25 7, 14, 21, 28, 35, 42, 49, 56,
26 15, 22, 29, 36, 43, 50, 57,
27 23, 30, 37, 44, 51, 58,
36 static int rlc(const s16 *in, __be16 *output, int blocktype)
44 /* read in block from framebuffer */
48 for (y = 0; y < 8; y++) {
49 for (x = 0; x < 8; x++) {
55 /* keep track of amount of trailing zeros */
56 for (i = 63; i >= 0 && !block[zigzag[i]]; i--)
59 *output++ = (blocktype == PBLOCK ? htons(PFRAME_BIT) : 0);
62 to_encode = 8 * 8 - (lastzero_run > 14 ? lastzero_run : 0);
65 while (i < to_encode) {
69 /* count leading zeros */
70 while ((tmp = block[zigzag[i]]) == 0 && cnt < 14) {
78 /* 4 bits for run, 12 for coefficient (quantization by 4) */
79 *output++ = htons((cnt | tmp << 4));
83 if (lastzero_run > 14) {
84 *output = htons(ALL_ZEROS | 0);
92 * This function will worst-case increase rlc_in by 65*2 bytes:
93 * one s16 value for the header and 8 * 8 coefficients of type s16.
95 static s16 derlc(const __be16 **rlc_in, s16 *dwht_out)
98 const __be16 *input = *rlc_in;
99 s16 ret = ntohs(*input++);
101 s16 block[8 * 8 + 16];
106 * Now de-compress, it expands one byte to up to 15 bytes
107 * (or fills the remainder of the 64 bytes with zeroes if it
108 * is the last byte to expand).
110 * So block has to be 8 * 8 + 16 bytes, the '+ 16' is to
111 * allow for overflow if the incoming data was malformed.
113 while (dec_count < 8 * 8) {
114 s16 in = ntohs(*input++);
115 int length = in & 0xf;
118 /* fill remainder with zeros */
120 for (i = 0; i < 64 - dec_count; i++)
125 for (i = 0; i < length; i++)
128 dec_count += length + 1;
133 for (i = 0; i < 64; i++) {
138 dwht_out[x + y * 8] = *wp++;
144 static const int quant_table[] = {
145 2, 2, 2, 2, 2, 2, 2, 2,
146 2, 2, 2, 2, 2, 2, 2, 2,
147 2, 2, 2, 2, 2, 2, 2, 3,
148 2, 2, 2, 2, 2, 2, 3, 6,
149 2, 2, 2, 2, 2, 3, 6, 6,
150 2, 2, 2, 2, 3, 6, 6, 6,
151 2, 2, 2, 3, 6, 6, 6, 6,
152 2, 2, 3, 6, 6, 6, 6, 8,
155 static const int quant_table_p[] = {
156 3, 3, 3, 3, 3, 3, 3, 3,
157 3, 3, 3, 3, 3, 3, 3, 3,
158 3, 3, 3, 3, 3, 3, 3, 3,
159 3, 3, 3, 3, 3, 3, 3, 6,
160 3, 3, 3, 3, 3, 3, 6, 6,
161 3, 3, 3, 3, 3, 6, 6, 9,
162 3, 3, 3, 3, 6, 6, 9, 9,
163 3, 3, 3, 6, 6, 9, 9, 10,
166 static void quantize_intra(s16 *coeff, s16 *de_coeff, u16 qp)
168 const int *quant = quant_table;
171 for (j = 0; j < 8; j++) {
172 for (i = 0; i < 8; i++, quant++, coeff++, de_coeff++) {
174 if (*coeff >= -qp && *coeff <= qp)
175 *coeff = *de_coeff = 0;
177 *de_coeff = *coeff << *quant;
182 static void dequantize_intra(s16 *coeff)
184 const int *quant = quant_table;
187 for (j = 0; j < 8; j++)
188 for (i = 0; i < 8; i++, quant++, coeff++)
192 static void quantize_inter(s16 *coeff, s16 *de_coeff, u16 qp)
194 const int *quant = quant_table_p;
197 for (j = 0; j < 8; j++) {
198 for (i = 0; i < 8; i++, quant++, coeff++, de_coeff++) {
200 if (*coeff >= -qp && *coeff <= qp)
201 *coeff = *de_coeff = 0;
203 *de_coeff = *coeff << *quant;
208 static void dequantize_inter(s16 *coeff)
210 const int *quant = quant_table_p;
213 for (j = 0; j < 8; j++)
214 for (i = 0; i < 8; i++, quant++, coeff++)
218 static void fwht(const u8 *block, s16 *output_block, unsigned int stride,
219 unsigned int input_step, bool intra)
221 /* we'll need more than 8 bits for the transformed coefficients */
222 s32 workspace1[8], workspace2[8];
223 const u8 *tmp = block;
224 s16 *out = output_block;
225 int add = intra ? 256 : 0;
229 stride *= input_step;
231 for (i = 0; i < 8; i++, tmp += stride, out += 8) {
232 switch (input_step) {
234 workspace1[0] = tmp[0] + tmp[1] - add;
235 workspace1[1] = tmp[0] - tmp[1];
237 workspace1[2] = tmp[2] + tmp[3] - add;
238 workspace1[3] = tmp[2] - tmp[3];
240 workspace1[4] = tmp[4] + tmp[5] - add;
241 workspace1[5] = tmp[4] - tmp[5];
243 workspace1[6] = tmp[6] + tmp[7] - add;
244 workspace1[7] = tmp[6] - tmp[7];
247 workspace1[0] = tmp[0] + tmp[2] - add;
248 workspace1[1] = tmp[0] - tmp[2];
250 workspace1[2] = tmp[4] + tmp[6] - add;
251 workspace1[3] = tmp[4] - tmp[6];
253 workspace1[4] = tmp[8] + tmp[10] - add;
254 workspace1[5] = tmp[8] - tmp[10];
256 workspace1[6] = tmp[12] + tmp[14] - add;
257 workspace1[7] = tmp[12] - tmp[14];
260 workspace1[0] = tmp[0] + tmp[3] - add;
261 workspace1[1] = tmp[0] - tmp[3];
263 workspace1[2] = tmp[6] + tmp[9] - add;
264 workspace1[3] = tmp[6] - tmp[9];
266 workspace1[4] = tmp[12] + tmp[15] - add;
267 workspace1[5] = tmp[12] - tmp[15];
269 workspace1[6] = tmp[18] + tmp[21] - add;
270 workspace1[7] = tmp[18] - tmp[21];
273 workspace1[0] = tmp[0] + tmp[4] - add;
274 workspace1[1] = tmp[0] - tmp[4];
276 workspace1[2] = tmp[8] + tmp[12] - add;
277 workspace1[3] = tmp[8] - tmp[12];
279 workspace1[4] = tmp[16] + tmp[20] - add;
280 workspace1[5] = tmp[16] - tmp[20];
282 workspace1[6] = tmp[24] + tmp[28] - add;
283 workspace1[7] = tmp[24] - tmp[28];
288 workspace2[0] = workspace1[0] + workspace1[2];
289 workspace2[1] = workspace1[0] - workspace1[2];
290 workspace2[2] = workspace1[1] - workspace1[3];
291 workspace2[3] = workspace1[1] + workspace1[3];
293 workspace2[4] = workspace1[4] + workspace1[6];
294 workspace2[5] = workspace1[4] - workspace1[6];
295 workspace2[6] = workspace1[5] - workspace1[7];
296 workspace2[7] = workspace1[5] + workspace1[7];
299 out[0] = workspace2[0] + workspace2[4];
300 out[1] = workspace2[0] - workspace2[4];
301 out[2] = workspace2[1] - workspace2[5];
302 out[3] = workspace2[1] + workspace2[5];
303 out[4] = workspace2[2] + workspace2[6];
304 out[5] = workspace2[2] - workspace2[6];
305 out[6] = workspace2[3] - workspace2[7];
306 out[7] = workspace2[3] + workspace2[7];
311 for (i = 0; i < 8; i++, out++) {
313 workspace1[0] = out[0] + out[1 * 8];
314 workspace1[1] = out[0] - out[1 * 8];
316 workspace1[2] = out[2 * 8] + out[3 * 8];
317 workspace1[3] = out[2 * 8] - out[3 * 8];
319 workspace1[4] = out[4 * 8] + out[5 * 8];
320 workspace1[5] = out[4 * 8] - out[5 * 8];
322 workspace1[6] = out[6 * 8] + out[7 * 8];
323 workspace1[7] = out[6 * 8] - out[7 * 8];
326 workspace2[0] = workspace1[0] + workspace1[2];
327 workspace2[1] = workspace1[0] - workspace1[2];
328 workspace2[2] = workspace1[1] - workspace1[3];
329 workspace2[3] = workspace1[1] + workspace1[3];
331 workspace2[4] = workspace1[4] + workspace1[6];
332 workspace2[5] = workspace1[4] - workspace1[6];
333 workspace2[6] = workspace1[5] - workspace1[7];
334 workspace2[7] = workspace1[5] + workspace1[7];
336 out[0 * 8] = workspace2[0] + workspace2[4];
337 out[1 * 8] = workspace2[0] - workspace2[4];
338 out[2 * 8] = workspace2[1] - workspace2[5];
339 out[3 * 8] = workspace2[1] + workspace2[5];
340 out[4 * 8] = workspace2[2] + workspace2[6];
341 out[5 * 8] = workspace2[2] - workspace2[6];
342 out[6 * 8] = workspace2[3] - workspace2[7];
343 out[7 * 8] = workspace2[3] + workspace2[7];
348 * Not the nicest way of doing it, but P-blocks get twice the range of
349 * that of the I-blocks. Therefore we need a type bigger than 8 bits.
350 * Furthermore values can be negative... This is just a version that
351 * works with 16 signed data
353 static void fwht16(const s16 *block, s16 *output_block, int stride, int intra)
355 /* we'll need more than 8 bits for the transformed coefficients */
356 s32 workspace1[8], workspace2[8];
357 const s16 *tmp = block;
358 s16 *out = output_block;
361 for (i = 0; i < 8; i++, tmp += stride, out += 8) {
363 workspace1[0] = tmp[0] + tmp[1];
364 workspace1[1] = tmp[0] - tmp[1];
366 workspace1[2] = tmp[2] + tmp[3];
367 workspace1[3] = tmp[2] - tmp[3];
369 workspace1[4] = tmp[4] + tmp[5];
370 workspace1[5] = tmp[4] - tmp[5];
372 workspace1[6] = tmp[6] + tmp[7];
373 workspace1[7] = tmp[6] - tmp[7];
376 workspace2[0] = workspace1[0] + workspace1[2];
377 workspace2[1] = workspace1[0] - workspace1[2];
378 workspace2[2] = workspace1[1] - workspace1[3];
379 workspace2[3] = workspace1[1] + workspace1[3];
381 workspace2[4] = workspace1[4] + workspace1[6];
382 workspace2[5] = workspace1[4] - workspace1[6];
383 workspace2[6] = workspace1[5] - workspace1[7];
384 workspace2[7] = workspace1[5] + workspace1[7];
387 out[0] = workspace2[0] + workspace2[4];
388 out[1] = workspace2[0] - workspace2[4];
389 out[2] = workspace2[1] - workspace2[5];
390 out[3] = workspace2[1] + workspace2[5];
391 out[4] = workspace2[2] + workspace2[6];
392 out[5] = workspace2[2] - workspace2[6];
393 out[6] = workspace2[3] - workspace2[7];
394 out[7] = workspace2[3] + workspace2[7];
399 for (i = 0; i < 8; i++, out++) {
401 workspace1[0] = out[0] + out[1*8];
402 workspace1[1] = out[0] - out[1*8];
404 workspace1[2] = out[2*8] + out[3*8];
405 workspace1[3] = out[2*8] - out[3*8];
407 workspace1[4] = out[4*8] + out[5*8];
408 workspace1[5] = out[4*8] - out[5*8];
410 workspace1[6] = out[6*8] + out[7*8];
411 workspace1[7] = out[6*8] - out[7*8];
414 workspace2[0] = workspace1[0] + workspace1[2];
415 workspace2[1] = workspace1[0] - workspace1[2];
416 workspace2[2] = workspace1[1] - workspace1[3];
417 workspace2[3] = workspace1[1] + workspace1[3];
419 workspace2[4] = workspace1[4] + workspace1[6];
420 workspace2[5] = workspace1[4] - workspace1[6];
421 workspace2[6] = workspace1[5] - workspace1[7];
422 workspace2[7] = workspace1[5] + workspace1[7];
425 out[0*8] = workspace2[0] + workspace2[4];
426 out[1*8] = workspace2[0] - workspace2[4];
427 out[2*8] = workspace2[1] - workspace2[5];
428 out[3*8] = workspace2[1] + workspace2[5];
429 out[4*8] = workspace2[2] + workspace2[6];
430 out[5*8] = workspace2[2] - workspace2[6];
431 out[6*8] = workspace2[3] - workspace2[7];
432 out[7*8] = workspace2[3] + workspace2[7];
436 static void ifwht(const s16 *block, s16 *output_block, int intra)
439 * we'll need more than 8 bits for the transformed coefficients
440 * use native unit of cpu
442 int workspace1[8], workspace2[8];
443 int inter = intra ? 0 : 1;
444 const s16 *tmp = block;
445 s16 *out = output_block;
448 for (i = 0; i < 8; i++, tmp += 8, out += 8) {
450 workspace1[0] = tmp[0] + tmp[1];
451 workspace1[1] = tmp[0] - tmp[1];
453 workspace1[2] = tmp[2] + tmp[3];
454 workspace1[3] = tmp[2] - tmp[3];
456 workspace1[4] = tmp[4] + tmp[5];
457 workspace1[5] = tmp[4] - tmp[5];
459 workspace1[6] = tmp[6] + tmp[7];
460 workspace1[7] = tmp[6] - tmp[7];
463 workspace2[0] = workspace1[0] + workspace1[2];
464 workspace2[1] = workspace1[0] - workspace1[2];
465 workspace2[2] = workspace1[1] - workspace1[3];
466 workspace2[3] = workspace1[1] + workspace1[3];
468 workspace2[4] = workspace1[4] + workspace1[6];
469 workspace2[5] = workspace1[4] - workspace1[6];
470 workspace2[6] = workspace1[5] - workspace1[7];
471 workspace2[7] = workspace1[5] + workspace1[7];
474 out[0] = workspace2[0] + workspace2[4];
475 out[1] = workspace2[0] - workspace2[4];
476 out[2] = workspace2[1] - workspace2[5];
477 out[3] = workspace2[1] + workspace2[5];
478 out[4] = workspace2[2] + workspace2[6];
479 out[5] = workspace2[2] - workspace2[6];
480 out[6] = workspace2[3] - workspace2[7];
481 out[7] = workspace2[3] + workspace2[7];
486 for (i = 0; i < 8; i++, out++) {
488 workspace1[0] = out[0] + out[1 * 8];
489 workspace1[1] = out[0] - out[1 * 8];
491 workspace1[2] = out[2 * 8] + out[3 * 8];
492 workspace1[3] = out[2 * 8] - out[3 * 8];
494 workspace1[4] = out[4 * 8] + out[5 * 8];
495 workspace1[5] = out[4 * 8] - out[5 * 8];
497 workspace1[6] = out[6 * 8] + out[7 * 8];
498 workspace1[7] = out[6 * 8] - out[7 * 8];
501 workspace2[0] = workspace1[0] + workspace1[2];
502 workspace2[1] = workspace1[0] - workspace1[2];
503 workspace2[2] = workspace1[1] - workspace1[3];
504 workspace2[3] = workspace1[1] + workspace1[3];
506 workspace2[4] = workspace1[4] + workspace1[6];
507 workspace2[5] = workspace1[4] - workspace1[6];
508 workspace2[6] = workspace1[5] - workspace1[7];
509 workspace2[7] = workspace1[5] + workspace1[7];
515 out[0 * 8] = workspace2[0] + workspace2[4];
516 out[1 * 8] = workspace2[0] - workspace2[4];
517 out[2 * 8] = workspace2[1] - workspace2[5];
518 out[3 * 8] = workspace2[1] + workspace2[5];
519 out[4 * 8] = workspace2[2] + workspace2[6];
520 out[5 * 8] = workspace2[2] - workspace2[6];
521 out[6 * 8] = workspace2[3] - workspace2[7];
522 out[7 * 8] = workspace2[3] + workspace2[7];
524 for (d = 0; d < 8; d++)
529 out[0 * 8] = workspace2[0] + workspace2[4];
530 out[1 * 8] = workspace2[0] - workspace2[4];
531 out[2 * 8] = workspace2[1] - workspace2[5];
532 out[3 * 8] = workspace2[1] + workspace2[5];
533 out[4 * 8] = workspace2[2] + workspace2[6];
534 out[5 * 8] = workspace2[2] - workspace2[6];
535 out[6 * 8] = workspace2[3] - workspace2[7];
536 out[7 * 8] = workspace2[3] + workspace2[7];
538 for (d = 0; d < 8; d++) {
546 static void fill_encoder_block(const u8 *input, s16 *dst,
547 unsigned int stride, unsigned int input_step)
551 for (i = 0; i < 8; i++) {
552 for (j = 0; j < 8; j++, input += input_step)
554 input += (stride - 8) * input_step;
558 static int var_intra(const s16 *input)
562 const s16 *tmp = input;
565 for (i = 0; i < 8 * 8; i++, tmp++)
569 for (i = 0; i < 8 * 8; i++, tmp++)
570 ret += (*tmp - mean) < 0 ? -(*tmp - mean) : (*tmp - mean);
574 static int var_inter(const s16 *old, const s16 *new)
579 for (i = 0; i < 8 * 8; i++, old++, new++)
580 ret += (*old - *new) < 0 ? -(*old - *new) : (*old - *new);
584 static int decide_blocktype(const u8 *cur, const u8 *reference,
585 s16 *deltablock, unsigned int stride,
586 unsigned int input_step)
595 fill_encoder_block(cur, tmp, stride, input_step);
596 fill_encoder_block(reference, old, 8, 1);
597 vari = var_intra(tmp);
599 for (k = 0; k < 8; k++) {
600 for (l = 0; l < 8; l++) {
601 *deltablock = *work - *reference;
608 vard = var_inter(old, tmp);
609 return vari <= vard ? IBLOCK : PBLOCK;
612 static void fill_decoder_block(u8 *dst, const s16 *input, int stride)
616 for (i = 0; i < 8; i++) {
617 for (j = 0; j < 8; j++)
623 static void add_deltas(s16 *deltas, const u8 *ref, int stride)
627 for (k = 0; k < 8; k++) {
628 for (l = 0; l < 8; l++) {
631 * Due to quantizing, it might possible that the
632 * decoded coefficients are slightly out of range
636 else if (*deltas > 255)
644 static u32 encode_plane(u8 *input, u8 *refp, __be16 **rlco, __be16 *rlco_max,
645 struct cframe *cf, u32 height, u32 width,
646 unsigned int input_step,
647 bool is_intra, bool next_is_intra)
649 u8 *input_start = input;
650 __be16 *rlco_start = *rlco;
652 __be16 pframe_bit = htons(PFRAME_BIT);
654 unsigned int last_size = 0;
657 for (j = 0; j < height / 8; j++) {
658 for (i = 0; i < width / 8; i++) {
659 /* intra code, first frame is always intra coded. */
660 int blocktype = IBLOCK;
664 blocktype = decide_blocktype(input, refp,
665 deltablock, width, input_step);
666 if (blocktype == IBLOCK) {
667 fwht(input, cf->coeffs, width, input_step, 1);
668 quantize_intra(cf->coeffs, cf->de_coeffs,
672 encoding |= FRAME_PCODED;
673 fwht16(deltablock, cf->coeffs, 8, 0);
674 quantize_inter(cf->coeffs, cf->de_coeffs,
677 if (!next_is_intra) {
678 ifwht(cf->de_coeffs, cf->de_fwht, blocktype);
680 if (blocktype == PBLOCK)
681 add_deltas(cf->de_fwht, refp, 8);
682 fill_decoder_block(refp, cf->de_fwht, 8);
685 input += 8 * input_step;
688 size = rlc(cf->coeffs, *rlco, blocktype);
689 if (last_size == size &&
690 !memcmp(*rlco + 1, *rlco - size + 1, 2 * size - 2)) {
691 __be16 *last_rlco = *rlco - size;
692 s16 hdr = ntohs(*last_rlco);
694 if (!((*last_rlco ^ **rlco) & pframe_bit) &&
695 (hdr & DUPS_MASK) < DUPS_MASK)
696 *last_rlco = htons(hdr + 2);
702 if (*rlco >= rlco_max) {
703 encoding |= FRAME_UNENCODED;
708 input += width * 7 * input_step;
712 if (encoding & FRAME_UNENCODED) {
713 u8 *out = (u8 *)rlco_start;
717 * The compressed stream should never contain the magic
718 * header, so when we copy the YUV data we replace 0xff
719 * by 0xfe. Since YUV is limited range such values
720 * shouldn't appear anyway.
722 for (i = 0; i < height * width; i++, input += input_step)
723 *out++ = (*input == 0xff) ? 0xfe : *input;
724 *rlco = (__be16 *)out;
725 encoding &= ~FRAME_PCODED;
730 u32 encode_frame(struct raw_frame *frm, struct raw_frame *ref_frm,
731 struct cframe *cf, bool is_intra, bool next_is_intra)
733 unsigned int size = frm->height * frm->width;
734 __be16 *rlco = cf->rlc_data;
737 u32 chroma_h = frm->height / frm->height_div;
738 u32 chroma_w = frm->width / frm->width_div;
739 unsigned int chroma_size = chroma_h * chroma_w;
741 rlco_max = rlco + size / 2 - 256;
742 encoding = encode_plane(frm->luma, ref_frm->luma, &rlco, rlco_max, cf,
743 frm->height, frm->width,
744 frm->luma_step, is_intra, next_is_intra);
745 if (encoding & FRAME_UNENCODED)
746 encoding |= LUMA_UNENCODED;
747 encoding &= ~FRAME_UNENCODED;
748 rlco_max = rlco + chroma_size / 2 - 256;
749 encoding |= encode_plane(frm->cb, ref_frm->cb, &rlco, rlco_max, cf,
751 frm->chroma_step, is_intra, next_is_intra);
752 if (encoding & FRAME_UNENCODED)
753 encoding |= CB_UNENCODED;
754 encoding &= ~FRAME_UNENCODED;
755 rlco_max = rlco + chroma_size / 2 - 256;
756 encoding |= encode_plane(frm->cr, ref_frm->cr, &rlco, rlco_max, cf,
758 frm->chroma_step, is_intra, next_is_intra);
759 if (encoding & FRAME_UNENCODED)
760 encoding |= CR_UNENCODED;
761 encoding &= ~FRAME_UNENCODED;
762 cf->size = (rlco - cf->rlc_data) * sizeof(*rlco);
766 static void decode_plane(struct cframe *cf, const __be16 **rlco, u8 *ref,
767 u32 height, u32 width, bool uncompressed)
769 unsigned int copies = 0;
775 memcpy(ref, *rlco, width * height);
776 *rlco += width * height / 2;
781 * When decoding each macroblock the rlco pointer will be increased
782 * by 65 * 2 bytes worst-case.
783 * To avoid overflow the buffer has to be 65/64th of the actual raw
784 * image size, just in case someone feeds it malicious data.
786 for (j = 0; j < height / 8; j++) {
787 for (i = 0; i < width / 8; i++) {
788 u8 *refp = ref + j * 8 * width + i * 8;
791 memcpy(cf->de_fwht, copy, sizeof(copy));
792 if (stat & PFRAME_BIT)
793 add_deltas(cf->de_fwht, refp, width);
794 fill_decoder_block(refp, cf->de_fwht, width);
799 stat = derlc(rlco, cf->coeffs);
801 if (stat & PFRAME_BIT)
802 dequantize_inter(cf->coeffs);
804 dequantize_intra(cf->coeffs);
806 ifwht(cf->coeffs, cf->de_fwht,
807 (stat & PFRAME_BIT) ? 0 : 1);
809 copies = (stat & DUPS_MASK) >> 1;
811 memcpy(copy, cf->de_fwht, sizeof(copy));
812 if (stat & PFRAME_BIT)
813 add_deltas(cf->de_fwht, refp, width);
814 fill_decoder_block(refp, cf->de_fwht, width);
819 void decode_frame(struct cframe *cf, struct raw_frame *ref, u32 hdr_flags)
821 const __be16 *rlco = cf->rlc_data;
822 u32 h = cf->height / 2;
823 u32 w = cf->width / 2;
825 if (hdr_flags & VICODEC_FL_CHROMA_FULL_HEIGHT)
827 if (hdr_flags & VICODEC_FL_CHROMA_FULL_WIDTH)
829 decode_plane(cf, &rlco, ref->luma, cf->height, cf->width,
830 hdr_flags & VICODEC_FL_LUMA_IS_UNCOMPRESSED);
831 decode_plane(cf, &rlco, ref->cb, h, w,
832 hdr_flags & VICODEC_FL_CB_IS_UNCOMPRESSED);
833 decode_plane(cf, &rlco, ref->cr, h, w,
834 hdr_flags & VICODEC_FL_CR_IS_UNCOMPRESSED);