⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 videoio.cxx

📁 windows mobile phone source code
💻 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)
 *
 * $Log: videoio.cxx,v $
 * Revision 1.21  2001/12/06 22:15:09  dereks
 * Additional debugging lines
 *
 * Revision 1.20  2001/11/28 04:45:14  robertj
 * Added Win32 flipped RGB colour formats.
 *
 * Revision 1.19  2001/11/28 00:07:32  dereks
 * Locking added to PVideoChannel, allowing reader/writer to be changed mid call
 * Enabled adjustment of the video frame rate
 * New fictitous image, a blank grey area
 *
 * Revision 1.18  2001/09/25 04:25:38  dereks
 * Add fix from Stelian Pop to improve the field of view  for
 * the  small image with a  Sony Vaio Motion Eye. Many thanks.
 *
 * Revision 1.17  2001/08/03 04:21:51  dereks
 * Add colour/size conversion for YUV422->YUV411P
 * Add Get/Set Brightness,Contrast,Hue,Colour for PVideoDevice,  and
 * Linux PVideoInputDevice.
 * Add lots of PTRACE statement for debugging colour conversion.
 * Add support for Sony Vaio laptop under linux. Requires 2.4.7 kernel.
 *
 * Revision 1.16  2001/06/27 17:23:33  rogerh
 * Back out my previous change
 *
 * Revision 1.15  2001/06/26 15:48:31  rogerh
 * Do not call GetInputDeviceName if there is no video grabber code
 *
 * Revision 1.14  2001/05/22 23:38:45  robertj
 * Fixed bug in PVideoOutputDevice, removed redundent SetFrameSize.
 *
 * Revision 1.13  2001/03/20 02:21:57  robertj
 * More enhancements from Mark Cooke
 *
 * Revision 1.12  2001/03/08 08:31:34  robertj
 * Numerous enhancements to the video grabbing code including resizing
 *   infrastructure to converters. Thanks a LOT, Mark Cooke.
 *
 * Revision 1.11  2001/03/08 02:18:45  robertj
 * Added improved defaulting of video formats so Open() does not fail.
 * Removed the requirement that the device be open before you can set
 *   formats such as colour, video, channel number etc.
 *
 * Revision 1.10  2001/03/07 01:41:03  dereks
 * Fix memory leak, on destroying PVideoDevice
 * Ensure converter class is resized correctly.
 *
 * Revision 1.9  2001/03/06 23:34:20  robertj
 * Added static function to get input device names.
 * Moved some inline virtuals to non-inline.
 *
 * Revision 1.8  2001/03/05 01:12:41  robertj
 * Added more source formats for conversion, use list. Thanks Mark Cooke.
 *
 * Revision 1.7  2001/03/03 05:06:31  robertj
 * Major upgrade of video conversion and grabbing classes.
 *
 * Revision 1.6  2000/12/19 22:20:26  dereks
 * Add video channel classes to connect to the PwLib PVideoInputDevice class.
 * Add PFakeVideoInput class to generate test images for video.
 *
 * Revision 1.5  2000/11/09 00:20:58  robertj
 * Added qcif size constants
 *
 * Revision 1.4  2000/07/26 03:50:50  robertj
 * Added last error variable to video device.
 *
 * Revision 1.3  2000/07/26 02:13:48  robertj
 * Added some more "common" bounds checking to video device.
 *
 * Revision 1.2  2000/07/25 13:38:26  robertj
 * Added frame rate parameter to video frame grabber.
 *
 * Revision 1.1  2000/07/15 09:47:35  robertj
 * Added video I/O device classes.
 *
 */

#include <ptlib.h>
#include <ptlib/videoio.h>
#include <ptlib/vconvert.h>



///////////////////////////////////////////////////////////////////////////////
// PVideoDevice

PVideoDevice::PVideoDevice()
{
  lastError = 0;

  videoFormat = Auto;
  channelNumber = -1;
  frameWidth = CIFWidth;
  frameHeight = CIFHeight;

  SetCanCaptureVideo(FALSE);    ///This device cannot grab video from a port.

  converter = NULL;

  SetFrameRate(0);
}

PVideoDevice::~PVideoDevice()
{
  if (converter)
    delete converter;
}


BOOL PVideoDevice::SetVideoFormat(VideoFormat videoFmt)
{
  videoFormat = videoFmt;
  return TRUE;
}


PVideoDevice::VideoFormat PVideoDevice::GetVideoFormat() const
{
  return videoFormat;
}


int PVideoDevice::GetNumChannels()
{
  return 1;
}


BOOL PVideoDevice::SetChannel(int channelNum)
{
  if (channelNum < 0) {
    for (int c = 0; c < GetNumChannels(); c++)
      if (SetChannel(c))
        return TRUE;
    return FALSE;
  }

  if (channelNum >= GetNumChannels())
    return FALSE;

  channelNumber = channelNum;
  return TRUE;
}


int PVideoDevice::GetChannel() const
{
  return channelNumber;
}


