wined3d: Filter out some shader compilation spam.
[wine] / dlls / qcap / yuv.c
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 <stdarg.h>
25
26 #include "windef.h"
27 #include "objbase.h"
28 #include "strmif.h"
29 #include "qcap_main.h"
30 #include "wine/debug.h"
31
32 WINE_DEFAULT_DEBUG_CHANNEL(qcap);
33
34 static int yuv_xy[256]; /* Gray value */
35 static int yuv_gu[256]; /* Green U */
36 static int yuv_bu[256]; /* Blue  U */
37 static int yuv_rv[256]; /* Red   V */
38 static int yuv_gv[256]; /* Green V */
39 static int initialised = 0;
40
41 static inline int ValidRange(int in) {
42    if (in > 255) in = 255;
43    if (in < 0) in = 0;
44    return in;
45 }
46
47 typedef struct RGB {
48 #if 0 /* For some reason I have to revert R and B, not sure why */
49   unsigned char r, g, b;
50 #else
51   unsigned char b, g, r;
52 #endif
53 } RGB;
54
55 static inline void YUV2RGB(const unsigned char y_, const unsigned char cb, const unsigned char cr, RGB* retval) {
56    retval->r = ValidRange(yuv_xy[y_] + yuv_rv[cr]);
57    retval->g = ValidRange(yuv_xy[y_] + yuv_gu[cb] + yuv_gv[cr]);
58    retval->b = ValidRange(yuv_xy[y_] + yuv_bu[cb]);
59 }
60
61 void YUV_Init(void) {
62    float y, u, v;
63    int y_, cb, cr;
64
65    if (initialised++) return;
66
67    for (y_ = 0; y_ <= 255; y_++)
68    {
69       y = ((float) 255 / 219) * (y_ - 16);
70       yuv_xy[y_] = ValidRange((int) (y));
71    }
72
73    for (cb = 0; cb <= 255; cb++)
74    {
75       u = ((float) 255 / 224) * (cb - 128);
76       yuv_gu[cb] = - ValidRange((int) (0.344 * u));
77       yuv_bu[cb] =   ValidRange((int) (1.772 * u));
78    }
79
80    for (cr = 0; cr <= 255; cr++)
81    {
82       v = ((float) 255 / 224) * (cr - 128);
83       yuv_rv[cr] =   ValidRange((int) (1.402 * v));
84       yuv_gv[cr] = - ValidRange((int) (0.714 * v));
85    }
86    TRACE("Filled hash table\n");
87 }
88
89 static void Parse_YUYV(unsigned char *destbuffer, const unsigned char *input, int width, int height)
90 {
91    const unsigned char *pY, *pCb, *pCr;
92    int togo = width * height / 2;
93    pY = input;
94    pCb = input+1;
95    pCr = input+3;
96    while (--togo) {
97       YUV2RGB(*pY, *pCb, *pCr, (RGB *)destbuffer);
98       pY += 2; destbuffer += 3;
99       YUV2RGB(*pY, *pCb, *pCr, (RGB *)destbuffer);
100       pY += 2; pCb += 4; pCr += 4; destbuffer += 3;
101    }
102 }
103
104 static void Parse_UYVY(unsigned char *destbuffer, const unsigned char *input, int width, int height)
105 {
106    const unsigned char *pY, *pCb, *pCr;
107    int togo = width * height / 2;
108    pY = input+1;
109    pCb = input;
110    pCr = input+2;
111    while (--togo) {
112       YUV2RGB(*pY, *pCb, *pCr, (RGB *)destbuffer);
113       pY += 2; destbuffer += 3;
114       YUV2RGB(*pY, *pCb, *pCr, (RGB *)destbuffer);
115       pY += 2; pCb += 4; pCr += 4; destbuffer += 3;
116    }
117 }
118
119 static void Parse_UYYVYY(unsigned char *destbuffer, const unsigned char *input, int width, int height)
120 {
121    const unsigned char *pY, *pCb, *pCr;
122    int togo = width * height / 4;
123    pY = input+1;
124    pCb = input;
125    pCr = input+4;
126    while (--togo) {
127       YUV2RGB(*pY, *pCb, *pCr, (RGB *)destbuffer);
128       destbuffer += 3; pY++;
129       YUV2RGB(*pY, *pCb, *pCr, (RGB *)destbuffer);
130       pY += 2; destbuffer += 3;
131       YUV2RGB(*pY, *pCb, *pCr, (RGB *)destbuffer);
132       destbuffer += 3; pY++;
133       YUV2RGB(*pY, *pCb, *pCr, (RGB *)destbuffer);
134       pY += 2; pCb += 6; pCr += 6; destbuffer += 3;
135    }
136 }
137
138 static void Parse_PYUV(unsigned char *destbuffer, const unsigned char *input, int width, int height, int wstep, int hstep)
139 {
140    /* We have 3 pointers, One to Y, one to Cb and 1 to Cr */
141
142 /* C19 *89* declaration block (Grr julliard for not allowing C99) */
143    int uvjump, ysize, uvsize;
144    const unsigned char *pY, *pCb, *pCr;
145    int swstep = 0, shstep = 0;
146    int ypos = 0, xpos = 0;
147    int indexUV = 0, cUv;
148 /* End of Grr */
149
150    uvjump = width / wstep;
151    ysize = width * height;
152    uvsize = (width / wstep) * (height / hstep);
153    pY = input;
154    pCb = pY + ysize;
155    pCr = pCb + uvsize;
156    /* Bottom down DIB */
157    do {
158       swstep = 0;
159       cUv = indexUV;
160       for (xpos = 0; xpos < width; xpos++) {
161          YUV2RGB(*(pY++), pCb[cUv], pCr[cUv], (RGB *)destbuffer);
162          destbuffer += 3;
163          if (++swstep == wstep) {
164             cUv++;
165             swstep = 0;
166          }
167       }
168       if (++shstep == hstep) {
169          shstep = 0;
170          indexUV = cUv;
171       }
172    } while (++ypos < height);
173 }
174
175 void YUV_To_RGB24(enum YUV_Format format, unsigned char *target, const unsigned char *source, int width, int height) {
176    int wstep, hstep;
177    if (format < ENDPLANAR) {
178       switch (format) {
179          case YUVP_421: wstep = 2; hstep = 1; break;
180          case YUVP_422: wstep = 2; hstep = 2; break;
181          case YUVP_441: wstep = 4; hstep = 1; break;
182          case YUVP_444: wstep = 4; hstep = 4; break;
183          default: ERR("Unhandled format \"%d\"\n", format); return;
184       }
185       Parse_PYUV(target, source, width, height, wstep, hstep);
186    } else {
187       switch (format) {
188          case YUYV: Parse_YUYV(target, source, width, height); return;
189          case UYVY: Parse_UYVY(target, source, width, height); return;
190          case UYYVYY: Parse_UYYVYY(target, source, width, height); return;
191          default: ERR("Unhandled format \"%d\"\n", format); return;
192       }
193    }
194 }