vconvert.cxx
来自「opal的ptlib c++源程序 可以从官方网站上下载」· CXX 代码 · 共 2,227 行 · 第 1/5 页
CXX
2,227 行
}
PColourConverter * PSynonymColourRegistration::Create(const PVideoFrameInfo & src,
const PVideoFrameInfo & dst) const
{
return new PSynonymColour(src, dst);
}
PBoolean PSynonymColour::Convert(const BYTE *srcFrameBuffer,
BYTE *dstFrameBuffer,
unsigned int __srcFrameBytes,
PINDEX * bytesReturned)
{
srcFrameBytes = __srcFrameBytes;
return Convert(srcFrameBuffer, dstFrameBuffer, bytesReturned);
}
PBoolean PSynonymColour::Convert(const BYTE *srcFrameBuffer,
BYTE *dstFrameBuffer,
PINDEX * bytesReturned)
{
if ((srcFrameWidth != dstFrameWidth) || (srcFrameHeight != dstFrameHeight)) {
PTRACE(2,"PColCnv\tCannot do synonym colour conversion, source and destination frame size not equal.");
return PFalse;
}
if (verticalFlip) {
PINDEX rowSize = dstFrameBytes/srcFrameHeight;
if (rowSize*srcFrameHeight != dstFrameBytes) {
PTRACE(2,"PColCnv\tCannot do synonym colour conversion, frame does not have equal sized scan lines.");
return PFalse;
}
if (srcFrameBuffer != dstFrameBuffer) {
const BYTE * srcRowPtr = srcFrameBuffer;
BYTE * dstRowPtr = dstFrameBuffer + srcFrameHeight*rowSize;
for (unsigned y = 0; y < srcFrameHeight; y++) {
dstRowPtr -= rowSize;
memcpy(dstRowPtr, srcRowPtr, rowSize);
srcRowPtr += rowSize;
}
}
else {
BYTE * rowPtr1 = dstFrameBuffer;
BYTE * rowPtr2 = dstFrameBuffer + srcFrameHeight*rowSize;
PBYTEArray temp(rowSize);
for (unsigned y = 0; y < srcFrameHeight; y += 2) {
rowPtr2 -= rowSize;
memcpy(temp.GetPointer(), rowPtr1, rowSize);
memcpy(rowPtr1, rowPtr2, rowSize);
memcpy(rowPtr2, temp.GetPointer(), rowSize);
rowPtr1 += rowSize;
}
}
}
else {
if (srcFrameBuffer != dstFrameBuffer)
memcpy(dstFrameBuffer, srcFrameBuffer, dstFrameBytes);
}
if (bytesReturned != NULL)
*bytesReturned = dstFrameBytes;
return PTrue;
}
///////////////////////////////////////////////////////////////////////////////
#define BLACK_Y 0
#define BLACK_U 128
#define BLACK_V 128
#define greytoy(r, y) y=r
#define greytoyuv(r, y, u, v) greytoy(r,y); u=BLACK_U; v=BLACK_V
void PStandardColourConverter::GreytoYUV420PSameSize(const BYTE * grey, BYTE * yuv) const
{
const unsigned planeSize = srcFrameWidth*srcFrameHeight;
const unsigned halfWidth = srcFrameWidth >> 1;
// get pointers to the data
BYTE * yplane = yuv;
BYTE * uplane = yuv + planeSize;
BYTE * vplane = yuv + planeSize + (planeSize >> 2);
const BYTE * greyIndex = grey;
for (unsigned y = 0; y < srcFrameHeight; y++) {
BYTE * yline = yplane + (y * srcFrameWidth);
BYTE * uline = uplane + ((y >> 1) * halfWidth);
BYTE * vline = vplane + ((y >> 1) * halfWidth);
if (verticalFlip)
greyIndex = grey + srcFrameWidth*(srcFrameHeight-1-y);
for (unsigned x = 0; x < srcFrameWidth; x+=2) {
greytoy(*greyIndex, *yline);
greyIndex++;
yline++;
greytoyuv(*greyIndex, *yline, *uline, *vline);
greyIndex++;
yline++;
uline++;
vline++;
}
}
}
// Simple crop/pad version. Image aligned to top-left
// and cropped / padded with black borders as required.
void PStandardColourConverter::GreytoYUV420PWithResize(const BYTE * grey, BYTE * yuv) const
{
int planeSize = dstFrameWidth*dstFrameHeight;
const int halfWidth = dstFrameWidth >> 1;
unsigned min_width, min_height;
min_width = (dstFrameWidth < srcFrameWidth) ? dstFrameWidth : srcFrameWidth;
min_height = (dstFrameHeight < srcFrameHeight) ? dstFrameHeight : srcFrameHeight;
// get pointers to the data
BYTE * yplane = yuv;
BYTE * uplane = yuv + planeSize;
BYTE * vplane = yuv + planeSize + (planeSize >> 2);
const BYTE * greyIndex = grey;
for (unsigned y = 0; y < min_height; y++)
{
BYTE * yline = yplane + (y * dstFrameWidth);
BYTE * uline = uplane + ((y >> 1) * halfWidth);
BYTE * vline = vplane + ((y >> 1) * halfWidth);
if (verticalFlip)
greyIndex = grey + srcFrameWidth*(min_height-1-y);
for (unsigned x = 0; x < min_width; x+=2)
{
greytoy(*greyIndex, *yline);
greyIndex++;
yline++;
greytoyuv(*greyIndex, *yline, *uline, *vline);
greyIndex++;
yline++;
uline++;
vline++;
}
// Crop if source width > dest width
if (srcFrameWidth > dstFrameWidth)
greyIndex += srcFrameWidth - dstFrameWidth;
// Pad if dest width < source width
if (dstFrameWidth > srcFrameWidth) {
memset(yline, BLACK_Y, dstFrameWidth - srcFrameWidth);
memset(uline, BLACK_U, (dstFrameWidth - srcFrameWidth)>>1);
memset(vline, BLACK_V, (dstFrameWidth - srcFrameWidth)>>1);
}
}
// Pad if dest height > source height
if (dstFrameHeight > srcFrameHeight) {
BYTE * yline = yplane + (srcFrameHeight * dstFrameWidth);
BYTE * uline = uplane + ((srcFrameHeight >> 1) * halfWidth);
BYTE * vline = vplane + ((srcFrameHeight >> 1) * halfWidth);
unsigned fill = (dstFrameHeight - srcFrameHeight) * dstFrameWidth;
memset(yline, BLACK_Y, fill);
memset(uline, BLACK_U, fill >> 2);
memset(vline, BLACK_V, fill >> 2);
}
}
PBoolean PStandardColourConverter::GreytoYUV420P(const BYTE * grey, BYTE * yuv, PINDEX * bytesReturned) const
{
if (grey == yuv)
return PFalse; // Cannot do in place conversion
if ((srcFrameWidth == dstFrameWidth) && (srcFrameHeight == dstFrameHeight))
GreytoYUV420PSameSize(grey, yuv);
else
GreytoYUV420PWithResize(grey, yuv);
if (bytesReturned != NULL)
*bytesReturned = dstFrameBytes;
return PTrue;
}
#define RGB2Y(r, g, b, y) \
y=(BYTE)(((int)257*(r) +(int)504*(g) +(int)98*(b))/1000)
#define RGB2YUV(r, g, b, y, cb, cr) \
RGB2Y(r, g, b, y); \
cb=(BYTE)((-148*(r) -291*(g) +439*(b))/1000 + 128); \
cr=(BYTE)(( 439*(r) -368*(g) - 71*(b))/1000 + 128)
void PStandardColourConverter::RGBtoYUV420PSameSize(const BYTE * rgb,
BYTE * yuv,
unsigned rgbIncrement,
unsigned redOffset,
unsigned blueOffset) const
{
const unsigned planeSize = srcFrameWidth*srcFrameHeight;
const unsigned halfWidth = srcFrameWidth >> 1;
// get pointers to the data
BYTE * yplane = yuv;
BYTE * uplane = yuv + planeSize;
BYTE * vplane = yuv + planeSize + (planeSize >> 2);
const BYTE * rgbIndex = rgb;
for (unsigned y = 0; y < srcFrameHeight; y++) {
BYTE * yline = yplane + (y * srcFrameWidth);
BYTE * uline = uplane + ((y >> 1) * halfWidth);
BYTE * vline = vplane + ((y >> 1) * halfWidth);
if (verticalFlip)
rgbIndex = rgb + (srcFrameWidth*(srcFrameHeight-1-y)*rgbIncrement);
for (unsigned x = 0; x < srcFrameWidth; x+=2) {
RGB2Y(rgbIndex[redOffset], rgbIndex[1], rgbIndex[blueOffset], *yline);
rgbIndex += rgbIncrement;
yline++;
RGB2YUV(rgbIndex[redOffset], rgbIndex[1], rgbIndex[blueOffset], *yline, *uline, *vline);
rgbIndex += rgbIncrement;
yline++;
uline++;
vline++;
}
}
}
// Simple crop/pad version. Image aligned to top-left
// and cropped / padded with black borders as required.
void PStandardColourConverter::RGBtoYUV420PWithResize(const BYTE * rgb,
BYTE * yuv,
unsigned rgbIncrement,
unsigned redOffset,
unsigned blueOffset) const
{
int planeSize = dstFrameWidth*dstFrameHeight;
const int halfWidth = dstFrameWidth >> 1;
unsigned min_width, min_height;
min_width = (dstFrameWidth < srcFrameWidth) ? dstFrameWidth : srcFrameWidth;
min_height = (dstFrameHeight < srcFrameHeight) ? dstFrameHeight : srcFrameHeight;
// get pointers to the data
BYTE * yplane = yuv;
BYTE * uplane = yuv + planeSize;
BYTE * vplane = yuv + planeSize + (planeSize >> 2);
const BYTE * rgbIndex = rgb;
for (unsigned y = 0; y < min_height; y++)
{
BYTE * yline = yplane + (y * dstFrameWidth);
BYTE * uline = uplane + ((y >> 1) * halfWidth);
BYTE * vline = vplane + ((y >> 1) * halfWidth);
if (verticalFlip)
rgbIndex = rgb + (srcFrameWidth*(min_height-1-y)*rgbIncrement);
for (unsigned x = 0; x < min_width; x+=2) {
RGB2Y(rgbIndex[redOffset], rgbIndex[1], rgbIndex[blueOffset], *yline);
rgbIndex += rgbIncrement;
yline++;
RGB2YUV(rgbIndex[redOffset], rgbIndex[1], rgbIndex[blueOffset], *yline, *uline, *vline);
rgbIndex += rgbIncrement;
yline++;
uline++;
vline++;
}
// Crop if source width > dest width
if (srcFrameWidth > dstFrameWidth)
rgbIndex += rgbIncrement * (srcFrameWidth - dstFrameWidth);
// Pad if dest width < source width
if (dstFrameWidth > srcFrameWidth) {
memset(yline, BLACK_Y, dstFrameWidth - srcFrameWidth);
memset(uline, BLACK_U, (dstFrameWidth - srcFrameWidth)>>1);
memset(vline, BLACK_V, (dstFrameWidth - srcFrameWidth)>>1);
}
}
// Pad if dest height > source height
if (dstFrameHeight > srcFrameHeight) {
BYTE * yline = yplane + (srcFrameHeight * dstFrameWidth);
BYTE * uline = uplane + ((srcFrameHeight >> 1) * halfWidth);
BYTE * vline = vplane + ((srcFrameHeight >> 1) * halfWidth);
unsigned fill = (dstFrameHeight - srcFrameHeight) * dstFrameWidth;
memset(yline, BLACK_Y, fill);
memset(uline, BLACK_U, fill >> 2);
memset(vline, BLACK_V, fill >> 2);
}
}
PBoolean PStandardColourConverter::RGBtoYUV420P(const BYTE * rgb,
BYTE * yuv,
PINDEX * bytesReturned,
unsigned rgbIncrement,
unsigned redOffset,
unsigned blueOffset) const
{
if (rgb == yuv)
return PFalse; // Cannot do in place conversion
if ((srcFrameWidth == dstFrameWidth) && (srcFrameHeight == dstFrameHeight))
RGBtoYUV420PSameSize(rgb, yuv, rgbIncrement, redOffset, blueOffset);
else
RGBtoYUV420PWithResize(rgb, yuv, rgbIncrement, redOffset, blueOffset);
if (bytesReturned != NULL)
*bytesReturned = dstFrameBytes;
return PTrue;
}
PSTANDARD_COLOUR_CONVERTER(Grey,YUV420P)
{
return GreytoYUV420P(srcFrameBuffer, dstFrameBuffer, bytesReturned);
}
PSTANDARD_COLOUR_CONVERTER(RGB24,YUV420P)
{
return RGBtoYUV420P(srcFrameBuffer, dstFrameBuffer, bytesReturned, 3, 0, 2);
}
PSTANDARD_COLOUR_CONVERTER(BGR24,YUV420P)
{
return RGBtoYUV420P(srcFrameBuffer, dstFrameBuffer, bytesReturned, 3, 2, 0);
}
PSTANDARD_COLOUR_CONVERTER(RGB32,YUV420P)
{
return RGBtoYUV420P(srcFrameBuffer, dstFrameBuffer, bytesReturned, 4, 0, 2);
}
PSTANDARD_COLOUR_CONVERTER(BGR32,YUV420P)
{
return RGBtoYUV420P(srcFrameBuffer, dstFrameBuffer, bytesReturned, 4, 2, 0);
}
/*
* Format YUY2 or YUV422(non planar):
*
* off: 0 Y00 U00 Y01 V00 Y02 U01 Y03 V01
* off: 8 Y10 U10 Y11 V10 Y12 U11 Y13 V11
* off:16 Y20 U20 Y21 V20 Y22 U21 Y23 V21
* off:24 Y30 U30 Y31 V30 Y32 U31 Y33 V31
* 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::YUY2toYUV420PSameSize(const BYTE *yuy2, BYTE *yuv420p) const
{
const BYTE *s;
BYTE *y, *u, *v;
unsigned int x, h;
int npixels = srcFrameWidth * srcFrameHeight;
s = yuy2;
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) {
*y++ = *s++;
*u++ = *s++;
*y++ = *s++;
*v++ = *s++;
}
/* Copy the second line discarding u and v information */
for (x=0; x<srcFrameWidth; x+=2) {
*y++ = *s++;
s++;
*y++ = *s++;
s++;
}
}
}
/*
* Format YUY2 or YUV422(non planar):
*
* off: 0 Y00 U00 Y01 V00 Y02 U01 Y03 V01
* off: 8 Y10 U10 Y11 V10 Y12 U11 Y13 V11
* off:16 Y20 U20 Y21 V20 Y22 U21 Y23 V21
* off:24 Y30 U30 Y31 V30 Y32 U31 Y33 V31
* 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::YUY2toYUV420PWithResize(const BYTE *yuy2, BYTE *yuv420p) const
{
const BYTE *s;
BYTE *y, *u, *v;
unsigned int x, h;
unsigned int npixels = srcFrameWidth * srcFrameHeight;
s = yuy2;
y = yuv420p;
u = yuv420p + npixels;
v = u + npixels/4;
if ( (dstFrameWidth * dstFrameHeight) > 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;
unsigned int bpixels = yOffset * dstFrameWidth;
/* Top border */
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?