//Colour format bit per pixel table.
// These are in rough order of colour gamut size
static struct {
  const char * colourFormat;
  unsigned     bitsPerPixel;
} colourFormatBPPTab[] = {
  { "RGB24",   24 },
  { "RGB24F",  24 },
  { "RGB32",   32 },
  { "RGB32F",  32 },
  { "YUV422",  16 },
  { "YUV422P", 16 },
  { "YUV411",  12 },
  { "YUV411P", 12 },
  { "RGB565",  16 },
  { "RGB565F", 16 },
  { "RGB555",  16 },
  { "RGB555F", 16 },
  { "YUV420",  12 },
  { "YUV420P", 12 },
  { "IYUV",    12 },
  { "I420",    12 },
  { "YUV410",  10 },
  { "YUV410P", 10 },
  { "Grey",     8 },
  { "GreyF",    8 }
};


BOOL PVideoDevice::SetColourFormatConverter(const PString & colourFmt)
{
  PTRACE(3,"PVideoDevice::SetColourFormatConverter " << colourFmt);
  if (converter) {    
    delete converter;
    converter = NULL;
  }
  
  if (SetColourFormat(colourFmt)) {
    PTRACE(3,"PVideoDevice::SetColourFormatConverter Success");
    PTRACE(3,"PVideoDevice::SetColourFormatConverter get " << colourFmt);    
    return TRUE;
  }
  
  /************************
    Eventually, need something more sophisticated than this, but for the
    moment pick the known colour formats that the device is very likely to
    support and then look for a conversion routine from that to the
    destination format.

    What we really want is some sort of better heuristic that looks at
    computational requirements of each converter and picks a pair of formats
    that the hardware supports and uses the least CPU.
  */

  PINDEX knownFormatIdx = 0;
  while (knownFormatIdx < PARRAYSIZE(colourFormatBPPTab)) {
    PString formatToTry = colourFormatBPPTab[knownFormatIdx].colourFormat;
    PTRACE(3,"PVideodevice::SetColourFormatConverter SEARCH " << colourFmt);
    PTRACE(3,"PVideodevice::SetColourFormatConverter TRY "    << formatToTry);
    if (SetColourFormat(formatToTry)) {
      PTRACE(3,"PVideodevice::SetColourFormatConverter SUCCESS. set camera to "<< formatToTry);
      converter = PColourConverter::Create(formatToTry, colourFmt, frameWidth, frameHeight);
      if (converter != NULL) {
	PTRACE(3,"PVideodevice::SetColourFormatConverter " << formatToTry << " SUCCEEDED");
        return TRUE;
      } 
    } 
    knownFormatIdx++;
  }

  PTRACE(3,"PVideodevice::SetColourFormatConverter  FAILED for "<< colourFmt);
  return FALSE;
}


BOOL PVideoDevice::SetColourFormat(const PString & colourFmt)
{
  if (!colourFmt) {
    colourFormat = colourFmt;
    return TRUE;
  }

  for (PINDEX i = 0; i < PARRAYSIZE(colourFormatBPPTab); i++) {
    if (SetColourFormat(colourFormatBPPTab[i].colourFormat))
      return TRUE;
  }

  return FALSE;
}


const PString & PVideoDevice::GetColourFormat() const
{
  return colourFormat;
}


BOOL PVideoDevice::SetFrameRate(unsigned rate)
{

  if (rate < 1) {
    frameRate = 0;
    return TRUE;
  }

  frameRate = rate;
  previousFrameTime = PTime();
  msBetweenFrames = 1000/rate;
  frameTimeError  = 0;

  return TRUE;
}


unsigned PVideoDevice::GetFrameRate() const
{
  return frameRate;
}


BOOL PVideoDevice::GetFrameSizeLimits(unsigned & minWidth,
                                      unsigned & minHeight,
                                      unsigned & maxWidth,
                                      unsigned & maxHeight) 
{
  minWidth = minHeight = 1;
  maxWidth = maxHeight = UINT_MAX;
  return FALSE;
}


static struct {
    unsigned dest_width, dest_height, device_width, device_height;
} prefResizeTable[] = {
    
    { 352, 288,    320, 240 },
    { 176, 144,    160, 120 },
    { 176, 144,    320, 240 }
};

