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

📄 vidinput_v4l.cxx

📁 sloedgy open sip stack source code
💻 CXX
📖 第 1 页 / 共 3 页
字号:
/*
 * video4linux.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): Derek Smithies (derek@indranet.co.nz)
 *                 Mark Cooke (mpc@star.sr.bham.ac.uk)
 *
 * $Log: vidinput_v4l.cxx,v $
 * Revision 1.1  2006/06/29 04:18:01  joegenbaclor
 * *** empty log message ***
 *
 * Revision 1.17  2006/02/06 22:22:16  dsandras
 * Added UYVY palette thanks to Luc Saillad <luc saillard org>. Thanks!
 *
 * Revision 1.16  2006/01/21 13:57:35  dsandras
 * V4L1 drivers are actually reporting RGB even though they are sending BGR.
 * Thanks to Luc Saillard <luc saillard org>.
 *
 * Revision 1.15  2005/11/30 12:47:39  csoutheren
 * Removed tabs, reformatted some code, and changed tags for Doxygen
 *
 * Revision 1.14  2005/08/09 09:08:10  rjongbloed
 * Merged new video code from branch back to the trunk.
 *
 * Revision 1.13.4.2  2005/07/24 09:01:49  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.13.4.1  2005/07/17 09:27:07  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.13  2004/11/21 19:17:17  dsandras
 * Temporarily removed the double names hack.
 *
 * Revision 1.12  2004/09/05 19:30:23  dsandras
 * Updated hint for buggy Quickcam camera.
 *
 * Revision 1.11  2004/08/20 01:46:45  dereksmithies
 * Patch from Srinivas.Kandagatla so that a video device can be opened with
 * either a)human friendly name,  or with b) the linux device name ("ov511++" or "/dev/video0").
 * Many thanks.
 *
 * Revision 1.10  2004/05/13 22:22:14  dereksmithies
 * Fix a problem with duplicate user friendly names.
 *
 * Revision 1.9  2004/02/15 22:10:10  anoncvs_net-mud
 * Applied patch from Fr閐閞ic Crozat <fcrozat@mandrakesoft.com> for buggy
 * Quickcam driver.
 *
 * Revision 1.8  2004/02/12 08:09:51  csoutheren
 * Patch for ALSA driver, thanks to Julien Puydt
 *
 * Revision 1.7  2004/02/06 22:21:17  dominance
 * fixed device detection when refreshing the device list. Patch supplied by PUYDT Julien <julien.puydt@laposte.net>. Thanks to Damien Sandras to point out this and for Julien to provide the fix this fast!
 *
 * Revision 1.6  2004/01/18 14:22:12  dereksmithies
 * Use names that are substrings of the actual device name, to open the device.
 *
 * Revision 1.5  2004/01/18 11:13:08  dereksmithies
 * Tidy up code & make more clear. Guarantee that tables of names are populated.
 *
 * Revision 1.4  2003/12/07 21:03:32  dominance
 * bttv of 2.4.23 doesn't seem to need anymore the hinting workaround.
 *
 * Revision 1.3  2003/11/25 22:55:13  dsandras
 * Added fallback using major and minor numbers for detection of devices when /proc/video doesn't exist (some 2.4 kernels and all 2.6 kernels).
 *
 * Revision 1.2  2003/11/18 10:42:09  csoutheren
 * Changed to work with new plugins
 *
 * Revision 1.1  2003/11/14 06:15:37  csoutheren
 * Initial version thanks to Snark and Damien
 *
 * Revision 1.39  2003/03/20 23:38:06  dereks
 * Fixes in handling of flags, and test for device opening
 *
 * Revision 1.38  2003/03/17 07:52:52  robertj
 * Removed canCaptureVideo variable as this is really a virtual function to
 *   distinguish PVideoOutputDevice from PVideoInputDevice, it is not dynamic.
 *
 * Revision 1.37  2003/03/06 02:43:43  dereks
 * Make error messages slightly more descriptive.
 *
 * Revision 1.36  2002/09/09 22:16:54  dereks
 * update hints for spca50x camera.
 *
 * Revision 1.35  2002/09/08 22:01:56  dereks
 * Add support for Intel PC Pro Camera, spca50x driver, Thanks Dennis Gilmore!
 *
 * Revision 1.34  2002/06/05 12:29:16  craigs
 * Changes for gcc 3.1
 *
 * Revision 1.33  2002/04/21 22:02:35  dereks
 * Tidy up test for existance of video devices. Thanks Guilhem Tardy.
 *
 * Revision 1.32  2002/04/17 21:54:06  dereks
 * Improve searching of proc file system for video device names. Thanks Guilhem Tardy.
 *
 * Revision 1.31  2002/04/13 07:54:38  rogerh
 * Add CPiA camera hint to work around driver bug.
 * From Damien Sandras and Keith Packard.
 *
 * Revision 1.30  2002/04/08 21:18:24  rogerh
 * Emulate original behaviour of pwlib when Open and then SetVideoFormat
 * are called. Tested by Mark Cooke.
 *
 * Revision 1.29  2002/04/05 06:41:54  rogerh
 * Apply video changes from Damien Sandras <dsandras@seconix.com>.
 * The Video Channel and Format are no longer set in Open(). Instead
 * call the new SetVideoChannelFormat() method. This makes video capture
 * and GnomeMeeting more stable with certain Linux video capture devices.
 *
 * Revision 1.28  2002/01/26 23:58:15  craigs
 * Changed for GCC 3.0 compatibility, thanks to manty@manty.net
 *
 * Revision 1.27  2002/01/16 03:43:01  dereks
 * Match every VIDIOCMCAPTURE with a VIDIOCSYNC.
 *
 * Revision 1.26  2002/01/04 04:11:45  dereks
 * Add video flip code from Walter Whitlock, which flips code at the grabber.
 *
 * Revision 1.25  2001/12/10 22:22:48  dereks
 * Add hint so Logitech USB Camera will only grab in large video size.
 *
 * Revision 1.24  2001/12/08 00:59:44  robertj
 * Added hint for BT879 chips, thanks Damian Sandras.
 *
 * Revision 1.23  2001/12/06 22:15:09  dereks
 * Additional debugging lines
 *
 * Revision 1.22  2001/11/30 00:14:46  dereks
 * Fix frame rate limitation.
 *
 * Revision 1.21  2001/11/28 05:10:19  robertj
 * Added enable of TV card sound when grabbing, thanks Santiago Garcia Mantinan
 *
 * Revision 1.20  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.19  2001/11/05 01:03:20  dereks
 * Fix error in collection of video data. Frame rate is now double of that
 * obtained previously.
 *
 * Revision 1.18  2001/08/22 02:04:43  robertj
 * Resolved confusion with YUV411P and YUV420P video formats, thanks Mark Cooke.
 *
 * Revision 1.17  2001/08/20 07:01:26  robertj
 * Fixed wierd problems with YUV411P and YUV420P formats, thanks Mark Cooke.
 *
 * Revision 1.16  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.15  2001/03/20 02:21:57  robertj
 * More enhancements from Mark Cooke
 *
 * Revision 1.14  2001/03/08 23:08:28  robertj
 * Fixed incorrect usage of VIDIOCSYNC, thanks Thorsten Westheider
 *
 * Revision 1.13  2001/03/08 21:46:11  dereks
 * Removed check when setting framesize. Thanks 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 03:59:13  robertj
 * Fixed previous change, needed to allow for -1 as chammelNumber in Open().
 *
 * Revision 1.10  2001/03/08 02:23:17  robertj
 * Added improved defaulting of video formats so Open() does not fail.
 *
 * Revision 1.9  2001/03/07 23:46:18  robertj
 * Double check the v4l device did actually change colour format, thanks Mark Cooke.
 *
 * Revision 1.8  2001/03/07 01:42:59  dereks
 * miscellaneous video fixes. Works on linux now. Add debug statements
 * (at PTRACE level of 1)
 *
 * Revision 1.7  2001/03/07 00:10:05  robertj
 * Improved the device list, uses /proc, thanks Thorsten Westheider.
 *
 * Revision 1.6  2001/03/03 23:25:07  robertj
 * Fixed use of video conversion function, returning bytes in destination frame.
 *
 * Revision 1.5  2001/03/03 06:13:01  robertj
 * Major upgrade of video conversion and grabbing classes.
 *
 * Revision 1.4  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.3  2000/07/30 03:54:28  robertj
 * Added more colour formats to video device enum.
 *
 * Revision 1.2  2000/07/26 06:13:25  robertj
 * Added missing pragma implementation for GNU headers.
 *
 * Revision 1.1  2000/07/26 02:40:30  robertj
 * Added video I/O devices.
 *
 */

