replace yuv420p_to_rgb24 by tested and conformant cvtColor

Conversion was not ITU 601 conformant. Also add YVU420 format to allowed
zero copy access.
pull/5572/head
Pavel Rojtberg 9 years ago
parent 8527d895bb
commit ad68b79630
  1. 96
      modules/videoio/src/cap_v4l.cpp

@ -552,6 +552,7 @@ static int v4l2_set_fps(CvCaptureCAM_V4L* capture) {
static int v4l2_num_channels(__u32 palette) {
switch(palette) {
case V4L2_PIX_FMT_YVU420:
case V4L2_PIX_FMT_MJPEG:
case V4L2_PIX_FMT_JPEG:
return 1;
@ -571,10 +572,17 @@ static void v4l2_create_frame(CvCaptureCAM_V4L *capture) {
int channels = 3;
if (!capture->convert_rgb) {
if (capture->palette == V4L2_PIX_FMT_MJPEG || capture->palette == V4L2_PIX_FMT_JPEG) {
channels = v4l2_num_channels(capture->palette);
switch(capture->palette) {
case V4L2_PIX_FMT_MJPEG:
case V4L2_PIX_FMT_JPEG:
size = CvSize(capture->buffers[capture->bufferIndex].length, 1);
break;
case V4L2_PIX_FMT_YVU420:
size.height = size.height * 3 / 2; // "1.5" channels
break;
}
channels = v4l2_num_channels(capture->palette);
}
/* Set up Image data */
@ -964,45 +972,6 @@ static bool icvGrabFrameCAM_V4L(CvCaptureCAM_V4L* capture) {
/* LIMIT: convert a 16.16 fixed-point value to a byte, with clipping. */
#define LIMIT(x) ((x)>0xffffff?0xff: ((x)<=0xffff?0:((x)>>16)))
static inline void
move_420_block(int yTL, int yTR, int yBL, int yBR, int u, int v,
int rowPixels, unsigned char * rgb)
{
const int rvScale = 91881;
const int guScale = -22553;
const int gvScale = -46801;
const int buScale = 116129;
const int yScale = 65536;
int r, g, b;
g = guScale * u + gvScale * v;
// if (force_rgb) {
// r = buScale * u;
// b = rvScale * v;
// } else {
r = rvScale * v;
b = buScale * u;
// }
yTL *= yScale; yTR *= yScale;
yBL *= yScale; yBR *= yScale;
/* Write out top two pixels */
rgb[0] = LIMIT(b+yTL); rgb[1] = LIMIT(g+yTL);
rgb[2] = LIMIT(r+yTL);
rgb[3] = LIMIT(b+yTR); rgb[4] = LIMIT(g+yTR);
rgb[5] = LIMIT(r+yTR);
/* Skip down to next line to write out bottom two pixels */
rgb += 3 * rowPixels;
rgb[0] = LIMIT(b+yBL); rgb[1] = LIMIT(g+yBL);
rgb[2] = LIMIT(r+yBL);
rgb[3] = LIMIT(b+yBR); rgb[4] = LIMIT(g+yBR);
rgb[5] = LIMIT(r+yBR);
}
static inline void
move_411_block(int yTL, int yTR, int yBL, int yBR, int u, int v,
int /*rowPixels*/, unsigned char * rgb)
@ -1042,49 +1011,12 @@ move_411_block(int yTL, int yTR, int yBL, int yBR, int u, int v,
rgb[5] = LIMIT(r+yBR);
}
// Consider a YUV420P image of 8x2 pixels.
//
// A plane of Y values A B C D E F G H
// I J K L M N O P
//
// A plane of U values 1 2 3 4
// A plane of V values 1 2 3 4 ....
//
// The U1/V1 samples correspond to the ABIJ pixels.
// U2/V2 samples correspond to the CDKL pixels.
//
/* Converts from planar YUV420P to RGB24. */
static void
yuv420p_to_rgb24(int width, int height,
unsigned char *pIn0, unsigned char *pOut0)
static inline void
yuv420p_to_rgb24(int width, int height, uchar* src, uchar* dst)
{
const int numpix = width * height;
const int bytes = 24 >> 3;
int i, j, y00, y01, y10, y11, u, v;
unsigned char *pY = pIn0;
unsigned char *pU = pY + numpix;
unsigned char *pV = pU + numpix / 4;
unsigned char *pOut = pOut0;
for (j = 0; j <= height - 2; j += 2) {
for (i = 0; i <= width - 2; i += 2) {
y00 = *pY;
y01 = *(pY + 1);
y10 = *(pY + width);
y11 = *(pY + width + 1);
u = (*pU++) - 128;
v = (*pV++) - 128;
move_420_block(y00, y01, y10, y11, u, v,
width, pOut);
pY += 2;
pOut += 2 * bytes;
}
pY += width;
pOut += width * bytes;
}
cvtColor(Mat(height * 3 / 2, width, CV_8U, src), Mat(height, width, CV_8UC3, dst),
COLOR_YUV2BGR_YV12);
}
// Consider a YUV411P image of 8x2 pixels.

Loading…
Cancel
Save