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

📄 vidinput_v4l2.cxx

📁 sloedgy open sip stack source code
💻 CXX
📖 第 1 页 / 共 3 页
字号:
/*
 * 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>
 *
 * $Log: vidinput_v4l2.cxx,v $
 * Revision 1.1  2006/06/29 04:18:00  joegenbaclor
 * *** empty log message ***
 *
 * Revision 1.18  2006/05/06 15:29:38  dsandras
 * Applied patch from Martin Rubli <martin rubli logitech com> to fix framerate
 * and computation issues. Thanks a lot!
 *
 * Revision 1.17  2006/03/12 11:16:19  dsandras
 * Added multi-buffering support to V4L2 thanks to Luc Saillard. Thanks!
 *
 * Revision 1.16  2006/03/12 11:09:51  dsandras
 * Applied patch from Luc Saillard to fix problems with MJPEG. Thanks!
 *
 * Revision 1.15  2006/03/06 19:09:31  dsandras
 * Applied patch from Luc Saillard <luc saillard org> to fix YUV422, which
 * is in fact YUYV.
 *
 * Revision 1.14  2006/02/06 22:23:08  dsandras
 * Added UYVY palette thanks to Luc Saillard <luc saillard org>. Thanks!
 *
 * Revision 1.13  2006/01/29 22:46:41  csoutheren
 * Added support for cameras that return MJPEG streams
 * Thanks to Luc Saillard and Damien Sandras
 *
 * Revision 1.12  2006/01/21 13:59:50  dsandras
 * Added BGR colour format thanks to Luc Saillard <luc saillard org>. Thanks!
 *
 * Revision 1.11  2006/01/17 22:28:26  dsandras
 * Another patch from Luc Saillard <luc saillard org> to fix V4L2 support when
 * opening/closing the device several times in a row. Thanks a lot!!!!!
 *
 * Revision 1.10  2006/01/09 18:22:42  dsandras
 * Use memset before some ioctl() to make valgrind happy.
 * Create a common function to set and get control information.
 * Fix range values return by the driver.
 * Fix setting value to be in the range (>>16 is unsigned).
 * Add support for YUY2.
 * Patch from Luc Saillard <luc _AT___ saillard.org>. Many thanks!
 *
 * Revision 1.9  2006/01/07 16:10:21  dsandras
 * More changes from Luc Saillard. Thanks!
 *
 * Revision 1.8  2006/01/05 19:21:37  dsandras
 * Applied patch from Luc Saillard <luc _____AT_ saillard.org>. Many thanks!
 *
 * Revision 1.7  2005/12/21 21:31:39  dsandras
 * Fixed build with gcc 4.1.
 *
 * Revision 1.6  2005/11/30 12:47:39  csoutheren
 * Removed tabs, reformatted some code, and changed tags for Doxygen
 *
 * Revision 1.5  2005/08/09 09:08:10  rjongbloed
 * Merged new video code from branch back to the trunk.
 *
 * Revision 1.4.4.2  2005/07/24 09:01:48  rjongbloed
 * Major revisions of the PWLib video subsystem including:
 *   removal of F suffix on colour formats for vertical flipping, all done with existing bool
 *   working through use of RGB and BGR formats so now consistent
 *   cleaning up the plug in system to use virtuals instead of pointers to functions.
 *   rewrite of SDL to be a plug in compatible video output device.
 *   extensive enhancement of video test program
 *
 * Revision 1.4.4.1  2005/07/17 11:30:42  rjongbloed
 * Major revisions of the PWLib video subsystem including:
 *   removal of F suffix on colour formats for vertical flipping, all done with existing bool
 *   working through use of RGB and BGR formats so now consistent
 *   cleaning up the plug in system to use virtuals instead of pointers to functions.
 *   rewrite of SDL to be a plug in compatible video output device.
 *   extensive enhancement of video test program
 *
 * 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);

#include "vidinput_names.h" 

class V4L2Names : public V4LXNames
{

  PCLASSINFO(V4L2Names, V4LXNames);

public:
  
  V4L2Names() { kernelVersion=KUNKNOWN; };

  virtual void Update ();
  
protected:
  
  virtual PString BuildUserFriendly(PString devname);

  enum KernelVersionEnum {
    K2_4, 
    K2_6,
    KUNKNOWN,
  } kernelVersion;

};


static 
V4L2Names & GetNames()
{
  static V4L2Names names;
  names.Update();
  return names;
}

///////////////////////////////////////////////////////////////////////////////
// PVideoInputDevice_V4L2

PVideoInputDevice_V4L2::PVideoInputDevice_V4L2()
{
  videoFd = -1;
  canRead = FALSE;
  canStream = FALSE;
  canSelect = FALSE;
  canSetFrameRate = FALSE;
  isMapped = FALSE;
  started = FALSE;
}

PVideoInputDevice_V4L2::~PVideoInputDevice_V4L2()
{
  Close();
}


#ifndef V4L2_PIX_FMT_H263
#define V4L2_PIX_FMT_H263       v4l2_fourcc('H','2','6','3')
#endif


static 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 
    { "BGR32", V4L2_PIX_FMT_BGR32 }, //PVideoDevice ColourFormat table.
    { "RGB24", V4L2_PIX_FMT_RGB24 }, 
    { "BGR24", V4L2_PIX_FMT_BGR24 },
    { "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_YUYV },   /* Note: YUV422 is for compatibility */
    { "YUV422P", V4L2_PIX_FMT_YUV422P },
    { "YUY2", V4L2_PIX_FMT_YUYV },
    { "JPEG", V4L2_PIX_FMT_JPEG },
    { "H263", V4L2_PIX_FMT_H263 },
    { "SBGGR8", V4L2_PIX_FMT_SBGGR8 },
    { "MJPEG", V4L2_PIX_FMT_MJPEG},
    { "UYVY422", V4L2_PIX_FMT_UYVY}
};