#pragma implementation "vidinput_v4l.h"

#include "vidinput_v4l.h"
#include <sys/utsname.h>

PCREATE_VIDINPUT_PLUGIN(V4L);

///////////////////////////////////////////////////////////////////////////////
// Linux Video4Linux Driver Hints Tables.
//
// In an ideal API, we wouldn't need these hints on setup.  There are enough
// wrinkles it seems we have to provide a static list of hints for known
// issues.

#define HINT_CSWIN_ZERO_FLAGS               0x0001
#define HINT_CSPICT_ALWAYS_WORKS            0x0002  /// ioctl return value indicates pict was set ok.
#define HINT_CGPICT_DOESNT_SET_PALETTE      0x0004
#define HINT_HAS_PREF_PALETTE               0x0008  /// use this palette with this camera.
#define HINT_ALWAYS_WORKS_320_240           0x0010  /// Camera always  opens OK at this size.
#define HINT_ALWAYS_WORKS_640_480           0x0020  /// Camera always  opens OK at this size.
#define HINT_ONLY_WORKS_PREF_PALETTE        0x0040  /// Camera always (and only) opens at pref palette.
#define HINT_CGWIN_FAILS                    0x0080  /// ioctl VIDIOCGWIN always fails.
#define HINT_FORCE_LARGE_SIZE               0x0100  /// driver does not work in small video size.
#define HINT_FORCE_DEPTH_16                 0x0200  /// CPiA cameras return a wrong value for the depth, and if you try to use that wrong value, it fails.
#define HINT_FORCE_DBLBUF                   0x0400  /// Force double buffering on quickcam express

