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

📄 vidinput_v4l2.cxx

📁 安装 H323需要的pwlib库
💻 CXX
📖 第 1 页 / 共 2 页
字号:
/* * vidinput_v4l2.cxx * * Classes to support streaming video input (grabbing) and output. * * Portable Windows Library * * Copyright (c) 1998-2000 Equivalence Pty. Ltd. * Copyright (c) 2003 March Networks * * 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. * * First V4L2 capture code written by March Networks  * (http://www.marchnetworks.com)  * * This code is based on the Video4Linux 1 code. * * Contributor(s): Guilhem Tardy (gtardy@salyens.com) * 		   Nicola Orru' <nigu@itadinanta.it> * * TODO: *  - fix the devices detection code using the new code from the V4L1 plugin *  - make that code work * * $Log: vidinput_v4l2.cxx,v $ * Revision 1.4  2004/11/07 22:48:47  dominance * fixed copyright of v4l2 plugin. Last commit's credits go to Nicola Orru' <nigu@itadinanta.it> ... * * Revision 1.3  2004/11/07 21:34:21  dominance * v4l2 patch to add verbose device names detection. * * Revision 1.2  2004/10/27 09:22:59  dsandras * Added patch from Nicola Orru' to make things work better. * * Revision 1.1  2004/09/21 12:54:23  dsandras * Added initial port to the new pwlib API/V4L2 API for the video4linux 2 code of Guilhem Tardy. Thanks! * * Revision 1.0  2003/03/03 12:27:00  guilhem * First build. * */#pragma implementation "vidinput_v4l2.h"#include "vidinput_v4l2.h"#include <sys/utsname.h>PCREATE_VIDINPUT_PLUGIN(V4L2, PVideoInputV4l2Device);#include "vidinput_names.h" class V4L2Names : public V4LXNames{  PCLASSINFO(V4L2Names, V4LXNames);public:    V4L2Names() { kernelVersion=KUNKNOWN; };  virtual void Update ();  protected:    virtual PString V4L2Names::BuildUserFriendly(PString devname);  enum KernelVersionEnum {    K2_4,     K2_6,    KUNKNOWN,  } kernelVersion;};static V4L2Names & GetNames(){  static V4L2Names names;  names.Update();  return names;}///////////////////////////////////////////////////////////////////////////////// PVideoInputV4l2DevicePVideoInputV4l2Device::PVideoInputV4l2Device(){  videoFd = -1;  canRead = FALSE;  canStream = FALSE;  canSelect = FALSE;  canSetFrameRate = FALSE;  isMapped = FALSE;}PVideoInputV4l2Device::~PVideoInputV4l2Device(){  Close();}#ifndef V4L2_PIX_FMT_H263#define V4L2_PIX_FMT_H263       v4l2_fourcc('H','2','6','3')#endifstatic struct {  const char * colourFormat;  __u32 code;} colourFormatTab[] = {    { "Grey", V4L2_PIX_FMT_GREY },  //Entries in this table correspond    { "RGB32", V4L2_PIX_FMT_RGB32 }, //(line by line) to those in the     { "RGB24", V4L2_PIX_FMT_RGB24 }, // PVideoDevice ColourFormat table.    { "RGB565", V4L2_PIX_FMT_RGB565 },    { "RGB555", V4L2_PIX_FMT_RGB555 },    { "YUV411", V4L2_PIX_FMT_Y41P },    { "YUV411P", V4L2_PIX_FMT_YUV411P },    { "YUV420", V4L2_PIX_FMT_NV21 },    { "YUV420P", V4L2_PIX_FMT_YUV420 },    { "YUV422", V4L2_PIX_FMT_YYUV },    { "YUV422P", V4L2_PIX_FMT_YUV422P },    { "JPEG", V4L2_PIX_FMT_JPEG },    { "H263", V4L2_PIX_FMT_H263 },    { "SBGGR8", V4L2_PIX_FMT_SBGGR8 }};BOOL PVideoInputV4l2Device::Open(const PString & devName, BOOL startImmediate){  struct utsname buf;  PString version;    uname (&buf);  if (buf.release)    version = PString (buf.release);  PTRACE(1,"PVidInDev\tOpen()\tvideoFd:" << videoFd);  Close();  PString name = GetNames().GetDeviceName(devName);  PTRACE(1,"PVidInDev\tOpen()\tdevName:" << name << "  videoFd:" << videoFd);    videoFd = ::open((const char *)name, O_RDWR);  if (videoFd < 0) {    PTRACE(1,"PVidInDev\topen failed : " << ::strerror(errno));    return FALSE;  }    PTRACE(6,"PVidInDev\topen, fd=" << videoFd);  deviceName=name;  // get the device capabilities  if (::ioctl(videoFd, VIDIOC_QUERYCAP, &videoCapability) < 0) {    PTRACE(1,"PVidInDev\tQUERYCAP failed : " << ::strerror(errno));    ::close (videoFd);    videoFd = -1;    return FALSE;  }      canRead = videoCapability.capabilities & V4L2_CAP_READWRITE;  canStream = videoCapability.capabilities & V4L2_CAP_STREAMING;  canSelect = videoCapability.capabilities & V4L2_CAP_ASYNCIO;  // set height and width  frameHeight = QCIFHeight;  frameWidth  = QCIFWidth;  // get the capture parameters  videoStreamParm.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;  if (::ioctl(videoFd, VIDIOC_G_PARM, &videoStreamParm) < 0)  {    PTRACE(1,"PVidInDev\tG_PARM failed : " << ::strerror(errno));    canSetFrameRate = FALSE;  } else {    canSetFrameRate = videoStreamParm.parm.capture.capability & V4L2_CAP_TIMEPERFRAME;    if (canSetFrameRate)      PVideoDevice::SetFrameRate (10000000 * videoStreamParm.parm.capture.timeperframe.numerator / videoStreamParm.parm.capture.timeperframe.denominator);  }    return TRUE;}BOOL PVideoInputV4l2Device::IsOpen() {  return videoFd >= 0;}BOOL PVideoInputV4l2Device::Close(){  PTRACE(1,"PVidInDev\tClose()\tvideoFd:" << videoFd << "  started:" << started);  if (!IsOpen())    return FALSE;  Stop();  ClearMapping();  ::close(videoFd);  PTRACE(6,"PVidInDev\tclose, fd=" << videoFd);  videoFd = -1;  canRead = FALSE;  canStream = FALSE;  canSelect = FALSE;  canSetFrameRate = FALSE;  isMapped = FALSE;  PTRACE(1,"PVidInDev\tClose()\tvideoFd:" << videoFd << "  started:" << started);  return TRUE;}BOOL PVideoInputV4l2Device::Start(){  // automatically set mapping  if (!isMapped && !SetMapping()) {    ClearMapping();    canStream = FALSE; // don't try again    return FALSE;  }  if (!started) {    PTRACE(6,"PVidInDev\tstart streaming, fd=" << videoFd);    struct v4l2_buffer buf;    buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;    buf.index = 0;    if (::ioctl(videoFd, VIDIOC_QBUF, &buf) < 0) {      PTRACE(3,"PVidInDev\tVIDIOC_QBUF failed : " << ::strerror(errno));      return FALSE;    }    buf.index = 0;    buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;    if (::ioctl(videoFd, VIDIOC_STREAMON, &buf.type) < 0) {      PTRACE(3,"PVidInDev\tSTREAMON failed : " << ::strerror(errno));      return FALSE;    }    started = TRUE;    // requeue all buffers    for (buf.index = 0; buf.index < videoBufferCount; buf.index++) {      PTRACE(3,"PVidInDev\tQBUF for index:" << buf.index);      if (::ioctl(videoFd, VIDIOC_QBUF, &buf) < 0) {	PTRACE(3,"PVidInDev\tQBUF failed : " << ::strerror(errno));	return FALSE;      }    }  }  return TRUE;}BOOL PVideoInputV4l2Device::Stop(){  if (started) {    PTRACE(6,"PVidInDev\tstop streaming, fd=" << videoFd);    int type = V4L2_BUF_TYPE_VIDEO_CAPTURE;    started = FALSE;    if (::ioctl(videoFd, VIDIOC_STREAMOFF, &type) < 0) {      PTRACE(3,"PVidInDev\tSTREAMOFF failed : " << ::strerror(errno));      return FALSE;    }    // no need to dequeue filled buffers, as this is handled by V4L2 at the next VIDIOC_STREAMON  }  return TRUE;}BOOL PVideoInputV4l2Device::IsCapturing(){  return started;}PStringList PVideoInputV4l2Device::GetInputDeviceNames(){  return GetNames().GetInputDeviceNames();  }BOOL PVideoInputV4l2Device::SetVideoFormat(VideoFormat newFormat){  if (newFormat == Auto) {    if (SetVideoFormat(PAL) ||	SetVideoFormat(NTSC) ||	SetVideoFormat(SECAM))      return TRUE;    else      return FALSE;  }  if (!PVideoDevice::SetVideoFormat(newFormat)) {    PTRACE(1,"PVideoDevice::SetVideoFormat failed for format " << newFormat);    return FALSE;  }  struct {    __u32 code;    const char * name;  } static const fmt[3] = { {V4L2_STD_PAL, "PAL"},      {V4L2_STD_NTSC, "NTSC"},      {V4L2_STD_SECAM, "SECAM"} };  struct v4l2_standard videoEnumStd;  videoEnumStd.index = 0;  while (1) {    if (::ioctl(videoFd, VIDIOC_ENUMSTD, &videoEnumStd) < 0) {      PTRACE(1,"VideoInputDevice\tEnumStd failed : " << ::strerror(errno));          videoEnumStd.id = V4L2_STD_PAL;      break;     }    if (videoEnumStd.id == fmt[newFormat].code) {      break;    }    videoEnumStd.index++;  }  // set the video standard  if (::ioctl(videoFd, VIDIOC_S_STD, &videoEnumStd.id) < 0) {    PTRACE(1,"VideoInputDevice\tS_STD failed : " << ::strerror(errno));  }  PTRACE(6,"PVidInDev\tset video format \"" << fmt[newFormat].name << "\", fd=" << videoFd);  return TRUE;}int PVideoInputV4l2Device::GetNumChannels() {  // if opened, return the capability value, else 1 as in videoio.cxx  if (IsOpen ()) {    struct v4l2_input videoEnumInput;    videoEnumInput.index = 0;    while (1) {      if (::ioctl(videoFd, VIDIOC_ENUMINPUT, &videoEnumInput) < 0) {	PTRACE(1,"VideoInputDevice\tEnumInput failed : " << ::strerror(errno));    	break;      }      else	videoEnumInput.index++;    }    return videoEnumInput.index;  }  else    return 1;}BOOL PVideoInputV4l2Device::SetChannel(int newChannel){  if (!PVideoDevice::SetChannel(newChannel)) {    PTRACE(1,"PVideoDevice::SetChannel failed for channel " << newChannel);    return FALSE;  }  // set the channel  if (::ioctl(videoFd, VIDIOC_S_INPUT, &channelNumber) < 0) {    PTRACE(1,"VideoInputDevice\tS_INPUT failed : " << ::strerror(errno));        return FALSE;  }  PTRACE(6,"PVidInDev\tset channel " << newChannel << ", fd=" << videoFd);  return TRUE;}BOOL PVideoInputV4l2Device::SetVideoChannelFormat (int newChannel, VideoFormat videoFormat) {  if (!SetChannel(newChannel) ||      !SetVideoFormat(videoFormat))    return FALSE;  return TRUE;}BOOL PVideoInputV4l2Device::SetColourFormat(const PString & newFormat){  PINDEX colourFormatIndex = 0;  while (newFormat != colourFormatTab[colourFormatIndex].colourFormat) {    colourFormatIndex++;    if (colourFormatIndex >= PARRAYSIZE(colourFormatTab))      return FALSE;  }  if (!PVideoDevice::SetColourFormat(newFormat)) {    PTRACE(3,"PVidInDev\tSetColourFormat failed for colour format " << newFormat);    return FALSE;  }  BOOL resume = started;  Stop();  ClearMapping();  struct v4l2_format videoFormat;  videoFormat.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;  // get the colour format  if (::ioctl(videoFd, VIDIOC_G_FMT, &videoFormat) < 0) {    PTRACE(1,"PVidInDev\tG_FMT failed : " << ::strerror(errno));    return FALSE;  }  videoFormat.fmt.pix.pixelformat = colourFormatTab[colourFormatIndex].code;  // set the colour format  if (::ioctl(videoFd, VIDIOC_S_FMT, &videoFormat) < 0) {    PTRACE(1,"PVidInDev\tS_FMT failed : " << ::strerror(errno));    PTRACE(1,"\tused code of " << videoFormat.fmt.pix.pixelformat << " for palette: " << colourFormatTab[colourFormatIndex].colourFormat);    return FALSE;  }  // get the colour format again to be careful about broken drivers  if (::ioctl(videoFd, VIDIOC_G_FMT, &videoFormat) < 0) {    PTRACE(1,"PVidInDev\tG_FMT failed : " << ::strerror(errno));    return FALSE;  }  if (videoFormat.fmt.pix.pixelformat != colourFormatTab[colourFormatIndex].code) {    PTRACE(3,"PVidInDev\tcolour format mismatch.");    return FALSE;  }  frameBytes = videoFormat.fmt.pix.sizeimage;  PTRACE(6,"PVidInDev\tset colour format \"" << newFormat << "\", fd=" << videoFd);  if (resume)    return Start();  return TRUE;}BOOL PVideoInputV4l2Device::SetFrameRate(unsigned rate){  if (!PVideoDevice::SetFrameRate(rate)) {    PTRACE(3,"PVidInDev\tSetFrameRate failed for rate " << rate);    return TRUE; // Ignore  }  if (canSetFrameRate) {    videoStreamParm.parm.capture.timeperframe.numerator = 10000000;    videoStreamParm.parm.capture.timeperframe.denominator = (rate ? rate : 1);    // set the stream parameters    if (::ioctl(videoFd, VIDIOC_S_PARM, &videoStreamParm) < 0)  {      PTRACE(1,"PVidInDev\tS_PARM failed : "<< ::strerror(errno));      return TRUE;    }    PTRACE(6,"PVidInDev\tset frame rate " << rate << "fps, fd=" << videoFd);  }  return TRUE;}BOOL PVideoInputV4l2Device::GetFrameSizeLimits(unsigned & minWidth,					       unsigned & minHeight,					       unsigned & maxWidth,					       unsigned & maxHeight) {  /* Not used in V4L2 */  minWidth=0;  maxWidth=65535;  minHeight=0;  maxHeight=65535;  return FALSE;}BOOL PVideoInputV4l2Device::SetFrameSize(unsigned width, unsigned height){  if (!PVideoDevice::SetFrameSize(width, height)) {    PTRACE(3,"PVidInDev\tSetFrameSize failed for size " << width << "x" << height);    return FALSE;  }  BOOL resume = started;  Stop();  ClearMapping();  if (!VerifyHardwareFrameSize(width, height)) {    PTRACE(3,"PVidInDev\tVerifyHardwareFrameSize failed for size " << width << "x" << height);    return FALSE;  }  PTRACE(6,"PVidInDev\tset frame size " << width << "x" << height << ", fd=" << videoFd);  if (resume)    return Start();  return TRUE;}PINDEX PVideoInputV4l2Device::GetMaxFrameBytes(){  if (converter != NULL) {    PINDEX bytes = converter->GetMaxDstFrameBytes();    if (bytes > frameBytes)      return bytes;  }  return frameBytes;}BOOL PVideoInputV4l2Device::SetMapping(){  if (!canStream)    return FALSE;

⌨️ 快捷键说明

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