📄 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.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 + -