1
2 /*
3 * Copyright 2018 Google LLC. All rights reserved.
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
6 * use this file except in compliance with the License. You may obtain a copy of
7 * the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
13 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
14 * License for the specific language governing permissions and limitations under
15 * the License.
16 */
17
18 // This file contains an adaptation of the algorithm at:
19 // https://github.com/GoogleChromeLabs/wasm-av1/blob/master/yuv-to-rgb.c
20
21 // The algorithm here creates precomputed lookup tables to speed up converting
22 // YUV frames to RGB. Since it is done once every camera frame it needs to be
23 // efficient.
24 //
25 // NOTE: This is code is being used temporarily until Cuttlefish supports
26 // hardware-accelerated camera frame transfer from host to guest. Ideally the
27 // conversions will be done via DMA or GPU algorithms, not via CPU copy
28
29 // Number of luminance values to precompute tables of for speed. Value is higher
30 // than 255 as to allow for future color depth expansion
31 #define ZOF_TAB 65536
32
33 // Size of single output pixel in bytes (RGBA x 1 byte each = 4 bytes)
34 #define ZOF_RGB 4
35
36 namespace cuttlefish {
37
38 // These tables will store precomputes values
39 static int T1[ZOF_TAB], T2[ZOF_TAB], T3[ZOF_TAB], T4[ZOF_TAB];
40 static int tables_initialized;
41
42 // Called once to initialize tables
build_yuv2rgb_tables()43 static void build_yuv2rgb_tables() {
44 for (int i = 0; i < ZOF_TAB; i++) {
45 T1[i] = (int)(1.370705 * (float)(i - 128));
46 T2[i] = (int)(-0.698001 * (float)(i - 128));
47 T3[i] = (int)(-0.337633 * (float)(i - 128));
48 T4[i] = (int)(1.732446 * (float)(i - 128));
49 }
50 }
51
52 #define clamp(val) ((val) < 0 ? 0 : (255 < (val) ? 255 : (val)))
53
Yuv2Rgb(unsigned char * src,unsigned char * dst,int width,int height)54 void Yuv2Rgb(unsigned char *src, unsigned char *dst, int width, int height) {
55 if (tables_initialized == 0) {
56 tables_initialized = !0;
57 build_yuv2rgb_tables();
58 }
59 // Setup pointers to the Y, U, V planes
60 unsigned char *y = src;
61 unsigned char *u = src + (width * height);
62 unsigned char *v =
63 u + (width * height) / 4; // Each chroma does 4 pixels in 4:2:0
64 // Loop the image, taking into account sub-sample for the chroma channels
65 for (int h = 0; h < height; h++) {
66 unsigned char *uline = u;
67 unsigned char *vline = v;
68 for (int w = 0; w < width; w++, y++) {
69 int r = *y + T1[*vline];
70 int g = *y + T2[*vline] + T3[*uline];
71 int b = *y + T4[*uline];
72 // Note: going BGRA here not RGBA
73 dst[0] = clamp(b); // 16-bit to 8-bit, chuck precision
74 dst[1] = clamp(g);
75 dst[2] = clamp(r);
76 dst[3] = 255;
77 dst += ZOF_RGB;
78 if (w & 0x01) {
79 uline++;
80 vline++;
81 }
82 }
83 if (h & 0x01) {
84 u += width / 2;
85 v += width / 2;
86 }
87 }
88 }
89
90 } // End namespace cuttlefish