xref: /reactos/dll/directx/wine/qcap/yuv.c (revision 53221834)
1 /* DirectShow capture services (QCAP.DLL)
2  *
3  * Copyright 2005 Maarten Lankhorst
4  *
5  * This file contains the part of the vfw capture interface that
6  * does the actual Video4Linux(1/2) stuff required for capturing
7  * and setting/getting media format..
8  *
9  * This library is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU Lesser General Public
11  * License as published by the Free Software Foundation; either
12  * version 2.1 of the License, or (at your option) any later version.
13  *
14  * This library is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17  * Lesser General Public License for more details.
18  *
19  * You should have received a copy of the GNU Lesser General Public
20  * License along with this library; if not, write to the Free Software
21  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
22  */
23 
24 #include "config.h"
25 #include <stdarg.h>
26 
27 #include "windef.h"
28 #include "wingdi.h"
29 #include "objbase.h"
30 #include "strmif.h"
31 #include "qcap_main.h"
32 #include "wine/debug.h"
33 
34 /* This is not used if V4L support is missing */
35 #if defined(HAVE_LINUX_VIDEODEV_H) || defined(HAVE_LIBV4L1_H)
36 
37 WINE_DEFAULT_DEBUG_CHANNEL(qcap);
38 
39 static int yuv_xy[256]; /* Gray value */
40 static int yuv_gu[256]; /* Green U */
41 static int yuv_bu[256]; /* Blue  U */
42 static int yuv_rv[256]; /* Red   V */
43 static int yuv_gv[256]; /* Green V */
44 static BOOL initialised = FALSE;
45 
46 static inline int ValidRange(int in) {
47    if (in > 255) in = 255;
48    if (in < 0) in = 0;
49    return in;
50 }
51 
52 typedef struct RGB {
53 #if 0 /* For some reason I have to revert R and B, not sure why */
54   unsigned char r, g, b;
55 #else
56   unsigned char b, g, r;
57 #endif
58 } RGB;
59 
60 static inline void YUV2RGB(const unsigned char y_, const unsigned char cb, const unsigned char cr, RGB* retval) {
61    retval->r = ValidRange(yuv_xy[y_] + yuv_rv[cr]);
62    retval->g = ValidRange(yuv_xy[y_] + yuv_gu[cb] + yuv_gv[cr]);
63    retval->b = ValidRange(yuv_xy[y_] + yuv_bu[cb]);
64 }
65 
66 void YUV_Init(void) {
67    float y, u, v;
68    int y_, cb, cr;
69 
70    if (initialised) return;
71    initialised = TRUE;
72 
73    for (y_ = 0; y_ <= 255; y_++)
74    {
75       y = ((float) 255 / 219) * (y_ - 16);
76       yuv_xy[y_] = y;
77    }
78 
79    for (cb = 0; cb <= 255; cb++)
80    {
81       u = ((float) 255 / 224) * (cb - 128);
82       yuv_gu[cb] = -0.344 * u;
83       yuv_bu[cb] =  1.772 * u;
84    }
85 
86    for (cr = 0; cr <= 255; cr++)
87    {
88       v = ((float) 255 / 224) * (cr - 128);
89       yuv_rv[cr] =  1.402 * v;
90       yuv_gv[cr] = -0.714 * v;
91    }
92    TRACE("Filled hash table\n");
93 }
94 
95 static void Parse_YUYV(unsigned char *destbuffer, const unsigned char *input, int width, int height)
96 {
97    const unsigned char *pY, *pCb, *pCr;
98    int togo = width * height / 2;
99    pY = input;
100    pCb = input+1;
101    pCr = input+3;
102    while (--togo) {
103       YUV2RGB(*pY, *pCb, *pCr, (RGB *)destbuffer);
104       pY += 2; destbuffer += 3;
105       YUV2RGB(*pY, *pCb, *pCr, (RGB *)destbuffer);
106       pY += 2; pCb += 4; pCr += 4; destbuffer += 3;
107    }
108 }
109 
110 static void Parse_UYVY(unsigned char *destbuffer, const unsigned char *input, int width, int height)
111 {
112    const unsigned char *pY, *pCb, *pCr;
113    int togo = width * height / 2;
114    pY = input+1;
115    pCb = input;
116    pCr = input+2;
117    while (--togo) {
118       YUV2RGB(*pY, *pCb, *pCr, (RGB *)destbuffer);
119       pY += 2; destbuffer += 3;
120       YUV2RGB(*pY, *pCb, *pCr, (RGB *)destbuffer);
121       pY += 2; pCb += 4; pCr += 4; destbuffer += 3;
122    }
123 }
124 
125 static void Parse_UYYVYY(unsigned char *destbuffer, const unsigned char *input, int width, int height)
126 {
127    const unsigned char *pY, *pCb, *pCr;
128    int togo = width * height / 4;
129    pY = input+1;
130    pCb = input;
131    pCr = input+4;
132    while (--togo) {
133       YUV2RGB(*pY, *pCb, *pCr, (RGB *)destbuffer);
134       destbuffer += 3; pY++;
135       YUV2RGB(*pY, *pCb, *pCr, (RGB *)destbuffer);
136       pY += 2; destbuffer += 3;
137       YUV2RGB(*pY, *pCb, *pCr, (RGB *)destbuffer);
138       destbuffer += 3; pY++;
139       YUV2RGB(*pY, *pCb, *pCr, (RGB *)destbuffer);
140       pY += 2; pCb += 6; pCr += 6; destbuffer += 3;
141    }
142 }
143 
144 static void Parse_PYUV(unsigned char *destbuffer, const unsigned char *input, int width, int height, int wstep, int hstep)
145 {
146    /* We have 3 pointers, One to Y, one to Cb and 1 to Cr */
147 
148 /* C19 *89* declaration block (Grr julliard for not allowing C99) */
149    int ysize, uvsize;
150    const unsigned char *pY, *pCb, *pCr;
151    int swstep = 0, shstep = 0;
152    int ypos = 0, xpos = 0;
153    int indexUV = 0, cUv;
154 /* End of Grr */
155 
156    ysize = width * height;
157    uvsize = (width / wstep) * (height / hstep);
158    pY = input;
159    pCb = pY + ysize;
160    pCr = pCb + uvsize;
161    /* Bottom down DIB */
162    do {
163       swstep = 0;
164       cUv = indexUV;
165       for (xpos = 0; xpos < width; xpos++) {
166          YUV2RGB(*(pY++), pCb[cUv], pCr[cUv], (RGB *)destbuffer);
167          destbuffer += 3;
168          if (++swstep == wstep) {
169             cUv++;
170             swstep = 0;
171          }
172       }
173       if (++shstep == hstep) {
174          shstep = 0;
175          indexUV = cUv;
176       }
177    } while (++ypos < height);
178 }
179 
180 void YUV_To_RGB24(enum YUV_Format format, unsigned char *target, const unsigned char *source, int width, int height) {
181    int wstep, hstep;
182    if (format < ENDPLANAR) {
183       switch (format) {
184          case YUVP_421: wstep = 2; hstep = 1; break;
185          case YUVP_422: wstep = 2; hstep = 2; break;
186          case YUVP_441: wstep = 4; hstep = 1; break;
187          case YUVP_444: wstep = 4; hstep = 4; break;
188          default: ERR("Unhandled format \"%d\"\n", format); return;
189       }
190       Parse_PYUV(target, source, width, height, wstep, hstep);
191    } else {
192       switch (format) {
193          case YUYV: Parse_YUYV(target, source, width, height); return;
194          case UYVY: Parse_UYVY(target, source, width, height); return;
195          case UYYVYY: Parse_UYYVYY(target, source, width, height); return;
196          default: ERR("Unhandled format \"%d\"\n", format); return;
197       }
198    }
199 }
200 #endif
201