Commit a64c10fd authored by Maarten Lankhorst's avatar Maarten Lankhorst Committed by Alexandre Julliard

Added YUV routines needed for v4l driver, and in the future possibly

other capture drivers too.
parent 8481c8df
...@@ -13,7 +13,8 @@ C_SRCS = \ ...@@ -13,7 +13,8 @@ C_SRCS = \
enummedia.c \ enummedia.c \
enumpins.c \ enumpins.c \
pin.c \ pin.c \
qcap_main.c qcap_main.c \
yuv.c
RC_SRCS = version.rc RC_SRCS = version.rc
......
...@@ -56,4 +56,23 @@ void DeleteMediaType(AM_MEDIA_TYPE * pmt); ...@@ -56,4 +56,23 @@ void DeleteMediaType(AM_MEDIA_TYPE * pmt);
BOOL CompareMediaTypes(const AM_MEDIA_TYPE * pmt1, const AM_MEDIA_TYPE * pmt2, BOOL bWildcards); BOOL CompareMediaTypes(const AM_MEDIA_TYPE * pmt1, const AM_MEDIA_TYPE * pmt2, BOOL bWildcards);
void dump_AM_MEDIA_TYPE(const AM_MEDIA_TYPE * pmt); void dump_AM_MEDIA_TYPE(const AM_MEDIA_TYPE * pmt);
enum YUV_Format {
/* Last 2 numbers give the skip info, the smaller they are the better
* Planar:
* HSKIP : VSKIP */
YUVP_421, /* 2 : 1 */
YUVP_422, /* 2 : 2 */
YUVP_441, /* 4 : 1 */
YUVP_444, /* 4 : 4 */
ENDPLANAR, /* No format, just last planar item so we can check on it */
/* Non-planar */
YUYV, /* Order: YUYV (Guess why it's named like that) */
UYVY, /* Order: UYVY (Looks like someone got bored and swapped the Y's) */
UYYVYY, /* YUV411 linux style, perhaps YUV420 is YYUYYV? */
};
void YUV_Init(void);
void YUV_To_RGB24(enum YUV_Format format, unsigned char *target, const unsigned char *source, int width, int height);
#endif /* _QCAP_MAIN_H_DEFINED */ #endif /* _QCAP_MAIN_H_DEFINED */
/* DirectShow capture services (QCAP.DLL)
*
* Copyright 2005 Maarten Lankhorst
*
* This file contains the part of the vfw capture interface that
* does the actual Video4Linux(1/2) stuff required for capturing
* and setting/getting media format..
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <stdarg.h>
#include "windef.h"
#include "winbase.h"
#include "objbase.h"
#include "strmif.h"
#include "qcap_main.h"
#include "wine/debug.h"
WINE_DEFAULT_DEBUG_CHANNEL(qcap);
static int yuv_xy[256]; /* Gray value */
static int yuv_gu[256]; /* Green U */
static int yuv_bu[256]; /* Blue U */
static int yuv_rv[256]; /* Red V */
static int yuv_gv[256]; /* Green V */
static int initialised = 0;
static inline int ValidRange(int in) {
if (in > 255) in = 255;
if (in < 0) in = 0;
return in;
}
typedef struct RGB {
#if 0 /* For some reason I have to revert R and B, not sure why */
unsigned char r, g, b;
#else
unsigned char b, g, r;
#endif
} RGB;
static inline void YUV2RGB(const unsigned char y_, const unsigned char cb, const unsigned char cr, RGB* retval) {
retval->r = ValidRange(yuv_xy[y_] + yuv_rv[cr]);
retval->g = ValidRange(yuv_xy[y_] + yuv_gu[cb] + yuv_gv[cr]);
retval->b = ValidRange(yuv_xy[y_] + yuv_bu[cb]);
}
void YUV_Init(void) {
float y, u, v;
int y_, cb, cr;
if (initialised++) return;
for (y_ = 0; y_ <= 255; y_++)
{
y = ((float) 255 / 219) * (y_ - 16);
yuv_xy[y_] = ValidRange((int) (y));
}
for (cb = 0; cb <= 255; cb++)
{
u = ((float) 255 / 224) * (cb - 128);
yuv_gu[cb] = - ValidRange((int) (0.344 * u));
yuv_bu[cb] = ValidRange((int) (1.772 * u));
}
for (cr = 0; cr <= 255; cr++)
{
v = ((float) 255 / 224) * (cr - 128);
yuv_rv[cr] = ValidRange((int) (1.402 * v));
yuv_gv[cr] = - ValidRange((int) (0.714 * v));
}
TRACE("Filled hash table\n");
}
static void Parse_YUYV(unsigned char *destbuffer, const unsigned char *input, int width, int height)
{
const unsigned char *pY, *pCb, *pCr;
int togo = width * height / 2;
pY = input;
pCb = input+1;
pCr = input+3;
while (--togo) {
YUV2RGB(*pY, *pCb, *pCr, (RGB *)destbuffer);
pY += 2; destbuffer += 3;
YUV2RGB(*pY, *pCb, *pCr, (RGB *)destbuffer);
pY += 2; pCb += 4; pCr += 4; destbuffer += 3;
}
}
static void Parse_UYVY(unsigned char *destbuffer, const unsigned char *input, int width, int height)
{
const unsigned char *pY, *pCb, *pCr;
int togo = width * height / 2;
pY = input+1;
pCb = input;
pCr = input+2;
while (--togo) {
YUV2RGB(*pY, *pCb, *pCr, (RGB *)destbuffer);
pY += 2; destbuffer += 3;
YUV2RGB(*pY, *pCb, *pCr, (RGB *)destbuffer);
pY += 2; pCb += 4; pCr += 4; destbuffer += 3;
}
}
static void Parse_UYYVYY(unsigned char *destbuffer, const unsigned char *input, int width, int height)
{
const unsigned char *pY, *pCb, *pCr;
int togo = width * height / 4;
pY = input+1;
pCb = input;
pCr = input+4;
while (--togo) {
YUV2RGB(*pY, *pCb, *pCr, (RGB *)destbuffer);
destbuffer += 3; pY++;
YUV2RGB(*pY, *pCb, *pCr, (RGB *)destbuffer);
pY += 2; destbuffer += 3;
YUV2RGB(*pY, *pCb, *pCr, (RGB *)destbuffer);
destbuffer += 3; pY++;
YUV2RGB(*pY, *pCb, *pCr, (RGB *)destbuffer);
pY += 2; pCb += 6; pCr += 6; destbuffer += 3;
}
}
static void Parse_PYUV(unsigned char *destbuffer, const unsigned char *input, int width, int height, int wstep, int hstep)
{
/* We have 3 pointers, One to Y, one to Cb and 1 to Cr */
/* C19 *89* declaration block (Grr julliard for not allowing C99) */
int uvjump, ysize, uvsize;
const unsigned char *pY, *pCb, *pCr;
int swstep = 0, shstep = 0;
int ypos = 0, xpos = 0;
int indexUV = 0, cUv;
/* End of Grr */
uvjump = width / wstep;
ysize = width * height;
uvsize = (width / wstep) * (height / hstep);
pY = input;
pCb = pY + ysize;
pCr = pCb + uvsize;
/* Bottom down DIB */
do {
swstep = 0;
cUv = indexUV;
for (xpos = 0; xpos < width; xpos++) {
YUV2RGB(*(pY++), pCb[cUv], pCr[cUv], (RGB *)destbuffer);
destbuffer += 3;
if (++swstep == wstep) {
cUv++;
swstep = 0;
}
}
if (++shstep == hstep) {
shstep = 0;
indexUV = cUv;
}
} while (++ypos < height);
}
void YUV_To_RGB24(enum YUV_Format format, unsigned char *target, const unsigned char *source, int width, int height) {
int wstep, hstep;
if (format < ENDPLANAR) {
switch (format) {
case YUVP_421: wstep = 2; hstep = 1; break;
case YUVP_422: wstep = 2; hstep = 2; break;
case YUVP_441: wstep = 4; hstep = 1; break;
case YUVP_444: wstep = 4; hstep = 4; break;
default: ERR("Unhandled format \"%d\"\n", format); return;
}
Parse_PYUV(target, source, width, height, wstep, hstep);
} else {
switch (format) {
case YUYV: Parse_YUYV(target, source, width, height); return;
case UYVY: Parse_UYVY(target, source, width, height); return;
case UYYVYY: Parse_UYYVYY(target, source, width, height); return;
default: ERR("Unhandled format \"%d\"\n", format); return;
}
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment