📄 vconvert.cxx
字号:
PTRACE(2,"PColCnv\tCreate error. Did not find " << srcColourFormat << "->" << destColourFormat);
return NULL;
}
PColourConverter::PColourConverter(const PString & src,
const PString & dst,
unsigned width,
unsigned height)
: srcColourFormat(src),
dstColourFormat(dst)
{
PTRACE(6,"PColCnv\tPColourConverter constructed: " << src << "->" << dst << ' ' << width << 'x'<< height);
#ifndef P_MACOSX
jdec = NULL;
#endif
verticalFlip = FALSE;
SetFrameSize(width,height);
}
BOOL PColourConverter::SetFrameSize(unsigned width, unsigned height)
{
BOOL ok1 = SetSrcFrameSize(width, height);
BOOL ok2 = SetDstFrameSize(width, height, FALSE);
PTRACE(2,"PColCnv\tSetFrameSize: " << width << 'x' << height
<< (ok1 && ok2 ? " OK" : " Failed"));
return ok1 && ok2;
}
BOOL PColourConverter::SetSrcFrameSize(unsigned width, unsigned height)
{
srcFrameWidth = width;
srcFrameHeight = height;
srcFrameBytes = PVideoDevice::CalculateFrameBytes(srcFrameWidth, srcFrameHeight, srcColourFormat);
PTRACE(srcFrameBytes != 0 ? 6 : 2, "PColCnv\tSetSrcFrameSize "
<< ((srcFrameBytes != 0) ? "Succeed": "Fail") << "ed, "
<< srcColourFormat << ' ' << srcFrameWidth << 'x' << srcFrameHeight
<< ", " << srcFrameBytes << " bytes.");
return srcFrameBytes != 0;
}
BOOL PColourConverter::SetDstFrameSize(unsigned width, unsigned height, BOOL bScale)
{
dstFrameWidth = width;
dstFrameHeight = height;
scaleNotCrop = bScale;
dstFrameBytes = PVideoDevice::CalculateFrameBytes(dstFrameWidth, dstFrameHeight, dstColourFormat);
PTRACE(dstFrameBytes != 0 ? 6 : 2, "PColCnv\tSetDstFrameSize "
<< ((dstFrameBytes != 0) ? "Succeed": "Fail") << "ed, "
<< dstColourFormat << ' ' << dstFrameWidth << 'x' << dstFrameHeight
<< ", " << dstFrameBytes << " bytes.");
return dstFrameBytes != 0;
}
BOOL PColourConverter::GetSrcFrameSize(unsigned &width, unsigned &height) const
{
width = srcFrameWidth;
height = srcFrameHeight;
return TRUE;
}
BOOL PColourConverter::GetDstFrameSize(unsigned &width, unsigned &height) const
{
width = dstFrameWidth;
height = dstFrameHeight;
return TRUE;
}
BOOL PColourConverter::ConvertInPlace(BYTE * frameBuffer,
PINDEX * bytesReturned,
BOOL noIntermediateFrame)
{
if (Convert(frameBuffer, frameBuffer, bytesReturned))
return TRUE;
if (noIntermediateFrame) {
PTRACE(2,"PColCnv\tError in ConvertInPlace, no intermediate frame available.");
return FALSE;
}
BYTE * intermediate = intermediateFrameStore.GetPointer(dstFrameBytes);
PINDEX bytes;
if (!Convert(frameBuffer, intermediate, &bytes))
return FALSE;
memcpy(frameBuffer, intermediate, bytes);
if (bytesReturned != NULL)
*bytesReturned = bytes;
return TRUE;
}
///////////////////////////////////////////////////////////////////////////////
PSynonymColourRegistration::PSynonymColourRegistration(const char * srcFmt,
const char * dstFmt)
: PColourConverterRegistration(srcFmt,dstFmt)
{
}
PColourConverter * PSynonymColourRegistration::Create(unsigned w, unsigned h) const
{
PINDEX tab = Find('\t');
return new PSynonymColour(Left(tab), Mid(tab+1), w, h);
}
BOOL PSynonymColour::Convert(const BYTE *srcFrameBuffer,
BYTE *dstFrameBuffer,
unsigned int __srcFrameBytes,
PINDEX * bytesReturned)
{
srcFrameBytes = __srcFrameBytes;
return Convert(srcFrameBuffer, dstFrameBuffer, bytesReturned);
}
BOOL 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 FALSE;
}
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 FALSE;
}
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 TRUE;
}
///////////////////////////////////////////////////////////////////////////////
#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);
}
}
BOOL PStandardColourConverter::GreytoYUV420P(const BYTE * grey, BYTE * yuv, PINDEX * bytesReturned) const
{
if (grey == yuv)
return FALSE; // Cannot do in place conversion
if ((srcFrameWidth == dstFrameWidth) && (srcFrameHeight == dstFrameHeight))
GreytoYUV420PSameSize(grey, yuv);
else
GreytoYUV420PWithResize(grey, yuv);
if (bytesReturned != NULL)
*bytesReturned = dstFrameBytes;
return TRUE;
}
#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);
}
}
BOOL PStandardColourConverter::RGBtoYUV420P(const BYTE * rgb,
BYTE * yuv,
PINDEX * bytesReturned,
unsigned rgbIncrement,
unsigned redOffset,
unsigned blueOffset) const
{
if (rgb == yuv)
return FALSE; // 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;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -