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