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
26namespace android {
27
28static 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
58static 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
88void 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
97void 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
106void 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 */
118static 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 */
131static 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
141void 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
149void 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
157void 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
165void 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