📄 vidinput_v4l2.cxx
字号:
/*
* 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 + -