📄 vconvert.cxx
字号:
/*
* vconvert.cxx
*
* Classes to support streaming video input (grabbing) and output.
*
* Portable Windows Library
*
* Copyright (c) 1993-2000 Equivalence Pty. Ltd.
*
* The contents of this file are subject to the Mozilla Public License
* Version 1.0 (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS"
* basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
* the License for the specific language governing rights and limitations
* under the License.
*
* The Original Code is Portable Windows Library.
*
* The Initial Developer of the Original Code is Equivalence Pty. Ltd.
*
* Contributor(s): Derek Smithies (derek@indranet.co.nz)
* Thorsten Westheider (thorsten.westheider@teleos-web.de)
* Mark Cooke (mpc@star.sr.bham.ac.uk)
*
* $Revision: 19008 $
* $Author: rjongbloed $
* $Date: 2007-11-29 09:17:41 +0000 (Thu, 29 Nov 2007) $
*/
#include <ptlib.h>
#if P_VIDEO
#include <ptlib/video.h>
#ifdef __GNUC__
#pragma implementation "vconvert.h"
#endif
#include <ptlib/vconvert.h>
#if defined(__GNUC__) || defined(__sun)
#include "tinyjpeg.h"
#endif
#ifdef _MSC_VER
#pragma warning(disable : 4244)
#endif
#ifdef P_MEDIALIB
#include <mlib.h>
#endif
static PColourConverterRegistration * RegisteredColourConvertersListHead = NULL;
PSYNONYM_COLOUR_CONVERTER(SBGGR8, SBGGR8);
PSYNONYM_COLOUR_CONVERTER(Grey, Grey);
PSYNONYM_COLOUR_CONVERTER(RGB24, RGB24);
PSYNONYM_COLOUR_CONVERTER(BGR24, BGR24);
PSYNONYM_COLOUR_CONVERTER(RGB32, RGB32);
PSYNONYM_COLOUR_CONVERTER(BGR32, BGR32);
PSYNONYM_COLOUR_CONVERTER(UYVY422,UYVY422);
PSYNONYM_COLOUR_CONVERTER(YUV411P,YUV411P);
PSYNONYM_COLOUR_CONVERTER(YUV420P,IYUV);
PSYNONYM_COLOUR_CONVERTER(IYUV, YUV420P);
PSYNONYM_COLOUR_CONVERTER(YUV420P,I420);
PSYNONYM_COLOUR_CONVERTER(I420, YUV420P);
class PStandardColourConverter : public PColourConverter
{
PCLASSINFO(PStandardColourConverter, PColourConverter);
protected:
PStandardColourConverter(
const PVideoFrameInfo & src,
const PVideoFrameInfo & dst
) : PColourConverter(src, dst) { }
PBoolean SBGGR8toYUV420P(
const BYTE * srgb,
BYTE * rgb,
PINDEX * bytesReturned
) const;
PBoolean SBGGR8toRGB(
const BYTE * srgb,
BYTE * rgb,
PINDEX * bytesReturned
) const;
void GreytoYUV420PSameSize(
const BYTE * rgb,
BYTE * yuv
) const;
void GreytoYUV420PWithResize(
const BYTE * rgb,
BYTE * yuv
) const;
PBoolean GreytoYUV420P(
const BYTE * rgb,
BYTE * yuv,
PINDEX * bytesReturned
) const;
void RGBtoYUV420PSameSize(
const BYTE * rgb,
BYTE * yuv,
unsigned rgbIncrement,
unsigned redOffset,
unsigned blueOffset
) const;
void RGBtoYUV420PWithResize(
const BYTE * rgb,
BYTE * yuv,
unsigned rgbIncrement,
unsigned redOffset,
unsigned blueOffset
) const;
PBoolean RGBtoYUV420P(
const BYTE * rgb,
BYTE * yuv,
PINDEX * bytesReturned,
unsigned rgbIncrement,
unsigned redOffset,
unsigned blueOffset
) const;
PBoolean YUV420PtoRGB(
const BYTE * yuv,
BYTE * rgb,
PINDEX * bytesReturned,
unsigned rgbIncrement,
unsigned redOffset,
unsigned blueOffset
) const;
PBoolean SwapRedAndBlue(
const BYTE * src,
BYTE * dst,
PINDEX * bytesReturned,
unsigned srcIncrement,
unsigned dstIncrement
) const;
void ResizeUYVY422(
const BYTE *src_uyvy,
BYTE *dst_uyvy
) const;
void ResizeYUV422(
const BYTE * src,
BYTE * dest
) const;
void ResizeYUV420P(
const BYTE * src,
BYTE * dest
) const;
void UYVY422toYUV420PSameSize(
const BYTE *uyvy,
BYTE *yuv420p
) const;
void UYVY422toYUV420PWithResize(
const BYTE *uyvy,
BYTE *yuv420p
) const;
void YUY2toYUV420PSameSize(
const BYTE *yuy2,
BYTE *yuv420p
) const;
void YUY2toYUV420PWithResize(
const BYTE *yuy2,
BYTE *yuv420p
) const;
bool MJPEGtoYUV420PSameSize(
const BYTE *yuy2,
BYTE *yuv420p
);
#if defined (__GNUC__) || defined (__sun)
bool MJPEGtoXXX(
const BYTE *mjpeg,
BYTE *output_data,
PINDEX *bytesReturned,
int format
);
bool MJPEGtoYUV420P(
const BYTE *mjpeg,
BYTE *yuv420p,
PINDEX *bytesReturned
);
bool MJPEGtoXXXSameSize(
const BYTE *yuy2,
BYTE *rgb,
int format
);
#endif
};
#define PSTANDARD_COLOUR_CONVERTER(from,to) \
PCOLOUR_CONVERTER2(P_##from##_##to,PStandardColourConverter,#from,#to)
#define new PNEW
///////////////////////////////////////////////////////////////////////////////
// PColourConverter
PColourConverterRegistration::PColourConverterRegistration(const PString & srcColourFormat,
const PString & destColourFormat)
: PCaselessString(srcColourFormat+'\t'+destColourFormat)
{
PColourConverterRegistration * test = RegisteredColourConvertersListHead;
while (test != NULL) {
if (*test == *this)
return;
test = test->link;
}
link = RegisteredColourConvertersListHead;
RegisteredColourConvertersListHead = this;
}
PColourConverter * PColourConverter::Create(const PVideoFrameInfo & src,
const PVideoFrameInfo & dst)
{
PString converterName = src.GetColourFormat() + '\t' + dst.GetColourFormat();
PColourConverterRegistration * find = RegisteredColourConvertersListHead;
while (find != NULL) {
if (*find == converterName) {
return find->Create(src, dst);
}
find = find->link;
}
PTRACE(2,"PColCnv\tCreate error. Did not find " << src.GetColourFormat() << "->" << dst.GetColourFormat());
return NULL;
}
PColourConverter * PColourConverter::Create(const PString & srcColourFormat,
const PString & destColourFormat,
unsigned width,
unsigned height)
{
PVideoFrameInfo src;
src.SetColourFormat(srcColourFormat);
src.SetFrameSize(width, height);
PVideoFrameInfo dst;
dst.SetColourFormat(destColourFormat);
return Create(src, dst);
}
PColourConverter::PColourConverter(
const PString & _srcColourFormat, ///< Name of source colour format
const PString & _dstColourFormat, ///< Name of destination colour format
unsigned width, ///< Width of frame
unsigned height ///< Height of frame
)
: verticalFlip(PFalse)
#ifndef P_MACOSX
, jdec(NULL)
#endif
{
PVideoFrameInfo src;
src.SetColourFormat(_srcColourFormat);
src.SetFrameSize(width, height);
PVideoFrameInfo dst;
dst.SetColourFormat(_dstColourFormat);
srcColourFormat = src.GetColourFormat();
dstColourFormat = dst.GetColourFormat();
resizeMode = dst.GetResizeMode();
src.GetFrameSize(srcFrameWidth, srcFrameHeight);
srcFrameBytes = src.CalculateFrameBytes();
dst.GetFrameSize(dstFrameWidth, dstFrameHeight);
dstFrameBytes = dst.CalculateFrameBytes();
PTRACE(6,"PColCnv\tPColourConverter constructed: " << srcColourFormat << ' ' << srcFrameWidth << 'x'<< srcFrameHeight
<< " -> " << dstColourFormat << ' ' << dstFrameWidth << 'x'<< dstFrameHeight);
}
PColourConverter::PColourConverter(const PVideoFrameInfo & src,
const PVideoFrameInfo & dst)
: srcColourFormat(src.GetColourFormat())
, dstColourFormat(dst.GetColourFormat())
, resizeMode(dst.GetResizeMode())
, verticalFlip(PFalse)
#ifndef P_MACOSX
, jdec(NULL)
#endif
{
src.GetFrameSize(srcFrameWidth, srcFrameHeight);
srcFrameBytes = src.CalculateFrameBytes();
dst.GetFrameSize(dstFrameWidth, dstFrameHeight);
dstFrameBytes = dst.CalculateFrameBytes();
PTRACE(6,"PColCnv\tPColourConverter constructed: " << srcColourFormat << ' ' << srcFrameWidth << 'x'<< srcFrameHeight
<< " -> " << dstColourFormat << ' ' << dstFrameWidth << 'x'<< dstFrameHeight);
}
PBoolean PColourConverter::SetFrameSize(unsigned width, unsigned height)
{
PBoolean ok1 = SetSrcFrameSize(width, height);
PBoolean ok2 = SetDstFrameSize(width, height);
PTRACE(2,"PColCnv\tSetFrameSize: " << width << 'x' << height
<< (ok1 && ok2 ? " OK" : " Failed"));
return ok1 && ok2;
}
PBoolean PColourConverter::SetSrcFrameInfo(const PVideoFrameInfo & info)
{
if (info.GetColourFormat() != GetSrcColourFormat())
return PFalse;
unsigned w, h;
return info.GetFrameSize(w, h) && SetSrcFrameSize(w, h);
}
PBoolean PColourConverter::SetDstFrameInfo(const PVideoFrameInfo & info)
{
if (info.GetColourFormat() != GetDstColourFormat())
return PFalse;
SetResizeMode(info.GetResizeMode());
unsigned w, h;
return info.GetFrameSize(w, h) && SetDstFrameSize(w, h);
}
void PColourConverter::GetSrcFrameInfo(PVideoFrameInfo & info)
{
info.SetColourFormat(GetSrcColourFormat());
info.SetFrameSize(srcFrameWidth, srcFrameHeight);
}
void PColourConverter::GetDstFrameInfo(PVideoFrameInfo & info)
{
info.SetColourFormat(GetDstColourFormat());
info.SetFrameSize(dstFrameWidth, dstFrameHeight);
}
PBoolean PColourConverter::SetSrcFrameSize(unsigned width, unsigned height)
{
if (srcFrameWidth == width && srcFrameHeight == height)
return PTrue;
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;
}
PBoolean PColourConverter::SetDstFrameSize(unsigned width, unsigned height)
{
dstFrameWidth = width;
dstFrameHeight = height;
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;
}
PBoolean PColourConverter::SetDstFrameSize(
unsigned width,
unsigned height,
PBoolean bScale
)
{
if (!SetDstFrameSize(width, height))
return PFalse;
if (bScale)
SetResizeMode(PVideoFrameInfo::eScale);
else
SetResizeMode(PVideoFrameInfo::eCropCentre);
return PTrue;
}
PBoolean PColourConverter::GetSrcFrameSize(unsigned &width, unsigned &height) const
{
width = srcFrameWidth;
height = srcFrameHeight;
return PTrue;
}
PBoolean PColourConverter::GetDstFrameSize(unsigned &width, unsigned &height) const
{
width = dstFrameWidth;
height = dstFrameHeight;
return PTrue;
}
PBoolean PColourConverter::ConvertInPlace(BYTE * frameBuffer,
PINDEX * bytesReturned,
PBoolean noIntermediateFrame)
{
if (Convert(frameBuffer, frameBuffer, bytesReturned))
return PTrue;
if (noIntermediateFrame) {
PTRACE(2,"PColCnv\tError in ConvertInPlace, no intermediate frame available.");
return PFalse;
}
BYTE * intermediate = intermediateFrameStore.GetPointer(dstFrameBytes);
PINDEX bytes;
if (!Convert(frameBuffer, intermediate, &bytes))
return PFalse;
memcpy(frameBuffer, intermediate, bytes);
if (bytesReturned != NULL)
*bytesReturned = bytes;
return PTrue;
}
///////////////////////////////////////////////////////////////////////////////
PSynonymColourRegistration::PSynonymColourRegistration(const char * srcFmt,
const char * dstFmt)
: PColourConverterRegistration(srcFmt,dstFmt)
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -