blob: ea28a337b3991013bae431e4feefbac6cc6dc302
1 | #include <stdio.h> |
2 | #include <stdlib.h> |
3 | #include <unistd.h> |
4 | #include <sys/ioctl.h> |
5 | #include <sys/types.h> |
6 | #include <sys/stat.h> |
7 | #include "util.h" |
8 | |
9 | #ifdef AMLOGIC_USB_CAMERA_SUPPORT |
10 | #define swap_cbcr |
11 | static void convert_rgb16_to_nv21(uint8_t *rgb, uint8_t *yuv, int width, int height) |
12 | { |
13 | int iy =0, iuv = 0; |
14 | uint8_t* buf_y = yuv; |
15 | uint8_t* buf_uv = buf_y + width * height; |
16 | uint16_t* buf_rgb = (uint16_t *)rgb; |
17 | int h,w,val_rgb,val_r,val_g,val_b; |
18 | int y,u,v; |
19 | for (h = 0; h < height; h++) { |
20 | for (w = 0; w < width; w++) { |
21 | val_rgb = buf_rgb[h * width + w]; |
22 | val_r = ((val_rgb & (0x1f << 11)) >> 11)<<3; |
23 | val_g = ((val_rgb & (0x3f << 5)) >> 5)<<2; |
24 | val_b = ((val_rgb & (0x1f << 0)) >> 0)<<3; |
25 | y = 0.30078 * val_r + 0.5859 * val_g + 0.11328 * val_b; |
26 | if (y > 255) { |
27 | y = 255; |
28 | } else if (y < 0) { |
29 | y = 0; |
30 | } |
31 | buf_y[iy++] = y; |
32 | if (0 == h % 2 && 0 == w % 2) { |
33 | u = -0.11328 * val_r - 0.33984 * val_g + 0.51179 * val_b + 128; |
34 | if (u > 255) { |
35 | u = 255; |
36 | } else if (u < 0) { |
37 | u = 0; |
38 | } |
39 | v = 0.51179 * val_r - 0.429688 * val_g - 0.08203 * val_b + 128; |
40 | if (v > 255) { |
41 | v = 255; |
42 | } else if (v < 0) { |
43 | v = 0; |
44 | } |
45 | #ifdef swap_cbcr |
46 | buf_uv[iuv++] = v; |
47 | buf_uv[iuv++] = u; |
48 | #else |
49 | buf_uv[iuv++] = u; |
50 | buf_uv[iuv++] = v; |
51 | #endif |
52 | } |
53 | } |
54 | } |
55 | } |
56 | |
57 | static inline void yuv_to_rgb16(unsigned char y,unsigned char u,unsigned char v,unsigned char *rgb) |
58 | { |
59 | register int r,g,b; |
60 | int rgb16; |
61 | |
62 | r = (1192 * (y - 16) + 1634 * (v - 128) ) >> 10; |
63 | g = (1192 * (y - 16) - 833 * (v - 128) - 400 * (u -128) ) >> 10; |
64 | b = (1192 * (y - 16) + 2066 * (u - 128) ) >> 10; |
65 | |
66 | r = r > 255 ? 255 : r < 0 ? 0 : r; |
67 | g = g > 255 ? 255 : g < 0 ? 0 : g; |
68 | b = b > 255 ? 255 : b < 0 ? 0 : b; |
69 | |
70 | rgb16 = (int)(((r >> 3)<<11) | ((g >> 2) << 5)| ((b >> 3) << 0)); |
71 | |
72 | *rgb = (unsigned char)(rgb16 & 0xFF); |
73 | rgb++; |
74 | *rgb = (unsigned char)((rgb16 & 0xFF00) >> 8); |
75 | |
76 | } |
77 | |
78 | void yuyv422_to_rgb16(unsigned char *from, unsigned char *to, int size) |
79 | { |
80 | int x,y,z=0; |
81 | |
82 | for (y = 0; y < size; y+=4) { |
83 | unsigned char Y1, Y2, U, V; |
84 | |
85 | Y1 = from[y + 0]; |
86 | U = from[y + 1]; |
87 | Y2 = from[y + 2]; |
88 | V = from[y + 3]; |
89 | |
90 | yuv_to_rgb16(Y1, U, V, &to[y]); |
91 | yuv_to_rgb16(Y2, U, V, &to[y + 2]); |
92 | } |
93 | } |
94 | |
95 | void yuyv422_to_rgb16(unsigned char *from, unsigned char *to, int width, int height) |
96 | { |
97 | yuyv422_to_rgb16(from,to,(width * height) * 2); |
98 | } |
99 | |
100 | void yuyv422_to_nv21(unsigned char *bufsrc, unsigned char *bufdest, int width, int height) |
101 | { |
102 | unsigned char *ptrsrcy1, *ptrsrcy2; |
103 | unsigned char *ptrsrcy3, *ptrsrcy4; |
104 | unsigned char *ptrsrccb1, *ptrsrccb2; |
105 | unsigned char *ptrsrccb3, *ptrsrccb4; |
106 | unsigned char *ptrsrccr1, *ptrsrccr2; |
107 | unsigned char *ptrsrccr3, *ptrsrccr4; |
108 | int srcystride, srcccstride; |
109 | |
110 | ptrsrcy1 = bufsrc ; |
111 | ptrsrcy2 = bufsrc + (width<<1) ; |
112 | ptrsrcy3 = bufsrc + (width<<1)*2 ; |
113 | ptrsrcy4 = bufsrc + (width<<1)*3 ; |
114 | |
115 | ptrsrccb1 = bufsrc + 1; |
116 | ptrsrccb2 = bufsrc + (width<<1) + 1; |
117 | ptrsrccb3 = bufsrc + (width<<1)*2 + 1; |
118 | ptrsrccb4 = bufsrc + (width<<1)*3 + 1; |
119 | |
120 | ptrsrccr1 = bufsrc + 3; |
121 | ptrsrccr2 = bufsrc + (width<<1) + 3; |
122 | ptrsrccr3 = bufsrc + (width<<1)*2 + 3; |
123 | ptrsrccr4 = bufsrc + (width<<1)*3 + 3; |
124 | |
125 | srcystride = (width<<1)*3; |
126 | srcccstride = (width<<1)*3; |
127 | |
128 | unsigned char *ptrdesty1, *ptrdesty2; |
129 | unsigned char *ptrdesty3, *ptrdesty4; |
130 | unsigned char *ptrdestcb1, *ptrdestcb2; |
131 | unsigned char *ptrdestcr1, *ptrdestcr2; |
132 | int destystride, destccstride; |
133 | |
134 | ptrdesty1 = bufdest; |
135 | ptrdesty2 = bufdest + width; |
136 | ptrdesty3 = bufdest + width*2; |
137 | ptrdesty4 = bufdest + width*3; |
138 | |
139 | ptrdestcb1 = bufdest + width*height; |
140 | ptrdestcb2 = bufdest + width*height + width; |
141 | |
142 | ptrdestcr1 = bufdest + width*height + 1; |
143 | ptrdestcr2 = bufdest + width*height + width + 1; |
144 | |
145 | destystride = (width)*3; |
146 | destccstride = width; |
147 | |
148 | int i, j; |
149 | |
150 | for(j=0; j<(height/4); j++) |
151 | { |
152 | for(i=0;i<(width/2);i++) |
153 | { |
154 | (*ptrdesty1++) = (*ptrsrcy1); |
155 | (*ptrdesty2++) = (*ptrsrcy2); |
156 | (*ptrdesty3++) = (*ptrsrcy3); |
157 | (*ptrdesty4++) = (*ptrsrcy4); |
158 | |
159 | ptrsrcy1 += 2; |
160 | ptrsrcy2 += 2; |
161 | ptrsrcy3 += 2; |
162 | ptrsrcy4 += 2; |
163 | |
164 | (*ptrdesty1++) = (*ptrsrcy1); |
165 | (*ptrdesty2++) = (*ptrsrcy2); |
166 | (*ptrdesty3++) = (*ptrsrcy3); |
167 | (*ptrdesty4++) = (*ptrsrcy4); |
168 | |
169 | ptrsrcy1 += 2; |
170 | ptrsrcy2 += 2; |
171 | ptrsrcy3 += 2; |
172 | ptrsrcy4 += 2; |
173 | |
174 | #if 0 |
175 | (*ptrdestcb1) = (*ptrsrccb1); |
176 | (*ptrdestcb2) = (*ptrsrccb3); |
177 | #else |
178 | (*ptrdestcb1) = (*ptrsrccr1); |
179 | (*ptrdestcb2) = (*ptrsrccr3); |
180 | #endif |
181 | |
182 | #if 0 |
183 | (*ptrdestcr1) = (*ptrsrccr1); |
184 | (*ptrdestcr2) = (*ptrsrccr3); |
185 | #else |
186 | (*ptrdestcr1) = (*ptrsrccb1); |
187 | (*ptrdestcr2) = (*ptrsrccb3); |
188 | #endif |
189 | |
190 | ptrdestcb1 += 2; |
191 | ptrdestcb2 += 2; |
192 | ptrdestcr1 += 2; |
193 | ptrdestcr2 += 2; |
194 | |
195 | ptrsrccb1 += 4; |
196 | ptrsrccb3 += 4; |
197 | ptrsrccr1 += 4; |
198 | ptrsrccr3 += 4; |
199 | |
200 | } |
201 | |
202 | |
203 | /* Update src pointers */ |
204 | ptrsrcy1 += srcystride; |
205 | ptrsrcy2 += srcystride; |
206 | ptrsrcy3 += srcystride; |
207 | ptrsrcy4 += srcystride; |
208 | |
209 | ptrsrccb1 += srcccstride; |
210 | ptrsrccb3 += srcccstride; |
211 | |
212 | ptrsrccr1 += srcccstride; |
213 | ptrsrccr3 += srcccstride; |
214 | |
215 | |
216 | /* Update dest pointers */ |
217 | ptrdesty1 += destystride; |
218 | ptrdesty2 += destystride; |
219 | ptrdesty3 += destystride; |
220 | ptrdesty4 += destystride; |
221 | |
222 | ptrdestcb1 += destccstride; |
223 | ptrdestcb2 += destccstride; |
224 | |
225 | ptrdestcr1 += destccstride; |
226 | ptrdestcr2 += destccstride; |
227 | |
228 | } |
229 | } |
230 | |
231 | static inline void yuv_to_rgb24(unsigned char y,unsigned char u,unsigned char v,unsigned char *rgb) |
232 | { |
233 | register int r,g,b; |
234 | int rgb24; |
235 | |
236 | r = (1192 * (y - 16) + 1634 * (v - 128) ) >> 10; |
237 | g = (1192 * (y - 16) - 833 * (v - 128) - 400 * (u -128) ) >> 10; |
238 | b = (1192 * (y - 16) + 2066 * (u - 128) ) >> 10; |
239 | |
240 | r = r > 255 ? 255 : r < 0 ? 0 : r; |
241 | g = g > 255 ? 255 : g < 0 ? 0 : g; |
242 | b = b > 255 ? 255 : b < 0 ? 0 : b; |
243 | |
244 | rgb24 = (int)((r <<16) | (g << 8)| b); |
245 | |
246 | *rgb = (unsigned char)r; |
247 | rgb++; |
248 | *rgb = (unsigned char)g; |
249 | rgb++; |
250 | *rgb = (unsigned char)b; |
251 | } |
252 | |
253 | void yuyv422_to_rgb24(unsigned char *buf, unsigned char *rgb, int width, int height) |
254 | { |
255 | int x,y,z=0; |
256 | int blocks; |
257 | |
258 | blocks = (width * height) * 2; |
259 | |
260 | for (y = 0,z=0; y < blocks; y+=4,z+=6) { |
261 | unsigned char Y1, Y2, U, V; |
262 | |
263 | Y1 = buf[y + 0]; |
264 | U = buf[y + 1]; |
265 | Y2 = buf[y + 2]; |
266 | V = buf[y + 3]; |
267 | |
268 | yuv_to_rgb24(Y1, U, V, &rgb[z]); |
269 | yuv_to_rgb24(Y2, U, V, &rgb[z + 3]); |
270 | |
271 | } |
272 | } |
273 | |
274 | void convert_rgb24_to_rgb16(uint8_t *src, uint8_t *dst, int width, int height) |
275 | { |
276 | int src_len = width*height*3; |
277 | int i = 0; |
278 | int j = 0; |
279 | |
280 | for (i = 0; i < src_len; i += 3) |
281 | { |
282 | dst[j] = (src[i]&0x1f) | (src[i+1]>>5); |
283 | dst[j+1] = ((src[i+1]>>2)<<5) | (src[i+2]>>3); |
284 | j += 2; |
285 | } |
286 | } |
287 | void yuyv_to_yv12(unsigned char *src, unsigned char *dst, int width, int height) |
288 | { |
289 | //width should be an even number. |
290 | //uv ALIGN 32. |
291 | int i,j,stride,c_stride,c_size,y_size,cb_offset,cr_offset; |
292 | unsigned char *dst_copy,*src_copy; |
293 | |
294 | dst_copy = dst; |
295 | src_copy = src; |
296 | |
297 | y_size = width*height; |
298 | c_stride = ALIGN(width/2, 16); |
299 | c_size = c_stride * height/2; |
300 | cr_offset = y_size; |
301 | cb_offset = y_size+c_size; |
302 | |
303 | for(i=0;i< y_size;i++){ |
304 | *dst++ = *src; |
305 | src += 2; |
306 | } |
307 | |
308 | dst = dst_copy; |
309 | src = src_copy; |
310 | |
311 | for(i=0;i<height;i+=2){ |
312 | for(j=1;j<width*2;j+=4){//one line has 2*width bytes for yuyv. |
313 | //ceil(u1+u2)/2 |
314 | *(dst+cr_offset+j/4)= (*(src+j+2) + *(src+j+2+width*2) + 1)/2; |
315 | *(dst+cb_offset+j/4)= (*(src+j) + *(src+j+width*2) + 1)/2; |
316 | } |
317 | dst += c_stride; |
318 | src += width*4; |
319 | } |
320 | } |
321 | #endif |
322 | void rgb24_memcpy(unsigned char *dst, unsigned char *src, int width, int height) |
323 | { |
324 | int stride = (width + 31) & ( ~31); |
325 | int w, h; |
326 | for (h=0; h<height; h++) |
327 | { |
328 | memcpy( dst, src, width*3); |
329 | dst += width*3; |
330 | src += stride*3; |
331 | } |
332 | } |
333 | |
334 | void nv21_memcpy_align32(unsigned char *dst, unsigned char *src, int width, int height) |
335 | { |
336 | int stride = (width + 31) & ( ~31); |
337 | int w, h; |
338 | for (h=0; h<height*3/2; h++) |
339 | { |
340 | memcpy( dst, src, width); |
341 | dst += width; |
342 | src += stride; |
343 | } |
344 | } |
345 | |
346 | void yv12_memcpy_align32(unsigned char *dst, unsigned char *src, int width, int height) |
347 | { |
348 | int new_width = (width + 63) & ( ~63); |
349 | int stride; |
350 | int w, h; |
351 | for (h=0; h<height; h++) |
352 | { |
353 | memcpy( dst, src, width); |
354 | dst += width; |
355 | src += new_width; |
356 | } |
357 | |
358 | stride = ALIGN(width/2, 16); |
359 | for (h=0; h<height; h++) |
360 | { |
361 | memcpy( dst, src, width/2); |
362 | dst += stride; |
363 | src += new_width/2; |
364 | } |
365 | } |
366 | |
367 | void yv12_adjust_memcpy(unsigned char *dst, unsigned char *src, int width, int height) |
368 | { |
369 | //width should be an even number. |
370 | int i,stride; |
371 | memcpy( dst, src, width*height); |
372 | src += width*height; |
373 | dst += width*height; |
374 | |
375 | stride = ALIGN(width/2, 16); |
376 | for(i =0; i< height; i++) |
377 | { |
378 | memcpy(dst,src, stride); |
379 | src+=width/2; |
380 | dst+=stride; |
381 | } |
382 | } |
383 | |
384 | void nv21_memcpy_canvas1080(unsigned char *dst, unsigned char *src, int width, int height) |
385 | { |
386 | int h; |
387 | for (h=0; h<height; h++){ |
388 | memcpy( dst, src, width); |
389 | dst += width; |
390 | src += width; |
391 | } |
392 | src+=width*8; |
393 | for (h=0; h<height/2; h++){ |
394 | memcpy( dst, src, width); |
395 | dst += width; |
396 | src += width; |
397 | } |
398 | } |
399 | |
400 | void yv12_memcpy_canvas1080(unsigned char *dst, unsigned char *src, int width, int height) |
401 | { |
402 | int h; |
403 | for (h=0; h<height; h++){ |
404 | memcpy( dst, src, width); |
405 | dst += width; |
406 | src += width; |
407 | } |
408 | src+=width*8; |
409 | for (h=0; h<height/2; h++){ |
410 | memcpy( dst, src, width/2); |
411 | dst += width/2; |
412 | src += width/2; |
413 | } |
414 | src+=width*2; |
415 | for (h=0; h<height/2; h++){ |
416 | memcpy( dst, src, width/2); |
417 | dst += width/2; |
418 | src += width/2; |
419 | } |
420 | } |
421 |