static struct {
  char     *name_regexp;        // String used to match the driver name
  char     *name;               // String used for ptrace output
  char     *version;             // Apply the hint if kernel
                                // version < given version,
                                // 0 means always apply
  unsigned hints;               // Hint flags
  int      pref_palette;        // Preferred palette.
} driver_hints[] = {

    /**Philips usb web cameras
       Native format is 420(P) so use it.
     */
    
  { "^Philips [0-9]+ webcam$",
    "Philips USB webcam",
    NULL,
    HINT_HAS_PREF_PALETTE,
    VIDEO_PALETTE_YUV420P },
  
  /**Brooktree based capture boards.

     The current bttv driver doesn't fail CSPICT calls with unsupported
     palettes.  It also doesn't return a useful value from CGPICT calls
     to readback the palette. Not needed anymore from 2.4.23
   */
    { "^BT8(4|7)(8|9)",
      "Brooktree BT848 and BT878 based capture boards",
      "2.4.23",
      HINT_CSWIN_ZERO_FLAGS |
      HINT_CSPICT_ALWAYS_WORKS |
      HINT_CGPICT_DOESNT_SET_PALETTE |
      HINT_HAS_PREF_PALETTE,
      VIDEO_PALETTE_YUV420P },

  /** Quickcam Express (qc-usb driver) */
  { "Logitech [USB Camera|QuickCam USB]",
    "Quickcam Express (qc-usb driver)",
    NULL,
    HINT_FORCE_DBLBUF,
    0},
  
  /** Sony Vaio Motion Eye camera
      Linux kernel 2.4.7 has meye.c driver module.
   */
  { "meye",
    "Sony Vaio Motion Eye Camera",
    NULL,
    HINT_CGPICT_DOESNT_SET_PALETTE |
    HINT_CSPICT_ALWAYS_WORKS       |
    HINT_ALWAYS_WORKS_320_240      |
    HINT_ALWAYS_WORKS_640_480      |
    HINT_CGWIN_FAILS               |
    HINT_ONLY_WORKS_PREF_PALETTE   |
    HINT_HAS_PREF_PALETTE,
    VIDEO_PALETTE_YUV422 },

  /** USB camera, which only works in large size.
   */
  { "Logitech USB Webcam",
    "Logitech USB Webcam which works in large size only",
    NULL,
    HINT_FORCE_LARGE_SIZE,
    VIDEO_PALETTE_YUV420P 
  },

  /** Creative VideoBlaster Webcam II USB
   */
  {"CPiA Camera",
   "CPIA which works with cpia and cpia_usb driver modules",
   NULL,
   HINT_FORCE_DEPTH_16 |
   HINT_ONLY_WORKS_PREF_PALETTE   |
   HINT_HAS_PREF_PALETTE,
   VIDEO_PALETTE_YUV422
  },

 /** Intel PC Pro Camera
 
 */
  { "SPCA50X USB Camera",
    "Intel PC Pro Camera uses the spca50x driver",
    NULL,
    HINT_ONLY_WORKS_PREF_PALETTE        |
    HINT_HAS_PREF_PALETTE,
    VIDEO_PALETTE_RGB24
  },


  /** Default device with no special settings
   */
  { "",
    "V4L Supported Device",
    0,
    0,
    0 }

};

