📄 vidinput_v4l.cxx
字号:
/* * 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.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, PVideoInputV4lDevice);///////////////////////////////////////////////////////////////////////////////// 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 expressstatic 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;};voidV4LNames::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 << ")"; tempList.SetDataAt(j, revisedUserName); } } } //At this stage, we have correctly modified the temp list of names. for (j = 0; j < tempList.GetSize(); j++) AddUserDeviceName(tempList.GetDataAt(j), tempList.GetKeyAt(j)); }PString V4LNames::GetUserFriendly(PString devName){ PWaitAndSignal m(mutex); PString result= deviceKey(devName); if (result.IsEmpty()) return devName; return result;}PString V4LNames::GetDeviceName(PString userName){ PWaitAndSignal m(mutex);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -