1 /* DirectShow capture services (QCAP.DLL)
3 * Copyright 2005 Maarten Lankhorst
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..
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.
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.
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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
30 #include "qcap_main.h"
31 #include "wine/debug.h"
33 WINE_DEFAULT_DEBUG_CHANNEL(qcap
);
35 static int yuv_xy
[256]; /* Gray value */
36 static int yuv_gu
[256]; /* Green U */
37 static int yuv_bu
[256]; /* Blue U */
38 static int yuv_rv
[256]; /* Red V */
39 static int yuv_gv
[256]; /* Green V */
40 static int initialised
= 0;
42 static inline int ValidRange(int in
) {
43 if (in
> 255) in
= 255;
49 #if 0 /* For some reason I have to revert R and B, not sure why */
50 unsigned char r
, g
, b
;
52 unsigned char b
, g
, r
;
56 static inline void YUV2RGB(const unsigned char y_
, const unsigned char cb
, const unsigned char cr
, RGB
* retval
) {
57 retval
->r
= ValidRange(yuv_xy
[y_
] + yuv_rv
[cr
]);
58 retval
->g
= ValidRange(yuv_xy
[y_
] + yuv_gu
[cb
] + yuv_gv
[cr
]);
59 retval
->b
= ValidRange(yuv_xy
[y_
] + yuv_bu
[cb
]);
66 if (initialised
++) return;
68 for (y_
= 0; y_
<= 255; y_
++)
70 y
= ((float) 255 / 219) * (y_
- 16);
71 yuv_xy
[y_
] = ValidRange((int) (y
));
74 for (cb
= 0; cb
<= 255; cb
++)
76 u
= ((float) 255 / 224) * (cb
- 128);
77 yuv_gu
[cb
] = - ValidRange((int) (0.344 * u
));
78 yuv_bu
[cb
] = ValidRange((int) (1.772 * u
));
81 for (cr
= 0; cr
<= 255; cr
++)
83 v
= ((float) 255 / 224) * (cr
- 128);
84 yuv_rv
[cr
] = ValidRange((int) (1.402 * v
));
85 yuv_gv
[cr
] = - ValidRange((int) (0.714 * v
));
87 TRACE("Filled hash table\n");
90 static void Parse_YUYV(unsigned char *destbuffer
, const unsigned char *input
, int width
, int height
)
92 const unsigned char *pY
, *pCb
, *pCr
;
93 int togo
= width
* height
/ 2;
98 YUV2RGB(*pY
, *pCb
, *pCr
, (RGB
*)destbuffer
);
99 pY
+= 2; destbuffer
+= 3;
100 YUV2RGB(*pY
, *pCb
, *pCr
, (RGB
*)destbuffer
);
101 pY
+= 2; pCb
+= 4; pCr
+= 4; destbuffer
+= 3;
105 static void Parse_UYVY(unsigned char *destbuffer
, const unsigned char *input
, int width
, int height
)
107 const unsigned char *pY
, *pCb
, *pCr
;
108 int togo
= width
* height
/ 2;
113 YUV2RGB(*pY
, *pCb
, *pCr
, (RGB
*)destbuffer
);
114 pY
+= 2; destbuffer
+= 3;
115 YUV2RGB(*pY
, *pCb
, *pCr
, (RGB
*)destbuffer
);
116 pY
+= 2; pCb
+= 4; pCr
+= 4; destbuffer
+= 3;
120 static void Parse_UYYVYY(unsigned char *destbuffer
, const unsigned char *input
, int width
, int height
)
122 const unsigned char *pY
, *pCb
, *pCr
;
123 int togo
= width
* height
/ 4;
128 YUV2RGB(*pY
, *pCb
, *pCr
, (RGB
*)destbuffer
);
129 destbuffer
+= 3; pY
++;
130 YUV2RGB(*pY
, *pCb
, *pCr
, (RGB
*)destbuffer
);
131 pY
+= 2; destbuffer
+= 3;
132 YUV2RGB(*pY
, *pCb
, *pCr
, (RGB
*)destbuffer
);
133 destbuffer
+= 3; pY
++;
134 YUV2RGB(*pY
, *pCb
, *pCr
, (RGB
*)destbuffer
);
135 pY
+= 2; pCb
+= 6; pCr
+= 6; destbuffer
+= 3;
139 static void Parse_PYUV(unsigned char *destbuffer
, const unsigned char *input
, int width
, int height
, int wstep
, int hstep
)
141 /* We have 3 pointers, One to Y, one to Cb and 1 to Cr */
143 /* C19 *89* declaration block (Grr julliard for not allowing C99) */
144 int uvjump
, ysize
, uvsize
;
145 const unsigned char *pY
, *pCb
, *pCr
;
146 int swstep
= 0, shstep
= 0;
147 int ypos
= 0, xpos
= 0;
148 int indexUV
= 0, cUv
;
151 uvjump
= width
/ wstep
;
152 ysize
= width
* height
;
153 uvsize
= (width
/ wstep
) * (height
/ hstep
);
157 /* Bottom down DIB */
161 for (xpos
= 0; xpos
< width
; xpos
++) {
162 YUV2RGB(*(pY
++), pCb
[cUv
], pCr
[cUv
], (RGB
*)destbuffer
);
164 if (++swstep
== wstep
) {
169 if (++shstep
== hstep
) {
173 } while (++ypos
< height
);
176 void YUV_To_RGB24(enum YUV_Format format
, unsigned char *target
, const unsigned char *source
, int width
, int height
) {
178 if (format
< ENDPLANAR
) {
180 case YUVP_421
: wstep
= 2; hstep
= 1; break;
181 case YUVP_422
: wstep
= 2; hstep
= 2; break;
182 case YUVP_441
: wstep
= 4; hstep
= 1; break;
183 case YUVP_444
: wstep
= 4; hstep
= 4; break;
184 default: ERR("Unhandled format \"%d\"\n", format
); return;
186 Parse_PYUV(target
, source
, width
, height
, wstep
, hstep
);
189 case YUYV
: Parse_YUYV(target
, source
, width
, height
); return;
190 case UYVY
: Parse_UYVY(target
, source
, width
, height
); return;
191 case UYYVYY
: Parse_UYYVYY(target
, source
, width
, height
); return;
192 default: ERR("Unhandled format \"%d\"\n", format
); return;