#define HINT(h) ((driver_hints[hint_index].hints & h) ? TRUE : FALSE)
#define MAJOR(a) (int)((unsigned short) (a) >> 8)
#define MINOR(a) (int)((unsigned short) (a) & 0xFF) 
// this is used to get more userfriendly names:
class V4LNames : public PObject
{ 
   PCLASSINFO(V4LNames, PObject);
public:
  V4LNames() {/* nothing */};

  void Update ();
  
  PString GetUserFriendly(PString devName);

  PString GetDeviceName(PString userName);

  PStringList GetInputDeviceNames();

protected:
  void AddUserDeviceName(PString userName, PString devName);

  PString BuildUserFriendly(PString devname);

  void PopulateDictionary();

  void ReadDeviceDirectory(PDirectory devdir, POrdinalToString & vid);

  PMutex          mutex;
  PStringToString deviceKey;
  PStringToString userKey;
  PStringList     inputDeviceNames;
};

void
V4LNames::Update()
{
  PDirectory   procvideo("/proc/video/dev");
  PString      entry;
  PStringList  devlist;
  
  inputDeviceNames.RemoveAll (); // flush the previous run
  if (procvideo.Exists()) {
    if (procvideo.Open(PFileInfo::RegularFile)) {
      do {
        entry = procvideo.GetEntryName();
        if ((entry.Left(5) == "video") || (entry.Left(7) == "capture")) {
          PString thisDevice = "/dev/video" + entry.Right(1);
          int videoFd = ::open((const char *)thisDevice, O_RDONLY | O_NONBLOCK);

          if ((videoFd > 0) || (errno == EBUSY)){
            BOOL valid = FALSE;
            struct video_capability  videoCaps;
            if (ioctl(videoFd, VIDIOCGCAP, &videoCaps) >= 0 && (videoCaps.type & VID_TYPE_CAPTURE) != 0)
              valid = TRUE;
            if (videoFd >= 0)
              close(videoFd); 
            if (valid)
              inputDeviceNames += thisDevice;
          }
        }
      } while (procvideo.Next());
    }   
  } 
  if (inputDeviceNames.GetSize() == 0) {
    POrdinalToString vid;
    ReadDeviceDirectory("/dev/", vid);

    for (PINDEX i = 0; i < vid.GetSize(); i++) {
      PINDEX cardnum = vid.GetKeyAt(i);
      int fd = ::open(vid[cardnum], O_RDONLY | O_NONBLOCK);
      if ((fd >= 0) || (errno == EBUSY)) {
        if (fd >= 0)
          ::close(fd);
        inputDeviceNames += vid[cardnum];
      }
    }
  }
  PopulateDictionary();
}

void  V4LNames::ReadDeviceDirectory(PDirectory devdir, POrdinalToString & vid)
{
  if (!devdir.Open())
    return;

  do {
    PString filename = devdir.GetEntryName();
    PString devname = devdir + filename;
    if (devdir.IsSubDir())
      ReadDeviceDirectory(devname, vid);
    else {

      PFileInfo info;
      if (devdir.GetInfo(info) && info.type == PFileInfo::CharDevice) {
        struct stat s;
        if (lstat(devname, &s) == 0) {
 
          static const int deviceNumbers[] = { 81 };
          for (PINDEX i = 0; i < PARRAYSIZE(deviceNumbers); i++) {
            if (MAJOR(s.st_rdev) == deviceNumbers[i]) {
              PINDEX num = MINOR(s.st_rdev);
              if (num <= 63 && num >= 0) {
                vid.SetAt(num, devname);
              }
            }
          }
        }
      }
    }
  } while (devdir.Next());
}

void V4LNames::PopulateDictionary()
{
  PINDEX i, j;
  PStringToString tempList;

  for (i = 0; i < inputDeviceNames.GetSize(); i++) {
    PString ufname = BuildUserFriendly(inputDeviceNames[i]);
    tempList.SetAt(inputDeviceNames[i], ufname);
  }

  //Now, we need to cope with the case where there are two video
  //devices available, which both have the same user friendly name.
  //Matching user friendly names have a (X) appended to the name.
  for (i = 0; i < tempList.GetSize(); i++) {
    PString userName = tempList.GetDataAt(i); 

    PINDEX matches = 1;    
    for (j = i + 1; j < tempList.GetSize(); j++) {
      if (tempList.GetDataAt(j) == userName) {
        matches++;
        PStringStream revisedUserName;
        revisedUserName << userName << " (" << matches << ")";

⌨️ 快捷键说明

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