blob: f63f67f112d2392e3ad53c9bf3f9cf3e49ca4a0e
1 | /* |
2 | * Copyright (C) 2011 The Android Open Source Project |
3 | * |
4 | * Licensed under the Apache License, Version 2.0 (the "License"); |
5 | * you may not use this file except in compliance with the License. |
6 | * You may obtain a copy of the License at |
7 | * |
8 | * http://www.apache.org/licenses/LICENSE-2.0 |
9 | * |
10 | * Unless required by applicable law or agreed to in writing, software |
11 | * distributed under the License is distributed on an "AS IS" BASIS, |
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
13 | * See the License for the specific language governing permissions and |
14 | * limitations under the License. |
15 | */ |
16 | |
17 | /* |
18 | * Contains implemenation of framebuffer conversion routines. |
19 | */ |
20 | |
21 | #define LOG_NDEBUG 0 |
22 | #define LOG_TAG "EmulatedCamera_Converter" |
23 | #include <cutils/log.h> |
24 | #include "Converters.h" |
25 | |
26 | namespace android { |
27 | |
28 | static void _YUV420SToRGB565(const uint8_t* Y, |
29 | const uint8_t* U, |
30 | const uint8_t* V, |
31 | int dUV, |
32 | uint16_t* rgb, |
33 | int width, |
34 | int height) |
35 | { |
36 | const uint8_t* U_pos = U; |
37 | const uint8_t* V_pos = V; |
38 | |
39 | for (int y = 0; y < height; y++) { |
40 | for (int x = 0; x < width; x += 2, U += dUV, V += dUV) { |
41 | const uint8_t nU = *U; |
42 | const uint8_t nV = *V; |
43 | *rgb = YUVToRGB565(*Y, nU, nV); |
44 | Y++; rgb++; |
45 | *rgb = YUVToRGB565(*Y, nU, nV); |
46 | Y++; rgb++; |
47 | } |
48 | if (y & 0x1) { |
49 | U_pos = U; |
50 | V_pos = V; |
51 | } else { |
52 | U = U_pos; |
53 | V = V_pos; |
54 | } |
55 | } |
56 | } |
57 | |
58 | static void _YUV420SToRGB32(const uint8_t* Y, |
59 | const uint8_t* U, |
60 | const uint8_t* V, |
61 | int dUV, |
62 | uint32_t* rgb, |
63 | int width, |
64 | int height) |
65 | { |
66 | const uint8_t* U_pos = U; |
67 | const uint8_t* V_pos = V; |
68 | |
69 | for (int y = 0; y < height; y++) { |
70 | for (int x = 0; x < width; x += 2, U += dUV, V += dUV) { |
71 | const uint8_t nU = *U; |
72 | const uint8_t nV = *V; |
73 | *rgb = YUVToRGB32(*Y, nU, nV); |
74 | Y++; rgb++; |
75 | *rgb = YUVToRGB32(*Y, nU, nV); |
76 | Y++; rgb++; |
77 | } |
78 | if (y & 0x1) { |
79 | U_pos = U; |
80 | V_pos = V; |
81 | } else { |
82 | U = U_pos; |
83 | V = V_pos; |
84 | } |
85 | } |
86 | } |
87 | |
88 | void YV12ToRGB565(const void* yv12, void* rgb, int width, int height) |
89 | { |
90 | const int pix_total = width * height; |
91 | const uint8_t* Y = reinterpret_cast<const uint8_t*>(yv12); |
92 | const uint8_t* U = Y + pix_total; |
93 | const uint8_t* V = U + pix_total / 4; |
94 | _YUV420SToRGB565(Y, U, V, 1, reinterpret_cast<uint16_t*>(rgb), width, height); |
95 | } |
96 | |
97 | void YV12ToRGB32(const void* yv12, void* rgb, int width, int height) |
98 | { |
99 | const int pix_total = width * height; |
100 | const uint8_t* Y = reinterpret_cast<const uint8_t*>(yv12); |
101 | const uint8_t* V = Y + pix_total; |
102 | const uint8_t* U = V + pix_total / 4; |
103 | _YUV420SToRGB32(Y, U, V, 1, reinterpret_cast<uint32_t*>(rgb), width, height); |
104 | } |
105 | |
106 | void YU12ToRGB32(const void* yu12, void* rgb, int width, int height) |
107 | { |
108 | const int pix_total = width * height; |
109 | const uint8_t* Y = reinterpret_cast<const uint8_t*>(yu12); |
110 | const uint8_t* U = Y + pix_total; |
111 | const uint8_t* V = U + pix_total / 4; |
112 | _YUV420SToRGB32(Y, U, V, 1, reinterpret_cast<uint32_t*>(rgb), width, height); |
113 | } |
114 | |
115 | /* Common converter for YUV 4:2:0 interleaved to RGB565. |
116 | * y, u, and v point to Y,U, and V panes, where U and V values are interleaved. |
117 | */ |
118 | static void _NVXXToRGB565(const uint8_t* Y, |
119 | const uint8_t* U, |
120 | const uint8_t* V, |
121 | uint16_t* rgb, |
122 | int width, |
123 | int height) |
124 | { |
125 | _YUV420SToRGB565(Y, U, V, 2, rgb, width, height); |
126 | } |
127 | |
128 | /* Common converter for YUV 4:2:0 interleaved to RGB32. |
129 | * y, u, and v point to Y,U, and V panes, where U and V values are interleaved. |
130 | */ |
131 | static void _NVXXToRGB32(const uint8_t* Y, |
132 | const uint8_t* U, |
133 | const uint8_t* V, |
134 | uint32_t* rgb, |
135 | int width, |
136 | int height) |
137 | { |
138 | _YUV420SToRGB32(Y, U, V, 2, rgb, width, height); |
139 | } |
140 | |
141 | void NV12ToRGB565(const void* nv12, void* rgb, int width, int height) |
142 | { |
143 | const int pix_total = width * height; |
144 | const uint8_t* y = reinterpret_cast<const uint8_t*>(nv12); |
145 | _NVXXToRGB565(y, y + pix_total, y + pix_total + 1, |
146 | reinterpret_cast<uint16_t*>(rgb), width, height); |
147 | } |
148 | |
149 | void NV12ToRGB32(const void* nv12, void* rgb, int width, int height) |
150 | { |
151 | const int pix_total = width * height; |
152 | const uint8_t* y = reinterpret_cast<const uint8_t*>(nv12); |
153 | _NVXXToRGB32(y, y + pix_total, y + pix_total + 1, |
154 | reinterpret_cast<uint32_t*>(rgb), width, height); |
155 | } |
156 | |
157 | void NV21ToRGB565(const void* nv21, void* rgb, int width, int height) |
158 | { |
159 | const int pix_total = width * height; |
160 | const uint8_t* y = reinterpret_cast<const uint8_t*>(nv21); |
161 | _NVXXToRGB565(y, y + pix_total + 1, y + pix_total, |
162 | reinterpret_cast<uint16_t*>(rgb), width, height); |
163 | } |
164 | |
165 | void NV21ToRGB32(const void* nv21, void* rgb, int width, int height) |
166 | { |
167 | const int pix_total = width * height; |
168 | const uint8_t* y = reinterpret_cast<const uint8_t*>(nv21); |
169 | _NVXXToRGB32(y, y + pix_total + 1, y + pix_total, |
170 | reinterpret_cast<uint32_t*>(rgb), width, height); |
171 | } |
172 | |
173 | }; /* namespace android */ |
174 |