BOOL PVideoDevice::SetFrameSizeConverter(unsigned width, unsigned height,
					 BOOL bScaleNotCrop)
{
  if (SetFrameSize(width, height))
    return TRUE;
  
  if (!converter)
    converter = PColourConverter::Create(colourFormat, colourFormat,
					 width, height);
  if (!converter) {
    PTRACE(1,"PVideoDevice::SetFrameSizeConverter Colour converter creation failed");
    return FALSE;
  }
  
  PTRACE(1,"PVideoDevice::SetFrameSizeConverter Colour converter creation has succeeded");
  
  PINDEX prefResizeIdx = 0;
  while (prefResizeIdx < PARRAYSIZE(prefResizeTable)) {
    
    if ((prefResizeTable[prefResizeIdx].dest_width == width) &&
        (prefResizeTable[prefResizeIdx].dest_height == height)) {

      if (SetFrameSize(prefResizeTable[prefResizeIdx].device_width,
                       prefResizeTable[prefResizeIdx].device_height)) {
	BOOL converterOK= converter->SetDstFrameSize(width, height, bScaleNotCrop);
	if (converterOK){
  	  PTRACE(3,"PVideoDevice\t SetFrameSizeConverter succceded for " <<
		 prefResizeTable[prefResizeIdx].device_width << "x" <<
		 prefResizeTable[prefResizeIdx].device_height << " ---> " <<
		 width<<"x"<<height);	       

	  return TRUE;
	}
	PTRACE(3,"PVideoDevice\t SetFrameSizeConverter FAILED for " <<
	       prefResizeTable[prefResizeIdx].device_width << "x" <<
	       prefResizeTable[prefResizeIdx].device_height << " ---> " <<
	       width<<"x"<<height);	       
      }
    }
    
    prefResizeIdx++;
  }

  // Failed to find a resolution the device can do so far, so try
  // using the maximum width and height it claims it can do.
  
  // QUESTION: DO WE WANT A MAX SIZE INSANITY CHECK HERE.

  unsigned minWidth, minHeight, maxWidth, maxHeight;
  GetFrameSizeLimits(minWidth, minHeight, maxWidth, maxHeight);

  if (SetFrameSize(maxWidth, maxHeight)){
    PTRACE(3,"PVideoDevice\t Success set hardware size to "<<maxWidth<<"x"<<maxHeight);
    if (converter->SetDstFrameSize(width, height, bScaleNotCrop)){
      PTRACE(3,"PVideoDeviceSetFrameSizeConvert SUCCEEDED for "<<width<<"x"<<height);
      return TRUE;
    }
  }
  PTRACE(3,"PVideoDeviceSetFrameSizeConverter FAILED for "<<width<<"x"<<height);
  return FALSE;
}


BOOL PVideoDevice::SetFrameSize(unsigned width, unsigned height)
{
  unsigned minWidth, minHeight, maxWidth, maxHeight;

  GetFrameSizeLimits(minWidth, minHeight, maxWidth, maxHeight);

  if (width < minWidth)
    frameWidth = minWidth;
  else if (width > maxWidth)
    frameWidth = maxWidth;
  else
    frameWidth = width;

  if (height < minHeight)
    frameHeight = minHeight;
  else if (height > maxHeight)
    frameHeight = maxHeight;
  else
    frameHeight = height;

  PTRACE(3,"PVideoDevice\t SetFrameSize for "<<width<<"x"<<height);

  if (converter) {
    converter->SetSrcFrameSize(width,height);
    converter->SetDstFrameSize(width,height, FALSE);    
  }
  
  return TRUE;
}


BOOL PVideoDevice::GetFrameSize(unsigned & width, unsigned & height) 
{
#if 1
    // Channels get very upset at this not returning the output size.
    if (converter)
	return converter->GetDstFrameSize(width, height);
#endif
  width = frameWidth;
  height = frameHeight;
  return TRUE;
}


unsigned PVideoDevice::GetFrameWidth() const
{
#if 1
    unsigned w,h;

    // Channels get very upset at this not returning the output size.
    if (converter) {
	converter->GetDstFrameSize(w, h);
	return w;
    }
#endif
  return frameWidth;
}


unsigned PVideoDevice::GetFrameHeight() const
{
#if 1
    unsigned w,h;

    // Channels get very upset at this not returning the output size.
    if (converter) {
	converter->GetDstFrameSize(w, h);
	return h;
    }
#endif
  return frameHeight;
}


unsigned PVideoDevice::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;
}
 

BOOL PVideoDevice::Close()
{
  return TRUE;  
}

BOOL PVideoDevice::GetParameters (int *whiteness, int *brightness, 
                                      int *colour, int *contrast, int *hue)
{
  if (!IsOpen())
    return FALSE;

  *brightness = frameBrightness;
  *colour     = frameColour;
  *contrast   = frameContrast;
  *hue        = frameHue;
  *whiteness  = frameWhiteness;

  return TRUE;
}


///////////////////////////////////////////////////////////////////////////////
// PVideoOutputDevice

PVideoOutputDevice::PVideoOutputDevice()
{
  now = 0;
  suppress = FALSE;
}


BOOL PVideoOutputDevice::Redraw(const void * /*frame*/)
{
  return FALSE;
}


void PVideoOutputDevice::SetNow(int _now)
{
  now = _now;
}


///////////////////////////////////////////////////////////////////////////////
// PVideoInputDevice

PStringList PVideoInputDevice::GetDeviceNames() const
{
  return GetInputDeviceNames();
}


BOOL PVideoInputDevice::GetFrame(PBYTEArray & frame)
{
  PINDEX returned;
  if (!GetFrameData(frame.GetPointer(GetMaxFrameBytes()), &returned))
    return FALSE;

  frame.SetSize(returned);
  return TRUE;
}


// End Of File ///////////////////////////////////////////////////////////////

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -