📄 vconvert.cxx
字号:
PSTANDARD_COLOUR_CONVERTER(BGR32,RGB24)
{
return SwapRedAndBlue(srcFrameBuffer, dstFrameBuffer, bytesReturned, 4, 3);
}
PSTANDARD_COLOUR_CONVERTER(RGB32,BGR32)
{
return SwapRedAndBlue(srcFrameBuffer, dstFrameBuffer, bytesReturned, 4, 4);
}
PSTANDARD_COLOUR_CONVERTER(BGR32,RGB32)
{
return SwapRedAndBlue(srcFrameBuffer, dstFrameBuffer, bytesReturned, 4, 4);
}
PSTANDARD_COLOUR_CONVERTER(RGB24,RGB32)
{
if ((dstFrameWidth != srcFrameWidth) || (dstFrameHeight != srcFrameHeight))
return PFalse;
// Go from bottom to top so can do in place conversion
const BYTE * src = srcFrameBuffer+srcFrameBytes-1;
BYTE * dst = dstFrameBuffer+dstFrameBytes-1;
for (unsigned x = 0; x < srcFrameWidth; x++) {
for (unsigned y = 0; y < srcFrameHeight; y++) {
*dst-- = 0;
for (unsigned p = 0; p < 3; p++)
*dst-- = *src--;
}
}
if (bytesReturned != NULL)
*bytesReturned = dstFrameBytes;
return PTrue;
}
PSTANDARD_COLOUR_CONVERTER(RGB32,RGB24)
{
if ((dstFrameWidth != srcFrameWidth) || (dstFrameHeight != srcFrameHeight))
return PFalse;
const BYTE * src = srcFrameBuffer;
BYTE * dst = dstFrameBuffer;
for (unsigned x = 0; x < srcFrameWidth; x++) {
for (unsigned y = 0; y < srcFrameHeight; y++) {
for (unsigned p = 0; p < 3; p++)
*dst++ = *src++;
src++;
}
}
if (bytesReturned != NULL)
*bytesReturned = dstFrameBytes;
return PTrue;
}
// 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.
//
// Consider a YUV411P image of 8x2 pixels.
//
// A plane of Y values as before.
//
// 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 ABCD pixels.
// U2/V2 samples correspond to the EFGH pixels.
//
// I choose to reoganize the U and V samples by using
// using U1 for ABCD, U3 for EFGH, U2 for IJKL, U4 for MNOP
//
// Possibly discarding U2/U4 completely, or using the
// average of U1 and U2 might be easier for compression
//
// TODO:
//
// - Inplace converter
// - Resizing / padding / scaling converter
//
PSTANDARD_COLOUR_CONVERTER(YUV420P,YUV411P)
{
if (srcFrameBuffer == dstFrameBuffer)
return PFalse;
if ((dstFrameWidth != srcFrameWidth) || (dstFrameHeight != srcFrameHeight))
return PFalse;
// Copy over the Y plane.
memcpy(dstFrameBuffer, srcFrameBuffer, srcFrameWidth*srcFrameHeight);
unsigned linewidth = dstFrameWidth / 4;
// Source data is the start of the U plane
const BYTE* src = srcFrameBuffer + srcFrameWidth * srcFrameHeight;
// Two output lines at a time
BYTE *dst0 = dstFrameBuffer + dstFrameWidth * dstFrameHeight;
BYTE *dst1 = dst0 + linewidth;
unsigned x, y;
// U plane
for (y = 0; y < dstFrameHeight; y += 2) {
for (x = 0; x < dstFrameWidth; x += 4) {
*dst0++ = *src++;
*dst1++ = *src++;
}
// Skip over the 2nd line we already did.
dst0 += linewidth;
dst1 = dst0 + linewidth;
}
// Source data is the start of the U plane
src = srcFrameBuffer + srcFrameWidth * srcFrameHeight * 5 / 4;
// Two output lines at a time
dst0 = dstFrameBuffer + dstFrameWidth * dstFrameHeight * 5 / 4;
dst1 = dst0 + linewidth;
// V plane
for (y = 0; y < dstFrameHeight; y += 2) {
for (x = 0; x < dstFrameWidth; x += 4) {
*dst0++ = *src++;
*dst1++ = *src++;
}
// Skip over the 2nd line we already did.
dst0 += linewidth;
dst1 = dst0 + linewidth;
}
if (bytesReturned != NULL)
*bytesReturned = dstFrameBytes;
return PTrue;
}
// YUV411P to YUV420P conversion
//
// Consider YUV411P U plane (. = pixel) :
//
// A... B... C... D...
// E... F... G... H...
// I... J... K... L...
// M... N... O... P...
//
// We map this to a YUV420P plane by
// discarding odd rows, and doubling up
// the even row samples:
//
// A.A. B.B. C.C. D.D.
// .... .... .... ....
// I.I. J.J. K.K. L.L.
// .... .... .... ....
//
// TODO:
//
// - Inplace converter
// - Resizing / padding / scaling converter
//
PSTANDARD_COLOUR_CONVERTER(YUV411P,YUV420P)
{
if (srcFrameBuffer == dstFrameBuffer)
return PFalse;
if ((dstFrameWidth != srcFrameWidth) || (dstFrameHeight != srcFrameHeight))
return PFalse;
// Copy over the Y plane.
memcpy(dstFrameBuffer, srcFrameBuffer, srcFrameWidth*srcFrameHeight);
unsigned linewidth = dstFrameWidth / 4;
// Source data is the start of the U plane
const BYTE* src = srcFrameBuffer + srcFrameWidth * srcFrameHeight;
// Output line
BYTE *dst0 = dstFrameBuffer + dstFrameWidth * dstFrameHeight;
unsigned x, y;
// U plane
for (y = 0; y < dstFrameHeight; y += 2) {
for (x = 0; x < dstFrameWidth; x += 4) {
// Double up the horizontal samples
*dst0++ = *src;
*dst0++ = *src++;
}
// Skip over the 2nd line we are decimating
src += linewidth;
}
// Source data is the start of the U plane
src = srcFrameBuffer + srcFrameWidth * srcFrameHeight * 5 / 4;
// Output line
dst0 = dstFrameBuffer + dstFrameWidth * dstFrameHeight * 5 / 4;
// V plane
for (y = 0; y < dstFrameHeight; y += 2) {
for (x = 0; x < dstFrameWidth; x += 4) {
// Double up the samples horizontal samples
*dst0++ = *src;
*dst0++ = *src++;
}
// Skip over the 2nd source line we already did.
src += linewidth;
}
if (bytesReturned != NULL)
*bytesReturned = dstFrameBytes;
return PTrue;
}
/*
* Format UYVY or UYVY422(non planar) 4x4
*
* off: 0 U00 Y00 V01 Y00 U02 Y01 V03 Y01
* off: 8 U10 Y10 V11 Y10 U12 Y11 V13 Y11
* off:16 U20 Y20 V21 Y20 U22 Y21 V23 Y21
* off:24 U30 Y30 V31 Y30 U32 Y31 V33 Y31
* length:32 bytes
*/
PSTANDARD_COLOUR_CONVERTER(UYVY422, UYVY422)
{
if (bytesReturned != NULL)
*bytesReturned = dstFrameBytes;
if (srcFrameBuffer == dstFrameBuffer) {
if (srcFrameWidth == dstFrameWidth && srcFrameHeight == dstFrameHeight)
return PTrue;
else if(srcFrameWidth < dstFrameWidth || srcFrameHeight < dstFrameHeight)
return PFalse;
}
if ((srcFrameWidth == dstFrameWidth) && (srcFrameHeight == dstFrameHeight))
memcpy(dstFrameBuffer,srcFrameBuffer,srcFrameWidth*srcFrameHeight*2);
else
ResizeUYVY422(srcFrameBuffer, dstFrameBuffer);
return PTrue;
}
/*
* Format UYVY (or UYVY422) non planar (4x4)
*
* off: 0 U00 Y00 V01 Y00 U02 Y01 V03 Y01
* off: 8 U10 Y10 V11 Y10 U12 Y11 V13 Y11
* off:16 U20 Y20 V21 Y20 U22 Y21 V23 Y21
* off:24 U30 Y30 V31 Y30 U32 Y31 V33 Y31
* length:32 bytes
*
* NOTE: This algorithm works only if the width and the height is pair.
*/
void PStandardColourConverter::ResizeUYVY422(const BYTE *src_uyvy, BYTE *dst_uyvy) const
{
const BYTE *s;
BYTE *d;
unsigned int x, h;
unsigned int npixels = dstFrameWidth * dstFrameHeight;
s = src_uyvy;
d = dst_uyvy;
if ( (srcFrameWidth * srcFrameHeight) < npixels ) {
// dest is bigger than the source. No subsampling.
// Place the src in the middle of the destination.
unsigned int yOffset = (dstFrameHeight - srcFrameHeight)/2;
unsigned int xOffset = (dstFrameWidth - srcFrameWidth)/2;
/* Top border */
for (h=0; h<yOffset; h++)
{
for (x=0; x<dstFrameWidth/2; x++)
{
*d++ = BLACK_U;
*d++ = BLACK_Y;
*d++ = BLACK_V;
*d++ = BLACK_Y;
}
}
for (h=0; h<srcFrameHeight; h+=2)
{
/* Left border */
for (x=0; x<xOffset/2; x++)
{
*d++ = BLACK_U;
*d++ = BLACK_Y;
*d++ = BLACK_V;
*d++ = BLACK_Y;
}
/* Copy the first line keeping all information */
memcpy(d, s, srcFrameWidth*2);
d += srcFrameWidth*2;
/* Right and Left border */
for (x=0; x<xOffset/2; x++)
{
*d++ = BLACK_U;
*d++ = BLACK_Y;
*d++ = BLACK_V;
*d++ = BLACK_Y;
}
}
for (h=0; h<yOffset; h++)
{
for (x=0; x<dstFrameWidth/2; x++)
{
*d++ = BLACK_U;
*d++ = BLACK_Y;
*d++ = BLACK_V;
*d++ = BLACK_Y;
}
}
} else {
/* FIXME */
}
}
/*
* Format UYVY or UYVY422(non planar) 4x4
*
* off: 0 U00 Y00 V01 Y00 U02 Y01 V03 Y01
* off: 8 U10 Y10 V11 Y10 U12 Y11 V13 Y11
* off:16 U20 Y20 V21 Y20 U22 Y21 V23 Y21
* off:24 U30 Y30 V31 Y30 U32 Y31 V33 Y31
* length:32 bytes
*
* Format YUV420P:
* off: 00 Y00 Y01 Y02 Y03
* off: 04 Y10 Y11 Y12 Y13
* off: 08 Y20 Y21 Y22 Y23
* off: 12 Y30 Y31 Y32 Y33
* off: 16 U00 U02 U20 U22
* off: 20 V00 V02 V20 V22
*
* So, we loose some bit of information when converting UYVY to YUV420
*
* NOTE: This algorithm works only if the width and the height is pair.
*/
void PStandardColourConverter::UYVY422toYUV420PSameSize(const BYTE *uyvy, BYTE *yuv420p) const
{
const BYTE *s;
BYTE *y, *u, *v;
unsigned int x, h;
int npixels = srcFrameWidth * srcFrameHeight;
s = uyvy;
y = yuv420p;
u = yuv420p + npixels;
v = u + npixels/4;
for (h=0; h<srcFrameHeight; h+=2) {
/* Copy the first line keeping all information */
for (x=0; x<srcFrameWidth; x+=2) {
*u++ = *s++;
*y++ = *s++;
*v++ = *s++;
*y++ = *s++;
}
/* Copy the second line discarding u and v information */
for (x=0; x<srcFrameWidth; x+=2) {
s++;
*y++ = *s++;
s++;
*y++ = *s++;
}
}
}
/*
* Format UYVY (or UYVY422) non planar (4x4)
*
* off: 0 U00 Y00 V01 Y00 U02 Y01 V03 Y01
* off: 8 U10 Y10 V11 Y10 U12 Y11 V13 Y11
* off:16 U20 Y20 V21 Y20 U22 Y21 V23 Y21
* off:24 U30 Y30 V31 Y30 U32 Y31 V33 Y31
* length:32 bytes
*
* Format YUV420P:
* off: 00 Y00 Y01 Y02 Y03
* off: 04 Y10 Y11 Y12 Y13
* off: 08 Y20 Y21 Y22 Y23
* off: 12 Y30 Y31 Y32 Y33
* off: 16 U00 U02 U20 U22
* off: 20 V00 V02 V20 V22
*
* So, we loose some bit of information when converting YUY2 to YUV420
*
* NOTE: This algorithm works only if the width and the height is pair.
*/
void PStandardColourConverter::UYVY422toYUV420PWithResize(const BYTE *uyvy, BYTE *yuv420p) const
{
const BYTE *s;
BYTE *y, *u, *v;
unsigned int x, h;
unsigned int npixels = dstFrameWidth * dstFrameHeight;
s = uyvy;
y = yuv420p;
u = yuv420p + npixels;
v = u + npixels/4;
if ( (srcFrameWidth * srcFrameHeight) < npixels ) {
// dest is bigger than the source
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -