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

📄 vfw.cxx

📁 windows mobile phone source code
💻 CXX
📖 第 1 页 / 共 2 页
字号:
/*
 * vfw.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): ______________________________________.
 *
 * $Log: vfw.cxx,v $
 * Revision 1.13  2001/11/28 04:37:46  robertj
 * Added "flipped" colour formats, thanks Telefonica Spain.
 * Added support for grabbing at a frame rate (from Linux).
 * Adjusted thread priority causing starvation, thanks Telefonica Spain.
 * Fixed startup problem if initialise gets error, thanks Telefonica Spain.
 *
 * Revision 1.12  2001/03/30 07:20:37  robertj
 * Some drivers (QuickCam) use key frame bit to indicate grab complete.
 *
 * Revision 1.11  2001/03/08 22:57:15  robertj
 * Added new VerifyHardwareFrameSize() function
 *
 * Revision 1.10  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.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/03 05:06:31  robertj
 * Major upgrade of video conversion and grabbing classes.
 *
 * Revision 1.7  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.6  2000/11/09 00:28:38  robertj
 * Changed video capture for step frame grab instead of streamed grabbing.
 *
 * Revision 1.5  2000/07/30 03:41:31  robertj
 * Added more colour formats to video device enum.
 *
 * Revision 1.4  2000/07/26 03:50:50  robertj
 * Added last error variable to video device.
 *
 * Revision 1.3  2000/07/25 13:38:26  robertj
 * Added frame rate parameter to video frame grabber.
 *
 * Revision 1.2  2000/07/25 13:14:07  robertj
 * Got the video capture stuff going!
 *
 * 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>


#define STEP_GRAB_CAPTURE 1


class PVideoInputThread : public PThread
{
  PCLASSINFO(PVideoInputThread, PThread);
  public:
 
    PVideoInputThread(PVideoInputDevice & dev)
      : PThread(30000, NoAutoDeleteThread, NormalPriority), device(dev) { Resume(); }
    void Main() { device.HandleCapture(); }
  protected:
    PVideoInputDevice & device;
};


///////////////////////////////////////////////////////////////////////////////

class PCapStatus : public CAPSTATUS
{
  public:
    PCapStatus(HWND hWnd);
    BOOL IsOK() { return uiImageWidth != 0; }
};


///////////////////////////////////////////////////////////////////////////////

class PVideoDeviceBitmap : PBYTEArray
{
  public:
    PVideoDeviceBitmap(unsigned width, unsigned height, const PString & fmt);
    PVideoDeviceBitmap(HWND hWnd);
    BOOL ApplyFormat(HWND hWnd) { return capSetVideoFormat(hWnd, theArray, GetSize()); }

    BITMAPINFO * operator->() const { return (BITMAPINFO *)theArray; }
};



///////////////////////////////////////////////////////////////////////////////


static struct {
  const char * colourFormat;
  BOOL  flipped;
  WORD  bitCount;
  DWORD compression;
} FormatTable[] = {
  { "Grey",    FALSE, 8,  BI_RGB,       },
  { "Gray",    FALSE, 8,  BI_RGB,       },
  { "GreyF",   TRUE,  8,  BI_RGB,       },
  { "GrayF",   TRUE,  8,  BI_RGB,       },
  { "RGB32",   FALSE, 32, BI_RGB,       },
  { "RGB32F",  TRUE,  32, BI_RGB,       },
  { "RGB24",   FALSE, 24, BI_RGB,       },
  { "RGB24F",  TRUE,  24, BI_RGB,       },
  { "RGB565",  FALSE, 16, BI_BITFIELDS, },
  { "RGB565F", TRUE,  16, BI_BITFIELDS, },
  { "RGB555",  FALSE, 15, BI_BITFIELDS, },
  { "RGB555F", TRUE,  15, BI_BITFIELDS, },

  // http://support.microsoft.com/support/kb/articles/q294/8/80.asp
  { "YUV420P", FALSE, 12, mmioFOURCC('I','Y','U','V') },
  { "IYUV",    FALSE, 12, mmioFOURCC('I','Y','U','V') },
  { "I420",    FALSE, 12, mmioFOURCC('I','4','2','0') }, // Like YVUV
  { "YV12",    FALSE, 12, mmioFOURCC('Y','V','1','2') }, // Like YVUV except planes switched

  { "YUV422",  FALSE, 16, mmioFOURCC('Y','U','Y','2') },
  { "YUY2",    FALSE, 16, mmioFOURCC('Y','U','Y','2') },
  { "UYVY",    FALSE, 16, mmioFOURCC('U','Y','V','Y') }, // Like YUY2 except for ordering
  { "YVYU",    FALSE, 16, mmioFOURCC('Y','V','Y','U') }, // Like YUY2 except for ordering

  { "MJPEG",   FALSE, 0,  mmioFOURCC('M','J','P','G') },
  { NULL },
};


PVideoDeviceBitmap::PVideoDeviceBitmap(unsigned width, unsigned height,
                                       const PString & fmt)
  : PBYTEArray(sizeof(BITMAPINFO))
{
  PINDEX i = 0;
  while (FormatTable[i].colourFormat != NULL && !(fmt *= FormatTable[i].colourFormat))
    i++;

  BITMAPINFO * bi = (BITMAPINFO *)theArray;

  bi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
  bi->bmiHeader.biWidth = width;
  bi->bmiHeader.biHeight = FormatTable[i].flipped ? height : -(int)height;
  bi->bmiHeader.biPlanes = 1;
  bi->bmiHeader.biBitCount = FormatTable[i].bitCount;

  if (FormatTable[i].colourFormat != NULL)
    bi->bmiHeader.biCompression = FormatTable[i].compression;
  else if (fmt.GetLength() == 4)
    bi->bmiHeader.biCompression = mmioFOURCC(fmt[0],fmt[1],fmt[2],fmt[3]);
  else {
    bi->bmiHeader.biCompression = 0xffffffff; // Indicate invalid colour format
    return;
  }

  bi->bmiHeader.biSizeImage = height*((bi->bmiHeader.biBitCount*width + 31)/32)*4;

  if (bi->bmiHeader.biCompression == BI_RGB && bi->bmiHeader.biBitCount == 8) {
    SetSize(sizeof(BITMAPINFOHEADER)+sizeof(RGBQUAD)*256);
    for (i = 0; i < 256; i++)
      bi->bmiColors[i].rgbBlue = bi->bmiColors[i].rgbGreen = bi->bmiColors[i].rgbRed = (BYTE)i;
    bi->bmiHeader.biHeight = -bi->bmiHeader.biHeight;
  }
}


PVideoDeviceBitmap::PVideoDeviceBitmap(HWND hCaptureWindow)
{
  PINDEX sz = capGetVideoFormatSize(hCaptureWindow);
  SetSize(sz);
  if (capGetVideoFormat(hCaptureWindow, theArray, sz))
    return;

  PTRACE(1, "capGetVideoFormat: failed - " << ::GetLastError());
  SetSize(0);
}


///////////////////////////////////////////////////////////////////////////////

PCapStatus::PCapStatus(HWND hWnd)
{
  memset(this, 0, sizeof(*this));
  if (capGetStatus(hWnd, this, sizeof(*this)))
    return;

  PTRACE(1, "capGetStatus: failed - " << ::GetLastError());
}


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

PVideoInputDevice::PVideoInputDevice()
{
  captureThread = NULL;
  hCaptureWindow = NULL;
  lastFramePtr = NULL;
  lastFrameSize = 0;
  isCapturingNow = FALSE;
}

BOOL PVideoInputDevice::Open(const PString & devName, BOOL startImmediate)
{
  Close();

  deviceName = devName;

  captureThread = new PVideoInputThread(*this);
  threadStarted.Wait();
  if (hCaptureWindow == NULL) {
    delete captureThread;
    captureThread = NULL;
    return FALSE;
  }

  if (startImmediate)
    return Start();

  return TRUE;
}


BOOL PVideoInputDevice::IsOpen() 
{
  return hCaptureWindow != NULL;
}


BOOL PVideoInputDevice::Close()
{
  if (!IsOpen())
    return FALSE;
 
  Stop();

  ::PostThreadMessage(captureThread->GetThreadId(), WM_QUIT, 0, 0L);
  captureThread->WaitForTermination();
  delete captureThread;
  captureThread = NULL;

  return TRUE;
}


BOOL PVideoInputDevice::Start()
{
  if (IsCapturing())
    return FALSE;
#if STEP_GRAB_CAPTURE
  isCapturingNow = TRUE;
  return capGrabFrameNoStop(hCaptureWindow);
#else
  if (capCaptureSequenceNoFile(hCaptureWindow)) {
    PCapStatus status(hCaptureWindow);
    isCapturingNow = status.fCapturingNow;
    return isCapturingNow;
  }

  lastError = ::GetLastError();
  PTRACE(1, "capCaptureSequenceNoFile: failed - " << lastError);
  return FALSE;
#endif
}


BOOL PVideoInputDevice::Stop()
{
  if (!IsCapturing())
    return FALSE;
  isCapturingNow = FALSE;
#if STEP_GRAB_CAPTURE
  return IsOpen() && frameAvailable.Wait(1000);
#else
  if (capCaptureStop(hCaptureWindow))
    return TRUE;

  lastError = ::GetLastError();
  PTRACE(1, "capCaptureStop: failed - " << lastError);
  return FALSE;
#endif
}

⌨️ 快捷键说明

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