BOOL PVideoInputDevice_V4L2::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 (videoStreamParm.parm.capture.timeperframe.denominator / videoStreamParm.parm.capture.timeperframe.numerator);
  }
  
  return TRUE;
}


BOOL PVideoInputDevice_V4L2::IsOpen() 
{
  return videoFd >= 0;
}


BOOL PVideoInputDevice_V4L2::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 PVideoInputDevice_V4L2::Start()
{
  // automatically set mapping
  if (!isMapped && !SetMapping()) {
    ClearMapping();
    canStream = FALSE; // don't try again
    return FALSE;
  }

  if (!started) {
    PTRACE(6,"PVidInDev\tstart queuing all buffers, fd=" << videoFd);

    /* Queue all buffers */
    currentvideoBuffer = 0;
    for (unsigned int i=0; i<videoBufferCount; i++) {

       struct v4l2_buffer buf;
       buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
       buf.memory = V4L2_MEMORY_MMAP;
       buf.index = i;

       if (::ioctl(videoFd, VIDIOC_QBUF, &buf) < 0) {
	  PTRACE(3,"PVidInDev\tVIDIOC_QBUF failed for buffer " << i << ": " << ::strerror(errno));
	  return FALSE;
       }
    }

    /* Start streaming */
    PTRACE(6,"PVidInDev\tstart streaming, fd=" << videoFd);
    enum v4l2_buf_type type;
    type = V4L2_BUF_TYPE_VIDEO_CAPTURE;

    if (::ioctl(videoFd, VIDIOC_STREAMON, &type) < 0) {
       PTRACE(3,"PVidInDev\tSTREAMON failed : " << ::strerror(errno));
       return FALSE;
    }

    started = TRUE;

  }
  return TRUE;
}


BOOL PVideoInputDevice_V4L2::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 PVideoInputDevice_V4L2::IsCapturing()
{
  return started;
}

PStringList PVideoInputDevice_V4L2::GetInputDeviceNames()
{
  return GetNames().GetInputDeviceNames();  

⌨️ 快捷键说明

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