📄 videoio.cxx
字号:
/*
* videoio.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): Mark Cooke (mpc@star.sr.bham.ac.uk)
*
* $Revision: 19426 $
* $Author: rjongbloed $
* $Date: 2008-02-09 03:19:51 +0000 (Sat, 09 Feb 2008) $
*/
#ifdef __GNUC__
#pragma implementation "videoio.h"
#endif
#include <ptlib.h>
#if P_VIDEO
#include <ptlib/pluginmgr.h>
#include <ptlib/videoio.h>
#include <ptlib/vconvert.h>
namespace PWLib {
PFactory<PDevicePluginAdapterBase>::Worker< PDevicePluginAdapter<PVideoInputDevice> > vidinChannelFactoryAdapter("PVideoInputDevice", PTrue);
PFactory<PDevicePluginAdapterBase>::Worker< PDevicePluginAdapter<PVideoOutputDevice> > vidoutChannelFactoryAdapter("PVideoOutputDevice", PTrue);
};
template <> PVideoInputDevice * PDevicePluginFactory<PVideoInputDevice>::Worker::Create(const PString & type) const
{
return PVideoInputDevice::CreateDevice(type);
}
template <> PVideoOutputDevice * PDevicePluginFactory<PVideoOutputDevice>::Worker::Create(const PString & type) const
{
return PVideoOutputDevice::CreateDevice(type);
}
///////////////////////////////////////////////////////////////////////////////
#if PTRACING
ostream & operator<<(ostream & strm, PVideoDevice::VideoFormat fmt)
{
static const char * const VideoFormatNames[PVideoDevice::NumVideoFormats] = {
"PAL",
"NTSC",
"SECAM",
"Auto"
};
if (fmt < PVideoDevice::NumVideoFormats && VideoFormatNames[fmt] != NULL)
strm << VideoFormatNames[fmt];
else
strm << "VideoFormat<" << (unsigned)fmt << '>';
return strm;
}
#endif
//Colour format bit per pixel table.
// These are in rough order of colour gamut size
static struct {
const char * colourFormat;
unsigned bitsPerPixel;
} colourFormatBPPTab[] = {
{ "YUV420", 12 },
{ "YUV420P", 12 },
{ "I420", 12 },
{ "RGB32", 32 },
{ "BGR32", 32 },
{ "RGB24", 24 },
{ "BGR24", 24 },
{ "MJPEG", 16 },
{ "JPEG", 16 },
{ "YUY2", 16 },
{ "YUV422", 16 },
{ "YUV422P", 16 },
{ "YUV411", 12 },
{ "YUV411P", 12 },
{ "RGB565", 16 },
{ "RGB555", 16 },
{ "IYUV", 12 },
{ "YUV410", 10 },
{ "YUV410P", 10 },
{ "Grey", 8 },
{ "GreyF", 8 },
{ "UYVY422", 16 },
{ "UYV444", 24 },
{ "SBGGR8", 8 }
};
template <class VideoDevice>
static VideoDevice * CreateDeviceWithDefaults(PString & adjustedDeviceName,
const PString & driverName,
PPluginManager * pluginMgr)
{
PString adjustedDriverName = driverName;
if (adjustedDeviceName.IsEmpty() || adjustedDeviceName == "*") {
if (driverName.IsEmpty() || driverName == "*") {
PStringArray drivers = VideoDevice::GetDriverNames(pluginMgr);
if (drivers.IsEmpty())
return NULL;
// Give precedence to drivers like camera grabbers, leave out the fail safe types such as NULL
PINDEX driverIndex;
for (driverIndex = drivers.GetSize()-1; driverIndex > 0; --driverIndex) {
static const char * lowPriorityDrivers[] = {
"YUVFile", "FakeVideo", "NULLOutput"
};
PINDEX i;
for (i = 0; i < PARRAYSIZE(lowPriorityDrivers); i++) {
if (drivers[driverIndex] == lowPriorityDrivers[i])
break;
}
if (i == PARRAYSIZE(lowPriorityDrivers))
break;
}
adjustedDriverName = drivers[driverIndex];
}
PStringArray devices = VideoDevice::GetDriversDeviceNames(adjustedDriverName);
if (!devices.IsEmpty())
adjustedDeviceName = devices[0];
}
return VideoDevice::CreateDeviceByName(adjustedDeviceName, adjustedDriverName, pluginMgr);
}
///////////////////////////////////////////////////////////////////////////////
// PVideoDevice
PVideoFrameInfo::PVideoFrameInfo()
: frameWidth(CIFWidth)
, frameHeight(CIFHeight)
, frameRate(25)
, colourFormat("YUV420P")
, resizeMode(eScale)
{
}
PBoolean PVideoFrameInfo::SetFrameSize(unsigned width, unsigned height)
{
if (width < 8 || height < 8)
return PFalse;
frameWidth = width;
frameHeight = height;
return PTrue;
}
PBoolean PVideoFrameInfo::GetFrameSize(unsigned & width, unsigned & height) const
{
width = frameWidth;
height = frameHeight;
return PTrue;
}
unsigned PVideoFrameInfo::GetFrameWidth() const
{
unsigned w,h;
GetFrameSize(w, h);
return w;
}
unsigned PVideoFrameInfo::GetFrameHeight() const
{
unsigned w,h;
GetFrameSize(w, h);
return h;
}
PBoolean PVideoFrameInfo::SetFrameRate(unsigned rate)
{
if (rate < 1 || rate > 999)
return PFalse;
frameRate = rate;
return PTrue;
}
unsigned PVideoFrameInfo::GetFrameRate() const
{
return frameRate;
}
PBoolean PVideoFrameInfo::SetColourFormat(const PString & colourFmt)
{
if (!colourFmt) {
colourFormat = colourFmt.ToUpper();
return PTrue;
}
for (PINDEX i = 0; i < PARRAYSIZE(colourFormatBPPTab); i++) {
if (SetColourFormat(colourFormatBPPTab[i].colourFormat))
return PTrue;
}
return PFalse;
}
const PString & PVideoFrameInfo::GetColourFormat() const
{
return colourFormat;
}
PINDEX PVideoFrameInfo::CalculateFrameBytes(unsigned width, unsigned height,
const PString & colourFormat)
{
for (PINDEX i = 0; i < PARRAYSIZE(colourFormatBPPTab); i++) {
if (colourFormat *= colourFormatBPPTab[i].colourFormat)
return width * height * colourFormatBPPTab[i].bitsPerPixel/8;
}
return 0;
}
PBoolean PVideoFrameInfo::ParseSize(const PString & str, unsigned & width, unsigned & height)
{
static struct {
const char * name;
unsigned width;
unsigned height;
} const sizeTable[] = {
{ "cif", PVideoDevice::CIFWidth, PVideoDevice::CIFHeight },
{ "qcif", PVideoDevice::QCIFWidth, PVideoDevice::QCIFHeight },
{ "sqcif", PVideoDevice::SQCIFWidth, PVideoDevice::SQCIFHeight },
{ "cif4", PVideoDevice::CIF4Width, PVideoDevice::CIF4Height },
{ "4cif", PVideoDevice::CIF4Width, PVideoDevice::CIF4Height },
{ "cif16", PVideoDevice::CIF16Width, PVideoDevice::CIF16Height },
{ "16cif", PVideoDevice::CIF16Width, PVideoDevice::CIF16Height },
{ "ccir601",720, 486 },
{ "ntsc", 720, 480 },
{ "pal", 768, 576 },
{ "hdtvp", 1280, 720 },
{ "hd720", 1280, 720 },
{ "hdtvi", 1920, 1080 },
{ "hd1080", 1920, 1080 },
{ "cga", 320, 240 },
{ "vga", 640, 480 },
{ "wvga", 854, 480 },
{ "svga", 800, 600 },
{ "xga", 1024, 768 },
{ "sxga", 1280, 1024 },
{ "wsxga", 1440, 900 },
{ "sxga+", 1400, 1050 },
{ "wsxga+", 1680, 1050 },
{ "uxga", 1600, 1200 },
{ "wuxga", 1920, 1200 },
{ "qxga", 2048, 1536 },
{ "wqxga", 2560, 1600 },
{ }
};
for (int i = 0; sizeTable[i].name != NULL; i++) {
if (str *= sizeTable[i].name) {
width = sizeTable[i].width;
height = sizeTable[i].height;
return PTrue;
}
}
return sscanf(str, "%ux%u", &width, &height) == 2 && width > 0 && height > 0;
}
///////////////////////////////////////////////////////////////////////////////
// PVideoDevice
PVideoDevice::PVideoDevice()
{
lastError = 0;
videoFormat = Auto;
channelNumber = -1; // -1 will find the first working channel number.
nativeVerticalFlip = PFalse;
converter = NULL;
}
PVideoDevice::~PVideoDevice()
{
if (converter)
delete converter;
}
PVideoDevice::OpenArgs::OpenArgs()
: pluginMgr(NULL),
deviceName("#1"),
videoFormat(Auto),
channelNumber(0),
colourFormat("YUV420P"),
convertFormat(PTrue),
rate(0),
width(CIFWidth),
height(CIFHeight),
convertSize(PTrue),
resizeMode(eScale),
flip(PFalse),
brightness(-1),
whiteness(-1),
contrast(-1),
colour(-1),
hue(-1)
{
}
PBoolean PVideoDevice::OpenFull(const OpenArgs & args, PBoolean startImmediate)
{
if (args.deviceName[0] == '#') {
PStringArray devices = GetDeviceNames();
PINDEX id = args.deviceName.Mid(1).AsUnsigned();
if (id == 0 || id > devices.GetSize())
return PFalse;
if (!Open(devices[id-1], PFalse))
return PFalse;
}
else {
if (!Open(args.deviceName, PFalse))
return PFalse;
}
if (!SetVideoFormat(args.videoFormat))
return PFalse;
if (!SetChannel(args.channelNumber))
return PFalse;
if (args.convertFormat) {
if (!SetColourFormatConverter(args.colourFormat))
return PFalse;
}
else {
if (!SetColourFormat(args.colourFormat))
return PFalse;
}
if (args.rate > 0) {
if (!SetFrameRate(args.rate))
return PFalse;
}
if (args.convertSize) {
if (!SetFrameSizeConverter(args.width, args.height, args.resizeMode))
return PFalse;
}
else {
if (!SetFrameSize(args.width, args.height))
return PFalse;
}
if (!SetVFlipState(args.flip))
return PFalse;
if (args.brightness >= 0) {
if (!SetBrightness(args.brightness))
return PFalse;
}
if (args.whiteness >= 0) {
if (!SetWhiteness(args.whiteness))
return PFalse;
}
if (args.contrast >= 0) {
if (!SetContrast(args.contrast))
return PFalse;
}
if (args.colour >= 0) {
if (!SetColour(args.colour))
return PFalse;
}
if (args.hue >= 0) {
if (!SetColour(args.hue))
return PFalse;
}
if (startImmediate)
return Start();
return PTrue;
}
PBoolean PVideoDevice::Close()
{
return PTrue;
}
PBoolean PVideoDevice::Start()
{
return PTrue;
}
PBoolean PVideoDevice::Stop()
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -