blob: e434861c58057d1aab527b8b303e26603800bbd5 [file] [log] [blame]
Chih-Wei Huang0d92eda2012-02-07 16:55:49 +08001/*
2 libcamera: An implementation of the library required by Android OS 3.2 so
3 it can access V4L2 devices as cameras.
4
Chih-Wei Huangd5590eb2019-02-26 17:48:45 +08005 (C) 2011 Eduardo José Tagle <ejtagle@tutopia.com>
Chih-Wei Huang0d92eda2012-02-07 16:55:49 +08006 (C) 2011 RedScorpion
7
8 Based on several packages:
9 - luvcview: Sdl video Usb Video Class grabber
10 (C) 2005,2006,2007 Laurent Pinchart && Michel Xhaard
11
12 - spcaview
13 (C) 2003,2004,2005,2006 Michel Xhaard
14
15 - JPEG decoder from http://www.bootsplash.org/
16 (C) August 2001 by Michael Schroeder, <mls@suse.de>
17
18 - libcamera V4L for Android 2.2
19 (C) 2009 0xlab.org - http://0xlab.org/
20 (C) 2010 SpectraCore Technologies
21 Author: Venkat Raju <codredruids@spectracoretech.com>
22 Based on a code from http://code.google.com/p/android-m912/downloads/detail?name=v4l2_camera_v2.patch
23
24 - guvcview: http://guvcview.berlios.de
25 Paulo Assis <pj.assis@gmail.com>
26 Nobuhiro Iwamatsu <iwamatsu@nigauri.org>
27
28 This program is free software: you can redistribute it and/or modify
29 it under the terms of the GNU General Public License as published by
30 the Free Software Foundation, either version 3 of the License, or
31 (at your option) any later version.
32
33 This program is distributed in the hope that it will be useful,
34 but WITHOUT ANY WARRANTY; without even the implied warranty of
35 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
36 GNU General Public License for more details.
37
38 You should have received a copy of the GNU General Public License
39 along with this program. If not, see <http://www.gnu.org/licenses/>.
40
41 */
42
43#include <stdio.h>
44#include <stdlib.h>
45#include <string.h>
46extern "C" {
47#include <jpeglib.h>
48}
49#include "Converter.h"
50#include "V4L2Camera.h"
51
52/*clip value between 0 and 255*/
53#define CLIP(value) (uint8_t)(((value)>0xFF)?0xff:(((value)<0)?0:(value)))
54
55
56/* convert yuyv to YVU420SP */
57void yuyv_to_yvu420sp(uint8_t *dst,int dstStride, int dstHeight, uint8_t *src, int srcStride, int width, int height)
58{
59 // Start of Y plane
60 uint8_t* dstY = dst;
61
62 // Calculate start of UV plane
63 uint8_t* dstVU = dst + dstStride * dstHeight;
64
65 int h=0;
66 int w=0;
67 int dyvu = dstStride - width;
68 int sw = srcStride - (width<<1);
69 for (h = 0; h<height; h +=2) {
70 for (w=0; w < width; w += 2) {
71 *dstY++ = *src++; // Y0
72 dstVU[1] = (src[0] + src[srcStride]) >> 1; // U
73 src++;
74 *dstY++ = *src++; // Y1
75 dstVU[0] = (src[0] + src[srcStride]) >> 1; // V
76 src++;
77 dstVU+=2;
78 }
79 src += sw;
80 dstY += dyvu;
81 dstVU += dyvu;
82 for (w=0; w < width; w += 2) {
83 *dstY++ = *src; // Y0
84 src += 2;
85 *dstY++ = *src; // Y1
86 src += 2;
87 }
88 src += sw;
89 dstY += dyvu;
90 }
91}
92
93/* convert yuyv to YVU420P */
94/* This format assumes that the horizontal strides (luma and chroma) are multiple of 16 pixels */
95void yuyv_to_yvu420p(uint8_t *dst,int dstStride, int dstHeight, uint8_t *src, int srcStride, int width, int height)
96{
97 // Calculate the chroma plane stride
98 int dstVUStride = ((dstStride >> 1) + 15) & (-16);
99
100 // Start of Y plane
101 uint8_t* dstY = dst;
102
103 // Calculate start of V plane
104 uint8_t* dstV = dst + dstStride * dstHeight;
105
106 // Calculate start of U plane
107 uint8_t* dstU = dstV + (dstVUStride * dstHeight >> 1);
108
109 int h=0;
110 int w=0;
111 int dy = dstStride - width;
112 int dvu = dstVUStride - (width >> 1);
113 int sw = srcStride - (width<<1);
114 for (h = 0; h<height; h +=2) {
115 for (w=0; w < width; w += 2) {
116 *dstY++ = *src++; // Y0
117 *dstU++ = (src[0] + src[srcStride]) >> 1; // U
118 src++;
119 *dstY++ = *src++; // Y1
120 *dstV++ = (src[0] + src[srcStride]) >> 1; // V
121 src++;
122 }
123 src += sw;
124 dstY += dy;
125 dstU += dvu;
126 dstV += dvu;
127 for (w=0; w < width; w += 2) {
128 *dstY++ = *src; // Y0
129 src += 2;
130 *dstY++ = *src; // Y1
131 src += 2;
132 }
133 src += sw;
134 dstY += dy;
135 }
136}
137
138/* This format assumes that the horizontal strides (luma and chroma) are multiple of 16 pixels */
139void yuyv_to_yuv420p(uint8_t *dst,int dstStride, int dstHeight, uint8_t *src, int srcStride, int width, int height)
140{
141 // Calculate the chroma plane stride
142 int dstUVStride = ((dstStride >> 1) + 15) & (-16);
143
144 // Start of Y plane
145 uint8_t* dstY = dst;
146
147 // Calculate start of U plane
148 uint8_t* dstU = dst + dstStride * dstHeight;
149
150 // Calculate start of V plane
151 uint8_t* dstV = dstU + (dstUVStride * dstHeight >> 1);
152
153 int h=0;
154 int w=0;
155 int dy = dstStride - width;
156 int dvu = dstUVStride - (width >> 1);
157 int sw = srcStride - (width<<1);
158 for (h = 0; h<height; h +=2) {
159 for (w=0; w < width; w += 2) {
160 *dstY++ = *src++; // Y0
161 *dstU++ = (src[0] + src[srcStride]) >> 1; // U
162 src++;
163 *dstY++ = *src++; // Y1
164 *dstV++ = (src[0] + src[srcStride]) >> 1; // V
165 src++;
166 }
167 src += sw;
168 dstY += dy;
169 dstU += dvu;
170 dstV += dvu;
171 for (w=0; w < width; w += 2) {
172 *dstY++ = *src; // Y0
173 src += 2;
174 *dstY++ = *src; // Y1
175 src += 2;
176 }
177 src += sw;
178 dstY += dy;
179 }
180}
181
182
183/* convert yuyv to YVU422P */
184/* This format assumes that the horizontal strides (luma and chroma) are multiple of 16 pixels */
185void yuyv_to_yvu422p(uint8_t *dst,int dstStride, int dstHeight, uint8_t *src, int srcStride, int width, int height)
186{
187 // Calculate the chroma plane stride
188 int dstVUStride = ((dstStride >> 1) + 15) & (-16);
189
190 // Start of Y plane
191 uint8_t* dstY = dst;
192
193 // Calculate start of U plane
194 uint8_t* dstV = dst + dstStride * dstHeight;
195
196 // Calculate start of V plane
197 uint8_t* dstU = dstV + (dstVUStride * dstHeight);
198
199 int h=0;
200 int w=0;
201 int dy = dstStride - width;
202 int dvu = dstVUStride - (width >> 1);
203 int sw = srcStride - (width<<1);
204 for (h = 0; h<height; h ++) {
205 for (w=0; w < width; w += 2) {
206 *dstY++ = *src++; // Y0
207 *dstU++ = *src++; // U
208 *dstY++ = *src++; // Y1
209 *dstV++ = *src++; // V
210 }
211 src += sw;
212 dstY += dy;
213 dstU += dvu;
214 dstV += dvu;
215 }
216}
217
218
219/*convert y16 (grey) to yuyv (packed)
220* args:
221* dst: pointer to frame buffer (yuyv)
222* dstStride: stride of framebuffer
223* src: pointer to temp buffer containing y16 (grey) data frame
224* width: picture width
225* height: picture height
226*/
227void y16_to_yuyv (uint8_t *dst,int dstStride, uint8_t *src, int srcStride, int width, int height)
228{
229 uint16_t *ptmp= (uint16_t *) src;
230
231 int h=0;
232 int w=0;
233 int dw = dstStride - (width << 1);
234 int sw = (srcStride>>1) - width;
235
236 for(h=0;h<height;h++)
237 {
238 for(w=0;w<width;w+=2)
239 {
240 /* Y0 */
241 *dst++ = (uint8_t) (ptmp[0] & 0xFF00) >> 8;
242 /* U */
243 *dst++ = 0x7F;
244 /* Y1 */
245 *dst++ = (uint8_t) (ptmp[1] & 0xFF00) >> 8;
246 /* V */
247 *dst++ = 0x7F;
248
249 ptmp += 2;
250 }
251 dst += dw; // Correct for stride
252 ptmp += sw;
253 }
254}
255
256/*convert yyuv (packed) to yuyv (packed)
257* args:
258* dst: pointer to frame buffer (yuyv)
259* dstStride: stride of framebuffer
260* src: pointer to temp buffer containing yyuv packed data frame
261* width: picture width
262* height: picture height
263*/
264void yyuv_to_yuyv (uint8_t *dst,int dstStride, uint8_t *src, int srcStride, int width, int height)
265{
266 uint8_t *ptmp=NULL;
267 uint8_t *pfmb=NULL;
268 ptmp = src;
269 pfmb = dst;
270
271 int h=0;
272 int w=0;
273 int dw = dstStride - (width << 1);
274 int sw = srcStride - (width << 1);
275
276 for(h=0;h<height;h++)
277 {
278 for(w=0;w<width;w+=2)
279 {
280 /* Y0 */
281 *pfmb++ = ptmp[0];
282 /* U */
283 *pfmb++ = ptmp[2];
284 /* Y1 */
285 *pfmb++ = ptmp[1];
286 /* V */
287 *pfmb++ = ptmp[3];
288
289 ptmp += 4;
290 }
291 pfmb += dw; // Correct for stride
292 ptmp += sw;
293 }
294}
295
296
297/*convert uyvy (packed) to yuyv (packed)
298* args:
299* dst: pointer to frame buffer (yuyv)
300* dstStride: stride of framebuffer
301* src: pointer to temp buffer containing uyvy packed data frame
302* width: picture width
303* height: picture height
304*/
305void uyvy_to_yuyv (uint8_t *dst,int dstStride, uint8_t *src, int srcStride, int width, int height)
306{
307 uint8_t *ptmp = src;
308 uint8_t *pfmb = dst;
309 int h=0;
310 int w=0;
311 int dw = dstStride - (width << 1);
312 int sw = srcStride - (width << 1);
313
314 for(h=0;h<height;h++)
315 {
316 for(w=0;w<width;w+=2)
317 {
318 /* Y0 */
319 *pfmb++ = ptmp[1];
320 /* U */
321 *pfmb++ = ptmp[0];
322 /* Y1 */
323 *pfmb++ = ptmp[3];
324 /* V */
325 *pfmb++ = ptmp[2];
326
327 ptmp += 4;
328 }
329 pfmb += dw; // Correct for stride
330 ptmp += sw;
331 }
332}
333
334
335/*convert yvyu (packed) to yuyv (packed)
336* args:
337* dst: pointer to frame buffer (yuyv)
338* dstStride: stride of framebuffer
339* src: pointer to temp buffer containing yvyu packed data frame
340* width: picture width
341* height: picture height
342*/
343void yvyu_to_yuyv (uint8_t *dst,int dstStride, uint8_t *src, int srcStride, int width, int height)
344{
345 uint8_t *ptmp=NULL;
346 uint8_t *pfmb=NULL;
347 ptmp = src;
348 pfmb = dst;
349
350 int h=0;
351 int w=0;
352 int dw = dstStride - (width << 1);
353 int sw = srcStride - (width << 1);
354
355 for(h=0;h<height;h++)
356 {
357 for(w=0;w<width;w+=2)
358 {
359 /* Y0 */
360 *pfmb++ = ptmp[0];
361 /* U */
362 *pfmb++ = ptmp[3];
363 /* Y1 */
364 *pfmb++ = ptmp[2];
365 /* V */
366 *pfmb++ = ptmp[1];
367
368 ptmp += 4;
369 }
370 pfmb += dw; // Correct for stride
371 ptmp += sw;
372 }
373}
374
375/*convert yuv 420 planar (yu12) to yuv 422
376* args:
377* dst: pointer to frame buffer (yuyv)
378* dstStride: stride of framebuffer
379* src: pointer to temp buffer containing yuv420 planar data frame
380* width: picture width
381* height: picture height
382*/
383void yuv420_to_yuyv (uint8_t *dst,int dstStride, uint8_t *src, int width, int height)
384{
385 uint8_t *py;
386 uint8_t *pu;
387 uint8_t *pv;
388
389 int linesize = width * 2;
390 int uvlinesize = width / 2;
391 int offsety=0;
392 int offsetuv=0;
393 int dw = dstStride - (width << 1);
394
395 py=src;
396 pu=py+(width*height);
397 pv=pu+(width*height/4);
398
399 int h=0;
400 int w=0;
401
402 int wy=0;
403 int wuv=0;
404
405 offsety = 0;
406 offsetuv = 0;
407
408 for(h=0;h<height;h+=2)
409 {
410 wy=0;
411 wuv=0;
412
413 for(w=0;w<linesize;w+=4)
414 {
415 /*y00*/
416 *dst++ = py[wy + offsety];
417 /*y10*/
418 dst[dstStride-1] = py[wy + offsety + width];
419
420 /*u0*/
421 uint8_t u0 = pu[wuv + offsetuv];
422 *dst++ = u0;
423 /*u0*/
424 dst[dstStride-1] = u0;
425
426 /*y01*/
427 *dst++ = py[(wy + 1) + offsety];
428 /*y11*/
429 dst[dstStride-1] = py[(wy + 1) + offsety + width];
430
431 /*v0*/
432 uint8_t u1 = pv[wuv + offsetuv];
433 *dst++ = u1;
434 /*v0*/
435 dst[dstStride-1] = u1;
436
437 wuv++;
438 wy+=2;
439 }
440
441 dst += dstStride + dw;
442 offsety += width * 2;
443 offsetuv += uvlinesize;
444 }
445}
446
447/*convert yvu 420 planar (yv12) to yuv 422
448* args:
449* dst: pointer to frame buffer (yuyv)
450* dstStride: stride of framebuffer
451* src: pointer to temp buffer containing yuv420 planar data frame
452* width: picture width
453* height: picture height
454*/
455void yvu420_to_yuyv (uint8_t *dst,int dstStride, uint8_t *src, int width, int height)
456{
457 uint8_t *py;
458 uint8_t *pv;
459 uint8_t *pu;
460
461 int linesize = width * 2;
462 int uvlinesize = width / 2;
463 int offsety=0;
464 int offsetuv=0;
465 int dw = dstStride - (width << 1);
466
467 py=src;
468 pv=py+(width*height);
469 pu=pv+((width*height)/4);
470
471 int h=0;
472 int w=0;
473
474 int wy=0;
475 int wuv=0;
476
477 offsety = 0;
478 offsetuv = 0;
479
480 for(h=0;h<height;h+=2)
481 {
482 wy=0;
483 wuv=0;
484
485 for(w=0;w<linesize;w+=4)
486 {
487 /*y00*/
488 *dst++ = py[wy + offsety];
489 /*y10*/
490 dst[dstStride-1] = py[wy + offsety + width];
491
492 /*u0*/
493 uint8_t u0 = pu[wuv + offsetuv];
494 *dst++ = u0;
495 /*u0*/
496 dst[dstStride-1] = u0;
497
498 /*y01*/
499 *dst++ = py[(wy + 1) + offsety];
500 /*y11*/
501 dst[dstStride-1] = py[(wy + 1) + offsety + width];
502
503 /*v0*/
504 uint8_t v0 = pv[wuv + offsetuv];
505 *dst++ = v0;
506 /*v0*/
507 dst[dstStride-1] = v0;
508
509 wuv++;
510 wy+=2;
511 }
512 dst += dstStride + dw;
513 offsety += width * 2;
514 offsetuv += uvlinesize;
515
516 }
517}
518
519/*convert yuv 420 planar (uv interleaved) (nv12) to yuv 422
520* args:
521* dst: pointer to frame buffer (yuyv)
522* dstStride: stride of framebuffer
523* src: pointer to temp buffer containing yuv420 (nv12) planar data frame
524* width: picture width
525* height: picture height
526*/
527void nv12_to_yuyv (uint8_t *dst,int dstStride, uint8_t *src, int width, int height)
528{
529 uint8_t *py;
530 uint8_t *puv;
531
532 int linesize = width * 2;
533 int offsety=0;
534 int offsetuv=0;
535 int dw = dstStride - (width << 1);
536
537 py=src;
538 puv=py+(width*height);
539
540 int h=0;
541 int w=0;
542
543 int wy=0;
544 int wuv=0;
545
546 for(h=0;h<height;h+=2)
547 {
548 wy=0;
549 wuv=0;
550
551 for(w=0;w<linesize;w+=4)
552 {
553 /*y00*/
554 *dst++ = py[wy + offsety];
555 /*y10*/
556 dst[dstStride-1] = py[wy + offsety + width];
557
558 /*u0*/
559 uint8_t u0 = puv[wuv + offsetuv];
560 *dst++ = u0;
561 /*u0*/
562 dst[dstStride-1] = u0;
563
564 /*y01*/
565 *dst++ = py[(wy + 1) + offsety];
566 /*y11*/
567 dst[dstStride-1] = py[(wy + 1) + offsety + width];
568
569 /*v0*/
570 uint8_t v0 = puv[(wuv + 1) + offsetuv];
571 *dst++ = v0;
572 /*v0*/
573 dst[dstStride-1] = v0;
574
575 wuv+=2;
576 wy+=2;
577 }
578
579 dst += dstStride + dw;
580 offsety += width * 2;
581 offsetuv += width;
582 }
583}
584
585/*convert yuv 420 planar (vu interleaved) (nv21) to yuv 422
586* args:
587* dst: pointer to frame buffer (yuyv)
588* dstStride: stride of framebuffer
589* src: pointer to temp buffer containing yuv420 (nv21) planar data frame
590* width: picture width
591* height: picture height
592*/
593void nv21_to_yuyv (uint8_t *dst,int dstStride, uint8_t *src, int width, int height)
594{
595 uint8_t *py;
596 uint8_t *puv;
597
598 int linesize = width * 2;
599 int offsety=0;
600 int offsetuv=0;
601 int dw = dstStride - (width << 1);
602
603 py=src;
604 puv=py+(width*height);
605
606 int h=0;
607 int w=0;
608
609 int wy=0;
610 int wuv=0;
611
612 for(h=0;h<height;h+=2)
613 {
614 wy=0;
615 wuv=0;
616
617 for(w=0;w<linesize;w+=4)
618 {
619 /*y00*/
620 *dst++ = py[wy + offsety];
621 /*y10*/
622 dst[dstStride-1] = py[wy + offsety + width];
623
624 /*u0*/
625 uint8_t u0 = puv[(wuv + 1) + offsetuv];
626 *dst++ = u0;
627 /*u0*/
628 dst[dstStride-1] = u0;
629
630 /*y01*/
631 *dst++ = py[(wy + 1) + offsety];
632
633 /*y11*/
634 dst[dstStride-1] = py[(wy + 1) + offsety + width];
635
636 /*v0*/
637 uint8_t v0 = puv[wuv + offsetuv];
638 *dst++ = v0;
639 /*v0*/
640 dst[dstStride-1] = v0;
641
642 wuv+=2;
643 wy+=2;
644 }
645
646 dst += dstStride + dw;
647 offsety += width * 2;
648 offsetuv += width;
649
650 }
651}
652
653/*convert yuv 422 planar (uv interleaved) (nv16) to yuv 422
654* args:
655* dst: pointer to frame buffer (yuyv)
656* dstStride: stride of framebuffer
657* src: pointer to temp buffer containing yuv422 (nv16) planar data frame
658* width: picture width
659* height: picture height
660*/
661void nv16_to_yuyv (uint8_t *dst,int dstStride, uint8_t *src, int width, int height)
662{
663 uint8_t *py;
664 uint8_t *puv;
665
666 int linesize = width * 2;
667 int offsety=0;
668 int offsetuv=0;
669 int dw = dstStride - (width << 1);
670
671 py=src;
672 puv=py+(width*height);
673
674 int h=0;
675 int w=0;
676
677 int wy=0;
678 int wuv=0;
679
680 for(h=0;h<height;h++)
681 {
682 wy=0;
683 wuv=0;
684
685 for(w=0;w<linesize;w+=4)
686 {
687 /*y00*/
688 *dst++ = py[wy + offsety];
689 /*u0*/
690 *dst++ = puv[wuv + offsetuv];
691 /*y01*/
692 *dst++ = py[(wy + 1) + offsety];
693 /*v0*/
694 *dst++ = puv[(wuv + 1) + offsetuv];
695
696 wuv+=2;
697 wy+=2;
698 }
699 dst += dw;
700 offsety += width;
701 offsetuv += width;
702 }
703}
704
705/*convert yuv 422 planar (vu interleaved) (nv61) to yuv 422
706* args:
707* dst: pointer to frame buffer (yuyv)
708* dstStride: stride of framebuffer
709* src: pointer to temp buffer containing yuv422 (nv61) planar data frame
710* width: picture width
711* height: picture height
712*/
713void nv61_to_yuyv (uint8_t *dst,int dstStride, uint8_t *src, int width, int height)
714{
715 uint8_t *py;
716 uint8_t *puv;
717
718 int linesize = width * 2;
719 int offsety=0;
720 int offsetuv=0;
721 int dw = dstStride - (width << 1);
722
723 py=src;
724 puv=py+(width*height);
725
726 int h=0;
727 int w=0;
728
729 int wy=0;
730 int wuv=0;
731
732 for(h=0;h<height;h++)
733 {
734 wy=0;
735 wuv=0;
736 for(w=0;w<linesize;w+=4)
737 {
738 /*y00*/
739 *dst++ = py[wy + offsety];
740 /*u0*/
741 *dst++ = puv[(wuv + 1) + offsetuv];
742 /*y01*/
743 *dst++ = py[(wy + 1) + offsety];
744 /*v0*/
745 *dst++ = puv[wuv + offsetuv];
746
747 wuv+=2;
748 wy+=2;
749 }
750 dst += dw;
751 offsety += width;
752 offsetuv += width;
753
754 }
755}
756
757/*convert yuv 411 packed (y41p) to yuv 422
758* args:
759* dst: pointer to frame buffer (yuyv)
760* dstStride: stride of framebuffer
761* src: pointer to temp buffer containing y41p data frame
762* width: picture width
763* height: picture height
764*/
765void y41p_to_yuyv (uint8_t *dst,int dstStride, uint8_t *src, int width, int height)
766{
767 int h=0;
768 int w=0;
769 int linesize = width * 3 /2;
770 int offset = 0;
771 int dw = dstStride - (width << 1);
772
773 for(h=0;h<height;h++)
774 {
775 offset = linesize * h;
776 for(w=0;w<linesize;w+=12)
777 {
778 *dst++=src[w+1 + offset]; //Y0
779 *dst++=src[w + offset]; //U0
780 *dst++=src[w+3 + offset]; //Y1
781 *dst++=src[w+2 + offset]; //V0
782 *dst++=src[w+5 + offset]; //Y2
783 *dst++=src[w + offset]; //U0
784 *dst++=src[w+7 + offset]; //Y3
785 *dst++=src[w+2 + offset]; //V0
786 *dst++=src[w+8 + offset]; //Y4
787 *dst++=src[w+4 + offset]; //U4
788 *dst++=src[w+9 + offset]; //Y5
789 *dst++=src[w+6 + offset]; //V4
790 *dst++=src[w+10+ offset]; //Y6
791 *dst++=src[w+4 + offset]; //U4
792 *dst++=src[w+11+ offset]; //Y7
793 *dst++=src[w+6 + offset]; //V4
794 }
795 dst += dw;
796 }
797}
798
799/*convert yuv mono (grey) to yuv 422
800* args:
801* dst: pointer to frame buffer (yuyv)
802* dstStride: stride of framebuffer
803* src: pointer to temp buffer containing grey (y only) data frame
804* width: picture width
805* height: picture height
806*/
807void grey_to_yuyv (uint8_t *dst,int dstStride, uint8_t *src, int srcStride, int width, int height)
808{
809 int h=0;
810 int w=0;
811 int dw = dstStride - (width << 1);
812 int sw = srcStride - width;
813
814 for(h=0;h<height;h++)
815 {
816 for(w=0;w<width;w++)
817 {
818 *dst++=*src++; //Y
819 *dst++=0x80; //U or V
820 }
821 dst += dw;
822 src += sw;
823 }
824}
825
826/*convert SPCA501 (s501) to yuv 422
827* s501 |Y0..width..Y0|U..width/2..U|Y1..width..Y1|V..width/2..V|
828* signed values (-128;+127) must be converted to unsigned (0; 255)
829* args:
830* dst: pointer to frame buffer (yuyv)
831* dstStride: stride of framebuffer
832* src: pointer to temp buffer containing s501 data frame
833* width: picture width
834* height: picture height
835*/
836void s501_to_yuyv(uint8_t *dst,int dstStride, uint8_t *src, int width, int height)
837{
838 uint8_t *U, *V, *Y0, *Y1;
839 uint8_t *line2;
840 int h, w;
841 int dw = dstStride - (width << 1);
842
843 Y0 = src; /*fisrt line*/
844 for (h = 0; h < height/2; h++ )
845 {
846 line2 = dst + dstStride; /* next line */
847 U = Y0 + width;
848 Y1 = U + width / 2;
849 V = Y1 + width;
850 for (w = width / 2; --w >= 0; )
851 {
852 *dst++ = 0x80 + *Y0++;
853 *dst++ = 0x80 + *U;
854 *dst++ = 0x80 + *Y0++;
855 *dst++ = 0x80 + *V;
856
857 *line2++ = 0x80 + *Y1++;
858 *line2++ = 0x80 + *U++;
859 *line2++ = 0x80 + *Y1++;
860 *line2++ = 0x80 + *V++;
861 }
862 Y0 += width * 2; /* next block of lines */
863 dst = line2 + dw;
864 }
865}
866
867/*convert SPCA505 (s505) to yuv 422
868* s505 |Y0..width..Y0|Y1..width..Y1|U..width/2..U|V..width/2..V|
869* signed values (-128;+127) must be converted to unsigned (0; 255)
870* args:
871* dst: pointer to frame buffer (yuyv)
872* dstStride: stride of framebuffer
873* src: pointer to temp buffer containing s501 data frame
874* width: picture width
875* height: picture height
876*/
877void s505_to_yuyv(uint8_t *dst,int dstStride, uint8_t *src, int width, int height)
878{
879 uint8_t *U, *V, *Y0, *Y1;
880 uint8_t *line2;
881 int h, w;
882 int dw = dstStride - (width << 1);
883
884 Y0 = src; /*fisrt line*/
885 for (h = 0; h < height/2; h++ )
886 {
887 line2 = dst + dstStride; /* next line */
888 Y1 = Y0 + width;
889 U = Y1 + width;
890 V = U + width/2;
891 for (w = width / 2; --w >= 0; )
892 {
893 *dst++ = 0x80 + *Y0++;
894 *dst++ = 0x80 + *U;
895 *dst++ = 0x80 + *Y0++;
896 *dst++ = 0x80 + *V;
897
898 *line2++ = 0x80 + *Y1++;
899 *line2++ = 0x80 + *U++;
900 *line2++ = 0x80 + *Y1++;
901 *line2++ = 0x80 + *V++;
902 }
903 Y0 += width * 2; /* next block of lines */
904 dst = line2 + dw;
905 }
906}
907
908/*convert SPCA508 (s508) to yuv 422
909* s508 |Y0..width..Y0|U..width/2..U|V..width/2..V|Y1..width..Y1|
910* signed values (-128;+127) must be converted to unsigned (0; 255)
911* args:
912* dst: pointer to frame buffer (yuyv)
913* dstStride: stride of framebuffer
914* src: pointer to temp buffer containing s501 data frame
915* width: picture width
916* height: picture height
917*/
918void s508_to_yuyv(uint8_t *dst,int dstStride, uint8_t *src, int width, int height)
919{
920 uint8_t *U, *V, *Y0, *Y1;
921 uint8_t *line2;
922 int h, w;
923 int dw = dstStride - (width << 1);
924
925 Y0 = src; /*fisrt line*/
926 for (h = 0; h < height/2; h++ )
927 {
928 line2 = dst + dstStride; /* next line */
929 U = Y0 + width;
930 V = U + width/2;
931 Y1= V + width/2;
932 for (w = width / 2; --w >= 0; )
933 {
934 *dst++ = 0x80 + *Y0++;
935 *dst++ = 0x80 + *U;
936 *dst++ = 0x80 + *Y0++;
937 *dst++ = 0x80 + *V;
938
939 *line2++ = 0x80 + *Y1++;
940 *line2++ = 0x80 + *U++;
941 *line2++ = 0x80 + *Y1++;
942 *line2++ = 0x80 + *V++;
943 }
944 Y0 += width * 2; /* next block of lines */
945 dst = line2 + dw;
946 }
947}
948
949// raw bayer functions
950// from libv4l bayer.c, (C) 2008 Hans de Goede <j.w.r.degoede@hhs.nl>
951//Note: original bayer_to_bgr24 code from :
952// 1394-Based Digital Camera Control Library
953//
954// Bayer pattern decoding functions
955//
956// Written by Damien Douxchamps and Frederic Devernay
957static void convert_border_bayer_line_to_bgr24( uint8_t* bayer, uint8_t* adjacent_bayer,
958 uint8_t *bgr, int width, bool start_with_green, bool blue_line)
959{
960 int t0, t1;
961
962 if (start_with_green)
963 {
964 /* First pixel */
965 if (blue_line)
966 {
967 *bgr++ = bayer[1];
968 *bgr++ = bayer[0];
969 *bgr++ = adjacent_bayer[0];
970 }
971 else
972 {
973 *bgr++ = adjacent_bayer[0];
974 *bgr++ = bayer[0];
975 *bgr++ = bayer[1];
976 }
977 /* Second pixel */
978 t0 = (bayer[0] + bayer[2] + adjacent_bayer[1] + 1) / 3;
979 t1 = (adjacent_bayer[0] + adjacent_bayer[2] + 1) >> 1;
980 if (blue_line)
981 {
982 *bgr++ = bayer[1];
983 *bgr++ = t0;
984 *bgr++ = t1;
985 }
986 else
987 {
988 *bgr++ = t1;
989 *bgr++ = t0;
990 *bgr++ = bayer[1];
991 }
992 bayer++;
993 adjacent_bayer++;
994 width -= 2;
995 }
996 else
997 {
998 /* First pixel */
999 t0 = (bayer[1] + adjacent_bayer[0] + 1) >> 1;
1000 if (blue_line)
1001 {
1002 *bgr++ = bayer[0];
1003 *bgr++ = t0;
1004 *bgr++ = adjacent_bayer[1];
1005 }
1006 else
1007 {
1008 *bgr++ = adjacent_bayer[1];
1009 *bgr++ = t0;
1010 *bgr++ = bayer[0];
1011 }
1012 width--;
1013 }
1014
1015 if (blue_line)
1016 {
1017 for ( ; width > 2; width -= 2)
1018 {
1019 t0 = (bayer[0] + bayer[2] + 1) >> 1;
1020 *bgr++ = t0;
1021 *bgr++ = bayer[1];
1022 *bgr++ = adjacent_bayer[1];
1023 bayer++;
1024 adjacent_bayer++;
1025
1026 t0 = (bayer[0] + bayer[2] + adjacent_bayer[1] + 1) / 3;
1027 t1 = (adjacent_bayer[0] + adjacent_bayer[2] + 1) >> 1;
1028 *bgr++ = bayer[1];
1029 *bgr++ = t0;
1030 *bgr++ = t1;
1031 bayer++;
1032 adjacent_bayer++;
1033 }
1034 }
1035 else
1036 {
1037 for ( ; width > 2; width -= 2)
1038 {
1039 t0 = (bayer[0] + bayer[2] + 1) >> 1;
1040 *bgr++ = adjacent_bayer[1];
1041 *bgr++ = bayer[1];
1042 *bgr++ = t0;
1043 bayer++;
1044 adjacent_bayer++;
1045
1046 t0 = (bayer[0] + bayer[2] + adjacent_bayer[1] + 1) / 3;
1047 t1 = (adjacent_bayer[0] + adjacent_bayer[2] + 1) >> 1;
1048 *bgr++ = t1;
1049 *bgr++ = t0;
1050 *bgr++ = bayer[1];
1051 bayer++;
1052 adjacent_bayer++;
1053 }
1054 }
1055
1056 if (width == 2)
1057 {
1058 /* Second to last pixel */
1059 t0 = (bayer[0] + bayer[2] + 1) >> 1;
1060 if (blue_line)
1061 {
1062 *bgr++ = t0;
1063 *bgr++ = bayer[1];
1064 *bgr++ = adjacent_bayer[1];
1065 }
1066 else
1067 {
1068 *bgr++ = adjacent_bayer[1];
1069 *bgr++ = bayer[1];
1070 *bgr++ = t0;
1071 }
1072 /* Last pixel */
1073 t0 = (bayer[1] + adjacent_bayer[2] + 1) >> 1;
1074 if (blue_line)
1075 {
1076 *bgr++ = bayer[2];
1077 *bgr++ = t0;
1078 *bgr++ = adjacent_bayer[1];
1079 }
1080 else
1081 {
1082 *bgr++ = adjacent_bayer[1];
1083 *bgr++ = t0;
1084 *bgr++ = bayer[2];
1085 }
1086 }
1087 else
1088 {
1089 /* Last pixel */
1090 if (blue_line)
1091 {
1092 *bgr++ = bayer[0];
1093 *bgr++ = bayer[1];
1094 *bgr++ = adjacent_bayer[1];
1095 }
1096 else
1097 {
1098 *bgr++ = adjacent_bayer[1];
1099 *bgr++ = bayer[1];
1100 *bgr++ = bayer[0];
1101 }
1102 }
1103}
1104
1105/* From libdc1394, which on turn was based on OpenCV's Bayer decoding */
1106static void bayer_to_rgbbgr24(uint8_t *bayer, uint8_t *bgr, int width, int height, bool start_with_green, bool blue_line)
1107{
1108 /* render the first line */
1109 convert_border_bayer_line_to_bgr24(bayer, bayer + width, bgr, width,
1110 start_with_green, blue_line);
1111 bgr += width * 3;
1112
1113 /* reduce height by 2 because of the special case top/bottom line */
1114 for (height -= 2; height; height--)
1115 {
1116 int t0, t1;
1117 /* (width - 2) because of the border */
1118 uint8_t *bayerEnd = bayer + (width - 2);
1119
1120 if (start_with_green)
1121 {
1122 /* OpenCV has a bug in the next line, which was
1123 t0 = (bayer[0] + bayer[width * 2] + 1) >> 1; */
1124 t0 = (bayer[1] + bayer[width * 2 + 1] + 1) >> 1;
1125 /* Write first pixel */
1126 t1 = (bayer[0] + bayer[width * 2] + bayer[width + 1] + 1) / 3;
1127 if (blue_line)
1128 {
1129 *bgr++ = t0;
1130 *bgr++ = t1;
1131 *bgr++ = bayer[width];
1132 }
1133 else
1134 {
1135 *bgr++ = bayer[width];
1136 *bgr++ = t1;
1137 *bgr++ = t0;
1138 }
1139
1140 /* Write second pixel */
1141 t1 = (bayer[width] + bayer[width + 2] + 1) >> 1;
1142 if (blue_line)
1143 {
1144 *bgr++ = t0;
1145 *bgr++ = bayer[width + 1];
1146 *bgr++ = t1;
1147 }
1148 else
1149 {
1150 *bgr++ = t1;
1151 *bgr++ = bayer[width + 1];
1152 *bgr++ = t0;
1153 }
1154 bayer++;
1155 }
1156 else
1157 {
1158 /* Write first pixel */
1159 t0 = (bayer[0] + bayer[width * 2] + 1) >> 1;
1160 if (blue_line)
1161 {
1162 *bgr++ = t0;
1163 *bgr++ = bayer[width];
1164 *bgr++ = bayer[width + 1];
1165 }
1166 else
1167 {
1168 *bgr++ = bayer[width + 1];
1169 *bgr++ = bayer[width];
1170 *bgr++ = t0;
1171 }
1172 }
1173
1174 if (blue_line)
1175 {
1176 for (; bayer <= bayerEnd - 2; bayer += 2)
1177 {
1178 t0 = (bayer[0] + bayer[2] + bayer[width * 2] +
1179 bayer[width * 2 + 2] + 2) >> 2;
1180 t1 = (bayer[1] + bayer[width] +
1181 bayer[width + 2] + bayer[width * 2 + 1] +
1182 2) >> 2;
1183 *bgr++ = t0;
1184 *bgr++ = t1;
1185 *bgr++ = bayer[width + 1];
1186
1187 t0 = (bayer[2] + bayer[width * 2 + 2] + 1) >> 1;
1188 t1 = (bayer[width + 1] + bayer[width + 3] +
1189 1) >> 1;
1190 *bgr++ = t0;
1191 *bgr++ = bayer[width + 2];
1192 *bgr++ = t1;
1193 }
1194 }
1195 else
1196 {
1197 for (; bayer <= bayerEnd - 2; bayer += 2)
1198 {
1199 t0 = (bayer[0] + bayer[2] + bayer[width * 2] +
1200 bayer[width * 2 + 2] + 2) >> 2;
1201 t1 = (bayer[1] + bayer[width] +
1202 bayer[width + 2] + bayer[width * 2 + 1] +
1203 2) >> 2;
1204 *bgr++ = bayer[width + 1];
1205 *bgr++ = t1;
1206 *bgr++ = t0;
1207
1208 t0 = (bayer[2] + bayer[width * 2 + 2] + 1) >> 1;
1209 t1 = (bayer[width + 1] + bayer[width + 3] +
1210 1) >> 1;
1211 *bgr++ = t1;
1212 *bgr++ = bayer[width + 2];
1213 *bgr++ = t0;
1214 }
1215 }
1216
1217 if (bayer < bayerEnd)
1218 {
1219 /* write second to last pixel */
1220 t0 = (bayer[0] + bayer[2] + bayer[width * 2] +
1221 bayer[width * 2 + 2] + 2) >> 2;
1222 t1 = (bayer[1] + bayer[width] +
1223 bayer[width + 2] + bayer[width * 2 + 1] +
1224 2) >> 2;
1225 if (blue_line)
1226 {
1227 *bgr++ = t0;
1228 *bgr++ = t1;
1229 *bgr++ = bayer[width + 1];
1230 }
1231 else
1232 {
1233 *bgr++ = bayer[width + 1];
1234 *bgr++ = t1;
1235 *bgr++ = t0;
1236 }
1237 /* write last pixel */
1238 t0 = (bayer[2] + bayer[width * 2 + 2] + 1) >> 1;
1239 if (blue_line)
1240 {
1241 *bgr++ = t0;
1242 *bgr++ = bayer[width + 2];
1243 *bgr++ = bayer[width + 1];
1244 }
1245 else
1246 {
1247 *bgr++ = bayer[width + 1];
1248 *bgr++ = bayer[width + 2];
1249 *bgr++ = t0;
1250 }
1251 bayer++;
1252 }
1253 else
1254 {
1255 /* write last pixel */
1256 t0 = (bayer[0] + bayer[width * 2] + 1) >> 1;
1257 t1 = (bayer[1] + bayer[width * 2 + 1] + bayer[width] + 1) / 3;
1258 if (blue_line)
1259 {
1260 *bgr++ = t0;
1261 *bgr++ = t1;
1262 *bgr++ = bayer[width + 1];
1263 }
1264 else
1265 {
1266 *bgr++ = bayer[width + 1];
1267 *bgr++ = t1;
1268 *bgr++ = t0;
1269 }
1270 }
1271
1272 /* skip 2 border pixels */
1273 bayer += 2;
1274
1275 blue_line = !blue_line;
1276 start_with_green = !start_with_green;
1277 }
1278
1279 /* render the last line */
1280 convert_border_bayer_line_to_bgr24(bayer + width, bayer, bgr, width, !start_with_green, !blue_line);
1281}
1282
1283/*convert bayer raw data to rgb24
1284* args:
1285* pBay: pointer to buffer containing Raw bayer data data
1286* pRGB24: pointer to buffer containing rgb24 data
1287* width: picture width
1288* height: picture height
1289* pix_order: bayer pixel order (0=gb/rg 1=gr/bg 2=bg/gr 3=rg/bg)
1290*/
1291void bayer_to_rgb24(uint8_t *pBay, uint8_t *pRGB24, int width, int height, int pix_order)
1292{
1293 switch (pix_order)
1294 {
1295 //conversion functions are build for bgr, by switching b and r lines we get rgb
1296 case 0: /* gbgbgb... | rgrgrg... (V4L2_PIX_FMT_SGBRG8)*/
1297 bayer_to_rgbbgr24(pBay, pRGB24, width, height, true, false);
1298 break;
1299
1300 case 1: /* grgrgr... | bgbgbg... (V4L2_PIX_FMT_SGRBG8)*/
1301 bayer_to_rgbbgr24(pBay, pRGB24, width, height, true, true);
1302 break;
1303
1304 case 2: /* bgbgbg... | grgrgr... (V4L2_PIX_FMT_SBGGR8)*/
1305 bayer_to_rgbbgr24(pBay, pRGB24, width, height, false, false);
1306 break;
1307
1308 case 3: /* rgrgrg... ! gbgbgb... (V4L2_PIX_FMT_SRGGB8)*/
1309 bayer_to_rgbbgr24(pBay, pRGB24, width, height, false, true);
1310 break;
1311
1312 default: /* default is 0*/
1313 bayer_to_rgbbgr24(pBay, pRGB24, width, height, true, false);
1314 break;
1315 }
1316}
1317
1318
1319void rgb_to_yuyv(uint8_t *pyuv, int dstStride, uint8_t *prgb, int srcStride, int width, int height)
1320{
1321
1322 int h;
1323 int dw = dstStride - (width << 1);
1324 for (h=0;h<height;h++) {
1325 int i=0;
1326 for(i=0;i<(width*3);i=i+6)
1327 {
1328 /* y */
1329 *pyuv++ =CLIP(0.299 * (prgb[i] - 128) + 0.587 * (prgb[i+1] - 128) + 0.114 * (prgb[i+2] - 128) + 128);
1330 /* u */
1331 *pyuv++ =CLIP(((- 0.147 * (prgb[i] - 128) - 0.289 * (prgb[i+1] - 128) + 0.436 * (prgb[i+2] - 128) + 128) +
1332 (- 0.147 * (prgb[i+3] - 128) - 0.289 * (prgb[i+4] - 128) + 0.436 * (prgb[i+5] - 128) + 128))/2);
1333 /* y1 */
1334 *pyuv++ =CLIP(0.299 * (prgb[i+3] - 128) + 0.587 * (prgb[i+4] - 128) + 0.114 * (prgb[i+5] - 128) + 128);
1335 /* v*/
1336 *pyuv++ =CLIP(((0.615 * (prgb[i] - 128) - 0.515 * (prgb[i+1] - 128) - 0.100 * (prgb[i+2] - 128) + 128) +
1337 (0.615 * (prgb[i+3] - 128) - 0.515 * (prgb[i+4] - 128) - 0.100 * (prgb[i+5] - 128) + 128))/2);
1338 }
1339 pyuv += dw;
1340 prgb += srcStride;
1341 }
1342}
1343
1344void bgr_to_yuyv(uint8_t *pyuv, int dstStride, uint8_t *pbgr, int srcStride, int width, int height)
1345{
1346 int h;
1347 int dw = dstStride - (width << 1);
1348 for (h=0;h<height;h++) {
1349 int i=0;
1350 for(i=0;i<(width*3);i=i+6)
1351 {
1352 /* y */
1353 *pyuv++ =CLIP(0.299 * (pbgr[i+2] - 128) + 0.587 * (pbgr[i+1] - 128) + 0.114 * (pbgr[i] - 128) + 128);
1354 /* u */
1355 *pyuv++ =CLIP(((- 0.147 * (pbgr[i+2] - 128) - 0.289 * (pbgr[i+1] - 128) + 0.436 * (pbgr[i] - 128) + 128) +
1356 (- 0.147 * (pbgr[i+5] - 128) - 0.289 * (pbgr[i+4] - 128) + 0.436 * (pbgr[i+3] - 128) + 128))/2);
1357 /* y1 */
1358 *pyuv++ =CLIP(0.299 * (pbgr[i+5] - 128) + 0.587 * (pbgr[i+4] - 128) + 0.114 * (pbgr[i+3] - 128) + 128);
1359 /* v*/
1360 *pyuv++ =CLIP(((0.615 * (pbgr[i+2] - 128) - 0.515 * (pbgr[i+1] - 128) - 0.100 * (pbgr[i] - 128) + 128) +
1361 (0.615 * (pbgr[i+5] - 128) - 0.515 * (pbgr[i+4] - 128) - 0.100 * (pbgr[i+3] - 128) + 128))/2);
1362 }
1363 pyuv += dw;
1364 pbgr += srcStride;
1365 }
1366}
1367
1368//--------------------------------------------------------------------------------------
1369
1370/*------------------------------- Color space conversions --------------------*/
1371
1372
1373/* rrrr rggg gggb bbbb */
1374
1375static inline uint16_t make565(int red, int green, int blue)
1376{
1377 return (uint16_t)( ((red << 8) & 0xf800) |
1378 ((green << 3) & 0x07e0) |
1379 ((blue >> 3) & 0x001f) );
1380}
1381
1382#define FIX1P8(x) ((int)((x) * (1<<8)))
1383
1384static inline int clip(int x)
1385{
1386 if (x > 255)
1387 x = 255;
1388 if (x < 0)
1389 x = 0;
1390 return x;
1391}
1392
1393
1394void yuyv_to_rgb565_line (uint8_t *pyuv, uint8_t *prgb, int width)
1395{
1396 int l=0;
1397 int ln = width >> 1;
1398 uint16_t *p = (uint16_t *)prgb;
1399
1400 for(l=0; l<ln; l++)
1401 { /*iterate every 4 bytes*/
1402
1403 int u = pyuv[1] - 128;
1404 int v = pyuv[3] - 128;
1405
1406 int ri = ( + FIX1P8(1.402) * v) >> 8;
1407 int gi = ( - FIX1P8(0.34414) * u - FIX1P8(0.71414) * v) >> 8;
1408 int bi = ( + FIX1P8(1.772) * u ) >> 8;
1409
1410 /* standart: r = y0 + 1.402 (v-128) */
1411 /* logitech: r = y0 + 1.370705 (v-128) */
1412 /* standart: g = y0 - 0.34414 (u-128) - 0.71414 (v-128)*/
1413 /* logitech: g = y0 - 0.337633 (u-128)- 0.698001 (v-128)*/
1414 /* standart: b = y0 + 1.772 (u-128) */
1415 /* logitech: b = y0 + 1.732446 (u-128) */
1416
1417 int y0 = pyuv[0];
1418 *p++ = make565(
1419 clip(y0 + ri),
1420 clip(y0 + gi),
1421 clip(y0 + bi)
1422 );
1423
1424 int y1 = pyuv[2];
1425 *p++ = make565(
1426 clip(y1 + ri),
1427 clip(y1 + gi),
1428 clip(y1 + bi)
1429 );
1430
1431 pyuv += 4;
1432 }
1433}
1434
1435/* regular yuv (YUYV) to rgb565*/
1436void yuyv_to_rgb565 (uint8_t *pyuv, int pyuvstride, uint8_t *prgb,int prgbstride, int width, int height)
1437{
1438 int h=0;
1439 for(h=0;h<height;h++)
1440 {
1441 yuyv_to_rgb565_line (pyuv,prgb,width);
1442 pyuv += pyuvstride;
1443 prgb += prgbstride;
1444 }
1445}
1446
1447
1448void yuyv_to_rgb24_line (uint8_t *pyuv, uint8_t *prgb, int width)
1449{
1450 int l=0;
1451 int ln = width >> 1;
1452
1453 for(l=0; l<ln; l++)
1454 { /*iterate every 4 bytes*/
1455
1456 int u = pyuv[1] - 128;
1457 int v = pyuv[3] - 128;
1458
1459 int ri = ( + FIX1P8(1.402) * v) >> 8;
1460 int gi = ( - FIX1P8(0.34414) * u - FIX1P8(0.71414) * v) >> 8;
1461 int bi = ( + FIX1P8(1.772) * u ) >> 8;
1462
1463 /* standart: r = y0 + 1.402 (v-128) */
1464 /* logitech: r = y0 + 1.370705 (v-128) */
1465 /* standart: g = y0 - 0.34414 (u-128) - 0.71414 (v-128)*/
1466 /* logitech: g = y0 - 0.337633 (u-128)- 0.698001 (v-128)*/
1467 /* standart: b = y0 + 1.772 (u-128) */
1468 /* logitech: b = y0 + 1.732446 (u-128) */
1469
1470 int y0 = pyuv[0];
1471 *prgb++ = clip(y0 + ri);
1472 *prgb++ = clip(y0 + gi);
1473 *prgb++ = clip(y0 + bi);
1474
1475 int y1 = pyuv[2];
1476 *prgb++ = clip(y1 + ri);
1477 *prgb++ = clip(y1 + gi);
1478 *prgb++ = clip(y1 + bi);
1479
1480 pyuv += 4;
1481 }
1482}
1483
1484/* regular yuv (YUYV) to rgb24*/
1485void yuyv_to_rgb24 (uint8_t *pyuv, int pyuvstride, uint8_t *prgb,int prgbstride, int width, int height)
1486{
1487 int h=0;
1488 for(h=0;h<height;h++)
1489 {
1490 yuyv_to_rgb24_line (pyuv,prgb,width);
1491 pyuv += pyuvstride;
1492 prgb += prgbstride;
1493 }
1494}
1495
1496void yuyv_to_rgb32_line (uint8_t *pyuv, uint8_t *prgb, int width)
1497{
1498 int l=0;
1499 int ln = width >> 1;
1500
1501 for(l=0; l<ln; l++)
1502 { /*iterate every 4 bytes*/
1503
1504 int u = pyuv[1] - 128;
1505 int v = pyuv[3] - 128;
1506
1507 int ri = ( + FIX1P8(1.402) * v) >> 8;
1508 int gi = ( - FIX1P8(0.34414) * u - FIX1P8(0.71414) * v) >> 8;
1509 int bi = ( + FIX1P8(1.772) * u ) >> 8;
1510
1511 /* standart: r = y0 + 1.402 (v-128) */
1512 /* logitech: r = y0 + 1.370705 (v-128) */
1513 /* standart: g = y0 - 0.34414 (u-128) - 0.71414 (v-128)*/
1514 /* logitech: g = y0 - 0.337633 (u-128)- 0.698001 (v-128)*/
1515 /* standart: b = y0 + 1.772 (u-128) */
1516 /* logitech: b = y0 + 1.732446 (u-128) */
1517
1518 int y0 = pyuv[0];
1519 *prgb++ = clip(y0 + ri);
1520 *prgb++ = clip(y0 + gi);
1521 *prgb++ = clip(y0 + bi);
1522 prgb++;
1523
1524 int y1 = pyuv[2];
1525 *prgb++ = clip(y1 + ri);
1526 *prgb++ = clip(y1 + gi);
1527 *prgb++ = clip(y1 + bi);
1528 prgb++;
1529
1530 pyuv += 4;
1531 }
1532}
1533
1534/* regular yuv (YUYV) to rgb32*/
1535void yuyv_to_rgb32 (uint8_t *pyuv, int pyuvstride, uint8_t *prgb,int prgbstride, int width, int height)
1536{
1537 int h=0;
1538 for(h=0;h<height;h++)
1539 {
1540 yuyv_to_rgb32_line (pyuv,prgb,width);
1541 pyuv += pyuvstride;
1542 prgb += prgbstride;
1543 }
1544}
1545
1546void yuyv_to_bgr24_line (uint8_t *pyuv, uint8_t *pbgr, int width)
1547{
1548 int l=0;
1549 int ln = width >> 1;
1550 for(l=0;l<ln;l++)
1551 { /*iterate every 4 bytes*/
1552 int u = pyuv[1] - 128;
1553 int v = pyuv[3] - 128;
1554
1555 int ri = ( + FIX1P8(1.402) * v) >> 8;
1556 int gi = ( - FIX1P8(0.34414) * u - FIX1P8(0.71414) * v) >> 8;
1557 int bi = ( + FIX1P8(1.772) * u ) >> 8;
1558
1559 /* standart: r = y0 + 1.402 (v-128) */
1560 /* logitech: r = y0 + 1.370705 (v-128) */
1561 /* standart: g = y0 - 0.34414 (u-128) - 0.71414 (v-128)*/
1562 /* logitech: g = y0 - 0.337633 (u-128)- 0.698001 (v-128)*/
1563 /* standart: b = y0 + 1.772 (u-128) */
1564 /* logitech: b = y0 + 1.732446 (u-128) */
1565
1566 int y0 = pyuv[0];
1567 *pbgr++ = clip(y0 + ri);
1568 *pbgr++ = clip(y0 + gi);
1569 *pbgr++ = clip(y0 + bi);
1570 pbgr++;
1571
1572 int y1 = pyuv[2];
1573 *pbgr++ = clip(y1 + ri);
1574 *pbgr++ = clip(y1 + gi);
1575 *pbgr++ = clip(y1 + bi);
1576 pbgr++;
1577
1578 pyuv += 4;
1579 }
1580}
1581
1582/* used for rgb video (fourcc="RGB ") */
1583/* lines are on correct order */
1584void yuyv_to_bgr24 (uint8_t *pyuv, int pyuvstride, uint8_t *pbgr, int pbgrstride, int width, int height)
1585{
1586 int h=0;
1587 for(h=0;h<height;h++)
1588 {
1589 yuyv_to_bgr24_line (pyuv,pbgr,width);
1590 pyuv += pyuvstride;
1591 pbgr += pbgrstride;
1592 }
1593}
1594
1595void yuyv_to_bgr32_line (uint8_t *pyuv, uint8_t *pbgr, int width)
1596{
1597 int l=0;
1598 int ln = width >> 1;
1599 for(l=0;l<ln;l++)
1600 { /*iterate every 4 bytes*/
1601 int u = pyuv[1] - 128;
1602 int v = pyuv[3] - 128;
1603
1604 int ri = ( + FIX1P8(1.402) * v) >> 8;
1605 int gi = ( - FIX1P8(0.34414) * u - FIX1P8(0.71414) * v) >> 8;
1606 int bi = ( + FIX1P8(1.772) * u ) >> 8;
1607
1608 /* standart: r = y0 + 1.402 (v-128) */
1609 /* logitech: r = y0 + 1.370705 (v-128) */
1610 /* standart: g = y0 - 0.34414 (u-128) - 0.71414 (v-128)*/
1611 /* logitech: g = y0 - 0.337633 (u-128)- 0.698001 (v-128)*/
1612 /* standart: b = y0 + 1.772 (u-128) */
1613 /* logitech: b = y0 + 1.732446 (u-128) */
1614
1615 int y0 = pyuv[0];
1616 *pbgr++ = clip(y0 + ri);
1617 *pbgr++ = clip(y0 + gi);
1618 *pbgr++ = clip(y0 + bi);
1619 pbgr++;
1620
1621 int y1 = pyuv[2];
1622 *pbgr++ = clip(y1 + ri);
1623 *pbgr++ = clip(y1 + gi);
1624 *pbgr++ = clip(y1 + bi);
1625 pbgr++;
1626
1627 pyuv += 4;
1628 }
1629}
1630
1631/* used for rgb video (fourcc="RGB ") */
1632/* lines are on correct order */
1633void yuyv_to_bgr32 (uint8_t *pyuv, int pyuvstride, uint8_t *pbgr, int pbgrstride, int width, int height)
1634{
1635 int h=0;
1636 for(h=0;h<height;h++)
1637 {
1638 yuyv_to_bgr32_line (pyuv,pbgr,width);
1639 pyuv += pyuvstride;
1640 pbgr += pbgrstride;
1641 }
1642}
1643
1644/* This a custom destination manager for jpeglib that
1645 enables the use of memory to memory compression.
1646 See IJG documentation for details.
1647*/
1648typedef struct {
1649 struct jpeg_destination_mgr pub; /* base class */
1650 JOCTET* buffer; /* buffer start address */
1651 size_t bufsize;
1652 size_t datasize; /* final size of compressed data */
1653 int overflowed;
1654} memory_destination_mgr;
1655typedef memory_destination_mgr* mem_dest_ptr;
1656
1657
1658/* This function is called by the library before any data gets written */
1659METHODDEF(void) init_destination (j_compress_ptr cinfo)
1660{
1661 mem_dest_ptr dest = (mem_dest_ptr)cinfo->dest;
1662
1663 dest->pub.next_output_byte = dest->buffer; /* set destination buffer */
1664 dest->pub.free_in_buffer = dest->bufsize; /* input buffer size */
1665 dest->datasize = 0; /* reset output size */
1666}
1667
1668/* This function is called by the library if the buffer fills up */
1669METHODDEF(boolean) empty_output_buffer (j_compress_ptr cinfo)
1670{
1671 mem_dest_ptr dest = (mem_dest_ptr)cinfo->dest;
1672
1673 // Reinit to the start. Better than crashing
1674 dest->pub.next_output_byte = (JOCTET*)dest->buffer;
1675 dest->pub.free_in_buffer = dest->bufsize;
1676 dest->overflowed = 1;
1677
1678 return TRUE;
1679}
1680
1681/* Usually the library wants to flush output here.
1682 I will calculate output buffer size here. */
1683
1684METHODDEF(void) term_destination (j_compress_ptr cinfo)
1685{
1686 mem_dest_ptr dest = (mem_dest_ptr)cinfo->dest;
1687 dest->datasize = dest->bufsize - dest->pub.free_in_buffer;
1688}
1689
1690/* Override the default destination manager initialization
1691 provided by jpeglib. Since we want to use memory-to-memory
1692 compression, we need to use our own destination manager.
1693*/
1694static GLOBAL(void) jpeg_memory_dest (j_compress_ptr cinfo,void* buf,int sz)
1695{
1696 mem_dest_ptr dest;
1697
1698 /* first call for this instance - need to setup */
1699 if (cinfo->dest == 0) {
1700 cinfo->dest = (struct jpeg_destination_mgr *)
1701 (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT,
1702 sizeof (memory_destination_mgr));
1703 }
1704
1705 dest = (mem_dest_ptr) cinfo->dest;
1706 dest->bufsize = sz;
1707 dest->buffer = (JOCTET*)buf;
1708 dest->datasize = 0;
1709
1710 /* set method callbacks */
1711 dest->pub.init_destination = init_destination;
1712 dest->pub.empty_output_buffer = empty_output_buffer;
1713 dest->pub.term_destination = term_destination;
1714}
1715
1716
1717/* yuyv_to_jpeg
1718 * converts an input image in the YUYV format into a jpeg image and puts
1719 * it in a memory buffer.
1720 */
1721int yuyv_to_jpeg(uint8_t* src, uint8_t* dst, int maxsize, int width, int height,int stride,int quality)
1722{
1723 // Round height to a multiple of 16:
1724 height &= (-16);
1725
1726 // Round width to a multiple of 16
1727 width &= (-16);
1728
1729 // Calculate deltaStride
1730 int dstride = stride - (width << 1);
1731
1732 int i, j;
1733
1734 JSAMPROW y[16],cb[8],cr[8];
1735 JSAMPARRAY data[3];
1736
1737 struct jpeg_compress_struct cinfo;
1738 struct jpeg_error_mgr jerr;
1739
1740 // Allocate memory for line buffers
1741 y[0] = (JSAMPROW) malloc(sizeof(JSAMPLE) * width * 16);
1742 cb[0] = (JSAMPROW) malloc(sizeof(JSAMPLE) * (width >> 1) * 8);
1743 cr[0] = (JSAMPROW) malloc(sizeof(JSAMPLE) * (width >> 1) * 8);
1744
1745 for (i = 1; i< 16; i++) {
1746 y[i] = y[0] + (i*(sizeof(JSAMPLE) * width));
1747 }
1748 for (i = 1; i< 8; i++) {
1749 cb[i] = cb[0] + (i*(sizeof(JSAMPLE) * (width >> 1)));
1750 cr[i] = cr[0] + (i*(sizeof(JSAMPLE) * (width >> 1)));
1751 }
1752
1753 data[0] = y;
1754 data[1] = cb;
1755 data[2] = cr;
1756
1757 cinfo.err = jpeg_std_error(&jerr); // errors get written to stderr
1758
1759 jpeg_create_compress(&cinfo);
1760 cinfo.image_width = width;
1761 cinfo.image_height = height;
1762 cinfo.input_components = 3;
1763 jpeg_set_defaults (&cinfo);
1764
1765 jpeg_set_colorspace(&cinfo, JCS_YCbCr);
1766
1767 cinfo.raw_data_in = TRUE; // supply downsampled data
1768 cinfo.comp_info[0].h_samp_factor = 2;
1769 cinfo.comp_info[0].v_samp_factor = 2;
1770 cinfo.comp_info[1].h_samp_factor = 1;
1771 cinfo.comp_info[1].v_samp_factor = 1;
1772 cinfo.comp_info[2].h_samp_factor = 1;
1773 cinfo.comp_info[2].v_samp_factor = 1;
1774
1775 jpeg_set_quality(&cinfo, quality, TRUE);
1776 cinfo.dct_method = JDCT_FASTEST;
1777
1778 jpeg_memory_dest(&cinfo,dst,maxsize); // data written to mem
1779
1780 jpeg_start_compress (&cinfo, TRUE);
1781
1782 uint8_t* yuyv = src;
1783
1784 for (j=0; j<height; j+=16) {
1785
1786 JSAMPROW pcb = cb[0];
1787 JSAMPROW pcr = cr[0];
1788 JSAMPROW py = y[0];
1789 for (i=0; i<8; i++) {
1790
1791 int x;
1792 for (x = 0; x < (width>>1); x++) {
1793 *py++ = *yuyv++; // Y0
1794 *pcb++ = (yuyv[0] + yuyv[stride]) >> 1; // U
1795 yuyv++;
1796 *py++ = *yuyv++; // Y1
1797 *pcr++ = (yuyv[0] + yuyv[stride]) >> 1; // V
1798 yuyv++;
1799 }
1800 yuyv += dstride;
1801 for (x = 0; x < (width>>1); x++) {
1802 *py++ = *yuyv++; // Y2
1803 yuyv++;
1804 *py++ = *yuyv++; // Y3
1805 yuyv++;
1806 }
1807 yuyv += dstride;
1808 }
1809 jpeg_write_raw_data(&cinfo, data, 8*2);
1810 }
1811
1812 jpeg_finish_compress(&cinfo);
1813
1814 // Release memory for line buffers
1815 free(y[0]);
1816 free(cb[0]);
1817 free(cr[0]);
1818
1819 // Create a buffer with the compressed data
1820 int fileSize = ((mem_dest_ptr)cinfo.dest)->datasize;
1821
1822 // Destroy compressor context
1823 jpeg_destroy_compress(&cinfo);
1824
1825 return fileSize;
1826}