blob: 723505c49e3d9c4544701973c21e97a3a8609ea3
1 | /*******************************************************************************# |
2 | # guvcview http://guvcview.sourceforge.net # |
3 | # # |
4 | # Paulo Assis <pj.assis@gmail.com> # |
5 | # Nobuhiro Iwamatsu <iwamatsu@nigauri.org> # |
6 | # # |
7 | # This program is free software; you can redistribute it and/or modify # |
8 | # it under the terms of the GNU General Public License as published by # |
9 | # the Free Software Foundation; either version 2 of the License, or # |
10 | # (at your option) any later version. # |
11 | # # |
12 | # This program is distributed in the hope that it will be useful, # |
13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of # |
14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # |
15 | # GNU General Public License for more details. # |
16 | # # |
17 | # You should have received a copy of the GNU General Public License # |
18 | # along with this program; if not, write to the Free Software # |
19 | # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # |
20 | # # |
21 | ********************************************************************************/ |
22 | |
23 | #include <stdlib.h> |
24 | #include <stdio.h> |
25 | #include <string.h> |
26 | #include "colorspaces.h" |
27 | #include <stdbool.h> |
28 | #define TRUE 1 |
29 | #define FALSE 0 |
30 | /*------------------------------- Color space conversions --------------------*/ |
31 | /* regular yuv (YUYV) to rgb24*/ |
32 | void |
33 | yuyv2rgb (BYTE *pyuv, BYTE *prgb, int width, int height) |
34 | { |
35 | int l=0; |
36 | int SizeYUV=height * width * 2; /* 2 bytes per pixel*/ |
37 | for(l=0;l<SizeYUV;l=l+4) |
38 | { /*iterate every 4 bytes*/ |
39 | /* standart: r = y0 + 1.402 (v-128) */ |
40 | /* logitech: r = y0 + 1.370705 (v-128) */ |
41 | *prgb++=CLIP(pyuv[l] + 1.402 * (pyuv[l+3]-128)); |
42 | /* standart: g = y0 - 0.34414 (u-128) - 0.71414 (v-128)*/ |
43 | /* logitech: g = y0 - 0.337633 (u-128)- 0.698001 (v-128)*/ |
44 | *prgb++=CLIP(pyuv[l] - 0.34414 * (pyuv[l+1]-128) -0.71414*(pyuv[l+3]-128)); |
45 | /* standart: b = y0 + 1.772 (u-128) */ |
46 | /* logitech: b = y0 + 1.732446 (u-128) */ |
47 | *prgb++=CLIP(pyuv[l] + 1.772 *( pyuv[l+1]-128)); |
48 | /* standart: r1 =y1 + 1.402 (v-128) */ |
49 | /* logitech: r1 = y1 + 1.370705 (v-128) */ |
50 | *prgb++=CLIP(pyuv[l+2] + 1.402 * (pyuv[l+3]-128)); |
51 | /* standart: g1 = y1 - 0.34414 (u-128) - 0.71414 (v-128)*/ |
52 | /* logitech: g1 = y1 - 0.337633 (u-128)- 0.698001 (v-128)*/ |
53 | *prgb++=CLIP(pyuv[l+2] - 0.34414 * (pyuv[l+1]-128) -0.71414 * (pyuv[l+3]-128)); |
54 | /* standart: b1 = y1 + 1.772 (u-128) */ |
55 | /* logitech: b1 = y1 + 1.732446 (u-128) */ |
56 | *prgb++=CLIP(pyuv[l+2] + 1.772*(pyuv[l+1]-128)); |
57 | } |
58 | } |
59 | |
60 | /* used for rgb video (fourcc="RGB ") */ |
61 | /* lines are on correct order */ |
62 | void |
63 | yuyv2bgr1 (BYTE *pyuv, BYTE *pbgr, int width, int height) |
64 | { |
65 | |
66 | int l=0; |
67 | int SizeYUV=height * width * 2; /* 2 bytes per pixel*/ |
68 | for(l=0;l<SizeYUV;l=l+4) |
69 | { /*iterate every 4 bytes*/ |
70 | /* standart: b = y0 + 1.772 (u-128) */ |
71 | /* logitech: b = y0 + 1.732446 (u-128) */ |
72 | *pbgr++=CLIP(pyuv[l] + 1.772 *( pyuv[l+1]-128)); |
73 | /* standart: g = y0 - 0.34414 (u-128) - 0.71414 (v-128)*/ |
74 | /* logitech: g = y0 - 0.337633 (u-128)- 0.698001 (v-128)*/ |
75 | *pbgr++=CLIP(pyuv[l] - 0.34414 * (pyuv[l+1]-128) -0.71414*(pyuv[l+3]-128)); |
76 | /* standart: r = y0 + 1.402 (v-128) */ |
77 | /* logitech: r = y0 + 1.370705 (v-128) */ |
78 | *pbgr++=CLIP(pyuv[l] + 1.402 * (pyuv[l+3]-128)); |
79 | /* standart: b1 = y1 + 1.772 (u-128) */ |
80 | /* logitech: b1 = y1 + 1.732446 (u-128) */ |
81 | *pbgr++=CLIP(pyuv[l+2] + 1.772*(pyuv[l+1]-128)); |
82 | /* standart: g1 = y1 - 0.34414 (u-128) - 0.71414 (v-128)*/ |
83 | /* logitech: g1 = y1 - 0.337633 (u-128)- 0.698001 (v-128)*/ |
84 | *pbgr++=CLIP(pyuv[l+2] - 0.34414 * (pyuv[l+1]-128) -0.71414 * (pyuv[l+3]-128)); |
85 | /* standart: r1 =y1 + 1.402 (v-128) */ |
86 | /* logitech: r1 = y1 + 1.370705 (v-128) */ |
87 | *pbgr++=CLIP(pyuv[l+2] + 1.402 * (pyuv[l+3]-128)); |
88 | } |
89 | } |
90 | |
91 | /* yuv (YUYV) to bgr with lines upsidedown */ |
92 | /* used for bitmap files (DIB24) */ |
93 | void |
94 | yuyv2bgr (BYTE *pyuv, BYTE *pbgr, int width, int height) |
95 | { |
96 | |
97 | int l=0; |
98 | int k=0; |
99 | BYTE *preverse; |
100 | int bytesUsed; |
101 | int SizeBGR=height * width * 3; /* 3 bytes per pixel*/ |
102 | /* BMP byte order is bgr and the lines start from last to first*/ |
103 | preverse=pbgr+SizeBGR;/*start at the end and decrement*/ |
104 | for(l=0;l<height;l++) |
105 | { /*iterate every 1 line*/ |
106 | preverse-=width*3;/*put pointer at begin of unprocessed line*/ |
107 | bytesUsed=l*width*2; |
108 | for (k=0;k<(width*2);k=k+4)/*iterate every 4 bytes in the line*/ |
109 | { |
110 | /* standart: b = y0 + 1.772 (u-128) */ |
111 | /* logitech: b = y0 + 1.732446 (u-128) */ |
112 | *preverse++=CLIP(pyuv[k+bytesUsed] + 1.772 *( pyuv[k+1+bytesUsed]-128)); |
113 | /* standart: g = y0 - 0.34414 (u-128) - 0.71414 (v-128)*/ |
114 | /* logitech: g = y0 - 0.337633 (u-128)- 0.698001 (v-128)*/ |
115 | *preverse++=CLIP(pyuv[k+bytesUsed] - 0.34414 * (pyuv[k+1+bytesUsed]-128) |
116 | -0.71414*(pyuv[k+3+bytesUsed]-128)); |
117 | /* standart: r = y0 + 1.402 (v-128) */ |
118 | /* logitech: r = y0 + 1.370705 (v-128) */ |
119 | *preverse++=CLIP(pyuv[k+bytesUsed] + 1.402 * (pyuv[k+3+bytesUsed]-128)); |
120 | /* standart: b1 = y1 + 1.772 (u-128) */ |
121 | /* logitech: b1 = y1 + 1.732446 (u-128) */ |
122 | *preverse++=CLIP(pyuv[k+2+bytesUsed] + 1.772*(pyuv[k+1+bytesUsed]-128)); |
123 | /* standart: g1 = y1 - 0.34414 (u-128) - 0.71414 (v-128)*/ |
124 | /* logitech: g1 = y1 - 0.337633 (u-128)- 0.698001 (v-128)*/ |
125 | *preverse++=CLIP(pyuv[k+2+bytesUsed] - 0.34414 * (pyuv[k+1+bytesUsed]-128) |
126 | -0.71414 * (pyuv[k+3+bytesUsed]-128)); |
127 | /* standart: r1 =y1 + 1.402 (v-128) */ |
128 | /* logitech: r1 = y1 + 1.370705 (v-128) */ |
129 | *preverse++=CLIP(pyuv[k+2+bytesUsed] + 1.402 * (pyuv[k+3+bytesUsed]-128)); |
130 | } |
131 | preverse-=width*3;/*get it back at the begin of processed line*/ |
132 | } |
133 | preverse=NULL; |
134 | } |
135 | |
136 | /* Unpack buffer of (vw bit) data into padded 16bit buffer. */ |
137 | static inline void convert_packed_to_16bit(uint8_t *raw, uint16_t *unpacked, int vw, int unpacked_len) |
138 | { |
139 | int mask = (1 << vw) - 1; |
140 | uint32_t buffer = 0; |
141 | int bitsIn = 0; |
142 | while (unpacked_len--) { |
143 | while (bitsIn < vw) { |
144 | buffer = (buffer << 8) | *(raw++); |
145 | bitsIn += 8; |
146 | } |
147 | bitsIn -= vw; |
148 | *(unpacked++) = (buffer >> bitsIn) & mask; |
149 | } |
150 | } |
151 | |
152 | /*convert y10b (bit-packed array greyscale format) to yuyv (packed) |
153 | * args: |
154 | * framebuffer: pointer to frame buffer (yuyv) |
155 | * tmpbuffer: pointer to temp buffer containing y10b (bit-packed array) data frame |
156 | * width: picture width |
157 | * height: picture height |
158 | */ |
159 | void y10b_to_yuyv (BYTE *framebuffer, BYTE *tmpbuffer, int width, int height) |
160 | { |
161 | UINT16 *unpacked_buffer = NULL; |
162 | UINT16 *ptmp; |
163 | int h = 0; |
164 | int w = 0; |
165 | |
166 | unpacked_buffer = malloc(width * height * sizeof(UINT16)); |
167 | convert_packed_to_16bit(tmpbuffer, unpacked_buffer, 10, width * height); |
168 | |
169 | ptmp = unpacked_buffer; |
170 | |
171 | for (h = 0; h < height; h++) |
172 | { |
173 | for (w = 0; w < width; w += 2) |
174 | { |
175 | /* Y0 */ |
176 | *framebuffer++ = (BYTE) ((ptmp[0] & 0x3FF) >> 2); |
177 | /* U */ |
178 | *framebuffer++ = 0x80; |
179 | /* Y1 */ |
180 | *framebuffer++ = (BYTE) ((ptmp[1] & 0x3FF) >> 2); |
181 | /* V */ |
182 | *framebuffer++ = 0x80; |
183 | |
184 | ptmp += 2; |
185 | } |
186 | } |
187 | |
188 | free(unpacked_buffer); |
189 | } |
190 | |
191 | /*convert y16 (grey) to yuyv (packed) |
192 | * args: |
193 | * framebuffer: pointer to frame buffer (yuyv) |
194 | * tmpbuffer: pointer to temp buffer containing y16 (grey) data frame |
195 | * width: picture width |
196 | * height: picture height |
197 | */ |
198 | void y16_to_yuyv (BYTE *framebuffer, BYTE *tmpbuffer, int width, int height) |
199 | { |
200 | UINT16 *ptmp= (UINT16 *) tmpbuffer; |
201 | |
202 | int h=0; |
203 | int w=0; |
204 | |
205 | for(h=0;h<height;h++) |
206 | { |
207 | for(w=0;w<width;w+=2) |
208 | { |
209 | /* Y0 */ |
210 | *framebuffer++ = (BYTE) ((ptmp[0] & 0xFF00) >> 8); |
211 | /* U */ |
212 | *framebuffer++ = 0x80; |
213 | /* Y1 */ |
214 | *framebuffer++ = (BYTE) ((ptmp[1] & 0xFF00) >> 8); |
215 | /* V */ |
216 | *framebuffer++ = 0x80; |
217 | |
218 | ptmp += 2; |
219 | } |
220 | } |
221 | } |
222 | |
223 | /*convert yyuv (packed) to yuyv (packed) |
224 | * args: |
225 | * framebuffer: pointer to frame buffer (yuyv) |
226 | * tmpbuffer: pointer to temp buffer containing yyuv packed data frame |
227 | * width: picture width |
228 | * height: picture height |
229 | */ |
230 | void yyuv_to_yuyv (BYTE *framebuffer, BYTE *tmpbuffer, int width, int height) |
231 | { |
232 | BYTE *ptmp=NULL; |
233 | BYTE *pfmb=NULL; |
234 | ptmp = tmpbuffer; |
235 | pfmb = framebuffer; |
236 | |
237 | int h=0; |
238 | int w=0; |
239 | |
240 | for(h=0;h<height;h++) |
241 | { |
242 | for(w=0;w<(width*2);w+=4) |
243 | { |
244 | /* Y0 */ |
245 | pfmb[0] = ptmp[0]; |
246 | /* U */ |
247 | pfmb[1] = ptmp[2]; |
248 | /* Y1 */ |
249 | pfmb[2] = ptmp[1]; |
250 | /* V */ |
251 | pfmb[3] = ptmp[3]; |
252 | |
253 | ptmp += 4; |
254 | pfmb += 4; |
255 | } |
256 | } |
257 | } |
258 | |
259 | |
260 | /*convert uyvy (packed) to yuyv (packed) |
261 | * args: |
262 | * framebuffer: pointer to frame buffer (yuyv) |
263 | * tmpbuffer: pointer to temp buffer containing uyvy packed data frame |
264 | * width: picture width |
265 | * height: picture height |
266 | */ |
267 | void uyvy_to_yuyv (BYTE *framebuffer, BYTE *tmpbuffer, int width, int height) |
268 | { |
269 | BYTE *ptmp = tmpbuffer; |
270 | BYTE *pfmb = framebuffer; |
271 | int h=0; |
272 | int w=0; |
273 | |
274 | for(h=0;h<height;h++) |
275 | { |
276 | for(w=0;w<(width*2);w+=4) |
277 | { |
278 | /* Y0 */ |
279 | pfmb[0] = ptmp[1]; |
280 | /* U */ |
281 | pfmb[1] = ptmp[0]; |
282 | /* Y1 */ |
283 | pfmb[2] = ptmp[3]; |
284 | /* V */ |
285 | pfmb[3] = ptmp[2]; |
286 | |
287 | ptmp += 4; |
288 | pfmb += 4; |
289 | } |
290 | } |
291 | } |
292 | |
293 | |
294 | /*convert yvyu (packed) to yuyv (packed) |
295 | * args: |
296 | * framebuffer: pointer to frame buffer (yuyv) |
297 | * tmpbuffer: pointer to temp buffer containing yvyu packed data frame |
298 | * width: picture width |
299 | * height: picture height |
300 | */ |
301 | void yvyu_to_yuyv (BYTE *framebuffer, BYTE *tmpbuffer, int width, int height) |
302 | { |
303 | BYTE *ptmp=NULL; |
304 | BYTE *pfmb=NULL; |
305 | ptmp = tmpbuffer; |
306 | pfmb = framebuffer; |
307 | |
308 | int h=0; |
309 | int w=0; |
310 | |
311 | for(h=0;h<height;h++) |
312 | { |
313 | for(w=0;w<(width*2);w+=4) |
314 | { |
315 | /* Y0 */ |
316 | pfmb[0] = ptmp[0]; |
317 | /* U */ |
318 | pfmb[1] = ptmp[3]; |
319 | /* Y1 */ |
320 | pfmb[2] = ptmp[2]; |
321 | /* V */ |
322 | pfmb[3] = ptmp[1]; |
323 | |
324 | ptmp += 4; |
325 | pfmb += 4; |
326 | } |
327 | } |
328 | } |
329 | |
330 | /*convert yuv 420 planar (yu12) to yuv 422 |
331 | * args: |
332 | * framebuffer: pointer to frame buffer (yuyv) |
333 | * tmpbuffer: pointer to temp buffer containing yuv420 planar data frame |
334 | * width: picture width |
335 | * height: picture height |
336 | */ |
337 | void yuv420_to_yuyv (BYTE *framebuffer, BYTE *tmpbuffer, int width, int height) |
338 | { |
339 | BYTE *py; |
340 | BYTE *pu; |
341 | BYTE *pv; |
342 | |
343 | int linesize = width * 2; |
344 | int uvlinesize = width / 2; |
345 | int offset=0; |
346 | int offset1=0; |
347 | int offsety=0; |
348 | int offsety1=0; |
349 | int offsetuv=0; |
350 | |
351 | py=tmpbuffer; |
352 | pu=py+(width*height); |
353 | pv=pu+(width*height/4); |
354 | |
355 | int h=0; |
356 | int w=0; |
357 | |
358 | int wy=0; |
359 | int huv=0; |
360 | int wuv=0; |
361 | |
362 | for(h=0;h<height;h+=2) |
363 | { |
364 | wy=0; |
365 | wuv=0; |
366 | offset = h * linesize; |
367 | offset1 = (h + 1) * linesize; |
368 | offsety = h * width; |
369 | offsety1 = (h + 1) * width; |
370 | offsetuv = huv * uvlinesize; |
371 | |
372 | for(w=0;w<linesize;w+=4) |
373 | { |
374 | /*y00*/ |
375 | framebuffer[w + offset] = py[wy + offsety]; |
376 | /*u0*/ |
377 | framebuffer[(w + 1) + offset] = pu[wuv + offsetuv]; |
378 | /*y01*/ |
379 | framebuffer[(w + 2) + offset] = py[(wy + 1) + offsety]; |
380 | /*v0*/ |
381 | framebuffer[(w + 3) + offset] = pv[wuv + offsetuv]; |
382 | |
383 | /*y10*/ |
384 | framebuffer[w + offset1] = py[wy + offsety1]; |
385 | /*u0*/ |
386 | framebuffer[(w + 1) + offset1] = pu[wuv + offsetuv]; |
387 | /*y11*/ |
388 | framebuffer[(w + 2) + offset1] = py[(wy + 1) + offsety1]; |
389 | /*v0*/ |
390 | framebuffer[(w + 3) + offset1] = pv[wuv + offsetuv]; |
391 | |
392 | wuv++; |
393 | wy+=2; |
394 | } |
395 | huv++; |
396 | } |
397 | } |
398 | |
399 | /*convert yvu 420 planar (yv12) to yuv 422 |
400 | * args: |
401 | * framebuffer: pointer to frame buffer (yuyv) |
402 | * tmpbuffer: pointer to temp buffer containing yuv420 planar data frame |
403 | * width: picture width |
404 | * height: picture height |
405 | */ |
406 | void yvu420_to_yuyv (BYTE *framebuffer, BYTE *tmpbuffer, int width, int height) |
407 | { |
408 | BYTE *py; |
409 | BYTE *pv; |
410 | BYTE *pu; |
411 | |
412 | int linesize = width * 2; |
413 | int uvlinesize = width / 2; |
414 | int offset=0; |
415 | int offset1=0; |
416 | int offsety=0; |
417 | int offsety1=0; |
418 | int offsetuv=0; |
419 | |
420 | py=tmpbuffer; |
421 | pv=py+(width*height); |
422 | pu=pv+((width*height)/4); |
423 | |
424 | int h=0; |
425 | int w=0; |
426 | |
427 | int wy=0; |
428 | int huv=0; |
429 | int wuv=0; |
430 | |
431 | for(h=0;h<height;h+=2) |
432 | { |
433 | wy=0; |
434 | wuv=0; |
435 | offset = h * linesize; |
436 | offset1 = (h + 1) * linesize; |
437 | offsety = h * width; |
438 | offsety1 = (h + 1) * width; |
439 | offsetuv = huv * uvlinesize; |
440 | |
441 | for(w=0;w<linesize;w+=4) |
442 | { |
443 | /*y00*/ |
444 | framebuffer[w + offset] = py[wy + offsety]; |
445 | /*u0*/ |
446 | framebuffer[(w + 1) + offset] = pu[wuv + offsetuv]; |
447 | /*y01*/ |
448 | framebuffer[(w + 2) + offset] = py[(wy + 1) + offsety]; |
449 | /*v0*/ |
450 | framebuffer[(w + 3) + offset] = pv[wuv + offsetuv]; |
451 | |
452 | /*y10*/ |
453 | framebuffer[w + offset1] = py[wy + offsety1]; |
454 | /*u0*/ |
455 | framebuffer[(w + 1) + offset1] = pu[wuv + offsetuv]; |
456 | /*y11*/ |
457 | framebuffer[(w + 2) + offset1] = py[(wy + 1) + offsety1]; |
458 | /*v0*/ |
459 | framebuffer[(w + 3) + offset1] = pv[wuv + offsetuv]; |
460 | |
461 | wuv++; |
462 | wy+=2; |
463 | } |
464 | huv++; |
465 | } |
466 | } |
467 | |
468 | /*convert yuv 420 planar (uv interleaved) (nv12) to yuv 422 |
469 | * args: |
470 | * framebuffer: pointer to frame buffer (yuyv) |
471 | * tmpbuffer: pointer to temp buffer containing yuv420 (nv12) planar data frame |
472 | * width: picture width |
473 | * height: picture height |
474 | */ |
475 | void nv12_to_yuyv (BYTE *framebuffer, BYTE *tmpbuffer, int width, int height) |
476 | { |
477 | BYTE *py; |
478 | BYTE *puv; |
479 | |
480 | int linesize = width * 2; |
481 | int offset=0; |
482 | int offset1=0; |
483 | int offsety=0; |
484 | int offsety1=0; |
485 | int offsetuv=0; |
486 | |
487 | py=tmpbuffer; |
488 | puv=py+(width*height); |
489 | |
490 | int h=0; |
491 | int w=0; |
492 | |
493 | int wy=0; |
494 | int huv=0; |
495 | int wuv=0; |
496 | |
497 | for(h=0;h<height;h+=2) |
498 | { |
499 | wy=0; |
500 | wuv=0; |
501 | offset = h * linesize; |
502 | offset1 = (h+1) * linesize; |
503 | offsety = h * width; |
504 | offsety1 = (h+1) * width; |
505 | offsetuv = huv * width; |
506 | for(w=0;w<linesize;w+=4) |
507 | { |
508 | /*y00*/ |
509 | framebuffer[w + offset] = py[wy + offsety]; |
510 | /*u0*/ |
511 | framebuffer[(w + 1) + offset] = puv[wuv + offsetuv]; |
512 | /*y01*/ |
513 | framebuffer[(w + 2) + offset] = py[(wy + 1) + offsety]; |
514 | /*v0*/ |
515 | framebuffer[(w + 3) + offset] = puv[(wuv + 1) + offsetuv]; |
516 | |
517 | /*y10*/ |
518 | framebuffer[w + offset1] = py[wy + offsety1]; |
519 | /*u0*/ |
520 | framebuffer[(w + 1) + offset1] = puv[wuv + offsetuv]; |
521 | /*y11*/ |
522 | framebuffer[(w + 2) + offset1] = py[(wy + 1) + offsety1]; |
523 | /*v0*/ |
524 | framebuffer[(w + 3) + offset1] = puv[(wuv + 1) + offsetuv]; |
525 | |
526 | wuv+=2; |
527 | wy+=2; |
528 | } |
529 | huv++; |
530 | } |
531 | } |
532 | |
533 | /*convert yuv 420 planar (vu interleaved) (nv21) to yuv 422 |
534 | * args: |
535 | * framebuffer: pointer to frame buffer (yuyv) |
536 | * tmpbuffer: pointer to temp buffer containing yuv420 (nv21) planar data frame |
537 | * width: picture width |
538 | * height: picture height |
539 | */ |
540 | void nv21_to_yuyv (BYTE *framebuffer, BYTE *tmpbuffer, int width, int height) |
541 | { |
542 | BYTE *py; |
543 | BYTE *puv; |
544 | |
545 | int linesize = width * 2; |
546 | int offset=0; |
547 | int offset1=0; |
548 | int offsety=0; |
549 | int offsety1=0; |
550 | int offsetuv=0; |
551 | |
552 | py=tmpbuffer; |
553 | puv=py+(width*height); |
554 | |
555 | int h=0; |
556 | int w=0; |
557 | |
558 | int wy=0; |
559 | int huv=0; |
560 | int wuv=0; |
561 | |
562 | for(h=0;h<height;h+=2) |
563 | { |
564 | wy=0; |
565 | wuv=0; |
566 | offset = h * linesize; |
567 | offset1 = (h+1) * linesize; |
568 | offsety = h * width; |
569 | offsety1 = (h+1) * width; |
570 | offsetuv = huv * width; |
571 | for(w=0;w<linesize;w+=4) |
572 | { |
573 | /*y00*/ |
574 | framebuffer[w + offset] = py[wy + offsety]; |
575 | /*u0*/ |
576 | framebuffer[(w + 1) + offset] = puv[(wuv + 1) + offsetuv]; |
577 | /*y01*/ |
578 | framebuffer[(w + 2) + offset] = py[(wy + 1) + offsety]; |
579 | /*v0*/ |
580 | framebuffer[(w + 3) + offset] = puv[wuv + offsetuv]; |
581 | |
582 | /*y10*/ |
583 | framebuffer[w + offset1] = py[wy + offsety1]; |
584 | /*u0*/ |
585 | framebuffer[(w + 1) + offset1] = puv[(wuv + 1) + offsetuv]; |
586 | /*y11*/ |
587 | framebuffer[(w + 2) + offset1] = py[(wy + 1) + offsety1]; |
588 | /*v0*/ |
589 | framebuffer[(w + 3) + offset1] = puv[wuv + offsetuv]; |
590 | |
591 | wuv+=2; |
592 | wy+=2; |
593 | } |
594 | huv++; |
595 | } |
596 | } |
597 | |
598 | /*convert yuv 422 planar (uv interleaved) (nv16) to yuv 422 |
599 | * args: |
600 | * framebuffer: pointer to frame buffer (yuyv) |
601 | * tmpbuffer: pointer to temp buffer containing yuv422 (nv16) planar data frame |
602 | * width: picture width |
603 | * height: picture height |
604 | */ |
605 | void nv16_to_yuyv (BYTE *framebuffer, BYTE *tmpbuffer, int width, int height) |
606 | { |
607 | BYTE *py; |
608 | BYTE *puv; |
609 | |
610 | int linesize = width * 2; |
611 | int offset=0; |
612 | int offsety=0; |
613 | int offsetuv=0; |
614 | |
615 | py=tmpbuffer; |
616 | puv=py+(width*height); |
617 | |
618 | int h=0; |
619 | int w=0; |
620 | |
621 | int wy=0; |
622 | int huv=0; |
623 | int wuv=0; |
624 | |
625 | for(h=0;h<height;h++) |
626 | { |
627 | wy=0; |
628 | wuv=0; |
629 | offset = h * linesize; |
630 | offsety = h * width; |
631 | offsetuv = huv * width; |
632 | for(w=0;w<linesize;w+=4) |
633 | { |
634 | /*y00*/ |
635 | framebuffer[w + offset] = py[wy + offsety]; |
636 | /*u0*/ |
637 | framebuffer[(w + 1) + offset] = puv[wuv + offsetuv]; |
638 | /*y01*/ |
639 | framebuffer[(w + 2) + offset] = py[(wy + 1) + offsety]; |
640 | /*v0*/ |
641 | framebuffer[(w + 3) + offset] = puv[(wuv + 1) + offsetuv]; |
642 | |
643 | wuv+=2; |
644 | wy+=2; |
645 | } |
646 | huv++; |
647 | } |
648 | } |
649 | |
650 | /*convert yuv 422 planar (vu interleaved) (nv61) to yuv 422 |
651 | * args: |
652 | * framebuffer: pointer to frame buffer (yuyv) |
653 | * tmpbuffer: pointer to temp buffer containing yuv422 (nv61) planar data frame |
654 | * width: picture width |
655 | * height: picture height |
656 | */ |
657 | void nv61_to_yuyv (BYTE *framebuffer, BYTE *tmpbuffer, int width, int height) |
658 | { |
659 | BYTE *py; |
660 | BYTE *puv; |
661 | |
662 | int linesize = width * 2; |
663 | int offset=0; |
664 | int offsety=0; |
665 | int offsetuv=0; |
666 | |
667 | py=tmpbuffer; |
668 | puv=py+(width*height); |
669 | |
670 | int h=0; |
671 | int w=0; |
672 | |
673 | int wy=0; |
674 | int huv=0; |
675 | int wuv=0; |
676 | |
677 | for(h=0;h<height;h++) |
678 | { |
679 | wy=0; |
680 | wuv=0; |
681 | offset = h * linesize; |
682 | offsety = h * width; |
683 | offsetuv = huv * width; |
684 | for(w=0;w<linesize;w+=4) |
685 | { |
686 | /*y00*/ |
687 | framebuffer[w + offset] = py[wy + offsety]; |
688 | /*u0*/ |
689 | framebuffer[(w + 1) + offset] = puv[(wuv + 1) + offsetuv]; |
690 | /*y01*/ |
691 | framebuffer[(w + 2) + offset] = py[(wy + 1) + offsety]; |
692 | /*v0*/ |
693 | framebuffer[(w + 3) + offset] = puv[wuv + offsetuv]; |
694 | |
695 | wuv+=2; |
696 | wy+=2; |
697 | } |
698 | huv++; |
699 | } |
700 | } |
701 | |
702 | /*convert yuv 411 packed (y41p) to yuv 422 |
703 | * args: |
704 | * framebuffer: pointer to frame buffer (yuyv) |
705 | * tmpbuffer: pointer to temp buffer containing y41p data frame |
706 | * width: picture width |
707 | * height: picture height |
708 | */ |
709 | void y41p_to_yuyv (BYTE *framebuffer, BYTE *tmpbuffer, int width, int height) |
710 | { |
711 | int h=0; |
712 | int w=0; |
713 | int linesize = width * 3 /2; |
714 | int offset = 0; |
715 | |
716 | for(h=0;h<height;h++) |
717 | { |
718 | offset = linesize * h; |
719 | for(w=0;w<linesize;w+=12) |
720 | { |
721 | *framebuffer++=tmpbuffer[w+1 + offset]; //Y0 |
722 | *framebuffer++=tmpbuffer[w + offset]; //U0 |
723 | *framebuffer++=tmpbuffer[w+3 + offset]; //Y1 |
724 | *framebuffer++=tmpbuffer[w+2 + offset]; //V0 |
725 | *framebuffer++=tmpbuffer[w+5 + offset]; //Y2 |
726 | *framebuffer++=tmpbuffer[w + offset]; //U0 |
727 | *framebuffer++=tmpbuffer[w+7 + offset]; //Y3 |
728 | *framebuffer++=tmpbuffer[w+2 + offset]; //V0 |
729 | *framebuffer++=tmpbuffer[w+8 + offset]; //Y4 |
730 | *framebuffer++=tmpbuffer[w+4 + offset]; //U4 |
731 | *framebuffer++=tmpbuffer[w+9 + offset]; //Y5 |
732 | *framebuffer++=tmpbuffer[w+6 + offset]; //V4 |
733 | *framebuffer++=tmpbuffer[w+10+ offset]; //Y6 |
734 | *framebuffer++=tmpbuffer[w+4 + offset]; //U4 |
735 | *framebuffer++=tmpbuffer[w+11+ offset]; //Y7 |
736 | *framebuffer++=tmpbuffer[w+6 + offset]; //V4 |
737 | } |
738 | } |
739 | } |
740 | |
741 | /*convert yuv mono (grey) to yuv 422 |
742 | * args: |
743 | * framebuffer: pointer to frame buffer (yuyv) |
744 | * tmpbuffer: pointer to temp buffer containing grey (y only) data frame |
745 | * width: picture width |
746 | * height: picture height |
747 | */ |
748 | void grey_to_yuyv (BYTE *framebuffer, BYTE *tmpbuffer, int width, int height) |
749 | { |
750 | int h=0; |
751 | int w=0; |
752 | int offset = 0; |
753 | |
754 | for(h=0;h<height;h++) |
755 | { |
756 | offset = width * h; |
757 | for(w=0;w<width;w++) |
758 | { |
759 | *framebuffer++=tmpbuffer[w + offset]; //Y |
760 | *framebuffer++=0x80; //U or V |
761 | } |
762 | } |
763 | } |
764 | |
765 | /*convert SPCA501 (s501) to yuv 422 |
766 | * s501 |Y0..width..Y0|U..width/2..U|Y1..width..Y1|V..width/2..V| |
767 | * signed values (-128;+127) must be converted to unsigned (0; 255) |
768 | * args: |
769 | * framebuffer: pointer to frame buffer (yuyv) |
770 | * tmpbuffer: pointer to temp buffer containing s501 data frame |
771 | * width: picture width |
772 | * height: picture height |
773 | */ |
774 | void s501_to_yuyv(BYTE *framebuffer, BYTE *tmpbuffer, int width, int height) |
775 | { |
776 | BYTE *U, *V, *Y0, *Y1; |
777 | BYTE *line2; |
778 | int h, w; |
779 | |
780 | Y0 = tmpbuffer; /*fisrt line*/ |
781 | for (h = 0; h < height/2; h++ ) |
782 | { |
783 | line2 = framebuffer + width * 2; /* next line */ |
784 | U = Y0 + width; |
785 | Y1 = U + width / 2; |
786 | V = Y1 + width; |
787 | for (w = width / 2; --w >= 0; ) |
788 | { |
789 | *framebuffer++ = 0x80 + *Y0++; |
790 | *framebuffer++ = 0x80 + *U; |
791 | *framebuffer++ = 0x80 + *Y0++; |
792 | *framebuffer++ = 0x80 + *V; |
793 | |
794 | *line2++ = 0x80 + *Y1++; |
795 | *line2++ = 0x80 + *U++; |
796 | *line2++ = 0x80 + *Y1++; |
797 | *line2++ = 0x80 + *V++; |
798 | } |
799 | Y0 += width * 2; /* next block of lines */ |
800 | framebuffer = line2; |
801 | } |
802 | } |
803 | |
804 | /*convert SPCA505 (s505) to yuv 422 |
805 | * s505 |Y0..width..Y0|Y1..width..Y1|U..width/2..U|V..width/2..V| |
806 | * signed values (-128;+127) must be converted to unsigned (0; 255) |
807 | * args: |
808 | * framebuffer: pointer to frame buffer (yuyv) |
809 | * tmpbuffer: pointer to temp buffer containing s501 data frame |
810 | * width: picture width |
811 | * height: picture height |
812 | */ |
813 | void s505_to_yuyv(BYTE *framebuffer, BYTE *tmpbuffer, int width, int height) |
814 | { |
815 | BYTE *U, *V, *Y0, *Y1; |
816 | BYTE *line2; |
817 | int h, w; |
818 | |
819 | Y0 = tmpbuffer; /*fisrt line*/ |
820 | for (h = 0; h < height/2; h++ ) |
821 | { |
822 | line2 = framebuffer + width * 2; /* next line */ |
823 | Y1 = Y0 + width; |
824 | U = Y1 + width; |
825 | V = U + width/2; |
826 | for (w = width / 2; --w >= 0; ) |
827 | { |
828 | *framebuffer++ = 0x80 + *Y0++; |
829 | *framebuffer++ = 0x80 + *U; |
830 | *framebuffer++ = 0x80 + *Y0++; |
831 | *framebuffer++ = 0x80 + *V; |
832 | |
833 | *line2++ = 0x80 + *Y1++; |
834 | *line2++ = 0x80 + *U++; |
835 | *line2++ = 0x80 + *Y1++; |
836 | *line2++ = 0x80 + *V++; |
837 | } |
838 | Y0 += width * 2; /* next block of lines */ |
839 | framebuffer = line2; |
840 | } |
841 | } |
842 | |
843 | /*convert SPCA508 (s508) to yuv 422 |
844 | * s508 |Y0..width..Y0|U..width/2..U|V..width/2..V|Y1..width..Y1| |
845 | * signed values (-128;+127) must be converted to unsigned (0; 255) |
846 | * args: |
847 | * framebuffer: pointer to frame buffer (yuyv) |
848 | * tmpbuffer: pointer to temp buffer containing s501 data frame |
849 | * width: picture width |
850 | * height: picture height |
851 | */ |
852 | void s508_to_yuyv(BYTE *framebuffer, BYTE *tmpbuffer, int width, int height) |
853 | { |
854 | BYTE *U, *V, *Y0, *Y1; |
855 | BYTE *line2; |
856 | int h, w; |
857 | |
858 | Y0 = tmpbuffer; /*fisrt line*/ |
859 | for (h = 0; h < height/2; h++ ) |
860 | { |
861 | line2 = framebuffer + width * 2; /* next line */ |
862 | U = Y0 + width; |
863 | V = U + width/2; |
864 | Y1= V + width/2; |
865 | for (w = width / 2; --w >= 0; ) |
866 | { |
867 | *framebuffer++ = 0x80 + *Y0++; |
868 | *framebuffer++ = 0x80 + *U; |
869 | *framebuffer++ = 0x80 + *Y0++; |
870 | *framebuffer++ = 0x80 + *V; |
871 | |
872 | *line2++ = 0x80 + *Y1++; |
873 | *line2++ = 0x80 + *U++; |
874 | *line2++ = 0x80 + *Y1++; |
875 | *line2++ = 0x80 + *V++; |
876 | } |
877 | Y0 += width * 2; /* next block of lines */ |
878 | framebuffer = line2; |
879 | } |
880 | } |
881 | |
882 | // raw bayer functions |
883 | // from libv4l bayer.c, (C) 2008 Hans de Goede <j.w.r.degoede@hhs.nl> |
884 | //Note: original bayer_to_bgr24 code from : |
885 | // 1394-Based Digital Camera Control Library |
886 | // |
887 | // Bayer pattern decoding functions |
888 | // |
889 | // Written by Damien Douxchamps and Frederic Devernay |
890 | static void convert_border_bayer_line_to_bgr24( BYTE* bayer, BYTE* adjacent_bayer, |
891 | BYTE *bgr, int width, bool start_with_green, bool blue_line) |
892 | { |
893 | int t0, t1; |
894 | |
895 | if (start_with_green) |
896 | { |
897 | /* First pixel */ |
898 | if (blue_line) |
899 | { |
900 | *bgr++ = bayer[1]; |
901 | *bgr++ = bayer[0]; |
902 | *bgr++ = adjacent_bayer[0]; |
903 | } |
904 | else |
905 | { |
906 | *bgr++ = adjacent_bayer[0]; |
907 | *bgr++ = bayer[0]; |
908 | *bgr++ = bayer[1]; |
909 | } |
910 | /* Second pixel */ |
911 | t0 = (bayer[0] + bayer[2] + adjacent_bayer[1] + 1) / 3; |
912 | t1 = (adjacent_bayer[0] + adjacent_bayer[2] + 1) >> 1; |
913 | if (blue_line) |
914 | { |
915 | *bgr++ = bayer[1]; |
916 | *bgr++ = t0; |
917 | *bgr++ = t1; |
918 | } |
919 | else |
920 | { |
921 | *bgr++ = t1; |
922 | *bgr++ = t0; |
923 | *bgr++ = bayer[1]; |
924 | } |
925 | bayer++; |
926 | adjacent_bayer++; |
927 | width -= 2; |
928 | } |
929 | else |
930 | { |
931 | /* First pixel */ |
932 | t0 = (bayer[1] + adjacent_bayer[0] + 1) >> 1; |
933 | if (blue_line) |
934 | { |
935 | *bgr++ = bayer[0]; |
936 | *bgr++ = t0; |
937 | *bgr++ = adjacent_bayer[1]; |
938 | } |
939 | else |
940 | { |
941 | *bgr++ = adjacent_bayer[1]; |
942 | *bgr++ = t0; |
943 | *bgr++ = bayer[0]; |
944 | } |
945 | width--; |
946 | } |
947 | |
948 | if (blue_line) |
949 | { |
950 | for ( ; width > 2; width -= 2) |
951 | { |
952 | t0 = (bayer[0] + bayer[2] + 1) >> 1; |
953 | *bgr++ = t0; |
954 | *bgr++ = bayer[1]; |
955 | *bgr++ = adjacent_bayer[1]; |
956 | bayer++; |
957 | adjacent_bayer++; |
958 | |
959 | t0 = (bayer[0] + bayer[2] + adjacent_bayer[1] + 1) / 3; |
960 | t1 = (adjacent_bayer[0] + adjacent_bayer[2] + 1) >> 1; |
961 | *bgr++ = bayer[1]; |
962 | *bgr++ = t0; |
963 | *bgr++ = t1; |
964 | bayer++; |
965 | adjacent_bayer++; |
966 | } |
967 | } |
968 | else |
969 | { |
970 | for ( ; width > 2; width -= 2) |
971 | { |
972 | t0 = (bayer[0] + bayer[2] + 1) >> 1; |
973 | *bgr++ = adjacent_bayer[1]; |
974 | *bgr++ = bayer[1]; |
975 | *bgr++ = t0; |
976 | bayer++; |
977 | adjacent_bayer++; |
978 | |
979 | t0 = (bayer[0] + bayer[2] + adjacent_bayer[1] + 1) / 3; |
980 | t1 = (adjacent_bayer[0] + adjacent_bayer[2] + 1) >> 1; |
981 | *bgr++ = t1; |
982 | *bgr++ = t0; |
983 | *bgr++ = bayer[1]; |
984 | bayer++; |
985 | adjacent_bayer++; |
986 | } |
987 | } |
988 | |
989 | if (width == 2) |
990 | { |
991 | /* Second to last pixel */ |
992 | t0 = (bayer[0] + bayer[2] + 1) >> 1; |
993 | if (blue_line) |
994 | { |
995 | *bgr++ = t0; |
996 | *bgr++ = bayer[1]; |
997 | *bgr++ = adjacent_bayer[1]; |
998 | } |
999 | else |
1000 | { |
1001 | *bgr++ = adjacent_bayer[1]; |
1002 | *bgr++ = bayer[1]; |
1003 | *bgr++ = t0; |
1004 | } |
1005 | /* Last pixel */ |
1006 | t0 = (bayer[1] + adjacent_bayer[2] + 1) >> 1; |
1007 | if (blue_line) |
1008 | { |
1009 | *bgr++ = bayer[2]; |
1010 | *bgr++ = t0; |
1011 | *bgr++ = adjacent_bayer[1]; |
1012 | } |
1013 | else |
1014 | { |
1015 | *bgr++ = adjacent_bayer[1]; |
1016 | *bgr++ = t0; |
1017 | *bgr++ = bayer[2]; |
1018 | } |
1019 | } |
1020 | else |
1021 | { |
1022 | /* Last pixel */ |
1023 | if (blue_line) |
1024 | { |
1025 | *bgr++ = bayer[0]; |
1026 | *bgr++ = bayer[1]; |
1027 | *bgr++ = adjacent_bayer[1]; |
1028 | } |
1029 | else |
1030 | { |
1031 | *bgr++ = adjacent_bayer[1]; |
1032 | *bgr++ = bayer[1]; |
1033 | *bgr++ = bayer[0]; |
1034 | } |
1035 | } |
1036 | } |
1037 | |
1038 | /* From libdc1394, which on turn was based on OpenCV's Bayer decoding */ |
1039 | static void bayer_to_rgbbgr24(BYTE *bayer, |
1040 | BYTE *bgr, int width, int height, |
1041 | bool start_with_green, bool blue_line) |
1042 | { |
1043 | /* render the first line */ |
1044 | convert_border_bayer_line_to_bgr24(bayer, bayer + width, bgr, width, |
1045 | start_with_green, blue_line); |
1046 | bgr += width * 3; |
1047 | |
1048 | /* reduce height by 2 because of the special case top/bottom line */ |
1049 | for (height -= 2; height; height--) |
1050 | { |
1051 | int t0, t1; |
1052 | /* (width - 2) because of the border */ |
1053 | BYTE *bayerEnd = bayer + (width - 2); |
1054 | |
1055 | if (start_with_green) |
1056 | { |
1057 | /* OpenCV has a bug in the next line, which was |
1058 | t0 = (bayer[0] + bayer[width * 2] + 1) >> 1; */ |
1059 | t0 = (bayer[1] + bayer[width * 2 + 1] + 1) >> 1; |
1060 | /* Write first pixel */ |
1061 | t1 = (bayer[0] + bayer[width * 2] + bayer[width + 1] + 1) / 3; |
1062 | if (blue_line) |
1063 | { |
1064 | *bgr++ = t0; |
1065 | *bgr++ = t1; |
1066 | *bgr++ = bayer[width]; |
1067 | } |
1068 | else |
1069 | { |
1070 | *bgr++ = bayer[width]; |
1071 | *bgr++ = t1; |
1072 | *bgr++ = t0; |
1073 | } |
1074 | |
1075 | /* Write second pixel */ |
1076 | t1 = (bayer[width] + bayer[width + 2] + 1) >> 1; |
1077 | if (blue_line) |
1078 | { |
1079 | *bgr++ = t0; |
1080 | *bgr++ = bayer[width + 1]; |
1081 | *bgr++ = t1; |
1082 | } |
1083 | else |
1084 | { |
1085 | *bgr++ = t1; |
1086 | *bgr++ = bayer[width + 1]; |
1087 | *bgr++ = t0; |
1088 | } |
1089 | bayer++; |
1090 | } |
1091 | else |
1092 | { |
1093 | /* Write first pixel */ |
1094 | t0 = (bayer[0] + bayer[width * 2] + 1) >> 1; |
1095 | if (blue_line) |
1096 | { |
1097 | *bgr++ = t0; |
1098 | *bgr++ = bayer[width]; |
1099 | *bgr++ = bayer[width + 1]; |
1100 | } |
1101 | else |
1102 | { |
1103 | *bgr++ = bayer[width + 1]; |
1104 | *bgr++ = bayer[width]; |
1105 | *bgr++ = t0; |
1106 | } |
1107 | } |
1108 | |
1109 | if (blue_line) |
1110 | { |
1111 | for (; bayer <= bayerEnd - 2; bayer += 2) |
1112 | { |
1113 | t0 = (bayer[0] + bayer[2] + bayer[width * 2] + |
1114 | bayer[width * 2 + 2] + 2) >> 2; |
1115 | t1 = (bayer[1] + bayer[width] + |
1116 | bayer[width + 2] + bayer[width * 2 + 1] + |
1117 | 2) >> 2; |
1118 | *bgr++ = t0; |
1119 | *bgr++ = t1; |
1120 | *bgr++ = bayer[width + 1]; |
1121 | |
1122 | t0 = (bayer[2] + bayer[width * 2 + 2] + 1) >> 1; |
1123 | t1 = (bayer[width + 1] + bayer[width + 3] + |
1124 | 1) >> 1; |
1125 | *bgr++ = t0; |
1126 | *bgr++ = bayer[width + 2]; |
1127 | *bgr++ = t1; |
1128 | } |
1129 | } |
1130 | else |
1131 | { |
1132 | for (; bayer <= bayerEnd - 2; bayer += 2) |
1133 | { |
1134 | t0 = (bayer[0] + bayer[2] + bayer[width * 2] + |
1135 | bayer[width * 2 + 2] + 2) >> 2; |
1136 | t1 = (bayer[1] + bayer[width] + |
1137 | bayer[width + 2] + bayer[width * 2 + 1] + |
1138 | 2) >> 2; |
1139 | *bgr++ = bayer[width + 1]; |
1140 | *bgr++ = t1; |
1141 | *bgr++ = t0; |
1142 | |
1143 | t0 = (bayer[2] + bayer[width * 2 + 2] + 1) >> 1; |
1144 | t1 = (bayer[width + 1] + bayer[width + 3] + |
1145 | 1) >> 1; |
1146 | *bgr++ = t1; |
1147 | *bgr++ = bayer[width + 2]; |
1148 | *bgr++ = t0; |
1149 | } |
1150 | } |
1151 | |
1152 | if (bayer < bayerEnd) |
1153 | { |
1154 | /* write second to last pixel */ |
1155 | t0 = (bayer[0] + bayer[2] + bayer[width * 2] + |
1156 | bayer[width * 2 + 2] + 2) >> 2; |
1157 | t1 = (bayer[1] + bayer[width] + |
1158 | bayer[width + 2] + bayer[width * 2 + 1] + |
1159 | 2) >> 2; |
1160 | if (blue_line) |
1161 | { |
1162 | *bgr++ = t0; |
1163 | *bgr++ = t1; |
1164 | *bgr++ = bayer[width + 1]; |
1165 | } |
1166 | else |
1167 | { |
1168 | *bgr++ = bayer[width + 1]; |
1169 | *bgr++ = t1; |
1170 | *bgr++ = t0; |
1171 | } |
1172 | /* write last pixel */ |
1173 | t0 = (bayer[2] + bayer[width * 2 + 2] + 1) >> 1; |
1174 | if (blue_line) |
1175 | { |
1176 | *bgr++ = t0; |
1177 | *bgr++ = bayer[width + 2]; |
1178 | *bgr++ = bayer[width + 1]; |
1179 | } |
1180 | else |
1181 | { |
1182 | *bgr++ = bayer[width + 1]; |
1183 | *bgr++ = bayer[width + 2]; |
1184 | *bgr++ = t0; |
1185 | } |
1186 | bayer++; |
1187 | } |
1188 | else |
1189 | { |
1190 | /* write last pixel */ |
1191 | t0 = (bayer[0] + bayer[width * 2] + 1) >> 1; |
1192 | t1 = (bayer[1] + bayer[width * 2 + 1] + bayer[width] + 1) / 3; |
1193 | if (blue_line) |
1194 | { |
1195 | *bgr++ = t0; |
1196 | *bgr++ = t1; |
1197 | *bgr++ = bayer[width + 1]; |
1198 | } |
1199 | else |
1200 | { |
1201 | *bgr++ = bayer[width + 1]; |
1202 | *bgr++ = t1; |
1203 | *bgr++ = t0; |
1204 | } |
1205 | } |
1206 | |
1207 | /* skip 2 border pixels */ |
1208 | bayer += 2; |
1209 | |
1210 | blue_line = !blue_line; |
1211 | start_with_green = !start_with_green; |
1212 | } |
1213 | |
1214 | /* render the last line */ |
1215 | convert_border_bayer_line_to_bgr24(bayer + width, bayer, bgr, width, |
1216 | !start_with_green, !blue_line); |
1217 | } |
1218 | |
1219 | /*convert bayer raw data to rgb24 |
1220 | * args: |
1221 | * pBay: pointer to buffer containing Raw bayer data data |
1222 | * pRGB24: pointer to buffer containing rgb24 data |
1223 | * width: picture width |
1224 | * height: picture height |
1225 | * pix_order: bayer pixel order (0=gb/rg 1=gr/bg 2=bg/gr 3=rg/bg) |
1226 | */ |
1227 | void |
1228 | bayer_to_rgb24(BYTE *pBay, BYTE *pRGB24, int width, int height, int pix_order) |
1229 | { |
1230 | switch (pix_order) |
1231 | { |
1232 | //conversion functions are build for bgr, by switching b and r lines we get rgb |
1233 | case 0: /* gbgbgb... | rgrgrg... (V4L2_PIX_FMT_SGBRG8)*/ |
1234 | bayer_to_rgbbgr24(pBay, pRGB24, width, height, TRUE, FALSE); |
1235 | break; |
1236 | |
1237 | case 1: /* grgrgr... | bgbgbg... (V4L2_PIX_FMT_SGRBG8)*/ |
1238 | bayer_to_rgbbgr24(pBay, pRGB24, width, height, TRUE, TRUE); |
1239 | break; |
1240 | |
1241 | case 2: /* bgbgbg... | grgrgr... (V4L2_PIX_FMT_SBGGR8)*/ |
1242 | bayer_to_rgbbgr24(pBay, pRGB24, width, height, FALSE, FALSE); |
1243 | break; |
1244 | |
1245 | case 3: /* rgrgrg... ! gbgbgb... (V4L2_PIX_FMT_SRGGB8)*/ |
1246 | bayer_to_rgbbgr24(pBay, pRGB24, width, height, FALSE, TRUE); |
1247 | break; |
1248 | |
1249 | default: /* default is 0*/ |
1250 | bayer_to_rgbbgr24(pBay, pRGB24, width, height, TRUE, FALSE); |
1251 | break; |
1252 | } |
1253 | } |
1254 | |
1255 | |
1256 | void |
1257 | rgb2yuyv(BYTE *prgb, BYTE *pyuv, int width, int height) |
1258 | { |
1259 | |
1260 | int i=0; |
1261 | for(i=0;i<(width*height*3);i=i+6) |
1262 | { |
1263 | /* y */ |
1264 | *pyuv++ =CLIP(0.299 * (prgb[i] - 128) + 0.587 * (prgb[i+1] - 128) + 0.114 * (prgb[i+2] - 128) + 128); |
1265 | /* u */ |
1266 | *pyuv++ =CLIP(((- 0.147 * (prgb[i] - 128) - 0.289 * (prgb[i+1] - 128) + 0.436 * (prgb[i+2] - 128) + 128) + |
1267 | (- 0.147 * (prgb[i+3] - 128) - 0.289 * (prgb[i+4] - 128) + 0.436 * (prgb[i+5] - 128) + 128))/2); |
1268 | /* y1 */ |
1269 | *pyuv++ =CLIP(0.299 * (prgb[i+3] - 128) + 0.587 * (prgb[i+4] - 128) + 0.114 * (prgb[i+5] - 128) + 128); |
1270 | /* v*/ |
1271 | *pyuv++ =CLIP(((0.615 * (prgb[i] - 128) - 0.515 * (prgb[i+1] - 128) - 0.100 * (prgb[i+2] - 128) + 128) + |
1272 | (0.615 * (prgb[i+3] - 128) - 0.515 * (prgb[i+4] - 128) - 0.100 * (prgb[i+5] - 128) + 128))/2); |
1273 | } |
1274 | } |
1275 | |
1276 | void |
1277 | bgr2yuyv(BYTE *pbgr, BYTE *pyuv, int width, int height) |
1278 | { |
1279 | |
1280 | int i=0; |
1281 | for(i=0;i<(width*height*3);i=i+6) |
1282 | { |
1283 | /* y */ |
1284 | *pyuv++ =CLIP(0.299 * (pbgr[i+2] - 128) + 0.587 * (pbgr[i+1] - 128) + 0.114 * (pbgr[i] - 128) + 128); |
1285 | /* u */ |
1286 | *pyuv++ =CLIP(((- 0.147 * (pbgr[i+2] - 128) - 0.289 * (pbgr[i+1] - 128) + 0.436 * (pbgr[i] - 128) + 128) + |
1287 | (- 0.147 * (pbgr[i+5] - 128) - 0.289 * (pbgr[i+4] - 128) + 0.436 * (pbgr[i+3] - 128) + 128))/2); |
1288 | /* y1 */ |
1289 | *pyuv++ =CLIP(0.299 * (pbgr[i+5] - 128) + 0.587 * (pbgr[i+4] - 128) + 0.114 * (pbgr[i+3] - 128) + 128); |
1290 | /* v*/ |
1291 | *pyuv++ =CLIP(((0.615 * (pbgr[i+2] - 128) - 0.515 * (pbgr[i+1] - 128) - 0.100 * (pbgr[i] - 128) + 128) + |
1292 | (0.615 * (pbgr[i+5] - 128) - 0.515 * (pbgr[i+4] - 128) - 0.100 * (pbgr[i+3] - 128) + 128))/2); |
1293 | } |
1294 | } |
1295 | |
1296 | /*use in utils.c for jpeg decoding 420 planar to 422 |
1297 | * args: |
1298 | * out: pointer to data output of idct (macroblocks yyyy u v) |
1299 | * pic: pointer to picture buffer (yuyv) |
1300 | * width: picture width |
1301 | */ |
1302 | void yuv420pto422(int * out,unsigned char *pic,int width) |
1303 | { |
1304 | int j, k; |
1305 | unsigned char *pic0, *pic1; |
1306 | int *outy, *outu, *outv; |
1307 | int outy1 = 0; |
1308 | int outy2 = 8; |
1309 | |
1310 | //yyyyuv |
1311 | pic0 = pic; |
1312 | pic1 = pic + width; |
1313 | outy = out; |
1314 | outu = out + 64 * 4; |
1315 | outv = out + 64 * 5; |
1316 | for (j = 0; j < 8; j++) |
1317 | { |
1318 | for (k = 0; k < 8; k++) |
1319 | { |
1320 | if( k == 4) |
1321 | { |
1322 | outy1 += 56; |
1323 | outy2 += 56; |
1324 | } |
1325 | *pic0++ = CLIP(outy[outy1]); //y1 line 1 |
1326 | *pic0++ = CLIP(128 + *outu); //u line 1-2 |
1327 | *pic0++ = CLIP(outy[outy1+1]); //y2 line 1 |
1328 | *pic0++ = CLIP(128 + *outv); //v line 1-2 |
1329 | *pic1++ = CLIP(outy[outy2]); //y1 line 2 |
1330 | *pic1++ = CLIP(128 + *outu); //u line 1-2 |
1331 | *pic1++ = CLIP(outy[outy2+1]); //y2 line 2 |
1332 | *pic1++ = CLIP(128 + *outv); //v line 1-2 |
1333 | outy1 +=2; outy2 += 2; outu++; outv++; |
1334 | } |
1335 | if(j==3) |
1336 | { |
1337 | outy = out + 128; |
1338 | } |
1339 | else |
1340 | { |
1341 | outy += 16; |
1342 | } |
1343 | outy1 = 0; |
1344 | outy2 = 8; |
1345 | pic0 += 2 * (width -16); |
1346 | pic1 += 2 * (width -16); |
1347 | } |
1348 | } |
1349 | |
1350 | /*use in utils.c for jpeg decoding 422 planar to 422 |
1351 | * args: |
1352 | * out: pointer to data output of idct (macroblocks yyyy u v) |
1353 | * pic: pointer to picture buffer (yuyv) |
1354 | * width: picture width |
1355 | */ |
1356 | void yuv422pto422(int * out,unsigned char *pic,int width) |
1357 | { |
1358 | int j, k; |
1359 | unsigned char *pic0, *pic1; |
1360 | int *outy, *outu, *outv; |
1361 | int outy1 = 0; |
1362 | int outy2 = 8; |
1363 | int outu1 = 0; |
1364 | int outv1 = 0; |
1365 | |
1366 | //yyyyuv |
1367 | pic0 = pic; |
1368 | pic1 = pic + width; |
1369 | outy = out; |
1370 | outu = out + 64 * 4; |
1371 | outv = out + 64 * 5; |
1372 | for (j = 0; j < 4; j++) |
1373 | { |
1374 | for (k = 0; k < 8; k++) |
1375 | { |
1376 | if( k == 4) |
1377 | { |
1378 | outy1 += 56; |
1379 | outy2 += 56; |
1380 | } |
1381 | *pic0++ = CLIP(outy[outy1]); //y1 line 1 |
1382 | *pic0++ = CLIP(128 + outu[outu1]); //u line 1 |
1383 | *pic0++ = CLIP(outy[outy1+1]); //y2 line 1 |
1384 | *pic0++ = CLIP(128 + outv[outv1]); //v line 1 |
1385 | *pic1++ = CLIP(outy[outy2]); //y1 line 2 |
1386 | *pic1++ = CLIP(128 + outu[outu1+8]);//u line 2 |
1387 | *pic1++ = CLIP(outy[outy2+1]); //y2 line 2 |
1388 | *pic1++ = CLIP(128 + outv[outv1+8]);//v line 2 |
1389 | outv1 += 1; outu1 += 1; |
1390 | outy1 +=2; outy2 +=2; |
1391 | } |
1392 | outy += 16;outu +=8; outv +=8; |
1393 | outv1 = 0; outu1=0; |
1394 | outy1 = 0; |
1395 | outy2 = 8; |
1396 | pic0 += 2 * (width -16); |
1397 | pic1 += 2 * (width -16); |
1398 | } |
1399 | } |
1400 | |
1401 | void yuv420pto420sp(int * out, addr *pic, int width) |
1402 | { |
1403 | int j, k; |
1404 | unsigned char *pic0, *pic1, *uv; |
1405 | int *outy, *outu, *outv; |
1406 | int *outy1 ; |
1407 | int *outy2 ; |
1408 | int *outu1 ; |
1409 | int *outv1 ; |
1410 | |
1411 | pic0 = pic->y; |
1412 | pic1 = pic->y + width; |
1413 | uv = pic->v; |
1414 | outy = out; |
1415 | outu = out + 64 * 4; |
1416 | outv = out + 64 * 5; |
1417 | |
1418 | for (j = 0; j < 8; j++) |
1419 | { |
1420 | outy1 = outy; |
1421 | outy2 = outy+8; |
1422 | outv1 = outv; |
1423 | outu1 = outu; |
1424 | |
1425 | { |
1426 | asm volatile( |
1427 | "mov r0,#0 \n\t" |
1428 | "vdup.u32 d30, r0 \n\t" |
1429 | "mov r0,#255 \n\t" |
1430 | "vdup.u32 d31, r0 \n\t" |
1431 | |
1432 | /*** line1 ***/ |
1433 | "mov r0, #256 @256=64*4\n\t" |
1434 | "vld4.32 {d26,d27,d28,d29}, [%[outy1]], r0 \n\t" |
1435 | "vmax.s32 d26, d26, d30 \n\t" |
1436 | "vmin.s32 d26, d26, d31 \n\t" |
1437 | "vmax.s32 d27, d27, d30 \n\t" |
1438 | "vmin.s32 d27, d27, d31 \n\t" |
1439 | "vmax.s32 d28, d28, d30 \n\t" |
1440 | "vmin.s32 d28, d28, d31 \n\t" |
1441 | "vmax.s32 d29, d29, d30 \n\t" |
1442 | "vmin.s32 d29, d29, d31 \n\t" |
1443 | "vst4.8 {d26[0],d27[0],d28[0],d29[0]}, [%[pic0]]! \n\t" |
1444 | "vst4.8 {d26[4],d27[4],d28[4],d29[4]}, [%[pic0]]! \n\t" |
1445 | |
1446 | /*** mb 2 ***/ |
1447 | "vld4.32 {d26,d27,d28,d29}, [%[outy1]] \n\t" |
1448 | "vmax.s32 d26, d26, d30 \n\t" |
1449 | "vmin.s32 d26, d26, d31 \n\t" |
1450 | "vmax.s32 d27, d27, d30 \n\t" |
1451 | "vmin.s32 d27, d27, d31 \n\t" |
1452 | "vmax.s32 d28, d28, d30 \n\t" |
1453 | "vmin.s32 d28, d28, d31 \n\t" |
1454 | "vmax.s32 d29, d29, d30 \n\t" |
1455 | "vmin.s32 d29, d29, d31 \n\t" |
1456 | "vst4.8 {d26[0],d27[0],d28[0],d29[0]}, [%[pic0]]! \n\t" |
1457 | "vst4.8 {d26[4],d27[4],d28[4],d29[4]}, [%[pic0]]! \n\t" |
1458 | |
1459 | /*** line2 ***/ |
1460 | "vld4.32 {d26,d27,d28,d29}, [%[outy2]],r0 \n\t" |
1461 | "vmax.s32 d26, d26, d30 \n\t" |
1462 | "vmin.s32 d26, d26, d31 \n\t" |
1463 | "vmax.s32 d27, d27, d30 \n\t" |
1464 | "vmin.s32 d27, d27, d31 \n\t" |
1465 | "vmax.s32 d28, d28, d30 \n\t" |
1466 | "vmin.s32 d28, d28, d31 \n\t" |
1467 | "vmax.s32 d29, d29, d30 \n\t" |
1468 | "vmin.s32 d29, d29, d31 \n\t" |
1469 | "vst4.8 {d26[0],d27[0],d28[0],d29[0]}, [%[pic1]]! \n\t" |
1470 | "vst4.8 {d26[4],d27[4],d28[4],d29[4]}, [%[pic1]]! \n\t" |
1471 | |
1472 | /*** mb2 ***/ |
1473 | "vld4.32 {d26,d27,d28,d29}, [%[outy2]] \n\t" |
1474 | "vmax.s32 d26, d26, d30 \n\t" |
1475 | "vmin.s32 d26, d26, d31 \n\t" |
1476 | "vmax.s32 d27, d27, d30 \n\t" |
1477 | "vmin.s32 d27, d27, d31 \n\t" |
1478 | "vmax.s32 d28, d28, d30 \n\t" |
1479 | "vmin.s32 d28, d28, d31 \n\t" |
1480 | "vmax.s32 d29, d29, d30 \n\t" |
1481 | "vmin.s32 d29, d29, d31 \n\t" |
1482 | "vst4.8 {d26[0],d27[0],d28[0],d29[0]}, [%[pic1]]! \n\t" |
1483 | "vst4.8 {d26[4],d27[4],d28[4],d29[4]}, [%[pic1]]! \n\t" |
1484 | |
1485 | /*** uv ***/ |
1486 | "mov r0, #16 @16=4*4 \n\t" |
1487 | "vld4.32 {d22,d24,d26,d28}, [%[outv1]], r0 \n\t" |
1488 | "vld4.32 {d23,d25,d27,d29}, [%[outu1]], r0 \n\t" |
1489 | |
1490 | "mov r0, #128 \n\t" |
1491 | "vdup.u32 d30, r0 \n\t" |
1492 | "vqadd.s32 d22, d22, d30 \n\t" |
1493 | "vqadd.s32 d23, d23, d30 \n\t" |
1494 | "vqadd.s32 d24, d24, d30 \n\t" |
1495 | "vqadd.s32 d25, d25, d30 \n\t" |
1496 | "vqadd.s32 d26, d26, d30 \n\t" |
1497 | "vqadd.s32 d27, d27, d30 \n\t" |
1498 | "vqadd.s32 d28, d28, d30 \n\t" |
1499 | "vqadd.s32 d29, d29, d30 \n\t" |
1500 | |
1501 | "mov r0, #0 \n\t" |
1502 | "vdup.u32 d30, r0 \n\t" |
1503 | |
1504 | "vmax.s32 d22, d22, d30 \n\t" |
1505 | "vmin.s32 d22, d22, d31 \n\t" |
1506 | "vmax.s32 d24, d24, d30 \n\t" |
1507 | "vmin.s32 d24, d24, d31 \n\t" |
1508 | "vmax.s32 d26, d26, d30 \n\t" |
1509 | "vmin.s32 d26, d26, d31 \n\t" |
1510 | "vmax.s32 d28, d28, d30 \n\t" |
1511 | "vmin.s32 d28, d28, d31 \n\t" |
1512 | |
1513 | "vmax.s32 d23, d23, d30 \n\t" |
1514 | "vmin.s32 d23, d23, d31 \n\t" |
1515 | "vmax.s32 d25, d25, d30 \n\t" |
1516 | "vmin.s32 d25, d25, d31 \n\t" |
1517 | "vmax.s32 d27, d27, d30 \n\t" |
1518 | "vmin.s32 d27, d27, d31 \n\t" |
1519 | "vmax.s32 d29, d29, d30 \n\t" |
1520 | "vmin.s32 d29, d29, d31 \n\t" |
1521 | |
1522 | "vst4.8 {d22[0],d23[0],d24[0],d25[0]}, [%[uv]]! \n\t" |
1523 | "vst4.8 {d26[0],d27[0],d28[0],d29[0]}, [%[uv]]! \n\t" |
1524 | "vst4.8 {d22[4],d23[4],d24[4],d25[4]}, [%[uv]]! \n\t" |
1525 | "vst4.8 {d26[4],d27[4],d28[4],d29[4]}, [%[uv]]! \n\t" |
1526 | ////////////////////////////// |
1527 | |
1528 | "4:@end \n\t" |
1529 | : [outy1] "+r" (outy1), [outy2] "+r" (outy2), |
1530 | [pic0] "+r" (pic0), [pic1] "+r" (pic1), |
1531 | [outu1] "+r" (outu1), [outv1] "+r" (outv1), |
1532 | [uv] "+r" (uv) |
1533 | : [width] "r" (width) |
1534 | : "cc", "memory", "r0","q11", "q12", "q13","q14","q15" |
1535 | ); |
1536 | } |
1537 | if(j == 3) |
1538 | outy += 80; |
1539 | else |
1540 | outy += 16; |
1541 | outu +=8; outv +=8; |
1542 | pic0 += 2 * (width - 8); |
1543 | pic1 += 2 * (width - 8); |
1544 | uv += width - 16; |
1545 | } |
1546 | } |
1547 | |
1548 | void yuv420pto420p(int * out, addr *pic, int width) |
1549 | { |
1550 | int j, k; |
1551 | unsigned char *pic0, *pic1, *u, *v; |
1552 | int *outy, *outu, *outv; |
1553 | int *outy1 ; |
1554 | int *outy2 ; |
1555 | int *outu1 ; |
1556 | int *outv1 ; |
1557 | |
1558 | pic0 = pic->y; |
1559 | pic1 = pic->y + width; |
1560 | v = pic->v; |
1561 | u = pic->u; |
1562 | outy = out; |
1563 | outu = out + 64 * 4; |
1564 | outv = out + 64 * 5; |
1565 | |
1566 | for (j = 0; j < 8; j++) |
1567 | { |
1568 | outy1 = outy; |
1569 | outy2 = outy+8; |
1570 | outv1 = outv; |
1571 | outu1 = outu; |
1572 | |
1573 | { |
1574 | asm volatile( |
1575 | "mov r0,#0 \n\t" |
1576 | "vdup.u32 d30, r0 \n\t" |
1577 | "mov r0,#255 \n\t" |
1578 | "vdup.u32 d31, r0 \n\t" |
1579 | |
1580 | /*** line1 ***/ |
1581 | "mov r0, #256 @256=64*4\n\t" |
1582 | "vld4.32 {d26,d27,d28,d29}, [%[outy1]], r0 \n\t" |
1583 | "vmax.s32 d26, d26, d30 \n\t" |
1584 | "vmin.s32 d26, d26, d31 \n\t" |
1585 | "vmax.s32 d27, d27, d30 \n\t" |
1586 | "vmin.s32 d27, d27, d31 \n\t" |
1587 | "vmax.s32 d28, d28, d30 \n\t" |
1588 | "vmin.s32 d28, d28, d31 \n\t" |
1589 | "vmax.s32 d29, d29, d30 \n\t" |
1590 | "vmin.s32 d29, d29, d31 \n\t" |
1591 | "vst4.8 {d26[0],d27[0],d28[0],d29[0]}, [%[pic0]]! \n\t" |
1592 | "vst4.8 {d26[4],d27[4],d28[4],d29[4]}, [%[pic0]]! \n\t" |
1593 | |
1594 | /*** mb 2 ***/ |
1595 | "vld4.32 {d26,d27,d28,d29}, [%[outy1]] \n\t" |
1596 | "vmax.s32 d26, d26, d30 \n\t" |
1597 | "vmin.s32 d26, d26, d31 \n\t" |
1598 | "vmax.s32 d27, d27, d30 \n\t" |
1599 | "vmin.s32 d27, d27, d31 \n\t" |
1600 | "vmax.s32 d28, d28, d30 \n\t" |
1601 | "vmin.s32 d28, d28, d31 \n\t" |
1602 | "vmax.s32 d29, d29, d30 \n\t" |
1603 | "vmin.s32 d29, d29, d31 \n\t" |
1604 | "vst4.8 {d26[0],d27[0],d28[0],d29[0]}, [%[pic0]]! \n\t" |
1605 | "vst4.8 {d26[4],d27[4],d28[4],d29[4]}, [%[pic0]]! \n\t" |
1606 | |
1607 | /*** line2 ***/ |
1608 | "vld4.32 {d26,d27,d28,d29}, [%[outy2]],r0 \n\t" |
1609 | "vmax.s32 d26, d26, d30 \n\t" |
1610 | "vmin.s32 d26, d26, d31 \n\t" |
1611 | "vmax.s32 d27, d27, d30 \n\t" |
1612 | "vmin.s32 d27, d27, d31 \n\t" |
1613 | "vmax.s32 d28, d28, d30 \n\t" |
1614 | "vmin.s32 d28, d28, d31 \n\t" |
1615 | "vmax.s32 d29, d29, d30 \n\t" |
1616 | "vmin.s32 d29, d29, d31 \n\t" |
1617 | "vst4.8 {d26[0],d27[0],d28[0],d29[0]}, [%[pic1]]! \n\t" |
1618 | "vst4.8 {d26[4],d27[4],d28[4],d29[4]}, [%[pic1]]! \n\t" |
1619 | |
1620 | /*** mb2 ***/ |
1621 | "vld4.32 {d26,d27,d28,d29}, [%[outy2]] \n\t" |
1622 | "vmax.s32 d26, d26, d30 \n\t" |
1623 | "vmin.s32 d26, d26, d31 \n\t" |
1624 | "vmax.s32 d27, d27, d30 \n\t" |
1625 | "vmin.s32 d27, d27, d31 \n\t" |
1626 | "vmax.s32 d28, d28, d30 \n\t" |
1627 | "vmin.s32 d28, d28, d31 \n\t" |
1628 | "vmax.s32 d29, d29, d30 \n\t" |
1629 | "vmin.s32 d29, d29, d31 \n\t" |
1630 | "vst4.8 {d26[0],d27[0],d28[0],d29[0]}, [%[pic1]]! \n\t" |
1631 | "vst4.8 {d26[4],d27[4],d28[4],d29[4]}, [%[pic1]]! \n\t" |
1632 | |
1633 | /*** uv ***/ |
1634 | "mov r0, #16 @16=4*4 \n\t" |
1635 | "vld4.32 {d22,d23,d24,d25}, [%[outv1]], r0 \n\t" |
1636 | "vld4.32 {d26,d27,d28,d29}, [%[outu1]], r0 \n\t" |
1637 | |
1638 | "mov r0, #128 \n\t" |
1639 | "vdup.u32 d30, r0 \n\t" |
1640 | "vqadd.s32 d22, d22, d30 \n\t" |
1641 | "vqadd.s32 d23, d23, d30 \n\t" |
1642 | "vqadd.s32 d24, d24, d30 \n\t" |
1643 | "vqadd.s32 d25, d25, d30 \n\t" |
1644 | "vqadd.s32 d26, d26, d30 \n\t" |
1645 | "vqadd.s32 d27, d27, d30 \n\t" |
1646 | "vqadd.s32 d28, d28, d30 \n\t" |
1647 | "vqadd.s32 d29, d29, d30 \n\t" |
1648 | |
1649 | "mov r0, #0 \n\t" |
1650 | "vdup.u32 d30, r0 \n\t" |
1651 | |
1652 | "vmax.s32 d22, d22, d30 \n\t" |
1653 | "vmin.s32 d22, d22, d31 \n\t" |
1654 | "vmax.s32 d23, d23, d30 \n\t" |
1655 | "vmin.s32 d23, d23, d31 \n\t" |
1656 | "vmax.s32 d24, d24, d30 \n\t" |
1657 | "vmin.s32 d24, d24, d31 \n\t" |
1658 | "vmax.s32 d25, d25, d30 \n\t" |
1659 | "vmin.s32 d25, d25, d31 \n\t" |
1660 | |
1661 | "vmax.s32 d26, d26, d30 \n\t" |
1662 | "vmin.s32 d26, d26, d31 \n\t" |
1663 | "vmax.s32 d27, d27, d30 \n\t" |
1664 | "vmin.s32 d27, d27, d31 \n\t" |
1665 | "vmax.s32 d28, d28, d30 \n\t" |
1666 | "vmin.s32 d28, d28, d31 \n\t" |
1667 | "vmax.s32 d29, d29, d30 \n\t" |
1668 | "vmin.s32 d29, d29, d31 \n\t" |
1669 | |
1670 | "vst4.8 {d22[0],d23[0],d24[0],d25[0]}, [%[v]]! \n\t" |
1671 | "vst4.8 {d22[4],d23[4],d24[4],d25[4]}, [%[v]]! \n\t" |
1672 | "vst4.8 {d26[0],d27[0],d28[0],d29[0]}, [%[u]]! \n\t" |
1673 | "vst4.8 {d26[4],d27[4],d28[4],d29[4]}, [%[u]]! \n\t" |
1674 | ////////////////////////////// |
1675 | |
1676 | "4:@end \n\t" |
1677 | : [outy1] "+r" (outy1), [outy2] "+r" (outy2), |
1678 | [pic0] "+r" (pic0), [pic1] "+r" (pic1), |
1679 | [outu1] "+r" (outu1), [outv1] "+r" (outv1), |
1680 | [u] "+r" (u), [v] "+r" (v) |
1681 | : [width] "r" (width) |
1682 | : "cc", "memory", "r0","q11","q12","q13","q14","q15" |
1683 | ); |
1684 | } |
1685 | if(j == 3) |
1686 | outy += 80; |
1687 | else |
1688 | outy += 16; |
1689 | outu += 8; outv += 8; |
1690 | pic0 += 2 * (width - 8); |
1691 | pic1 += 2 * (width - 8); |
1692 | u += width / 2 - 8; |
1693 | v += width / 2 - 8; |
1694 | } |
1695 | } |
1696 | |
1697 | void yuv422pto420sp(int * out, addr *pic, int width) |
1698 | { |
1699 | int j, k; |
1700 | unsigned char *pic0, *pic1,*uv; |
1701 | int *outy, *outu, *outv; |
1702 | int *outy1 ; |
1703 | int *outy2 ; |
1704 | int *outu1 ; |
1705 | int *outv1 ; |
1706 | |
1707 | //yyyyuv |
1708 | pic0 = pic->y; |
1709 | pic1 = pic->y + width; |
1710 | uv = pic->v; |
1711 | outy = out; |
1712 | outu = out + 64 * 4; |
1713 | outv = out + 64 * 5; |
1714 | |
1715 | for (j = 0; j < 4; j++) |
1716 | { |
1717 | outy1 = outy; |
1718 | outy2 = outy+8; |
1719 | outv1 = outv; |
1720 | outu1 = outu; |
1721 | |
1722 | for (k = 0; k < 2; k++) |
1723 | { |
1724 | asm volatile( |
1725 | "mov r0,#0 \n\t" |
1726 | "vdup.u32 d30, r0 \n\t" |
1727 | "mov r0,#255 \n\t" |
1728 | "vdup.u32 d31, r0 \n\t" |
1729 | |
1730 | /////////////////////////////line1 |
1731 | "mov r0, #256 @256=64*4\n\t" |
1732 | "vld4.32 {d26,d27,d28,d29}, [%[outy1]], r0 \n\t" |
1733 | "vmax.s32 d26, d26, d30 \n\t" |
1734 | "vmin.s32 d26, d26, d31 \n\t" |
1735 | "vmax.s32 d27, d27, d30 \n\t" |
1736 | "vmin.s32 d27, d27, d31 \n\t" |
1737 | "vmax.s32 d28, d28, d30 \n\t" |
1738 | "vmin.s32 d28, d28, d31 \n\t" |
1739 | "vmax.s32 d29, d29, d30 \n\t" |
1740 | "vmin.s32 d29, d29, d31 \n\t" |
1741 | "vst4.8 {d26[0],d27[0],d28[0],d29[0]}, [%[pic0]]! \n\t" |
1742 | "vst4.8 {d26[4],d27[4],d28[4],d29[4]}, [%[pic0]]! \n\t" |
1743 | |
1744 | /////////////////////////////line2 |
1745 | "vld4.32 {d26,d27,d28,d29}, [%[outy2]],r0 \n\t" |
1746 | "vmax.s32 d26, d26, d30 \n\t" |
1747 | "vmin.s32 d26, d26, d31 \n\t" |
1748 | "vmax.s32 d27, d27, d30 \n\t" |
1749 | "vmin.s32 d27, d27, d31 \n\t" |
1750 | "vmax.s32 d28, d28, d30 \n\t" |
1751 | "vmin.s32 d28, d28, d31 \n\t" |
1752 | "vmax.s32 d29, d29, d30 \n\t" |
1753 | "vmin.s32 d29, d29, d31 \n\t" |
1754 | "vst4.8 {d26[0],d27[0],d28[0],d29[0]}, [%[pic1]]! \n\t" |
1755 | "vst4.8 {d26[4],d27[4],d28[4],d29[4]}, [%[pic1]]! \n\t" |
1756 | |
1757 | //////////////////////////////uv |
1758 | "mov r0, #16 @16=4*4 \n\t" |
1759 | "vld4.32 {d22,d24,d26,d28}, [%[outv1]], r0 \n\t" |
1760 | "vld4.32 {d23,d25,d27,d29}, [%[outu1]], r0 \n\t" |
1761 | |
1762 | "mov r0, #128 \n\t" |
1763 | "vdup.u32 d30, r0 \n\t" |
1764 | "vqadd.s32 d22, d22, d30 \n\t" |
1765 | "vqadd.s32 d23, d23, d30 \n\t" |
1766 | "vqadd.s32 d24, d24, d30 \n\t" |
1767 | "vqadd.s32 d25, d25, d30 \n\t" |
1768 | "vqadd.s32 d26, d26, d30 \n\t" |
1769 | "vqadd.s32 d27, d27, d30 \n\t" |
1770 | "vqadd.s32 d28, d28, d30 \n\t" |
1771 | "vqadd.s32 d29, d29, d30 \n\t" |
1772 | |
1773 | "mov r0, #0 \n\t" |
1774 | "vdup.u32 d30, r0 \n\t" |
1775 | |
1776 | "vmax.s32 d22, d22, d30 \n\t" |
1777 | "vmin.s32 d22, d22, d31 \n\t" |
1778 | "vmax.s32 d24, d24, d30 \n\t" |
1779 | "vmin.s32 d24, d24, d31 \n\t" |
1780 | "vmax.s32 d26, d26, d30 \n\t" |
1781 | "vmin.s32 d26, d26, d31 \n\t" |
1782 | "vmax.s32 d28, d28, d30 \n\t" |
1783 | "vmin.s32 d28, d28, d31 \n\t" |
1784 | |
1785 | "vmax.s32 d23, d23, d30 \n\t" |
1786 | "vmin.s32 d23, d23, d31 \n\t" |
1787 | "vmax.s32 d25, d25, d30 \n\t" |
1788 | "vmin.s32 d25, d25, d31 \n\t" |
1789 | "vmax.s32 d27, d27, d30 \n\t" |
1790 | "vmin.s32 d27, d27, d31 \n\t" |
1791 | "vmax.s32 d29, d29, d30 \n\t" |
1792 | "vmin.s32 d29, d29, d31 \n\t" |
1793 | |
1794 | "vst4.8 {d22[0],d23[0],d24[0],d25[0]}, [%[uv]]! \n\t" |
1795 | "vst4.8 {d26[0],d27[0],d28[0],d29[0]}, [%[uv]]! \n\t" |
1796 | ////////////////////////////// |
1797 | |
1798 | "4:@end \n\t" |
1799 | : [outy1] "+r" (outy1), [outy2] "+r" (outy2), |
1800 | [pic0] "+r" (pic0), [pic1] "+r" (pic1), |
1801 | [outu1] "+r" (outu1), [outv1] "+r" (outv1), |
1802 | [uv] "+r" (uv) |
1803 | : [width] "r" (width) |
1804 | : "cc", "memory", "r0","q11","q12","q13","q14","q15" |
1805 | ); |
1806 | } |
1807 | outy += 16;outu +=8; outv +=8; |
1808 | pic0 += 2 * (width - 8); |
1809 | pic1 += 2 * (width - 8); |
1810 | uv += width - 16; |
1811 | } |
1812 | } |
1813 | |
1814 | void yuv422pto420p(int * out, addr *pic, int width) |
1815 | { |
1816 | int j, k; |
1817 | unsigned char *pic0, *pic1,*v,*u; |
1818 | int *outy, *outu, *outv; |
1819 | int *outy1 ; |
1820 | int *outy2 ; |
1821 | int *outu1 ; |
1822 | int *outv1 ; |
1823 | |
1824 | //yyyyuv |
1825 | pic0 = pic->y; |
1826 | pic1 = pic->y + width; |
1827 | v = pic->v; |
1828 | u = pic->u; |
1829 | outy = out; |
1830 | outu = out + 64 * 4; |
1831 | outv = out + 64 * 5; |
1832 | for (j = 0; j < 4; j++) |
1833 | { |
1834 | outy1 = outy; |
1835 | outy2 = outy+8; |
1836 | outv1 = outv; |
1837 | outu1 = outu; |
1838 | |
1839 | for (k = 0; k < 2; k++) |
1840 | { |
1841 | asm volatile( |
1842 | "mov r0,#0 \n\t" |
1843 | "vdup.u32 d30, r0 \n\t" |
1844 | "mov r0,#255 \n\t" |
1845 | "vdup.u32 d31, r0 \n\t" |
1846 | |
1847 | /////////////////////////////line1 |
1848 | "mov r0, #256 @256=64*4\n\t" |
1849 | "vld4.32 {d26,d27,d28,d29}, [%[outy1]], r0 \n\t" |
1850 | "vmax.s32 d26, d26, d30 \n\t" |
1851 | "vmin.s32 d26, d26, d31 \n\t" |
1852 | "vmax.s32 d27, d27, d30 \n\t" |
1853 | "vmin.s32 d27, d27, d31 \n\t" |
1854 | "vmax.s32 d28, d28, d30 \n\t" |
1855 | "vmin.s32 d28, d28, d31 \n\t" |
1856 | "vmax.s32 d29, d29, d30 \n\t" |
1857 | "vmin.s32 d29, d29, d31 \n\t" |
1858 | "vst4.8 {d26[0],d27[0],d28[0],d29[0]}, [%[pic0]]! \n\t" |
1859 | "vst4.8 {d26[4],d27[4],d28[4],d29[4]}, [%[pic0]]! \n\t" |
1860 | |
1861 | /////////////////////////////line2 |
1862 | "vld4.32 {d26,d27,d28,d29}, [%[outy2]],r0 \n\t" |
1863 | "vmax.s32 d26, d26, d30 \n\t" |
1864 | "vmin.s32 d26, d26, d31 \n\t" |
1865 | "vmax.s32 d27, d27, d30 \n\t" |
1866 | "vmin.s32 d27, d27, d31 \n\t" |
1867 | "vmax.s32 d28, d28, d30 \n\t" |
1868 | "vmin.s32 d28, d28, d31 \n\t" |
1869 | "vmax.s32 d29, d29, d30 \n\t" |
1870 | "vmin.s32 d29, d29, d31 \n\t" |
1871 | "vst4.8 {d26[0],d27[0],d28[0],d29[0]}, [%[pic1]]! \n\t" |
1872 | "vst4.8 {d26[4],d27[4],d28[4],d29[4]}, [%[pic1]]! \n\t" |
1873 | |
1874 | //////////////////////////////uv |
1875 | "mov r0, #16 @16=4*4 \n\t" |
1876 | "vld4.32 {d22,d23,d24,d25}, [%[outv1]], r0 \n\t" |
1877 | "vld4.32 {d26,d27,d28,d29}, [%[outu1]], r0 \n\t" |
1878 | |
1879 | "mov r0, #128 \n\t" |
1880 | "vdup.u32 d30, r0 \n\t" |
1881 | "vqadd.s32 d22, d22, d30 \n\t" |
1882 | "vqadd.s32 d23, d23, d30 \n\t" |
1883 | "vqadd.s32 d24, d24, d30 \n\t" |
1884 | "vqadd.s32 d25, d25, d30 \n\t" |
1885 | "vqadd.s32 d26, d26, d30 \n\t" |
1886 | "vqadd.s32 d27, d27, d30 \n\t" |
1887 | "vqadd.s32 d28, d28, d30 \n\t" |
1888 | "vqadd.s32 d29, d29, d30 \n\t" |
1889 | |
1890 | "mov r0, #0 \n\t" |
1891 | "vdup.u32 d30, r0 \n\t" |
1892 | |
1893 | "vmax.s32 d22, d22, d30 \n\t" |
1894 | "vmin.s32 d22, d22, d31 \n\t" |
1895 | "vmax.s32 d24, d24, d30 \n\t" |
1896 | "vmin.s32 d24, d24, d31 \n\t" |
1897 | "vmax.s32 d26, d26, d30 \n\t" |
1898 | "vmin.s32 d26, d26, d31 \n\t" |
1899 | "vmax.s32 d28, d28, d30 \n\t" |
1900 | "vmin.s32 d28, d28, d31 \n\t" |
1901 | |
1902 | "vmax.s32 d23, d23, d30 \n\t" |
1903 | "vmin.s32 d23, d23, d31 \n\t" |
1904 | "vmax.s32 d25, d25, d30 \n\t" |
1905 | "vmin.s32 d25, d25, d31 \n\t" |
1906 | "vmax.s32 d27, d27, d30 \n\t" |
1907 | "vmin.s32 d27, d27, d31 \n\t" |
1908 | "vmax.s32 d29, d29, d30 \n\t" |
1909 | "vmin.s32 d29, d29, d31 \n\t" |
1910 | |
1911 | "vst4.8 {d22[0],d23[0],d24[0],d25[0]}, [%[v]]! \n\t" |
1912 | "vst4.8 {d26[0],d27[0],d28[0],d29[0]}, [%[u]]! \n\t" |
1913 | ////////////////////////////// |
1914 | "4:@end \n\t" |
1915 | : [outy1] "+r" (outy1), [outy2] "+r" (outy2), |
1916 | [pic0] "+r" (pic0), [pic1] "+r" (pic1), |
1917 | [outu1] "+r" (outu1), [outv1] "+r" (outv1), |
1918 | [v] "+r" (v),[u] "+r" (u) |
1919 | : [width] "r" (width) |
1920 | : "cc", "memory", "r0","q11", "q12", "q13","q14","q15" |
1921 | ); |
1922 | } |
1923 | outy += 16;outu +=8; outv +=8; |
1924 | pic0 += 2 * (width - 8); |
1925 | pic1 += 2 * (width - 8); |
1926 | v += width/2 - 8; |
1927 | u += width/2 - 8; |
1928 | } |
1929 | } |
1930 | |
1931 | /*use in utils.c for jpeg decoding 444 planar to 422 |
1932 | * args: |
1933 | * out: pointer to data output of idct (macroblocks yyyy u v) |
1934 | * pic: pointer to picture buffer (yuyv) |
1935 | * width: picture width |
1936 | */ |
1937 | void yuv444pto422(int * out,unsigned char *pic,int width) |
1938 | { |
1939 | int j, k; |
1940 | unsigned char *pic0, *pic1; |
1941 | int *outy, *outu, *outv; |
1942 | int outy1 = 0; |
1943 | int outy2 = 8; |
1944 | int outu1 = 0; |
1945 | int outv1 = 0; |
1946 | |
1947 | //yyyyuv |
1948 | pic0 = pic; |
1949 | pic1 = pic + width; |
1950 | outy = out; |
1951 | outu = out + 64 * 4; // Ooops where did i invert ?? |
1952 | outv = out + 64 * 5; |
1953 | for (j = 0; j < 4; j++) |
1954 | { |
1955 | for (k = 0; k < 4; k++) |
1956 | { |
1957 | *pic0++ =CLIP( outy[outy1]); //y1 line 1 |
1958 | *pic0++ =CLIP( 128 + outu[outu1]); //u line 1 |
1959 | *pic0++ =CLIP( outy[outy1+1]); //y2 line 1 |
1960 | *pic0++ =CLIP( 128 + outv[outv1]); //v line 1 |
1961 | *pic1++ =CLIP( outy[outy2]); //y1 line 2 |
1962 | *pic1++ =CLIP( 128 + outu[outu1+8]);//u line 2 |
1963 | *pic1++ =CLIP( outy[outy2+1]); //y2 line 2 |
1964 | *pic1++ =CLIP( 128 + outv[outv1+8]);//v line 2 |
1965 | outv1 += 2; outu1 += 2; |
1966 | outy1 +=2; outy2 +=2; |
1967 | } |
1968 | outy += 16;outu +=16; outv +=16; |
1969 | outv1 = 0; outu1=0; |
1970 | outy1 = 0; |
1971 | outy2 = 8; |
1972 | pic0 += 2 * (width -8); |
1973 | pic1 += 2 * (width -8); |
1974 | } |
1975 | } |
1976 | |
1977 | /*use in utils.c for jpeg decoding 400 planar to 422 |
1978 | * args: |
1979 | * out: pointer to data output of idct (macroblocks yyyy ) |
1980 | * pic: pointer to picture buffer (yuyv) |
1981 | * width: picture width |
1982 | */ |
1983 | void yuv400pto422(int * out,unsigned char *pic,int width) |
1984 | { |
1985 | int j, k; |
1986 | unsigned char *pic0, *pic1; |
1987 | int *outy ; |
1988 | int outy1 = 0; |
1989 | int outy2 = 8; |
1990 | pic0 = pic; |
1991 | pic1 = pic + width; |
1992 | outy = out; |
1993 | |
1994 | //yyyy |
1995 | for (j = 0; j < 4; j++) |
1996 | { |
1997 | for (k = 0; k < 4; k++) |
1998 | { |
1999 | *pic0++ = CLIP(outy[outy1]); //y1 line 1 |
2000 | *pic0++ = 128 ; //u |
2001 | *pic0++ = CLIP(outy[outy1+1]);//y2 line 1 |
2002 | *pic0++ = 128 ; //v |
2003 | *pic1++ = CLIP(outy[outy2]); //y1 line 2 |
2004 | *pic1++ = 128 ; //u |
2005 | *pic1++ = CLIP(outy[outy2+1]);//y2 line 2 |
2006 | *pic1++ = 128 ; //v |
2007 | outy1 +=2; outy2 +=2; |
2008 | } |
2009 | outy += 16; |
2010 | outy1 = 0; |
2011 | outy2 = 8; |
2012 | pic0 += 2 * (width -8); |
2013 | pic1 += 2 * (width -8); |
2014 | } |
2015 | } |
2016 | |
2017 |